from django.test import TestCase, Client
from rest_framework import status
-from lcm.pub.database.models import NfInstModel, JobModel, NSInstModel, VmInstModel
+from lcm.pub.database.models import NfInstModel, JobModel, NSInstModel, VmInstModel, OOFDataModel, SubscriptionModel
from lcm.pub.exceptions import NSLCMException
from lcm.pub.utils import restcall
-from lcm.pub.utils.jobutil import JOB_MODEL_STATUS
-from lcm.pub.utils.jobutil import JobUtil, JOB_TYPE
+from lcm.pub.enum import JOB_MODEL_STATUS, JOB_TYPE
+from lcm.pub.utils.jobutil import JobUtil
from lcm.pub.utils.timeutil import now_time
from lcm.pub.utils.values import ignore_case_get
from lcm.ns_vnfs.biz.create_vnfs import CreateVnfs
+from lcm.ns_vnfs.biz.grant_vnf import GrantVnf
from lcm.ns_vnfs.biz.heal_vnfs import NFHealService
from lcm.ns_vnfs.biz.scale_vnfs import NFManualScaleService
+from lcm.ns_vnfs.biz.subscribe import SubscriptionDeletion
from lcm.ns_vnfs.biz.terminate_nfs import TerminateVnfs
-from lcm.ns_vnfs.const import VNF_STATUS, INST_TYPE
+from lcm.ns_vnfs.enum import VNF_STATUS, INST_TYPE
from lcm.ns_vnfs.biz import create_vnfs
+from lcm.ns_vnfs.biz.place_vnfs import PlaceVnfs
+from lcm.pub.msapi import resmgr
class TestGetVnfViews(TestCase):
def test_get_vnf(self):
response = self.client.get("/api/nslcm/v1/ns/vnfs/%s" % self.nf_inst_id)
- self.failUnlessEqual(status.HTTP_200_OK, response.status_code)
+ self.assertEqual(status.HTTP_200_OK, response.status_code)
context = json.loads(response.content)
- self.failUnlessEqual(self.nf_inst_id, context['vnfInstId'])
+ self.assertEqual(self.nf_inst_id, context['vnfInstId'])
class TestCreateVnfViews(TestCase):
"vnf_param2": "22"
}),
"vnfminstanceid": "1",
- "vimId": "zte_test"
+ # "vimId": "zte_test"
+ "vimId": '{"cloud_owner": "VCPE", "cloud_regionid": "RegionOne"}'
}
}
],
@mock.patch.object(CreateVnfs, 'run')
def test_create_vnf(self, mock_run):
response = self.client.post("/api/nslcm/v1/ns/vnfs", data=self.data)
- self.failUnlessEqual(status.HTTP_202_ACCEPTED, response.status_code)
+ self.assertEqual(status.HTTP_202_ACCEPTED, response.status_code)
context = json.loads(response.content)
self.assertTrue(NfInstModel.objects.filter(nfinstid=context['vnfInstId']).exists())
CreateVnfs(data, nf_inst_id, job_id).run()
self.assertTrue(NfInstModel.objects.get(nfinstid=nf_inst_id).status, VNF_STATUS.ACTIVE)
+ @mock.patch.object(restcall, 'call_req')
+ @mock.patch.object(CreateVnfs, 'build_homing_request')
+ def test_send_homing_request(self, mock_build_req, mock_call_req):
+ nf_inst_id, job_id = create_vnfs.prepare_create_params()
+ OOFDataModel.objects.all().delete()
+ resp = {
+ "requestId": "1234",
+ "transactionId": "1234",
+ "requestStatus": "accepted"
+ }
+ mock_build_req.return_value = {
+ "requestInfo": {
+ "transactionId": "1234",
+ "requestId": "1234",
+ "callbackUrl": "xx",
+ "sourceId": "vfc",
+ "requestType": "create",
+ "numSolutions": 1,
+ "optimizers": ["placement"],
+ "timeout": 600
+ },
+ "placementInfo": {
+ "placementDemands": [
+ {
+ "resourceModuleName": "vG",
+ "serviceResourceId": "1234",
+ "resourceModelInfo": {
+ "modelInvariantId": "1234",
+ "modelVersionId": "1234"
+ }
+ }
+ ]
+ },
+ "serviceInfo": {
+ "serviceInstanceId": "1234",
+ "serviceName": "1234",
+ "modelInfo": {
+ "modelInvariantId": "5678",
+ "modelVersionId": "7890"
+ }
+ }
+ }
+ mock_call_req.return_value = [0, json.JSONEncoder().encode(resp), '202']
+ data = {
+ 'ns_instance_id': ignore_case_get(self.data, 'nsInstanceId'),
+ 'additional_param_for_ns': ignore_case_get(self.data, 'additionalParamForNs'),
+ 'additional_param_for_vnf': ignore_case_get(self.data, 'additionalParamForVnf'),
+ 'vnf_index': ignore_case_get(self.data, 'vnfIndex')
+ }
+ CreateVnfs(data, nf_inst_id, job_id).send_homing_request_to_OOF()
+ ret = OOFDataModel.objects.filter(request_id="1234", transaction_id="1234")
+ self.assertIsNotNone(ret)
+
class TestTerminateVnfViews(TestCase):
def setUp(self):
package_id='pkg1',
vnfd_model=self.vnfd_model)
VmInstModel.objects.create(vmid="1",
- vimid="zte_test",
+ # vimid="zte_test",
+ vimid='{"cloud_owner": "VCPE", "cloud_regionid": "RegionOne"}',
resouceid="1",
insttype=INST_TYPE.VNF,
instid=self.nf_inst_id,
"terminationType": "forceful",
"gracefulTerminationTimeout": "600"}
- response = self.client.post("/api/nslcm/v1/ns/vnfs/%s" % self.nf_inst_id, data=req_data)
- self.failUnlessEqual(status.HTTP_201_CREATED, response.status_code)
+ response = self.client.post("/api/nslcm/v1/ns/terminatevnf/%s" % self.nf_inst_id, data=req_data)
+ self.assertEqual(status.HTTP_202_ACCEPTED, response.status_code)
@mock.patch.object(restcall, 'call_req')
- def test_terminate_vnf(self, mock_call_req):
+ @mock.patch.object(SubscriptionDeletion, 'send_subscription_deletion_request')
+ def test_terminate_vnf(self, mock_send_subscription_deletion_request, mock_call_req):
job_id = JobUtil.create_job("VNF", JOB_TYPE.TERMINATE_VNF, self.nf_inst_id)
nfinst = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
if nfinst:
- self.failUnlessEqual(1, 1)
+ self.assertEqual(1, 1)
else:
- self.failUnlessEqual(1, 0)
+ self.assertEqual(1, 0)
+
+ notification_types = ["VnfLcmOperationOccurrenceNotification"],
+ operation_types = [
+ "INSTANTIATE",
+ "SCALE",
+ "SCALE_TO_LEVEL",
+ "CHANGE_FLAVOUR",
+ "TERMINATE",
+ "HEAL",
+ "OPERATE",
+ "CHANGE_EXT_CONN",
+ "MODIFY_INFO"
+ ],
+ operation_states = [
+ "STARTING",
+ "PROCESSING",
+ "COMPLETED",
+ "FAILED_TEMP",
+ "FAILED",
+ "ROLLING_BACK",
+ "ROLLED_BACK"
+ ],
+ vnf_instance_subscription_filter = {
+ "vnfdIds": [],
+ "vnfInstanceIds": '1',
+ "vnfInstanceNames": [],
+ "vnfProductsFromProviders": {}
+ }
+ SubscriptionModel.objects.create(
+ subscription_id='1',
+ notification_types=json.dumps(notification_types),
+ operation_types=json.dumps(operation_types),
+ operation_states=json.dumps(operation_states),
+ vnf_instance_filter=json.dumps(vnf_instance_subscription_filter),
+ # callback_uri,
+ # links=json.dumps(...)
+ )
vnf_info = {
"vnf-id": "vnf-id-test111",
def side_effect(*args):
return mock_vals[args[4]]
+
mock_call_req.side_effect = side_effect
req_data = {
TerminateVnfs(req_data, self.nf_inst_id, job_id).run()
nfinst = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
if nfinst:
- self.failUnlessEqual(1, 0)
+ self.assertEqual(1, 0)
else:
- self.failUnlessEqual(1, 1)
+ self.assertEqual(1, 1)
class TestScaleVnfViews(TestCase):
}
response = self.client.get("/api/nslcm/v1/vnfms/%s" % self.vnfm_id)
- self.failUnlessEqual(status.HTTP_200_OK, response.status_code, response.content)
+ self.assertEqual(status.HTTP_200_OK, response.status_code, response.content)
context = json.loads(response.content)
self.assertEqual(expect_data, context)
class TestGetVimInfoViews(TestCase):
def setUp(self):
self.client = Client()
- self.vim_id = "zte_test"
+ self.vim_id = {"cloud_owner": "VCPE", "cloud_regionid": "RegionOne"}
def tearDown(self):
pass
"createTime": ""
}
- response = self.client.get("/api/nslcm/v1/vims/%s" % self.vim_id)
- self.failUnlessEqual(status.HTTP_200_OK, response.status_code)
+ # response = self.client.get("/api/nslcm/v1/vims/%s" % self.vim_id)
+ response = self.client.get("/api/nslcm/v1/vims/%s/%s" % (self.vim_id['cloud_owner'], self.vim_id['cloud_regionid']))
+ self.assertEqual(status.HTTP_200_OK, response.status_code)
context = json.loads(response.content)
self.assertEqual(expect_data["url"], context["url"])
+class TestPlaceVnfViews(TestCase):
+ def setUp(self):
+ self.vnf_inst_id = "1234"
+ self.vnf_id = "vG"
+ self.client = Client()
+ OOFDataModel.objects.all().delete()
+ OOFDataModel.objects.create(
+ request_id="1234",
+ transaction_id="1234",
+ request_status="init",
+ request_module_name=self.vnf_id,
+ service_resource_id=self.vnf_inst_id,
+ vim_id="",
+ cloud_owner="",
+ cloud_region_id="",
+ vdu_info="",
+ )
+
+ def tearDown(self):
+ OOFDataModel.objects.all().delete()
+
+ @mock.patch.object(restcall, 'call_req')
+ def test_place_vnf(self, mock_call_req):
+ vdu_info_json = [{
+ "vduName": "vG_0",
+ "flavorName": "HPA.flavor.1",
+ "flavorId": "12345",
+ "directive": []
+ }]
+ PlaceVnfs(vnf_place_request).extract()
+ db_info = OOFDataModel.objects.filter(request_id=vnf_place_request.get("requestId"), transaction_id=vnf_place_request.get("transactionId"))
+ self.assertEqual(db_info[0].request_status, "completed")
+ self.assertEqual(db_info[0].vim_id, "CloudOwner1_DLLSTX1A")
+ self.assertEqual(db_info[0].cloud_owner, "CloudOwner1")
+ self.assertEqual(db_info[0].cloud_region_id, "DLLSTX1A")
+ self.assertEqual(db_info[0].vdu_info, json.dumps(vdu_info_json))
+
+ def test_place_vnf_with_invalid_response(self):
+ resp = {
+ "requestId": "1234",
+ "transactionId": "1234",
+ "statusMessage": "xx",
+ "requestStatus": "pending",
+ "solutions": {
+ "placementSolutions": [
+ [
+ {
+ "resourceModuleName": self.vnf_id,
+ "serviceResourceId": self.vnf_inst_id,
+ "solution": {
+ "identifierType": "serviceInstanceId",
+ "identifiers": [
+ "xx"
+ ],
+ "cloudOwner": "CloudOwner1 "
+ },
+ "assignmentInfo": []
+ }
+ ]
+ ],
+ "licenseSolutions": [
+ {
+ "resourceModuleName": "string",
+ "serviceResourceId": "string",
+ "entitlementPoolUUID": [
+ "string"
+ ],
+ "licenseKeyGroupUUID": [
+ "string"
+ ],
+ "entitlementPoolInvariantUUID": [
+ "string"
+ ],
+ "licenseKeyGroupInvariantUUID": [
+ "string"
+ ]
+ }
+ ]
+ }
+ }
+ PlaceVnfs(resp).extract()
+ db_info = OOFDataModel.objects.filter(request_id=resp.get("requestId"), transaction_id=resp.get("transactionId"))
+ self.assertEqual(db_info[0].request_status, "pending")
+ self.assertEqual(db_info[0].vim_id, "none")
+ self.assertEqual(db_info[0].cloud_owner, "none")
+ self.assertEqual(db_info[0].cloud_region_id, "none")
+ self.assertEqual(db_info[0].vdu_info, "none")
+
+ def test_place_vnf_with_no_assignment_info(self):
+ resp = {
+ "requestId": "1234",
+ "transactionId": "1234",
+ "statusMessage": "xx",
+ "requestStatus": "completed",
+ "solutions": {
+ "placementSolutions": [
+ [
+ {
+ "resourceModuleName": self.vnf_id,
+ "serviceResourceId": self.vnf_inst_id,
+ "solution": {
+ "identifierType": "serviceInstanceId",
+ "identifiers": [
+ "xx"
+ ],
+ "cloudOwner": "CloudOwner1 "
+ }
+ }
+ ]
+ ],
+ "licenseSolutions": [
+ {
+ "resourceModuleName": "string",
+ "serviceResourceId": "string",
+ "entitlementPoolUUID": [
+ "string"
+ ],
+ "licenseKeyGroupUUID": [
+ "string"
+ ],
+ "entitlementPoolInvariantUUID": [
+ "string"
+ ],
+ "licenseKeyGroupInvariantUUID": [
+ "string"
+ ]
+ }
+ ]
+ }
+ }
+ PlaceVnfs(resp).extract()
+ db_info = OOFDataModel.objects.filter(request_id=resp.get("requestId"), transaction_id=resp.get("transactionId"))
+ self.assertEqual(db_info[0].request_status, "completed")
+ self.assertEqual(db_info[0].vim_id, "none")
+ self.assertEqual(db_info[0].cloud_owner, "none")
+ self.assertEqual(db_info[0].cloud_region_id, "none")
+ self.assertEqual(db_info[0].vdu_info, "none")
+
+ def test_place_vnf_no_directives(self):
+ resp = {
+ "requestId": "1234",
+ "transactionId": "1234",
+ "statusMessage": "xx",
+ "requestStatus": "completed",
+ "solutions": {
+ "placementSolutions": [
+ [
+ {
+ "resourceModuleName": self.vnf_id,
+ "serviceResourceId": self.vnf_inst_id,
+ "solution": {
+ "identifierType": "serviceInstanceId",
+ "identifiers": [
+ "xx"
+ ],
+ "cloudOwner": "CloudOwner1 "
+ },
+ "assignmentInfo": [
+ {"key": "locationId",
+ "value": "DLLSTX1A"
+ }
+ ]
+ }
+ ]
+ ],
+ "licenseSoutions": [
+ {
+ "resourceModuleName": "string",
+ "serviceResourceId": "string",
+ "entitlementPoolUUID": [
+ "string"
+ ],
+ "licenseKeyGroupUUID": [
+ "string"
+ ],
+ "entitlementPoolInvariantUUID": [
+ "string"
+ ],
+ "licenseKeyGroupInvariantUUID": [
+ "string"
+ ]
+ }
+ ]
+ }
+ }
+ PlaceVnfs(resp).extract()
+ db_info = OOFDataModel.objects.filter(request_id=resp.get("requestId"), transaction_id=resp.get("transactionId"))
+ self.assertEqual(db_info[0].request_status, "completed")
+ self.assertEqual(db_info[0].vim_id, "none")
+ self.assertEqual(db_info[0].cloud_owner, "none")
+ self.assertEqual(db_info[0].cloud_region_id, "none")
+ self.assertEqual(db_info[0].vdu_info, "none")
+
+ def test_place_vnf_with_no_solution(self):
+ resp = {
+ "requestId": "1234",
+ "transactionId": "1234",
+ "statusMessage": "xx",
+ "requestStatus": "completed",
+ "solutions": {
+ "placementSolutions": [],
+ "licenseSoutions": []
+ }
+ }
+ PlaceVnfs(resp).extract()
+ db_info = OOFDataModel.objects.filter(request_id=resp.get("requestId"), transaction_id=resp.get("transactionId"))
+ self.assertEqual(db_info[0].request_status, "completed")
+ self.assertEqual(db_info[0].vim_id, "none")
+ self.assertEqual(db_info[0].cloud_owner, "none")
+ self.assertEqual(db_info[0].cloud_region_id, "none")
+ self.assertEqual(db_info[0].vdu_info, "none")
+
+
+class TestGrantVnfViews(TestCase):
+ def setUp(self):
+ self.vnf_inst_id = str(uuid.uuid4())
+ self.data = {
+ "vnfInstanceId": self.vnf_inst_id,
+ "vnfLcmOpOccId": "1234",
+ "operation": "INSTANTIATE"
+ }
+ vdu_info_dict = [{"vduName": "vg", "flavorName": "flavor_1", "flavorId": "12345", "directive": []}]
+ OOFDataModel(request_id='1234', transaction_id='1234', request_status='done', request_module_name='vg',
+ service_resource_id=self.vnf_inst_id, vim_id='cloudOwner_casa', cloud_owner='cloudOwner',
+ cloud_region_id='casa', vdu_info=json.dumps(vdu_info_dict)).save()
+
+ def tearDown(self):
+ OOFDataModel.objects.all().delete()
+
+ @mock.patch.object(resmgr, "grant_vnf")
+ def test_exec_grant(self, mock_grant):
+ resmgr_grant_resp = {
+ "vim": {
+ "vimId": "cloudOwner_casa",
+ "accessInfo": {
+ "tenant": "tenantA"
+ }
+ }
+ }
+ mock_grant.return_value = resmgr_grant_resp
+ resp = GrantVnf(self.data).exec_grant()
+ self.assertEqual(resp['vimAssets']['computeResourceFlavours'][0]['vimConnectionId'], 'cloudOwner_casa')
+ self.assertEqual(resp['vimAssets']['computeResourceFlavours'][0]['resourceProviderId'], 'vg')
+ self.assertEqual(resp['vimAssets']['computeResourceFlavours'][0]['vimFlavourId'], '12345')
+
+
vnfd_model_dict = {
'local_storages': [],
'vdus': [
],
'nfv_compute': {
'mem_size': '',
- 'num_cpus': u'2'
+ 'num_cpus': '2'
},
'local_storages': [
],
- 'vdu_id': u'vdu_omm.001',
- 'image_file': u'opencos_sss_omm_img_release_20150723-1-disk1',
+ 'vdu_id': 'vdu_omm.001',
+ 'image_file': 'opencos_sss_omm_img_release_20150723-1-disk1',
'dependencies': [
],
'local_affinity_antiaffinity_rule': {
},
- 'template_id': u'omm.001',
+ 'template_id': 'omm.001',
'manual_scale_select_vim': False
},
- 'description': u'singleommvm'
+ 'description': 'singleommvm'
},
{
'volumn_storages': [
],
'nfv_compute': {
'mem_size': '',
- 'num_cpus': u'4'
+ 'num_cpus': '4'
},
'local_storages': [
],
- 'vdu_id': u'vdu_1',
- 'image_file': u'sss',
+ 'vdu_id': 'vdu_1',
+ 'image_file': 'sss',
'dependencies': [
],
'local_affinity_antiaffinity_rule': {
},
- 'template_id': u'1',
+ 'template_id': '1',
'manual_scale_select_vim': False
},
- 'description': u'ompvm'
+ 'description': 'ompvm'
},
{
'volumn_storages': [
],
'nfv_compute': {
'mem_size': '',
- 'num_cpus': u'14'
+ 'num_cpus': '14'
},
'local_storages': [
],
- 'vdu_id': u'vdu_2',
- 'image_file': u'sss',
+ 'vdu_id': 'vdu_2',
+ 'image_file': 'sss',
'dependencies': [
],
'local_affinity_antiaffinity_rule': {
},
- 'template_id': u'2',
+ 'template_id': '2',
'manual_scale_select_vim': False
},
- 'description': u'ompvm'
+ 'description': 'ompvm'
},
{
'volumn_storages': [
],
'nfv_compute': {
'mem_size': '',
- 'num_cpus': u'14'
+ 'num_cpus': '14'
},
'local_storages': [
],
- 'vdu_id': u'vdu_3',
- 'image_file': u'sss',
+ 'vdu_id': 'vdu_3',
+ 'image_file': 'sss',
'dependencies': [
],
'local_affinity_antiaffinity_rule': {
},
- 'template_id': u'3',
+ 'template_id': '3',
'manual_scale_select_vim': False
},
- 'description': u'ompvm'
+ 'description': 'ompvm'
},
{
'volumn_storages': [
],
'nfv_compute': {
'mem_size': '',
- 'num_cpus': u'4'
+ 'num_cpus': '4'
},
'local_storages': [
],
- 'vdu_id': u'vdu_10',
- 'image_file': u'sss',
+ 'vdu_id': 'vdu_10',
+ 'image_file': 'sss',
'dependencies': [
],
'local_affinity_antiaffinity_rule': {
},
- 'template_id': u'10',
+ 'template_id': '10',
'manual_scale_select_vim': False
},
- 'description': u'ppvm'
+ 'description': 'ppvm'
},
{
'volumn_storages': [
],
'nfv_compute': {
'mem_size': '',
- 'num_cpus': u'14'
+ 'num_cpus': '14'
},
'local_storages': [
],
- 'vdu_id': u'vdu_11',
- 'image_file': u'sss',
+ 'vdu_id': 'vdu_11',
+ 'image_file': 'sss',
'dependencies': [
],
'local_affinity_antiaffinity_rule': {
},
- 'template_id': u'11',
+ 'template_id': '11',
'manual_scale_select_vim': False
},
- 'description': u'ppvm'
+ 'description': 'ppvm'
},
{
'volumn_storages': [
],
'nfv_compute': {
'mem_size': '',
- 'num_cpus': u'14'
+ 'num_cpus': '14'
},
'local_storages': [
],
- 'vdu_id': u'vdu_12',
- 'image_file': u'sss',
+ 'vdu_id': 'vdu_12',
+ 'image_file': 'sss',
'dependencies': [
],
'local_affinity_antiaffinity_rule': {
},
- 'template_id': u'12',
+ 'template_id': '12',
'manual_scale_select_vim': False
},
- 'description': u'ppvm'
+ 'description': 'ppvm'
}
],
'volumn_storages': [
'targets': {
},
- 'policy_id': u'policy_scale_sss-vnf-template',
+ 'policy_id': 'policy_scale_sss-vnf-template',
'properties': {
'policy_file': '*-vnfd.zip/*-vnf-policy.xml'
},
{
'description': '',
'properties': {
- 'name': u'opencos_sss_omm_img_release_20150723-1-disk1.vmdk',
+ 'name': 'opencos_sss_omm_img_release_20150723-1-disk1.vmdk',
'checksum': '',
- 'disk_format': u'VMDK',
- 'file_url': u'./zte-cn-sss-main-image/OMM/opencos_sss_omm_img_release_20150723-1-disk1.vmdk',
+ 'disk_format': 'VMDK',
+ 'file_url': './zte-cn-sss-main-image/OMM/opencos_sss_omm_img_release_20150723-1-disk1.vmdk',
'container_type': 'vm',
'version': '',
'hypervisor_type': 'kvm'
},
- 'image_file_id': u'opencos_sss_omm_img_release_20150723-1-disk1'
+ 'image_file_id': 'opencos_sss_omm_img_release_20150723-1-disk1'
},
{
'description': '',
'properties': {
- 'name': u'sss.vmdk',
+ 'name': 'sss.vmdk',
'checksum': '',
- 'disk_format': u'VMDK',
- 'file_url': u'./zte-cn-sss-main-image/NE/sss.vmdk',
+ 'disk_format': 'VMDK',
+ 'file_url': './zte-cn-sss-main-image/NE/sss.vmdk',
'container_type': 'vm',
'version': '',
'hypervisor_type': 'kvm'
},
- 'image_file_id': u'sss'
+ 'image_file_id': 'sss'
}
],
'vls': [
],
'metadata': {
- 'vendor': u'zte',
+ 'vendor': 'zte',
'is_shared': False,
'description': '',
- 'domain_type': u'CN',
- 'version': u'v4.14.10',
+ 'domain_type': 'CN',
+ 'version': 'v4.14.10',
'vmnumber_overquota_alarm': False,
'cross_dc': False,
- 'vnf_type': u'SSS',
- 'vnfd_version': u'V00000001',
- 'id': u'sss-vnf-template',
- 'name': u'sss-vnf-template'
+ 'vnf_type': 'SSS',
+ 'vnfd_version': 'V00000001',
+ 'id': 'sss-vnf-template',
+ 'name': 'sss-vnf-template'
}
}
},
"imageInfo": []
}
+
+vnf_place_request = {
+ "requestId": "1234",
+ "transactionId": "1234",
+ "statusMessage": "xx",
+ "requestStatus": "completed",
+ "solutions": {
+ "placementSolutions": [
+ [
+ {
+ "resourceModuleName": "vG",
+ "serviceResourceId": "1234",
+ "solution": {
+ "identifierType": "serviceInstanceId",
+ "identifiers": [
+ "xx"
+ ],
+ "cloudOwner": "CloudOwner1"
+ },
+ "assignmentInfo": [
+ {"key": "isRehome",
+ "value": "false"
+ },
+ {"key": "locationId",
+ "value": "DLLSTX1A"
+ },
+ {"key": "locationType",
+ "value": "openstack-cloud"
+ },
+ {"key": "vimId",
+ "value": "CloudOwner1_DLLSTX1A"
+ },
+ {"key": "physicalLocationId",
+ "value": "DLLSTX1223"
+ },
+ {"key": "oof_directives",
+ "value": {
+ "directives": [
+ {
+ "id": "vG_0",
+ "type": "tosca.nodes.nfv.Vdu.Compute",
+ "directives": [
+ {
+ "type": "flavor_directives",
+ "attributes": [
+ {
+ "attribute_name": "flavorName",
+ "attribute_value": "HPA.flavor.1"
+ },
+ {
+ "attribute_name": "flavorId",
+ "attribute_value": "12345"
+ },
+ ]
+ }
+ ]
+ },
+ {
+ "id": "",
+ "type": "vnf",
+ "directives": [
+ {"type": " ",
+ "attributes": [
+ {
+ "attribute_name": " ",
+ "attribute_value": " "
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ ],
+ "licenseSolutions": [
+ {
+ "resourceModuleName": "string",
+ "serviceResourceId": "string",
+ "entitlementPoolUUID": [
+ "string"
+ ],
+ "licenseKeyGroupUUID": [
+ "string"
+ ],
+ "entitlementPoolInvariantUUID": [
+ "string"
+ ],
+ "licenseKeyGroupInvariantUUID": [
+ "string"
+ ]
+ }
+ ]
+ }
+}