Browse Source

Merge "support fail operation task of v2 API"

changes/84/822284/12
Zuul 4 months ago committed by Gerrit Code Review
parent
commit
0d04ca644f
  1. 5
      releasenotes/notes/add-v2-fail-api-b35b605f262210b2.yaml
  2. 9
      tacker/sol_refactored/api/policies/vnflcm_v2.py
  3. 1
      tacker/sol_refactored/api/router.py
  4. 7
      tacker/sol_refactored/common/lcm_op_occ_utils.py
  5. 29
      tacker/sol_refactored/controller/vnflcm_v2.py
  6. 13
      tacker/sol_refactored/test-tools/cli.py
  7. 72
      tacker/tests/unit/sol_refactored/controller/test_vnflcm_v2.py

5
releasenotes/notes/add-v2-fail-api-b35b605f262210b2.yaml

@ -0,0 +1,5 @@
---
features:
- |
Add the Version "2.0.0" of Fail operation API
based on ETSI NFV specifications.

9
tacker/sol_refactored/api/policies/vnflcm_v2.py

@ -168,6 +168,15 @@ rules = [
'path': VNF_LCM_OP_OCCS_ID_PATH + '/rollback'}
]
),
policy.DocumentedRuleDefault(
name=POLICY_NAME.format('lcm_op_occ_fail'),
check_str=RULE_ANY,
description="Fail VnfLcmOpOcc.",
operations=[
{'method': 'POST',
'path': VNF_LCM_OP_OCCS_ID_PATH + '/fail'}
]
),
# NOTE: 'DELETE' is not defined in the specification. It is for test
# use since it is convenient to be able to delete under development.
# It is available when config parameter

1
tacker/sol_refactored/api/router.py

@ -47,6 +47,7 @@ class VnflcmAPIRouterV2(sol_wsgi.SolAPIRouter):
("/vnf_lcm_op_occs", {"GET": "lcm_op_occ_list"}),
("/vnf_lcm_op_occs/{id}/retry", {"POST": "lcm_op_occ_retry"}),
("/vnf_lcm_op_occs/{id}/rollback", {"POST": "lcm_op_occ_rollback"}),
("/vnf_lcm_op_occs/{id}/fail", {"POST": "lcm_op_occ_fail"}),
# NOTE: 'DELETE' is not defined in the specification. It is for test
# use since it is convenient to be able to delete under development.
# It is available when config parameter

7
tacker/sol_refactored/common/lcm_op_occ_utils.py

@ -55,13 +55,14 @@ def make_lcmocc_links(lcmocc, endpoint):
links.vnfInstance = objects.Link(
href=inst_utils.inst_href(lcmocc.vnfInstanceId, endpoint))
links.retry = objects.Link(
href=lcmocc_task_href(lcmocc.vnfInstanceId, 'retry', endpoint))
href=lcmocc_task_href(lcmocc.id, 'retry', endpoint))
links.rollback = objects.Link(
href=lcmocc_task_href(lcmocc.vnfInstanceId, 'rollback', endpoint))
href=lcmocc_task_href(lcmocc.id, 'rollback', endpoint))
links.fail = objects.Link(
href=lcmocc_task_href(lcmocc.id, 'fail', endpoint))
# TODO(oda-g): add when implemented
# links.grant
# links.cancel
# links.fail
# links.vnfSnapshot
return links

29
tacker/sol_refactored/controller/vnflcm_v2.py

@ -359,6 +359,35 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
return sol_wsgi.SolResponse(202, None)
def lcm_op_occ_fail(self, request, id):
context = request.context
lcmocc = lcmocc_utils.get_lcmocc(context, id)
return self._lcm_op_occ_fail(context, lcmocc)
@coordinate.lock_vnf_instance('{lcmocc.vnfInstanceId}')
def _lcm_op_occ_fail(self, context, lcmocc):
if lcmocc.operationState != v2fields.LcmOperationStateType.FAILED_TEMP:
raise sol_ex.LcmOpOccNotFailedTemp(lcmocc_id=lcmocc.id)
inst = inst_utils.get_inst(context, lcmocc.vnfInstanceId)
grant_req, grant = lcmocc_utils.get_grant_req_and_grant(context,
lcmocc)
lcmocc.operationState = v2fields.LcmOperationStateType.FAILED
with context.session.begin(subtransactions=True):
lcmocc.update(context)
grant_req.delete(context)
grant.delete(context)
# send notification FAILED
self.nfvo_client.send_lcmocc_notification(context, lcmocc, inst,
self.endpoint)
resp_body = self._lcmocc_view.detail(lcmocc)
return sol_wsgi.SolResponse(200, resp_body)
def lcm_op_occ_delete(self, request, id):
# not allowed to delete on the specification
if not CONF.v2_vnfm.test_enable_lcm_op_occ_delete:

13
tacker/sol_refactored/test-tools/cli.py

@ -98,6 +98,11 @@ class Client(object):
path = self.path + '/' + id + '/rollback'
resp, body = self.client.do_request(path, "POST", version="2.0.0")
def fail(self, id):
path = self.path + '/' + id + '/fail'
resp, body = self.client.do_request(path, "POST", version="2.0.0")
self.print(resp, body)
def usage():
print("usage: cli resource action [arg...]")
@ -116,6 +121,7 @@ def usage():
print(" lcmocc delete {id}")
print(" lcmocc retry {id}")
print(" lcmocc rollback {id}")
print(" lcmocc fail {id}")
os._exit(1)
@ -139,7 +145,8 @@ if __name__ == '__main__':
usage()
client = Client("/vnflcm/v2/subscriptions")
elif resource == "lcmocc":
if action not in ["list", "show", "delete", "retry", "rollback"]:
if action not in ["list", "show", "delete", "retry", "rollback",
"fail"]:
usage()
client = Client("/vnflcm/v2/vnf_lcm_op_occs")
else:
@ -180,3 +187,7 @@ if __name__ == '__main__':
if len(sys.argv) != 4:
usage()
client.rollback(sys.argv[3])
elif action == "fail":
if len(sys.argv) != 4:
usage()
client.fail(sys.argv[3])

72
tacker/tests/unit/sol_refactored/controller/test_vnflcm_v2.py

@ -21,6 +21,7 @@ from oslo_utils import uuidutils
from tacker import context
from tacker.sol_refactored.api import api_version
from tacker.sol_refactored.common import exceptions as sol_ex
from tacker.sol_refactored.common import lcm_op_occ_utils as lcmocc_utils
from tacker.sol_refactored.controller import vnflcm_v2
from tacker.sol_refactored.nfvo import nfvo_client
from tacker.sol_refactored import objects
@ -39,7 +40,7 @@ class TestVnflcmV2(db_base.SqlTestCase):
self.request = mock.Mock()
self.request.context = self.context
def _create_inst_and_lcmocc(self, inst_state, op_state):
def _set_inst_and_lcmocc(self, inst_state, op_state):
inst = objects.VnfInstanceV2(
# required fields
id=uuidutils.generate_uuid(),
@ -62,7 +63,13 @@ class TestVnflcmV2(db_base.SqlTestCase):
operation=fields.LcmOperationType.INSTANTIATE,
isAutomaticInvocation=False,
isCancelPending=False,
operationParams=req)
operationParams=req
)
return inst, lcmocc
def _create_inst_and_lcmocc(self, inst_state, op_state):
inst, lcmocc = self._set_inst_and_lcmocc(inst_state, op_state)
inst.create(self.context)
lcmocc.create(self.context)
@ -191,3 +198,64 @@ class TestVnflcmV2(db_base.SqlTestCase):
self.assertRaises(sol_ex.LcmOpOccNotFailedTemp,
self.controller.lcm_op_occ_rollback, request=self.request,
id=lcmocc_id)
def test_fail_not_failed_temp(self):
_, lcmocc_id = self._create_inst_and_lcmocc('INSTANTIATED',
fields.LcmOperationStateType.COMPLETED)
self.assertRaises(sol_ex.LcmOpOccNotFailedTemp,
self.controller.lcm_op_occ_fail, request=self.request,
id=lcmocc_id)
def _prepare_db_for_fail(self):
inst, lcmocc = self._set_inst_and_lcmocc('NOT_INSTANTIATED',
fields.LcmOperationStateType.FAILED_TEMP)
inst.create(self.context)
lcmocc.create(self.context)
grant_req = objects.GrantRequestV1(
# required fields
vnfInstanceId=lcmocc.vnfInstanceId,
vnfLcmOpOccId=lcmocc.id,
vnfdId=uuidutils.generate_uuid(),
operation=lcmocc.operation,
isAutomaticInvocation=lcmocc.isAutomaticInvocation
)
grant = objects.GrantV1(
# required fields
id=uuidutils.generate_uuid(),
vnfInstanceId=lcmocc.vnfInstanceId,
vnfLcmOpOccId=lcmocc.id
)
grant_req.create(self.context)
grant.create(self.context)
lcmocc.grantId = grant.id
lcmocc.update(self.context)
return lcmocc
@mock.patch.object(nfvo_client.NfvoClient, 'send_lcmocc_notification')
def test_lcm_op_occ_fail(self, mocked_send_lcmocc_notification):
# prepare
lcmocc = self._prepare_db_for_fail()
op_state = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
mocked_send_lcmocc_notification.side_effect = _store_state
# run lcm_op_occ_fail
self.controller.lcm_op_occ_fail(self.request, lcmocc.id)
# check operationstate
self.assertEqual(1, mocked_send_lcmocc_notification.call_count)
self.assertEqual(fields.LcmOperationStateType.FAILED, op_state[0])
# check grant_req and grant are deleted
self.assertRaises(sol_ex.GrantRequestOrGrantNotFound,
lcmocc_utils.get_grant_req_and_grant, self.context, lcmocc)

Loading…
Cancel
Save