Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
import os
import yaml
import argparse
import uuid
from cliff import show, lister
from osc_lib import exceptions
from osc_lib import utils as osc_utils

from workloadmgrclient import timezone
from workloadmgrclient import utils
from workloadmgrclient.openstack.common import strutils
from workloadmgrclient.v1 import WorkloadmgrCommand

class MigrationPlanCommand(WorkloadmgrCommand):
    resource = "migration_plans"

class ListMigrationPlans(MigrationPlanCommand, lister.Lister):
    """List all the migration_plans of current project."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "--all",
            type=strutils.bool_from_string,
            metavar="{True,False}",
            help="List all migration plans of all the projects (valid for admin user only)",
            default=False,
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        search_opts = {
            "all_migration_plans": parsed_args.all,
        }
        migration_plan_objs = client.list(search_opts=search_opts) or []
        return (
            ["ID", "Name", "Project ID", "Status", "Created At"],
            (
                osc_utils.get_item_properties(
                    obj,
                    [
                        "id",
                        "name",
                        "project_id",
                        "status",
                        "created_at",
                    ],
                )
                for obj in migration_plan_objs
            ),
        )


class ShowMigrationPlan(MigrationPlanCommand, show.ShowOne):
    """Show details about a migration plan."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "migration_plan_id",
            metavar="<migration_plan_id>",
            help="ID of the migration plan."
        )

        parser.add_argument(
            "--scheduler_trust",
            type=bool,
            metavar="<scheduler_trust {true}>",
            help="scheduler_trust."
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        scheduler_trust = False
        # checks for scheduler_trust key and pass it to find_resource if present.
        if parsed_args.scheduler_trust:
            scheduler_trust = {'scheduler_trust': parsed_args.scheduler_trust}
            migration_plan = utils.find_resource(client, parsed_args.migration_plan_id, scheduler_trust)
        else:
            migration_plan = utils.find_resource(client, parsed_args.migration_plan_id)
        info = {}
        info.update(migration_plan._info)
        info.pop("links", None)
        metadata = info.pop("metadata", {})

        for i, val in enumerate(info["vms"]):
            info["vms"][i].pop("metadata", None)

        # TODO: check for better approach here
        if getattr(
            self.app.options,
            "verbose",
            getattr(self.app.options, "verbose_level", None),
        ):
            self._produce_verbose_output(metadata)

        columns = list(info.keys())
        data = osc_utils.get_dict_properties(info, columns)
        return columns, data


class CreateMigrationPlan(MigrationPlanCommand, lister.Lister):
    """Creates a migration plan."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            metavar="<vm-id>",
            nargs="+",
            dest="vmids",
            help="Required to set atleast one VMware VM,"
            " specify a vm-id to include in the migration plan."
            " Specify vm-id multiple times to include multiple VMs.",
        )
        parser.add_argument(
            "--display-name",
            metavar="<display-name>",
            help="Optional migration plan name. (Default=None)",
            default=None,
        )
        parser.add_argument(
            "--display-description",
            metavar="<display-description>",
            help="Optional migration plan description. (Default=None)",
            default=None,
        )
        parser.add_argument(
            "--backup-target-type",
            metavar="<backup-target-type>",
            help="Backup target type id or name. default BTT will be used if not provided",
            default=None,
        )
        parser.add_argument(
            "--source-platform",
            metavar="<source-platform>",
            help="Optional migration plan source platform (Default=vmware)",
            default="vmware",
        )
        parser.add_argument(
            "--metadata",
            metavar="<key=key-name>",
            action="append",
            dest="metadata",
            default=[],
            help="Specify a key value pairs to include in the migration plan metadata. "
                 "Specify option multiple times to include multiple keys. "
                 "key=value",
        )

    def take_action(self, parsed_args):
        client = self.get_client()

        vms = [{"vm-id": vm} for vm in parsed_args.vmids]

        metadata = {}
        for metadata_str in parsed_args.metadata:
            err_msg = (
                "Invalid metadata argument '%s'. metadata arguments must be of the "
                "form --metadata <key=value>" % metadata_str
            )

            for kv_str in metadata_str.split(","):
                try:
                    k, v = kv_str.split("=", 1)
                except ValueError:
                    raise exceptions.CommandError(err_msg)

                if k in metadata:
                    metadata[k] = v
                else:
                    metadata.setdefault(k, v)

        metadata['backup_target_type'] = parsed_args.backup_target_type
        migration_plan_obj = client.create(
            parsed_args.display_name,
            parsed_args.display_description,
            vms,
            metadata,
            parsed_args.source_platform
        )

        if migration_plan_obj:
            return (
                ["ID", "Name", "Status"],
                (
                    osc_utils.get_item_properties(obj, ["id", "name", "status"])
                    for obj in [migration_plan_obj]
                ),
            )
        return


class ModifyMigrationPlan(MigrationPlanCommand):
    """Modify a migration plan."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "migration_plan_id", metavar="<migration_plan_id>", help="ID of the migration_plan."
        )
        parser.add_argument(
            "--display-name",
            metavar="<display-name>",
            help="Optional migration_plan name. (Default=None)",
            default=None,
        )
        parser.add_argument(
            "--display-description",
            metavar="<display-description>",
            help="Optional migration_plan description. (Default=None)",
            default=None,
        )
        parser.add_argument(
            "--vmid",
            metavar="<vm-id=vi-uuid>",
            action="append",
            dest="vms",
            default=[],
            help="Specify a vm to include in the migration plan. "
            "Specify option multiple times to include multiple vms. "
            "vm-id: include the vm with this UUID ",
        )
        parser.add_argument(
            "--metadata",
            metavar="<key=key-name>",
            action="append",
            dest="metadata",
            default=[],
            help="Specify a key value pairs to include in the workload_type metadata "
            "Specify option multiple times to include multiple keys. "
            "key=value",
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        workload_obj = utils.find_resource(client, parsed_args.migration_plan_id)
        vms = []
        for vm_str in parsed_args.vms:
            err_msg = (
                "Invalid vmid argument '%s'. VM arguments must be of the "
                "form --vmid <vm-id=vm-uuid>" % vm_str
            )
            vm = {"vm-id": ""}

            for kv_str in vm_str.split(","):
                try:
                    k, v = kv_str.split("=", 1)
                except ValueError:
                    raise exceptions.CommandError(err_msg)

                if k in vm_info:
                    vm_info[k] = v
                else:
                    raise exceptions.CommandError(err_msg)

            if not vm_info["vm-id"]:
                raise exceptions.CommandError(err_msg)

            instances.append(vm_info)

        metadata = {}
        for metadata_str in parsed_args.metadata:
            err_msg = (
                "Invalid metadata argument '%s'. metadata arguments must be of the "
                "form --metadata <key=value>" % metadata_str
            )

            for kv_str in metadata_str.split(","):
                try:
                    k, v = kv_str.split("=", 1)
                except ValueError:
                    raise exceptions.CommandError(err_msg)

                if k in metadata:
                    metadata[k] = v
                else:
                    metadata.setdefault(k, v)

        migration_plan_obj.update(
            migration_plan_obj.id,
            parsed_args.display_name,
            parsed_args.display_description,
            vms,
            metadata,
        )
        return


class DeleteMigrationPlan(MigrationPlanCommand):
    """Remove a migration plan."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "migration_plan_id", metavar="<migration_plan_id>", help="ID of the migration plan to delete."
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        migration_plan = utils.find_resource(client, parsed_args.migration_plan_id)
        migration_plan.delete()
        return


class ListvCenterVMs(MigrationPlanCommand, lister.Lister):
    """List all the VMs of the vCenter."""

    def take_action(self, parsed_args):
        client = self.get_client()
        vcenter_vms = client.get_vcenter_vms()['vcenter_vms'] or []
        return (
            ["ID", "Name", "Status", "VMware Tools"],
            (
                osc_utils.get_dict_properties(
                    vm,
                    [
                        "vm_id",
                        "vm_name",
                        "power_state",
                        "tools_running",
                    ],
                )
                for vm in vcenter_vms
            ),
        )
class GetvCenterVMs(MigrationPlanCommand):
    """Get vCenter VMs."""

    def take_action(self, parsed_args):
        client = self.get_client()
        migration_plan = utils.find_resource(client, parsed_args.migration_plan_id)
        migration_plan.delete()
        return


class UnlockMigrationPlan(MigrationPlanCommand):
    """unlock a workload."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "migration_plan_id", metavar="<migration_plan_id>", help="ID of the migration plan to reset."
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        migration_plan_obj = utils.find_resource(client, parsed_args.migration_plan_id)
        migration_plan_obj.unlock()


class ImportMigrationPlanList(MigrationPlanCommand, lister.Lister):
    """Get list of migration_plans to be imported."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "--project_id",
            metavar="<project_id>",
            default=None,
            help="List migration_plans belongs to given project only.",
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        migration_plan_objs = client.get_import_migration_plans_list(
            project_id=parsed_args.project_id
        )
        return (
            ["ID", "Name", "Project_ID"],
            (
                osc_utils.get_dict_properties(
                    obj, ["id", "name", "project_id"]
                )
                for obj in migration_plan_objs
            ),
        )


class ImportMigrationPlans(MigrationPlanCommand, lister.Lister):
    """Import all migration plan records from backup store."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "--migration-plan-ids",
            metavar="<migration_plan_ids>",
            nargs="+",
            help="Specify migration_plan ids to import only specified migration_plans"
             " --migration-plan-ids <migration_plan_id1> <migration_plan_id2> ... <migration_plan_id_N>",
        )

        parser.add_argument(
            "--source-btt",
            metavar="<source-btt>",
            nargs="+",
            help="Imports migration plans exists in provided Backup Target Type Id.\nIf used with --migration-plan-ids then given migration_plan ids will be searched in provided --source-btt"
        )

        parser.add_argument(
            "--source-btt-all",
            help="This will search in all Backup Target Types and import all available migration plans.\nif used with --migration-plan-ids then given migration_plan ids will be searched in all available Backup Target Types and same will be imported",
            action="store_true",
        )

        parser.add_argument(
            "--target-btt",
            metavar="<target-btt>",
            default=None,
            help="Backup Target Type Id to which you need to assign migration plans.\nIf not provided then BTT of original BT will be used if exists otherwise Default BTT will be used if not provided."
        )

    def take_action(self, parsed_args):
        client = self.get_client()

        if parsed_args.migration_plan_ids:
            for migration_plan_id in parsed_args.migration_plan_ids:
                try:
                    uuid.UUID(migration_plan_id)
                except ValueError:
                    raise exceptions.CommandError("Invalid --migration-plan-ids: {}".format(migration_plan_id))

        if parsed_args.source_btt:
            for source_btt in parsed_args.source_btt:
                try:
                    uuid.UUID(source_btt)
                except ValueError:
                    raise exceptions.CommandError("Invalid --source-btt: {}".format(source_btt))

        result = client.import_migration_plans(parsed_args.migration_plan_ids, parsed_args.source_btt, parsed_args.source_btt_all, parsed_args.target_btt)
        if len(result["failed_migration_plans"]):
            message = (
                "\nPlease verify if failed migration_plan or source-btt or target-btt id's are valid.\n"
            )
            utils.print_data_vertically([result["failed_migration_plans"]], ["Failed_MigrationPlans"])
            print(message)
            if result['imported_migration_plans']:
                print("Following migration_plans are imported successfully")
        return (
            ["Name", "ID", "ProjectID", "UserID"],
            (
                osc_utils.get_dict_properties(obj, ["name", "id", "project_id", "user_id"])
                for obj in result['imported_migration_plans']
            ),
        )

class DiscoverVMsMigrationPlan(MigrationPlanCommand):
    """discover VM's of a migration plan."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "migration_plan_id", metavar="<migration_plan_id>", help="ID of the migration_plan."
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        result = client.discover_vms(parsed_args.migration_plan_id)
        print('DiscoverVMs has been successfully scheduled for migration plan: {}'.format(parsed_args.migration_plan_id))

class GetMigrationPlanByVmId(MigrationPlanCommand, lister.Lister):
    """List the migration_plan for given vm id"""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "vm_id", metavar="<vm_id>", help="ID of the VM."
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        migration_plan = client.migration_plan_get_by_vmid(parsed_args.vm_id)
        if not migration_plan:
            print('VM ID: {} is not part of any migration plan'.format(parsed_args.vm_id))
        return (
                ["ID", "Name", "Project ID", "Status", "Created At"],
                (
                    osc_utils.get_item_properties(
                        obj,
                        [
                            "id",
                            "name",
                            "project_id",
                            "status",
                            "created_at",
                        ],
                    )
                    for obj in migration_plan
                ),
            )