diff --git a/blazarclient/tests/v1/shell_commands/test_leases.py b/blazarclient/tests/v1/shell_commands/test_leases.py index a623445..97be1a9 100644 --- a/blazarclient/tests/v1/shell_commands/test_leases.py +++ b/blazarclient/tests/v1/shell_commands/test_leases.py @@ -114,3 +114,62 @@ class CreateLeaseTestCase(tests.TestCase): self.assertRaises(exception.DuplicatedLeaseParameters, self.cl.args2body, args) + + +class UpdateLeaseTestCase(tests.TestCase): + + def setUp(self): + super(UpdateLeaseTestCase, self).setUp() + self.cl = leases.UpdateLease(shell.BlazarShell(), mock.Mock()) + + def test_args2body_time_params(self): + args = argparse.Namespace( + name=None, + prolong_for='1h', + reduce_by=None, + end_date=None, + defer_by=None, + advance_by=None, + start_date=None, + reservation=None + ) + expected = { + 'prolong_for': '1h', + } + + self.assertDictEqual(self.cl.args2body(args), expected) + + def test_args2body_reservation_params(self): + args = argparse.Namespace( + name=None, + prolong_for=None, + reduce_by=None, + end_date=None, + defer_by=None, + advance_by=None, + start_date=None, + reservation=[ + 'id=798379a6-194c-45dc-ba34-1b5171d5552f,' + 'max=3,' + 'hypervisor_properties=' + '["and", [">=", "$vcpus", "4"], ' + '[">=", "$memory_mb", "8192"]],' + 'resource_properties=' + '["==", "$extra_key", "extra_value"]' + ] + ) + expected = { + 'reservations': [ + { + 'id': '798379a6-194c-45dc-ba34-1b5171d5552f', + 'max': 3, + 'hypervisor_properties': + '["and", [">=", "$vcpus", "4"], ' + '[">=", "$memory_mb", "8192"]]', + 'resource_properties': + '["==", "$extra_key", "extra_value"]' + } + ] + } + + self.assertDictEqual(self.cl.args2body(args), expected) diff --git a/blazarclient/v1/leases.py b/blazarclient/v1/leases.py index bae58a6..80b647b 100644 --- a/blazarclient/v1/leases.py +++ b/blazarclient/v1/leases.py @@ -38,7 +38,8 @@ class LeaseClientManager(base.BaseClientManager): return self._get('/leases/%s' % lease_id, 'lease') def update(self, lease_id, name=None, prolong_for=None, reduce_by=None, - end_date=None, advance_by=None, defer_by=None, start_date=None): + end_date=None, advance_by=None, defer_by=None, start_date=None, + reservations=None): """Update attributes of the lease.""" values = {} if name: @@ -72,6 +73,9 @@ class LeaseClientManager(base.BaseClientManager): lease_start_date_change, defer_by is not None) + if reservations: + values['reservations'] = reservations + if not values: return _('No values to update passed.') return self._update('/leases/%s' % lease_id, values, diff --git a/blazarclient/v1/shell_commands/leases.py b/blazarclient/v1/shell_commands/leases.py index fe7346c..c06f2ae 100644 --- a/blazarclient/v1/shell_commands/leases.py +++ b/blazarclient/v1/shell_commands/leases.py @@ -286,6 +286,14 @@ class UpdateLease(command.UpdateCommand): help='New name for the lease', default=None ) + parser.add_argument( + '--reservation', + metavar="", + action='append', + help='Reservation values to update. The reservation must be ' + 'selected with the id= key-value pair.', + default=None) + #prolong-for and reduce_by are mutually exclusive group = parser.add_mutually_exclusive_group() group.add_argument( @@ -343,6 +351,44 @@ class UpdateLease(command.UpdateCommand): params['advance_by'] = parsed_args.advance_by if parsed_args.start_date: params['start_date'] = parsed_args.start_date + if parsed_args.reservation: + keys = [ + # General keys + 'id', + # Keys for host reservation + 'min', 'max', 'hypervisor_properties', 'resource_properties', + # Keys for instance reservation (update of instance reservation + # is NOT yet supported) + ] + params['reservations'] = [] + reservations = [] + for res_str in parsed_args.reservation: + err_msg = ("Invalid reservation argument '%s'. " + "Reservation arguments must be of the form " + "--reservation " % res_str) + res_info = {} + prog = re.compile('^(?:(.*),)?(%s)=(.*)$' % '|'.join(keys)) + + def parse_params(params): + match = prog.search(params) + if match: + k, v = match.group(2, 3) + if strutils.is_int_like(v): + v = int(v) + res_info[k] = v + if match.group(1) is not None: + parse_params(match.group(1)) + + parse_params(res_str) + if res_info: + if 'id' not in res_info: + raise exception.IncorrectLease( + 'The key-value pair id= is ' + 'required for the --reservation argument') + reservations.append(res_info) + if not reservations: + raise exception.IncorrectLease(err_msg) + params['reservations'] = reservations return params