Merge "Refactor libvirt create calls"
This commit is contained in:
commit
25b665d6ec
|
@ -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']),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
else:
|
||||
# createXML call creates a transient domain
|
||||
domain = self._conn.createXML(xml, launch_flags)
|
||||
return domain
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue