Ejemplo n.º 1
0
 def delete_lease(self, lease_id):
     lease = self.get_lease(lease_id)
     if (datetime.datetime.utcnow() < lease['start_date'] or
             datetime.datetime.utcnow() > lease['end_date']):
         with trusts.create_ctx_from_trust(lease['trust_id']) as ctx:
             for reservation in lease['reservations']:
                 plugin = self.plugins[reservation['resource_type']]
                 try:
                     plugin.on_end(reservation['resource_id'])
                 except (db_ex.ClimateDBException, RuntimeError):
                     error_msg = "Failed to delete a reservation for a lease."
                     lease_state = states.LeaseState(id=lease_id,
                             action=states.lease.DELETE,
                             status=states.lease.FAILED,
                             status_reason=error_msg)
                     lease_state.save()
                     LOG.exception(error_msg)
                     raise
             db_api.lease_destroy(lease_id)
             self._send_notification(lease, ctx, events=['delete'])
     else:
         error_msg = "Already started lease cannot be deleted"
         lease_state = states.LeaseState(id=lease_id,
                 action=states.lease.DELETE,
                 status=states.lease.FAILED,
                 status_reason=error_msg)
         lease_state.save()
         raise common_ex.NotAuthorized(error_msg)
Ejemplo n.º 2
0
 def test_state_attributes(self):
     self.leaseState = states.LeaseState(id=1,
                                         action=states.lease.CREATE,
                                         status=states.lease.IN_PROGRESS)
     self.assertEqual(self.leaseState.action, states.lease.CREATE)
     self.assertEqual(self.leaseState.status, states.lease.IN_PROGRESS)
     self.assertEqual(self.leaseState.status_reason, None)
Ejemplo n.º 3
0
 def test_update_state_with_incorrect_action_status(self):
     self.leaseState = states.LeaseState(id=1)
     self.assertRaises(mgr_exc.InvalidStateUpdate,
                       self.leaseState.update,
                       action='foo',
                       status=states.lease.IN_PROGRESS)
     self.assertRaises(mgr_exc.InvalidStateUpdate,
                       self.leaseState.update,
                       action=states.lease.CREATE,
                       status='bar')
Ejemplo n.º 4
0
    def test_save_state_with_nonexisting_lease(self):
        def fake_lease_update_raise(id, values):
            raise db_exc.ClimateDBException

        self.lease_update.side_effect = fake_lease_update_raise
        self.leaseState = states.LeaseState(id=1, autosave=False)
        self.leaseState.update(action=states.lease.CREATE,
                               status=states.lease.IN_PROGRESS,
                               status_reason="Creating Lease...")
        self.assertRaises(mgr_exc.InvalidState, self.leaseState.save)
Ejemplo n.º 5
0
 def test_state_init_with_args(self):
     self.leaseState = states.LeaseState(id=1,
                                         action=states.lease.CREATE,
                                         status=states.lease.IN_PROGRESS)
     self.assertEqual(0, self.lease_get.call_count)
     expected = {
         'action': 'CREATE',
         'status': 'IN_PROGRESS',
         'status_reason': None
     }
     self.assertEqual(expected, self.leaseState.current())
Ejemplo n.º 6
0
 def test_update_state_with_noautosave(self):
     self.leaseState = states.LeaseState(id=1, autosave=False)
     self.leaseState.update(action=states.lease.CREATE,
                            status=states.lease.IN_PROGRESS,
                            status_reason="Creating Lease...")
     expected = {
         'action': 'CREATE',
         'status': 'IN_PROGRESS',
         'status_reason': "Creating Lease..."
     }
     self.assertEqual(0, self.lease_update.call_count)
     self.assertEqual(expected, self.leaseState.current())
Ejemplo n.º 7
0
 def test_save_state(self):
     self.leaseState = states.LeaseState(id=1, autosave=False)
     self.leaseState.update(action=states.lease.CREATE,
                            status=states.lease.IN_PROGRESS,
                            status_reason="Creating Lease...")
     self.assertEqual(0, self.lease_update.call_count)
     self.leaseState.save()
     values = {
         'action': 'CREATE',
         'status': 'IN_PROGRESS',
         'status_reason': "Creating Lease..."
     }
     self.lease_update.assert_called_once_with(1, values)
Ejemplo n.º 8
0
    def _basic_action(self, lease_id, event_id, action_time,
                      reservation_status=None):
        """Commits basic lease actions such as starting and ending."""
        lease = self.get_lease(lease_id)

        event_status = 'DONE'

        if action_time == 'on_start':
            lease_action = states.lease.START
            status_reason = "Starting lease..."
        elif action_time == 'on_end':
            lease_action = states.lease.STOP
            status_reason = "Stopping lease..."
        else:
            raise AttributeError("action_time is %s instead of either on_start or on_end"
                                 % action_time)

        lease_state = states.LeaseState(id=lease_id, action=lease_action,
                status=states.lease.IN_PROGRESS,
                status_reason=status_reason)
        lease_state.save()

        for reservation in lease['reservations']:
            resource_type = reservation['resource_type']
            try:
                self.resource_actions[resource_type][action_time](
                    reservation['resource_id']
                )
            except common_ex.ClimateException:
                LOG.exception("Failed to execute action %(action)s "
                              "for lease %(lease)s"
                              % {
                                  'action': action_time,
                                  'lease': lease_id,
                              })
                event_status = 'ERROR'
                db_api.reservation_update(reservation['id'],
                                          {'status': 'error'})
            else:
                if reservation_status is not None:
                    db_api.reservation_update(reservation['id'],
                                              {'status': reservation_status})

        db_api.event_update(event_id, {'status': event_status})

        if event_status == 'DONE':
            lease_status = states.lease.COMPLETE
            if action_time ==  'on_start':
                status_reason = "Successfully started lease"
            elif action_time == 'on_end':
                status_reason = "Successfully stopped lease"
            else:
                raise AttributeError("action_time is %s instead of either on_start or on_end"
                                     % action_time)
        elif event_status == 'ERROR':
            lease_status = states.lease.FAILED
            if action_time ==  'on_start':
                status_reason = "Failed to start lease"
            elif action_time == 'on_end':
                status_reason = "Failed to stop lease"
            else:
                raise AttributeError("action_time is %s instead of either on_start or on_end"
                                     % action_time)
        else:
            raise AttributeError("event_status is %s instead of either DONE or ERROR"
                                 % event_status)

        lease_state.update(action=lease_action,
                           status=lease_status,
                           status_reason=status_reason)
        lease_state.save()
Ejemplo n.º 9
0
    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_notification', 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)
        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.NotAuthorized(
                'Cannot modify the start date of already started leases')

        if (lease['start_date'] > now and
                values['start_date'] < now):
            raise common_ex.NotAuthorized(
                'Start date must later than current date')

        if lease['end_date'] < now:
            raise common_ex.NotAuthorized(
                'Terminated leases can only be renamed')

        if (values['end_date'] < now or
           values['end_date'] < values['start_date']):
            raise common_ex.NotAuthorized(
                '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.ClimateException as e:
                    LOG.error("Invalid before_end_date param. %s" % e.message)
                    raise e

            # TODO(frossigneux) rollback if an exception is raised
            for reservation in (
                    db_api.reservation_get_all_by_lease_id(lease_id)):
                reservation['start_date'] = values['start_date']
                reservation['end_date'] = values['end_date']
                resource_type = reservation['resource_type']
                self.plugins[resource_type].update_reservation(
                    reservation['id'],
                    reservation)

        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.ClimateException(
                '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.ClimateException(
                '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)

        db_api.lease_update(lease_id, values)

        lease_state = states.LeaseState(id=lease_id,
                action=states.lease.UPDATE,
                status=states.lease.COMPLETE,
                status_reason="Successfully updated lease")
        lease_state.save()
        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
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
 def test_state_init_with_no_existing_lease(self):
     self.lease_get.return_value = None
     self.leaseState = states.LeaseState(id=1)
     expected = {'action': None, 'status': None, 'status_reason': None}
     self.assertEqual(expected, self.leaseState.current())
Ejemplo n.º 12
0
 def test_state_init(self):
     self.leaseState = states.LeaseState(id=1)
     self.lease_get.assert_called_once_with(1)
     expected = {'action': None, 'status': None, 'status_reason': None}
     self.assertEqual(expected, self.leaseState.current())