Add vmmStorage{Pool,Vol}, poll for these devices in connection tick function.

This commit is contained in:
Cole Robinson 2008-08-07 17:37:16 -04:00
parent 14bea347df
commit 8c95e6d6f2
3 changed files with 316 additions and 0 deletions

View File

@ -36,6 +36,7 @@ import virtinst
from virtManager.domain import vmmDomain from virtManager.domain import vmmDomain
from virtManager.network import vmmNetwork from virtManager.network import vmmNetwork
from virtManager.netdev import vmmNetDevice from virtManager.netdev import vmmNetDevice
from virtManager.storagepool import vmmStoragePool
LIBVIRT_POLICY_FILE = "/usr/share/PolicyKit/policy/libvirtd.policy" LIBVIRT_POLICY_FILE = "/usr/share/PolicyKit/policy/libvirtd.policy"
@ -97,6 +98,14 @@ class vmmConnection(gobject.GObject):
[str, str]), [str, str]),
"net-stopped": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, "net-stopped": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
[str, str]), [str, str]),
"pool-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
[str, str]),
"pool-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
[str, str]),
"pool-started": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
[str, str]),
"pool-stopped": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
[str, str]),
"netdev-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, "netdev-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
[str]), [str]),
"netdev-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, "netdev-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
@ -134,6 +143,8 @@ class vmmConnection(gobject.GObject):
self.state = self.STATE_DISCONNECTED self.state = self.STATE_DISCONNECTED
self.vmm = None self.vmm = None
# Connection Storage pools: UUID -> vmmStoragePool
self.pools = {}
# Host network devices. name -> vmmNetDevice object # Host network devices. name -> vmmNetDevice object
self.netdevs = {} self.netdevs = {}
# Virtual networks UUUID -> vmmNetwork object # Virtual networks UUUID -> vmmNetwork object
@ -339,6 +350,9 @@ class vmmConnection(gobject.GObject):
def get_net_device(self, path): def get_net_device(self, path):
return self.netdevs[path] return self.netdevs[path]
def get_pool(self, uuid):
return self.pools[uuid]
def open(self): def open(self):
if self.state != self.STATE_DISCONNECTED: if self.state != self.STATE_DISCONNECTED:
return return
@ -513,6 +527,7 @@ class vmmConnection(gobject.GObject):
#self.vmm.close() #self.vmm.close()
self.vmm = None self.vmm = None
self.nets = {} self.nets = {}
self.pools = {}
self.vms = {} self.vms = {}
self.activeUUIDs = [] self.activeUUIDs = []
self.record = [] self.record = []
@ -528,6 +543,9 @@ class vmmConnection(gobject.GObject):
def list_net_device_paths(self): def list_net_device_paths(self):
return self.netdevs.keys() return self.netdevs.keys()
def list_pool_uuids(self):
return self.pools.keys()
def get_host_info(self): def get_host_info(self):
return self.hostinfo return self.hostinfo
@ -662,6 +680,60 @@ class vmmConnection(gobject.GObject):
return (startNets, stopNets, newNets, origNets, currentNets) return (startNets, stopNets, newNets, origNets, currentNets)
def _update_pools(self):
origPools = self.pools
currentPools = {}
startPools = []
stopPools = []
newPools = []
newActivePoolNames = []
newInactivePoolNames = []
try:
newActivePoolNames = self.vmm.listStoragePools()
except:
logging.warn("Unable to list active pools")
try:
newInactivePoolNames = self.vmm.listDefinedStoragePools()
except:
logging.warn("Unable to list inactive pools")
for name in newActivePoolNames:
try:
pool = self.vmm.storagePoolLookupByName(name)
uuid = self.uuidstr(pool.UUID())
if not origPools.has_key(uuid):
currentPools[uuid] = vmmStoragePool(self.config, self,
pool, uuid, True)
newPools.append(uuid)
startPools.append(uuid)
else:
currentPools[uuid] = origPools[uuid]
if not currentPools[uuid].is_active():
currentPools[uuid].set_active(True)
startPools.append(uuid)
del origPools[uuid]
except libvirt.libvirtError:
logging.warn("Couldn't fetch active pool '%s'" % name)
for name in newInactivePoolNames:
try:
pool = self.vmm.storagePoolLookupByName(name)
uuid = self.uuidstr(pool.UUID())
if not origPools.has_key(uuid):
currentPools[uuid] = vmmStoragePool(self.config, self,
pool, uuid, False)
newPools.append(uuid)
else:
currentPools[uuid] = origPools[uuid]
if currentPools[uuid].is_active():
currentPools[uuid].set_active(False)
stopPools.append(uuid)
del origPools[uuid]
except libvirt.libvirtError:
logging.warn("Couldn't fetch inactive pool '%s'" % name)
return (stopPools, startPools, origPools, newPools, currentPools)
def _update_vms(self): def _update_vms(self):
"""returns lists of changed VM states""" """returns lists of changed VM states"""
@ -778,6 +850,10 @@ class vmmConnection(gobject.GObject):
(startNets, stopNets, newNets, (startNets, stopNets, newNets,
oldNets, self.nets) = self._update_nets() oldNets, self.nets) = self._update_nets()
# Update pools
(stopPools, startPools, oldPools,
newPools, self.pools) = self._update_pools()
# Poll for changed/new/removed VMs # Poll for changed/new/removed VMs
(startVMs, newVMs, oldVMs, (startVMs, newVMs, oldVMs,
self.vms, self.activeUUIDs) = self._update_vms() self.vms, self.activeUUIDs) = self._update_vms()
@ -801,6 +877,15 @@ class vmmConnection(gobject.GObject):
for uuid in stopNets: for uuid in stopNets:
self.emit("net-stopped", self.uri, uuid) self.emit("net-stopped", self.uri, uuid)
for uuid in oldPools:
self.emit("pool-removed", self.uri, uuid)
for uuid in newPools:
self.emit("pool-added", self.uri, uuid)
for uuid in startPools:
self.emit("pool-started", self.uri, uuid)
for uuid in stopPools:
self.emit("pool-stopped", self.uri, uuid)
# Finally, we sample each domain # Finally, we sample each domain
now = time() now = time()
try: try:

View File

@ -0,0 +1,145 @@
#
# Copyright (C) 2008 Red Hat, Inc.
# Copyright (C) 2008 Cole Robinson <crobinso@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., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
#
import gobject
import libvirt
import libxml2
import logging
import virtinst
import virtinst.util as util
from virtManager.storagevol import vmmStorageVolume
class vmmStoragePool(gobject.GObject):
__gsignals__ = { }
def __init__(self, config, connection, pool, uuid, active):
self.__gobject_init__()
self.config = config
self.connection = connection
self.pool = pool # Libvirt pool object
self.uuid = uuid # String UUID
self.active = active # bool indicating if it is running
self._volumes = {} # UUID->vmmStorageVolume mapping of the
# pools associated volumes
self._xml = None # xml cache
self._update_xml()
self.update_volumes()
def set_active(self, state):
self.active = state
self._update_xml()
def is_active(self):
return self.active
def can_change_alloc(self):
type = self.get_type()
return (type in [virtinst.Storage.StoragePool.TYPE_LOGICAL])
def get_connection(self):
return self.connection
def get_name(self):
return self.pool.name()
def get_uuid(self):
return self.uuid
def start(self):
self.pool.create(0)
self._update_xml()
def stop(self):
self.pool.destroy()
self._update_xml()
def delete(self):
self.pool.undefine()
del(self.pool)
def _update_xml(self):
self._xml = self.pool.XMLDesc(0)
def get_xml(self):
if self._xml is None:
self._update_xml()
return self._xml
def set_autostart(self, value):
self.pool.setAutostart(value)
def get_autostart(self):
return self.pool.autostart()
def get_target_path(self):
return util.get_xml_path(self.get_xml(), "/pool/target/path")
def get_allocation(self):
return long(util.get_xml_path(self.get_xml(), "/pool/allocation"))
def get_available(self):
return long(util.get_xml_path(self.get_xml(), "/pool/available"))
def get_capacity(self):
return long(util.get_xml_path(self.get_xml(), "/pool/capacity"))
def get_pretty_allocation(self):
return self._prettyify(self.get_allocation())
def get_pretty_available(self):
return self._prettyify(self.get_available())
def get_pretty_capacity(self):
return self._prettyify(self.get_capacity())
def get_type(self):
return util.get_xml_path(self.get_xml(), "/pool/@type")
def get_volumes(self):
self.update_volumes()
return self._volumes
def get_volume(self, uuid):
return self._volumes[uuid]
def update_volumes(self):
if not self.is_active():
self._volumes = {}
return
self.pool.refresh(0)
vols = self.pool.listVolumes()
new_vol_list = {}
for volname in vols:
if self._volumes.has_key(volname):
new_vol_list[volname] = self._volumes[volname]
else:
new_vol_list[volname] = vmmStorageVolume(self.config,
self.connection,
self.pool.storageVolLookupByName(volname),
volname)
self._volumes = new_vol_list
def _prettyify(self, val):
if val > (1024*1024*1024):
return "%2.2f GB" % (val/(1024.0*1024.0*1024.0))
else:
return "%2.2f MB" % (val/(1024.0*1024.0))
gobject.type_register(vmmStoragePool)

View File

@ -0,0 +1,86 @@
#
# Copyright (C) 2008 Red Hat, Inc.
# Copyright (C) 2008 Cole Robinson <crobinso@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., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
#
import gobject
import libvirt
import libxml2
import logging
import virtinst
import virtinst.util as util
class vmmStorageVolume(gobject.GObject):
__gsignals__ = { }
def __init__(self, config, connection, vol, name):
self.__gobject_init__()
self.config = config
self.connection = connection
self.vol = vol # Libvirt storage volume object
self.name = name
self._xml = None # Cache xml rather than repeated lookups
self._update_xml()
def get_connection(self):
return self.connection
def get_name(self):
return self.name
def get_path(self):
return self.vol.path()
def delete(self):
self.vol.undefine()
del(self.vol)
def get_xml(self):
if self._xml is None:
self._update_xml()
return self._xml
def get_target_path(self):
return util.get_xml_path(self.get_xml(),"/volume/target/path")
def get_format(self):
return util.get_xml_path(self.get_xml(),"/volume/target/format/@type")
def get_allocation(self):
return long(util.get_xml_path(self.get_xml(),"/volume/allocation"))
def get_capacity(self):
return long(util.get_xml_path(self.get_xml(),"/volume/capacity"))
def get_pretty_capacity(self):
return self._prettyify(self.get_capacity())
def get_pretty_allocation(self):
return self._prettyify(self.get_allocation())
def get_type(self):
return util.get_xml_path(self.get_xml(),"/volume/format/@type")
def _update_xml(self):
self._xml = self.vol.XMLDesc(0)
def _prettyify(self, val):
if val > (1024*1024*1024):
return "%2.2f GB" % (val/(1024.0*1024.0*1024.0))
else:
return "%2.2f MB" % (val/(1024.0*1024.0))
gobject.type_register(vmmStorageVolume)