def ActionProc(ctx, action_id): """Action process.""" # Step 1: materialize the action object action = Action.load(ctx, action_id=action_id, project_safe=False) if action is None: LOG.error('Action "%s" could not be found.', action_id) return False EVENT.info(action, consts.PHASE_START, action_id[:8]) reason = 'Action completed' success = True try: # Step 2: execute the action result, reason = action.execute() if result == action.RES_RETRY: success = False except Exception as ex: # We catch exception here to make sure the following logics are # executed. result = action.RES_ERROR reason = six.text_type(ex) LOG.exception('Unexpected exception occurred during action ' '%(action)s (%(id)s) execution: %(reason)s', {'action': action.action, 'id': action.id, 'reason': reason}) success = False finally: # NOTE: locks on action is eventually released here by status update action.set_status(result, reason) return success
def ActionProc(context, action_id): '''Action process.''' # Step 1: materialize the action object action = Action.load(context, action_id=action_id) if action is None: LOG.error(_LE('Action "%s" could not be found.'), action_id) return False # TODO(Anyone): Remove context usage in event module EVENT.info(action.context, action, action.action, 'START') reason = 'Action completed' success = True try: # Step 2: execute the action result, reason = action.execute() except Exception as ex: # We catch exception here to make sure the following logics are # executed. result = action.RES_ERROR reason = six.text_type(ex) LOG.exception(_('Unexpected exception occurred during action ' '%(action)s (%(id)s) execution: %(reason)s'), {'action': action.action, 'id': action.id, 'reason': reason}) success = False finally: # NOTE: locks on action is eventually released here by status update action.set_status(result, reason) return success
def set_status(self, result, reason=None): """Set action status based on return value from execute.""" timestamp = wallclock() if result == self.RES_OK: status = self.SUCCEEDED ao.Action.mark_succeeded(self.context, self.id, timestamp) elif result == self.RES_ERROR: status = self.FAILED ao.Action.mark_failed(self.context, self.id, timestamp, reason or 'ERROR') elif result == self.RES_TIMEOUT: status = self.FAILED ao.Action.mark_failed(self.context, self.id, timestamp, reason or 'TIMEOUT') elif result == self.RES_CANCEL: status = self.CANCELLED ao.Action.mark_cancelled(self.context, self.id, timestamp) elif result == self.RES_LIFECYCLE_COMPLETE: status = self.SUCCEEDED ao.Action.mark_ready(self.context, self.id, timestamp) else: # result == self.RES_RETRY: retries = self.data.get('retries', 0) # Action failed at the moment, but can be retried # retries time is configurable if retries < cfg.CONF.lock_retry_times: status = self.READY retries += 1 self.data.update({'retries': retries}) ao.Action.abandon(self.context, self.id, {'data': self.data}) # sleep for a while eventlet.sleep(cfg.CONF.lock_retry_interval) dispatcher.start_action(self.id) else: status = self.RES_ERROR if not reason: reason = ('Exceeded maximum number of retries (%d)' '') % cfg.CONF.lock_retry_times ao.Action.mark_failed(self.context, self.id, timestamp, reason) if status == self.SUCCEEDED: EVENT.info(self, consts.PHASE_END, reason or 'SUCCEEDED') elif status == self.READY: EVENT.warning(self, consts.PHASE_ERROR, reason or 'RETRY') else: EVENT.error(self, consts.PHASE_ERROR, reason or 'ERROR') self.status = status self.status_reason = reason
def do_create(self, context): if self.status != self.INIT: LOG.error(_LE('Node is in status "%s"'), self.status) return False self.set_status(context, self.CREATING, reason='Creation in progress') event_mod.info(context, self, 'create') try: physical_id = profile_base.Profile.create_object(context, self) except exception.InternalError as ex: self._handle_exception(context, 'create', self.ERROR, ex) return False if not physical_id: return False status_reason = 'Creation succeeded' self.set_status(context, self.ACTIVE, status_reason) self.physical_id = physical_id self.store(context) return True
def test_info(self, mock_dump): entity = mock.Mock(id='1234567890') entity.name = 'fake_obj' action = mock.Mock(entity=entity, action='ACTION_NAME') res = event.info(action, 'P1', 'R1', 'TS1') self.assertIsNone(res) mock_dump.assert_called_once_with(logging.INFO, action, 'P1', 'R1', 'TS1')
def store(self, context): '''Store the cluster in database and return its ID. If the ID already exists, we do an update. ''' values = { 'name': self.name, 'profile_id': self.profile_id, 'user': self.user, 'project': self.project, 'domain': self.domain, 'parent': self.parent, 'init_time': self.init_time, 'created_time': self.created_time, 'updated_time': self.updated_time, 'deleted_time': self.deleted_time, 'min_size': self.min_size, 'max_size': self.max_size, 'desired_capacity': self.desired_capacity, 'next_index': self.next_index, 'timeout': self.timeout, 'status': self.status, 'status_reason': self.status_reason, 'meta_data': self.metadata, 'data': self.data, } timestamp = timeutils.utcnow() if self.id: values['updated_time'] = timestamp db_api.cluster_update(context, self.id, values) event_mod.info(context, self, 'update') else: self.init_time = timestamp values['init_time'] = timestamp cluster = db_api.cluster_create(context, values) self.id = cluster.id event_mod.info(context, self, 'create') self._load_runtime_data(context) return self.id
def do_delete(self, context): if not self.physical_id: db_api.node_delete(context, self.id) return True # TODO(Qiming): check if actions are working on it and can be canceled self.set_status(context, self.DELETING, reason='Deletion in progress') event_mod.info(context, self, 'delete') try: res = profile_base.Profile.delete_object(context, self) except exception.ResourceStatusError as ex: self._handle_exception(context, 'delete', self.ERROR, ex) res = False if res: db_api.node_delete(context, self.id) return True else: self.set_status(context, self.ERROR, reason='Deletion failed') return False
def do_create(self, context): if self.status != self.INIT: LOG.error(_LE('Node is in status "%s"'), self.status) return False self.set_status(context, self.CREATING, reason='Creation in progress') event_mod.info(context, self, 'create') physical_id = profile_base.Profile.create_object(context, self) if not physical_id: return False if self.cluster_id is not None: self.index = db_api.cluster_get_next_index(context, self.cluster_id) self.physical_id = physical_id self.created_time = datetime.datetime.utcnow() self.status = self.ACTIVE self.status_reason = 'Creation succeeded' self.store(context) return True
def store(self, context): '''Store the node record into database table. The invocation of DB API could be a node_create or a node_update, depending on whether node has an ID assigned. ''' values = { 'name': self.name, 'physical_id': self.physical_id, 'cluster_id': self.cluster_id, 'profile_id': self.profile_id, 'user': self.user, 'project': self.project, 'domain': self.domain, 'index': self.index, 'role': self.role, 'init_time': self.init_time, 'created_time': self.created_time, 'updated_time': self.updated_time, 'deleted_time': self.deleted_time, 'status': self.status, 'status_reason': self.status_reason, 'meta_data': self.metadata, 'data': self.data, } if self.id: db_api.node_update(context, self.id, values) event_mod.info(context, self, 'update') else: init_time = timeutils.utcnow() self.init_time = init_time values['init_time'] = init_time node = db_api.node_create(context, values) event_mod.info(context, self, 'create') self.id = node.id self._load_runtime_data(context) return self.id
def set_status(self, result, reason=None): """Set action status based on return value from execute.""" timestamp = wallclock() if result == self.RES_OK: status = self.SUCCEEDED ao.Action.mark_succeeded(self.context, self.id, timestamp) elif result == self.RES_ERROR: status = self.FAILED ao.Action.mark_failed(self.context, self.id, timestamp, reason or 'ERROR') elif result == self.RES_TIMEOUT: status = self.FAILED ao.Action.mark_failed(self.context, self.id, timestamp, reason or 'TIMEOUT') elif result == self.RES_CANCEL: status = self.CANCELLED ao.Action.mark_cancelled(self.context, self.id, timestamp) else: # result == self.RES_RETRY: status = self.READY # Action failed at the moment, but can be retried # We abandon it and then notify other dispatchers to execute it ao.Action.abandon(self.context, self.id) dispatcher.start_action() if status == self.SUCCEEDED: EVENT.info(self, consts.PHASE_END, reason or 'SUCCEEDED') elif status == self.READY: EVENT.warning(self, consts.PHASE_ERROR, reason or 'RETRY') else: EVENT.error(self, consts.PHASE_ERROR, reason or 'ERROR') self.status = status self.status_reason = reason
def set_status(self, result, reason=None): """Set action status based on return value from execute.""" timestamp = wallclock() if result == self.RES_OK: status = self.SUCCEEDED db_api.action_mark_succeeded(self.context, self.id, timestamp) elif result == self.RES_ERROR: status = self.FAILED db_api.action_mark_failed(self.context, self.id, timestamp, reason=reason or 'ERROR') elif result == self.RES_TIMEOUT: status = self.FAILED db_api.action_mark_failed(self.context, self.id, timestamp, reason=reason or 'TIMEOUT') elif result == self.RES_CANCEL: status = self.CANCELLED db_api.action_mark_cancelled(self.context, self.id, timestamp) else: # result == self.RES_RETRY: status = self.READY # Action failed at the moment, but can be retried # We abandon it and then notify other dispatchers to execute it db_api.action_abandon(self.context, self.id) if status == self.SUCCEEDED: EVENT.info(self.context, self, self.action, status, reason) elif status == self.READY: EVENT.warning(self.context, self, self.action, status, reason) else: EVENT.error(self.context, self, self.action, status, reason) self.status = status self.status_reason = reason
def store(self, context): '''Store the cluster in database and return its ID. If the ID already exists, we do an update. ''' values = { 'name': self.name, 'profile_id': self.profile_id, 'user': self.user, 'project': self.project, 'domain': self.domain, 'parent': self.parent, 'init_time': self.init_time, 'created_time': self.created_time, 'updated_time': self.updated_time, 'deleted_time': self.deleted_time, 'size': self.size, 'next_index': self.next_index, 'timeout': self.timeout, 'status': self.status, 'status_reason': self.status_reason, 'tags': self.tags, 'data': self.data, } if self.id: db_api.cluster_update(context, self.id, values) event_mod.info(context, self, 'update') else: values['init_time'] = datetime.datetime.utcnow() cluster = db_api.cluster_create(context, values) self.id = cluster.id event_mod.info(context, self, 'create') self._load_runtime_data(context) return self.id