~ubuntu-branches/ubuntu/quantal/nova/quantal-proposed

« back to all changes in this revision

Viewing changes to nova/compute/manager.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-09 14:24:07 UTC
  • mto: This revision was merged to the branch mainline in revision 55.
  • Revision ID: package-import@ubuntu.com-20111209142407-fviz6p5dnictpxsr
Tags: upstream-2012.1~e2~20111208.11721
ImportĀ upstreamĀ versionĀ 2012.1~e2~20111208.11721

Show diffs side-by-side

added added

removed removed

Lines of Context:
300
300
    def _run_instance(self, context, instance_uuid,
301
301
                      requested_networks=None,
302
302
                      injected_files=[],
303
 
                      admin_pass=None,
 
303
                      admin_password=None,
304
304
                      **kwargs):
305
305
        """Launch a new instance with specified options."""
306
306
        context = context.elevated()
315
315
                block_device_info = self._prep_block_device(context, instance)
316
316
                instance = self._spawn(context, instance, image_meta,
317
317
                                       network_info, block_device_info,
318
 
                                       injected_files, admin_pass)
 
318
                                       injected_files, admin_password)
319
319
            except:
320
 
                self._deallocate_network(context, instance)
321
 
                raise
 
320
                with utils.save_and_reraise_exception():
 
321
                    self._deallocate_network(context, instance)
322
322
            self._notify_about_instance_usage(instance)
323
323
        except exception.InstanceNotFound:
324
324
            LOG.exception(_("Instance %s not found.") % instance_uuid)
970
970
        network_info = self._get_instance_nw_info(context, instance_ref)
971
971
        self.driver.destroy(instance_ref, network_info)
972
972
        topic = self.db.queue_get_for(context, FLAGS.compute_topic,
973
 
                instance_ref['host'])
 
973
                migration_ref['source_compute'])
974
974
        rpc.cast(context, topic,
975
975
                {'method': 'finish_revert_resize',
976
976
                 'args': {'instance_uuid': instance_ref['uuid'],
998
998
        self._instance_update(context,
999
999
                              instance_ref["uuid"],
1000
1000
                              memory_mb=instance_type['memory_mb'],
 
1001
                              host=migration_ref['source_compute'],
1001
1002
                              vcpus=instance_type['vcpus'],
1002
1003
                              local_gb=instance_type['local_gb'],
1003
1004
                              instance_type_id=instance_type['id'])
1069
1070
        migration_ref = self.db.migration_get(context, migration_id)
1070
1071
        instance_ref = self.db.instance_get_by_uuid(context,
1071
1072
                migration_ref.instance_uuid)
 
1073
        instance_type_ref = self.db.instance_type_get(context,
 
1074
                migration_ref.new_instance_type_id)
1072
1075
 
1073
1076
        self.db.migration_update(context,
1074
1077
                                 migration_id,
1076
1079
 
1077
1080
        try:
1078
1081
            disk_info = self.driver.migrate_disk_and_power_off(
1079
 
                    context, instance_ref, migration_ref['dest_host'])
1080
 
        except exception.MigrationError, error:
1081
 
            LOG.error(_('%s. Setting instance vm_state to ERROR') % (error,))
1082
 
            self._instance_update(context,
1083
 
                                  instance_uuid,
1084
 
                                  vm_state=vm_states.ERROR)
1085
 
            return
 
1082
                    context, instance_ref, migration_ref['dest_host'],
 
1083
                    instance_type_ref)
 
1084
        except Exception, error:
 
1085
            with utils.save_and_reraise_exception():
 
1086
                msg = _('%s. Setting instance vm_state to ERROR')
 
1087
                LOG.error(msg % error)
 
1088
                self._instance_update(context,
 
1089
                                      instance_uuid,
 
1090
                                      vm_state=vm_states.ERROR)
1086
1091
 
1087
1092
        self.db.migration_update(context,
1088
1093
                                 migration_id,
1133
1138
        # Have to look up image here since we depend on disk_format later
1134
1139
        image_meta = _get_image_meta(context, instance_ref['image_ref'])
1135
1140
 
1136
 
        self.driver.finish_migration(context, migration_ref, instance_ref,
1137
 
                                     disk_info, network_info, image_meta,
1138
 
                                     resize_instance)
 
1141
        try:
 
1142
            self.driver.finish_migration(context, migration_ref, instance_ref,
 
1143
                                         disk_info, network_info, image_meta,
 
1144
                                         resize_instance)
 
1145
        except Exception, error:
 
1146
            with utils.save_and_reraise_exception():
 
1147
                msg = _('%s. Setting instance vm_state to ERROR')
 
1148
                LOG.error(msg % error)
 
1149
                self._instance_update(context,
 
1150
                                      instance_uuid,
 
1151
                                      vm_state=vm_states.ERROR)
1139
1152
 
1140
1153
        self._instance_update(context,
1141
1154
                              instance_uuid,
1794
1807
        self.driver.destroy(instance_ref, network_info,
1795
1808
                            block_device_info, True)
1796
1809
 
1797
 
    def periodic_tasks(self, context=None):
1798
 
        """Tasks to be run at a periodic interval."""
1799
 
        error_list = super(ComputeManager, self).periodic_tasks(context)
1800
 
        if error_list is None:
1801
 
            error_list = []
1802
 
 
1803
 
        try:
1804
 
            if FLAGS.reboot_timeout > 0:
1805
 
                self.driver.poll_rebooting_instances(FLAGS.reboot_timeout)
1806
 
        except Exception as ex:
1807
 
            LOG.warning(_("Error during poll_rebooting_instances: %s"),
1808
 
                    unicode(ex))
1809
 
            error_list.append(ex)
1810
 
 
1811
 
        try:
1812
 
            if FLAGS.rescue_timeout > 0:
1813
 
                self.driver.poll_rescued_instances(FLAGS.rescue_timeout)
1814
 
        except Exception as ex:
1815
 
            LOG.warning(_("Error during poll_rescued_instances: %s"),
1816
 
                    unicode(ex))
1817
 
            error_list.append(ex)
1818
 
 
1819
 
        try:
1820
 
            if FLAGS.resize_confirm_window > 0:
1821
 
                self.driver.poll_unconfirmed_resizes(
1822
 
                        FLAGS.resize_confirm_window)
1823
 
        except Exception as ex:
1824
 
            LOG.warning(_("Error during poll_unconfirmed_resizes: %s"),
1825
 
                    unicode(ex))
1826
 
            error_list.append(ex)
1827
 
 
1828
 
        try:
1829
 
            self._report_driver_status()
1830
 
        except Exception as ex:
1831
 
            LOG.warning(_("Error during report_driver_status(): %s"),
1832
 
                    unicode(ex))
1833
 
            error_list.append(ex)
1834
 
 
1835
 
        try:
1836
 
            self._sync_power_states(context)
1837
 
        except Exception as ex:
1838
 
            LOG.warning(_("Error during power_state sync: %s"), unicode(ex))
1839
 
            error_list.append(ex)
1840
 
 
1841
 
        try:
1842
 
            self._reclaim_queued_deletes(context)
1843
 
        except Exception as ex:
1844
 
            LOG.warning(_("Error during reclamation of queued deletes: %s"),
1845
 
                        unicode(ex))
1846
 
            error_list.append(ex)
1847
 
        try:
1848
 
            start = utils.current_audit_period()[1]
1849
 
            self._update_bandwidth_usage(context, start)
1850
 
        except NotImplementedError:
1851
 
            # Not all hypervisors have bandwidth polling implemented yet.
1852
 
            # If they don't id doesn't break anything, they just don't get the
1853
 
            # info in the usage events. (mdragon)
1854
 
            pass
1855
 
        except Exception as ex:
1856
 
            LOG.warning(_("Error updating bandwidth usage: %s"),
1857
 
                        unicode(ex))
1858
 
            error_list.append(ex)
1859
 
 
1860
 
        return error_list
1861
 
 
1862
 
    def _update_bandwidth_usage(self, context, start_time, stop_time=None):
 
1810
    @manager.periodic_task
 
1811
    def _poll_rebooting_instances(self, context):
 
1812
        if FLAGS.reboot_timeout > 0:
 
1813
            self.driver.poll_rebooting_instances(FLAGS.reboot_timeout)
 
1814
 
 
1815
    @manager.periodic_task
 
1816
    def _poll_rescued_instances(self, context):
 
1817
        if FLAGS.rescue_timeout > 0:
 
1818
            self.driver.poll_rescued_instances(FLAGS.rescue_timeout)
 
1819
 
 
1820
    @manager.periodic_task
 
1821
    def _poll_unconfirmed_resizes(self, context):
 
1822
        if FLAGS.resize_confirm_window > 0:
 
1823
            self.driver.poll_unconfirmed_resizes(FLAGS.resize_confirm_window)
 
1824
 
 
1825
    @manager.periodic_task
 
1826
    def _poll_bandwidth_usage(self, context, start_time=None, stop_time=None):
 
1827
        if not start_time:
 
1828
            start_time = utils.current_audit_period()[1]
 
1829
 
1863
1830
        curr_time = time.time()
1864
1831
        if curr_time - self._last_bw_usage_poll > FLAGS.bandwith_poll_interval:
1865
1832
            self._last_bw_usage_poll = curr_time
1866
1833
            LOG.info(_("Updating bandwidth usage cache"))
1867
 
            bw_usage = self.driver.get_all_bw_usage(start_time, stop_time)
 
1834
 
 
1835
            try:
 
1836
                bw_usage = self.driver.get_all_bw_usage(start_time, stop_time)
 
1837
            except NotImplementedError:
 
1838
                # NOTE(mdragon): Not all hypervisors have bandwidth polling
 
1839
                # implemented yet.  If they don't it doesn't break anything,
 
1840
                # they just don't get the info in the usage events.
 
1841
                return
 
1842
 
1868
1843
            for usage in bw_usage:
1869
1844
                vif = usage['virtual_interface']
1870
1845
                self.db.bw_usage_update(context,
1873
1848
                                        start_time,
1874
1849
                                        usage['bw_in'], usage['bw_out'])
1875
1850
 
1876
 
    def _report_driver_status(self):
 
1851
    @manager.periodic_task
 
1852
    def _report_driver_status(self, context):
1877
1853
        curr_time = time.time()
1878
1854
        if curr_time - self._last_host_check > FLAGS.host_state_interval:
1879
1855
            self._last_host_check = curr_time
1883
1859
            self.update_service_capabilities(
1884
1860
                self.driver.get_host_stats(refresh=True))
1885
1861
 
 
1862
    @manager.periodic_task
1886
1863
    def _sync_power_states(self, context):
1887
1864
        """Align power states between the database and the hypervisor.
1888
1865
 
1921
1898
                                  db_instance["id"],
1922
1899
                                  power_state=vm_power_state)
1923
1900
 
 
1901
    @manager.periodic_task
1924
1902
    def _reclaim_queued_deletes(self, context):
1925
1903
        """Reclaim instances that are queued for deletion."""
 
1904
        if FLAGS.reclaim_instance_interval <= 0:
 
1905
            LOG.debug(_("FLAGS.reclaim_instance_interval <= 0, skipping..."))
 
1906
            return
1926
1907
 
1927
1908
        instances = self.db.instance_get_all_by_host(context, self.host)
1928
 
 
1929
 
        queue_time = datetime.timedelta(
1930
 
                         seconds=FLAGS.reclaim_instance_interval)
1931
 
        curtime = utils.utcnow()
1932
1909
        for instance in instances:
1933
 
            if instance['vm_state'] == vm_states.SOFT_DELETE and \
1934
 
               (curtime - instance['deleted_at']) >= queue_time:
1935
 
                LOG.info('Deleting %s' % instance['name'])
 
1910
            old_enough = (not instance.deleted_at or utils.is_older_than(
 
1911
                    instance.deleted_at,
 
1912
                    FLAGS.reclaim_instance_interval))
 
1913
            soft_deleted = instance.vm_state == vm_states.SOFT_DELETE
 
1914
 
 
1915
            if soft_deleted and old_enough:
 
1916
                instance_id = instance.id
 
1917
                LOG.info(_("Reclaiming deleted instance %(instance_id)s"),
 
1918
                         locals())
1936
1919
                self._delete_instance(context, instance)