logo
关于我们

技术分享

技术分享 openstack虚拟机迁移到ovirt环境脚本实现

openstack虚拟机迁移到ovirt环境脚本实现

2021-06-06

1、需求背景:

旧平台openstack虚拟机需要迁移到ovirt-engine环境,直接用ovirt自带的对接openstack环境一直cinder鉴权报错,调查是版本不支持,只能手动备份导入的ovirt平台。

思路:获取openstack环境虚拟机信息,读取迁移虚拟机表格,导出虚拟机为qcow2,上传到ovirt平台创建虚拟机挂盘。

2、获取openstack计算节点虚拟机信息

通过virsh list获取instance实例列表,再通过dumpxml获取虚拟机信息利用xml模块解析所需要的信息

    def get_vms_list(self):
        # print("virsh list --all --name ...")
        list_cmd = "virsh list --all --name".split(" ")
        stdout, stderr = self.cmd_process(list_cmd)
        instance_names = list(filter(None, stdout.split("\n")))
        return instance_names

    def get_dumpxml_info(self, instance_name):
        # print("virsh dumpxml...")
        info_cmd = "virsh dumpxml %s" % instance_name
        stdout, _ = self.cmd_process(info_cmd.split(" "))
        return stdout

    def get_vms_info(self):
        instance_names = self.get_vms_list()
        vms_info = []
        for instance_name in instance_names:
            xml_str = self.get_dumpxml_info(instance_name)
            DOMTree = xml.dom.minidom.parseString(xml_str)
            collection = DOMTree.documentElement
            vm_info = {}
            data_volume = []
            vm_info["instance_name"] = collection.getElementsByTagName("name")[0].childNodes[0].data
            vm_info["vm_name"] = collection.getElementsByTagName("metadata")[0].getElementsByTagName("nova:instance")[
                0].getElementsByTagName("nova:name")[0].childNodes[0].data
            vm_info["vm_flavor"] = collection.getElementsByTagName("metadata")[0].getElementsByTagName("nova:instance")[
                    0].getElementsByTagName("nova:flavor")[0].getAttribute("name")
            vm_info["instance_uuid"] = collection.getElementsByTagName("uuid")[0].childNodes[0].data
            vm_info["instance_vcpu"] = collection.getElementsByTagName("vcpu")[0].childNodes[0].data
            vm_info["instance_memory"] = collection.getElementsByTagName("memory")[0].childNodes[0].data
            for disk_info in collection.getElementsByTagName("devices")[0].getElementsByTagName("disk"):
                dev = disk_info.getElementsByTagName("target")[0].getAttribute("dev")
                if dev == "vda" or dev == "hda":
                    vm_info["system_volume"] = disk_info.getElementsByTagName("source")[0].getAttribute("name")
                else:
                    data_volume.append(disk_info.getElementsByTagName("source")[0].getAttribute("name"))
            vm_info["data_volume"] = data_volume
            vms_info.append(vm_info)
        return vms_info

计算节点都要执行,最后汇总到执行脚本的节点,并且汇总读取信息(注意系统卷和数据卷的判断根据具体环境修改适配)

    run_first_time = False
    if run_first_time:
        for host in HOST_LIST:
            print("** get the vm info from %s" % host)
            os.system("scp get_vm_info.py root@%s:/home" % host)
            sshclient_execmd(host, "python /home/get_vm_info.py > /home/%s_vm_info.txt" % host)
            time.sleep(1)
            sshclient_execmd(host, "scp  /home/%s_vm_info.txt root@cmp014:/home/test/info" % host)
            time.sleep(1)
    print("** update vm info successful")

    print("** read the info file")
    info_path = "/home/test/info"
    files = os.listdir(info_path)
    for file_name in files:
        print("** read the file : %s" % file_name)
        with open(info_path + "/" + file_name) as f:
            content = f.read()
        all_vms_info.extend(ast.literal_eval(content))

 

3、获取卷信息后转换格式

    def rbd_export(self, volume_path, volume_name):
        rbd_cmd_str = "rbd export %s %s.qcow2" % (volume_path, volume_name)
        self.cmd_process(rbd_cmd_str.split(" "))
        print ("**%s exported %s successfully." % (volume_path, volume_name))

    def img_covert(self, qcow2_path, qcow2_name):
        img_covert_str = "qemu-img convert -O qcow2 %s %s" % (qcow2_path + ".qcow2", qcow2_name + ".qcow2")
        self.cmd_process(img_covert_str.split(" "))
        print ("**%s coverted successfully." % qcow2_name)
        os.remove(qcow2_path + ".qcow2")
        print ("**remove tmp file:%s" % (qcow2_path + ".qcow2"))

    def clean_disks(self, qcow2_name):
        if os.path.exists(qcow2_name + ".qcow2"):
            os.remove(qcow2_name + ".qcow2")
            print ("** remove disk %s" % qcow2_name)

4、虚拟机disk转换之后利用ovirt sdk的方法上传系统盘和数据盘,创建虚拟机将盘挂载在虚拟机上,添加网卡,等等

    def upload_disk(self):
        print ("--Step01:upload disk....")
        for volume_path in self.volumes_list:
            # Get image info using qemu-img
            image_info = self.get_image_info(volume_path)
            new_disk_format = self.get_disk_format(image_info)

            print("**Uploaded image format: %s" % image_info["format"])
            print("**Disk content type: %s" % image_info["content_type"])
            print("**Disk format: %s" % new_disk_format)
            print("**Transfer format: %s" % image_info["transfer_format"])

            # This example will connect to the server and create a new `floating`
            # disk, one that isn't attached to any virtual machine.
            # Then using transfer service it will transfer disk data from local
            # qcow2 disk to the newly created disk in server.
            print("**Creating disk...")
            image_size = os.path.getsize(volume_path)
            disks_service = self.system_service.disks_service()
            disk = disks_service.add(
                disk=types.Disk(
                    name=os.path.basename(volume_path[:-6]),
                    content_type=image_info["content_type"],
                    description='Uploaded disk',
                    format=new_disk_format,
                    initial_size=image_size,
                    provisioned_size=image_info["virtual-size"],
                    sparse=new_disk_format == types.DiskFormat.COW,
                    storage_domains=[
                        types.StorageDomain(
                            name=self.args.sd_name
                        )
                    ]
                )
            )

            # Wait till the disk is up, as the transfer can't start if the
            # disk is locked:
            disk_service = disks_service.disk_service(disk.id)
            while True:
                time.sleep(5)
                disk = disk_service.get()
                if disk.status == types.DiskStatus.OK:
                    break

            print("**Creating transfer session...")

            # Get a reference to the service that manages the image
            # transfer that was added in the previous step:
            transfers_service = self.system_service .image_transfers_service()

            # Add a new image transfer:
            transfer = transfers_service.add(
                types.ImageTransfer(
                    image=types.Image(
                        id=disk.id
                    ),
                    # 'format' can be used only for ovirt-engine 4.3 or above
                    format=image_info["transfer_format"],
                )
            )

            # Get reference to the created transfer service:
            transfer_service = transfers_service.image_transfer_service(transfer.id)

            # After adding a new transfer for the disk, the transfer's status will be INITIALIZING.
            # Wait until the init phase is over. The actual transfer can start when its status is "Transferring".
            while transfer.phase == types.ImageTransferPhase.INITIALIZING:
                time.sleep(1)
                transfer = transfer_service.get()

            print("**Uploading image...")

            # At this stage, the SDK granted the permission to start transferring the disk, and the
            # user should choose its preferred tool for doing it - regardless of the SDK.
            # In this example, we will use Python's httplib.HTTPSConnection for transferring the data.
            if args.direct:
                if transfer.transfer_url is not None:
                    destination_url = transfer.transfer_url
                else:
                    print("**Direct upload to host not supported (requires ovirt-engine 4.2 or above).")
                    sys.exit(1)
            else:
                destination_url = transfer.proxy_url

            with ui.ProgressBar(image_size) as pb:
                client.upload(
                    volume_path,
                    destination_url,
                    self.args.cafile,
                    secure=self.args.secure,
                    progress=pb.update)

            print("**Finalizing transfer session...")
            # Successful cleanup
            transfer_service.finalize()
            print("**Upload %s completed successfully" % volume_path)

    def attach_disk(self, disk_attachments_service, disk_name, vm_name, bootable=True):
        disks_service = self.system_service.disks_service()
        while True:
            time.sleep(5)
            my_disk = disks_service.list(search='name=%s' % disk_name)[0]
            if my_disk.status == types.DiskStatus.OK:
                print ("**DiskStatus is ok")
                break
        disk_attachment = disk_attachments_service.add(
            types.DiskAttachment(
                disk=my_disk,
                interface=types.DiskInterface.VIRTIO,
                bootable=bootable,
                active=True,
            ),
        )
        # Wait until the disk status is OK:
        disk_service = disks_service.disk_service(disk_attachment.disk.id)
        while True:
            time.sleep(5)
            disk = disk_service.get()
            if disk.status == types.DiskStatus.OK:
                print("**Disk '%s' added to '%s'." % (disk.name, vm_name))
                break

    def attach_nics(self, vm_name):
        vms_service = self.system_service.vms_service()
        vm = vms_service.list(search='name=%s' % vm_name)[0]
        cluster = self.system_service.clusters_service().cluster_service(vm.cluster.id).get()
        dcs_service = self.system_service.data_centers_service()
        dc = dcs_service.list(search='Clusters.name=%s' % cluster.name)[0]
        networks_service = dcs_service.service(dc.id).networks_service()
        network = next(
            (n for n in networks_service.list()
             if n.name == 'Ext-Net'),
            None
        )
        profiles_service = self.system_service.vnic_profiles_service()
        profile_id = None
        nic_name = random.choice(NIC_LIST)
        for profile in profiles_service.list():
            if profile.name == nic_name:
                print ("**add nic : %s" % profile.name)
                profile_id = profile.id
                break

        # Locate the service that manages the network interface cards of the
        # virtual machine:
        nics_service = vms_service.vm_service(vm.id).nics_service()

        # Use the "add" method of the network interface cards service to add the
        # new network interface card:
        nics_service.add(
            types.Nic(
                name='mynic',
                description='My network interface card',
                vnic_profile=types.VnicProfile(
                    id=profile_id,
                ),
            ),
        )
        print("**Nic added successfully")

    def assign_permission(self, permissions_service, user, group):
        if user:
            print("**assign user permission.")
            permissions_service.add(
                types.Permission(
                    user=types.User(
                        id=user.id,
                    ),
                    role=types.Role(
                        name=USER_ROLENAME,
                    ),
                ),
            )
        else:
            print ("**user is none, pass the user assign permission")
        if group:
            print ("**assign group permission.")
            permissions_service.add(
                types.Permission(
                    group=types.Group(
                        id=group.id,
                    ),
                    role=types.Role(
                        name=GROUP_ROLENAME,
                    ),
                ),
            )
        else:
            print ("**group is none, pass the user assign permission")

    def create_vm(self):
        print ("--Step02:begin create vm")
        vms_service = self.system_service.vms_service()
        users_service = connection.system_service().users_service()
        groups_service = connection.system_service().groups_service()
        try:
            user = users_service.list(search='usrname=%s' % op.user_name)[0]
        except:
            user = None
        try:
            group = groups_service.list(search='name=%s' % op.group_name)[0]
        except:
            group = None
        vm = vms_service.add(
            types.Vm(
                name=op.vm_name,
                description='migrate from openstack',
                comment=group.name if group else None,
                cluster=types.Cluster(
                    name='Default',
                ),
                cpu=types.Cpu(
                    topology=types.CpuTopology(
                        cores=1,
                        sockets=int(self.vm_info.get("instance_vcpu")),
                        threads=1
                    )
                ),
                template=types.Template(
                    name='Blank',
                ),
                high_availability=types.HighAvailability(
                    enabled=True,
                    priority=1
                ),
                memory=int(self.vm_info.get("instance_memory"))*1024,
            ),
        )
        # Find the service that manages the virtual machine:
        vm_service = vms_service.vm_service(vm.id)

        # Wait till the virtual machine is down, which means that it is
        # completely created:
        while True:
            time.sleep(5)
            vm = vm_service.get()
            if vm.status == types.VmStatus.DOWN:
                print("**The vm %s is created successfully." % self.vm_info.get("vm_name"))
                break
        print ("--Step03:begin to attach disk.")
        disk_attachments_service = vm_service.disk_attachments_service()
        for volume_path in self.volumes_list:
            print ("**begin to attach disk: %s" % volume_path)
            self.attach_disk(disk_attachments_service, str(volume_path[:-6]), vm.name, bootable=("system" in volume_path))
        print ("--Step04:begin to attach nic.")
        self.attach_nics(vm.name)
        print ("--Step05:assign permission to vms.")
        permissions_service = vm_service.permissions_service()
        self.assign_permission(permissions_service, user, group)

5、执行结果

openstack虚拟机迁移到ovirt环境脚本实现

云祺备份软件,云祺容灾备份系统,虚拟机备份,数据库备份,文件备份,实时备份,勒索软件,美国,图书馆
  • 标签:
  • 其他

您可能感兴趣的新闻 换一批

现在下载,可享30天免费试用

立即下载