From 4a9f4f4eef4e6fd6ab84ec2e03437144f9ab62f8 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Thu, 10 Mar 2011 16:07:50 -0600 Subject: More resize --- nova/virt/xenapi/vmops.py | 13 +++++++++++-- nova/virt/xenapi_conn.py | 9 +++++---- 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 562ecd4d5..9e0bd6a75 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -365,9 +365,18 @@ class VMOps(object): return new_cow_uuid - def resize(self, instance, flavor): + def resize_instance(self, instance, vdi_uuid): """Resize a running instance by changing it's RAM and disk size """ - raise NotImplementedError() + vm_ref = VMHelper.lookup(self._session, instance.name) + vdi_ref, vm_vdi_rec = \ + VMHelper.get_vdi_for_vm_safely(self._session, vm_ref) + new_disk_size = instance.local_gb + + #TODO(mdietz): this will need to be adjusted for swap later + task = self._session.call_xenapi('VDI.resize_online', vdi_ref, + new_disk_size) + vm_ref = VMHelper.lookup(self._session, instance.name) + self._session.wait_for_task(task, instance.id) def reboot(self, instance): """Reboot VM instance""" diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index b63a5f8c3..92b262479 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -158,6 +158,11 @@ class XenAPIConnection(object): """Create VM instance""" self._vmops.spawn(instance) + def resize_instance(self, instance, disk_info): + """Resizes instance attributes such as RAM and disk space to the + attributes specified by the record""" + self._vmops.resize_instance(instance, disk_info['cow']) + def finish_resize(self, instance, disk_info): """Completes a resize, turning on the migrated instance""" vdi_uuid = self._vmops.attach_disk(instance, disk_info['base_copy'], @@ -168,10 +173,6 @@ class XenAPIConnection(object): """ Create snapshot from a running VM instance """ self._vmops.snapshot(instance, image_id) - def resize(self, instance, flavor): - """Resize a VM instance""" - raise NotImplementedError() - def reboot(self, instance): """Reboot VM instance""" self._vmops.reboot(instance) -- cgit From c94ec9a5bab6c07b402b68e2f4ff081247a27cda Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 14 Mar 2011 14:17:58 -0700 Subject: Initial implementation of refresh instance states --- nova/virt/connection.py | 4 +++- nova/virt/fake.py | 36 ++++++++++++++++++++++++++---------- nova/virt/hyperv.py | 4 +++- nova/virt/libvirt_conn.py | 24 +++++++++++++++++++++++- nova/virt/xenapi/vmops.py | 19 +++++++++++++++++++ nova/virt/xenapi_conn.py | 7 ++++++- 6 files changed, 80 insertions(+), 14 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/connection.py b/nova/virt/connection.py index 13181b730..d585b6c21 100644 --- a/nova/virt/connection.py +++ b/nova/virt/connection.py @@ -23,6 +23,8 @@ import sys from nova import flags from nova import log as logging +from nova import utils +from nova.compute import driver from nova.virt import fake from nova.virt import libvirt_conn from nova.virt import xenapi_conn @@ -72,4 +74,4 @@ def get_connection(read_only=False): if conn is None: LOG.error(_('Failed to open connection to the hypervisor')) sys.exit(1) - return conn + return utils.check_instance(conn, driver.ComputeDriver) diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 3a06284a1..18cca3f5e 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -26,6 +26,8 @@ semantics of real hypervisor connections. """ from nova import exception +from nova import utils +from nova.compute import driver from nova.compute import power_state @@ -34,7 +36,14 @@ def get_connection(_): return FakeConnection.instance() -class FakeConnection(object): +class FakeInstance(object): + + def __init__(self, name, state): + self.name = name + self.state = state + + +class FakeConnection(driver.ComputeDriver): """ The interface to this class talks in terms of 'instances' (Amazon EC2 and internal Nova terminology), by which we mean 'running virtual machine' @@ -90,6 +99,17 @@ class FakeConnection(object): """ return self.instances.keys() + def _map_to_instance_info(self, instance): + instance = utils.check_instance(instance, FakeInstance) + info = driver.InstanceInfo(instance.name, instance.state) + return info + + def list_instances_detail(self): + info_list = [] + for instance in self.instances: + info_list.append(self._map_to_instance_info(instance)) + return info_list + def spawn(self, instance): """ Create a new instance/VM/domain on the virtualization platform. @@ -109,9 +129,10 @@ class FakeConnection(object): that it was before this call began. """ - fake_instance = FakeInstance() - self.instances[instance.name] = fake_instance - fake_instance._state = power_state.RUNNING + name = instance.name + state = power_state.RUNNING + fake_instance = FakeInstance(name, state) + self.instances[name] = fake_instance def snapshot(self, instance, name): """ @@ -270,7 +291,7 @@ class FakeConnection(object): raise exception.NotFound(_("Instance %s Not Found") % instance_name) i = self.instances[instance_name] - return {'state': i._state, + return {'state': i.state, 'max_mem': 0, 'mem': 0, 'num_cpu': 2, @@ -428,8 +449,3 @@ class FakeConnection(object): """This method is supported only by libvirt.""" raise NotImplementedError('This method is supported only by libvirt.') - -class FakeInstance(object): - - def __init__(self): - self._state = power_state.NOSTATE diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py index 29d18dac5..aea7413c6 100644 --- a/nova/virt/hyperv.py +++ b/nova/virt/hyperv.py @@ -67,6 +67,7 @@ from nova import exception from nova import flags from nova import log as logging from nova.auth import manager +from nova.compute import driver from nova.compute import power_state from nova.virt import images @@ -108,8 +109,9 @@ def get_connection(_): return HyperVConnection() -class HyperVConnection(object): +class HyperVConnection(driver.ComputeDriver): def __init__(self): + super(HyperVConnection, self).__init__() self._conn = wmi.WMI(moniker='//./root/virtualization') self._cim_conn = wmi.WMI(moniker='//./root/cimv2') diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 0b306c950..e95bcac39 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -60,6 +60,7 @@ from nova import log as logging #from nova import test from nova import utils from nova.auth import manager +from nova.compute import driver from nova.compute import instance_types from nova.compute import power_state from nova.virt import disk @@ -154,9 +155,10 @@ def _get_ip_version(cidr): return int(net.version()) -class LibvirtConnection(object): +class LibvirtConnection(driver.ComputeDriver): def __init__(self, read_only): + super(LibvirtConnection, self).__init__() self.libvirt_uri = self.get_uri() self.libvirt_xml = open(FLAGS.libvirt_xml_template).read() @@ -235,6 +237,26 @@ class LibvirtConnection(object): return [self._conn.lookupByID(x).name() for x in self._conn.listDomainsID()] + def _map_to_instance_info(self, domain): + # .info() returns a list of: + #state: one of the state values (virDomainState) + #maxMemory: the maximum memory used by the domain + #memory: the current amount of memory used by the domain + #nbVirtCPU: the number of virtual CPU + #cpuTime: the time used by the domain in nanoseconds + (state, _max_mem, _mem, _num_cpu, _cpu_time) = domain.info() + name = domain.name() + + return driver.InstanceInfo(name, state) + + def list_instances_detail(self): + infos = [] + for domain_id in self._conn.listDomainsID(): + domain = self._conn.lookupById(domain_id) + info = self._map_to_instance_info(domain) + infos.append(info) + return infos + def destroy(self, instance, cleanup=True): try: virt_dom = self._conn.lookupByName(instance['name']) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index fcb290d03..2fce93e38 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -34,6 +34,7 @@ from nova import exception from nova import utils from nova.auth.manager import AuthManager +from nova.compute import driver from nova.compute import power_state from nova.virt.xenapi.network_utils import NetworkHelper from nova.virt.xenapi.vm_utils import VMHelper @@ -55,6 +56,8 @@ class VMOps(object): def list_instances(self): """List VM instances""" + # TODO(justinsb): Should we just always use the details method? + # Seems to be the same number of API calls.. vm_refs = [] for vm_ref in self._session.get_xenapi().VM.get_all(): vm_rec = self._session.get_xenapi().VM.get_record(vm_ref) @@ -62,6 +65,22 @@ class VMOps(object): vm_refs.append(vm_rec["name_label"]) return vm_refs + def list_instances_detail(self): + """List VM instances, returning InstanceInfo objects""" + instance_infos = [] + for vm_ref in self._session.get_xenapi().VM.get_all(): + vm_rec = self._session.get_xenapi().VM.get_record(vm_ref) + if not vm_rec["is_a_template"] and not vm_rec["is_control_domain"]: + name = vm_rec["name_label"] + + #TODO(justinsb): Yuk... + openstack_format = VMHelper.compile_info(vm_rec) + state = openstack_format['state'] + + instance_info = driver.InstanceInfo(name, state) + instance_infos.append(instance_info) + return instance_infos + def _start(self, instance, vm_ref=None): """Power on a VM instance""" if not vm_ref: diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index da42a83b6..9390db0bb 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -69,6 +69,7 @@ from nova import db from nova import utils from nova import flags from nova import log as logging +from nova.compute import driver from nova.virt.xenapi.vmops import VMOps from nova.virt.xenapi.volumeops import VolumeOps @@ -141,10 +142,11 @@ def get_connection(_): return XenAPIConnection(url, username, password) -class XenAPIConnection(object): +class XenAPIConnection(driver.ComputeDriver): """A connection to XenServer or Xen Cloud Platform""" def __init__(self, url, user, pw): + super(XenAPIConnection, self).__init__() session = XenAPISession(url, user, pw) self._vmops = VMOps(session) self._volumeops = VolumeOps(session) @@ -160,6 +162,9 @@ class XenAPIConnection(object): """List VM instances""" return self._vmops.list_instances() + def list_instances_detail(self): + return self._vmops.list_instances_detail() + def spawn(self, instance): """Create VM instance""" self._vmops.spawn(instance) -- cgit From 54f16ee6012082c1ad9de423698573c5d9b47540 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 14 Mar 2011 14:38:39 -0700 Subject: pep8 --- nova/virt/fake.py | 1 - nova/virt/xenapi/vmops.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 18cca3f5e..ccf2a7d68 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -448,4 +448,3 @@ class FakeConnection(driver.ComputeDriver): def unfilter_instance(self, instance_ref): """This method is supported only by libvirt.""" raise NotImplementedError('This method is supported only by libvirt.') - diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 2fce93e38..3a58a887e 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -72,7 +72,7 @@ class VMOps(object): vm_rec = self._session.get_xenapi().VM.get_record(vm_ref) if not vm_rec["is_a_template"] and not vm_rec["is_control_domain"]: name = vm_rec["name_label"] - + #TODO(justinsb): Yuk... openstack_format = VMHelper.compile_info(vm_rec) state = openstack_format['state'] -- cgit From 738653b6b4ac744519a050fe50e7c795a7c63579 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 14 Mar 2011 15:11:14 -0700 Subject: Added test and fixed up code so that it works --- nova/virt/fake.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/fake.py b/nova/virt/fake.py index ccf2a7d68..e0e2369c7 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -106,7 +106,7 @@ class FakeConnection(driver.ComputeDriver): def list_instances_detail(self): info_list = [] - for instance in self.instances: + for instance in self.instances.values(): info_list.append(self._map_to_instance_info(instance)) return info_list @@ -448,3 +448,7 @@ class FakeConnection(driver.ComputeDriver): def unfilter_instance(self, instance_ref): """This method is supported only by libvirt.""" raise NotImplementedError('This method is supported only by libvirt.') + + def test_remove_vm(self, instance_name): + """ Removes the named VM, as if it crashed. For testing""" + self.instances.pop(instance_name) -- cgit From 9f135cc4d6069a0b882c8e848d3b6cb292002d10 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 14 Mar 2011 15:37:04 -0700 Subject: Implemented Hyper-V list_instances_detail function. Needs a cleanup by someone that knows the Hyper-V code --- nova/virt/hyperv.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py index aea7413c6..435272109 100644 --- a/nova/virt/hyperv.py +++ b/nova/virt/hyperv.py @@ -126,6 +126,19 @@ class HyperVConnection(driver.ComputeDriver): for v in self._conn.Msvm_ComputerSystem(['ElementName'])] return vms + def list_instances_detail(self): + #TODO(justinsb): This is a terrible implementation (1+N) + instance_infos = [] + for instance_name in self.list_instances(): + info = self.get_info(instance_name) + + state = info['state'] + + instance_info = driver.InstanceInfo(instance_name, state) + instance_infos.append(instance_info) + + return instance_infos + def spawn(self, instance): """ Create a new VM and start it.""" vm = self._lookup(instance.name) @@ -347,7 +360,7 @@ class HyperVConnection(driver.ComputeDriver): newinst = cl.new() #Copy the properties from the original. for prop in wmi_obj._properties: - newinst.Properties_.Item(prop).Value =\ + newinst.Properties_.Item(prop).Value = \ wmi_obj.Properties_.Item(prop).Value return newinst -- cgit From 74987666f89b4d15ffcf17b43b3752135ba08a65 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Tue, 15 Mar 2011 18:48:17 -0500 Subject: A few fixes --- nova/virt/xenapi/vmops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index d1aaf998f..119d6dba8 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -304,7 +304,7 @@ class VMOps(object): try: # transfer the base copy template_vm_ref, template_vdi_uuids = self._get_snapshot(instance) - base_copy_uuid = template_vdi_uuids[1] + base_copy_uuid = template_vdi_uuids['snap'] vdi_ref, vm_vdi_rec = \ VMHelper.get_vdi_for_vm_safely(self._session, vm_ref) cow_uuid = vm_vdi_rec['uuid'] @@ -319,7 +319,7 @@ class VMOps(object): self._session.wait_for_task(task, instance.id) # Now power down the instance and transfer the COW VHD - self._shutdown(instance, vm_ref, method='clean') + self._shutdown(instance, vm_ref) params = {'host': dest, 'vdi_uuid': cow_uuid, -- cgit From 39e722b58b87297aee770637f6a82ee1f206aecf Mon Sep 17 00:00:00 2001 From: Cerberus Date: Tue, 15 Mar 2011 18:51:22 -0500 Subject: Tweak --- nova/virt/xenapi/vmops.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 119d6dba8..958201695 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -319,7 +319,7 @@ class VMOps(object): self._session.wait_for_task(task, instance.id) # Now power down the instance and transfer the COW VHD - self._shutdown(instance, vm_ref) + self._shutdown(instance, vm_ref, hard=False) params = {'host': dest, 'vdi_uuid': cow_uuid, @@ -447,7 +447,8 @@ class VMOps(object): """Shutdown an instance""" state = self.get_info(instance['name'])['state'] if state == power_state.SHUTDOWN: - LOG.warn(_("VM %(vm)s already halted, skipping shutdown...") % + instance_name = instance.name + LOG.warn(_("VM %(instance_name)s already halted, skipping shutdown...") % locals()) return -- cgit From 9650e73db3e18f839f8abf7a47aebb6fbf8c9e36 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Tue, 15 Mar 2011 19:10:50 -0500 Subject: Plugin --- nova/virt/xenapi/vmops.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 958201695..cdc4a417c 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -370,7 +370,6 @@ class VMOps(object): #TODO(mdietz): this will need to be adjusted for swap later task = self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size) - vm_ref = VMHelper.lookup(self._session, instance.name) self._session.wait_for_task(task, instance.id) def reboot(self, instance): -- cgit From 9cb503ae9d4112fa464f2284631ad1e24f8f7ce4 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 16 Mar 2011 11:38:40 -0500 Subject: Stuff --- nova/virt/xenapi/vmops.py | 3 +-- nova/virt/xenapi_conn.py | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index cdc4a417c..ebaa4a69a 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -363,8 +363,7 @@ class VMOps(object): def resize_instance(self, instance, vdi_uuid): """Resize a running instance by changing it's RAM and disk size """ vm_ref = VMHelper.lookup(self._session, instance.name) - vdi_ref, vm_vdi_rec = \ - VMHelper.get_vdi_for_vm_safely(self._session, vm_ref) + vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) new_disk_size = instance.local_gb #TODO(mdietz): this will need to be adjusted for swap later diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 6b1b51fee..b8256d205 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -164,15 +164,11 @@ class XenAPIConnection(object): """Create VM instance""" self._vmops.spawn(instance) - def resize_instance(self, instance, disk_info): - """Resizes instance attributes such as RAM and disk space to the - attributes specified by the record""" - self._vmops.resize_instance(instance, disk_info['cow']) - def finish_resize(self, instance, disk_info): """Completes a resize, turning on the migrated instance""" vdi_uuid = self._vmops.attach_disk(instance, disk_info['base_copy'], disk_info['cow']) + self._vmops.resize_instance(instance, vdi_uuid) self._vmops._spawn_with_disk(instance, vdi_uuid) def snapshot(self, instance, image_id): -- cgit From dee86f53b0d1dccbc69d354b66ca7a4767e81d43 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 16 Mar 2011 11:54:10 -0500 Subject: tweak --- nova/virt/xenapi/vmops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index ebaa4a69a..483b0cb82 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -364,7 +364,7 @@ class VMOps(object): """Resize a running instance by changing it's RAM and disk size """ vm_ref = VMHelper.lookup(self._session, instance.name) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) - new_disk_size = instance.local_gb + new_disk_size = instance.local_gb * 1024 #TODO(mdietz): this will need to be adjusted for swap later task = self._session.call_xenapi('VDI.resize_online', vdi_ref, -- cgit From d99a8d48cf38eb6be01587f9b377f48ff6cd88a2 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Wed, 16 Mar 2011 17:09:13 +0000 Subject: Logging statements --- nova/virt/xenapi/vmops.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 483b0cb82..c292822ca 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -363,13 +363,16 @@ class VMOps(object): def resize_instance(self, instance, vdi_uuid): """Resize a running instance by changing it's RAM and disk size """ vm_ref = VMHelper.lookup(self._session, instance.name) - vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) new_disk_size = instance.local_gb * 1024 + LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %d megs") % (vdi_uuid, + instance.name, new_disk_size)) + vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) #TODO(mdietz): this will need to be adjusted for swap later task = self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size) self._session.wait_for_task(task, instance.id) + LOG.debug(_("Resize instance %s complete") % (instance.name)) def reboot(self, instance): """Reboot VM instance""" -- cgit From a31e715617e5af107bc79caeedf0aff41f65fb07 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 16 Mar 2011 12:57:45 -0500 Subject: The geebees --- nova/virt/xenapi/vmops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index c292822ca..b449437c9 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -363,7 +363,7 @@ class VMOps(object): def resize_instance(self, instance, vdi_uuid): """Resize a running instance by changing it's RAM and disk size """ vm_ref = VMHelper.lookup(self._session, instance.name) - new_disk_size = instance.local_gb * 1024 + new_disk_size = str(instance.local_gb * 1024 * 1024) LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %d megs") % (vdi_uuid, instance.name, new_disk_size)) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) -- cgit From e2399c434386a31114273f2cf6f14586a25480c2 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 16 Mar 2011 13:06:49 -0500 Subject: Derped again --- nova/virt/xenapi/vmops.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index b449437c9..7f80de8a9 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -363,8 +363,10 @@ class VMOps(object): def resize_instance(self, instance, vdi_uuid): """Resize a running instance by changing it's RAM and disk size """ vm_ref = VMHelper.lookup(self._session, instance.name) - new_disk_size = str(instance.local_gb * 1024 * 1024) - LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %d megs") % (vdi_uuid, + + #The new disk size must be in bytes + new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024) + LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %s megs") % (vdi_uuid, instance.name, new_disk_size)) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) -- cgit From 647f5f0d0283b3852115d821b80a965b0bc92c35 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 16 Mar 2011 13:24:51 -0500 Subject: chchchchchanges --- nova/virt/xenapi/vmops.py | 19 ++++++++++--------- nova/virt/xenapi_conn.py | 3 ++- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 7f80de8a9..6ff0aad15 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -72,7 +72,7 @@ class VMOps(object): LOG.debug(_("Starting instance %s"), instance.name) self._session.call_xenapi('VM.start', vm_ref, False, False) - def create_disk(self, instance): + def _create_disk(self, instance): user = AuthManager().get_user(instance.user_id) project = AuthManager().get_project(instance.project_id) disk_image_type = VMHelper.determine_disk_image_type(instance) @@ -81,11 +81,11 @@ class VMOps(object): return vdi_uuid def spawn(self, instance): - vdi_uuid = self.create_disk(instance) - self._spawn_with_disk(instance, vdi_uuid=vdi_uuid) + vdi_uuid = self._create_disk(instance) + vm_ref = self._create_vm(instance, vdi_uuid) + self._spawn(instance, vm_ref) - def _spawn_with_disk(self, instance, vdi_uuid): - """Create VM instance""" + def _create_vm(self, instance, vdi_uuid): instance_name = instance.name vm_ref = VMHelper.lookup(self._session, instance_name) if vm_ref is not None: @@ -130,7 +130,10 @@ class VMOps(object): # inject_network_info and create vifs networks = self.inject_network_info(instance) self.create_vifs(instance, networks) + return vm_ref + def _spawn(self, instance, vm_ref): + """Spawn a new instance""" LOG.debug(_('Starting VM %s...'), vm_ref) self._start(instance, vm_ref) LOG.info(_('Spawning VM %(instance_name)s created %(vm_ref)s.') @@ -364,16 +367,14 @@ class VMOps(object): """Resize a running instance by changing it's RAM and disk size """ vm_ref = VMHelper.lookup(self._session, instance.name) + #TODO(mdietz): this will need to be adjusted for swap later #The new disk size must be in bytes new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024) LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %s megs") % (vdi_uuid, instance.name, new_disk_size)) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) - #TODO(mdietz): this will need to be adjusted for swap later - task = self._session.call_xenapi('VDI.resize_online', vdi_ref, - new_disk_size) - self._session.wait_for_task(task, instance.id) + self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size) LOG.debug(_("Resize instance %s complete") % (instance.name)) def reboot(self, instance): diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index b8256d205..fd68c0fe7 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -168,8 +168,9 @@ class XenAPIConnection(object): """Completes a resize, turning on the migrated instance""" vdi_uuid = self._vmops.attach_disk(instance, disk_info['base_copy'], disk_info['cow']) + self._vmops._create_vm(instance, vdi_uuid) self._vmops.resize_instance(instance, vdi_uuid) - self._vmops._spawn_with_disk(instance, vdi_uuid) + self._vmops._spawn_with_disk(instance) def snapshot(self, instance, image_id): """ Create snapshot from a running VM instance """ -- cgit From 11e7b6a08d1557a0986b480c032958cd30762f33 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 16 Mar 2011 13:31:05 -0500 Subject: chchchchchanges --- nova/virt/xenapi/vmops.py | 2 -- nova/virt/xenapi_conn.py | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 6ff0aad15..92594c9c6 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -365,8 +365,6 @@ class VMOps(object): def resize_instance(self, instance, vdi_uuid): """Resize a running instance by changing it's RAM and disk size """ - vm_ref = VMHelper.lookup(self._session, instance.name) - #TODO(mdietz): this will need to be adjusted for swap later #The new disk size must be in bytes new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024) diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index fd68c0fe7..046f74c8d 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -168,9 +168,9 @@ class XenAPIConnection(object): """Completes a resize, turning on the migrated instance""" vdi_uuid = self._vmops.attach_disk(instance, disk_info['base_copy'], disk_info['cow']) - self._vmops._create_vm(instance, vdi_uuid) + vm_ref = self._vmops._create_vm(instance, vdi_uuid) self._vmops.resize_instance(instance, vdi_uuid) - self._vmops._spawn_with_disk(instance) + self._vmops._spawn(instance, vm_ref) def snapshot(self, instance, image_id): """ Create snapshot from a running VM instance """ -- cgit From d8c3ea5e6b594e6285650c5bdac6302b7be295dc Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 16 Mar 2011 13:39:43 -0500 Subject: chchchchchanges --- nova/virt/xenapi/vmops.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 92594c9c6..931fc1cb4 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -136,6 +136,7 @@ class VMOps(object): """Spawn a new instance""" LOG.debug(_('Starting VM %s...'), vm_ref) self._start(instance, vm_ref) + instance_name = instance.name LOG.info(_('Spawning VM %(instance_name)s created %(vm_ref)s.') % locals()) -- cgit From 007c2802e542bf954f0aa5b589f2adc3a1bfa89a Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 16 Mar 2011 15:41:53 -0500 Subject: Reverting --- nova/virt/xenapi/vmops.py | 10 +++------- nova/virt/xenapi_conn.py | 8 ++++---- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 931fc1cb4..7525ff5ec 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -85,7 +85,8 @@ class VMOps(object): vm_ref = self._create_vm(instance, vdi_uuid) self._spawn(instance, vm_ref) - def _create_vm(self, instance, vdi_uuid): + def _spawn(self, instance, vdi_uuid): + """Spawn a new instance""" instance_name = instance.name vm_ref = VMHelper.lookup(self._session, instance_name) if vm_ref is not None: @@ -130,13 +131,8 @@ class VMOps(object): # inject_network_info and create vifs networks = self.inject_network_info(instance) self.create_vifs(instance, networks) - return vm_ref - - def _spawn(self, instance, vm_ref): - """Spawn a new instance""" LOG.debug(_('Starting VM %s...'), vm_ref) self._start(instance, vm_ref) - instance_name = instance.name LOG.info(_('Spawning VM %(instance_name)s created %(vm_ref)s.') % locals()) @@ -343,7 +339,7 @@ class VMOps(object): # sensible so we don't need to blindly pass around dictionaries return {'base_copy': base_copy_uuid, 'cow': cow_uuid} - def attach_disk(self, instance, base_copy_uuid, cow_uuid): + def link_disks(self, instance, base_copy_uuid, cow_uuid): """Links the base copy VHD to the COW via the XAPI plugin""" vm_ref = VMHelper.lookup(self._session, instance.name) new_base_copy_uuid = str(uuid.uuid4()) diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 046f74c8d..99ec53c11 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -166,11 +166,11 @@ class XenAPIConnection(object): def finish_resize(self, instance, disk_info): """Completes a resize, turning on the migrated instance""" - vdi_uuid = self._vmops.attach_disk(instance, disk_info['base_copy'], + vdi_uuid = self._vmops.link_disks(instance, disk_info['base_copy'], disk_info['cow']) - vm_ref = self._vmops._create_vm(instance, vdi_uuid) - self._vmops.resize_instance(instance, vdi_uuid) - self._vmops._spawn(instance, vm_ref) + #vm_ref = self._vmops._create_vm(instance, vdi_uuid) + #self._vmops.resize_instance(instance, vdi_uuid) + self._vmops._spawn(instance, vdi_uuid) def snapshot(self, instance, image_id): """ Create snapshot from a running VM instance """ -- cgit From 0e63a45f40a2069d497878b7c05d00522c3a2774 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 16 Mar 2011 16:24:38 -0500 Subject: Again --- nova/virt/xenapi/vmops.py | 13 ++++++++----- nova/virt/xenapi_conn.py | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 7525ff5ec..ab98ef000 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -85,8 +85,7 @@ class VMOps(object): vm_ref = self._create_vm(instance, vdi_uuid) self._spawn(instance, vm_ref) - def _spawn(self, instance, vdi_uuid): - """Spawn a new instance""" + def _create_vm(self, instance, vdi_uuid): instance_name = instance.name vm_ref = VMHelper.lookup(self._session, instance_name) if vm_ref is not None: @@ -131,8 +130,13 @@ class VMOps(object): # inject_network_info and create vifs networks = self.inject_network_info(instance) self.create_vifs(instance, networks) + return vm_ref + + def _spawn(self, instance, vm_ref): + """Spawn a new instance""" LOG.debug(_('Starting VM %s...'), vm_ref) self._start(instance, vm_ref) + instance_name = instance.name LOG.info(_('Spawning VM %(instance_name)s created %(vm_ref)s.') % locals()) @@ -365,10 +369,9 @@ class VMOps(object): #TODO(mdietz): this will need to be adjusted for swap later #The new disk size must be in bytes new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024) - LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %s megs") % (vdi_uuid, - instance.name, new_disk_size)) + LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %sGB") % (vdi_uuid, + instance.name, instance.local_gb)) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) - self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size) LOG.debug(_("Resize instance %s complete") % (instance.name)) diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 99ec53c11..2b0f82a4a 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -168,9 +168,9 @@ class XenAPIConnection(object): """Completes a resize, turning on the migrated instance""" vdi_uuid = self._vmops.link_disks(instance, disk_info['base_copy'], disk_info['cow']) - #vm_ref = self._vmops._create_vm(instance, vdi_uuid) - #self._vmops.resize_instance(instance, vdi_uuid) - self._vmops._spawn(instance, vdi_uuid) + vm_ref = self._vmops._create_vm(instance, vdi_uuid) + self._vmops.resize_instance(instance, vdi_uuid) + self._vmops._spawn(instance, vm_ref) def snapshot(self, instance, image_id): """ Create snapshot from a running VM instance """ -- cgit From c7da5632e954c860defc322e971936a8d60eb8fd Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 16 Mar 2011 16:55:58 -0500 Subject: foo --- nova/virt/xenapi/vmops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index ab98ef000..9719e05b9 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -308,7 +308,7 @@ class VMOps(object): try: # transfer the base copy template_vm_ref, template_vdi_uuids = self._get_snapshot(instance) - base_copy_uuid = template_vdi_uuids['snap'] + base_copy_uuid = template_vdi_uuids['image'] vdi_ref, vm_vdi_rec = \ VMHelper.get_vdi_for_vm_safely(self._session, vm_ref) cow_uuid = vm_vdi_rec['uuid'] -- cgit From aa13754d04c17ae9985017e22ae4f68916bc2781 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Thu, 17 Mar 2011 10:03:47 -0500 Subject: Foo --- nova/virt/xenapi/vmops.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 9719e05b9..b5003f0f8 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -307,7 +307,7 @@ class VMOps(object): template_vdi_uuids = template_vm_ref = None try: # transfer the base copy - template_vm_ref, template_vdi_uuids = self._get_snapshot(instance) + template_vm_ref, template_vdi_uuids = selimage._get_snapshot(instance) base_copy_uuid = template_vdi_uuids['image'] vdi_ref, vm_vdi_rec = \ VMHelper.get_vdi_for_vm_safely(self._session, vm_ref) @@ -368,6 +368,7 @@ class VMOps(object): """Resize a running instance by changing it's RAM and disk size """ #TODO(mdietz): this will need to be adjusted for swap later #The new disk size must be in bytes + new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024) LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %sGB") % (vdi_uuid, instance.name, instance.local_gb)) -- cgit From 4f1f5bb1ed2cbb57e9ba8ea481ae31c0e6acc7bd Mon Sep 17 00:00:00 2001 From: Cerberus Date: Thu, 17 Mar 2011 11:03:07 -0500 Subject: refactoring --- nova/virt/xenapi/vmops.py | 22 +++++++++++++++++----- nova/virt/xenapi_conn.py | 10 +++++----- 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index b5003f0f8..ee99a9918 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -62,6 +62,17 @@ class VMOps(object): vm_refs.append(vm_rec["name_label"]) return vm_refs + def revert_resize(self, instance): + vm_ref = VMHelper.lookup(self._session, instance.name) + self._start(instance, vm_ref) + + def finish_resize(self, instance, disk_info): + vdi_uuid = self._vmops.link_disks(instance, disk_info['base_copy'], + disk_info['cow']) + vm_ref = self._create_vm(instance, vdi_uuid) + self.resize_instance(instance, vdi_uuid) + self._spawn(instance, vm_ref) + def _start(self, instance, vm_ref=None): """Power on a VM instance""" if not vm_ref: @@ -307,7 +318,8 @@ class VMOps(object): template_vdi_uuids = template_vm_ref = None try: # transfer the base copy - template_vm_ref, template_vdi_uuids = selimage._get_snapshot(instance) + template_vm_ref, template_vdi_uuids = \ + self.image._get_snapshot(instance) base_copy_uuid = template_vdi_uuids['image'] vdi_ref, vm_vdi_rec = \ VMHelper.get_vdi_for_vm_safely(self._session, vm_ref) @@ -370,8 +382,8 @@ class VMOps(object): #The new disk size must be in bytes new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024) - LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %sGB") % (vdi_uuid, - instance.name, instance.local_gb)) + LOG.debug(_("Resizpng VDI %s for instance %s. Expanding to %sGB") % + (vdi_uuid, instance.name, instance.local_gb)) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size) LOG.debug(_("Resize instance %s complete") % (instance.name)) @@ -451,8 +463,8 @@ class VMOps(object): state = self.get_info(instance['name'])['state'] if state == power_state.SHUTDOWN: instance_name = instance.name - LOG.warn(_("VM %(instance_name)s already halted, skipping shutdown...") % - locals()) + LOG.warn(_("VM %(instance_name)s already halted," + "skipping shutdown...") % locals()) return instance_id = instance.id diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 2b0f82a4a..da2fb51f1 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -164,13 +164,13 @@ class XenAPIConnection(object): """Create VM instance""" self._vmops.spawn(instance) + def revert_resize(self, instance): + """Reverts a resize, powering back on the instance""" + self._vmops.revert_resize(instance) + def finish_resize(self, instance, disk_info): """Completes a resize, turning on the migrated instance""" - vdi_uuid = self._vmops.link_disks(instance, disk_info['base_copy'], - disk_info['cow']) - vm_ref = self._vmops._create_vm(instance, vdi_uuid) - self._vmops.resize_instance(instance, vdi_uuid) - self._vmops._spawn(instance, vm_ref) + self._vmops.finish_resize(instance, disk_info) def snapshot(self, instance, image_id): """ Create snapshot from a running VM instance """ -- cgit From 1ffef31839f3c1f4386d5df834af6d53483c09ed Mon Sep 17 00:00:00 2001 From: Cerberus Date: Thu, 17 Mar 2011 11:16:59 -0500 Subject: oh come on --- nova/virt/xenapi/vmops.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index ee99a9918..b6bcc60ea 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -318,8 +318,7 @@ class VMOps(object): template_vdi_uuids = template_vm_ref = None try: # transfer the base copy - template_vm_ref, template_vdi_uuids = \ - self.image._get_snapshot(instance) + template_vm_ref, template_vdi_uuids = self._get_snapshot(instance) base_copy_uuid = template_vdi_uuids['image'] vdi_ref, vm_vdi_rec = \ VMHelper.get_vdi_for_vm_safely(self._session, vm_ref) -- cgit From d6ae8e4c2f6011497b1db23fcbafb23b663f924d Mon Sep 17 00:00:00 2001 From: Cerberus Date: Thu, 17 Mar 2011 11:24:24 -0500 Subject: Foo --- nova/virt/xenapi/vmops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index b6bcc60ea..326d43aa9 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -67,7 +67,7 @@ class VMOps(object): self._start(instance, vm_ref) def finish_resize(self, instance, disk_info): - vdi_uuid = self._vmops.link_disks(instance, disk_info['base_copy'], + vdi_uuid = self.link_disks(instance, disk_info['base_copy'], disk_info['cow']) vm_ref = self._create_vm(instance, vdi_uuid) self.resize_instance(instance, vdi_uuid) -- cgit From 9351bd5538ea0fc0a77c4dee13406ac7a71ca1ae Mon Sep 17 00:00:00 2001 From: Cerberus Date: Fri, 18 Mar 2011 17:01:44 -0500 Subject: Seriously? --- nova/virt/xenapi/vmops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index b27fe2216..4dca26f61 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -383,7 +383,7 @@ class VMOps(object): #The new disk size must be in bytes new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024) - LOG.debug(_("Resizpng VDI %s for instance %s. Expanding to %sGB") % + LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %sGB") % (vdi_uuid, instance.name, instance.local_gb)) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size) -- cgit From 62f9cc7cee30332143bf4e6e54fd21335db3c8da Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 14:36:32 +0100 Subject: Convert _cache_image to use utils.synchronized decorator. Disable its test case, since I think it is no longer needed with the tests for synchronized. --- nova/virt/libvirt_conn.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index e80b9fbdf..ca8d81f5f 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -48,7 +48,6 @@ from xml.dom import minidom from eventlet import tpool -from eventlet import semaphore import IPy @@ -552,13 +551,12 @@ class LibvirtConnection(object): os.mkdir(base_dir) base = os.path.join(base_dir, fname) - if fname not in LibvirtConnection._image_sems: - LibvirtConnection._image_sems[fname] = semaphore.Semaphore() - with LibvirtConnection._image_sems[fname]: + @utils.synchronized(fname) + def call_if_not_exists(base, fn, *args, **kwargs): if not os.path.exists(base): fn(target=base, *args, **kwargs) - if not LibvirtConnection._image_sems[fname].locked(): - del LibvirtConnection._image_sems[fname] + + call_if_not_exists(base, fn, *args, **kwargs) if cow: utils.execute('qemu-img', 'create', '-f', 'qcow2', '-o', -- cgit From 01e7e598d0eb4aab9c3e7f69926a2875cdf22136 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 14:39:35 +0100 Subject: Get rid of IptablesManager's explicit semaphore. --- nova/virt/libvirt_conn.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index ca8d81f5f..902866167 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -1766,14 +1766,11 @@ class IptablesFirewallDriver(FirewallDriver): def refresh_security_group_members(self, security_group): pass + @utils.synchronized('iptables', external=True) def refresh_security_group_rules(self, security_group): - # We use the semaphore to make sure noone applies the rule set - # after we've yanked the existing rules but before we've put in - # the new ones. - with self.iptables.semaphore: - for instance in self.instances.values(): - self.remove_filters_for_instance(instance) - self.add_filters_for_instance(instance) + for instance in self.instances.values(): + self.remove_filters_for_instance(instance) + self.add_filters_for_instance(instance) self.iptables.apply() def _security_group_chain_name(self, security_group_id): -- cgit From de2ecf115ff0baf43fa530807997513c728ffdaf Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 15:16:08 +0100 Subject: Fix locking problem in security group refresh code. --- nova/virt/libvirt_conn.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 902866167..fcd78b3b2 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -1766,12 +1766,15 @@ class IptablesFirewallDriver(FirewallDriver): def refresh_security_group_members(self, security_group): pass - @utils.synchronized('iptables', external=True) def refresh_security_group_rules(self, security_group): + self.do_refresh_security_group_rules(security_group) + self.iptables.apply() + + @utils.synchronized('iptables', external=True) + def do_refresh_security_group_rules(self, security_group): for instance in self.instances.values(): self.remove_filters_for_instance(instance) self.add_filters_for_instance(instance) - self.iptables.apply() def _security_group_chain_name(self, security_group_id): return 'nova-sg-%s' % (security_group_id,) -- cgit From 3c7de6db490a8482f6d1fb5fefc750050cb1e269 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 16:42:37 +0100 Subject: Pass a fake timing source to test_ensure_filtering_rules_for_instance_timeout, shaving off 30 seconds of test run time. --- nova/virt/libvirt_conn.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index e80b9fbdf..de4a8fbca 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -42,13 +42,13 @@ import shutil import sys import random import subprocess -import time import uuid from xml.dom import minidom -from eventlet import tpool +from eventlet import greenthread from eventlet import semaphore +from eventlet import tpool import IPy @@ -1133,7 +1133,8 @@ class LibvirtConnection(object): return - def ensure_filtering_rules_for_instance(self, instance_ref): + def ensure_filtering_rules_for_instance(self, instance_ref, + time=None): """Setting up filtering rules and waiting for its completion. To migrate an instance, filtering rules to hypervisors @@ -1157,6 +1158,9 @@ class LibvirtConnection(object): """ + if not time: + time = greenthread + # If any instances never launch at destination host, # basic-filtering must be set here. self.firewall_driver.setup_basic_filtering(instance_ref) -- cgit From 116c0d52d21ebd6ed55a61467aac5d8c06a4b086 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Tue, 22 Mar 2011 17:46:17 +0000 Subject: Merge stuff --- nova/virt/xenapi/vmops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 1f5d2d155..c1a65c997 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -387,8 +387,8 @@ class VMOps(object): #The new disk size must be in bytes new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024) - LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %sGB"), - (vdi_uuid, instance.name, instance.local_gb)) + LOG.debug(_("Resizing VDI %(vdi_uuid) for instance %(instance.name). " + "Expanding to %(instance.local_gb)GB") % locals()) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size) LOG.debug(_("Resize instance %s complete") % (instance.name)) -- cgit From 3b3889a19c4efa8dc917f772613543780f361df3 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Tue, 22 Mar 2011 17:55:40 +0000 Subject: tweak --- nova/virt/xenapi/vmops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index c1a65c997..8ac944966 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -387,8 +387,8 @@ class VMOps(object): #The new disk size must be in bytes new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024) - LOG.debug(_("Resizing VDI %(vdi_uuid) for instance %(instance.name). " - "Expanding to %(instance.local_gb)GB") % locals()) + LOG.debug(_("Resizing VDI %(vdi_uuid) for instance %(instance.name)s. " + "Expanding to %(instance.local_gb)f GB") % locals()) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size) LOG.debug(_("Resize instance %s complete") % (instance.name)) -- cgit From 4c76bcc12954734d19afcb5e4519e35c23e39d6d Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Tue, 22 Mar 2011 18:04:09 +0000 Subject: tweak --- nova/virt/xenapi/vmops.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 8ac944966..383096d63 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -387,8 +387,10 @@ class VMOps(object): #The new disk size must be in bytes new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024) - LOG.debug(_("Resizing VDI %(vdi_uuid) for instance %(instance.name)s. " - "Expanding to %(instance.local_gb)f GB") % locals()) + instance_name = instance.name + instance_local_gb = instance.local_gb + LOG.debug(_("Resizing VDI %(vdi_uuid)s for instance %(instance_name)s." + " Expanding to %(instance_local_gb)d GB") % locals()) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size) LOG.debug(_("Resize instance %s complete") % (instance.name)) -- cgit From 365b98f4d52740ef85f8a8f098a32e441d7ac168 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 22 Mar 2011 21:42:17 -0700 Subject: Renamed check_instance -> check_isinstance to make intent clearer --- nova/virt/connection.py | 2 +- nova/virt/fake.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/connection.py b/nova/virt/connection.py index d585b6c21..4ba31c7a7 100644 --- a/nova/virt/connection.py +++ b/nova/virt/connection.py @@ -74,4 +74,4 @@ def get_connection(read_only=False): if conn is None: LOG.error(_('Failed to open connection to the hypervisor')) sys.exit(1) - return utils.check_instance(conn, driver.ComputeDriver) + return utils.check_isinstance(conn, driver.ComputeDriver) diff --git a/nova/virt/fake.py b/nova/virt/fake.py index e0e2369c7..57b02e00b 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -100,7 +100,7 @@ class FakeConnection(driver.ComputeDriver): return self.instances.keys() def _map_to_instance_info(self, instance): - instance = utils.check_instance(instance, FakeInstance) + instance = utils.check_isinstance(instance, FakeInstance) info = driver.InstanceInfo(instance.name, instance.state) return info -- cgit From 19da125805eedbfcfd202abac4a90c57e6c538c4 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 22 Mar 2011 22:38:37 -0700 Subject: Filled out the base-driver contract, so it's not a false-promise --- nova/virt/driver.py | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 nova/virt/driver.py (limited to 'nova/virt') diff --git a/nova/virt/driver.py b/nova/virt/driver.py new file mode 100644 index 000000000..6c1b97ce9 --- /dev/null +++ b/nova/virt/driver.py @@ -0,0 +1,228 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Driver base-classes: + + (Beginning of) the contract that compute drivers must follow, and shared + types that support that contract +""" + +from nova.compute import power_state + + +class InstanceInfo(object): + def __init__(self, name, state): + self.name = name + assert state in power_state.valid_states() + self.state = state + + +class ComputeDriver(object): + """Base class for compute drivers.""" + + def init_host(self, host): + """Adopt existing VM's running here""" + raise NotImplementedError() + + def get_info(self, instance_name): + """Get the current status of an instance, by name (not ID!) + + Returns a dict containing: + :state: the running state, one of the power_state codes + :max_mem: (int) the maximum memory in KBytes allowed + :mem: (int) the memory in KBytes used by the domain + :num_cpu: (int) the number of virtual CPUs for the domain + :cpu_time: (int) the CPU time used in nanoseconds + """ + raise NotImplementedError() + + def list_instances(self): + raise NotImplementedError() + + def list_instances_detail(self): + """Return a list of InstanceInfo for all registered VMs""" + raise NotImplementedError() + + def spawn(self, instance): + """Launch a VM for the specified instance""" + raise NotImplementedError() + + def destroy(self, instance, cleanup=True): + """Shutdown specified VM""" + raise NotImplementedError() + + def reboot(self, instance): + """Reboot specified VM""" + raise NotImplementedError() + + def snapshot_instance(self, context, instance_id, image_id): + raise NotImplementedError() + + def get_console_pool_info(self, console_type): + """??? + + Returns a dict containing: + :address: ??? + :username: ??? + :password: ??? + """ + raise NotImplementedError() + + def get_console_output(self, instance): + raise NotImplementedError() + + def get_ajax_console(self, instance): + raise NotImplementedError() + + def get_diagnostics(self, instance): + """Return data about VM diagnostics""" + raise NotImplementedError() + + def get_host_ip_addr(self): + raise NotImplementedError() + + def attach_volume(self, context, instance_id, volume_id, mountpoint): + raise NotImplementedError() + + def detach_volume(self, context, instance_id, volume_id): + raise NotImplementedError() + + def compare_cpu(self, context, cpu_info): + raise NotImplementedError() + + def migrate_disk_and_power_off(self, instance, dest): + """Transfers the VHD of a running instance to another host, then shuts + off the instance copies over the COW disk""" + raise NotImplementedError() + + def snapshot(self, instance, image_id): + """ Create snapshot from a running VM instance """ + raise NotImplementedError() + + def finish_resize(self, instance, disk_info): + """Completes a resize, turning on the migrated instance""" + raise NotImplementedError() + + def pause(self, instance, callback): + """Pause VM instance""" + raise NotImplementedError() + + def unpause(self, instance, callback): + """Unpause paused VM instance""" + raise NotImplementedError() + + def suspend(self, instance, callback): + """suspend the specified instance""" + raise NotImplementedError() + + def resume(self, instance, callback): + """resume the specified instance""" + raise NotImplementedError() + + def rescue(self, instance, callback): + """Rescue the specified instance""" + raise NotImplementedError() + + def unrescue(self, instance, callback): + """Unrescue the specified instance""" + raise NotImplementedError() + + def update_available_resource(self, ctxt, host): + """Updates compute manager resource info on ComputeNode table. + + This method is called when nova-compute launches, and + whenever admin executes "nova-manage service update_resource". + + :param ctxt: security context + :param host: hostname that compute manager is currently running + + """ + raise NotImplementedError() + + def live_migration(self, ctxt, instance_ref, dest, + post_method, recover_method): + """Spawning live_migration operation for distributing high-load. + + :params ctxt: security context + :params instance_ref: + nova.db.sqlalchemy.models.Instance object + instance object that is migrated. + :params dest: destination host + :params post_method: + post operation method. + expected nova.compute.manager.post_live_migration. + :params recover_method: + recovery method when any exception occurs. + expected nova.compute.manager.recover_live_migration. + + """ + raise NotImplementedError() + + def refresh_security_group_rules(self, security_group_id): + raise NotImplementedError() + + def refresh_security_group_members(self, security_group_id): + raise NotImplementedError() + + def reset_network(self, instance): + """reset networking for specified instance""" + raise NotImplementedError() + + def ensure_filtering_rules_for_instance(self, instance_ref): + """Setting up filtering rules and waiting for its completion. + + To migrate an instance, filtering rules to hypervisors + and firewalls are inevitable on destination host. + ( Waiting only for filtering rules to hypervisor, + since filtering rules to firewall rules can be set faster). + + Concretely, the below method must be called. + - setup_basic_filtering (for nova-basic, etc.) + - prepare_instance_filter(for nova-instance-instance-xxx, etc.) + + to_xml may have to be called since it defines PROJNET, PROJMASK. + but libvirt migrates those value through migrateToURI(), + so , no need to be called. + + Don't use thread for this method since migration should + not be started when setting-up filtering rules operations + are not completed. + + :params instance_ref: nova.db.sqlalchemy.models.Instance object + + """ + raise NotImplementedError() + + def unfilter_instance(self, instance): + """Stop filtering instance""" + raise NotImplementedError() + + def set_admin_password(self, context, instance_id, new_pass=None): + """Set the root/admin password for an instance on this server.""" + raise NotImplementedError() + + def inject_file(self, instance, b64_path, b64_contents): + """Create a file on the VM instance. The file path and contents + should be base64-encoded. + """ + raise NotImplementedError() + + def inject_network_info(self, instance): + """inject network info for specified instance""" + raise NotImplementedError() + -- cgit From a4d78e44d7ca35a6cca4454667cab743409fd95a Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 22 Mar 2011 22:45:15 -0700 Subject: Added space in between # and TODO in #TODO --- nova/virt/hyperv.py | 2 +- nova/virt/xenapi/vmops.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py index 435272109..21e21ec13 100644 --- a/nova/virt/hyperv.py +++ b/nova/virt/hyperv.py @@ -127,7 +127,7 @@ class HyperVConnection(driver.ComputeDriver): return vms def list_instances_detail(self): - #TODO(justinsb): This is a terrible implementation (1+N) + # TODO(justinsb): This is a terrible implementation (1+N) instance_infos = [] for instance_name in self.list_instances(): info = self.get_info(instance_name) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 3a58a887e..6cd61a86f 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -73,7 +73,7 @@ class VMOps(object): if not vm_rec["is_a_template"] and not vm_rec["is_control_domain"]: name = vm_rec["name_label"] - #TODO(justinsb): Yuk... + # TODO(justinsb): Yuk... openstack_format = VMHelper.compile_info(vm_rec) state = openstack_format['state'] @@ -932,7 +932,7 @@ class VMOps(object): """ vm_ref = self._get_vm_opaque_ref(instance_or_vm) data = self._session.call_xenapi_request('VM.get_xenstore_data', - (vm_ref, )) + (vm_ref,)) ret = {} if keys is None: keys = data.keys() -- cgit From 52c2bb5e7fadf12aae96d895d374990fd4990e29 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 22 Mar 2011 22:49:22 -0700 Subject: Cleaned up comment about virsh domain.info() return format --- nova/virt/libvirt_conn.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index e95bcac39..dfe0bca49 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -60,10 +60,10 @@ from nova import log as logging #from nova import test from nova import utils from nova.auth import manager -from nova.compute import driver from nova.compute import instance_types from nova.compute import power_state from nova.virt import disk +from nova.virt import driver from nova.virt import images libvirt = None @@ -135,8 +135,8 @@ def get_connection(read_only): def _late_load_cheetah(): global Template if Template is None: - t = __import__('Cheetah.Template', globals(), locals(), ['Template'], - -1) + t = __import__('Cheetah.Template', globals(), locals(), + ['Template'], -1) Template = t.Template @@ -238,12 +238,15 @@ class LibvirtConnection(driver.ComputeDriver): for x in self._conn.listDomainsID()] def _map_to_instance_info(self, domain): - # .info() returns a list of: - #state: one of the state values (virDomainState) - #maxMemory: the maximum memory used by the domain - #memory: the current amount of memory used by the domain - #nbVirtCPU: the number of virtual CPU - #cpuTime: the time used by the domain in nanoseconds + """Gets info from a virsh domain object into an InstanceInfo""" + + # domain.info() returns a list of: + # state: one of the state values (virDomainState) + # maxMemory: the maximum memory used by the domain + # memory: the current amount of memory used by the domain + # nbVirtCPU: the number of virtual CPU + # puTime: the time used by the domain in nanoseconds + (state, _max_mem, _mem, _num_cpu, _cpu_time) = domain.info() name = domain.name() -- cgit From 95a32b4ae8d418576799fb9dd5d34e73728d7a1f Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 22 Mar 2011 22:50:45 -0700 Subject: Clarified my "Yuk" comment --- nova/virt/xenapi/vmops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 6cd61a86f..a0c84c803 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -73,7 +73,7 @@ class VMOps(object): if not vm_rec["is_a_template"] and not vm_rec["is_control_domain"]: name = vm_rec["name_label"] - # TODO(justinsb): Yuk... + # TODO(justinsb): This a roundabout way to map the state openstack_format = VMHelper.compile_info(vm_rec) state = openstack_format['state'] -- cgit From b69a63c5d7458610b6e8931b4955c0b5b2b468f5 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 22 Mar 2011 22:58:52 -0700 Subject: Fixed up the new location of driver.py --- nova/virt/driver.py | 5 ++++- nova/virt/fake.py | 2 +- nova/virt/hyperv.py | 2 +- nova/virt/xenapi_conn.py | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 6c1b97ce9..d01a91b93 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -33,7 +33,10 @@ class InstanceInfo(object): class ComputeDriver(object): - """Base class for compute drivers.""" + """Base class for compute drivers. + + Lots of documentation is currently on fake.py. + """ def init_host(self, host): """Adopt existing VM's running here""" diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 57b02e00b..5b0fe1877 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -27,8 +27,8 @@ semantics of real hypervisor connections. from nova import exception from nova import utils -from nova.compute import driver from nova.compute import power_state +from nova.virt import driver def get_connection(_): diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py index 21e21ec13..bd45dfe0e 100644 --- a/nova/virt/hyperv.py +++ b/nova/virt/hyperv.py @@ -67,8 +67,8 @@ from nova import exception from nova import flags from nova import log as logging from nova.auth import manager -from nova.compute import driver from nova.compute import power_state +from nova.virt import driver from nova.virt import images wmi = None diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 9390db0bb..b5bff6c26 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -69,7 +69,7 @@ from nova import db from nova import utils from nova import flags from nova import log as logging -from nova.compute import driver +from nova.virt import driver from nova.virt.xenapi.vmops import VMOps from nova.virt.xenapi.volumeops import VolumeOps -- cgit From 3362be7e9f2feda33e14ab4fb7c6f70277df1cf5 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Wed, 23 Mar 2011 12:53:10 +0000 Subject: Checking whether cidr_v6 is not null before populating ipv6 key in network info map (VMOps._get_network_info) --- nova/virt/xenapi/vmops.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 499c6d8a1..b51489ebc 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -723,8 +723,9 @@ class VMOps(object): 'mac': instance.mac_address, 'rxtx_cap': flavor['rxtx_cap'], 'dns': [network['dns']], - 'ips': [ip_dict(ip) for ip in network_IPs], - 'ip6s': [ip6_dict(ip) for ip in network_IPs]} + 'ips': [ip_dict(ip) for ip in network_IPs]} + if network['cidr_v6']: + info['ip6s'] = [ip6_dict(ip) for ip in network_IPs] network_info.append((network, info)) return network_info -- cgit From abb764f51385a0b811b23379d78f7db027d4cca5 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Wed, 23 Mar 2011 14:41:35 -0500 Subject: Automatically unrescue instances after a given timeout --- nova/virt/libvirt_conn.py | 4 ++ nova/virt/xenapi/vmops.py | 95 +++++++++++++++++++++++++++++++++++------------ nova/virt/xenapi_conn.py | 4 ++ 3 files changed, 79 insertions(+), 24 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index e80b9fbdf..07545382d 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -412,6 +412,10 @@ class LibvirtConnection(object): # the normal xml file, we can just call reboot here self.reboot(instance) + @exception.wrap_exception + def poll_rescued_instances(self, timeout): + pass + @exception.wrap_exception def spawn(self, instance): xml = self.to_xml(instance) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 61ff00903..f46ac3b7e 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -51,6 +51,7 @@ class VMOps(object): def __init__(self, session): self.XenAPI = session.get_imported_xenapi() self._session = session + self.poll_rescue_last_ran = None VMHelper.XenAPI = self.XenAPI @@ -462,6 +463,10 @@ class VMOps(object): except self.XenAPI.Failure, exc: LOG.exception(exc) + def _shutdown_rescue(self, vm_ref): + """Shutdown a rescue instance""" + self._session.call_xenapi("Async.VM.hard_shutdown", rescue_vm_ref) + def _destroy_vdis(self, instance, vm_ref): """Destroys all VDIs associated with a VM""" instance_id = instance.id @@ -479,6 +484,24 @@ class VMOps(object): except self.XenAPI.Failure, exc: LOG.exception(exc) + def _destroy_rescue_vdis(self, rescue_vm_ref): + """Destroys all VDIs associated with a rescued VM""" + vdi_refs = VMHelper.lookup_vm_vdis(self._session, rescue_vm_ref) + for vdi_ref in vdi_refs: + try: + self._session.call_xenapi("Async.VDI.destroy", vdi_ref) + except self.XenAPI.Failure: + continue + + def _destroy_rescue_vbds(self, rescue_vm_ref): + """Destroys all VBDs tied to a rescue VM""" + vbd_refs = self._session.get_xenapi().VM.get_VBDs(rescue_vm_ref) + for vbd_ref in vbd_refs: + _vbd_ref = self._session.get_xenapi().VBD.get_record(vbd_ref) + if _vbd_ref["userdevice"] == "1": + VMHelper.unplug_vbd(self._session, vbd_ref) + VMHelper.destroy_vbd(self._session, vbd_ref) + def _destroy_kernel_ramdisk(self, instance, vm_ref): """ Three situations can occur: @@ -529,6 +552,10 @@ class VMOps(object): LOG.debug(_("Instance %(instance_id)s VM destroyed") % locals()) + def _destroy_rescue(self, vm_ref): + """Destroy a rescue instance""" + self._session.call_xenapi("Async.VM.destroy", rescue_vm_ref) + def destroy(self, instance): """ Destroy VM instance @@ -632,41 +659,61 @@ class VMOps(object): """ rescue_vm_ref = VMHelper.lookup(self._session, - instance.name + "-rescue") + instance.name + "-rescue") if not rescue_vm_ref: raise exception.NotFound(_( "Instance is not in Rescue Mode: %s" % instance.name)) original_vm_ref = self._get_vm_opaque_ref(instance) - vbd_refs = self._session.get_xenapi().VM.get_VBDs(rescue_vm_ref) - instance._rescue = False - for vbd_ref in vbd_refs: - _vbd_ref = self._session.get_xenapi().VBD.get_record(vbd_ref) - if _vbd_ref["userdevice"] == "1": - VMHelper.unplug_vbd(self._session, vbd_ref) - VMHelper.destroy_vbd(self._session, vbd_ref) - - task1 = self._session.call_xenapi("Async.VM.hard_shutdown", - rescue_vm_ref) - self._session.wait_for_task(task1, instance.id) - - vdi_refs = VMHelper.lookup_vm_vdis(self._session, rescue_vm_ref) - for vdi_ref in vdi_refs: - try: - task = self._session.call_xenapi('Async.VDI.destroy', vdi_ref) - self._session.wait_for_task(task, instance.id) - except self.XenAPI.Failure: - continue - - task2 = self._session.call_xenapi('Async.VM.destroy', rescue_vm_ref) - self._session.wait_for_task(task2, instance.id) - + self._destroy_rescue_vbds(rescue_vm_ref) + self._shutdown_rescue(rescue_vm_ref) + self._destroy_rescue_vdis(rescue_vm_ref) + self._destroy_rescue(rescue_vm_ref) self._release_bootlock(original_vm_ref) self._start(instance, original_vm_ref) + def poll_rescued_instances(self, timeout): + """Look for expirable rescued instances + - forcibly exit rescue mode for any instances that have been + in rescue mode for >= the provided timeout + """ + last_ran = self.poll_rescue_last_ran + if last_ran: + if not utils.is_then_greater(last_ran, timeout * 60 * 60): + # Do not run. Let's bail. + return + else: + # Update the time tracker and proceed. + self.poll_rescue_last_ran = utils.utcnow() + else: + # We need a base time to start tracking. + self.poll_rescue_last_ran = utils.utcnow() + return + + vms = [] + for instance in self.list_instances(): + if instance.endswith("-rescue"): + vms.append(dict(name=instance, + vm_ref=VMHelper.lookup(self._session, + instance))) + + for vm in vms: + rescue_name = vm["name"] + rescue_vm_ref = vm["vm_ref"] + original_name = vm["name"].split("-rescue", 1)[0] + original_vm_ref = VMHelper.lookup(self._session, original_name) + + self._destroy_rescue_vbds(rescue_vm_ref) + self._shutdown_rescue(rescue_vm_ref) + self._destroy_rescue_vdis(rescue_vm_ref) + self._destroy_rescue(rescue_vm_ref) + self._release_bootlock(original_vm_ref) + self._session.call_xenapi("VM.start", original_vm_ref, False, + False) + def get_info(self, instance): """Return data about VM instance""" vm_ref = self._get_vm_opaque_ref(instance) diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index da42a83b6..50aad96b8 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -225,6 +225,10 @@ class XenAPIConnection(object): """Unrescue the specified instance""" self._vmops.unrescue(instance, callback) + def poll_rescued_instances(self, timeout): + """Poll for rescued instances""" + self._vmops.poll_rescued_instances(timeout) + def reset_network(self, instance): """reset networking for specified instance""" self._vmops.reset_network(instance) -- cgit From a291e68fef876080d7984a1d7192e939808596bf Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Wed, 23 Mar 2011 14:55:33 -0500 Subject: Fixed some typos --- nova/virt/xenapi/vmops.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index cb36730a0..0a516bd36 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -463,7 +463,7 @@ class VMOps(object): except self.XenAPI.Failure, exc: LOG.exception(exc) - def _shutdown_rescue(self, vm_ref): + def _shutdown_rescue(self, rescue_vm_ref): """Shutdown a rescue instance""" self._session.call_xenapi("Async.VM.hard_shutdown", rescue_vm_ref) @@ -552,7 +552,7 @@ class VMOps(object): LOG.debug(_("Instance %(instance_id)s VM destroyed") % locals()) - def _destroy_rescue(self, vm_ref): + def _destroy_rescue_instance(self, rescue_vm_ref): """Destroy a rescue instance""" self._session.call_xenapi("Async.VM.destroy", rescue_vm_ref) @@ -671,7 +671,7 @@ class VMOps(object): self._destroy_rescue_vbds(rescue_vm_ref) self._shutdown_rescue(rescue_vm_ref) self._destroy_rescue_vdis(rescue_vm_ref) - self._destroy_rescue(rescue_vm_ref) + self._destroy_rescue_instance(rescue_vm_ref) self._release_bootlock(original_vm_ref) self._start(instance, original_vm_ref) @@ -709,7 +709,7 @@ class VMOps(object): self._destroy_rescue_vbds(rescue_vm_ref) self._shutdown_rescue(rescue_vm_ref) self._destroy_rescue_vdis(rescue_vm_ref) - self._destroy_rescue(rescue_vm_ref) + self._destroy_rescue_instance(rescue_vm_ref) self._release_bootlock(original_vm_ref) self._session.call_xenapi("VM.start", original_vm_ref, False, False) -- cgit From a12b6f0a0808fba5541723a537118447b55b69ad Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Wed, 23 Mar 2011 17:15:41 -0500 Subject: Better method name --- nova/virt/xenapi/vmops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 0a516bd36..3f1eceddc 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -682,7 +682,7 @@ class VMOps(object): """ last_ran = self.poll_rescue_last_ran if last_ran: - if not utils.is_then_greater(last_ran, timeout * 60 * 60): + if not utils.is_older_than(last_ran, timeout * 60 * 60): # Do not run. Let's bail. return else: -- cgit From e19b12f668fb6cd693df6834f8895fb5487953d7 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Wed, 23 Mar 2011 18:34:47 -0500 Subject: Review feedback --- nova/virt/xenapi/vmops.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 3f1eceddc..1f2e10aa6 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -497,8 +497,8 @@ class VMOps(object): """Destroys all VBDs tied to a rescue VM""" vbd_refs = self._session.get_xenapi().VM.get_VBDs(rescue_vm_ref) for vbd_ref in vbd_refs: - _vbd_ref = self._session.get_xenapi().VBD.get_record(vbd_ref) - if _vbd_ref["userdevice"] == "1": + vbd_rec = self._session.get_xenapi().VBD.get_record(vbd_ref) + if vbd_rec["userdevice"] == "1": # primary VBD is always 1 VMHelper.unplug_vbd(self._session, vbd_ref) VMHelper.destroy_vbd(self._session, vbd_ref) @@ -554,6 +554,10 @@ class VMOps(object): def _destroy_rescue_instance(self, rescue_vm_ref): """Destroy a rescue instance""" + self._destroy_rescue_vbds(rescue_vm_ref) + self._shutdown_rescue(rescue_vm_ref) + self._destroy_rescue_vdis(rescue_vm_ref) + self._session.call_xenapi("Async.VM.destroy", rescue_vm_ref) def destroy(self, instance): @@ -668,9 +672,6 @@ class VMOps(object): original_vm_ref = self._get_vm_opaque_ref(instance) instance._rescue = False - self._destroy_rescue_vbds(rescue_vm_ref) - self._shutdown_rescue(rescue_vm_ref) - self._destroy_rescue_vdis(rescue_vm_ref) self._destroy_rescue_instance(rescue_vm_ref) self._release_bootlock(original_vm_ref) self._start(instance, original_vm_ref) @@ -682,7 +683,7 @@ class VMOps(object): """ last_ran = self.poll_rescue_last_ran if last_ran: - if not utils.is_older_than(last_ran, timeout * 60 * 60): + if not utils.is_older_than(last_ran, timeout): # Do not run. Let's bail. return else: @@ -693,23 +694,22 @@ class VMOps(object): self.poll_rescue_last_ran = utils.utcnow() return - vms = [] + rescue_vms = [] for instance in self.list_instances(): if instance.endswith("-rescue"): - vms.append(dict(name=instance, - vm_ref=VMHelper.lookup(self._session, - instance))) + rescue_vms.append(dict(name=instance, + vm_ref=VMHelper.lookup(self._session, + instance))) - for vm in vms: + for vm in rescue_vms: rescue_name = vm["name"] rescue_vm_ref = vm["vm_ref"] + + self._destroy_rescue_instance(rescue_vm_ref) + original_name = vm["name"].split("-rescue", 1)[0] original_vm_ref = VMHelper.lookup(self._session, original_name) - self._destroy_rescue_vbds(rescue_vm_ref) - self._shutdown_rescue(rescue_vm_ref) - self._destroy_rescue_vdis(rescue_vm_ref) - self._destroy_rescue_instance(rescue_vm_ref) self._release_bootlock(original_vm_ref) self._session.call_xenapi("VM.start", original_vm_ref, False, False) -- cgit From 7a93455f41e5198fdce8aa1b3091efd956e1c186 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 23 Mar 2011 16:49:50 -0700 Subject: Doh! Missed two places which were importing the old driver location --- nova/virt/connection.py | 2 +- nova/virt/xenapi/vmops.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/connection.py b/nova/virt/connection.py index 4ba31c7a7..af7001715 100644 --- a/nova/virt/connection.py +++ b/nova/virt/connection.py @@ -24,7 +24,7 @@ import sys from nova import flags from nova import log as logging from nova import utils -from nova.compute import driver +from nova.virt import driver from nova.virt import fake from nova.virt import libvirt_conn from nova.virt import xenapi_conn diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 2a9694f45..3fd98be67 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -35,8 +35,8 @@ from nova import exception from nova import utils from nova.auth.manager import AuthManager -from nova.compute import driver from nova.compute import power_state +from nova.virt import driver from nova.virt.xenapi.network_utils import NetworkHelper from nova.virt.xenapi.vm_utils import VMHelper from nova.virt.xenapi.vm_utils import ImageType -- cgit From 3c295817f91eb7c76a64d157ff4a938c85075a36 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 23 Mar 2011 18:50:30 -0700 Subject: pep8 fixes, backported some important fixes that didn't make it over from my testing system :-( --- nova/virt/driver.py | 9 ++++----- nova/virt/libvirt_conn.py | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/driver.py b/nova/virt/driver.py index d01a91b93..e82f49ebe 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -28,13 +28,13 @@ from nova.compute import power_state class InstanceInfo(object): def __init__(self, name, state): self.name = name - assert state in power_state.valid_states() + assert state in power_state.valid_states(), "Bad state: %s" % state self.state = state class ComputeDriver(object): """Base class for compute drivers. - + Lots of documentation is currently on fake.py. """ @@ -44,7 +44,7 @@ class ComputeDriver(object): def get_info(self, instance_name): """Get the current status of an instance, by name (not ID!) - + Returns a dict containing: :state: the running state, one of the power_state codes :max_mem: (int) the maximum memory in KBytes allowed @@ -78,7 +78,7 @@ class ComputeDriver(object): def get_console_pool_info(self, console_type): """??? - + Returns a dict containing: :address: ??? :username: ??? @@ -228,4 +228,3 @@ class ComputeDriver(object): def inject_network_info(self, instance): """inject network info for specified instance""" raise NotImplementedError() - diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index e57859f9d..ddc525e06 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -255,7 +255,7 @@ class LibvirtConnection(driver.ComputeDriver): def list_instances_detail(self): infos = [] for domain_id in self._conn.listDomainsID(): - domain = self._conn.lookupById(domain_id) + domain = self._conn.lookupByID(domain_id) info = self._map_to_instance_info(domain) infos.append(info) return infos -- cgit From 31940b550e49c23ba29c71a0e0593a6d14331516 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 23 Mar 2011 19:02:20 -0700 Subject: Added revert_resize to base class --- nova/virt/driver.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'nova/virt') diff --git a/nova/virt/driver.py b/nova/virt/driver.py index e82f49ebe..4c77048be 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -120,6 +120,10 @@ class ComputeDriver(object): def finish_resize(self, instance, disk_info): """Completes a resize, turning on the migrated instance""" raise NotImplementedError() + + def revert_resize(self, instance): + """Reverts a resize, powering back on the instance""" + raise NotImplementedError() def pause(self, instance, callback): """Pause VM instance""" -- cgit From 3cde42aaac50e32f2c8fcd4493c40a2eaf1a0d4d Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 23 Mar 2011 19:15:41 -0700 Subject: pep8 fix --- nova/virt/driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 4c77048be..0e3a4aa3b 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -120,7 +120,7 @@ class ComputeDriver(object): def finish_resize(self, instance, disk_info): """Completes a resize, turning on the migrated instance""" raise NotImplementedError() - + def revert_resize(self, instance): """Reverts a resize, powering back on the instance""" raise NotImplementedError() -- cgit From 10e61af8a23c126c15fcfcf25156d32facf19ec2 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Wed, 23 Mar 2011 22:55:04 -0500 Subject: Added hyperv stub --- nova/virt/hyperv.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'nova/virt') diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py index 29d18dac5..75fed6d4f 100644 --- a/nova/virt/hyperv.py +++ b/nova/virt/hyperv.py @@ -467,3 +467,6 @@ class HyperVConnection(object): if vm is None: raise exception.NotFound('Cannot detach volume from missing %s ' % instance_name) + + def poll_rescued_instances(self, timeout): + pass -- cgit