Exemple #1
0
    def test_update_migration_record(self):
        db_handler.initialise_flavor_mapping()
        flavor_data = {'src_flavor_name': "name",
                        'src_uuid': "123",
                        'src_cloud': "cloud1",
                        'dst_flavor_name': "d_name",
                        'dst_uuid': "234",
                        'dst_cloud': "cloud2",
                        'state': "unknown"}
        db_handler.record_flavor_migrated([flavor_data])

        new_data = {'src_flavor_name': "name",
                        'src_uuid': "123",
                        'src_cloud': "cloud1",
                        'dst_flavor_name': "d_name",
                        'dst_uuid': "234",
                        'dst_cloud': "cloud2",
                        'state': "completed"}

        values = ["name", "123", "cloud1", "cloud2"]
        db_handler.update_migration_record(**new_data)
        return_data = db_handler.get_migrated_flavor(values)

        self.assertIsNot(None, return_data)
        self.assertEqual("completed", return_data["state"])

        table_name = "flavors"
        w_dict = OrderedDict([('src_flavor_name', "name"),
                              ('src_uuid', "123"),
                              ('src_cloud', "cloud1"),
                              ('dst_cloud', "cloud2")])

        delete_record(table_name, w_dict)
    def revert(self, flavors_to_migrate):
        if flavors_to_migrate is None:
            LOG.info("Start reverting flavours.\n")
            flavors_to_migrate = []
            for flavor in self.nv_source.flavors.list():
                flavors_to_migrate.append(flavor.name)

        elif type(flavors_to_migrate) is str:
            flavors_to_migrate = [flavors_to_migrate]
        elif type(flavors_to_migrate) is list \
                and len(flavors_to_migrate) == 0:
            LOG.info("No flavour resources to be reverted.\n")
            return
        elif type(flavors_to_migrate) is list \
                and len(flavors_to_migrate) > 0:
            LOG.info("Start reverting flavours.\n")
        else:
            LOG.error("Incorrect parameter '{0}'.\n"
                      "Expects: a list of flavor names\n"
                      "Received: '{1}'".format("tenants_to_move",
                                               flavors_to_migrate))
            return

        s_cloud_name = cfg.CONF.SOURCE.os_cloud_name
        t_cloud_name = cfg.CONF.TARGET.os_cloud_name

        for flavor in flavors_to_migrate:
            try:
                s_flavor = self.nv_source.flavors.find(name=flavor)
            except nova_exceptions.NotFound:
                LOG.info("Do not need to revert flavour {0}, "
                         "since it does not exist in cloud {1} "
                         .format(flavor, s_cloud_name))
                return

            values = [flavor, s_flavor.id, s_cloud_name, t_cloud_name]
            flavor_data = flavors.get_migrated_flavor(values)

            if flavor_data is not None:
                if flavor_data["state"] == "completed":
                    try:
                        t_flavor = self.nv_target.flavors.\
                            find(name=flavor_data["dst_flavor_name"])
                        self.nv_target.flavors.delete(t_flavor)
                    except nova_exceptions.NotFound:
                        LOG.info("Do not need to revert flavour {0}, "
                                 "since it has not been migrated successfully"
                                 " to cloud {1}"
                                 .format(flavor_data["dst_flavor_name"],
                                         t_cloud_name))

                # delete record from flyway database
                flavors.delete_migration_record(values)
Exemple #3
0
    def test_delete_migration_record(self):
        db_handler.initialise_flavor_mapping()
        flavor_data = {'src_flavor_name': "name",
                        'src_uuid': "123",
                        'src_cloud': "cloud1",
                        'dst_flavor_name': "d_name",
                        'dst_uuid': "234",
                        'dst_cloud': "cloud2",
                        'state': "unknown"}
        db_handler.record_flavor_migrated([flavor_data])

        values = ["name", "123", "cloud1", "cloud2"]
        db_handler.delete_migration_record(values)

        return_data = db_handler.get_migrated_flavor(values)
        self.assertIs(None, return_data)
Exemple #4
0
    def retrieve_flavor(self, server, s_nova_client, t_nova_client):
        """ function to safely get the corresponding flavor on destination
         cloud of the flavor which has been used by the server instance on
         source cloud

        :param server: server instance to migrate
        :param s_nova_client: nova client of the source cloud
        :param t_nova_client: nova client of the target cloud
        :return: flavor to be used by the server instance on destination
        :raise exceptions.ResourceNotFoundException:
        """

        # find original flavor used on the source cloud
        s_flavor_id = server.flavor['id']
        try:
            s_flavor = s_nova_client.flavors.find(id=s_flavor_id)
        except nova_exceptions.NotFound:
            raise exceptions.ResourceNotFoundException(
                ResourceType.vm, s_flavor_id, self.s_cloud_name)

        # check whether the flavor has been migrated or not
        filter_values = [s_flavor.name, s_flavor.id, self.s_cloud_name,
                         self.t_cloud_name]
        m_flavor = flavors.get_migrated_flavor(filter_values)

        if not m_flavor:
            LOG.info("Flavor '{0}' required by instance [ID: {1}, Name: {2}] "
                     "has been migrated yet, use default solution."
                     .format(s_flavor.name, server.id, server.name))
            try:
                m_flavor = t_nova_client.flavors.find(id=server.flavor['id'])
            except Exception:
                return None

            return m_flavor

        # try to get its corresponding flavor on destination cloud
        dst_flavor_id = m_flavor['dst_uuid']
        try:
            flavor_to_use = t_nova_client.flavors.find(id=dst_flavor_id)
        except nova_exceptions.NotFound:
            LOG.info("Migrated flavor '{0}' does not exist on destination "
                     "cloud '{1}'".format(s_flavor.name, self.t_cloud_name))
            raise exceptions.ResourceNotFoundException(
                ResourceType.vm, s_flavor_id, self.s_cloud_name)

        return flavor_to_use
    def migrate_one_flavor(self, flavor_name):
        try:
            s_flavor = self.nv_source.flavors.find(name=flavor_name)
        except nova_exceptions.NotFound:
            # encapsulate exceptions to make it more understandable
            # to user. Other exception handling mechanism can be added later
            raise exceptions.ResourceNotFoundException(
                ResourceType.flavor, flavor_name,
                cfg.CONF.SOURCE.os_cloud_name)

        s_cloud_name = cfg.CONF.SOURCE.os_cloud_name
        t_cloud_name = cfg.CONF.TARGET.os_cloud_name

        # check whether the tenant has been migrated
        values = [s_flavor, s_flavor.id, s_cloud_name, t_cloud_name]
        m_flavor = flavors.get_migrated_flavor(values)

        if m_flavor is not None and m_flavor['state'] == "completed":
            print("flavor {0} in cloud {1} has already been migrated"
                  .format(m_flavor["src_flavor_name"], s_cloud_name))

        elif m_flavor is None:
            # check for tenant name duplication
            new_flavor_name = s_flavor.name
            try:
                found = True
                while found:
                    found = self.nv_target.flavors.find(name=new_flavor_name)
                    if found:
                        user_input = \
                            raw_input("duplicated flavor '{0}' found on "
                                      "cloud '{1}'\nPlease type in a new "
                                      "name or 'abort':"
                                      .format(found.name, t_cloud_name))
                        if user_input is "abort":
                            # TODO: implement cleaning up and proper exit
                            return None
                        elif user_input:
                            new_flavor_name = user_input

            except nova_exceptions.NotFound:
                # irrelevant exception swallow the exception
                pass

            new_flavor_details = {
                'name': new_flavor_name,
                'ram': s_flavor.ram,
                'vcpus': s_flavor.vcpus,
                'disk': s_flavor.disk,
                'ephemeral': s_flavor.ephemera if s_flavor.ephemeral else 0,
                'swap': s_flavor.swap if s_flavor.swap else 0,
                'rxtx_factor': s_flavor.rxtx_factor,
                'is_public': getattr(s_flavor,
                                     'os-flavor-access:is_public', False)}

            # preparing record for inserting into database
            flavor_migration_data = {'src_flavor_name': s_flavor.name,
                                     'src_uuid': s_flavor.id,
                                     'src_cloud': s_cloud_name,
                                     'dst_flavor_name': new_flavor_name,
                                     'dst_uuid': "NULL",
                                     'dst_cloud': t_cloud_name,
                                     'state': "unknown"}

            # create a new tenant
            try:
                migrated_flavor = self.nv_target.flavors.create(
                    **new_flavor_details)

                flavor_migration_data.update({'dst_uuid': migrated_flavor.id})

            except Exception as e:
            # TODO: not sure what exactly the exception will be thrown
            # TODO: upon creation failure
                print "flavor '{}' migration failure\nDetails:"\
                    .format(s_flavor.name, e.message)
                # update database record
                flavor_migration_data.update({'state': "error"})
                flavors.record_flavor_migrated([flavor_migration_data])
                return

            flavor_migration_data.update({'state': "completed"})
            flavors.record_flavor_migrated([flavor_migration_data])
    def migrate_one_flavor(self, flavor_name):
        try:
            s_flavor = self.nv_source.flavors.find(name=flavor_name)
        except nova_exceptions.NotFound:
            # encapsulate exceptions to make it more understandable
            # to user. Other exception handling mechanism can be added later
            LOG.error(exceptions.ResourceNotFoundException(
                ResourceType.flavor, flavor_name,
                cfg.CONF.SOURCE.os_cloud_name))
            return

        s_cloud_name = cfg.CONF.SOURCE.os_cloud_name
        t_cloud_name = cfg.CONF.TARGET.os_cloud_name

        # check whether the tenant has been migrated
        values = [flavor_name, s_flavor.id, s_cloud_name, t_cloud_name]
        m_flavor = flavors.get_migrated_flavor(values)
        new_flavor_name = flavor_name

        if m_flavor is not None and m_flavor['state'] == "completed":
            LOG.info("flavor {0} in cloud {1} has already been migrated"
                     .format(m_flavor["src_flavor_name"], s_cloud_name))
            return

        elif m_flavor is not None and m_flavor['state'] != "completed":
            LOG.info("Retrying migrating {0} from {1}"
                     .format(flavor_name, s_cloud_name))

        elif m_flavor is None:
            # check for tenant name duplication
            new_flavor_name = s_flavor.name
            try:
                if self.duplicates_handle == "SKIP":
                    found = self.nv_target.flavors.find(name=new_flavor_name)
                    if found:
                        LOG.info("Skipping flavor '{0}' duplicates"
                                 "found on cloud '{1}'"
                                 .format(found.name, t_cloud_name))
                        return

                elif self.duplicates_handle == "AUTO_RENAME":
                    found = True
                    while found:
                        found = self.nv_target.flavors.find(name=new_flavor_name)
                        if found:
                            new_flavor_name += "_migrated"

            except nova_exceptions.NotFound:
                # irrelevant exception swallow the exception
                pass

            # preparing record for inserting into database
            flavor_migration_data = {'src_flavor_name': s_flavor.name,
                                     'src_uuid': s_flavor.id,
                                     'src_cloud': s_cloud_name,
                                     'dst_flavor_name': new_flavor_name,
                                     'dst_uuid': "NULL",
                                     'dst_cloud': t_cloud_name,
                                     'state': "unknown"}
            
            flavors.record_flavor_migrated([flavor_migration_data])

            LOG.info("Start migrating flavour '{}'\n".format(s_flavor.name))

        swap = getattr(s_flavor, 'swap', 0)
        if not swap:
            swap = 0
        else:
            swap = int(swap)

        new_flavor_details = {
            'name': new_flavor_name,
            'ram': s_flavor.ram,
            'vcpus': s_flavor.vcpus,
            'disk': s_flavor.disk,
            'ephemeral': getattr(s_flavor, 'ephemeral', 0),
            'swap': swap,
            'rxtx_factor': s_flavor.rxtx_factor,
            'is_public': getattr(s_flavor,
                                 'os-flavor-access:is_public', False)}

        # create a new tenant
        flavour_data = flavors.get_migrated_flavor(values)
        try:
            migrated_flavor = self.nv_target.flavors.create(
                **new_flavor_details)

            flavour_data.update({'dst_uuid': migrated_flavor.id})

        except Exception as e:
            LOG.error("flavor '{}' migration failure\nDetails:"
                      .format(s_flavor.name, e.args))
            # update database record
            flavour_data.update({'state': "error"})
            flavors.update_migration_record(**flavour_data)
            return

        flavour_data.update({'state': "completed"})
        flavors.update_migration_record(**flavour_data)