def validate(value): # NOTE(sbauza): cpu_info can be very different from one Nova driver to # another. We need to keep this method as generic as # possible, ie. we accept JSONified dict. try: cpu_info = jsonutils.loads(value) except TypeError: raise exceptions.InvalidInput(cls=CPUInfo.name, value=value) if not isinstance(cpu_info, dict): raise exceptions.InvalidInput(cls=CPUInfo.name, value=value) return value
def validate(value): # NOTE(sbauza): We need to accept non-unicoded Python2 strings if (isinstance(value, six.text_type) or isinstance(value, str) or isinstance(value, int)): return value else: raise exceptions.InvalidInput(cls=TextOrInteger.name, value=value)
def _check_for_invalid_date_inputs(self, lease, values, now): if (lease['start_date'] < now and values['start_date'] != lease['start_date']): raise common_ex.InvalidInput( 'Cannot modify the start date of already started leases') if (lease['start_date'] > now and values['start_date'] < now): raise common_ex.InvalidInput( 'Start date must be later than current date') if lease['end_date'] < now: raise common_ex.InvalidInput( 'Terminated leases can only be renamed') if (values['end_date'] < now or values['end_date'] < values['start_date']): raise common_ex.InvalidInput( 'End date must be later than current and start date')
def validate(self, value): try: datetime.datetime.strptime(value, self.format) except ValueError: # FIXME(sbauza): Start_date and end_date are given using a specific # format but are shown in default ISO8601, we must # fail back to it for verification try: wutils.parse_isodatetime(value) except ValueError: raise exceptions.InvalidInput(cls=Datetime.name, value=value) return value
def update_lease(self, lease_id, values): if not values: return db_api.lease_get(lease_id) if len(values) == 1 and 'name' in values: db_api.lease_update(lease_id, values) return db_api.lease_get(lease_id) lease = db_api.lease_get(lease_id) start_date = values.get( 'start_date', datetime.datetime.strftime(lease['start_date'], LEASE_DATE_FORMAT)) end_date = values.get( 'end_date', datetime.datetime.strftime(lease['end_date'], LEASE_DATE_FORMAT)) before_end_date = values.get('before_end_date', None) start_date, end_date, now = self._parse_lease_dates(start_date, end_date) values['start_date'] = start_date values['end_date'] = end_date self._check_for_invalid_date_inputs(lease, values, now) with trusts.create_ctx_from_trust(lease['trust_id']): if before_end_date: try: before_end_date = self._date_from_string(before_end_date) self._check_date_within_lease_limits(before_end_date, values) except common_ex.BlazarException as e: LOG.error("Invalid before_end_date param. %s", str(e)) raise e reservations = values.get('reservations', []) existing_reservations = ( db_api.reservation_get_all_by_lease_id(lease_id)) try: invalid_ids = set([r['id'] for r in reservations]).difference( [r['id'] for r in existing_reservations]) except KeyError: raise exceptions.MissingParameter(param='reservation ID') if invalid_ids: raise common_ex.InvalidInput( 'Please enter valid reservation IDs. Invalid reservation ' 'IDs are: %s' % ','.join([str(id) for id in invalid_ids])) try: [ self.plugins[r['resource_type']] for r in (reservations + existing_reservations)] except KeyError: raise exceptions.CantUpdateParameter(param='resource_type') existing_allocs = self._existing_allocations(existing_reservations) if reservations: new_reservations = reservations new_allocs = self._allocation_candidates(values, existing_reservations) else: # User is not updating reservation parameters, e.g., is only # adjusting lease start/end dates. new_reservations = existing_reservations new_allocs = existing_allocs try: self.enforcement.check_update(context.current(), lease, values, existing_allocs, new_allocs, existing_reservations, new_reservations) except common_ex.NotAuthorized as e: LOG.error("Enforcement checks failed. %s", str(e)) raise common_ex.NotAuthorized(e) # TODO(frossigneux) rollback if an exception is raised for reservation in existing_reservations: v = {} v['start_date'] = values['start_date'] v['end_date'] = values['end_date'] try: v.update([r for r in reservations if r['id'] == reservation['id']].pop()) except IndexError: pass resource_type = v.get('resource_type', reservation['resource_type']) if resource_type != reservation['resource_type']: raise exceptions.CantUpdateParameter( param='resource_type') self.plugins[resource_type].update_reservation( reservation['id'], v) event = db_api.event_get_first_sorted_by_filters( 'lease_id', 'asc', { 'lease_id': lease_id, 'event_type': 'start_lease' } ) if not event: raise common_ex.BlazarException( 'Start lease event not found') db_api.event_update(event['id'], {'time': values['start_date']}) event = db_api.event_get_first_sorted_by_filters( 'lease_id', 'asc', { 'lease_id': lease_id, 'event_type': 'end_lease' } ) if not event: raise common_ex.BlazarException( 'End lease event not found') db_api.event_update(event['id'], {'time': values['end_date']}) notifications = ['update'] self._update_before_end_event(lease, values, notifications, before_end_date) try: del values['reservations'] except KeyError: pass db_api.lease_update(lease_id, values) lease = db_api.lease_get(lease_id) with trusts.create_ctx_from_trust(lease['trust_id']) as ctx: self._send_notification(lease, ctx, events=notifications) return lease
def create_lease(self, lease_values): """Create a lease with reservations. Return either the model of created lease or None if any error. """ lease_values['status'] = status.lease.CREATING try: trust_id = lease_values.pop('trust_id') except KeyError: raise exceptions.MissingTrustId() self.validate_params(lease_values, ['name', 'start_date', 'end_date']) # Remove and keep event and reservation values events = lease_values.pop("events", []) reservations = lease_values.pop("reservations", []) for res in reservations: self.validate_params(res, ['resource_type']) # Create the lease without the reservations start_date, end_date, now = self._parse_lease_dates( lease_values['start_date'], lease_values['end_date']) if start_date < now: raise common_ex.InvalidInput( 'Start date must be later than current date') if end_date <= start_date: raise common_ex.InvalidInput( 'End date must be later than start date.') with trusts.create_ctx_from_trust(trust_id) as ctx: # NOTE(priteau): We should not get user_id from ctx, because we are # in the context of the trustee (blazar user). # lease_values['user_id'] is set in blazar/api/v1/service.py lease_values['project_id'] = ctx.project_id lease_values['start_date'] = start_date lease_values['end_date'] = end_date allocations = self._allocation_candidates( lease_values, reservations) try: self.enforcement.check_create( context.current(), lease_values, reservations, allocations) except common_ex.NotAuthorized as e: LOG.error("Enforcement checks failed. %s", str(e)) raise common_ex.NotAuthorized(e) events.append({'event_type': 'start_lease', 'time': start_date, 'status': status.event.UNDONE}) events.append({'event_type': 'end_lease', 'time': end_date, 'status': status.event.UNDONE}) before_end_date = lease_values.get('before_end_date', None) if before_end_date: # incoming param. Validation check try: before_end_date = self._date_from_string( before_end_date) self._check_date_within_lease_limits(before_end_date, lease_values) except common_ex.BlazarException as e: LOG.error("Invalid before_end_date param. %s", str(e)) raise e elif CONF.manager.minutes_before_end_lease > 0: delta = datetime.timedelta( minutes=CONF.manager.minutes_before_end_lease) before_end_date = lease_values['end_date'] - delta if before_end_date: event = {'event_type': 'before_end_lease', 'status': status.event.UNDONE} events.append(event) self._update_before_end_event_date(event, before_end_date, lease_values) try: if trust_id: lease_values.update({'trust_id': trust_id}) lease = db_api.lease_create(lease_values) lease_id = lease['id'] except db_ex.BlazarDBDuplicateEntry: LOG.exception('Cannot create a lease - duplicated lease name') raise exceptions.LeaseNameAlreadyExists( name=lease_values['name']) except db_ex.BlazarDBException: LOG.exception('Cannot create a lease') raise else: try: for reservation in reservations: reservation['lease_id'] = lease['id'] reservation['start_date'] = lease['start_date'] reservation['end_date'] = lease['end_date'] self._create_reservation(reservation) except Exception: LOG.exception("Failed to create reservation for a lease. " "Rollback the lease and associated " "reservations") db_api.lease_destroy(lease_id) raise try: for event in events: event['lease_id'] = lease['id'] db_api.event_create(event) except (exceptions.UnsupportedResourceType, common_ex.BlazarException): LOG.exception("Failed to create event for a lease. " "Rollback the lease and associated " "reservations") db_api.lease_destroy(lease_id) raise else: db_api.lease_update( lease_id, {'status': status.lease.PENDING}) lease = db_api.lease_get(lease_id) self._send_notification(lease, ctx, events=['create']) return lease
def update_lease(self, lease_id, values): if not values: return db_api.lease_get(lease_id) if len(values) == 1 and 'name' in values: db_api.lease_update(lease_id, values) return db_api.lease_get(lease_id) lease = db_api.lease_get(lease_id) start_date = values.get( 'start_date', datetime.datetime.strftime(lease['start_date'], LEASE_DATE_FORMAT)) end_date = values.get( 'end_date', datetime.datetime.strftime(lease['end_date'], LEASE_DATE_FORMAT)) before_end_date = values.get('before_end_date', None) now = datetime.datetime.utcnow() now = datetime.datetime(now.year, now.month, now.day, now.hour, now.minute) if start_date == 'now': start_date = now else: start_date = self._date_from_string(start_date) if end_date == 'now': end_date = now else: end_date = self._date_from_string(end_date) values['start_date'] = start_date values['end_date'] = end_date if (lease['start_date'] < now and values['start_date'] != lease['start_date']): raise common_ex.InvalidInput( 'Cannot modify the start date of already started leases') if (lease['start_date'] > now and values['start_date'] < now): raise common_ex.InvalidInput( 'Start date must be later than current date') if lease['end_date'] < now: raise common_ex.InvalidInput( 'Terminated leases can only be renamed') if (values['end_date'] < now or values['end_date'] < values['start_date']): raise common_ex.InvalidInput( 'End date must be later than current and start date') with trusts.create_ctx_from_trust(lease['trust_id']): if before_end_date: try: before_end_date = self._date_from_string(before_end_date) self._check_date_within_lease_limits(before_end_date, values) except common_ex.BlazarException as e: LOG.error("Invalid before_end_date param. %s", str(e)) raise e # TODO(frossigneux) rollback if an exception is raised reservations = values.get('reservations', []) reservations_db = db_api.reservation_get_all_by_lease_id(lease_id) try: invalid_ids = set([r['id'] for r in reservations]).difference( [r['id'] for r in reservations_db]) except KeyError: raise exceptions.MissingParameter(param='reservation ID') if invalid_ids: raise common_ex.InvalidInput( 'Please enter valid reservation IDs. Invalid reservation ' 'IDs are: %s' % ','.join([str(id) for id in invalid_ids])) for reservation in (reservations_db): v = {} v['start_date'] = values['start_date'] v['end_date'] = values['end_date'] try: v.update([r for r in reservations if r['id'] == reservation['id']].pop()) except IndexError: pass resource_type = v.get('resource_type', reservation['resource_type']) if resource_type != reservation['resource_type']: raise exceptions.CantUpdateParameter( param='resource_type') self.plugins[resource_type].update_reservation( reservation['id'], v) event = db_api.event_get_first_sorted_by_filters( 'lease_id', 'asc', { 'lease_id': lease_id, 'event_type': 'start_lease' } ) if not event: raise common_ex.BlazarException( 'Start lease event not found') db_api.event_update(event['id'], {'time': values['start_date']}) event = db_api.event_get_first_sorted_by_filters( 'lease_id', 'asc', { 'lease_id': lease_id, 'event_type': 'end_lease' } ) if not event: raise common_ex.BlazarException( 'End lease event not found') db_api.event_update(event['id'], {'time': values['end_date']}) notifications = ['update'] self._update_before_end_event(lease, values, notifications, before_end_date) try: del values['reservations'] except KeyError: pass db_api.lease_update(lease_id, values) lease = db_api.lease_get(lease_id) with trusts.create_ctx_from_trust(lease['trust_id']) as ctx: self._send_notification(lease, ctx, events=notifications) return lease