diff --git a/ci/clib.py b/ci/clib.py index 8ad5d0aba421e4d65e3030dbc0294f161f4991e1..4d3a31b7c88e3ac8ae61d76f6484ead2668e716c 100644 --- a/ci/clib.py +++ b/ci/clib.py @@ -126,8 +126,8 @@ def migrate_rbd_image(args, server_block_device_mapping): source_server_rbd_images, stderr, ecode = ceph_rbd_image_exists(args, server_block_device_mapping['source']['ceph_pool_name'], server_block_device_mapping['source']['ceph_rbd_image_name']) - log_or_assert(args, "G.1 Source OpenStack VM RBD image exists - query succeeded", ecode == 0, locals()) - log_or_assert(args, "G.1 Source OpenStack VM RBD image exists - single image returned", + log_or_assert(args, "G.01 Source OpenStack VM RBD image exists - query succeeded", ecode == 0, locals()) + log_or_assert(args, "G.01 Source OpenStack VM RBD image exists - single image returned", source_server_rbd_images and len(source_server_rbd_images) == 1, locals()) source_server_rbd_image = source_server_rbd_images[0] @@ -137,8 +137,8 @@ def migrate_rbd_image(args, server_block_device_mapping): destination_server_rbd_images, stderr, ecode = ceph_rbd_image_exists(args, server_block_device_mapping['destination']['ceph_pool_name'], server_block_device_mapping['destination']['volume_id']) - log_or_assert(args, "G.2 Destination OpenStack VM RBD image exists - query succeeded", ecode == 0, locals()) - log_or_assert(args, "G.2 Destination OpenStack VM RBD image exists - single image returned", + log_or_assert(args, "G.02 Destination OpenStack VM RBD image exists - query succeeded", ecode == 0, locals()) + log_or_assert(args, "G.02 Destination OpenStack VM RBD image exists - single image returned", destination_server_rbd_images and len(destination_server_rbd_images) == 1, locals()) destination_server_rbd_image = destination_server_rbd_images[0] @@ -152,7 +152,7 @@ def migrate_rbd_image(args, server_block_device_mapping): source_server_rbd_image, source_rbd_image_snapshot_name) log_or_assert(args, - "G.3 Source OpenStack VM RBD image has non-colliding snapshot " \ + "G.03 Source OpenStack VM RBD image has non-colliding snapshot " \ f"({server_block_device_mapping['source']['ceph_pool_name']}/{source_server_rbd_image}@{source_rbd_image_snapshot_name})", ecode != 0, locals()) @@ -161,7 +161,7 @@ def migrate_rbd_image(args, server_block_device_mapping): source_server_rbd_image, source_rbd_image_snapshot_name) log_or_assert(args, - "G.4 Source OpenStack VM RBD image snapshot created " \ + "G.04 Source OpenStack VM RBD image snapshot created " \ f"({server_block_device_mapping['source']['ceph_pool_name']}/{source_server_rbd_image}@{source_rbd_image_snapshot_name})", ecode == 0, locals()) @@ -171,7 +171,7 @@ def migrate_rbd_image(args, server_block_device_mapping): source_server_rbd_image, source_rbd_image_snapshot_name) log_or_assert(args, - "G.5 Source OpenStack VM RBD image snapshot exists " \ + "G.05 Source OpenStack VM RBD image snapshot exists " \ f"({server_block_device_mapping['source']['ceph_pool_name']}/{source_server_rbd_image}@{source_rbd_image_snapshot_name})", ecode == 0, locals()) @@ -183,13 +183,13 @@ def migrate_rbd_image(args, server_block_device_mapping): server_block_device_mapping['destination']['ceph_pool_name'], destination_server_rbd_image) log_or_assert(args, - f"G.6 Destination OpenStack VM RBD image deletion succeeded ({server_block_device_mapping['destination']['ceph_pool_name']}/{destination_server_rbd_image})", + f"G.06 Destination OpenStack VM RBD image deletion succeeded ({server_block_device_mapping['destination']['ceph_pool_name']}/{destination_server_rbd_image})", ecode == 0, locals()) stdout, stderr, ecode = ceph_rbd_image_exists(args, server_block_device_mapping['destination']['ceph_pool_name'], destination_server_rbd_image) log_or_assert(args, - f"G.7 Destination OpenStack VM RBD image does not exist ({server_block_device_mapping['destination']['ceph_pool_name']}/{destination_server_rbd_image})", + f"G.07 Destination OpenStack VM RBD image does not exist ({server_block_device_mapping['destination']['ceph_pool_name']}/{destination_server_rbd_image})", ecode != 0, locals()) @@ -204,7 +204,7 @@ def migrate_rbd_image(args, server_block_device_mapping): server_block_device_mapping['source']['ceph_pool_name'], source_rbd_cloned_image_name) log_or_assert(args, - "G.8 Source OpenStack VM RBD image cloned succesfully " \ + "G.08 Source OpenStack VM RBD image cloned succesfully " \ f"({server_block_device_mapping['source']['ceph_pool_name']}/{source_server_rbd_image}@{source_rbd_image_snapshot_name} -> " \ f"{server_block_device_mapping['source']['ceph_pool_name']}/{source_rbd_cloned_image_name})", ecode == 0, locals()) @@ -212,7 +212,7 @@ def migrate_rbd_image(args, server_block_device_mapping): server_block_device_mapping['source']['ceph_pool_name'], source_rbd_cloned_image_name) log_or_assert(args, - f"G.9 Source OpenStack VM cloned RBD image exists ({server_block_device_mapping['source']['ceph_pool_name']}/{source_rbd_cloned_image_name})", + f"G.09 Source OpenStack VM cloned RBD image exists ({server_block_device_mapping['source']['ceph_pool_name']}/{source_rbd_cloned_image_name})", ecode == 0, locals()) ## G1: flatten cloned RBD image diff --git a/ci/lib.py b/ci/lib.py index f2ac7fecac29ff5f9bcd4f1dc6aacccb577f4e1c..319d5845a22abf8b7141eb646bf0fdc60adc7d8c 100644 --- a/ci/lib.py +++ b/ci/lib.py @@ -261,26 +261,6 @@ def get_server_floating_ip_port(ostack_connection, server): return None -def get_server_block_device_mapping(args, server_volume_attachment, server_volume, server_root_device_name): - """ return server block device mapping item """ - return {'source': {'block_storage_type': 'openstack-volume-ceph-rbd-image', - 'volume_attachment_id': server_volume_attachment.id, - 'volume_id': server_volume.id, - 'ceph_pool_name': args.source_ceph_cinder_pool_name, - 'ceph_rbd_image_name': server_volume.id}, - 'destination': {'volume_size': server_volume.size, - 'volume_name': get_dst_resource_name(args, server_volume.name), - 'volume_description': server_volume.description, - 'volume_id': None, - 'ceph_pool_name': args.destination_ceph_cinder_pool_name, - 'device_name': os.path.basename(server_volume_attachment.device), - 'volume_bootable': server_root_device_name == server_volume_attachment.device}} - - - - - - def describe_server_network_connection(args, dst_ostack_conn, netaddr_dict): """ create ostack server to network connection via network id or fixed-ip retults in single dictionary fed to conn.compute.create_server(...networks=[ <>, ...]) @@ -305,4 +285,3 @@ def describe_server_network_connection(args, dst_ostack_conn, netaddr_dict): if fixed_port: return {'port': fixed_port.id} return {'uuid': dst_network.id} - diff --git a/ci/olib.py b/ci/olib.py index 89bb2433fc39d38aa7efce8b4eb9047efdf06df6..4d455ee76ded925fe17d09c2f67e6a9c449f9ecd 100644 --- a/ci/olib.py +++ b/ci/olib.py @@ -1,10 +1,13 @@ """ OpenStack migrator - OpenStack library """ import copy +import math +import os.path import xmltodict import openstack +import clib from lib import log_or_assert, get_dst_resource_name, get_dst_resource_desc, remote_cmd_exec, normalize_table_data, trim_dict def get_destination_network(source_network): @@ -348,3 +351,100 @@ def get_or_create_dst_server_security_groups(args, src_ostack_conn, dst_ostack_c "F.12 Destination OpenStack server - destination security groups exists", dst_server_security_groups) return dst_server_security_groups + +def get_server_block_device_mapping(args, server_volume_attachment, server_volume, server_root_device_name): + """ return server block device mapping item """ + return {'source': {'block_storage_type': 'openstack-volume-ceph-rbd-image', + 'volume_attachment_id': server_volume_attachment.id, + 'volume_id': server_volume.id, + 'ceph_pool_name': args.source_ceph_cinder_pool_name, + 'ceph_rbd_image_name': server_volume.id}, + 'destination': {'volume_size': server_volume.size, + 'volume_name': get_dst_resource_name(args, server_volume.name), + 'volume_description': server_volume.description, + 'volume_id': None, + 'ceph_pool_name': args.destination_ceph_cinder_pool_name, + 'device_name': os.path.basename(server_volume_attachment.device), + 'volume_bootable': server_root_device_name == server_volume_attachment.device}} + + +def create_dst_server_block_device_mappings(args, src_ostack_conn, src_server, source_rbd_images): + """ create description how to connect block device to destination VM server """ + server_block_device_mappings = [ ] + # schema: [ {}, ... ] + # where {} is following dict + # { 'source': {'block_storage_type': 'openstack-volume-ceph-rbd-image', 'volume_attachment_id': <>, 'volume_id': <>, + # 'ceph_pool_name': <pool-name>, 'ceph_rbd_image_name': <rbd-image-name>, 'ceph_rbd_image_size': <size-gb>} + # OR + # {'block_storage_type': 'ceph-rbd-image', 'ceph_pool_name': <pool-name>, 'ceph_rbd_image_name': <rbd-image-name>, 'ceph_rbd_image_size': <size-gb> } ] + # 'destination': {'volume_size': <size-gb>, 'volume_id': <vol-id>, 'device_name': <dev-name>, 'volume_bootable': True/False} + # } + + src_server_root_device_name = src_server.root_device_name + log_or_assert(args, + f"F.20 Source OpenStack server - root device name received ({src_server_root_device_name})", + src_server_root_device_name) + + src_server_volume_attachments = tuple(src_ostack_conn.compute.volume_attachments(src_server.id)) + args.logger.debug(f"F.21 Source OpenStack server - volume attachments received {src_server_volume_attachments}") + + src_ceph_ephemeral_rbd_image = None + if src_server_root_device_name in [ i_source_server_attachment.device for i_source_server_attachment in src_server_volume_attachments ]: + args.logger.info("F.22 Source OpenStack server - one of attached volume is attached as the root partition") + + # populate server_block_device_mappings + for i_source_server_volume_attachment in src_server_volume_attachments: + i_server_volume = src_ostack_conn.block_storage.find_volume(i_source_server_volume_attachment.volume_id) + server_block_device_mappings.append(get_server_block_device_mapping(args, i_source_server_volume_attachment, + i_server_volume, src_server_root_device_name)) + else: + args.logger.info("F.22 Source OpenStack server - none of attached volumes is attached as the root partition. Seeking for root partition RBD image") + + src_ceph_ephemeral_rbd_image = f"{src_server.id}_disk" + if src_ceph_ephemeral_rbd_image in source_rbd_images[args.source_ceph_ephemeral_pool_name]: + + args.logger.info(f"F.23 Source OpenStack server - Root partition found as RBD image {args.source_ceph_ephemeral_pool_name}/{src_ceph_ephemeral_rbd_image}") + + # get rbd image info / size + src_ceph_ephemeral_rbd_image_data, _, _ = clib.ceph_rbd_image_info(args, args.source_ceph_ephemeral_pool_name, + src_ceph_ephemeral_rbd_image) + log_or_assert(args, + f"F.24 Source OpenStack ceph RBD image proper information received {src_ceph_ephemeral_rbd_image_data}", + src_ceph_ephemeral_rbd_image_data and 'size' in src_ceph_ephemeral_rbd_image_data) + src_ceph_ephemeral_rbd_image_size = math.ceil(src_ceph_ephemeral_rbd_image_data['size'] / 1024 / 1024 / 1024) + log_or_assert(args, + f"F.25 Source OpenStack ceph RBD image size calculated ({src_ceph_ephemeral_rbd_image_size})", + src_ceph_ephemeral_rbd_image_size) + + # populate server_block_device_mappings + ## initial disk + server_block_device_mappings.append({'source': {'block_storage_type': 'ceph-rbd-image', + 'volume_id': src_ceph_ephemeral_rbd_image, + 'ceph_pool_name': args.source_ceph_ephemeral_pool_name, + 'ceph_rbd_image_name': src_ceph_ephemeral_rbd_image, + 'ceph_rbd_image_size': src_ceph_ephemeral_rbd_image_size}, + 'destination': {'volume_size': src_ceph_ephemeral_rbd_image_size, + 'volume_name': get_dst_resource_name(args, + src_ceph_ephemeral_rbd_image), + 'volume_description': f"migrated (RBD {args.source_ceph_ephemeral_pool_name}/{src_ceph_ephemeral_rbd_image})", + 'volume_id': None, + 'ceph_pool_name': args.destination_ceph_cinder_pool_name, + 'device_name': os.path.basename(src_server_root_device_name), + 'volume_bootable': True}}) + + ## other disks attached to VM + for i_source_server_volume_attachment in src_server_volume_attachments: + i_server_volume = src_ostack_conn.block_storage.find_volume(i_source_server_volume_attachment.volume_id) + server_block_device_mappings.append(get_server_block_device_mapping(args, + i_source_server_volume_attachment, + i_server_volume, + src_server_root_device_name)) + + log_or_assert(args, + "F.26 Source OpenStack server - root partition detected", + server_block_device_mappings and server_block_device_mappings[0] and server_block_device_mappings[0]['source']) + log_or_assert(args, + "F.27 Destination OpenStack server - root partition details generated", + server_block_device_mappings and server_block_device_mappings[0] and server_block_device_mappings[0]['destination']) + + return server_block_device_mappings diff --git a/ci/project-migrator.py b/ci/project-migrator.py index c69ab124c7b3c508db5910511588f3ad54ff107a..b7a300c1bf53c2722a74c45ffe478d4f80f43749 100755 --- a/ci/project-migrator.py +++ b/ci/project-migrator.py @@ -30,9 +30,6 @@ Usage example: import argparse import logging -import math -import os -import os.path import pprint import sys @@ -179,77 +176,10 @@ def main(args): source_project, destination_project, i_source_server_detail) - # volume detection - i_server_block_device_mappings = [ ] - # schema: [ {}, ... ] - # where {} is following dict - # { 'source': {'block_storage_type': 'openstack-volume-ceph-rbd-image', 'volume_attachment_id': <>, 'volume_id': <>, - # 'ceph_pool_name': <pool-name>, 'ceph_rbd_image_name': <rbd-image-name>, 'ceph_rbd_image_size': <size-gb>} - # OR - # {'block_storage_type': 'ceph-rbd-image', 'ceph_pool_name': <pool-name>, 'ceph_rbd_image_name': <rbd-image-name>, 'ceph_rbd_image_size': <size-gb> } ] - # 'destination': {'volume_size': <size-gb>, 'volume_id': <vol-id>, 'device_name': <dev-name>, 'volume_bootable': True/False} - # } - - i_source_server_root_device_name = i_source_server_detail.root_device_name - lib.log_or_assert(args, f"F.20 Source OpenStack server - root device name received ({i_source_server_root_device_name})", - i_source_server_root_device_name) - - i_source_server_volume_attachments = tuple(source_project_conn.compute.volume_attachments(i_source_server_detail.id)) - assert_msg = f"F.21 Source OpenStack server - volume attachments received {i_source_server_volume_attachments}" - #pprint.pprint(i_source_server_volume_attachments) - - i_source_ceph_ephemeral_rbd_image = None - if i_source_server_root_device_name in [ i_source_server_attachment.device for i_source_server_attachment in i_source_server_volume_attachments ]: - args.logger.info("F.22 Source OpenStack server - one of attached volume is attached as the root partition") - - # populate i_server_block_device_mappings - for i_source_server_volume_attachment in i_source_server_volume_attachments: - i_server_volume = source_project_conn.block_storage.find_volume(i_source_server_volume_attachment.volume_id) - i_server_block_device_mappings.append(lib.get_server_block_device_mapping(args, i_source_server_volume_attachment, - i_server_volume, i_source_server_root_device_name)) - else: - args.logger.info("F.22 Source OpenStack server - none of attached volumes is attached as the root partition. Seeking for root partition RBD image") - - if f"{i_source_server_detail.id}_disk" in source_rbd_images[args.source_ceph_ephemeral_pool_name]: - i_source_ceph_ephemeral_rbd_image = f"{i_source_server_detail.id}_disk" - args.logger.info(f"F.23 Source OpenStack server - Root partition found as RBD image {args.source_ceph_ephemeral_pool_name}/{i_source_ceph_ephemeral_rbd_image}") - - # get rbd image info / size - i_source_ceph_ephemeral_rbd_image_data, _, _ = clib.ceph_rbd_image_info(args, args.source_ceph_ephemeral_pool_name, - i_source_ceph_ephemeral_rbd_image) - lib.log_or_assert(args, f"F.24 Source OpenStack ceph RBD image proper information received {i_source_ceph_ephemeral_rbd_image_data}", - i_source_ceph_ephemeral_rbd_image_data and 'size' in i_source_ceph_ephemeral_rbd_image_data) - i_source_ceph_ephemeral_rbd_image_size = math.ceil(i_source_ceph_ephemeral_rbd_image_data['size'] / 1024 / 1024 / 1024) - lib.log_or_assert(args, f"F.25 Source OpenStack ceph RBD image size calculated ({i_source_ceph_ephemeral_rbd_image_size})", - i_source_ceph_ephemeral_rbd_image_size) - - - # populate i_server_block_device_mappings - ## initial disk - i_server_block_device_mappings.append({'source': {'block_storage_type': 'ceph-rbd-image', - 'volume_id': i_source_ceph_ephemeral_rbd_image, - 'ceph_pool_name': args.source_ceph_ephemeral_pool_name, - 'ceph_rbd_image_name': i_source_ceph_ephemeral_rbd_image, - 'ceph_rbd_image_size': i_source_ceph_ephemeral_rbd_image_size}, - 'destination': {'volume_size': i_source_ceph_ephemeral_rbd_image_size, - 'volume_name': lib.get_dst_resource_name(args, i_source_ceph_ephemeral_rbd_image), - 'volume_description': f"RBD {args.source_ceph_ephemeral_pool_name}/{i_source_ceph_ephemeral_rbd_image}", - 'volume_id': None, - 'ceph_pool_name': args.destination_ceph_cinder_pool_name, - 'device_name': os.path.basename(i_source_server_root_device_name), - 'volume_bootable': True}}) - - ## other disks attached to VM - for i_source_server_volume_attachment in i_source_server_volume_attachments: - i_server_volume = source_project_conn.block_storage.find_volume(i_source_server_volume_attachment.volume_id) - i_server_block_device_mappings.append(lib.get_server_block_device_mapping(args, i_source_server_volume_attachment, - i_server_volume, i_source_server_root_device_name)) - - lib.log_or_assert(args, "F.26 Source OpenStack server - root partition detected", - i_server_block_device_mappings and i_server_block_device_mappings[0] and i_server_block_device_mappings[0]['source']) - lib.log_or_assert(args, "F.27 Destination OpenStack server - root partition details generated", - i_server_block_device_mappings and i_server_block_device_mappings[0] and i_server_block_device_mappings[0]['destination']) - + # volume detection, block device mapping creation + i_server_block_device_mappings = \ + olib.create_dst_server_block_device_mappings(args, source_project_conn, + i_source_server_detail, source_rbd_images) # volume creation in destination cloud for i_destination_server_block_device_mapping in i_server_block_device_mappings: