def create_lease(self, lease_values): """Create a lease with reservations. Return either the model of created lease or None if any error. """ try: trust_id = lease_values.pop('trust_id') except KeyError: raise exceptions.MissingTrustId() # Remove and keep reservation values reservations = lease_values.pop("reservations", []) # Create the lease without the reservations start_date = lease_values['start_date'] end_date = lease_values['end_date'] 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) end_date = self._date_from_string(end_date) if start_date < now: raise common_ex.NotAuthorized( 'Start date must later than current date') with trusts.create_ctx_from_trust(trust_id) as ctx: lease_values['user_id'] = ctx.user_id lease_values['project_id'] = ctx.project_id lease_values['start_date'] = start_date lease_values['end_date'] = end_date if not lease_values.get('events'): lease_values['events'] = [] lease_values['events'].append({'event_type': 'start_lease', 'time': start_date, 'status': 'UNDONE'}) lease_values['events'].append({'event_type': 'end_lease', 'time': end_date, 'status': 'UNDONE'}) before_end_date = lease_values.get('before_end_notification', 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.ClimateException as e: LOG.error("Invalid before_end_date param. %s" % e.message) raise e elif CONF.manager.notify_hours_before_lease_end > 0: delta = datetime.timedelta( hours=CONF.manager.notify_hours_before_lease_end) before_end_date = lease_values['end_date'] - delta if before_end_date: event = {'event_type': 'before_end_lease', 'status': 'UNDONE'} lease_values['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.ClimateDBDuplicateEntry: LOG.exception('Cannot create a lease - duplicated lease name') raise exceptions.LeaseNameAlreadyExists( name=lease_values['name']) except db_ex.ClimateDBException: 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'] resource_type = reservation['resource_type'] if resource_type in self.plugins: self.plugins[resource_type].create_reservation( reservation) else: raise exceptions.UnsupportedResourceType( resource_type) except (exceptions.UnsupportedResourceType, common_ex.ClimateException): LOG.exception("Failed to create reservation for a lease. " "Rollback the lease and associated " "reservations") db_api.lease_destroy(lease_id) raise else: lease_state = states.LeaseState(id=lease['id'], action=states.lease.CREATE, status=states.lease.COMPLETE, status_reason="Successfully created lease") lease_state.save() lease = db_api.lease_get(lease['id']) self._send_notification(lease, ctx, events=['create']) return lease
def create_computehost(self, host_values): # TODO(sbauza): # - Exception handling for HostNotFound host_id = host_values.pop('id', None) host_name = host_values.pop('name', None) try: trust_id = host_values.pop('trust_id') except KeyError: raise manager_ex.MissingTrustId() host_ref = host_id or host_name if host_ref is None: raise manager_ex.InvalidHost(host=host_values) with trusts.create_ctx_from_trust(trust_id): inventory = nova_inventory.NovaInventory() servers = inventory.get_servers_per_host(host_ref) if servers: raise manager_ex.HostHavingServers(host=host_ref, servers=servers) host_details = inventory.get_host_details(host_ref) # NOTE(sbauza): Only last duplicate name for same extra capability # will be stored to_store = set(host_values.keys()) - set(host_details.keys()) extra_capabilities_keys = to_store extra_capabilities = dict( (key, host_values[key]) for key in extra_capabilities_keys ) pool = rp.ReservationPool() pool.add_computehost(self.freepool_name, host_details['service_name']) host = None cantaddextracapability = [] try: if trust_id: host_details.update({'trust_id': trust_id}) host = db_api.host_create(host_details) except db_ex.ClimateDBException: # We need to rollback # TODO(sbauza): Investigate use of Taskflow for atomic # transactions pool.remove_computehost(self.freepool_name, host_details['service_name']) if host: for key in extra_capabilities: values = {'computehost_id': host['id'], 'capability_name': key, 'capability_value': extra_capabilities[key], } try: db_api.host_extra_capability_create(values) except db_ex.ClimateDBException: cantaddextracapability.append(key) if cantaddextracapability: raise manager_ex.CantAddExtraCapability( keys=cantaddextracapability, host=host['id']) if host: return self.get_computehost(host['id']) else: return None