summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-06-06 23:01:20 +0000
committerGerrit Code Review <review@openstack.org>2012-06-06 23:01:20 +0000
commit25b665d6ec966f3b27af56e2085dda0923728bd5 (patch)
treecd79632ae5f86533d674cc9cd551772df50a1ee1
parent21cd91513591729e6bb8bec27e2f50804d7b0f89 (diff)
parentae878fc8b9761d099a4145617e4a48cbeb390623 (diff)
downloadnova-25b665d6ec966f3b27af56e2085dda0923728bd5.tar.gz
nova-25b665d6ec966f3b27af56e2085dda0923728bd5.tar.xz
nova-25b665d6ec966f3b27af56e2085dda0923728bd5.zip
Merge "Refactor libvirt create calls"
-rw-r--r--nova/tests/fakelibvirt.py5
-rw-r--r--nova/tests/test_libvirt.py26
-rw-r--r--nova/virt/libvirt/connection.py142
3 files changed, 81 insertions, 92 deletions
diff --git a/nova/tests/fakelibvirt.py b/nova/tests/fakelibvirt.py
index 693330408..563677cca 100644
--- a/nova/tests/fakelibvirt.py
+++ b/nova/tests/fakelibvirt.py
@@ -288,6 +288,11 @@ class Domain(object):
self._state = VIR_DOMAIN_SHUTDOWN
self._connection._mark_not_running(self)
+ def reset(self, flags):
+ # FIXME: Not handling flags at the moment
+ self._state = VIR_DOMAIN_RUNNING
+ self._connection._mark_running(self)
+
def info(self):
return [self._state,
long(self._def['memory']),
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index daadc43fc..ef2374fca 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -2509,7 +2509,7 @@ class LibvirtDriverTestCase(test.TestCase):
def fake_get_instance_disk_info(instance):
return '[]'
- def fake_destroy(instance, network_info, cleanup=True):
+ def fake_destroy(instance):
pass
def fake_get_host_ip_addr():
@@ -2554,7 +2554,7 @@ class LibvirtDriverTestCase(test.TestCase):
def fake_get_instance_disk_info(instance):
return disk_info_text
- def fake_destroy(instance, network_info, cleanup=True):
+ def fake_destroy(instance):
pass
def fake_get_host_ip_addr():
@@ -2636,9 +2636,12 @@ class LibvirtDriverTestCase(test.TestCase):
block_device_info=None):
pass
- def fake_create_new_domain(xml):
+ def fake_create_domain(xml):
return None
+ def fake_enable_hairpin(instance):
+ pass
+
def fake_execute(*args, **kwargs):
pass
@@ -2648,8 +2651,10 @@ class LibvirtDriverTestCase(test.TestCase):
self.stubs.Set(self.libvirtconnection, 'plug_vifs', fake_plug_vifs)
self.stubs.Set(self.libvirtconnection, '_create_image',
fake_create_image)
- self.stubs.Set(self.libvirtconnection, '_create_new_domain',
- fake_create_new_domain)
+ self.stubs.Set(self.libvirtconnection, '_create_domain',
+ fake_create_domain)
+ self.stubs.Set(self.libvirtconnection, '_enable_hairpin',
+ fake_enable_hairpin)
self.stubs.Set(utils, 'execute', fake_execute)
fw = base_firewall.NoopFirewallDriver()
self.stubs.Set(self.libvirtconnection, 'firewall_driver', fw)
@@ -2671,15 +2676,20 @@ class LibvirtDriverTestCase(test.TestCase):
def fake_plug_vifs(instance, network_info):
pass
- def fake_create_new_domain(xml):
+ def fake_create_domain(xml):
return None
+ def fake_enable_hairpin(instance):
+ pass
+
self.stubs.Set(self.libvirtconnection, 'plug_vifs', fake_plug_vifs)
self.stubs.Set(utils, 'execute', fake_execute)
fw = base_firewall.NoopFirewallDriver()
self.stubs.Set(self.libvirtconnection, 'firewall_driver', fw)
- self.stubs.Set(self.libvirtconnection, '_create_new_domain',
- fake_create_new_domain)
+ self.stubs.Set(self.libvirtconnection, '_create_domain',
+ fake_create_domain)
+ self.stubs.Set(self.libvirtconnection, '_enable_hairpin',
+ fake_enable_hairpin)
with utils.tempdir() as tmpdir:
self.flags(instances_path=tmpdir)
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
index 763202218..a8bdd3b38 100644
--- a/nova/virt/libvirt/connection.py
+++ b/nova/virt/libvirt/connection.py
@@ -400,8 +400,7 @@ class LibvirtDriver(driver.ComputeDriver):
for (network, mapping) in network_info:
self.vif_driver.unplug(instance, (network, mapping))
- def _destroy(self, instance, network_info, block_device_info=None,
- cleanup=True):
+ def _destroy(self, instance):
try:
virt_dom = self._lookup_by_name(instance['name'])
except exception.NotFound:
@@ -430,6 +429,33 @@ class LibvirtDriver(driver.ComputeDriver):
locals(), instance=instance)
raise
+ def _wait_for_destroy():
+ """Called at an interval until the VM is gone."""
+ try:
+ state = self.get_info(instance)['state']
+ except exception.NotFound:
+ LOG.error(_("During wait destroy, instance disappeared."),
+ instance=instance)
+ raise utils.LoopingCallDone(False)
+
+ if state == power_state.SHUTOFF:
+ LOG.info(_("Instance destroyed successfully."),
+ instance=instance)
+ raise utils.LoopingCallDone(True)
+
+ timer = utils.LoopingCall(_wait_for_destroy)
+ return timer.start(interval=0.5)
+
+ def destroy(self, instance, network_info, block_device_info=None):
+ self._destroy(instance)
+ self._cleanup(instance, network_info, block_device_info)
+
+ def _cleanup(self, instance, network_info, block_device_info):
+ try:
+ virt_dom = self._lookup_by_name(instance['name'])
+ except exception.NotFound:
+ virt_dom = None
+ if virt_dom:
try:
# NOTE(derekh): we can switch to undefineFlags and
# VIR_DOMAIN_UNDEFINE_MANAGED_SAVE once we require 0.9.4
@@ -440,11 +466,8 @@ class LibvirtDriver(driver.ComputeDriver):
LOG.error(_("Error from libvirt during saved instance "
"removal. Code=%(errcode)s Error=%(e)s") %
locals(), instance=instance)
-
try:
- # NOTE(justinsb): We remove the domain definition. We probably
- # would do better to keep it if cleanup=False (e.g. volumes?)
- # (e.g. #2 - not losing machines on failure)
+ # NOTE(justinsb): We remove the domain definition.
virt_dom.undefine()
except libvirt.libvirtError as e:
errcode = e.get_error_code()
@@ -454,19 +477,6 @@ class LibvirtDriver(driver.ComputeDriver):
raise
self.unplug_vifs(instance, network_info)
-
- def _wait_for_destroy():
- """Called at an interval until the VM is gone."""
- try:
- self.get_info(instance)
- except exception.NotFound:
- LOG.info(_("Instance destroyed successfully."),
- instance=instance)
- raise utils.LoopingCallDone
-
- timer = utils.LoopingCall(_wait_for_destroy)
- timer.start(interval=0.5)
-
try:
self.firewall_driver.unfilter_instance(instance,
network_info=network_info)
@@ -487,16 +497,7 @@ class LibvirtDriver(driver.ComputeDriver):
self.volume_driver_method('disconnect_volume',
connection_info,
mountpoint)
- if cleanup:
- self._cleanup(instance)
- return True
-
- def destroy(self, instance, network_info, block_device_info=None):
- return self._destroy(instance, network_info, block_device_info,
- cleanup=True)
-
- def _cleanup(self, instance):
target = os.path.join(FLAGS.instances_path, instance['name'])
LOG.info(_('Deleting instance files %(target)s') % locals(),
instance=instance)
@@ -785,18 +786,7 @@ class LibvirtDriver(driver.ComputeDriver):
existing domain.
"""
virt_dom = self._conn.lookupByName(instance['name'])
- # NOTE(itoumsn): Use XML delived from the running instance
- # instead of using to_xml(instance, network_info). This is almost
- # the ultimate stupid workaround.
- if not xml:
- xml = virt_dom.XMLDesc(0)
-
- self._destroy(instance, network_info, cleanup=False)
- self.plug_vifs(instance, network_info)
- self.firewall_driver.setup_basic_filtering(instance, network_info)
- self.firewall_driver.prepare_instance_filter(instance, network_info)
- self._create_new_domain(xml)
- self.firewall_driver.apply_instance_filter(instance, network_info)
+ virt_dom.reset(0)
def _wait_for_reboot():
"""Called at an interval until the VM is running again."""
@@ -842,9 +832,9 @@ class LibvirtDriver(driver.ComputeDriver):
@exception.wrap_exception()
def resume_state_on_host_boot(self, context, instance, network_info):
"""resume guest state when a host is booted"""
- # NOTE(dprince): use hard reboot to ensure network and firewall
- # rules are configured
- self._hard_reboot(instance, network_info)
+ virt_dom = self._conn.lookupByName(instance['name'])
+ xml = virt_dom.XMLDesc(0)
+ self._create_domain_and_network(xml, instance, network_info)
@exception.wrap_exception()
def rescue(self, context, instance, network_info, image_meta):
@@ -873,22 +863,21 @@ class LibvirtDriver(driver.ComputeDriver):
rescue=rescue_images)
self._create_image(context, instance, xml, '.rescue', rescue_images,
network_info=network_info)
- self._hard_reboot(instance, network_info, xml=xml)
+ self._destroy(instance)
+ self._create_domain(xml, virt_dom)
@exception.wrap_exception()
def unrescue(self, instance, network_info):
"""Reboot the VM which is being rescued back into primary images.
-
- Because reboot destroys and re-creates instances, unresue should
- simply call reboot.
-
"""
unrescue_xml_path = os.path.join(FLAGS.instances_path,
instance['name'],
'unrescue.xml')
xml = libvirt_utils.load_file(unrescue_xml_path)
+ virt_dom = self._conn.lookupByName(instance['name'])
+ self._destroy(instance)
+ self._create_domain(xml, virt_dom)
libvirt_utils.file_delete(unrescue_xml_path)
- self._hard_reboot(instance, network_info, xml=xml)
rescue_files = os.path.join(FLAGS.instances_path, instance['name'],
"*.rescue")
for rescue_file in glob.iglob(rescue_files):
@@ -918,15 +907,10 @@ class LibvirtDriver(driver.ComputeDriver):
block_device_info=None):
xml = self.to_xml(instance, network_info, image_meta,
block_device_info=block_device_info)
- self.firewall_driver.setup_basic_filtering(instance, network_info)
- self.firewall_driver.prepare_instance_filter(instance, network_info)
self._create_image(context, instance, xml, network_info=network_info,
block_device_info=block_device_info)
-
- self._create_new_domain(xml)
+ self._create_domain_and_network(xml, instance, network_info)
LOG.debug(_("Instance is running"), instance=instance)
- self._enable_hairpin(instance)
- self.firewall_driver.apply_instance_filter(instance, network_info)
def _wait_for_boot():
"""Called at an interval until the VM is running."""
@@ -1751,22 +1735,25 @@ class LibvirtDriver(driver.ComputeDriver):
'num_cpu': num_cpu,
'cpu_time': cpu_time}
- def _create_new_domain(self, xml, persistent=True, launch_flags=0):
- # NOTE(justinsb): libvirt has two types of domain:
- # * a transient domain disappears when the guest is shutdown
- # or the host is rebooted.
- # * a permanent domain is not automatically deleted
- # NOTE(justinsb): Even for ephemeral instances, transient seems risky
+ def _create_domain(self, xml=None, domain=None, launch_flags=0):
+ """Create a domain.
- if persistent:
- # To create a persistent domain, first define it, then launch it.
+ Either domain or xml must be passed in. If both are passed, then
+ the domain definition is overwritten from the xml.
+ """
+ if xml:
domain = self._conn.defineXML(xml)
+ domain.createWithFlags(launch_flags)
+ return domain
- domain.createWithFlags(launch_flags)
- else:
- # createXML call creates a transient domain
- domain = self._conn.createXML(xml, launch_flags)
-
+ def _create_domain_and_network(self, xml, instance, network_info):
+ """Do required network setup and create domain."""
+ self.plug_vifs(instance, network_info)
+ self.firewall_driver.setup_basic_filtering(instance, network_info)
+ self.firewall_driver.prepare_instance_filter(instance, network_info)
+ domain = self._create_domain(xml)
+ self._enable_hairpin(instance)
+ self.firewall_driver.apply_instance_filter(instance, network_info)
return domain
def get_all_block_devices(self):
@@ -2527,7 +2514,7 @@ class LibvirtDriver(driver.ComputeDriver):
disk_info_text = self.get_instance_disk_info(instance['name'])
disk_info = jsonutils.loads(disk_info_text)
- self._destroy(instance, network_info, cleanup=False)
+ self._destroy(instance)
# copy disks to destination
# if disk type is qcow2, convert to raw then send to dest.
@@ -2609,19 +2596,12 @@ class LibvirtDriver(driver.ComputeDriver):
utils.execute('mv', path_qcow, info['path'])
xml = self.to_xml(instance, network_info)
-
- self.plug_vifs(instance, network_info)
- self.firewall_driver.setup_basic_filtering(instance, network_info)
- self.firewall_driver.prepare_instance_filter(instance, network_info)
# assume _create_image do nothing if a target file exists.
# TODO(oda): injecting files is not necessary
self._create_image(context, instance, xml,
network_info=network_info,
block_device_info=None)
-
- self._create_new_domain(xml)
- self.firewall_driver.apply_instance_filter(instance, network_info)
-
+ self._create_domain_and_network(xml, instance, network_info)
timer = utils.LoopingCall(self._wait_for_running, instance)
return timer.start(interval=0.5)
@@ -2636,13 +2616,7 @@ class LibvirtDriver(driver.ComputeDriver):
xml_path = os.path.join(inst_base, 'libvirt.xml')
xml = open(xml_path).read()
-
- self.plug_vifs(instance, network_info)
- self.firewall_driver.setup_basic_filtering(instance, network_info)
- self.firewall_driver.prepare_instance_filter(instance, network_info)
- # images already exist
- self._create_new_domain(xml)
- self.firewall_driver.apply_instance_filter(instance, network_info)
+ self._create_domain_and_network(xml, instance, network_info)
timer = utils.LoopingCall(self._wait_for_running, instance)
return timer.start(interval=0.5)