Repository URL to install this package:
|
Version:
5.2.8.8 ▾
|
python3-workloadmgrclient
/
usr
/
lib
/
python3
/
dist-packages
/
workloadmgrclient
/
v1
/
migration_plan.py
|
|---|
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"
def _produce_verbose_output(self, metadata):
metadata.pop('migration_plan_approx_size')
utils.print_dict(metadata, "Metadata")
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= "Specify one or multiple vm-id(s) "
"to include in 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(
"--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"
"\nMust provide vcenter name in the form vcenter_name=<vcenter_name>.",
)
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)
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(
"--add-vmid",
metavar="<vm-id=vi-uuid>",
dest="add_vms",
default="",
help="Specify a vm to include in the migration plan. "
"Specify multiple VMs IDs separated by comma(,) to include multiple vms. "
)
parser.add_argument(
"--remove-vmid",
metavar="<vm-id=vi-uuid>",
dest="rm_vms",
default="",
help="Specify a vm to include in the migration plan. "
"Specify multiple VMs IDs separated by comma(,) to include multiple vms. "
)
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()
migration_plan_obj = utils.find_resource(client, parsed_args.migration_plan_id)
vms = migration_plan_obj.vms
if not vms:
vms = []
# Build a map of id to index for quick access
vm_id_to_index = {item['id']: idx for idx, item in enumerate(vms)}
parsed_add_vms = parsed_args.add_vms
err_msg = (
"Invalid vmid argument '%s'. VM arguments must be of the "
"form vm-id[,vm-id1,vm-id2,..]" % parsed_add_vms
)
try:
parsed_add_vms = set(parsed_add_vms.split(','))
except Exception as ex:
raise exceptions.CommandError(err_msg)
parsed_rm_vms = parsed_args.rm_vms
err_msg = (
"Invalid vmid argument '%s'. VM arguments must be of the "
"form vm-id[,vm-id1,vm-id2,..]" % parsed_rm_vms
)
try:
parsed_rm_vms = set(parsed_rm_vms.split(','))
except Exception as ex:
raise exceptions.CommandError(err_msg)
if parsed_add_vms:
missing_vms_to_add = parsed_add_vms - set(vm_id_to_index)
if parsed_rm_vms:
present_vms_to_rm = parsed_rm_vms & set(vm_id_to_index)
# Collect their indices of the VMs to be removed
present_ids_with_indices = {id_: vm_id_to_index[id_] for id_ in present_vms_to_rm}
# Delete present ones from original list (do this in reverse index order to avoid shifting)
for index in sorted(present_ids_with_indices.values(), reverse=True):
del vms[index]
new_vms = [{'vm-id':vm['id'] for vm in vms}] if vms else []
# Add the missing ones
for missing_id in missing_vms_to_add:
if missing_id:
new_vms.append({'vm-id': missing_id})
# Update metadata
metadata = migration_plan_obj.metadata
restricted_meta = ['vcenter_name', 'backup_media_target']
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:
if k in restricted_meta:
raise exceptions.CommandError("{} is a restricted metadata "
"and can not be updated".format(k))
metadata[k] = v
else:
metadata.setdefault(k, v)
migration_plan_obj.update(
migration_plan_obj.id,
parsed_args.display_name,
parsed_args.display_description,
new_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>",
)
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))
result = client.import_migration_plans(parsed_args.migration_plan_ids)
if len(result["failed_migration_plans"]):
message = (
"\nPlease verify failed migration_plan 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
),
)
class ListvCenters(MigrationPlanCommand, lister.Lister):
"""List all the VCenters configured for migration."""
def take_action(self, parsed_args):
client = self.get_client()
vcenters = client.get_vcenters() or {}
vcenters.pop('vcenters', [])
return (
["Name", "URL", "User", "SSL_Enabled"],
(
osc_utils.get_dict_properties(
detail,
[
"vcenter_name",
"vcenter_url",
"vcenter_username",
"vcenter_ssl",
],
)
for vc, detail in vcenters.items()
),
)