Example #1
0
    def test_migrate_live_unexpected_error(self):
        body = {
            'os-migrateLive': {
                'host': 'hostname',
                'block_migration': 'auto'
            }
        }
        exc = exception.InvalidHypervisorType(
            reason="The supplied hypervisor type of is invalid.")
        instance = self._stub_instance_get()

        with mock.patch.object(self.compute_api,
                               'live_migrate',
                               side_effect=exc) as mock_live_migrate:
            self.assertRaises(webob.exc.HTTPInternalServerError,
                              self.controller._migrate_live,
                              self.req,
                              instance.uuid,
                              body=body)
            mock_live_migrate.assert_called_once_with(self.context, instance,
                                                      None,
                                                      self.disk_over_commit,
                                                      'hostname', self.force,
                                                      self. async)
        self.mock_get.assert_called_once_with(self.context,
                                              instance.uuid,
                                              expected_attrs=None)
Example #2
0
    def _live_migration_common_check(self, context, instance_ref, dest):
        """Live migration common check routine.

        The following checks are based on
        http://wiki.libvirt.org/page/TodoPreMigrationChecks

        :param context: security context
        :param instance_ref: nova.db.sqlalchemy.models.Instance object
        :param dest: destination host
        """
        dservice_ref = self._get_compute_info(context, dest)
        src = instance_ref['host']
        oservice_ref = self._get_compute_info(context, src)

        # Checking hypervisor is same.
        orig_hypervisor = oservice_ref['hypervisor_type']
        dest_hypervisor = dservice_ref['hypervisor_type']
        if orig_hypervisor != dest_hypervisor:
            raise exception.InvalidHypervisorType()

        # Checking hypervisor version.
        orig_hypervisor = oservice_ref['hypervisor_version']
        dest_hypervisor = dservice_ref['hypervisor_version']
        if orig_hypervisor > dest_hypervisor:
            raise exception.DestinationHypervisorTooOld()
Example #3
0
    def test_migrate_live_invalid_hypervisor_type(self):
        ctxt = context.get_admin_context()
        ctxt.user_id = 'fake'
        ctxt.project_id = 'fake'
        ctxt.is_admin = True
        app = fakes.wsgi_app(fake_auth_context=ctxt, init_only=('servers', ))
        req = webob.Request.blank('/v2/fake/servers/%s/action' % self.UUID)
        req.method = 'POST'
        req.body = jsonutils.dumps({
            'os-migrateLive': {
                'host': 'hostname',
                'block_migration': False,
                'disk_over_commit': False,
            }
        })
        req.content_type = 'application/json'

        def fake_update(inst, context, instance, task_state,
                        expected_task_state):
            return None

        def fake_migrate_server(self, context, instance, scheduler_hint, live,
                                rebuild, flavor, block_migration,
                                disk_over_commit):
            raise exception.InvalidHypervisorType()

        self.stubs.Set(compute_api.API, 'update', fake_update)
        self.stubs.Set(conductor_api.ComputeTaskAPI, 'migrate_server',
                       fake_migrate_server)

        res = req.get_response(app)
        self.assertEqual(res.status_int, 400)
        self.assertIn(unicode(exception.InvalidHypervisorType()), res.body)
Example #4
0
    def _live_migration_common_check(self, context, instance_ref, dest):
        """Live migration common check routine.

        Below checkings are followed by
        http://wiki.libvirt.org/page/TodoPreMigrationChecks

        :param context: security context
        :param instance_ref: nova.db.sqlalchemy.models.Instance object
        :param dest: destination host

        """

        # Checking shared storage connectivity
        self.mounted_on_same_shared_storage(context, instance_ref, dest)

        # Checking dest exists.
        dservice_refs = db.service_get_all_compute_by_host(context, dest)
        dservice_ref = dservice_refs[0]['compute_node'][0]

        # Checking original host( where instance was launched at) exists.
        try:
            oservice_refs = db.service_get_all_compute_by_host(
                context, instance_ref['launched_on'])
        except exception.NotFound:
            raise exception.SourceHostUnavailable()
        oservice_ref = oservice_refs[0]['compute_node'][0]

        # Checking hypervisor is same.
        orig_hypervisor = oservice_ref['hypervisor_type']
        dest_hypervisor = dservice_ref['hypervisor_type']
        if orig_hypervisor != dest_hypervisor:
            raise exception.InvalidHypervisorType()

        # Checkng hypervisor version.
        orig_hypervisor = oservice_ref['hypervisor_version']
        dest_hypervisor = dservice_ref['hypervisor_version']
        if orig_hypervisor > dest_hypervisor:
            raise exception.DestinationHypervisorTooOld()

        # Checking cpuinfo.
        try:
            rpc.call(
                context, db.queue_get_for(context, FLAGS.compute_topic, dest),
                {
                    "method": 'compare_cpu',
                    "args": {
                        'cpu_info': oservice_ref['cpu_info']
                    }
                })

        except rpc.RemoteError:
            src = instance_ref['host']
            logging.exception(
                _("host %(dest)s is not compatible with "
                  "original host %(src)s.") % locals())
            raise
Example #5
0
    def _check_compatible_with_source_hypervisor(self, destination):
        source_info = self._get_compute_info(self.source)
        destination_info = self._get_compute_info(destination)

        source_type = source_info['hypervisor_type']
        destination_type = destination_info['hypervisor_type']
        if source_type != destination_type:
            raise exception.InvalidHypervisorType()

        source_version = source_info['hypervisor_version']
        destination_version = destination_info['hypervisor_version']
        if source_version > destination_version:
            raise exception.DestinationHypervisorTooOld()
Example #6
0
    def test_migrate_live_unexpected_error(self):
        exc = exception.InvalidHypervisorType(
            reason="The supplied hypervisor type of is invalid.")
        self.mox.StubOutWithMock(self.compute_api, 'live_migrate')
        instance = self._stub_instance_get()
        self.compute_api.live_migrate(self.context, instance, None,
                                      self.disk_over_commit, 'hostname',
                                      self.force, self. async).AndRaise(exc)

        self.mox.ReplayAll()
        body = {
            'os-migrateLive': {
                'host': 'hostname',
                'block_migration': 'auto'
            }
        }

        self.assertRaises(webob.exc.HTTPInternalServerError,
                          self.controller._migrate_live,
                          self.req,
                          instance.uuid,
                          body=body)
Example #7
0
 def test_migrate_live_invalid_hypervisor_type(self):
     self._test_migrate_live_failed_with_exception(
         exception.InvalidHypervisorType())
Example #8
0
 def fake_migrate_server(self, context, instance,
         scheduler_hint, live, rebuild, flavor,
         block_migration, disk_over_commit):
     raise exception.InvalidHypervisorType()
Example #9
0
    def _live_migration_common_check(self, context, instance_ref, dest,
                                     block_migration):
        """Live migration common check routine.

        Below checkings are followed by
        http://wiki.libvirt.org/page/TodoPreMigrationChecks

        :param context: security context
        :param instance_ref: nova.db.sqlalchemy.models.Instance object
        :param dest: destination host
        :param block_migration if True, check for block_migration.

        """

        # Checking shared storage connectivity
        # if block migration, instances_paths should not be on shared storage.
        try:
            self.mounted_on_same_shared_storage(context, instance_ref, dest)
            if block_migration:
                reason = _("Block migration can not be used "
                           "with shared storage.")
                raise exception.InvalidSharedStorage(reason=reason, path=dest)
        except exception.FileNotFound:
            if not block_migration:
                src = instance_ref['host']
                ipath = FLAGS.instances_path
                LOG.error(
                    _("Cannot confirm tmpfile at %(ipath)s is on "
                      "same shared storage between %(src)s "
                      "and %(dest)s.") % locals())
                raise

        # Checking dest exists.
        dservice_refs = db.service_get_all_compute_by_host(context, dest)
        dservice_ref = dservice_refs[0]['compute_node'][0]

        # Checking original host( where instance was launched at) exists.
        try:
            oservice_refs = db.service_get_all_compute_by_host(
                context, instance_ref['launched_on'])
        except exception.NotFound:
            raise exception.SourceHostUnavailable()
        oservice_ref = oservice_refs[0]['compute_node'][0]

        # Checking hypervisor is same.
        orig_hypervisor = oservice_ref['hypervisor_type']
        dest_hypervisor = dservice_ref['hypervisor_type']
        if orig_hypervisor != dest_hypervisor:
            raise exception.InvalidHypervisorType()

        # Checkng hypervisor version.
        orig_hypervisor = oservice_ref['hypervisor_version']
        dest_hypervisor = dservice_ref['hypervisor_version']
        if orig_hypervisor > dest_hypervisor:
            raise exception.DestinationHypervisorTooOld()

        # Checking cpuinfo.
        try:
            rpc.call(
                context, db.queue_get_for(context, FLAGS.compute_topic, dest),
                {
                    "method": 'compare_cpu',
                    "args": {
                        'cpu_info': oservice_ref['cpu_info']
                    }
                })

        except rpc.RemoteError:
            src = instance_ref['host']
            LOG.exception(
                _("host %(dest)s is not compatible with "
                  "original host %(src)s.") % locals())
            raise
Example #10
0
    def _live_migration_common_check(self, context, instance_ref, dest,
                                     block_migration, disk_over_commit):
        """Live migration common check routine.

        Below checkings are followed by
        http://wiki.libvirt.org/page/TodoPreMigrationChecks

        :param context: security context
        :param instance_ref: nova.db.sqlalchemy.models.Instance object
        :param dest: destination host
        :param block_migration: if true, block_migration.
        :param disk_over_commit: if True, consider real(not virtual)
                                 disk size.

        """

        # Checking shared storage connectivity
        # if block migration, instances_paths should not be on shared storage.
        shared = self.mounted_on_same_shared_storage(context, instance_ref,
                                                     dest)
        if block_migration:
            if shared:
                reason = _("Block migration can not be used "
                           "with shared storage.")
                raise exception.InvalidSharedStorage(reason=reason, path=dest)

        elif not shared:
            reason = _("Live migration can not be used "
                       "without shared storage.")
            raise exception.InvalidSharedStorage(reason=reason, path=dest)

        # Checking destination host exists.
        dservice_refs = db.service_get_all_compute_by_host(context, dest)
        dservice_ref = dservice_refs[0]['compute_node'][0]

        # Checking original host( where instance was launched at) exists.
        try:
            oservice_refs = db.service_get_all_compute_by_host(context,
                                           instance_ref['host'])
        except exception.NotFound:
            raise exception.SourceHostUnavailable()
        oservice_ref = oservice_refs[0]['compute_node'][0]

        # Checking hypervisor is same.
        orig_hypervisor = oservice_ref['hypervisor_type']
        dest_hypervisor = dservice_ref['hypervisor_type']
        if orig_hypervisor != dest_hypervisor:
            raise exception.InvalidHypervisorType()

        # Checkng hypervisor version.
        orig_hypervisor = oservice_ref['hypervisor_version']
        dest_hypervisor = dservice_ref['hypervisor_version']
        if orig_hypervisor > dest_hypervisor:
            raise exception.DestinationHypervisorTooOld()

        # Checking cpuinfo.
        try:
            self.compute_rpcapi.compare_cpu(context, oservice_ref['cpu_info'],
                                            dest)

        except exception.InvalidCPUInfo:
            src = instance_ref['host']
            LOG.exception(_("host %(dest)s is not compatible with "
                                "original host %(src)s.") % locals())
            raise
Example #11
0
    def test_live_migration_auto_set_dest(self):
        instance = self._live_migration_instance()

        # Confirm scheduler picks target host if none given.
        self.mox.StubOutWithMock(db, 'instance_type_get')
        self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
        self.mox.StubOutWithMock(self.driver, 'select_hosts')
        self.mox.StubOutWithMock(self.driver, '_live_migration_common_check')
        self.mox.StubOutWithMock(rpc, 'call')
        self.mox.StubOutWithMock(self.driver.compute_rpcapi, 'live_migration')

        dest = None
        block_migration = False
        disk_over_commit = False
        instance_type = instance_types.extract_instance_type(instance)
        request_spec = {'instance_properties': instance,
                        'instance_type': instance_type,
                        'instance_uuids': [instance['uuid']],
                        'image': self.image_service.show(self.context,
                                                         instance['image_ref'])
                        }

        self.driver._live_migration_src_check(self.context, instance)

        db.instance_type_get(self.context,
                             instance_type['id']).MultipleTimes().AndReturn(
                                instance_type)

        # First selected host raises exception.InvalidHypervisorType
        self.driver.select_hosts(self.context, request_spec,
                {'ignore_hosts': [instance['host']]}).AndReturn(['fake_host2'])
        self.driver._live_migration_common_check(self.context, instance,
                'fake_host2').AndRaise(exception.InvalidHypervisorType())

        # Second selected host raises exception.InvalidCPUInfo
        self.driver.select_hosts(self.context, request_spec,
                {'ignore_hosts': [instance['host'],
                                  'fake_host2']}).AndReturn(['fake_host3'])
        self.driver._live_migration_common_check(self.context, instance,
                                                 'fake_host3')
        rpc.call(self.context, "compute.fake_host3",
                   {"method": 'check_can_live_migrate_destination',
                    "args": {'instance': instance,
                             'block_migration': block_migration,
                             'disk_over_commit': disk_over_commit},
                    "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
                 None).AndRaise(exception.InvalidCPUInfo(reason=""))

        # Third selected host pass all checks
        self.driver.select_hosts(self.context, request_spec,
                {'ignore_hosts': [instance['host'],
                                  'fake_host2',
                                  'fake_host3']}).AndReturn(['fake_host4'])
        self.driver._live_migration_common_check(self.context, instance,
                                                 'fake_host4')
        rpc.call(self.context, "compute.fake_host4",
                   {"method": 'check_can_live_migrate_destination',
                    "args": {'instance': instance,
                             'block_migration': block_migration,
                             'disk_over_commit': disk_over_commit},
                    "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
                 None).AndReturn({})
        self.driver.compute_rpcapi.live_migration(self.context,
                host=instance['host'], instance=instance, dest='fake_host4',
                block_migration=block_migration, migrate_data={})

        self.mox.ReplayAll()
        result = self.driver.schedule_live_migration(self.context,
                instance=instance, dest=dest,
                block_migration=block_migration,
                disk_over_commit=disk_over_commit)
        self.assertEqual(result, None)
Example #12
0
 def fake_scheduler_api_live_migration(context, dest,
                                 block_migration=False,
                                 disk_over_commit=False, instance=None,
                                 instance_id=None, topic=None):
     raise exception.InvalidHypervisorType()