Subject: [PATCH] Re-establish block storage connections on reboot
Author: Rafi Khardalian <rafi@metacloud.com>
Date:   Thu Aug 9 13:18:54 2012 -0700

Re-establish block storage connections anytime a VM is hard rebooted.
The code path utilized when "start_guests_on_host_boot" is set ultimately
results in a hard reboot, which is also accounted for via this patch.

diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index bb1de9e..d208273 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -256,9 +256,12 @@ class ComputeManager(manager.SchedulerDependentManager):
                 FLAGS.start_guests_on_host_boot):
                 LOG.info(_('Rebooting instance after nova-compute restart.'),
                          locals(), instance=instance)
+
+                block_device_info = self._get_instance_volume_block_device_info(
+                            context, instance['id'])
                 try:
                     self.driver.resume_state_on_host_boot(context, instance,
-                                self._legacy_nw_info(net_info))
+                                self._legacy_nw_info(net_info), block_device_info)
                 except NotImplementedError:
                     LOG.warning(_('Hypervisor driver does not support '
                                   'resume guests'), instance=instance)
@@ -927,8 +930,12 @@ class ComputeManager(manager.SchedulerDependentManager):
                      context=context)
 
         network_info = self._get_instance_nw_info(context, instance)
+
+        block_device_info = self._get_instance_volume_block_device_info(
+                            context, instance['id'])
+
         self.driver.reboot(instance, self._legacy_nw_info(network_info),
-                           reboot_type)
+                           reboot_type, block_device_info)
 
         current_power_state = self._get_power_state(context, instance)
         self._instance_update(context,
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
index 602efd1..a08a3ce 100644
--- a/nova/virt/libvirt/connection.py
+++ b/nova/virt/libvirt/connection.py
@@ -728,7 +728,7 @@ class LibvirtConnection(driver.ComputeDriver):
                                      image_file)
 
     @exception.wrap_exception()
-    def reboot(self, instance, network_info, reboot_type='SOFT'):
+    def reboot(self, instance, network_info, reboot_type='SOFT', block_device_info=None):
         """Reboot a virtual machine, given an instance reference."""
         if reboot_type == 'SOFT':
             # NOTE(vish): This will attempt to do a graceful shutdown/restart.
@@ -739,7 +739,7 @@ class LibvirtConnection(driver.ComputeDriver):
             else:
                 LOG.info(_("Failed to soft reboot instance."),
                          instance=instance)
-        return self._hard_reboot(instance, network_info)
+        return self._hard_reboot(instance, network_info, block_device_info=block_device_info)
 
     def _soft_reboot(self, instance):
         """Attempt to shutdown and restart the instance gracefully.
@@ -774,7 +774,7 @@ class LibvirtConnection(driver.ComputeDriver):
             greenthread.sleep(1)
         return False
 
-    def _hard_reboot(self, instance, network_info, xml=None):
+    def _hard_reboot(self, instance, network_info, xml=None, block_device_info=None):
         """Reboot a virtual machine, given an instance reference.
 
         This method actually destroys and re-creates the domain to ensure the
@@ -783,6 +783,17 @@ class LibvirtConnection(driver.ComputeDriver):
         If xml is set, it uses the passed in xml in place of the xml from the
         existing domain.
         """
+
+        block_device_mapping = driver.block_device_info_get_mapping(
+            block_device_info)
+
+        for vol in block_device_mapping:
+            connection_info = vol['connection_info']
+            mount_device = vol['mount_device'].rpartition("/")[2]
+            self.volume_driver_method('connect_volume',
+                                      connection_info,
+                                      mount_device)
+
         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
@@ -839,11 +850,11 @@ class LibvirtConnection(driver.ComputeDriver):
         dom.create()
 
     @exception.wrap_exception()
-    def resume_state_on_host_boot(self, context, instance, network_info):
+    def resume_state_on_host_boot(self, context, instance, network_info, block_device_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)
+        self._hard_reboot(instance, network_info, block_device_info=block_device_info)
 
     @exception.wrap_exception()
     def rescue(self, context, instance, network_info, image_meta):
