diff --git a/coriolisclient/cli/transfer_executions.py b/coriolisclient/cli/transfer_executions.py index a585f84..0b1e199 100644 --- a/coriolisclient/cli/transfer_executions.py +++ b/coriolisclient/cli/transfer_executions.py @@ -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) diff --git a/coriolisclient/cli/transfer_schedules.py b/coriolisclient/cli/transfer_schedules.py index 90f8a67..c4d758a 100644 --- a/coriolisclient/cli/transfer_schedules.py +++ b/coriolisclient/cli/transfer_schedules.py @@ -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, @@ -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 @@ -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): @@ -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) @@ -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): @@ -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) diff --git a/coriolisclient/cli/transfers.py b/coriolisclient/cli/transfers.py index c8ede4c..37e1bbb 100644 --- a/coriolisclient/cli/transfers.py +++ b/coriolisclient/cli/transfers.py @@ -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", @@ -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", ] @@ -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: @@ -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 @@ -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) @@ -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 @@ -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( diff --git a/coriolisclient/tests/cli/data/shell_create_keystone_auth.yml b/coriolisclient/tests/cli/data/shell_create_keystone_auth.yml index c36fcf3..b5503cf 100644 --- a/coriolisclient/tests/cli/data/shell_create_keystone_auth.yml +++ b/coriolisclient/tests/cli/data/shell_create_keystone_auth.yml @@ -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' @@ -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' diff --git a/coriolisclient/tests/cli/test_transfer_executions.py b/coriolisclient/tests/cli/test_transfer_executions.py index 3366846..1f3dc97 100644 --- a/coriolisclient/tests/cli/test_transfer_executions.py +++ b/coriolisclient/tests/cli/test_transfer_executions.py @@ -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 @@ -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) diff --git a/coriolisclient/tests/cli/test_transfer_schedules.py b/coriolisclient/tests/cli/test_transfer_schedules.py index 25bb2b9..2bf301f 100644 --- a/coriolisclient/tests/cli/test_transfer_schedules.py +++ b/coriolisclient/tests/cli/test_transfer_schedules.py @@ -53,7 +53,8 @@ class TransferScheduleFormatterTestCase(test_base.CoriolisBaseTestCase): def setUp(self): super(TransferScheduleFormatterTestCase, self).setUp() - self.transfer = transfer_schedules.TransferScheduleFormatter() + self.transfer_schedules = ( + transfer_schedules.TransferScheduleFormatter()) def test_get_sorted_list(self): obj1 = mock.Mock() @@ -64,7 +65,7 @@ def test_get_sorted_list(self): obj3.created_at = "date3" obj_list = [obj2, obj1, obj3] - result = self.transfer._get_sorted_list(obj_list) + result = self.transfer_schedules._get_sorted_list(obj_list) self.assertEqual( [obj1, obj2, obj3], @@ -79,7 +80,7 @@ def test_get_formatted_data(self): obj.created_at = mock.sentinel.created_at obj.expiration_date = mock.sentinel.expiration_date - result = self.transfer._get_formatted_data(obj) + result = self.transfer_schedules._get_formatted_data(obj) self.assertEqual( ( @@ -98,7 +99,8 @@ class TransferScheduleDetailFormatterTestCase(test_base.CoriolisBaseTestCase): def setUp(self): super(TransferScheduleDetailFormatterTestCase, self).setUp() - self.transfer = transfer_schedules.TransferScheduleDetailFormatter() + self.transfer_schedules = ( + transfer_schedules.TransferScheduleDetailFormatter()) def test_get_formatted_data(self): obj = mock.Mock() @@ -110,8 +112,9 @@ def test_get_formatted_data(self): obj.enabled = False obj.expiration_date = mock.sentinel.expiration_date obj.shutdown_instance = mock.sentinel.shutdown_instance + obj.auto_deploy = mock.sentinel.auto_deploy - result = self.transfer._get_formatted_data(obj) + result = self.transfer_schedules._get_formatted_data(obj) self.assertEqual( ( @@ -122,7 +125,8 @@ def test_get_formatted_data(self): mock.sentinel.updated_at, False, mock.sentinel.expiration_date, - mock.sentinel.shutdown_instance + mock.sentinel.shutdown_instance, + mock.sentinel.auto_deploy, ), result ) @@ -134,7 +138,7 @@ class CreateTransferScheduleTestCase(test_base.CoriolisBaseTestCase): def setUp(self): self.mock_app = mock.Mock() super(CreateTransferScheduleTestCase, self).setUp() - self.transfer = transfer_schedules.CreateTransferSchedule( + self.transfer_schedules = transfer_schedules.CreateTransferSchedule( self.mock_app, mock.sentinel.app_args) @mock.patch.object(show.ShowOne, 'get_parser') @@ -142,7 +146,7 @@ def test_get_parser( self, mock_get_parser ): - result = self.transfer.get_parser(mock.sentinel.prog_name) + result = self.transfer_schedules.get_parser(mock.sentinel.prog_name) self.assertEqual( mock_get_parser.return_value, @@ -163,14 +167,15 @@ def test_take_action( args = mock.Mock() args.transfer = mock.sentinel.transfer args.disabled = False - args.shutdown_instance = mock.sentinel.shutdown_instance + args.shutdown_instance = False + args.auto_deploy = False mock_schedule_group_args = {"minute": mock.sentinel.minute} mock_parse_schedule_group_args.return_value = mock_schedule_group_args mock_schedule = mock.Mock() self.mock_app.client_manager.coriolis.transfer_schedules.create = \ mock_schedule - result = self.transfer.take_action(args) + result = self.transfer_schedules.take_action(args) self.assertEqual( mock_get_formatted_entity.return_value, @@ -181,7 +186,8 @@ def test_take_action( mock_schedule_group_args, True, mock_parse_expiration_date.return_value, - mock.sentinel.shutdown_instance + False, + False, ) mock_get_formatted_entity.assert_called_once_with( mock_schedule.return_value) @@ -198,7 +204,7 @@ def test_take_action_no_parsed_schedule( self.assertRaises( exceptions.CoriolisException, - self.transfer.take_action, + self.transfer_schedules.take_action, args ) mock_parse_expiration_date.assert_not_called() @@ -210,7 +216,7 @@ class ShowTransferScheduleTestCase(test_base.CoriolisBaseTestCase): def setUp(self): self.mock_app = mock.Mock() super(ShowTransferScheduleTestCase, self).setUp() - self.transfer = transfer_schedules.ShowTransferSchedule( + self.transfer_schedules = transfer_schedules.ShowTransferSchedule( self.mock_app, mock.sentinel.app_args) @mock.patch.object(show.ShowOne, 'get_parser') @@ -218,7 +224,7 @@ def test_get_parser( self, mock_get_parser ): - result = self.transfer.get_parser(mock.sentinel.prog_name) + result = self.transfer_schedules.get_parser(mock.sentinel.prog_name) self.assertEqual( mock_get_parser.return_value, @@ -239,7 +245,7 @@ def test_take_action( self.mock_app.client_manager.coriolis.transfer_schedules.get = \ schedule - result = self.transfer.take_action(args) + result = self.transfer_schedules.take_action(args) self.assertEqual( mock_get_formatted_entity.return_value, @@ -256,7 +262,7 @@ class UpdateTransferScheduleTestCase(test_base.CoriolisBaseTestCase): def setUp(self): self.mock_app = mock.Mock() super(UpdateTransferScheduleTestCase, self).setUp() - self.transfer = transfer_schedules.UpdateTransferSchedule( + self.transfer_schedules = transfer_schedules.UpdateTransferSchedule( self.mock_app, mock.sentinel.app_args) @mock.patch.object(show.ShowOne, 'get_parser') @@ -264,7 +270,7 @@ def test_get_parser( self, mock_get_parser ): - result = self.transfer.get_parser(mock.sentinel.prog_name) + result = self.transfer_schedules.get_parser(mock.sentinel.prog_name) self.assertEqual( mock_get_parser.return_value, @@ -288,6 +294,7 @@ def test_take_action( args.enabled = True args.transfer = mock.sentinel.transfer args.id = mock.sentinel.id + args.auto_deploy = False mock_parse_schedule_group_args.return_value = \ {"minute": mock.sentinel.minute} transfer_schedule = mock.Mock() @@ -298,9 +305,10 @@ def test_take_action( "expiration_date": mock_parse_expiration_date.return_value, "shutdown_instance": True, "enabled": True, + "auto_deploy": False, } - result = self.transfer.take_action(args) + result = self.transfer_schedules.take_action(args) self.assertEqual( mock_get_formatted_entity.return_value, @@ -329,13 +337,14 @@ def test_take_action_no_updated_values( args.expires = False args.shutdown = None args.enabled = None + args.auto_deploy = None mock_parse_schedule_group_args.return_value = {} transfer_schedule = mock.Mock() self.mock_app.client_manager.coriolis.transfer_schedules = \ transfer_schedule expected_updated_values = {"expiration_date": None} - result = self.transfer.take_action(args) + result = self.transfer_schedules.take_action(args) self.assertEqual( mock_get_formatted_entity.return_value, @@ -356,7 +365,7 @@ class DeleteTransferScheduleTestCase(test_base.CoriolisBaseTestCase): def setUp(self): self.mock_app = mock.Mock() super(DeleteTransferScheduleTestCase, self).setUp() - self.transfer = transfer_schedules.DeleteTransferSchedule( + self.transfer_schedules = transfer_schedules.DeleteTransferSchedule( self.mock_app, mock.sentinel.app_args) @mock.patch.object(command.Command, 'get_parser') @@ -364,7 +373,7 @@ def test_get_parser( self, mock_get_parser ): - result = self.transfer.get_parser(mock.sentinel.prog_name) + result = self.transfer_schedules.get_parser(mock.sentinel.prog_name) self.assertEqual( mock_get_parser.return_value, @@ -380,7 +389,7 @@ def test_take_action(self): self.mock_app.client_manager.coriolis.transfer_schedules = \ transfer_schedule - self.transfer.take_action(args) + self.transfer_schedules.take_action(args) transfer_schedule.delete.assert_called_once_with( mock.sentinel.transfer, mock.sentinel.id) @@ -392,7 +401,7 @@ class ListTransferScheduleTestCase(test_base.CoriolisBaseTestCase): def setUp(self): self.mock_app = mock.Mock() super(ListTransferScheduleTestCase, self).setUp() - self.transfer = transfer_schedules.ListTransferSchedule( + self.transfer_schedules = transfer_schedules.ListTransferSchedule( self.mock_app, mock.sentinel.app_args) @mock.patch.object(lister.Lister, 'get_parser') @@ -400,7 +409,7 @@ def test_get_parser( self, mock_get_parser ): - result = self.transfer.get_parser(mock.sentinel.prog_name) + result = self.transfer_schedules.get_parser(mock.sentinel.prog_name) self.assertEqual( mock_get_parser.return_value, @@ -421,7 +430,7 @@ def test_take_action( self.mock_app.client_manager.coriolis.transfer_schedules.list = \ mock_transfer_list - result = self.transfer.take_action(args) + result = self.transfer_schedules.take_action(args) self.assertEqual( mock_list_objects.return_value, diff --git a/coriolisclient/tests/cli/test_transfers.py b/coriolisclient/tests/cli/test_transfers.py index 4e6b8d6..9a49423 100644 --- a/coriolisclient/tests/cli/test_transfers.py +++ b/coriolisclient/tests/cli/test_transfers.py @@ -214,6 +214,8 @@ def test_get_formatted_data( mock.sentinel.formatted_executions mock_obj.info = mock.sentinel.info mock_obj.scenario = mock.sentinel.scenario + mock_obj.clone_disks = mock.sentinel.clone_disks + mock_obj.skip_os_morphing = mock.sentinel.skip_os_morphing expected_result = [ mock.sentinel.id, mock.sentinel.created_at, @@ -234,8 +236,10 @@ def test_get_formatted_data( mock.sentinel.backend_mappings, mock.sentinel.default_storage, mock.sentinel.user_scripts, + mock.sentinel.clone_disks, + mock.sentinel.skip_os_morphing, mock.sentinel.formatted_executions, - mock.sentinel.info + mock.sentinel.info, ] result = self.transfer._get_formatted_data(mock_obj) @@ -293,6 +297,8 @@ def test_take_action( {'instance_id': "instance_id1", 'pool_id': "pool_id1"}, {'instance_id': "instance_id2", 'pool_id': "pool_id2"} ] + args.clone_disks = True + args.skip_os_morphing = False mock_endpoints = mock.Mock() mock_transfers = mock.Mock() self.mock_app.client_manager.coriolis.endpoints = mock_endpoints @@ -330,7 +336,8 @@ def test_take_action( mock.sentinel.destination_minion_pool_id, instance_osmorphing_minion_pool_mappings={ 'instance_id1': 'pool_id1', 'instance_id2': 'pool_id2'}, - user_scripts=mock_compose_user_scripts.return_value + user_scripts=mock_compose_user_scripts.return_value, + clone_disks=True, skip_os_morphing=False, ) mock_get_formatted_entity.assert_called_once_with( mock_transfers.return_value) @@ -520,6 +527,8 @@ def test_take_action( {"instance_id": "mock_instance1", "pool_id": "mock_pool1"}, {"instance_id": "mock_instance2", "pool_id": "mock_pool2"} ] + args.clone_disks = True + args.skip_os_morphing = False mock_transfer = mock.Mock() self.mock_app.client_manager.coriolis.transfers = mock_transfer mock_get_option_value_from_args.side_effect = [ @@ -541,7 +550,9 @@ def test_take_action( mock.sentinel.destination_minion_pool_id, "instance_osmorphing_minion_pool_mappings": {"mock_instance1": "mock_pool1", "mock_instance2": "mock_pool2"}, - "user_scripts": mock.sentinel.user_scripts + "user_scripts": mock.sentinel.user_scripts, + "clone_disks": True, + "skip_os_morphing": False, } result = self.transfer.take_action(args) diff --git a/coriolisclient/tests/v1/test_transfer_executions.py b/coriolisclient/tests/v1/test_transfer_executions.py index 90c2044..ab5a7f0 100644 --- a/coriolisclient/tests/v1/test_transfer_executions.py +++ b/coriolisclient/tests/v1/test_transfer_executions.py @@ -68,13 +68,15 @@ def test_get(self, mock_get): @mock.patch.object(transfer_executions.TransferExecutionManager, "_post") def test_create(self, mock_post): expected_data = { - "shutdown_instances": mock.sentinel.shutdown_instances + "shutdown_instances": mock.sentinel.shutdown_instances, + "auto_deploy": mock.sentinel.auto_deploy, } expected_data = {"execution": expected_data} result = self.transfer_execution.create( mock.sentinel.transfer, - shutdown_instances=mock.sentinel.shutdown_instances + shutdown_instances=mock.sentinel.shutdown_instances, + auto_deploy=mock.sentinel.auto_deploy, ) self.assertEqual( diff --git a/coriolisclient/tests/v1/test_transfer_schedules.py b/coriolisclient/tests/v1/test_transfer_schedules.py index b5dbd7d..4cebaa2 100644 --- a/coriolisclient/tests/v1/test_transfer_schedules.py +++ b/coriolisclient/tests/v1/test_transfer_schedules.py @@ -63,7 +63,8 @@ def test_create(self, mock_post): "schedule": mock.sentinel.schedule, "enabled": True, "expiration_date": '2034-11-26T00:00:00Z', - "shutdown_instance": mock.sentinel.shutdown_instance + "shutdown_instance": mock.sentinel.shutdown_instance, + "auto_deploy": mock.sentinel.auto_deploy, } result = self.transfer_schedule.create( @@ -71,7 +72,8 @@ def test_create(self, mock_post): mock.sentinel.schedule, True, expiration_date, - mock.sentinel.shutdown_instance + mock.sentinel.shutdown_instance, + mock.sentinel.auto_deploy, ) self.assertEqual( diff --git a/coriolisclient/tests/v1/test_transfers.py b/coriolisclient/tests/v1/test_transfers.py index 9d76646..7966dc3 100644 --- a/coriolisclient/tests/v1/test_transfers.py +++ b/coriolisclient/tests/v1/test_transfers.py @@ -129,6 +129,8 @@ def test_create(self, mock_post): mock.sentinel.destination_minion_pool_id, "instance_osmorphing_minion_pool_mappings": mock.sentinel.instance_osmorphing_minion_pool_mappings, + "clone_disks": True, + "skip_os_morphing": False, } expected_data = {"transfer": expected_data} @@ -151,6 +153,8 @@ def test_create(self, mock_post): mock.sentinel.destination_minion_pool_id, instance_osmorphing_minion_pool_mappings= mock.sentinel.instance_osmorphing_minion_pool_mappings, + clone_disks=True, + skip_os_morphing=False, ) self.assertEqual( diff --git a/coriolisclient/v1/transfer_executions.py b/coriolisclient/v1/transfer_executions.py index 731fc38..0552aae 100644 --- a/coriolisclient/v1/transfer_executions.py +++ b/coriolisclient/v1/transfer_executions.py @@ -45,8 +45,10 @@ def get(self, transfer, execution): "execution_id": base.getid(execution)}, 'execution') - def create(self, transfer, shutdown_instances=False): - data = {"execution": {"shutdown_instances": shutdown_instances}} + def create(self, transfer, shutdown_instances=False, auto_deploy=False): + data = {"execution": { + "shutdown_instances": shutdown_instances, + "auto_deploy": auto_deploy}} return self._post( '/transfers/%s/executions' % base.getid(transfer), data, 'execution') diff --git a/coriolisclient/v1/transfer_schedules.py b/coriolisclient/v1/transfer_schedules.py index c02e785..0dca527 100644 --- a/coriolisclient/v1/transfer_schedules.py +++ b/coriolisclient/v1/transfer_schedules.py @@ -45,11 +45,12 @@ def get(self, transfer, schedule): 'schedule') def create(self, transfer, schedule, enabled, expiration_date, - shutdown_instance): + shutdown_instance, auto_deploy): data = { "schedule": schedule, "enabled": enabled, "shutdown_instance": shutdown_instance, + "auto_deploy": auto_deploy, } if expiration_date: data["expiration_date"] = self._format_rfc3339_datetime( diff --git a/coriolisclient/v1/transfers.py b/coriolisclient/v1/transfers.py index ebba87d..d4559d5 100644 --- a/coriolisclient/v1/transfers.py +++ b/coriolisclient/v1/transfers.py @@ -62,7 +62,7 @@ def create(self, origin_endpoint_id, destination_endpoint_id, network_map=None, notes=None, storage_mappings=None, origin_minion_pool_id=None, destination_minion_pool_id=None, instance_osmorphing_minion_pool_mappings=None, - user_scripts=None): + user_scripts=None, clone_disks=True, skip_os_morphing=False): if not network_map: network_map = destination_environment.get('network_map', {}) if not storage_mappings: @@ -79,6 +79,8 @@ def create(self, origin_endpoint_id, destination_endpoint_id, "notes": notes, "storage_mappings": storage_mappings, "user_scripts": user_scripts, + "clone_disks": clone_disks, + "skip_os_morphing": skip_os_morphing, } } if source_environment: diff --git a/tox.ini b/tox.ini index 63e5067..82ae014 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 4.0.2 -envlist = py3,pep8 +envlist = py3,pep8,cover skipsdist = True [testenv] @@ -21,7 +21,7 @@ setenv = commands = stestr run --no-subunit-trace {posargs} coverage combine - coverage report --skip-covered + coverage report --fail-under=82 --skip-covered coverage html -d cover coverage xml -o cover/coverage.xml