OpenStack to OpenStack Migration - Flavor Migration


You need to apply this patch manually for the code shared below to work seamlessly, including versions 1.4.0 and 1.5.0 of openstacksdk.

Now that our user and project have been created on the newstack, we can proceed to migrate our flavors. When migrating the flavors, we will not only migrate those that are public but also migrate the ones accesible to specific projects, ensuring that the same access permissions are granted on the newstack.

We have 3 flavors, and one of them (ID:2795e8b0-e93b-49ae-8e98-2aa08f2b3408) is accessible only to the "deneme_proj" project. This means that even the admin project cannot see or use this flavors when creating VMs. Therefore, when listing it, we need to add "--all" to the end of our CLI command.

erdem@EWUL:~$ openstack --os-cloud oldstack flavor list --all
+--------------------------------------+----------------+------+------+-----------+-------+-----------+
| ID                                   | Name           |  RAM | Disk | Ephemeral | VCPUs | Is Public |
+--------------------------------------+----------------+------+------+-----------+-------+-----------+
| 2795e8b0-e93b-49ae-8e98-2aa08f2b3408 | 2CPU_2GB       | 2048 |   10 |         0 |     2 | False     |
| 3244255f-dbde-4406-8125-7b882f1a72c8 | 1CPU_1GB       | 1024 |   10 |         0 |     1 | True      |
| 94dc3438-5f84-43e4-ba54-dc63ef11e1c7 | plain_2CPU_2GB | 2048 |   10 |         0 |     2 | True      |
+--------------------------------------+----------------+------+------+-----------+-------+-----------+

In our "plain_2CPU_2GB" flavor, there are no metadata settings, meaning there are no limits on disk, virtual interfaces, and so on. However, the other two flavors have these types of limits. For example, an flavors with both metadata and accessibility restricted to the "deneme_proj" project appears as follows on the oldstack:

erdem@EWUL:~$ openstack --os-cloud oldstack flavor show 2795e8b0-e93b-49ae-8e98-2aa08f2b3408
| OS-FLV-DISABLED:disabled   | False
| OS-FLV-EXT-DATA:ephemeral  | 0
| access_project_ids         | ['5b656fc728104f97a0d6b8c1e0ac8ed2']
| description                | None
| disk                       | 10
| id                         | 2795e8b0-e93b-49ae-8e98-2aa08f2b3408
| name                       | 2CPU_2GB
| os-flavor-access:is_public | False
| properties                 | quota:disk_read_bytes_sec='20971520',
                               quota:disk_write_bytes_sec='20971520',
                               quota:vif_inbound_burst='12800',
                               quota:vif_inbound_peak='12800',
                               quota:vif_outbound_burst='12800',
                               quota:vif_outbound_peak='12800' 
| ram                        | 2048
| rxtx_factor                | 1.0 
| swap                       | 0   
| vcpus                      | 2   

To migrate flavors, we will create a script named '3_flavor_migration.py,' alongside our previous script, then we will begin by performing the imports in the 'cloud_connection.py' script, just as we did before. This time, our filtering process will be a bit different. We will either migrate all flavors or only those flavors that are listed in the access list of a specific project (non-public flavors).

A flavor can be accessible to multiple projects, which is why it's essential for all projects with any access to the flavor must have been migrated in the previous steps to perform this operation.

# --------------------------------------------------------------------------------- #
#   FLAVORS TO / NOT TO MIGRATE
#   If migrate_flavors_of_projects is empty, script migrates every public and private 
#   flavor. If project ID/IDs (oldstack) given, then only the private flavors 
#   accessible to that IDs are migrated
migrate_flavors_of_projects = [
]
#   FLAVORS TO / NOT TO MIGRATE
# --------------------------------------------------------------------------------- #

After filtering, the steps will proceed as follows:

  1. We will fetch the details of the flavor from the oldstack.
  2. A flavor will be created on the newstack using these details.
  3. If there is any extra metadata associated with the flavor on the oldstack, it will be transferred to the newstack.
  4. If there are access restrictions on the oldstack flavor, they will be implemented on the newstack.

Each part provided in this list is indicated within the code below with its respective number as a comment in the format # [X] #.

for flavor in connold.compute.flavors():

    flavor = flavor.to_dict()
    should_filter = True

    # Check If Flavor Should Migrate 
    if migrate_flavors_of_projects:
        # If migrate_flavors_of_projects is Populated, Flavor Cannot be Public
        if not flavor['is_public']:
            access_list = connold.compute.get_flavor_access(flavor['id'])

            # Check If Flavor Has Access For any migrate_flavors_of_projects IDs
            for m_project in migrate_flavors_of_projects:
                if next((tenant for tenant in access_list if tenant['tenant_id'] == m_project ), False):
                    should_filter = False
                    break
    else:
        should_filter = False

    # Continue Loop
    if should_filter:
        continue

    # [1] # Create New Flavor Details
    c_flavor_attrs = {
        "description":      flavor["description"],
        "disk":             flavor["disk"],
        "ephemeral":        flavor["ephemeral"],
        "is_public":        flavor["is_public"],
        "name":             flavor["name"],
        "ram":              flavor["ram"],
        "rxtx_factor":      flavor["rxtx_factor"],
        "swap":             flavor["swap"],
        "vcpus":            flavor["vcpus"],
    }

    # [2] # Create Flavor W/O Extra Specs
    new_flavor = connnew.compute.create_flavor(**c_flavor_attrs)

    # [3] # If There are Extra Specs Update Those
    if flavor['extra_specs']:
        new_flavor = connnew.compute.create_flavor_extra_specs(new_flavor,flavor['extra_specs'])

    print("-----------------NEW Flavor DETAILS----------------------")
    pp.pprint(new_flavor.to_dict())
    print("---------------------------------------------------------")

    # [4] # Add Access List (If NOT Public)
    if flavor['is_public']:
        continue

    old_access_list = connold.compute.get_flavor_access(flavor['id'])
    for old_access in old_access_list:
        old_project = connold.identity.get_project(old_access['tenant_id'])
        new_project = connnew.identity.find_project(old_project['name'])

        print("-------------------")
        print("Adding Access: ", new_flavor['name'], " to ", "Project: " , new_project['name'])
        new_flavor  = connnew.compute.flavor_add_tenant_access(new_flavor['id'],new_project['id'])
        print("-------------------")

When we run our script, the output is as follows:

-----------------NEW Flavor DETAILS----------------------
{   'description': None,
    'disk': 10,
    'ephemeral': 0,
    'extra_specs': {   'quota:disk_read_bytes_sec': '20971520',
                       'quota:disk_write_bytes_sec': '20971520',
                       'quota:vif_inbound_burst': '12800',
                       'quota:vif_inbound_peak': '12800',
                       'quota:vif_outbound_burst': '12800',
                       'quota:vif_outbound_peak': '12800'},
    'id': '6304930a-f2ad-46be-9dec-64ab02a57b23',
    'is_disabled': False,
    'is_public': False,
    'location': Munch({'cloud': 'newstack', 'region_name': 'RegionOne', 'zone': None, 'project': Munch({'id': '0a466901b0e14283af568085d07617ca', 'name': 'admin', 'domain_id': None, 'domain_name': 'Default'})}),
    'name': '2CPU_2GB',
    'original_name': None,
    'ram': 2048,
    'rxtx_factor': 1.0,
    'swap': 0,
    'vcpus': 2}
---------------------------------------------------------
-------------------
Adding Access:  2CPU_2GB  to  Project:  deneme_proj
-------------------
-----------------NEW Flavor DETAILS----------------------
{   'description': None,
    'disk': 10,
    'ephemeral': 0,
    'extra_specs': {   'quota:disk_read_bytes_sec': '10485760',
                       'quota:disk_write_bytes_sec': '10485760',
                       'quota:vif_inbound_burst': '12800',
                       'quota:vif_inbound_peak': '12800',
                       'quota:vif_outbound_burst': '12800',
                       'quota:vif_outbound_peak': '12800'},
    'id': 'f145026e-f124-4597-af86-f63cc0d27757',
    'is_disabled': False,
    'is_public': True,
    'location': Munch({'cloud': 'newstack', 'region_name': 'RegionOne', 'zone': None, 'project': Munch({'id': '0a466901b0e14283af568085d07617ca', 'name': 'admin', 'domain_id': None, 'domain_name': 'Default'})}),
    'name': '1CPU_1GB',
    'original_name': None,
    'ram': 1024,
    'rxtx_factor': 1.0,
    'swap': 0,
    'vcpus': 1}
---------------------------------------------------------
-----------------NEW Flavor DETAILS----------------------
{   'description': None,
    'disk': 10,
    'ephemeral': 0,
    'extra_specs': {},
    'id': '18528a45-784e-4247-b77a-f07257e25b12',
    'is_disabled': False,
    'is_public': True,
    'location': Munch({'cloud': 'newstack', 'region_name': 'RegionOne', 'zone': None, 'project': Munch({'id': '0a466901b0e14283af568085d07617ca', 'name': 'admin', 'domain_id': None, 'domain_name': 'Default'})}),
    'name': 'plain_2CPU_2GB',
    'original_name': None,
    'ram': 2048,
    'rxtx_factor': 1.0,
    'swap': 0,
    'vcpus': 2}
---------------------------------------------------------

Let's check the newstack using the CLI, and even inspect the flavor that has both metadata and access restrictions.

erdem@EWUL:~$ openstack --os-cloud newstack flavor list --all
+--------------------------------------+----------------+------+------+-----------+-------+-----------+
| ID                                   | Name           |  RAM | Disk | Ephemeral | VCPUs | Is Public |
+--------------------------------------+----------------+------+------+-----------+-------+-----------+
| 18528a45-784e-4247-b77a-f07257e25b12 | plain_2CPU_2GB | 2048 |   10 |         0 |     2 | True      |
| 6304930a-f2ad-46be-9dec-64ab02a57b23 | 2CPU_2GB       | 2048 |   10 |         0 |     2 | False     |
| f145026e-f124-4597-af86-f63cc0d27757 | 1CPU_1GB       | 1024 |   10 |         0 |     1 | True      |
+--------------------------------------+----------------+------+------+-----------+-------+-----------+
erdem@EWUL:~$ openstack --os-cloud newstack flavor show 6304930a-f2ad-46be-9dec-64ab02a57b23
| OS-FLV-DISABLED:disabled   | False
| OS-FLV-EXT-DATA:ephemeral  | 0
| access_project_ids         | ['28683b546d9b4a2e9943810d71ec99cf']
| description                | None
| disk                       | 10
| id                         | 6304930a-f2ad-46be-9dec-64ab02a57b23
| name                       | 2CPU_2GB
| os-flavor-access:is_public | False
| properties                 | quota:disk_read_bytes_sec='20971520',
                               quota:disk_write_bytes_sec='20971520',
                               quota:vif_inbound_burst='12800',
                               quota:vif_inbound_peak='12800',
                               quota:vif_outbound_burst='12800',
                               quota:vif_outbound_peak='12800'
| ram                        | 2048
| rxtx_factor                | 1.0 
| swap                       | 0   
| vcpus                      | 2   

We have listed them using CLI and examined the flavor with access restrictions. All three flavors, their associated metadata, and access restrictions have been successfully migrated. Now that our projects and flavors have been moved, we can proceed to the Security Migration phase and migrate security groups and their rules.

OpenStack to OpenStack Migration:

  1. Article Series
  2. Deployment Info
  3. Preparation
  4. User Migration
  5. Project Migration
  6. Flavor Migration
  7. Security Migration
  8. Network Migration
  9. TBC

References:

Thanks:

Main Photo: Paolo Bendandi on Unsplash

Previous Next