def test_action_check_status(self): specs = [ {'name': 'A01', 'target': 'cluster_001'}, {'name': 'A02', 'target': 'node_001'}, ] id_of = {} for spec in specs: action = _create_action(self.ctx, **spec) id_of[spec['name']] = action.id db_api.dependency_add(self.ctx, id_of['A02'], id_of['A01']) action1 = db_api.action_get(self.ctx, id_of['A01']) self.assertEqual(consts.ACTION_WAITING, action1.status) timestamp = time.time() status = db_api.action_check_status(self.ctx, id_of['A01'], timestamp) self.assertEqual(consts.ACTION_WAITING, status) status = db_api.action_check_status(self.ctx, id_of['A01'], timestamp) self.assertEqual(consts.ACTION_WAITING, status) timestamp = time.time() db_api.action_mark_succeeded(self.ctx, id_of['A02'], timestamp) status = db_api.action_check_status(self.ctx, id_of['A01'], timestamp) self.assertEqual(consts.ACTION_READY, status) action1 = db_api.action_get(self.ctx, id_of['A01']) self.assertEqual('All depended actions completed.', action1.status_reason) self.assertEqual(timestamp, action1.end_time)
def test_action_get_project_safe(self): parser.simple_parse(shared.sample_action) action = _create_action(self.ctx) new_ctx = utils.dummy_context(project='another-project') retobj = db_api.action_get(new_ctx, action.id, project_safe=True) self.assertIsNone(retobj) retobj = db_api.action_get(new_ctx, action.id, project_safe=False) self.assertIsNotNone(retobj)
def _prepare_action_mark_failed_cancel(self): specs = [ {'name': 'A01', 'status': 'INIT', 'target': 'cluster_001'}, {'name': 'A02', 'status': 'INIT', 'target': 'node_001'}, {'name': 'A03', 'status': 'INIT', 'target': 'node_002'}, {'name': 'A04', 'status': 'INIT', 'target': 'node_003'}, {'name': 'A05', 'status': 'INIT', 'target': 'cluster_002'}, {'name': 'A06', 'status': 'INIT', 'target': 'cluster_003'}, {'name': 'A07', 'status': 'INIT', 'target': 'cluster_004'}, ] id_of = {} for spec in specs: action = _create_action(self.ctx, **spec) id_of[spec['name']] = action.id db_api.dependency_add(self.ctx, [id_of['A02'], id_of['A03'], id_of['A04']], id_of['A01']) db_api.dependency_add(self.ctx, id_of['A01'], [id_of['A05'], id_of['A06'], id_of['A07']]) res = db_api.dependency_get_depended(self.ctx, id_of['A01']) self.assertEqual(3, len(res)) self.assertIn(id_of['A02'], res) self.assertIn(id_of['A03'], res) self.assertIn(id_of['A04'], res) action = db_api.action_get(self.ctx, id_of['A01']) self.assertEqual(consts.ACTION_WAITING, action.status) for aid in [id_of['A02'], id_of['A03'], id_of['A04']]: res = db_api.dependency_get_dependents(self.ctx, aid) self.assertEqual(1, len(res)) self.assertIn(id_of['A01'], res) res = db_api.dependency_get_depended(self.ctx, aid) self.assertEqual(0, len(res)) res = db_api.dependency_get_dependents(self.ctx, id_of['A01']) self.assertEqual(3, len(res)) self.assertIn(id_of['A05'], res) self.assertIn(id_of['A06'], res) self.assertIn(id_of['A07'], res) for aid in [id_of['A05'], id_of['A06'], id_of['A07']]: res = db_api.dependency_get_depended(self.ctx, aid) self.assertEqual(1, len(res)) self.assertIn(id_of['A01'], res) res = db_api.dependency_get_dependents(self.ctx, aid) self.assertEqual(0, len(res)) action = db_api.action_get(self.ctx, aid) self.assertEqual(consts.ACTION_WAITING, action.status) return id_of
def _check_dependency_add_dependent_list(self): specs = [ {'name': 'A01', 'target': 'cluster_001'}, {'name': 'A02', 'target': 'node_001'}, {'name': 'A03', 'target': 'node_002'}, {'name': 'A04', 'target': 'node_003'}, ] id_of = {} for spec in specs: action = _create_action(self.ctx, **spec) id_of[spec['name']] = action.id db_api.dependency_add(self.ctx, id_of['A01'], [id_of['A02'], id_of['A03'], id_of['A04']]) res = db_api.dependency_get_dependents(self.ctx, id_of['A01']) self.assertEqual(3, len(res)) self.assertIn(id_of['A02'], res) self.assertIn(id_of['A03'], res) self.assertIn(id_of['A04'], res) res = db_api.dependency_get_depended(self.ctx, id_of['A01']) self.assertEqual(0, len(res)) for aid in [id_of['A02'], id_of['A03'], id_of['A04']]: res = db_api.dependency_get_depended(self.ctx, aid) self.assertEqual(1, len(res)) self.assertIn(id_of['A01'], res) res = db_api.dependency_get_dependents(self.ctx, aid) self.assertEqual(0, len(res)) action = db_api.action_get(self.ctx, aid) self.assertEqual(action.status, consts.ACTION_WAITING) return id_of
def test_action_mark_succeeded(self): timestamp = time.time() id_of = self._check_action_add_dependency_dependent_list() db_api.action_mark_succeeded(self.ctx, id_of['action_001'], timestamp) action = db_api.action_get(self.ctx, id_of['action_001']) self.assertEqual(0, len(action.depended_by)) self.assertEqual(db_api.ACTION_SUCCEEDED, action.status) self.assertEqual(db_api.ACTION_SUCCEEDED, action.status) self.assertEqual(timestamp, action.end_time) for id in [id_of['action_002'], id_of['action_003'], id_of['action_004']]: action = db_api.action_get(self.ctx, id) self.assertEqual(0, len(action.depends_on))
def test_from_db_record(self): values = copy.deepcopy(self.action_values) obj = action_base.Action('OBJID', 'OBJECT_ACTION', self.ctx, **values) obj.store(self.ctx) record = db_api.action_get(self.ctx, obj.id) action_obj = action_base.Action._from_db_record(record) self.assertIsInstance(action_obj, action_base.Action) self.assertEqual(obj.id, action_obj.id) self.assertEqual(obj.action, action_obj.action) self.assertEqual(obj.name, action_obj.name) self.assertEqual(obj.target, action_obj.target) self.assertEqual(obj.cause, action_obj.cause) self.assertEqual(obj.owner, action_obj.owner) self.assertEqual(obj.interval, action_obj.interval) self.assertEqual(obj.start_time, action_obj.start_time) self.assertEqual(obj.end_time, action_obj.end_time) self.assertEqual(obj.timeout, action_obj.timeout) self.assertEqual(obj.status, action_obj.status) self.assertEqual(obj.status_reason, action_obj.status_reason) self.assertEqual(obj.inputs, action_obj.inputs) self.assertEqual(obj.outputs, action_obj.outputs) self.assertEqual(obj.depends_on, action_obj.depends_on) self.assertEqual(obj.depended_by, action_obj.depended_by) self.assertEqual(obj.created_time, action_obj.created_time) self.assertEqual(obj.updated_time, action_obj.updated_time) self.assertEqual(obj.deleted_time, action_obj.deleted_time) self.assertEqual(obj.data, action_obj.data)
def test_action_del_dependency_dependent_list(self): id_of = self._check_action_add_dependency_dependent_list() db_api.action_del_dependency(self.ctx, id_of['action_001'], [id_of['action_002'], id_of['action_003'], id_of['action_004']]) action = db_api.action_get(self.ctx, id_of['action_001']) self.assertEqual(0, len(action.depended_by)) for id in [id_of['action_002'], id_of['action_003'], id_of['action_004']]: action = db_api.action_get(self.ctx, id) self.assertEqual(0, len(action.depends_on)) self.assertEqual(db_api.ACTION_READY, action.status)
def test_action_mark_cancelled(self): timestamp = time.time() id_of = self._prepare_action_mark_failed_cancel() db_api.action_mark_cancelled(self.ctx, id_of['action_002'], timestamp) for id in [id_of['action_003'], id_of['action_004']]: action = db_api.action_get(self.ctx, id) self.assertEqual(db_api.ACTION_INIT, action.status) for id in [id_of['action_002'], id_of['action_001'], id_of['action_005'], id_of['action_006'], id_of['action_007']]: action = db_api.action_get(self.ctx, id) self.assertEqual(db_api.ACTION_CANCELED, action.status) self.assertEqual(timestamp, action.end_time)
def test_from_db_record_with_empty_fields(self): values = copy.deepcopy(self.action_values) del values['inputs'] del values['outputs'] obj = action_base.Action('OBJID', 'OBJECT_ACTION', self.ctx, **values) obj.store(self.ctx) record = db_api.action_get(self.ctx, obj.id) action_obj = action_base.Action._from_db_record(record) self.assertEqual({}, action_obj.inputs) self.assertEqual({}, action_obj.outputs)
def test_action_mark_cancelled(self): timestamp = time.time() id_of = self._prepare_action_mark_failed_cancel() db_api.action_mark_cancelled(self.ctx, id_of['A01'], timestamp) for aid in [id_of['A05'], id_of['A06'], id_of['A07']]: action = db_api.action_get(self.ctx, aid) self.assertEqual(consts.ACTION_CANCELLED, action.status) self.assertEqual(timestamp, action.end_time) result = db_api.dependency_get_dependents(self.ctx, id_of['A01']) self.assertEqual(0, len(result))
def _check_action_add_dependency_depended_list(self): specs = [ {'name': 'action_001', 'target': 'cluster_001'}, {'name': 'action_002', 'target': 'node_001'}, {'name': 'action_003', 'target': 'node_002'}, {'name': 'action_004', 'target': 'node_003'}, ] id_of = {} for spec in specs: action = _create_action(self.ctx, action=shared.sample_action, **spec) id_of[spec['name']] = action.id db_api.action_add_dependency(self.ctx, [id_of['action_002'], id_of['action_003'], id_of['action_004']], id_of['action_001']) action = db_api.action_get(self.ctx, id_of['action_001']) l = action.depends_on self.assertEqual(3, len(l)) self.assertIn(id_of['action_002'], l) self.assertIn(id_of['action_003'], l) self.assertIn(id_of['action_004'], l) self.assertIsNone(action.depended_by) self.assertEqual(action.status, db_api.ACTION_WAITING) for id in [id_of['action_002'], id_of['action_003'], id_of['action_004']]: action = db_api.action_get(self.ctx, id) l = action.depended_by self.assertEqual(1, len(l)) self.assertIn(id_of['action_001'], l) self.assertIsNone(action.depends_on) return id_of
def test_action_get(self): data = parser.simple_parse(shared.sample_action) action = _create_action(self.ctx) retobj = db_api.action_get(self.ctx, action.id) self.assertIsNotNone(retobj) self.assertEqual(data['name'], retobj.name) self.assertEqual(data['target'], retobj.target) self.assertEqual(data['action'], retobj.action) self.assertEqual(data['cause'], retobj.cause) self.assertEqual(data['timeout'], retobj.timeout) self.assertEqual(data['status'], retobj.status) self.assertEqual(data['status_reason'], retobj.status_reason) self.assertEqual(10, retobj.inputs['max_size']) self.assertIsNone(retobj.outputs)
def test_action_update(self): action = _create_action(self.ctx) values = { 'status': 'ERROR', 'status_reason': 'Cluster creation failed', 'data': {'key1': 'value1', 'key2': 'value2'} } db_api.action_update(self.ctx, action.id, values) action = db_api.action_get(self.ctx, action.id) self.assertEqual('ERROR', action.status) self.assertEqual('Cluster creation failed', action.status_reason) self.assertEqual({'key1': 'value1', 'key2': 'value2'}, action.data) self.assertRaises(exception.ActionNotFound, db_api.action_update, self.ctx, 'fake-uuid', values)
def test_load(self): values = copy.deepcopy(self.action_values) obj = action_base.Action('OBJID', 'OBJECT_ACTION', self.ctx, **values) obj.store(self.ctx) result = action_base.Action.load(self.ctx, obj.id, None) # no need to do a thorough test here self.assertEqual(obj.id, result.id) self.assertEqual(obj.action, result.action) db_action = db_api.action_get(self.ctx, obj.id) result = action_base.Action.load(self.ctx, None, db_action) # no need to do a thorough test here self.assertEqual(obj.id, result.id) self.assertEqual(obj.action, result.action)
def test_action_mark_succeeded(self): timestamp = time.time() id_of = self._check_dependency_add_dependent_list() db_api.action_mark_succeeded(self.ctx, id_of['A01'], timestamp) res = db_api.dependency_get_depended(self.ctx, id_of['A01']) self.assertEqual(0, len(res)) action = db_api.action_get(self.ctx, id_of['A01']) self.assertEqual(consts.ACTION_SUCCEEDED, action.status) self.assertEqual(timestamp, action.end_time) for aid in [id_of['A02'], id_of['A03'], id_of['A04']]: res = db_api.dependency_get_dependents(self.ctx, aid) self.assertEqual(0, len(res))
def _check_dependency_add_dependent_list(self): specs = [ { 'name': 'A01', 'target': 'cluster_001' }, { 'name': 'A02', 'target': 'node_001' }, { 'name': 'A03', 'target': 'node_002' }, { 'name': 'A04', 'target': 'node_003' }, ] id_of = {} for spec in specs: action = _create_action(self.ctx, **spec) id_of[spec['name']] = action.id db_api.dependency_add(self.ctx, id_of['A01'], [id_of['A02'], id_of['A03'], id_of['A04']]) res = db_api.dependency_get_dependents(self.ctx, id_of['A01']) self.assertEqual(3, len(res)) self.assertIn(id_of['A02'], res) self.assertIn(id_of['A03'], res) self.assertIn(id_of['A04'], res) res = db_api.dependency_get_depended(self.ctx, id_of['A01']) self.assertEqual(0, len(res)) for aid in [id_of['A02'], id_of['A03'], id_of['A04']]: res = db_api.dependency_get_depended(self.ctx, aid) self.assertEqual(1, len(res)) self.assertIn(id_of['A01'], res) res = db_api.dependency_get_dependents(self.ctx, aid) self.assertEqual(0, len(res)) action = db_api.action_get(self.ctx, aid) self.assertEqual(action.status, consts.ACTION_WAITING) return id_of
def test_action_update(self): action = _create_action(self.ctx) values = { 'status': 'ERROR', 'status_reason': 'Cluster creation failed', 'data': { 'key1': 'value1', 'key2': 'value2' } } db_api.action_update(self.ctx, action.id, values) action = db_api.action_get(self.ctx, action.id) self.assertEqual('ERROR', action.status) self.assertEqual('Cluster creation failed', action.status_reason) self.assertEqual({'key1': 'value1', 'key2': 'value2'}, action.data) self.assertRaises(exception.ResourceNotFound, db_api.action_update, self.ctx, 'fake-uuid', values)
def test_delete_cluster_lock_and_node_lock_2(self): # Test the case that an action is about node that also locked a # cluster and the cluster lock will remain locked # # (dead-engine) --> Action --> NodeLock # |action|owner| |node |action| # | A1 | E1 | |N1 |A1 | # --> ClusterLock # |cluster|action |scope| # |C1 |[A1, A2]|2 | # preparation engine_id = UUID1 action = shared.create_action(self.ctx, target=self.node.id, status='RUNNING', owner=engine_id, project=self.ctx.project) db_api.cluster_lock_acquire(self.cluster.id, action.id, 1) db_api.cluster_lock_acquire(self.cluster.id, UUID2, 1) db_api.node_lock_acquire(self.node.id, action.id) # do it db_api.gc_by_engine(engine_id) # assertion # a read lock is okay now and cluster lock state not broken observed = db_api.cluster_lock_acquire(self.cluster.id, UUID3, 1) self.assertIn(UUID2, observed) self.assertIn(UUID3, observed) self.assertNotIn(action.id, observed) # node can be locked again observed = db_api.node_lock_acquire(self.node.id, UUID2) self.assertEqual(UUID2, observed) new_action = db_api.action_get(self.ctx, action.id) self.assertEqual('FAILED', new_action.status) self.assertEqual("Engine failure", new_action.status_reason)
def test_action_mark_ready(self): timestamp = time.time() specs = [ {'name': 'A01', 'status': 'INIT', 'target': 'cluster_001'}, {'name': 'A02', 'status': 'INIT', 'target': 'node_001'}, {'name': 'A03', 'status': 'INIT', 'target': 'node_002'}, {'name': 'A04', 'status': 'INIT', 'target': 'node_003'}, {'name': 'A05', 'status': 'INIT', 'target': 'cluster_002'}, {'name': 'A06', 'status': 'INIT', 'target': 'cluster_003'}, {'name': 'A07', 'status': 'INIT', 'target': 'cluster_004'}, ] id_of = {} for spec in specs: action = _create_action(self.ctx, **spec) id_of[spec['name']] = action.id db_api.action_mark_ready(self.ctx, id_of['A01'], timestamp) action = db_api.action_get(self.ctx, id_of['A01']) self.assertEqual(consts.ACTION_READY, action.status) self.assertEqual(round(timestamp, 6), float(action.end_time))
def _prepare_action_mark_failed_cancel(self): specs = [ { 'name': 'A01', 'status': 'INIT', 'target': 'cluster_001' }, { 'name': 'A02', 'status': 'INIT', 'target': 'node_001' }, { 'name': 'A03', 'status': 'INIT', 'target': 'node_002', 'inputs': { 'update_parent_status': False } }, { 'name': 'A04', 'status': 'INIT', 'target': 'node_003' }, { 'name': 'A05', 'status': 'INIT', 'target': 'cluster_002' }, { 'name': 'A06', 'status': 'INIT', 'target': 'cluster_003' }, { 'name': 'A07', 'status': 'INIT', 'target': 'cluster_004' }, ] id_of = {} for spec in specs: action = _create_action(self.ctx, **spec) id_of[spec['name']] = action.id # A01 has dependents A02, A03, A04 db_api.dependency_add(self.ctx, [id_of['A02'], id_of['A03'], id_of['A04']], id_of['A01']) # A05, A06, A07 each has dependent A01 db_api.dependency_add(self.ctx, id_of['A01'], [id_of['A05'], id_of['A06'], id_of['A07']]) res = db_api.dependency_get_depended(self.ctx, id_of['A01']) self.assertEqual(3, len(res)) self.assertIn(id_of['A02'], res) self.assertIn(id_of['A03'], res) self.assertIn(id_of['A04'], res) action = db_api.action_get(self.ctx, id_of['A01']) self.assertEqual(consts.ACTION_WAITING, action.status) for aid in [id_of['A02'], id_of['A03'], id_of['A04']]: res = db_api.dependency_get_dependents(self.ctx, aid) self.assertEqual(1, len(res)) self.assertIn(id_of['A01'], res) res = db_api.dependency_get_depended(self.ctx, aid) self.assertEqual(0, len(res)) res = db_api.dependency_get_dependents(self.ctx, id_of['A01']) self.assertEqual(3, len(res)) self.assertIn(id_of['A05'], res) self.assertIn(id_of['A06'], res) self.assertIn(id_of['A07'], res) for aid in [id_of['A05'], id_of['A06'], id_of['A07']]: res = db_api.dependency_get_depended(self.ctx, aid) self.assertEqual(1, len(res)) self.assertIn(id_of['A01'], res) res = db_api.dependency_get_dependents(self.ctx, aid) self.assertEqual(0, len(res)) action = db_api.action_get(self.ctx, aid) self.assertEqual(consts.ACTION_WAITING, action.status) return id_of
def _prepare_action_mark_failed_cancel(self): specs = [ {'name': 'action_001', 'status': 'INIT', 'target': 'cluster_001'}, {'name': 'action_002', 'status': 'INIT', 'target': 'node_001'}, {'name': 'action_003', 'status': 'INIT', 'target': 'node_002'}, {'name': 'action_004', 'status': 'INIT', 'target': 'node_003'}, {'name': 'action_005', 'status': 'INIT', 'target': 'cluster_002'}, {'name': 'action_006', 'status': 'INIT', 'target': 'cluster_003'}, {'name': 'action_007', 'status': 'INIT', 'target': 'cluster_004'}, ] id_of = {} for spec in specs: action = _create_action(self.ctx, action=shared.sample_action, **spec) # action.status = db_api.ACTION_INIT id_of[spec['name']] = action.id db_api.action_add_dependency(self.ctx, [id_of['action_002'], id_of['action_003'], id_of['action_004']], id_of['action_001']) db_api.action_add_dependency(self.ctx, id_of['action_001'], [id_of['action_005'], id_of['action_006'], id_of['action_007']]) action = db_api.action_get(self.ctx, id_of['action_001']) l = action.depends_on self.assertEqual(3, len(l)) self.assertIn(id_of['action_002'], l) self.assertIn(id_of['action_003'], l) self.assertIn(id_of['action_004'], l) self.assertEqual(db_api.ACTION_WAITING, action.status) for id in [id_of['action_002'], id_of['action_003'], id_of['action_004']]: action = db_api.action_get(self.ctx, id) l = action.depended_by self.assertEqual(1, len(l)) self.assertIn(id_of['action_001'], l) self.assertIsNone(action.depends_on) action = db_api.action_get(self.ctx, id_of['action_001']) l = action.depended_by self.assertEqual(3, len(l)) self.assertIn(id_of['action_005'], l) self.assertIn(id_of['action_006'], l) self.assertIn(id_of['action_007'], l) for id in [id_of['action_005'], id_of['action_006'], id_of['action_007']]: action = db_api.action_get(self.ctx, id) l = action.depends_on self.assertEqual(1, len(l)) self.assertIn(id_of['action_001'], l) self.assertIsNone(action.depended_by) self.assertEqual(db_api.ACTION_WAITING, action.status) return id_of
def test_action_get_with_admin_context(self): parser.simple_parse(shared.sample_action) action = _create_action(self.ctx) new_ctx = utils.dummy_context(project='another-project', is_admin=True) retobj = db_api.action_get(new_ctx, action.id, project_safe=True) self.assertIsNotNone(retobj)
def test_action_get_with_invalid_id(self): retobj = db_api.action_get(self.ctx, 'fake-uuid') self.assertIsNone(retobj)
def test_mult_engine_keep_node_scope_lock(self): engine1 = UUID1 engine2 = UUID2 node2 = shared.create_node(self.ctx, self.cluster, self.profile) c_action = shared.create_action(self.ctx, target=self.cluster.id, status='WAITING', owner=engine1, project=self.ctx.project_id) n_action_1 = shared.create_action(self.ctx, target=self.node.id, status='RUNNING', owner=engine1, project=self.ctx.project_id) n_action_2 = shared.create_action(self.ctx, target=node2.id, status='RUNNING', owner=engine2, project=self.ctx.project_id) db_api.dependency_add(self.ctx, [n_action_1.id, n_action_2.id], c_action.id) db_api.cluster_lock_acquire(self.cluster.id, c_action.id, -1) db_api.cluster_lock_acquire(self.cluster.id, n_action_1.id, 1) db_api.cluster_lock_acquire(self.cluster.id, n_action_2.id, 1) db_api.node_lock_acquire(self.node.id, n_action_1.id) db_api.node_lock_acquire(node2.id, n_action_2.id) # do it db_api.dummy_gc(engine1) # try to acquire cluster scope lock observed = db_api.cluster_lock_acquire(self.cluster.id, UUID3, -1) self.assertIn(UUID3, observed) self.assertEqual(1, len(observed)) # try to acquire node scope lock UUID4 = uuidutils.generate_uuid() observed = db_api.cluster_lock_acquire(self.node.id, UUID4, 1) self.assertIn(UUID4, observed) self.assertEqual(1, len(observed)) # node scope lock will be also released UUID5 = uuidutils.generate_uuid() observed = db_api.cluster_lock_acquire(node2.id, UUID5, 1) self.assertIn(UUID5, observed) self.assertEqual(1, len(observed)) # try to acquire node lock UUID6 = uuidutils.generate_uuid() observed = db_api.node_lock_acquire(self.node.id, UUID6) self.assertEqual(UUID6, observed) # node locks for actions owned by other engines are still there UUID7 = uuidutils.generate_uuid() observed = db_api.node_lock_acquire(node2.id, UUID7) self.assertNotEqual(UUID7, observed) self.assertEqual(n_action_2.id, observed) # check dependency dependents = db_api.dependency_get_depended(self.ctx, c_action.id) self.assertEqual(0, len(dependents)) # check action status new_c_action = db_api.action_get(self.ctx, c_action.id) self.assertEqual('FAILED', new_c_action.status) self.assertIsNone(new_c_action.owner) new_n_action_1 = db_api.action_get(self.ctx, n_action_1.id) self.assertEqual('FAILED', new_n_action_1.status) self.assertIsNone(new_n_action_1.owner) new_n_action_2 = db_api.action_get(self.ctx, n_action_2.id) self.assertEqual('FAILED', new_n_action_2.status) self.assertIsNone(new_n_action_2.owner)