Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion coriolisclient/cli/transfer_executions.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,17 @@ def get_parser(self, prog_name):
help='Shutdown instances before executing the '
'transfer', action='store_true',
default=False)
parser.add_argument('--auto-deploy',
help="Automatically execute deployment after the "
"transfer execution finishes",
action='store_true',
default=False)
return parser

def take_action(self, args):
execution = (
self.app.client_manager.coriolis.transfer_executions.create(
args.transfer, args.shutdown_instances))
args.transfer, args.shutdown_instances, args.auto_deploy))

return TransferExecutionDetailFormatter().get_formatted_entity(
execution)
Expand Down
28 changes: 25 additions & 3 deletions coriolisclient/cli/transfer_schedules.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ class TransferScheduleDetailFormatter(formatter.EntityFormatter):
"last_updated",
"enabled",
"expires",
"shutdown_instance")
"shutdown_instance",
"auto_deploy")

def _get_formatted_data(self, obj):
data = (obj.id,
Expand All @@ -82,7 +83,8 @@ def _get_formatted_data(self, obj):
obj.updated_at,
obj.enabled,
obj.expiration_date,
obj.shutdown_instance)
obj.shutdown_instance,
obj.auto_deploy)
return data


Expand All @@ -104,6 +106,11 @@ def get_parser(self, prog_name):
help='Shutdown instance',
action='store_true',
default=False)
parser.add_argument('--auto-deploy',
help="Auto Deploy transfer after scheduled "
"execution completes.",
action="store_true",
default=False)
return parser

def take_action(self, args):
Expand All @@ -115,7 +122,8 @@ def take_action(self, args):
exp = _parse_expiration_date(args.expires_at)
schedule = self.app.client_manager.coriolis.transfer_schedules.create(
args.transfer, parsed_schedule,
args.disabled is False, exp, args.shutdown_instance)
args.disabled is False, exp, args.shutdown_instance,
args.auto_deploy)
return TransferScheduleDetailFormatter().get_formatted_entity(
schedule)

Expand Down Expand Up @@ -179,6 +187,18 @@ def get_parser(self, prog_name):
help="Don't shutdown instance",
dest="shutdown",
action='store_false')
auto_deploy_parser = parser.add_mutually_exclusive_group(
required=False)
auto_deploy_parser.add_argument(
"--auto-deploy",
help="Auto Deploy transfer after scheduled execution completes.",
dest="auto_deploy",
action="store_true")
auto_deploy_parser.add_argument(
"--dont-auto-deploy",
help="Stops auto deployment when starting scheduled execution",
dest="auto_deploy",
action="store_false")
return parser

def take_action(self, args):
Expand All @@ -198,6 +218,8 @@ def take_action(self, args):
updated_values["shutdown_instance"] = args.shutdown
if args.enabled is not None:
updated_values["enabled"] = args.enabled
if args.auto_deploy is not None:
updated_values['auto_deploy'] = args.auto_deploy

schedule = self.app.client_manager.coriolis.transfer_schedules.update(
args.transfer, args.id, updated_values)
Expand Down
41 changes: 39 additions & 2 deletions coriolisclient/cli/transfers.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,36 @@
from coriolisclient.cli import transfer_executions
from coriolisclient.cli import utils as cli_utils


TRANSFER_SCENARIO_REPLICA = "replica"
TRANSFER_SCENARIO_LIVE_MIGRATION = "live_migration"


def _add_default_deployment_args_to_parser(parser):
cd_group = parser.add_mutually_exclusive_group()
cd_group.add_argument('--clone-disks',
help='Retain the transfer disks by cloning them '
'when launching deployment',
action='store_true', dest="clone_disks",
default=None)
cd_group.add_argument('--dont-clone-disks',
help="Deploy directly on transfer disks, without "
"cloning them.",
action="store_false", dest="clone_disks",
default=None)

osm_group = parser.add_mutually_exclusive_group()
osm_group.add_argument('--os-morphing',
help="Include the OSMorphing process on the "
"deployments of this transfer.",
action="store_false", dest="skip_os_morphing",
default=None)
osm_group.add_argument('--skip-os-morphing',
help='Skip the OS morphing process on the '
'deployments of this transfer',
action='store_true', default=None,
dest="skip_os_morphing")


class TransferFormatter(formatter.EntityFormatter):

columns = ("ID",
Expand Down Expand Up @@ -85,6 +110,8 @@ def __init__(self, show_instances_data=False):
"storage_backend_mappings",
"default_storage_backend",
"user_scripts",
"clone_disks",
"skip_os_morphing",
"executions",
]

Expand Down Expand Up @@ -129,6 +156,8 @@ def _get_formatted_data(self, obj):
cli_utils.format_mapping(backend_mappings),
default_storage,
cli_utils.format_json_for_object_property(obj, 'user_scripts'),
obj.clone_disks,
obj.skip_os_morphing,
self._format_executions(obj.executions)]

if "instances-data" in self.columns:
Expand Down Expand Up @@ -195,6 +224,7 @@ def get_parser(self, prog_name):
include_osmorphing_pool_mappings_arg=True)

cli_utils.add_storage_mappings_arguments_to_parser(parser)
_add_default_deployment_args_to_parser(parser)

return parser

Expand Down Expand Up @@ -233,7 +263,9 @@ def take_action(self, args):
destination_minion_pool_id=args.destination_minion_pool_id,
instance_osmorphing_minion_pool_mappings=(
instance_osmorphing_minion_pool_mappings),
user_scripts=user_scripts)
user_scripts=user_scripts,
clone_disks=args.clone_disks,
skip_os_morphing=args.skip_os_morphing)

return TransferDetailFormatter().get_formatted_entity(transfer)

Expand Down Expand Up @@ -330,6 +362,7 @@ def get_parser(self, prog_name):
parser, include_origin_pool_arg=True,
include_destination_pool_arg=True,
include_osmorphing_pool_mappings_arg=True)
_add_default_deployment_args_to_parser(parser)

return parser

Expand Down Expand Up @@ -372,6 +405,10 @@ def take_action(self, args):
instance_osmorphing_minion_pool_mappings)
if user_scripts:
updated_properties['user_scripts'] = user_scripts
if args.clone_disks is not None:
updated_properties['clone_disks'] = args.clone_disks
if args.skip_os_morphing is not None:
updated_properties['skip_os_morphing'] = args.skip_os_morphing

if not updated_properties:
raise ValueError(
Expand Down
4 changes: 4 additions & 0 deletions coriolisclient/tests/cli/data/shell_create_keystone_auth.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@
os_tenant_id: "mock_os_tenant_id"
kwargs:
auth_url: "mock_auth_url"
password: "mock_password"
expected_kwargs:
auth_url: "mock_auth_url"
project_id: "mock_os_project_id"
password: "mock_password"
api_version: '3'
auth_type: 'other'
auth_fun: 'keystoneauth1.identity.v3.Password'
Expand All @@ -58,9 +60,11 @@
os_tenant_id: "mock_os_tenant_id"
kwargs:
auth_url: "mock_auth_url"
password: "mock_password"
expected_kwargs:
auth_url: "mock_auth_url"
project_id: "mock_os_project_id"
password: "mock_password"
api_version: '3'
auth_type:
auth_fun: 'keystoneauth1.identity.v3.Password'
Expand Down
4 changes: 3 additions & 1 deletion coriolisclient/tests/cli/test_transfer_executions.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ def test_take_action(
args = mock.Mock()
args.transfer = mock.sentinel.transfer
args.shutdown_instances = mock.sentinel.shutdown_instances
args.auto_deploy = mock.sentinel.auto_deploy
mock_execution = mock.Mock()
self.mock_app.client_manager.coriolis.transfer_executions.create = \
mock_execution
Expand All @@ -269,7 +270,8 @@ def test_take_action(
result
)
mock_execution.assert_called_once_with(
mock.sentinel.transfer, mock.sentinel.shutdown_instances)
mock.sentinel.transfer, mock.sentinel.shutdown_instances,
mock.sentinel.auto_deploy)
mock_get_formatted_entity.assert_called_once_with(
mock_execution.return_value)

Expand Down
Loading