[virt-who] Workaround for removing machines using xen
by Radek Novacek
commit 468f72898bdebb362174cd9073b22536d2ba3555
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Wed Nov 30 11:58:30 2011 +0100
Workaround for removing machines using xen
virt.py | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
---
diff --git a/virt.py b/virt.py
index a64b0e1..b4a62de 100644
--- a/virt.py
+++ b/virt.py
@@ -63,7 +63,14 @@ class Virt:
def changed(self, conn, dom, event, detail, opaque):
print "EVENT: Domain %s(%s) %s %s" % (dom.name(), dom.ID(), eventToString(event), detailToString(event, detail))
if self.changedCallback:
- self.changedCallback(self.listDomains())
+ l = self.listDomains()
+ # Workaround: when removing machine from xen it is still in list of
+ # domains, so we'll remove it manually
+ if event == libvirt.VIR_DOMAIN_EVENT_UNDEFINED:
+ uuid = dom.UUIDString()
+ # Copy the list of domains without deleted domain
+ l = [d for d in l if d.UUIDString() != uuid]
+ self.changedCallback(l)
def domainListChangedCallback(self, callback):
self.changedCallback = callback
12 years, 5 months
[virt-who] Make the main loop more robust.
by Radek Novacek
commit 15d839c36e9aedd4d653833d6a713acd6a2f60ba
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Tue Nov 1 14:57:02 2011 +0100
Make the main loop more robust.
VirtWho class is introduced to handle error states better. Now it can
recover from failures such as libvirtd restart, error in communication
with subscription manager etc.
subscriptionmanager.py | 8 ++-
vdsm.py | 3 +
virt-who.py | 209 ++++++++++++++++++++++++++++++++++++++----------
virt.py | 35 +++++---
4 files changed, 200 insertions(+), 55 deletions(-)
---
diff --git a/subscriptionmanager.py b/subscriptionmanager.py
index b65ae77..1374a0d 100644
--- a/subscriptionmanager.py
+++ b/subscriptionmanager.py
@@ -25,6 +25,9 @@ import rhsm.connection as rhsm_connection
import rhsm.certificate as rhsm_certificate
import rhsm.config as rhsm_config
+class SubscriptionManagerError(Exception):
+ pass
+
class SubscriptionManager:
""" Class for interacting subscription-manager. """
def __init__(self, logger):
@@ -72,7 +75,10 @@ class SubscriptionManager:
self.logger.debug("Sending update to updateConsumer: %s" % uuids)
# Send list of guest uuids to the server
- self.connection.updateConsumer(self.uuid(), guest_uuids=uuids)
+ try:
+ self.connection.updateConsumer(self.uuid(), guest_uuids=uuids)
+ except Exception, e:
+ raise SubscriptionManagerError(str(e))
def uuid(self):
""" Read consumer certificate and get consumer UUID from it. """
diff --git a/vdsm.py b/vdsm.py
index aa029c1..e4a6b9e 100644
--- a/vdsm.py
+++ b/vdsm.py
@@ -104,6 +104,9 @@ class VDSM:
domains.append(Domain(vm['vmId']))
return domains
+ def ping(self):
+ # Not implemented yet
+ return True
if __name__ == '__main__':
import logging
diff --git a/virt-who.py b/virt-who.py
index 012794b..32be133 100644
--- a/virt-who.py
+++ b/virt-who.py
@@ -25,7 +25,7 @@ import time
from virt import Virt, VirtError
from vdsm import VDSM
from event import virEventLoopPureStart
-from subscriptionmanager import SubscriptionManager
+from subscriptionmanager import SubscriptionManager, SubscriptionManagerError
import logging
import log
@@ -34,6 +34,142 @@ from optparse import OptionParser
from ConfigParser import NoOptionError
+# Default interval to retry after unsuccessful run
+RetryInterval = 60 # One minute
+# Default interval for sending list of UUIDs
+DefaultInterval = 3600 # Once per hour
+
+class VirtWho(object):
+ def __init__(self, logger, options):
+ """
+ VirtWho class provides bridge between virtualization supervisor and
+ Subscription Manager.
+
+ logger - logger instance
+ options - options for virt-who, parsed from command line arguments
+ """
+ self.logger = logger
+ self.options = options
+
+ self.virt = None
+ self.subscriptionManager = None
+
+ def initVirt(self):
+ """
+ Connect to the virtualization supervisor (libvirt or VDSM)
+ """
+ if self.options.useVDSM:
+ self.virt = VDSM(self.logger)
+ else:
+ self.virt = Virt(self.logger)
+ # We can listen for libvirt events
+ self.tryRegisterEventCallback()
+
+ def initSM(self):
+ """
+ Connect to the subscription manager (candlepin).
+ """
+ try:
+ self.subscriptionManager = SubscriptionManager(self.logger)
+ self.subscriptionManager.connect()
+ self.tryRegisterEventCallback()
+ except NoOptionError, e:
+ logger.error("Error in reading configuration file (/etc/rhsm/rhsm.conf): %s" % e)
+ # Unability to parse configuration file is fatal error, so we'll quit
+ sys.exit(4)
+ except Exception, e:
+ raise e
+
+ def tryRegisterEventCallback(self):
+ """
+ This method register the handler which listen to guest changes
+
+ If virt-who is running in background mode with libvirt backend, it can
+ monitor virt guests changes and send updates as soon as the change happens,
+
+ """
+ if self.options.background and not self.options.useVDSM:
+ if self.virt is not None and self.subscriptionManager is not None:
+ # Send list of virt guests when something changes in libvirt
+ self.virt.domainListChangedCallback(self.subscriptionManager.sendVirtGuests)
+ # Register listener for domain changes
+ self.virt.virt.domainEventRegister(self.virt.changed, None)
+
+ def checkConnections(self):
+ """
+ Check if connection to subscription manager and virtualization supervisor
+ is established and reconnect if needed.
+ """
+ if self.subscriptionManager is None:
+ self.initSM()
+ if self.virt is None:
+ self.initVirt()
+
+ def send(self):
+ """
+ Send list of uuids to subscription manager
+
+ return - True if sending is successful, False otherwise
+ """
+ # Try to send it twice
+ return self._send(True)
+
+ def _send(self, retry):
+ """
+ Send list of uuids to subscription manager. This method will call itself
+ once if sending fails.
+
+ retry - Should be True on first run, False on second.
+ return - True if sending is successful, False otherwise
+ """
+ try:
+ self.checkConnections()
+ self.subscriptionManager.sendVirtGuests(self.virt.listDomains())
+ return True
+ except VirtError, e:
+ # Communication with virtualization supervisor failed
+ logger.exception(e)
+ self.virt = None
+ # Retry once
+ if retry:
+ logger.error("Error in communication with virt backend, trying to recover")
+ return self._send(False)
+ else:
+ logger.error("Unable to recover, retry in %d seconds." % RetryInterval)
+ return False
+ except SubscriptionManagerError, e:
+ # Communication with subscription manager failed
+ logger.exception(e)
+ self.subscriptionManager = None
+ # Retry once
+ if retry:
+ logger.error("Error in communication with candlepin, trying to recover")
+ return self._send(False)
+ else:
+ logger.error("Unable to recover, retry in %d seconds." % RetryInterval)
+ return False
+ except Exception, e:
+ # Some other error happens
+ logger.exception(e)
+ self.virt = None
+ self.subscriptionManager = None
+ # Retry once
+ if retry:
+ logger.error("Unexcepted error occurs, trying to recover")
+ return self._send(False)
+ else:
+ logger.error("Unable to recover, retry in %d seconds." % RetryInterval)
+ return False
+
+ def ping(self):
+ """
+ Test if connection to virtualization manager is alive.
+
+ return - True if connection is alive, False otherwise
+ """
+ if self.virt is None:
+ return False
+ return self.virt.ping()
if __name__ == '__main__':
log.init_logger()
@@ -80,9 +216,10 @@ if __name__ == '__main__':
logger.warning("Interval is not positive number, ignoring")
options.interval = 0
- if options.background and options.interval > 0:
- logger.warning("Interval and background options can't be used together, using interval only")
- options.background = False
+ if options.background and options.interval == 0:
+ # Interval is still used in background mode, because events can get lost
+ # (e.g. libvirtd restart)
+ options.interval = DefaultInterval
if options.background and options.useVDSM:
logger.error("Unable to start in background in VDSM mode, use interval instead")
@@ -105,47 +242,37 @@ if __name__ == '__main__':
f.write("%d" % os.getpid())
f.close()
except Exception, e:
- logger.error("Unable to create pid file: %s", str(e))
+ logger.error("Unable to create pid file: %s" % str(e))
- virEventLoopPureStart()
+ if not options.useVDSM:
+ virEventLoopPureStart()
- try:
- subscriptionManager = SubscriptionManager(logger)
- except NoOptionError, e:
- logger.error("Error in reading configuration file (/etc/rhsm/rhsm.conf): %s" % e)
- sys.exit(2)
+ virtWho = VirtWho(logger, options)
- if options.useVDSM:
- try:
- virt = VDSM(logger)
- except Exception, e:
- logger.exception(e)
- sys.exit(3)
- else:
- try:
- virt = Virt(logger)
- except VirtError, e:
- logger.exception(e)
- sys.exit(3)
+ if options.interval > 0:
+ if options.background:
+ logger.debug("Starting infinite loop with %d seconds interval and event handling" % options.interval)
+ else:
+ logger.debug("Starting infinite loop with %d seconds interval" % options.interval)
- subscriptionManager.connect()
- if options.background:
- # Run rhsm.sendVirtGuests when something changes in libvirt
- virt.domainListChangedCallback(subscriptionManager.sendVirtGuests)
- # Register listener for domain changes
- virt.virt.domainEventRegister(virt.changed, None)
- # Send current virt guests
- subscriptionManager.sendVirtGuests(virt.listDomains())
- # libvirt event loop is running in separate thread, wait forever
- logger.debug("Entering infinite loop")
while 1:
- time.sleep(1)
- elif options.interval > 0:
- logger.debug("Starting infinite loop with %d seconds interval" % options.interval)
- while 1:
- # Run in infinite loop and send list of UUIDs every N seconds
- subscriptionManager.sendVirtGuests(virt.listDomains())
- time.sleep(options.interval)
+ # Run in infinite loop and send list of UUIDs every 'options.interval' seconds
+
+ if virtWho.send():
+ # Check if connection is established each 'RetryInterval' seconds
+ slept = 0
+ while slept < options.interval:
+ # Sleep 'RetryInterval' or the rest of options.interval
+ t = min(RetryInterval, options.interval - RetryInterval)
+ time.sleep(t)
+ slept += t
+ # Check the connection
+ if not virtWho.ping():
+ # End the cycle
+ break
+ else:
+ # If last send fails, new try will be sooner
+ time.sleep(RetryInterval)
else:
# Send list of virtual guests and exit
- subscriptionManager.sendVirtGuests(virt.listDomains())
+ virtWho.send()
diff --git a/virt.py b/virt.py
index 2b8ef16..a64b0e1 100644
--- a/virt.py
+++ b/virt.py
@@ -30,7 +30,7 @@ class Virt:
self.logger = logger
self.virt = None
# Log libvirt errors
- libvirt.registerErrorHandler(lambda ctx, error: self.logger.debug(error), None)
+ libvirt.registerErrorHandler(lambda ctx, error: None, None) #self.logger.exception(error), None)
try:
self.virt = libvirt.openReadOnly("")
except libvirt.libvirtError, e:
@@ -40,18 +40,20 @@ class Virt:
""" Get list of all domains. """
domains = []
- # Active domains
- for domainID in self.virt.listDomainsID():
- domain = self.virt.lookupByID(domainID)
- domains.append(domain)
- self.logger.debug("Virtual machine found: %s: %s" % (domain.name(), domain.UUIDString()))
-
- # Non active domains
- for domainName in self.virt.listDefinedDomains():
- domain = self.virt.lookupByName(domainName)
- domains.append(domain)
- self.logger.debug("Virtual machine found: %s: %s" % (domainName, domain.UUIDString()))
-
+ try:
+ # Active domains
+ for domainID in self.virt.listDomainsID():
+ domain = self.virt.lookupByID(domainID)
+ domains.append(domain)
+ self.logger.debug("Virtual machine found: %s: %s" % (domain.name(), domain.UUIDString()))
+
+ # Non active domains
+ for domainName in self.virt.listDefinedDomains():
+ domain = self.virt.lookupByName(domainName)
+ domains.append(domain)
+ self.logger.debug("Virtual machine found: %s: %s" % (domainName, domain.UUIDString()))
+ except libvirt.libvirtError, e:
+ raise VirtError(str(e))
return domains
def __del__(self):
@@ -66,6 +68,13 @@ class Virt:
def domainListChangedCallback(self, callback):
self.changedCallback = callback
+ def ping(self):
+ try:
+ self.virt.getVersion()
+ return True
+ except Exception:
+ return False
+
def eventToString(event):
eventStrings = ( "Defined",
"Undefined",
12 years, 5 months
[virt-who/vsphere: 2/2] Initial implementation of vsphere support.
by Radek Novacek
commit a3a557f1be5a5d64dbca1afcec2488beb61d7403
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Wed Nov 16 17:59:35 2011 +0100
Initial implementation of vsphere support.
So far as a standalone script only.
vsphere.py | 33 ++++++++++++++++++++++++++++-----
1 files changed, 28 insertions(+), 5 deletions(-)
---
diff --git a/vsphere.py b/vsphere.py
index da91015..c6fdc43 100644
--- a/vsphere.py
+++ b/vsphere.py
@@ -2,9 +2,9 @@
import sys
import suds
-#import logging
-#logging.basicConfig(level=logging.INFO)
-#logging.getLogger('suds.client').setLevel(logging.DEBUG)
+import logging
+logging.basicConfig(level=logging.INFO)
+logging.getLogger('suds.client').setLevel(logging.DEBUG)
def get_search_filter_spec(client, begin_entity, property_spec):
""" Build a PropertyFilterSpec capable of full inventory traversal.
@@ -147,7 +147,7 @@ class VSphere:
hostObjs.append(host)
# Get list of host uuids, names and virtual machines
- object_contents = self.RetrieveProperties('HostSystem', ['name', 'vm', 'hardware'], hostObjs)
+ object_contents = self.RetrieveProperties('HostSystem', ['name', 'vm', 'hardware', 'config'], hostObjs)
vmObjs = []
for host in object_contents:
for propSet in host.propSet:
@@ -161,6 +161,18 @@ class VSphere:
v = VM(vm)
self.vms[vm.value] = v
self.hosts[host.obj.value].vms.append(v)
+ elif propSet.name == 'config':
+ self.hosts[host.obj.value].osType = propSet.val.product.osType
+ self.hosts[host.obj.value].product = propSet.val.product.fullName
+ if hasattr(propSet.val.network, 'pnic'):
+ for nic in propSet.val.network.pnic:
+ self.hosts[host.obj.value].nics[nic.mac] = Nic(nic.device, nic.mac, nic.spec.ip.ipAddress)
+ if hasattr(propSet.val.network, 'consoleVnic'):
+ for nic in propSet.val.network.consoleVnic:
+ self.hosts[host.obj.value].nics[nic.spec.mac].ip = nic.spec.ip.ipAddress
+ if hasattr(propSet.val.network, 'vnic'):
+ for nic in propSet.val.network.vnic:
+ self.hosts[host.obj.value].nics[nic.spec.mac].ip = nic.spec.ip.ipAddress
# Get list of virtual machine uuids
object_contents = self.RetrieveProperties('VirtualMachine', ['name', 'config'], vmObjs)
@@ -209,7 +221,9 @@ class VSphere:
for cluster in self.clusters.values():
print "ComputeResource: %s" % cluster.name
for host in cluster.hosts:
- print "\tHostSystem: %s (%s)" % (host.name, host.uuid)
+ print "\tHostSystem: %s (%s) <%s, %s>" % (host.name, host.uuid, host.osType, host.product)
+ for mac, nic in host.nics.items():
+ print "\t\tNIC: %s (MAC: %s, IP: %s)" % (nic.device, mac, nic.ip)
for vm in host.vms:
print "\t\tVirtualMachine: %s (%s)" % (vm.name, vm.uuid)
@@ -230,7 +244,10 @@ class Host:
self.value = obj.value
self.name = name
self.uuid = None
+ self.osType = None
+ self.product = None
+ self.nics = {}
self.vms = []
class VM:
@@ -241,6 +258,12 @@ class VM:
self.name = name
self.uuid = None
+class Nic:
+ def __init__(self, device, mac, ip):
+ self.device = device
+ self.mac = mac
+ self.ip = ip
+
if __name__ == '__main__':
# TODO: read from config
if len(sys.argv) < 4:
12 years, 6 months
[virt-who/vsphere: 1/2] Vsphere test script for listing virtual machines in vCenter
by Radek Novacek
commit bbfb9d068a02608fa01d8268c85ba4579431ef58
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Mon Oct 31 09:04:23 2011 +0100
Vsphere test script for listing virtual machines in vCenter
vsphere.py | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 252 insertions(+), 0 deletions(-)
---
diff --git a/vsphere.py b/vsphere.py
new file mode 100644
index 0000000..da91015
--- /dev/null
+++ b/vsphere.py
@@ -0,0 +1,252 @@
+
+import sys
+import suds
+
+#import logging
+#logging.basicConfig(level=logging.INFO)
+#logging.getLogger('suds.client').setLevel(logging.DEBUG)
+
+def get_search_filter_spec(client, begin_entity, property_spec):
+ """ Build a PropertyFilterSpec capable of full inventory traversal.
+
+ By specifying all valid traversal specs we are creating a PFS that
+ can recursively select any object under the given enitity.
+ """
+
+ # The selection spec for additional objects we want to filter
+ ss_strings = ['resource_pool_traversal_spec',
+ 'resource_pool_vm_traversal_spec',
+ 'folder_traversal_spec',
+ 'datacenter_host_traversal_spec',
+ 'datacenter_vm_traversal_spec',
+ 'compute_resource_rp_traversal_spec',
+ 'compute_resource_host_traversal_spec',
+ 'host_vm_traversal_spec']
+
+ # Create a selection spec for each of the strings specified above
+ selection_specs = []
+ for ss_string in ss_strings:
+ sp = client.factory.create('ns0:SelectionSpec')
+ sp.name = ss_string
+ selection_specs.append(sp)
+
+ rpts = client.factory.create('ns0:TraversalSpec')
+ rpts.name = 'resource_pool_traversal_spec'
+ rpts.type = 'ResourcePool'
+ rpts.path = 'resourcePool'
+ rpts.selectSet = [selection_specs[0], selection_specs[1]]
+
+ rpvts = client.factory.create('ns0:TraversalSpec')
+ rpvts.name = 'resource_pool_vm_traversal_spec'
+ rpvts.type = 'ResourcePool'
+ rpvts.path = 'vm'
+
+ crrts = client.factory.create('ns0:TraversalSpec')
+ crrts.name = 'compute_resource_rp_traversal_spec'
+ crrts.type = 'ComputeResource'
+ crrts.path = 'resourcePool'
+ crrts.selectSet = [selection_specs[0], selection_specs[1]]
+
+ crhts = client.factory.create('ns0:TraversalSpec')
+ crhts.name = 'compute_resource_host_traversal_spec'
+ crhts.type = 'ComputeResource'
+ crhts.path = 'host'
+
+ dhts = client.factory.create('ns0:TraversalSpec')
+ dhts.name = 'datacenter_host_traversal_spec'
+ dhts.type = 'Datacenter'
+ dhts.path = 'hostFolder'
+ dhts.selectSet = [selection_specs[2]]
+
+ dvts = client.factory.create('ns0:TraversalSpec')
+ dvts.name = 'datacenter_vm_traversal_spec'
+ dvts.type = 'Datacenter'
+ dvts.path = 'vmFolder'
+ dvts.selectSet = [selection_specs[2]]
+
+ hvts = client.factory.create('ns0:TraversalSpec')
+ hvts.name = 'host_vm_traversal_spec'
+ hvts.type = 'HostSystem'
+ hvts.path = 'vm'
+ hvts.selectSet = [selection_specs[2]]
+
+ fts = client.factory.create('ns0:TraversalSpec')
+ fts.name = 'folder_traversal_spec'
+ fts.type = 'Folder'
+ fts.path = 'childEntity'
+ fts.selectSet = [selection_specs[2], selection_specs[3],
+ selection_specs[4], selection_specs[5],
+ selection_specs[6], selection_specs[7],
+ selection_specs[1]]
+
+ obj_spec = client.factory.create('ns0:ObjectSpec')
+ obj_spec.obj = begin_entity
+ obj_spec.selectSet = [fts, dvts, dhts, crhts, crrts, rpts, hvts, rpvts]
+
+ pfs = client.factory.create('ns0:PropertyFilterSpec')
+ pfs.propSet = [property_spec]
+ pfs.objectSet = [obj_spec]
+ return pfs
+
+
+class VSphere:
+ def __init__(self, url, username, password):
+ self.url = url
+
+ # Connect to the vCenter server
+ self.client = suds.client.Client("%s/sdk/vimService.wsdl" % url)
+
+ self.client.set_options(location="%s/sdk" % url)
+
+ # Get Meta Object Reference to ServiceInstance which is the root object of the inventory
+ self.moRef = suds.sudsobject.Property('ServiceInstance')
+ self.moRef._type = 'ServiceInstance'
+
+ # Service Content object defines properties of the ServiceInstance object
+ self.sc = self.client.service.RetrieveServiceContent(_this=self.moRef)
+
+ # Login to server using given credentials
+ self.client.service.Login(_this=self.sc.sessionManager, userName=username, password=password)
+
+ self.clusters = {}
+ self.hosts = {}
+ self.vms = {}
+
+ def scan(self):
+ """
+ Scan method does full inventory traversal on the vCenter machine. It finds
+ all ComputeResources, Hosts and VirtualMachines.
+ """
+
+ # Find all ComputeResources in whole vsphere tree
+ ts = self.client.factory.create('ns0:PropertySpec')
+ ts.type = 'ComputeResource'
+ ts.pathSet = 'name'
+ ts.all = True
+ object_content = self.client.service.RetrieveProperties(_this=self.sc.propertyCollector,
+ specSet=[get_search_filter_spec(self.client, self.sc.rootFolder, [ts])])
+
+ # Get properties of each cluster
+ clusterObjs = []
+ for cluster in object_content:
+ for propSet in cluster.propSet:
+ if propSet.name == "name":
+ self.clusters[cluster.obj.value] = Cluster(cluster.obj, propSet.val)
+ clusterObjs.append(cluster.obj)
+
+ # Get list of hosts from cluster
+ object_contents = self.RetrieveProperties('ComputeResource', 'host', clusterObjs)
+ hostObjs = []
+ for cluster in object_contents:
+ for propSet in cluster.propSet:
+ if propSet.name == 'host':
+ for host in propSet.val.ManagedObjectReference:
+ h = Host(host)
+ self.hosts[host.value] = h
+ self.clusters[cluster.obj.value].hosts.append(h)
+ hostObjs.append(host)
+
+ # Get list of host uuids, names and virtual machines
+ object_contents = self.RetrieveProperties('HostSystem', ['name', 'vm', 'hardware'], hostObjs)
+ vmObjs = []
+ for host in object_contents:
+ for propSet in host.propSet:
+ if propSet.name == "name":
+ self.hosts[host.obj.value].name = propSet.val
+ elif propSet.name == "hardware":
+ self.hosts[host.obj.value].uuid = propSet.val.systemInfo.uuid
+ elif propSet.name == "vm":
+ for vm in propSet.val.ManagedObjectReference:
+ vmObjs.append(vm)
+ v = VM(vm)
+ self.vms[vm.value] = v
+ self.hosts[host.obj.value].vms.append(v)
+
+ # Get list of virtual machine uuids
+ object_contents = self.RetrieveProperties('VirtualMachine', ['name', 'config'], vmObjs)
+ for obj in object_contents:
+ for propSet in obj.propSet:
+ if propSet.name == 'name':
+ self.vms[obj.obj.value].name = propSet.val
+ elif propSet.name == 'config':
+ self.vms[obj.obj.value].uuid = propSet.val.uuid
+
+
+ def RetrieveProperties(self, propSetType, propSetPathSet, objects):
+ """
+ Retrieve properties (defined by propSetPathSet) of objects of type propSetType.
+
+ propSetType - name of the type to query
+ propSetPathSet - property or list of properties to obtain
+ objects - get properties of each object from this list
+
+ return - object_properties struct
+ """
+
+ # PropertyFilterSpec is constructed from PropertySpec and ObjectSpec
+ propSet = self.client.factory.create('ns0:PropertySpec')
+ propSet.type = propSetType
+ propSet.all = False
+ propSet.pathSet = propSetPathSet
+
+ objectSets = []
+ for obj in objects:
+ objectSet = self.client.factory.create('ns0:ObjectSpec')
+ objectSet.obj = obj
+ objectSets.append(objectSet)
+
+ pfs = self.client.factory.create('ns0:PropertyFilterSpec')
+ pfs.propSet = [propSet]
+ pfs.objectSet = objectSets
+
+ # Query the VSphere server
+ return self.client.service.RetrieveProperties(_this=self.sc.propertyCollector, specSet=[pfs])
+
+ def printLayout(self):
+ """
+ Prints the layout of vCenter.
+ """
+ for cluster in self.clusters.values():
+ print "ComputeResource: %s" % cluster.name
+ for host in cluster.hosts:
+ print "\tHostSystem: %s (%s)" % (host.name, host.uuid)
+ for vm in host.vms:
+ print "\t\tVirtualMachine: %s (%s)" % (vm.name, vm.uuid)
+
+class Cluster:
+ def __init__(self, obj, name=None):
+ self.obj = obj
+ self._type = obj._type
+ self.value = obj.value
+ self.name = name
+ self.uuid = None
+
+ self.hosts = []
+
+class Host:
+ def __init__(self, obj, name=None):
+ self.obj = obj
+ self._type = obj._type
+ self.value = obj.value
+ self.name = name
+ self.uuid = None
+
+ self.vms = []
+
+class VM:
+ def __init__(self, obj, name=None):
+ self.obj = obj
+ self.value = obj.value
+ self._type = obj._type
+ self.name = name
+ self.uuid = None
+
+if __name__ == '__main__':
+ # TODO: read from config
+ if len(sys.argv) < 4:
+ print "Usage: %s url username password"
+ sys.exit(0)
+
+ vsphere = VSphere(sys.argv[1], sys.argv[2], sys.argv[3])
+ vsphere.scan()
+ vsphere.printLayout()
12 years, 6 months
[virt-who] (2 commits) Created branch vsphere
by Radek Novacek
The branch 'vsphere' was created.
Summary of new commits:
bbfb9d0... Vsphere test script for listing virtual machines in vCenter
a3a557f... Initial implementation of vsphere support.
12 years, 6 months