OpenStack to OpenStack Migration - Project 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 has been created on the newstack, we can proceed to migrate our project. During this process, we will not only migrate the project itself but also map the permissions associated with the project to the newstack belonging to the same users.

For this task, let's create another script named 2_project_migration_user_association.py alongside our previous script. Initially, just like we did for user migration, we will perform the imports in the cloud_connection.py script.

To perform this task, all users with any roles on the project must have been migrated in the previous step. Similarly, if custom roles were added, even though they were not mentioned in the article series, they should also be migrated. The process of migrating roles can be accomplished using the openstacksdk, which provides a convenient way to achieve this.

Let's filter the projects just like we did with user migration.

# --------------------------------------------------------------------------------- #
#   PROJECTS TO / NOT TO MIGRATE
#   If projects_to_migrate is empty, script migrates every project that is not in 
#   projects_to_filter list to destination  
projects_to_migrate = [
]

projects_to_filter = [
    'admin',
    'service'
]
#   PROJECTS TO / NOT TO MIGRATE
# --------------------------------------------------------------------------------- #

Our filtering logic remains the same as in the previous text. Our process will once again iterate through all projects within a loop and apply filtering. The subsequent steps after filtering will proceed as follows:

  1. Retrieve project details from the oldstack.
  2. Create a project on the newstack using these details.
  3. Identify authorizations on the oldstack project and find corresponding user information on the newstack for users with these authorizations. Recreate the same authorizations.
  4. Obtain quotas for the project from the oldstack.
  5. Apply these quotas 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 project in connold.identity.projects():

    project = project.to_dict()
    should_filter = False

    # Check If Project Should NOT Migrate
    if project['name'] in projects_to_filter:
        should_filter = True
    if projects_to_migrate:
        if project['name'] not in projects_to_migrate:
            should_filter = True

    # Continue Loop
    if should_filter:
        continue

    # Print Migrating Project Details
    print("----------------------------------------------------------")
    pp.pprint(project)
    print("----------------------------------------------------------")
    print("PROJECT: ", project['name'], " ID: ", project['id'], " will be migrated..." )
    print("----------------------------------------------------------")

    # [1] # Create New Project Details
    c_project_attrs = {
        "description":      project["description"],
        "is_domain":        project["is_domain"],
        "is_enabled":       project["is_enabled"],
        "name":             project["name"]
    }

    # [2] # Create New Project on Destination OpenStack 
    new_project = connnew.identity.create_project(**c_project_attrs)
    print("-----------------NEW Project DETAILS----------------------")
    pp.pprint(new_project.to_dict())
    print("----------------------------------------------------------")

    # [3] # Find User/Roles of This Project and Assing Corresponding on Destination OpenStack
    for role_assigns in connold.identity.role_assignments():
        role_assigns = role_assigns.to_dict()

        if 'project' in role_assigns['scope']:
            if role_assigns['scope']['project']['id'] == project['id']:

                old_user_id = role_assigns['user']['id']
                old_user = connold.identity.get_user(old_user_id)
                new_user = connold.identity.find_user(old_user.to_dict()['name'] )

                role = connold.identity.get_role(role_assigns['role']['id'])
                new_role = connnew.identity.find_role(role.to_dict()['name'])

                print("-------------------")
                print("Adding role: ", new_role['name'], " to ", "Project: " , new_project['name'], " ID: ", new_project['id'], " for ", new_user['name'])
                connnew.grant_role(new_role['id'],user=new_user['name'],project=new_project['id'],wait=True)
                print("-------------------")

    # [4] # Get Compute Volume and Network Quotas for Project 
    qutoas = connold.get_compute_quotas(project['id'])
    compute_qutoas = qutoas.to_dict()

    qutoas = connold.get_volume_quotas(project['id'])
    volume_qutoas = qutoas.to_dict()

    qutoas = connold.get_network_quotas(project['id'])
    network_qutoas = qutoas.to_dict()

    # Create Compute Volume and Network Quota Details
    c_compute_quotas = {
        "cores":                        compute_qutoas["cores"],
        "injected_file_content_bytes":  compute_qutoas["injected_file_content_bytes"],
        "injected_file_path_bytes":     compute_qutoas["injected_file_path_bytes"],
        "injected_files":               compute_qutoas["injected_files"],
        "instances":                    compute_qutoas["instances"],
        "key_pairs":                    compute_qutoas["key_pairs"],
        "metadata_items":               compute_qutoas["metadata_items"],
        "ram":                          compute_qutoas["ram"],
        "server_group_members":         compute_qutoas["server_group_members"],
        "server_groups":                compute_qutoas["server_groups"]
    }

    c_volume_quotas = {
        "gigabytes":        volume_qutoas["gigabytes"],
        "snapshots":        volume_qutoas["snapshots"],
        "volumes":          volume_qutoas["volumes"]    
    }

    c_network_quotas = {
        "floating_ips":         network_qutoas["floating_ips"],
        "networks":             network_qutoas["networks"],
        "ports":                network_qutoas["ports"],
        "rbac_policies":        network_qutoas["rbac_policies"],
        "routers":              network_qutoas["routers"],
        "security_group_rules": network_qutoas["security_group_rules"],
        "subnets":              network_qutoas["subnets"]
    }

    # [5] # Aplly Quotas to New Project on Destination OpenStack
    connnew.set_compute_quotas(new_project['id'],**c_compute_quotas)
    connnew.set_volume_quotas(new_project['id'],**c_volume_quotas)
    connnew.set_network_quotas(new_project['id'],**c_network_quotas)

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

----------------------------------------------------------
{   'description': 'Deneme Project',
    'domain_id': 'default',
    'id': '5b656fc728104f97a0d6b8c1e0ac8ed2',
    'is_domain': False,
    'is_enabled': True,
    'links': {   'self': 'http://172.16.0.10:5000/v3/projects/5b656fc728104f97a0d6b8c1e0ac8ed2'},
    'location': Munch({'cloud': 'oldstack', 'region_name': 'RegionOne', 'zone': None, 'project': Munch({'id': '7525ce2c81a24e87a202dae3c99f3b56', 'name': 'admin', 'domain_id': None, 'domain_name': 'Default'})}),
    'name': 'deneme_proj',
    'options': {},
    'parent_id': 'default',
    'tags': []}
----------------------------------------------------------
PROJECT:  deneme_proj  ID:  5b656fc728104f97a0d6b8c1e0ac8ed2  will be migrated...
----------------------------------------------------------
-----------------NEW Project DETAILS----------------------
{   'description': 'Deneme Project',
    'domain_id': 'default',
    'id': '28683b546d9b4a2e9943810d71ec99cf',
    'is_domain': False,
    'is_enabled': True,
    'links': {   'self': 'http://172.16.0.11:5000/v3/projects/28683b546d9b4a2e9943810d71ec99cf'},
    'location': Munch({'cloud': 'newstack', 'region_name': 'RegionOne', 'zone': None, 'project': Munch({'id': '0a466901b0e14283af568085d07617ca', 'name': 'admin', 'domain_id': None, 'domain_name': 'Default'})}),
    'name': 'deneme_proj',
    'options': {},
    'parent_id': 'default',
    'tags': []}
----------------------------------------------------------
-------------------
Adding role:  _member_  to  Project:  deneme_proj  ID:  28683b546d9b4a2e9943810d71ec99cf  for  deneme_user
-------------------
-------------------
Adding role:  member  to  Project:  deneme_proj  ID:  28683b546d9b4a2e9943810d71ec99cf  for  deneme_user
-------------------

On the newstack side, a new project has been created with the ID "28683b546d9b4a2e9943810d71ec99cf". Let's perform a quick check through the interface for our quotas, and for our roles, let's use the CLI and grep based on our new project's ID.

quotas

erdem@EWUL:~$ openstack --os-cloud newstack role assignment list | grep 28683b546d9b4a2e9943810d71ec99cf
+----------------------------------+----------------------------------+-------+----------------------------------+----------------------------------+--------+-----------+
| Role                             | User                             | Group | Project                          | Domain                           | System | Inherited |
+----------------------------------+----------------------------------+-------+----------------------------------+----------------------------------+--------+-----------+
| 0e39ed0129d443a9b530c09a5c6c1df9 | 415cbda201ff4f0db64d0ddbfb798b2f |       | 28683b546d9b4a2e9943810d71ec99cf |                                  |        | False     |
| 95906f72054b4b4f82449103830d111a | 415cbda201ff4f0db64d0ddbfb798b2f |       | 28683b546d9b4a2e9943810d71ec99cf |                                  |        | False     |

In our confirmations, we have observed that our project, quotas, and roles have been migrated successfully. We can say that another step has been accomplished.

We have transferred our project along with project-user authorizations. Now, we can proceed to the Flavor Migration phase.

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: John Rodenn Castillo on Unsplash

Previous Next