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:
- Retrieve project details from the oldstack.
- Create a project on the newstack using these details.
- Identify authorizations on the oldstack project and find corresponding user information on the newstack for users with these authorizations. Recreate the same authorizations.
- Obtain quotas for the project from the oldstack.
- 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.
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:
- Article Series
- Deployment Info
- Preparation
- User Migration
- Project Migration
- Flavor Migration
- Security Migration
- Network Migration
- TBC
References:
- Patch Storyboard
- openstacksdk User Operations
- openstacksdk Project Operations
- openstacksdk Role Operations
- openstacksdk Grant Role
Thanks:
Main Photo: John Rodenn Castillo on Unsplash