Keep guest instances when libvirt host restarts

This commit is contained in:
Justin Santa Barbara 2011-04-07 23:52:48 +00:00 committed by Tarmac
commit df0e479e20
3 changed files with 48 additions and 19 deletions

View File

@ -1097,12 +1097,8 @@ class ComputeManager(manager.SchedulerDependentManager):
db_instance['id'],
vm_state)
if vm_state == power_state.SHUTOFF:
# TODO(soren): This is what the compute manager does when you
# terminate an instance. At some point I figure we'll have a
# "terminated" state and some sort of cleanup job that runs
# occasionally, cleaning them out.
self.db.instance_destroy(context, db_instance['id'])
# NOTE(justinsb): We no longer auto-remove SHUTOFF instances
# It's quite hard to get them back when we do.
# Are there VMs not in the DB?
for vm_not_found_in_db in vms_not_found_in_db:

View File

@ -666,4 +666,5 @@ class ComputeTestCase(test.TestCase):
instances = db.instance_get_all(context.get_admin_context())
LOG.info(_("After force-killing instances: %s"), instances)
self.assertEqual(len(instances), 0)
self.assertEqual(len(instances), 1)
self.assertEqual(power_state.SHUTOFF, instances[0]['state'])

View File

@ -117,6 +117,8 @@ flags.DEFINE_integer('live_migration_bandwidth', 0,
'Define live migration behavior')
flags.DEFINE_string('qemu_img', 'qemu-img',
'binary to use for qemu-img commands')
flags.DEFINE_bool('start_guests_on_host_boot', False,
'Whether to restart guests when the host reboots')
def get_connection(read_only):
@ -231,12 +233,8 @@ class LibvirtConnection(driver.ComputeDriver):
{'name': instance['name'], 'state': state})
db.instance_set_state(ctxt, instance['id'], state)
if state == power_state.SHUTOFF:
# TODO(soren): This is what the compute manager does when you
# terminate # an instance. At some point I figure we'll have a
# "terminated" state and some sort of cleanup job that runs
# occasionally, cleaning them out.
db.instance_destroy(ctxt, instance['id'])
# NOTE(justinsb): We no longer delete SHUTOFF instances,
# the user may want to power them back on
if state != power_state.RUNNING:
continue
@ -475,7 +473,7 @@ class LibvirtConnection(driver.ComputeDriver):
xml = self.to_xml(instance)
self.firewall_driver.setup_basic_filtering(instance)
self.firewall_driver.prepare_instance_filter(instance)
self._conn.createXML(xml, 0)
self._create_new_domain(xml)
self.firewall_driver.apply_instance_filter(instance)
timer = utils.LoopingCall(f=None)
@ -523,7 +521,7 @@ class LibvirtConnection(driver.ComputeDriver):
'kernel_id': FLAGS.rescue_kernel_id,
'ramdisk_id': FLAGS.rescue_ramdisk_id}
self._create_image(instance, xml, '.rescue', rescue_images)
self._conn.createXML(xml, 0)
self._create_new_domain(xml)
timer = utils.LoopingCall(f=None)
@ -566,10 +564,15 @@ class LibvirtConnection(driver.ComputeDriver):
self.firewall_driver.setup_basic_filtering(instance, network_info)
self.firewall_driver.prepare_instance_filter(instance, network_info)
self._create_image(instance, xml, network_info)
self._conn.createXML(xml, 0)
domain = self._create_new_domain(xml)
LOG.debug(_("instance %s: is running"), instance['name'])
self.firewall_driver.apply_instance_filter(instance)
if FLAGS.start_guests_on_host_boot:
LOG.debug(_("instance %s: setting autostart ON") %
instance['name'])
domain.setAutostart(1)
timer = utils.LoopingCall(f=None)
def _wait_for_boot():
@ -989,11 +992,22 @@ class LibvirtConnection(driver.ComputeDriver):
return xml
def get_info(self, instance_name):
# NOTE(justinsb): When libvirt isn't running / can't connect, we get:
# libvir: Remote error : unable to connect to
# '/var/run/libvirt/libvirt-sock', libvirtd may need to be started:
# No such file or directory
try:
virt_dom = self._conn.lookupByName(instance_name)
except:
raise exception.NotFound(_("Instance %s not found")
% instance_name)
except libvirt.libvirtError as e:
errcode = e.get_error_code()
if errcode == libvirt.VIR_ERR_NO_DOMAIN:
raise exception.NotFound(_("Instance %s not found")
% instance_name)
LOG.warning(_("Error from libvirt during lookup. "
"Code=%(errcode)s Error=%(e)s") %
locals())
raise
(state, max_mem, mem, num_cpu, cpu_time) = virt_dom.info()
return {'state': state,
'max_mem': max_mem,
@ -1001,6 +1015,24 @@ class LibvirtConnection(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
if persistent:
# To create a persistent domain, first define it, then launch it.
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 get_diagnostics(self, instance_name):
raise exception.ApiError(_("diagnostics are not supported "
"for libvirt"))