2006-06-28 15:50:17 -04:00
|
|
|
#
|
|
|
|
|
# Copyright (C) 2006 Red Hat, Inc.
|
|
|
|
|
# Copyright (C) 2006 Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
|
#
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
#
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-06-14 13:52:46 -04:00
|
|
|
import gobject
|
2006-06-14 10:59:40 -04:00
|
|
|
import libvirt
|
2006-07-24 13:50:11 -04:00
|
|
|
import os
|
2006-06-14 17:52:49 -04:00
|
|
|
from time import time
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-06-14 17:52:49 -04:00
|
|
|
from virtManager.domain import vmmDomain
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-06-14 13:52:46 -04:00
|
|
|
class vmmConnection(gobject.GObject):
|
|
|
|
|
__gsignals__ = {
|
|
|
|
|
"vm-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
2006-06-14 17:52:49 -04:00
|
|
|
[str, str]),
|
2006-06-14 13:52:46 -04:00
|
|
|
"vm-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
2006-06-14 17:52:49 -04:00
|
|
|
[str, str]),
|
2006-06-14 16:20:06 -04:00
|
|
|
"disconnected": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [str])
|
2006-06-14 13:52:46 -04:00
|
|
|
}
|
|
|
|
|
|
2006-06-14 16:56:49 -04:00
|
|
|
def __init__(self, config, uri, readOnly):
|
2006-06-14 13:52:46 -04:00
|
|
|
self.__gobject_init__()
|
2006-06-14 10:59:40 -04:00
|
|
|
self.config = config
|
2006-06-14 14:36:26 -04:00
|
|
|
self.uri = uri
|
2006-06-28 10:40:35 -04:00
|
|
|
self.readOnly = readOnly
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-06-27 14:16:13 -04:00
|
|
|
openURI = uri
|
|
|
|
|
if openURI == "Xen":
|
|
|
|
|
openURI = None
|
2006-06-14 10:59:40 -04:00
|
|
|
if readOnly:
|
2006-06-27 14:16:13 -04:00
|
|
|
self.vmm = libvirt.openReadOnly(openURI)
|
2006-06-14 10:59:40 -04:00
|
|
|
else:
|
2006-06-27 14:16:13 -04:00
|
|
|
self.vmm = libvirt.open(openURI)
|
2006-06-14 10:59:40 -04:00
|
|
|
|
|
|
|
|
self.vms = {}
|
|
|
|
|
|
2006-06-28 10:40:35 -04:00
|
|
|
def is_read_only(self):
|
|
|
|
|
return self.readOnly
|
|
|
|
|
|
2006-06-14 14:36:26 -04:00
|
|
|
def get_uri(self):
|
|
|
|
|
return self.uri
|
|
|
|
|
|
2006-06-14 16:20:06 -04:00
|
|
|
def get_vm(self, uuid):
|
|
|
|
|
return self.vms[uuid]
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-08-21 14:00:32 -04:00
|
|
|
def close(self):
|
2006-06-14 14:36:26 -04:00
|
|
|
if self.vmm == None:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
#self.vmm.close()
|
2006-06-14 13:52:46 -04:00
|
|
|
self.vmm = None
|
2006-06-14 16:20:06 -04:00
|
|
|
self.emit("disconnected", self.uri)
|
2006-06-14 13:52:46 -04:00
|
|
|
|
2006-06-14 10:59:40 -04:00
|
|
|
def get_host_info(self):
|
2006-06-14 17:52:49 -04:00
|
|
|
return self.hostinfo
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-06-14 13:52:46 -04:00
|
|
|
def connect(self, name, callback):
|
2006-08-21 14:00:32 -04:00
|
|
|
handle_id = gobject.GObject.connect(self, name, callback)
|
2006-06-14 18:51:58 -04:00
|
|
|
|
2006-06-14 13:52:46 -04:00
|
|
|
if name == "vm-added":
|
2006-06-14 10:59:40 -04:00
|
|
|
for uuid in self.vms.keys():
|
2006-06-14 17:52:49 -04:00
|
|
|
self.emit("vm-added", self.uri, uuid)
|
|
|
|
|
|
2006-08-21 14:00:32 -04:00
|
|
|
return handle_id
|
|
|
|
|
|
2006-06-14 17:52:49 -04:00
|
|
|
def host_memory_size(self):
|
|
|
|
|
return self.hostinfo[1]*1024
|
|
|
|
|
|
|
|
|
|
def host_active_processor_count(self):
|
|
|
|
|
return self.hostinfo[2]
|
|
|
|
|
|
|
|
|
|
def host_maximum_processor_count(self):
|
|
|
|
|
return self.hostinfo[4] * self.hostinfo[5] * self.hostinfo[6] * self.hostinfo[7]
|
|
|
|
|
|
2006-07-20 11:16:07 -04:00
|
|
|
def restore(self, frm):
|
2006-07-24 13:50:11 -04:00
|
|
|
status = self.vmm.restore(frm)
|
|
|
|
|
if(status == 0):
|
|
|
|
|
os.remove(frm)
|
|
|
|
|
return status
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-10-03 11:53:07 -04:00
|
|
|
def tick(self, noStatsUpdate=False):
|
2006-06-14 13:52:46 -04:00
|
|
|
if self.vmm == None:
|
|
|
|
|
return
|
|
|
|
|
|
2006-10-09 13:28:13 -04:00
|
|
|
oldActiveIDs = {}
|
|
|
|
|
oldInactiveNames = {}
|
2006-07-13 13:35:24 -04:00
|
|
|
for uuid in self.vms.keys():
|
|
|
|
|
vm = self.vms[uuid]
|
2006-10-09 13:28:13 -04:00
|
|
|
if vm.get_id() == -1:
|
|
|
|
|
oldInactiveNames[vm.get_name()] = vm
|
|
|
|
|
else:
|
|
|
|
|
oldActiveIDs[vm.get_id()] = vm
|
|
|
|
|
|
|
|
|
|
newActiveIDs = self.vmm.listDomainsID()
|
|
|
|
|
newInactiveNames = self.vmm.listDefinedDomains()
|
|
|
|
|
|
|
|
|
|
newUUIDs = {}
|
|
|
|
|
oldUUIDs = {}
|
|
|
|
|
curUUIDs = {}
|
|
|
|
|
maybeNewUUIDs = {}
|
|
|
|
|
|
|
|
|
|
# NB in these first 2 loops, we go to great pains to
|
|
|
|
|
# avoid actually instantiating a new VM object so that
|
|
|
|
|
# the common case of 'no new/old VMs' avoids hitting
|
|
|
|
|
# XenD too much & thus slowing stuff down.
|
|
|
|
|
|
|
|
|
|
# Filter out active domains which haven't changed
|
|
|
|
|
if newActiveIDs != None:
|
|
|
|
|
for id in newActiveIDs:
|
|
|
|
|
if oldActiveIDs.has_key(id):
|
|
|
|
|
# No change, copy across existing VM object
|
|
|
|
|
vm = oldActiveIDs[id]
|
2006-10-10 11:30:00 -04:00
|
|
|
#print "Existing active " + str(vm.get_name()) + " " + vm.get_uuid()
|
2006-10-09 13:28:13 -04:00
|
|
|
curUUIDs[vm.get_uuid()] = vm
|
2006-07-13 13:35:24 -04:00
|
|
|
else:
|
2006-10-09 13:28:13 -04:00
|
|
|
# May be a new VM, we have no choice but
|
|
|
|
|
# to create the wrapper so we can see
|
|
|
|
|
# if its a previously inactive domain.
|
2006-07-13 13:35:24 -04:00
|
|
|
vm = self.vmm.lookupByID(id)
|
|
|
|
|
uuid = self.uuidstr(vm.UUID())
|
2006-10-09 13:28:13 -04:00
|
|
|
maybeNewUUIDs[uuid] = vmmDomain(self.config, self, vm, uuid)
|
|
|
|
|
curUUIDs[uuid] = maybeNewUUIDs[uuid]
|
2006-10-10 11:30:00 -04:00
|
|
|
#print "Maybe new active " + str(maybeNewUUIDs[uuid].get_name()) + " " + uuid
|
2006-10-09 13:28:13 -04:00
|
|
|
|
|
|
|
|
# Filter out inactive domains which haven't changed
|
|
|
|
|
if newInactiveNames != None:
|
|
|
|
|
for name in newInactiveNames:
|
|
|
|
|
if oldInactiveNames.has_key(name):
|
|
|
|
|
# No change, copy across existing VM object
|
|
|
|
|
vm = oldInactiveNames[name]
|
2006-10-10 11:30:00 -04:00
|
|
|
#print "Existing inactive " + str(vm.get_name()) + " " + vm.get_uuid()
|
2006-10-09 13:28:13 -04:00
|
|
|
curUUIDs[vm.get_uuid()] = vm
|
|
|
|
|
else:
|
|
|
|
|
# May be a new VM, we have no choice but
|
|
|
|
|
# to create the wrapper so we can see
|
|
|
|
|
# if its a previously inactive domain.
|
|
|
|
|
vm = self.vmm.lookupByName(name)
|
|
|
|
|
uuid = self.uuidstr(vm.UUID())
|
|
|
|
|
maybeNewUUIDs[uuid] = vmmDomain(self.config, self, vm, uuid)
|
|
|
|
|
curUUIDs[uuid] = maybeNewUUIDs[uuid]
|
2006-10-10 11:30:00 -04:00
|
|
|
#print "Maybe new inactive " + str(maybeNewUUIDs[uuid].get_name()) + " " + uuid
|
2006-10-09 13:28:13 -04:00
|
|
|
|
|
|
|
|
# At this point, maybeNewUUIDs has domains which are
|
|
|
|
|
# either completely new, or changed state.
|
|
|
|
|
|
|
|
|
|
# Filter out VMs which merely changed state, leaving
|
|
|
|
|
# only new domains
|
|
|
|
|
for uuid in maybeNewUUIDs.keys():
|
|
|
|
|
vm = maybeNewUUIDs[uuid]
|
|
|
|
|
if not(self.vms.has_key(vm.get_uuid())):
|
|
|
|
|
#print "Completely new VM " + str(vm)
|
|
|
|
|
newUUIDs[vm.get_uuid()] = vm
|
|
|
|
|
else:
|
|
|
|
|
#print "Mere state change " + str(vm)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# Finalize list of domains which went away altogether
|
|
|
|
|
for uuid in self.vms.keys():
|
|
|
|
|
vm = self.vms[uuid]
|
|
|
|
|
if not(curUUIDs.has_key(uuid)):
|
|
|
|
|
#print "Completly old VM " + str(vm)
|
|
|
|
|
oldUUIDs[uuid] = vm
|
|
|
|
|
else:
|
|
|
|
|
#print "Mere state change " + str(vm)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# We have our new master list
|
|
|
|
|
self.vms = curUUIDs
|
|
|
|
|
|
|
|
|
|
# Inform everyone what changed
|
|
|
|
|
for uuid in oldUUIDs:
|
|
|
|
|
vm = oldUUIDs[uuid]
|
|
|
|
|
self.emit("vm-removed", self.uri, uuid)
|
|
|
|
|
|
|
|
|
|
for uuid in newUUIDs:
|
|
|
|
|
vm = newUUIDs[uuid]
|
2006-07-13 13:35:24 -04:00
|
|
|
self.emit("vm-added", self.uri, uuid)
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-10-09 13:28:13 -04:00
|
|
|
# Finally, we sample each domain
|
2006-06-14 17:52:49 -04:00
|
|
|
now = time()
|
|
|
|
|
self.hostinfo = self.vmm.getInfo()
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-10-03 11:53:07 -04:00
|
|
|
updateVMs = self.vms
|
|
|
|
|
if noStatsUpdate:
|
|
|
|
|
updateVMs = newVms
|
|
|
|
|
|
|
|
|
|
for uuid in updateVMs.keys():
|
|
|
|
|
self.vms[uuid].tick(now)
|
2006-06-14 10:59:40 -04:00
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
def uuidstr(self, rawuuid):
|
|
|
|
|
hex = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
|
|
|
|
|
uuid = []
|
|
|
|
|
for i in range(16):
|
|
|
|
|
uuid.append(hex[((ord(rawuuid[i]) >> 4) & 0xf)])
|
|
|
|
|
uuid.append(hex[(ord(rawuuid[i]) & 0xf)])
|
|
|
|
|
if i == 3 or i == 5 or i == 7 or i == 9:
|
|
|
|
|
uuid.append('-')
|
|
|
|
|
return "".join(uuid)
|
|
|
|
|
|
2006-06-14 13:52:46 -04:00
|
|
|
gobject.type_register(vmmConnection)
|
2006-06-14 10:59:40 -04:00
|
|
|
|