Enhancement of get VNF LCM operation occurrence
- Added support for getting Individual VNF LCM operation occurrence by its ID - The query information is enhanced by improving filtering expressions and operators - Attributes are also added including (but not limited to): * grant_id * _links * >retry * >fail * changedExtConnectivity - This patch has 2 BP features (Get VNFM LCM Operation Occurence and attributes of Change External Connectivity are also added). Since both features are related, they are merged to one patch. This is why this patch have 2 BPs. - Filtering for the following attributes: operationParams, error, resourceChanges and changedInfo is only limited to the parent attribute. Currently, child attributes/nested attributes are not searchable. Implements: blueprint support-fundamental-lcm Implements: blueprint support-change-external-connectivity Spec: https://specs.openstack.org/openstack/tacker-specs/specs/wallaby/support-fundamental-vnf-lcm-based-on-ETSI-NFV.html Spec: https://specs.openstack.org/openstack/tacker-specs/specs/wallaby/support-change-external-VNF-connectivity-operation.html Change-Id: Ie9b07c203807d08857be65298d9128b026a8fd37
This commit is contained in:
parent
3717b4ee1a
commit
87ea725784
@ -0,0 +1,82 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "d85c6ae4-af16-42c0-96fc-82f7c014c468",
|
||||||
|
"operationState": "COMPLETED",
|
||||||
|
"stateEnteredTime": "2020-08-02T06:50:50.883373",
|
||||||
|
"startTime": "2020-08-02T06:41:34.883483",
|
||||||
|
"vnfInstanceId": "0b7b95a9-21d5-4ac4-80c8-9ae9f7323787",
|
||||||
|
"grantId": "3432cebe-db0a-11e8-9023-005056317abe",
|
||||||
|
"operation": "INSTANTIATE",
|
||||||
|
"isAutomaticInvocation": false,
|
||||||
|
"operationParams": "{
|
||||||
|
'flavourId': 'default',
|
||||||
|
'instantiationLevelId': 'vnf-min',
|
||||||
|
}",
|
||||||
|
"isCancelPending": false,
|
||||||
|
"resourceChanges": {
|
||||||
|
"affectedVnfcs": [
|
||||||
|
{
|
||||||
|
"id": "36e24439-829c-4803-a413-385cd658d544",
|
||||||
|
"vduId": "VDU",
|
||||||
|
"changeType": "ADDED",
|
||||||
|
"computeResource": {
|
||||||
|
"vimConnectionId": "f26f181d-7891-4720-b022-b074ec1733ef",
|
||||||
|
"resourceId": "e0510ba9-3a53-4fcf-9dcc-58dea5c048b0",
|
||||||
|
"vimLevelResourceType": "OS::Nova::Server",
|
||||||
|
},
|
||||||
|
"affectedVnfcCpIds": [
|
||||||
|
"VDU1_CP0",
|
||||||
|
"VDU1_CP1"
|
||||||
|
],
|
||||||
|
"addedStorageResourceIds": [
|
||||||
|
"81ae44f6-b65b-47aa-a578-e53b7a50a574"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"affectedVirtualLinks": [
|
||||||
|
{
|
||||||
|
"id": "9836f7f2-5af4-4df5-a89f-933479448ef7",
|
||||||
|
"vnfVirtualLinkDescId": "internalNW",
|
||||||
|
"changeType": "ADDED",
|
||||||
|
"networkResource": {
|
||||||
|
"vimConnectionId": "f26f181d-7891-4720-b022-b074ec1733ef",
|
||||||
|
"resourceId": "400692e5-b2db-478e-acb1-b77a92635ec6",
|
||||||
|
"vimLevelResourceType": "OS::Neutron::Net"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"affectedVirtualStorages": [
|
||||||
|
{
|
||||||
|
"id": "81ae44f6-b65b-47aa-a578-e53b7a50a574",
|
||||||
|
"virtualStorageDescId": "Storage",
|
||||||
|
"changeType": "ADDED",
|
||||||
|
"storageResource": {
|
||||||
|
"vimConnectionId": "f26f181d-7891-4720-b022-b074ec1733ef",
|
||||||
|
"resourceId": "842f527e-0092-4f11-aede-f981ba4fd884",
|
||||||
|
"vimLevelResourceType": "OS::Cinder::Volume"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"_links": {
|
||||||
|
"self": {
|
||||||
|
"href": "http://sample.com/vnflcm/v1/vnf_lcm_op_occs/d85c6ae4-af16-42c0-96fc-82f7c014c468"
|
||||||
|
},
|
||||||
|
"vnfInstance": {
|
||||||
|
"href": "http://sample.com/vnflcm/v1/vnf_instances/0b7b95a9-21d5-4ac4-80c8-9ae9f7323787"
|
||||||
|
},
|
||||||
|
"grant":{
|
||||||
|
"href":"http://sample.com/grant/v1/grants/3432cebe-db0a-11e8-9023-005056317abe"
|
||||||
|
},
|
||||||
|
"retry":{
|
||||||
|
"href":"http://sample1.com/vnflcm/v1/vnf_lcm_op_occs/d85c6ae4-af16-42c0-96fc-82f7c014c468/retry"
|
||||||
|
},
|
||||||
|
"rollback":{
|
||||||
|
"href":"http://sample1.com/vnflcm/v1/vnf_lcm_op_occs/d85c6ae4-af16-42c0-96fc-82f7c014c468/rollback"
|
||||||
|
},
|
||||||
|
"fail":{
|
||||||
|
"href":"http://sample1.com/vnflcm/v1/vnf_lcm_op_occs/d85c6ae4-af16-42c0-96fc-82f7c014c468/fail"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -4,6 +4,7 @@
|
|||||||
"stateEnteredTime": "2020-08-02T06:50:50.883373",
|
"stateEnteredTime": "2020-08-02T06:50:50.883373",
|
||||||
"startTime": "2020-08-02T06:41:34.883483",
|
"startTime": "2020-08-02T06:41:34.883483",
|
||||||
"vnfInstanceId": "0b7b95a9-21d5-4ac4-80c8-9ae9f7323787",
|
"vnfInstanceId": "0b7b95a9-21d5-4ac4-80c8-9ae9f7323787",
|
||||||
|
"grantId": "3432cebe-db0a-11e8-9023-005056317abe",
|
||||||
"operation": "INSTANTIATE",
|
"operation": "INSTANTIATE",
|
||||||
"isAutomaticInvocation": false,
|
"isAutomaticInvocation": false,
|
||||||
"operationParams": "{
|
"operationParams": "{
|
||||||
@ -65,6 +66,15 @@
|
|||||||
},
|
},
|
||||||
"grant": {
|
"grant": {
|
||||||
"href": "/grant/v1/grants/3432cebe-db0a-11e8-9023-005056317abe"
|
"href": "/grant/v1/grants/3432cebe-db0a-11e8-9023-005056317abe"
|
||||||
|
},
|
||||||
|
"retry":{
|
||||||
|
"href":"http://sample1.com/vnflcm/v1/vnf_lcm_op_occs/d85c6ae4-af16-42c0-96fc-82f7c014c468/retry"
|
||||||
|
},
|
||||||
|
"rollback":{
|
||||||
|
"href":"http://sample1.com/vnflcm/v1/vnf_lcm_op_occs/d85c6ae4-af16-42c0-96fc-82f7c014c468/rollback"
|
||||||
|
},
|
||||||
|
"fail":{
|
||||||
|
"href":"http://sample1.com/vnflcm/v1/vnf_lcm_op_occs/d85c6ae4-af16-42c0-96fc-82f7c014c468/fail"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -712,6 +712,116 @@ Response Parameters
|
|||||||
- stateEnteredTime: state_entered_time
|
- stateEnteredTime: state_entered_time
|
||||||
- startTime: start_time
|
- startTime: start_time
|
||||||
- vnfInstanceId: vnf_lcm_vnf_instance_id
|
- vnfInstanceId: vnf_lcm_vnf_instance_id
|
||||||
|
- grantId: grant_id
|
||||||
|
- operation: operation
|
||||||
|
- isAutomaticInvocation: is_automatic_invocation
|
||||||
|
- operationParams: operation_params
|
||||||
|
- isCancelPending: is_cancel_pending
|
||||||
|
- error: error
|
||||||
|
- title: error_title
|
||||||
|
- status: error_status
|
||||||
|
- detail: error_detail
|
||||||
|
- resourceChanges: resource_changes
|
||||||
|
- affectedVnfcs: affected_vnfcs
|
||||||
|
- id: affected_vnfcs_id
|
||||||
|
- vduId: affected_vnfcs_vdu_id
|
||||||
|
- changeType: affected_vnfcs_change_type
|
||||||
|
- computeResource: vnfc_resource_info_compute_resource
|
||||||
|
- vimConnectionId: vim_connection_id
|
||||||
|
- resourceId: resource_handle_resource_id
|
||||||
|
- vimLevelResourceType: resource_handle_vim_level_resource_type
|
||||||
|
- affectedVnfcCpIds: affected_vnfc_cp_ids
|
||||||
|
- addedStorageResourceIds: added_storage_resource_ids
|
||||||
|
- removedStorageResourceIds: removed_storage_resource_ids
|
||||||
|
- affectedVirtualLinks: affected_virtual_links
|
||||||
|
- id: affected_virtual_links_id
|
||||||
|
- vnfVirtualLinkDescId: vnf_virtual_link_resource_info_vnf_virtual_link_desc_id
|
||||||
|
- changeType: affected_virtual_links_change_type
|
||||||
|
- networkResource: vnf_virtual_link_resource_info_network_resource
|
||||||
|
- vimConnectionId: vim_connection_id
|
||||||
|
- resourceId: resource_handle_resource_id
|
||||||
|
- vimLevelResourceType: resource_handle_vim_level_resource_type
|
||||||
|
- affectedVirtualStorages: affected_virtual_storages
|
||||||
|
- id: affected_virtual_storages_id
|
||||||
|
- virtualStorageDescId: affected_virtual_storages_virtual_storage_desc_id
|
||||||
|
- changeType: affected_virtual_storages_change_type
|
||||||
|
- storageResource: virtual_storage_resource_info_storage_resource
|
||||||
|
- vimConnectionId: vim_connection_id
|
||||||
|
- resourceId: resource_handle_resource_id
|
||||||
|
- vimLevelResourceType: resource_handle_vim_level_resource_type
|
||||||
|
- changedInfo: changed_info
|
||||||
|
- vnfInstanceName: changed_info_vnf_instance_name
|
||||||
|
- vnfInstanceDescription: changed_info_vnf_instance_description
|
||||||
|
- metadata: changed_info_metadata
|
||||||
|
- vimConnectionInfo: changed_info_vim_connection_info
|
||||||
|
- id: vim_connection_info_id
|
||||||
|
- vimId: vim_connection_info_vim_id
|
||||||
|
- vimType: vim_connection_info_vim_type
|
||||||
|
- interfaceInfo: vim_connection_info_interface_info
|
||||||
|
- endpoint: vim_connection_info_interface_info_endpoint
|
||||||
|
- accessInfo: vim_connection_info_access_info
|
||||||
|
- username: vim_connection_info_access_info_username
|
||||||
|
- region: vim_connection_info_access_info_region
|
||||||
|
- password: vim_connection_info_access_info_password
|
||||||
|
- tenant: vim_connection_info_access_info_tenant
|
||||||
|
- vnfPkgId: changed_info_vnf_pkg_id
|
||||||
|
- vnfdId: changed_info_vnfd_id
|
||||||
|
- vnfProvider: changed_info_vnf_provider
|
||||||
|
- vnfProductName: changed_info_vnf_product_name
|
||||||
|
- vnfSotwareVersion: changed_info_vnf_sotware_version
|
||||||
|
- vnfdVersion: changed_info_vnfd_version
|
||||||
|
- changedExtConnectivity: changed_ext_connectivity
|
||||||
|
- id: changed_ext_connectivity_id
|
||||||
|
- resourceHandle: resource_handle
|
||||||
|
- vimConnectionId: vim_connection_id
|
||||||
|
- resourceId: resource_handle_resource_id
|
||||||
|
- vimLevelResourceType: resource_handle_vim_level_resource_type
|
||||||
|
- extLinkPorts: ext_link_ports
|
||||||
|
- id: ext_link_port_id
|
||||||
|
- resourceHandle: resource_handle
|
||||||
|
- vimConnectionId: vim_connection_id
|
||||||
|
- resourceId: resource_handle_resource_id
|
||||||
|
- vimLevelResourceType: resource_handle_vim_level_resource_type
|
||||||
|
- cpInstanceId: cp_instance_id
|
||||||
|
- _links: vnf_instance_links
|
||||||
|
|
||||||
|
Response Example
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/vnflcm/show-vnflcm-operation-occurrence-response.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
List VNF LCM operation occurrence
|
||||||
|
=================================
|
||||||
|
|
||||||
|
.. rest_method:: GET /vnflcm/v1/vnf_lcm_op_occs
|
||||||
|
|
||||||
|
The API consumer can use this method to query status information about multiple VNF lifecycle management operation
|
||||||
|
occurrences.
|
||||||
|
|
||||||
|
Response Codes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. rest_status_code:: success status.yaml
|
||||||
|
|
||||||
|
- 200
|
||||||
|
|
||||||
|
.. rest_status_code:: error status.yaml
|
||||||
|
|
||||||
|
- 400
|
||||||
|
- 403
|
||||||
|
|
||||||
|
Response Parameters
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters_vnflcm.yaml
|
||||||
|
|
||||||
|
- id: vnf_lcm_op_occ_id_response
|
||||||
|
- operationState: operation_state
|
||||||
|
- stateEnteredTime: state_entered_time
|
||||||
|
- startTime: start_time
|
||||||
|
- vnfInstanceId: vnf_lcm_vnf_instance_id
|
||||||
|
- grantId: grant_id
|
||||||
- operation: operation
|
- operation: operation
|
||||||
- isAutomaticInvocation: is_automatic_invocation
|
- isAutomaticInvocation: is_automatic_invocation
|
||||||
- operationParams: operation_params
|
- operationParams: operation_params
|
||||||
@ -774,7 +884,7 @@ Response Parameters
|
|||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
.. literalinclude:: samples/vnflcm/show-vnflcm-operation-occurrence-response.json
|
.. literalinclude:: samples/vnflcm/list-vnflcm-operation-occurrence-response.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
|
||||||
Roll back a VNF lifecycle operation
|
Roll back a VNF lifecycle operation
|
||||||
|
@ -163,6 +163,18 @@ def _parse_filter(filter_rule):
|
|||||||
try:
|
try:
|
||||||
tokens = filter_rule.split(',')
|
tokens = filter_rule.split(',')
|
||||||
filter_type = None
|
filter_type = None
|
||||||
|
|
||||||
|
# TODO(esto-aln): This condition and the lines below will be removed
|
||||||
|
# if JSON will be supported via OR Mapping. Currently this condition
|
||||||
|
# allows support of JSON strings '"{...}"' for filtering
|
||||||
|
if (tokens[2].startswith("'\"{") and
|
||||||
|
tokens[len(tokens) - 1].endswith("}\"'")):
|
||||||
|
tokens[2] = ','.join(tokens[2:])
|
||||||
|
|
||||||
|
# retain first 3 indices and remove the rest
|
||||||
|
# to process as string
|
||||||
|
tokens = tokens[0:3]
|
||||||
|
|
||||||
if len(tokens) >= 3:
|
if len(tokens) >= 3:
|
||||||
if tokens[0] in _filters.SUPPORTED_OP_ONE:
|
if tokens[0] in _filters.SUPPORTED_OP_ONE:
|
||||||
filter_type = 'simple_filter_expr_one'
|
filter_type = 'simple_filter_expr_one'
|
||||||
|
@ -89,6 +89,8 @@ class ViewBuilder(base.BaseViewBuilder):
|
|||||||
|
|
||||||
return vim_connections
|
return vim_connections
|
||||||
|
|
||||||
|
# TODO(esto-aln): This method will be transferred to
|
||||||
|
# tacker/api/views/vnf_lcm_op_occs.py in the future
|
||||||
def _get_lcm_op_occs_links(self, vnf_lcm_op_occs):
|
def _get_lcm_op_occs_links(self, vnf_lcm_op_occs):
|
||||||
_links = {
|
_links = {
|
||||||
"self": {
|
"self": {
|
||||||
@ -101,6 +103,12 @@ class ViewBuilder(base.BaseViewBuilder):
|
|||||||
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
||||||
"id": vnf_lcm_op_occs.vnf_instance_id}
|
"id": vnf_lcm_op_occs.vnf_instance_id}
|
||||||
},
|
},
|
||||||
|
"retry": {
|
||||||
|
"href":
|
||||||
|
'%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s/retry'
|
||||||
|
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
||||||
|
"id": vnf_lcm_op_occs.id}
|
||||||
|
},
|
||||||
"rollback": {
|
"rollback": {
|
||||||
"href":
|
"href":
|
||||||
'%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s/rollback'
|
'%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s/rollback'
|
||||||
@ -111,6 +119,12 @@ class ViewBuilder(base.BaseViewBuilder):
|
|||||||
"href": '%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s/grant'
|
"href": '%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s/grant'
|
||||||
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
||||||
"id": vnf_lcm_op_occs.id}
|
"id": vnf_lcm_op_occs.id}
|
||||||
|
},
|
||||||
|
"fail": {
|
||||||
|
"href":
|
||||||
|
'%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s/fail'
|
||||||
|
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
||||||
|
"id": vnf_lcm_op_occs.id}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,11 +143,13 @@ class ViewBuilder(base.BaseViewBuilder):
|
|||||||
vnf_instance_dict.update(links)
|
vnf_instance_dict.update(links)
|
||||||
return vnf_instance_dict
|
return vnf_instance_dict
|
||||||
|
|
||||||
|
# TODO(esto-aln): This method will be transferred to
|
||||||
|
# tacker/api/views/vnf_lcm_op_occs.py in the future
|
||||||
def _get_vnf_lcm_op_occs(self, vnf_lcm_op_occs):
|
def _get_vnf_lcm_op_occs(self, vnf_lcm_op_occs):
|
||||||
vnf_lcm_op_occs_dict = vnf_lcm_op_occs.to_dict()
|
vnf_lcm_op_occs_dict = vnf_lcm_op_occs.to_dict()
|
||||||
vnf_lcm_op_occs_dict.pop('error_point')
|
|
||||||
vnf_lcm_op_occs_dict = utils.convert_snakecase_to_camelcase(
|
vnf_lcm_op_occs_dict = utils.convert_snakecase_to_camelcase(
|
||||||
vnf_lcm_op_occs_dict)
|
vnf_lcm_op_occs_dict)
|
||||||
|
vnf_lcm_op_occs_dict.pop('errorPoint')
|
||||||
|
|
||||||
links = self._get_lcm_op_occs_links(vnf_lcm_op_occs)
|
links = self._get_lcm_op_occs_links(vnf_lcm_op_occs)
|
||||||
|
|
||||||
@ -257,5 +273,7 @@ class ViewBuilder(base.BaseViewBuilder):
|
|||||||
def subscription_show(self, vnf_lcm_subscriptions):
|
def subscription_show(self, vnf_lcm_subscriptions):
|
||||||
return self._get_vnf_lcm_subscription(vnf_lcm_subscriptions)
|
return self._get_vnf_lcm_subscription(vnf_lcm_subscriptions)
|
||||||
|
|
||||||
|
# TODO(esto-aln): This method will be transferred to
|
||||||
|
# tacker/api/views/vnf_lcm_op_occs.py in the future
|
||||||
def show_lcm_op_occs(self, vnf_lcm_op_occs):
|
def show_lcm_op_occs(self, vnf_lcm_op_occs):
|
||||||
return self._get_vnf_lcm_op_occs(vnf_lcm_op_occs)
|
return self._get_vnf_lcm_op_occs(vnf_lcm_op_occs)
|
||||||
|
118
tacker/api/views/vnf_lcm_op_occs.py
Normal file
118
tacker/api/views/vnf_lcm_op_occs.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from tacker.api import views as base
|
||||||
|
from tacker.common import utils
|
||||||
|
import tacker.conf
|
||||||
|
from tacker.objects import vnf_lcm_op_occs as _vnf_lcm_op_occs
|
||||||
|
|
||||||
|
CONF = tacker.conf.CONF
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ViewBuilder(base.BaseViewBuilder):
|
||||||
|
|
||||||
|
FLATTEN_ATTRIBUTES = _vnf_lcm_op_occs.VnfLcmOpOcc.FLATTEN_ATTRIBUTES
|
||||||
|
COMPLEX_ATTRIBUTES = _vnf_lcm_op_occs.VnfLcmOpOcc.COMPLEX_ATTRIBUTES
|
||||||
|
FLATTEN_COMPLEX_ATTRIBUTES = [key for key in FLATTEN_ATTRIBUTES.keys()
|
||||||
|
if '/' in key]
|
||||||
|
|
||||||
|
def _get_lcm_op_occs_links(self, vnf_lcm_op_occs):
|
||||||
|
_links = {
|
||||||
|
"self": {
|
||||||
|
"href": '%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s'
|
||||||
|
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
||||||
|
"id": vnf_lcm_op_occs.id}
|
||||||
|
},
|
||||||
|
"vnfInstance": {
|
||||||
|
"href": '%(endpoint)s/vnflcm/v1/vnf_instances/%(id)s'
|
||||||
|
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
||||||
|
"id": vnf_lcm_op_occs.vnf_instance_id}
|
||||||
|
},
|
||||||
|
"retry": {
|
||||||
|
"href":
|
||||||
|
'%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s/retry'
|
||||||
|
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
||||||
|
"id": vnf_lcm_op_occs.id}
|
||||||
|
},
|
||||||
|
"rollback": {
|
||||||
|
"href":
|
||||||
|
'%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s/rollback'
|
||||||
|
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
||||||
|
"id": vnf_lcm_op_occs.id}
|
||||||
|
},
|
||||||
|
"grant": {
|
||||||
|
"href": '%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s/grant'
|
||||||
|
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
||||||
|
"id": vnf_lcm_op_occs.id}
|
||||||
|
},
|
||||||
|
"fail": {
|
||||||
|
"href":
|
||||||
|
'%(endpoint)s/vnflcm/v1/vnf_lcm_op_occs/%(id)s/fail'
|
||||||
|
% {"endpoint": CONF.vnf_lcm.endpoint_url,
|
||||||
|
"id": vnf_lcm_op_occs.id}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {"_links": _links}
|
||||||
|
|
||||||
|
def _get_vnf_lcm_op_occs_list(self, vnf_lcm_op_occs, include_fields=None):
|
||||||
|
vnf_lcm_op_occs_dict = vnf_lcm_op_occs.to_dict(
|
||||||
|
include_fields=include_fields)
|
||||||
|
|
||||||
|
vnf_lcm_op_occs_dict = utils.convert_snakecase_to_camelcase(
|
||||||
|
vnf_lcm_op_occs_dict)
|
||||||
|
vnf_lcm_op_occs_dict.pop('errorPoint', None)
|
||||||
|
|
||||||
|
links = self._get_lcm_op_occs_links(vnf_lcm_op_occs)
|
||||||
|
|
||||||
|
vnf_lcm_op_occs_dict.update(links)
|
||||||
|
return vnf_lcm_op_occs_dict
|
||||||
|
|
||||||
|
def index(self, request, vnf_lcm_op_occs, all_fields=True,
|
||||||
|
exclude_fields=None, fields=None, exclude_default=False):
|
||||||
|
|
||||||
|
# Find out which fields are to be returned in the response.
|
||||||
|
if all_fields:
|
||||||
|
include_fields = set(self.FLATTEN_ATTRIBUTES.keys())
|
||||||
|
if fields:
|
||||||
|
fields = set(fields.split(','))
|
||||||
|
attributes = set(self.COMPLEX_ATTRIBUTES).intersection(fields)
|
||||||
|
for attribute in attributes:
|
||||||
|
add_fields = set([key for key in self.FLATTEN_ATTRIBUTES.
|
||||||
|
keys() if key.startswith(attribute)])
|
||||||
|
fields = fields.union(add_fields)
|
||||||
|
|
||||||
|
include_fields = set(
|
||||||
|
_vnf_lcm_op_occs.VnfLcmOpOcc.SIMPLE_ATTRIBUTES).union(fields)
|
||||||
|
elif exclude_default:
|
||||||
|
include_fields = set(
|
||||||
|
_vnf_lcm_op_occs.VnfLcmOpOcc.SIMPLE_ATTRIBUTES)
|
||||||
|
elif exclude_fields:
|
||||||
|
exclude_fields = set(exclude_fields.split(','))
|
||||||
|
exclude_additional_attributes = set(
|
||||||
|
self.COMPLEX_ATTRIBUTES).intersection(exclude_fields)
|
||||||
|
for attribute in exclude_additional_attributes:
|
||||||
|
fields = set([key for key in self.FLATTEN_ATTRIBUTES.keys()
|
||||||
|
if key.startswith(attribute)])
|
||||||
|
exclude_fields = exclude_fields.union(fields)
|
||||||
|
|
||||||
|
include_fields = set(self.FLATTEN_ATTRIBUTES.keys()) - \
|
||||||
|
exclude_fields
|
||||||
|
|
||||||
|
return [
|
||||||
|
self._get_vnf_lcm_op_occs_list(
|
||||||
|
vnf_lcm_op_occ, include_fields=include_fields)
|
||||||
|
for vnf_lcm_op_occ in vnf_lcm_op_occs]
|
@ -42,6 +42,7 @@ from tacker._i18n import _
|
|||||||
from tacker.api.schemas import vnf_lcm
|
from tacker.api.schemas import vnf_lcm
|
||||||
from tacker.api import validation
|
from tacker.api import validation
|
||||||
from tacker.api.views import vnf_lcm as vnf_lcm_view
|
from tacker.api.views import vnf_lcm as vnf_lcm_view
|
||||||
|
from tacker.api.views import vnf_lcm_op_occs as vnf_op_occs_view
|
||||||
from tacker.api.vnflcm.v1 import sync_resource
|
from tacker.api.vnflcm.v1 import sync_resource
|
||||||
from tacker.common import exceptions
|
from tacker.common import exceptions
|
||||||
from tacker.common import utils
|
from tacker.common import utils
|
||||||
@ -52,6 +53,7 @@ from tacker.extensions import vnfm
|
|||||||
from tacker import manager
|
from tacker import manager
|
||||||
from tacker import objects
|
from tacker import objects
|
||||||
from tacker.objects import fields
|
from tacker.objects import fields
|
||||||
|
from tacker.objects import vnf_lcm_op_occs as vnf_lcm_op_occs_obj
|
||||||
from tacker.objects import vnf_lcm_subscriptions as subscription_obj
|
from tacker.objects import vnf_lcm_subscriptions as subscription_obj
|
||||||
from tacker.plugins.common import constants
|
from tacker.plugins.common import constants
|
||||||
from tacker.policies import vnf_lcm as vnf_lcm_policies
|
from tacker.policies import vnf_lcm as vnf_lcm_policies
|
||||||
@ -185,6 +187,7 @@ class VnfLcmController(wsgi.Controller):
|
|||||||
super(VnfLcmController, self).__init__()
|
super(VnfLcmController, self).__init__()
|
||||||
self.rpc_api = vnf_lcm_rpc.VNFLcmRPCAPI()
|
self.rpc_api = vnf_lcm_rpc.VNFLcmRPCAPI()
|
||||||
self._vnfm_plugin = manager.TackerManager.get_service_plugins()['VNFM']
|
self._vnfm_plugin = manager.TackerManager.get_service_plugins()['VNFM']
|
||||||
|
self._view_builder_op_occ = vnf_op_occs_view.ViewBuilder()
|
||||||
|
|
||||||
def _get_vnf_instance_href(self, vnf_instance):
|
def _get_vnf_instance_href(self, vnf_instance):
|
||||||
return '/vnflcm/v1/vnf_instances/%s' % vnf_instance.id
|
return '/vnflcm/v1/vnf_instances/%s' % vnf_instance.id
|
||||||
@ -1503,6 +1506,40 @@ class VnfLcmController(wsgi.Controller):
|
|||||||
return self._make_problem_detail(error_msg,
|
return self._make_problem_detail(error_msg,
|
||||||
500, title='Internal Server Error')
|
500, title='Internal Server Error')
|
||||||
|
|
||||||
|
@wsgi.response(http_client.OK)
|
||||||
|
@wsgi.expected_errors((http_client.FORBIDDEN, http_client.BAD_REQUEST))
|
||||||
|
def list_lcm_op_occs(self, request):
|
||||||
|
context = request.environ['tacker.context']
|
||||||
|
context.can(vnf_lcm_policies.VNFLCM % 'list_lcm_op_occs')
|
||||||
|
|
||||||
|
all_fields = request.GET.get('all_fields')
|
||||||
|
exclude_default = request.GET.get('exclude_default')
|
||||||
|
fields = request.GET.get('fields')
|
||||||
|
exclude_fields = request.GET.get('exclude_fields')
|
||||||
|
filters = request.GET.get('filter')
|
||||||
|
if not (all_fields or fields or exclude_fields):
|
||||||
|
exclude_default = True
|
||||||
|
|
||||||
|
self._view_builder_op_occ.validate_attribute_fields(
|
||||||
|
all_fields=all_fields, fields=fields,
|
||||||
|
exclude_fields=exclude_fields,
|
||||||
|
exclude_default=exclude_default)
|
||||||
|
|
||||||
|
filters = self._view_builder_op_occ.validate_filter(filters)
|
||||||
|
|
||||||
|
try:
|
||||||
|
vnf_lcm_op_occs = \
|
||||||
|
vnf_lcm_op_occs_obj.VnfLcmOpOccList.get_by_filters(
|
||||||
|
request.context, read_deleted='no', filters=filters)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.exception(traceback.format_exc())
|
||||||
|
return self._make_problem_detail(
|
||||||
|
str(e), 500, title='Internal Server Error')
|
||||||
|
|
||||||
|
return self._view_builder_op_occ.index(request, vnf_lcm_op_occs,
|
||||||
|
all_fields=all_fields, exclude_fields=exclude_fields,
|
||||||
|
fields=fields, exclude_default=exclude_default)
|
||||||
|
|
||||||
def _make_problem_detail(
|
def _make_problem_detail(
|
||||||
self,
|
self,
|
||||||
detail,
|
detail,
|
||||||
|
@ -138,3 +138,15 @@ class VnflcmAPIRouter(wsgi.Router):
|
|||||||
methods = {"GET": "subscription_show", "DELETE": "delete_subscription"}
|
methods = {"GET": "subscription_show", "DELETE": "delete_subscription"}
|
||||||
self._setup_route(mapper, "/subscriptions/{subscriptionId}",
|
self._setup_route(mapper, "/subscriptions/{subscriptionId}",
|
||||||
methods, controller, default_resource)
|
methods, controller, default_resource)
|
||||||
|
|
||||||
|
# {apiRoot}/vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/retry resource
|
||||||
|
methods = {"POST": "retry"}
|
||||||
|
self._setup_route(mapper,
|
||||||
|
"/vnf_lcm_op_occs/{id}/retry",
|
||||||
|
methods, controller, default_resource)
|
||||||
|
|
||||||
|
# Allowed methods on
|
||||||
|
# {apiRoot}/vnflcm/v1/vnf_lcm_op_occs resource
|
||||||
|
methods = {"GET": "list_lcm_op_occs"}
|
||||||
|
self._setup_route(mapper, "/vnf_lcm_op_occs",
|
||||||
|
methods, controller, default_resource)
|
||||||
|
@ -305,6 +305,7 @@ class VnfLcmOpOccs(model_base.BASE, models.SoftDeleteMixin,
|
|||||||
vnf_instance_id = sa.Column(sa.String(36),
|
vnf_instance_id = sa.Column(sa.String(36),
|
||||||
sa.ForeignKey('vnf_instances.id'),
|
sa.ForeignKey('vnf_instances.id'),
|
||||||
nullable=False)
|
nullable=False)
|
||||||
|
grant_id = sa.Column(sa.String(36), nullable=True)
|
||||||
state_entered_time = sa.Column(sa.DateTime(), nullable=False)
|
state_entered_time = sa.Column(sa.DateTime(), nullable=False)
|
||||||
start_time = sa.Column(sa.DateTime(), nullable=False)
|
start_time = sa.Column(sa.DateTime(), nullable=False)
|
||||||
operation_state = sa.Column(sa.String(length=255), nullable=False)
|
operation_state = sa.Column(sa.String(length=255), nullable=False)
|
||||||
@ -315,6 +316,7 @@ class VnfLcmOpOccs(model_base.BASE, models.SoftDeleteMixin,
|
|||||||
error = sa.Column(sa.JSON(), nullable=True)
|
error = sa.Column(sa.JSON(), nullable=True)
|
||||||
resource_changes = sa.Column(sa.JSON(), nullable=True)
|
resource_changes = sa.Column(sa.JSON(), nullable=True)
|
||||||
changed_info = sa.Column(sa.JSON(), nullable=True)
|
changed_info = sa.Column(sa.JSON(), nullable=True)
|
||||||
|
changed_ext_connectivity = sa.Column(sa.JSON(), nullable=True)
|
||||||
error_point = sa.Column(sa.Integer, nullable=False)
|
error_point = sa.Column(sa.Integer, nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
# flake8: noqa: E402
|
||||||
|
|
||||||
|
"""add_column_to_vnf_lcm_op_occs
|
||||||
|
|
||||||
|
Revision ID: 3adac34764da
|
||||||
|
Revises: 62d18199909e
|
||||||
|
Create Date: 2021-02-16 16:19:12.100380
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '3adac34764da'
|
||||||
|
down_revision = '7186440a306b'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from tacker.db import migration
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(active_plugins=None, options=None):
|
||||||
|
op.add_column('vnf_lcm_op_occs',
|
||||||
|
sa.Column('grant_id', sa.VARCHAR(length=36), nullable=True))
|
||||||
|
op.add_column('vnf_lcm_op_occs',
|
||||||
|
sa.Column('changed_ext_connectivity', sa.JSON(), nullable=True))
|
@ -1 +1 @@
|
|||||||
7186440a306b
|
3adac34764da
|
||||||
|
@ -225,8 +225,7 @@ class LcmOccsOperationState(BaseTackerEnum):
|
|||||||
FAILED_TEMP = 'FAILED_TEMP'
|
FAILED_TEMP = 'FAILED_TEMP'
|
||||||
FAILED = 'FAILED'
|
FAILED = 'FAILED'
|
||||||
|
|
||||||
ALL = (STARTING, PROCESSING, COMPLETED,
|
ALL = (STARTING, PROCESSING, COMPLETED, FAILED_TEMP, FAILED)
|
||||||
FAILED_TEMP, FAILED)
|
|
||||||
|
|
||||||
|
|
||||||
class LcmOccsOperationType(BaseTackerEnum):
|
class LcmOccsOperationType(BaseTackerEnum):
|
||||||
|
@ -15,10 +15,13 @@ from datetime import datetime
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
|
from oslo_versionedobjects import base as ovoo_base
|
||||||
from sqlalchemy import exc
|
from sqlalchemy import exc
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
|
from sqlalchemy_filters import apply_filters
|
||||||
|
|
||||||
from tacker.common import exceptions
|
from tacker.common import exceptions
|
||||||
|
from tacker.common import utils
|
||||||
from tacker.db import api as db_api
|
from tacker.db import api as db_api
|
||||||
from tacker.db.db_sqlalchemy import api
|
from tacker.db.db_sqlalchemy import api
|
||||||
from tacker.db.db_sqlalchemy import models
|
from tacker.db.db_sqlalchemy import models
|
||||||
@ -55,11 +58,34 @@ def _vnf_lcm_op_occ_update(context, values):
|
|||||||
if values.changed_info:
|
if values.changed_info:
|
||||||
update.update({'changed_info': jsonutils.dumps(
|
update.update({'changed_info': jsonutils.dumps(
|
||||||
values.changed_info.to_dict())})
|
values.changed_info.to_dict())})
|
||||||
|
if 'changed_ext_connectivity' in values:
|
||||||
|
if values.changed_ext_connectivity:
|
||||||
|
update.update({'changed_ext_connectivity': jsonutils.dumps(
|
||||||
|
[chg_ext_conn.to_dict() for chg_ext_conn in
|
||||||
|
values.changed_ext_connectivity])})
|
||||||
api.model_query(context, models.VnfLcmOpOccs). \
|
api.model_query(context, models.VnfLcmOpOccs). \
|
||||||
filter_by(id=values.id). \
|
filter_by(id=values.id). \
|
||||||
update(update, synchronize_session=False)
|
update(update, synchronize_session=False)
|
||||||
|
|
||||||
|
|
||||||
|
def _make_vnf_lcm_op_occs_list(context, op_occ_list,
|
||||||
|
db_op_occ_list):
|
||||||
|
lcm_op_occ_class = VnfLcmOpOcc
|
||||||
|
|
||||||
|
op_occ_list.objects = []
|
||||||
|
for db_op_occ in db_op_occ_list:
|
||||||
|
if(db_op_occ['changed_info'] and
|
||||||
|
isinstance(db_op_occ['changed_info'], str)):
|
||||||
|
db_op_occ['changed_info'] = jsonutils.loads(
|
||||||
|
db_op_occ['changed_info'])
|
||||||
|
vnf_lcm_op_occ_obj = lcm_op_occ_class._from_db_object(
|
||||||
|
context, lcm_op_occ_class(context), db_op_occ)
|
||||||
|
op_occ_list.objects.append(vnf_lcm_op_occ_obj)
|
||||||
|
|
||||||
|
op_occ_list.obj_reset_changes()
|
||||||
|
return op_occ_list
|
||||||
|
|
||||||
|
|
||||||
@db_api.context_manager.reader
|
@db_api.context_manager.reader
|
||||||
def _vnf_lcm_op_occs_get_by_id(context, vnf_lcm_op_occ_id):
|
def _vnf_lcm_op_occs_get_by_id(context, vnf_lcm_op_occ_id):
|
||||||
|
|
||||||
@ -91,6 +117,19 @@ def _vnf_lcm_op_occs_get_by_vnf_instance_id(context, vnf_instance_id):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@db_api.context_manager.reader
|
||||||
|
def _vnf_lcm_op_occs_get_by_filters(context, read_deleted=None,
|
||||||
|
filters=None):
|
||||||
|
|
||||||
|
query = api.model_query(context, models.VnfLcmOpOccs,
|
||||||
|
read_deleted=read_deleted, project_only=True)
|
||||||
|
|
||||||
|
if filters:
|
||||||
|
query = apply_filters(query, filters)
|
||||||
|
|
||||||
|
return query.all()
|
||||||
|
|
||||||
|
|
||||||
@db_api.context_manager.reader
|
@db_api.context_manager.reader
|
||||||
def _vnf_notify_get_by_id(context, vnf_instance_id, columns_to_join=None):
|
def _vnf_notify_get_by_id(context, vnf_instance_id, columns_to_join=None):
|
||||||
|
|
||||||
@ -170,6 +209,7 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat,
|
|||||||
'state_entered_time': fields.DateTimeField(nullable=False),
|
'state_entered_time': fields.DateTimeField(nullable=False),
|
||||||
'start_time': fields.DateTimeField(nullable=False),
|
'start_time': fields.DateTimeField(nullable=False),
|
||||||
'vnf_instance_id': fields.StringField(nullable=False),
|
'vnf_instance_id': fields.StringField(nullable=False),
|
||||||
|
'grant_id': fields.StringField(nullable=True),
|
||||||
'operation': fields.StringField(nullable=False),
|
'operation': fields.StringField(nullable=False),
|
||||||
'is_automatic_invocation': fields.BooleanField(default=False),
|
'is_automatic_invocation': fields.BooleanField(default=False),
|
||||||
'operation_params': fields.StringField(nullable=True),
|
'operation_params': fields.StringField(nullable=True),
|
||||||
@ -180,9 +220,40 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat,
|
|||||||
'ResourceChanges', nullable=True, default=None),
|
'ResourceChanges', nullable=True, default=None),
|
||||||
'changed_info': fields.ObjectField(
|
'changed_info': fields.ObjectField(
|
||||||
'VnfInfoModifications', nullable=True, default=None),
|
'VnfInfoModifications', nullable=True, default=None),
|
||||||
|
'changed_ext_connectivity': fields.ListOfObjectsField(
|
||||||
|
'ExtVirtualLinkInfo', nullable=True, default=[]),
|
||||||
'error_point': fields.IntegerField(nullable=True, default=0)
|
'error_point': fields.IntegerField(nullable=True, default=0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALL_ATTRIBUTES = {
|
||||||
|
'id': ('id', 'string', 'VnfLcmOpOccs'),
|
||||||
|
'operationState': ('operation_state', 'string', 'VnfLcmOpOccs'),
|
||||||
|
'stateEnteredTime':
|
||||||
|
('state_entered_time', 'datetime', 'VnfLcmOpOccs'),
|
||||||
|
'startTime': ('start_time', 'datetime', 'VnfLcmOpOccs'),
|
||||||
|
'vnfInstanceId': ('vnf_instance_id', 'string', 'VnfLcmOpOccs'),
|
||||||
|
'grantId': ('grant_id', 'string', 'VnfLcmOpOccs'),
|
||||||
|
'operation': ('operation', 'string', 'VnfLcmOpOccs'),
|
||||||
|
'isAutomaticInvocation':
|
||||||
|
('is_automatic_invocation', 'boolean', 'VnfLcmOpOccs'),
|
||||||
|
'isCancelPending': ('is_cancel_pending', 'string', 'VnfLcmOpOccs'),
|
||||||
|
'errorPoint': ('error_point', 'number', 'VnfLcmOpOccs'),
|
||||||
|
'operationParams': ('operation_params', 'string', 'VnfLcmOpOccs'),
|
||||||
|
'error': ('error', 'string', 'VnfLcmOpOccs'),
|
||||||
|
'resourceChanges': ('resource_changes', 'string', 'VnfLcmOpOccs'),
|
||||||
|
'changedInfo': ('changed_info', 'string', 'VnfLcmOpOccs')
|
||||||
|
}
|
||||||
|
|
||||||
|
FLATTEN_ATTRIBUTES = utils.flatten_dict(ALL_ATTRIBUTES.copy())
|
||||||
|
|
||||||
|
SIMPLE_ATTRIBUTES = ['id', 'operationState', 'stateEnteredTime',
|
||||||
|
'startTime', 'vnfInstanceId', 'grantId', 'operation',
|
||||||
|
'isAutomaticInvocation',
|
||||||
|
'isCancelPending', 'errorPoint']
|
||||||
|
|
||||||
|
COMPLEX_ATTRIBUTES = ['error', 'resourceChanges', 'changedInfo',
|
||||||
|
'operationParams', 'changedExtConnectivity']
|
||||||
|
|
||||||
@base.remotable
|
@base.remotable
|
||||||
def create(self):
|
def create(self):
|
||||||
updates = self.obj_clone()
|
updates = self.obj_clone()
|
||||||
@ -197,7 +268,9 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat,
|
|||||||
def _from_db_object(context, vnf_lcm_op_occ_obj, db_vnf_lcm_op_occ):
|
def _from_db_object(context, vnf_lcm_op_occ_obj, db_vnf_lcm_op_occ):
|
||||||
|
|
||||||
special_fields = ['error',
|
special_fields = ['error',
|
||||||
'resource_changes', 'changed_info']
|
'resource_changes',
|
||||||
|
'changed_info',
|
||||||
|
'changed_ext_connectivity']
|
||||||
for key in vnf_lcm_op_occ_obj.fields:
|
for key in vnf_lcm_op_occ_obj.fields:
|
||||||
if key in special_fields:
|
if key in special_fields:
|
||||||
continue
|
continue
|
||||||
@ -214,6 +287,12 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat,
|
|||||||
changed_info = VnfInfoModifications.obj_from_primitive(
|
changed_info = VnfInfoModifications.obj_from_primitive(
|
||||||
db_vnf_lcm_op_occ['changed_info'], context)
|
db_vnf_lcm_op_occ['changed_info'], context)
|
||||||
vnf_lcm_op_occ_obj.changed_info = changed_info
|
vnf_lcm_op_occ_obj.changed_info = changed_info
|
||||||
|
if db_vnf_lcm_op_occ['changed_ext_connectivity']:
|
||||||
|
changed_ext_conn = \
|
||||||
|
[objects.ExtVirtualLinkInfo.obj_from_primitive(
|
||||||
|
chg_ext_conn, context) for chg_ext_conn in
|
||||||
|
db_vnf_lcm_op_occ['changed_ext_connectivity']]
|
||||||
|
vnf_lcm_op_occ_obj.changed_ext_connectivity = changed_ext_conn
|
||||||
|
|
||||||
vnf_lcm_op_occ_obj._context = context
|
vnf_lcm_op_occ_obj._context = context
|
||||||
vnf_lcm_op_occ_obj.obj_reset_changes()
|
vnf_lcm_op_occ_obj.obj_reset_changes()
|
||||||
@ -238,6 +317,11 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat,
|
|||||||
obj_data = VnfInfoModifications._from_dict(
|
obj_data = VnfInfoModifications._from_dict(
|
||||||
primitive.get('changed_info'))
|
primitive.get('changed_info'))
|
||||||
primitive.update({'changed_info': obj_data})
|
primitive.update({'changed_info': obj_data})
|
||||||
|
if 'changed_ext_connectivity' in primitive.keys():
|
||||||
|
obj_data = [objects.ExtVirtualLinkInfo.obj_from_primitive(
|
||||||
|
chg_ext_conn, context) for chg_ext_conn in
|
||||||
|
primitive.get('changed_ext_connectivity')]
|
||||||
|
primitive.update({'changed_ext_connectivity': obj_data})
|
||||||
vnf_lcm_op_occ = VnfLcmOpOcc._from_dict(primitive)
|
vnf_lcm_op_occ = VnfLcmOpOcc._from_dict(primitive)
|
||||||
|
|
||||||
return vnf_lcm_op_occ
|
return vnf_lcm_op_occ
|
||||||
@ -252,6 +336,7 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat,
|
|||||||
state_entered_time = data_dict.get('state_entered_time')
|
state_entered_time = data_dict.get('state_entered_time')
|
||||||
start_time = data_dict.get('start_time')
|
start_time = data_dict.get('start_time')
|
||||||
vnf_instance_id = data_dict.get('vnf_instance_id')
|
vnf_instance_id = data_dict.get('vnf_instance_id')
|
||||||
|
grant_id = data_dict.get('grant_id')
|
||||||
operation = data_dict.get('operation')
|
operation = data_dict.get('operation')
|
||||||
is_automatic_invocation = data_dict.get('is_automatic_invocation')
|
is_automatic_invocation = data_dict.get('is_automatic_invocation')
|
||||||
operation_params = data_dict.get('operation_params')
|
operation_params = data_dict.get('operation_params')
|
||||||
@ -259,12 +344,14 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat,
|
|||||||
error = data_dict.get('error')
|
error = data_dict.get('error')
|
||||||
resource_changes = data_dict.get('resource_changes')
|
resource_changes = data_dict.get('resource_changes')
|
||||||
changed_info = data_dict.get('changed_info')
|
changed_info = data_dict.get('changed_info')
|
||||||
|
changed_ext_connectivity = data_dict.get('changed_ext_connectivity')
|
||||||
error_point = data_dict.get('error_point')
|
error_point = data_dict.get('error_point')
|
||||||
|
|
||||||
obj = cls(operation_state=operation_state,
|
obj = cls(operation_state=operation_state,
|
||||||
state_entered_time=state_entered_time,
|
state_entered_time=state_entered_time,
|
||||||
start_time=start_time,
|
start_time=start_time,
|
||||||
vnf_instance_id=vnf_instance_id,
|
vnf_instance_id=vnf_instance_id,
|
||||||
|
grant_id=grant_id,
|
||||||
operation=operation,
|
operation=operation,
|
||||||
is_automatic_invocation=is_automatic_invocation,
|
is_automatic_invocation=is_automatic_invocation,
|
||||||
operation_params=operation_params,
|
operation_params=operation_params,
|
||||||
@ -272,28 +359,76 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat,
|
|||||||
error=error,
|
error=error,
|
||||||
resource_changes=resource_changes,
|
resource_changes=resource_changes,
|
||||||
changed_info=changed_info,
|
changed_info=changed_info,
|
||||||
|
changed_ext_connectivity=changed_ext_connectivity,
|
||||||
error_point=error_point
|
error_point=error_point
|
||||||
)
|
)
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def to_dict(self):
|
def _get_error(self, include_fields=None):
|
||||||
data = {'id': self.id,
|
key = 'error'
|
||||||
'operation_state': self.operation_state,
|
if key in include_fields:
|
||||||
'state_entered_time': self.state_entered_time,
|
return {key: self.error.to_dict()}
|
||||||
'start_time': self.start_time,
|
|
||||||
'vnf_instance_id': self.vnf_instance_id,
|
def _get_resource_changes(self, include_fields=None):
|
||||||
'operation': self.operation,
|
key = 'resourceChanges'
|
||||||
'is_automatic_invocation': self.is_automatic_invocation,
|
if key in include_fields:
|
||||||
'operation_params': self.operation_params,
|
return {key: self.resource_changes.to_dict()}
|
||||||
'is_cancel_pending': self.is_cancel_pending,
|
|
||||||
'error_point': self.error_point}
|
def _get_changed_info(self, include_fields=None):
|
||||||
|
key = 'changedInfo'
|
||||||
|
if key in include_fields:
|
||||||
|
return {key: self.changed_info.to_dict()}
|
||||||
|
|
||||||
|
def _get_operation_params(self, include_fields=None):
|
||||||
|
key = 'operationParams'
|
||||||
|
if key in include_fields:
|
||||||
|
return {key: self.operation_params}
|
||||||
|
|
||||||
|
def _get_changed_ext_connectivity(self, include_fields=None):
|
||||||
|
key = 'changedExtConnectivity'
|
||||||
|
return {key: [chg_ext_conn.to_dict() for chg_ext_conn in
|
||||||
|
self.changed_ext_connectivity]}
|
||||||
|
|
||||||
|
def to_dict(self, include_fields=None):
|
||||||
|
data = dict()
|
||||||
|
if not include_fields:
|
||||||
|
include_fields = set(self.FLATTEN_ATTRIBUTES.keys())
|
||||||
|
|
||||||
|
# add simple fields
|
||||||
|
to_fields = set(self.SIMPLE_ATTRIBUTES).intersection(include_fields)
|
||||||
|
for field in to_fields:
|
||||||
|
data[field] = getattr(self, self.FLATTEN_ATTRIBUTES[field][0])
|
||||||
|
|
||||||
|
# add complex attributes
|
||||||
if self.error:
|
if self.error:
|
||||||
data.update({'error': self.error.to_dict()})
|
error = self._get_error(include_fields=include_fields)
|
||||||
|
if error:
|
||||||
|
data.update(error)
|
||||||
|
|
||||||
if self.resource_changes:
|
if self.resource_changes:
|
||||||
data.update({'resource_changes': self.resource_changes.to_dict()})
|
resource_changes = self._get_resource_changes(
|
||||||
|
include_fields=include_fields)
|
||||||
|
if resource_changes:
|
||||||
|
data.update(resource_changes)
|
||||||
|
|
||||||
if self.changed_info:
|
if self.changed_info:
|
||||||
data.update({'changed_info': self.changed_info.to_dict()})
|
changed_info = self._get_changed_info(
|
||||||
|
include_fields=include_fields)
|
||||||
|
if changed_info:
|
||||||
|
data.update(changed_info)
|
||||||
|
|
||||||
|
if self.operation_params:
|
||||||
|
operation_params = self._get_operation_params(
|
||||||
|
include_fields=include_fields)
|
||||||
|
if operation_params:
|
||||||
|
data.update(operation_params)
|
||||||
|
|
||||||
|
if self.changed_ext_connectivity:
|
||||||
|
changed_ext_connectivity = self._get_changed_ext_connectivity(
|
||||||
|
include_fields=include_fields)
|
||||||
|
if changed_ext_connectivity:
|
||||||
|
data.update(changed_ext_connectivity)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@ -309,6 +444,22 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat,
|
|||||||
return cls._from_db_object(context, cls(), db_vnf_lcm_op_occs)
|
return cls._from_db_object(context, cls(), db_vnf_lcm_op_occs)
|
||||||
|
|
||||||
|
|
||||||
|
@base.TackerObjectRegistry.register
|
||||||
|
class VnfLcmOpOccList(ovoo_base.ObjectListBase, base.TackerObject):
|
||||||
|
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
'objects': fields.ListOfObjectsField('VnfLcmOpOcc')
|
||||||
|
}
|
||||||
|
|
||||||
|
@base.remotable_classmethod
|
||||||
|
def get_by_filters(cls, context, read_deleted=None, filters=None):
|
||||||
|
db_vnf_lcm_op_occs = _vnf_lcm_op_occs_get_by_filters(
|
||||||
|
context, read_deleted=read_deleted, filters=filters)
|
||||||
|
return _make_vnf_lcm_op_occs_list(context, cls(), db_vnf_lcm_op_occs)
|
||||||
|
|
||||||
|
|
||||||
@base.TackerObjectRegistry.register
|
@base.TackerObjectRegistry.register
|
||||||
class ResourceChanges(base.TackerObject,
|
class ResourceChanges(base.TackerObject,
|
||||||
base.TackerPersistentObject):
|
base.TackerPersistentObject):
|
||||||
|
@ -99,6 +99,17 @@ rules = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=VNFLCM % 'list_lcm_op_occs',
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="Query VNF LCM operation occurrence",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/vnflcm/v1/vnf_lcm_op_occs'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
),
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
name=VNFLCM % 'index',
|
name=VNFLCM % 'index',
|
||||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
@ -487,6 +487,14 @@ class BaseVnfLcmTest(base.BaseTackerTest):
|
|||||||
|
|
||||||
return resp, response_body
|
return resp, response_body
|
||||||
|
|
||||||
|
def _list_op_occs(self, filter_string=''):
|
||||||
|
show_url = os.path.join(
|
||||||
|
self.base_vnf_lcm_op_occs_url)
|
||||||
|
resp, response_body = self.http_client.do_request(
|
||||||
|
show_url + filter_string, "GET")
|
||||||
|
|
||||||
|
return resp, response_body
|
||||||
|
|
||||||
def _wait_terminate_vnf_instance(self, id, timeout=None):
|
def _wait_terminate_vnf_instance(self, id, timeout=None):
|
||||||
start_time = int(time.time())
|
start_time = int(time.time())
|
||||||
|
|
||||||
|
@ -778,6 +778,8 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
- Get vnflcmOpOccId to retry.
|
- Get vnflcmOpOccId to retry.
|
||||||
- Retry instantiation operation.
|
- Retry instantiation operation.
|
||||||
- Get opOccs information.
|
- Get opOccs information.
|
||||||
|
- Get opOccs list.
|
||||||
|
- Delete VNF instance.
|
||||||
- Delete subscription.
|
- Delete subscription.
|
||||||
"""
|
"""
|
||||||
# Create subscription and register it.
|
# Create subscription and register it.
|
||||||
@ -855,6 +857,10 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
||||||
self._assert_occ_show(resp, op_occs_info)
|
self._assert_occ_show(resp, op_occs_info)
|
||||||
|
|
||||||
|
# occ-list
|
||||||
|
resp, op_occs_info = self._list_op_occs()
|
||||||
|
self._assert_occ_list(resp, op_occs_info)
|
||||||
|
|
||||||
# Delete VNF
|
# Delete VNF
|
||||||
resp, _ = self._delete_vnf_instance(vnf_instance_id)
|
resp, _ = self._delete_vnf_instance(vnf_instance_id)
|
||||||
self._wait_lcm_done(vnf_instance_id=vnf_instance_id)
|
self._wait_lcm_done(vnf_instance_id=vnf_instance_id)
|
||||||
@ -877,7 +883,9 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
- Get vnfcmOpOccId to retry.
|
- Get vnfcmOpOccId to retry.
|
||||||
- Retry Scale-Out operation.
|
- Retry Scale-Out operation.
|
||||||
- Get opOccs information.
|
- Get opOccs information.
|
||||||
- Terminate VNF.
|
- Get opOccs list.
|
||||||
|
- Terminate VNF instance.
|
||||||
|
- Delete VNF instance.
|
||||||
- Delete subscription.
|
- Delete subscription.
|
||||||
"""
|
"""
|
||||||
# Create subscription and register it.
|
# Create subscription and register it.
|
||||||
@ -964,6 +972,10 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
||||||
self._assert_occ_show(resp, op_occs_info)
|
self._assert_occ_show(resp, op_occs_info)
|
||||||
|
|
||||||
|
# occ-list
|
||||||
|
resp, op_occs_info = self._list_op_occs()
|
||||||
|
self._assert_occ_list(resp, op_occs_info)
|
||||||
|
|
||||||
# Terminate VNF
|
# Terminate VNF
|
||||||
stack = self._get_heat_stack(vnf_instance_id)
|
stack = self._get_heat_stack(vnf_instance_id)
|
||||||
resources_list = self._get_heat_resource_list(stack.id)
|
resources_list = self._get_heat_resource_list(stack.id)
|
||||||
@ -1000,6 +1012,7 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
- Get vnflcmOpOccId to rollback.
|
- Get vnflcmOpOccId to rollback.
|
||||||
- Rollback instantiation operation.
|
- Rollback instantiation operation.
|
||||||
- Get opOccs information.
|
- Get opOccs information.
|
||||||
|
- Get opOccs list
|
||||||
- Delete subscription.
|
- Delete subscription.
|
||||||
"""
|
"""
|
||||||
# Create subscription and register it.
|
# Create subscription and register it.
|
||||||
@ -1072,6 +1085,10 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
||||||
self._assert_occ_show(resp, op_occs_info)
|
self._assert_occ_show(resp, op_occs_info)
|
||||||
|
|
||||||
|
# occ-list
|
||||||
|
resp, op_occs_info = self._list_op_occs()
|
||||||
|
self._assert_occ_list(resp, op_occs_info)
|
||||||
|
|
||||||
# Delete VNF
|
# Delete VNF
|
||||||
resp, _ = self._delete_vnf_instance(vnf_instance_id)
|
resp, _ = self._delete_vnf_instance(vnf_instance_id)
|
||||||
self._wait_lcm_done(vnf_instance_id=vnf_instance_id)
|
self._wait_lcm_done(vnf_instance_id=vnf_instance_id)
|
||||||
@ -1094,6 +1111,7 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
- Get vnfcmOpOccId to rollback.
|
- Get vnfcmOpOccId to rollback.
|
||||||
- Rollback Scale-Out operation.
|
- Rollback Scale-Out operation.
|
||||||
- Get opOccs information.
|
- Get opOccs information.
|
||||||
|
- get opOccs List.
|
||||||
- Terminate VNF.
|
- Terminate VNF.
|
||||||
- Delete subscription.
|
- Delete subscription.
|
||||||
"""
|
"""
|
||||||
@ -1176,6 +1194,10 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
||||||
self._assert_occ_show(resp, op_occs_info)
|
self._assert_occ_show(resp, op_occs_info)
|
||||||
|
|
||||||
|
# occ-list
|
||||||
|
resp, op_occs_info = self._list_op_occs()
|
||||||
|
self._assert_occ_list(resp, op_occs_info)
|
||||||
|
|
||||||
# Terminate VNF
|
# Terminate VNF
|
||||||
stack = self._get_heat_stack(vnf_instance_id)
|
stack = self._get_heat_stack(vnf_instance_id)
|
||||||
resources_list = self._get_heat_resource_list(stack.id)
|
resources_list = self._get_heat_resource_list(stack.id)
|
||||||
@ -1283,6 +1305,10 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
||||||
self._assert_occ_show(resp, op_occs_info)
|
self._assert_occ_show(resp, op_occs_info)
|
||||||
|
|
||||||
|
# occ-list
|
||||||
|
resp, op_occs_info = self._list_op_occs()
|
||||||
|
self._assert_occ_list(resp, op_occs_info)
|
||||||
|
|
||||||
# Delete Stack
|
# Delete Stack
|
||||||
stack = self._get_heat_stack(vnf_instance_id)
|
stack = self._get_heat_stack(vnf_instance_id)
|
||||||
self._delete_heat_stack(stack.id)
|
self._delete_heat_stack(stack.id)
|
||||||
@ -1391,6 +1417,10 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id)
|
||||||
self._assert_occ_show(resp, op_occs_info)
|
self._assert_occ_show(resp, op_occs_info)
|
||||||
|
|
||||||
|
# occ-list
|
||||||
|
resp, op_occs_info = self._list_op_occs()
|
||||||
|
self._assert_occ_list(resp, op_occs_info)
|
||||||
|
|
||||||
# Terminate VNF
|
# Terminate VNF
|
||||||
stack = self._get_heat_stack(vnf_instance_id)
|
stack = self._get_heat_stack(vnf_instance_id)
|
||||||
resources_list = self._get_heat_resource_list(stack.id)
|
resources_list = self._get_heat_resource_list(stack.id)
|
||||||
@ -1562,3 +1592,24 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest):
|
|||||||
self.assertIsNotNone(_links.get('vnfInstance').get('href'))
|
self.assertIsNotNone(_links.get('vnfInstance').get('href'))
|
||||||
self.assertIsNotNone(_links.get('grant'))
|
self.assertIsNotNone(_links.get('grant'))
|
||||||
self.assertIsNotNone(_links.get('grant').get('href'))
|
self.assertIsNotNone(_links.get('grant').get('href'))
|
||||||
|
|
||||||
|
def _assert_occ_list(self, resp, op_occs_list):
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
|
||||||
|
# Only check required parameters.
|
||||||
|
for op_occs_info in op_occs_list:
|
||||||
|
self.assertIsNotNone(op_occs_info.get('id'))
|
||||||
|
self.assertIsNotNone(op_occs_info.get('operationState'))
|
||||||
|
self.assertIsNotNone(op_occs_info.get('stateEnteredTime'))
|
||||||
|
self.assertIsNotNone(op_occs_info.get('vnfInstanceId'))
|
||||||
|
self.assertIsNotNone(op_occs_info.get('operation'))
|
||||||
|
self.assertIsNotNone(op_occs_info.get('isAutomaticInvocation'))
|
||||||
|
self.assertIsNotNone(op_occs_info.get('isCancelPending'))
|
||||||
|
|
||||||
|
_links = op_occs_info.get('_links')
|
||||||
|
self.assertIsNotNone(_links.get('self'))
|
||||||
|
self.assertIsNotNone(_links.get('self').get('href'))
|
||||||
|
self.assertIsNotNone(_links.get('vnfInstance'))
|
||||||
|
self.assertIsNotNone(_links.get('vnfInstance').get('href'))
|
||||||
|
self.assertIsNotNone(_links.get('grant'))
|
||||||
|
self.assertIsNotNone(_links.get('grant').get('href'))
|
||||||
|
@ -512,3 +512,23 @@ def get_vnf(vnfd_id, vim_id):
|
|||||||
'placement_attr': "test_placement_attr",
|
'placement_attr': "test_placement_attr",
|
||||||
'vim_id': vim_id
|
'vim_id': vim_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_changed_ext_conn_data():
|
||||||
|
return [{
|
||||||
|
"id": uuidsentinel.change_ext_conn_id,
|
||||||
|
"resource_handle": {
|
||||||
|
"vim_connection_id": uuidsentinel.vim_connection_id,
|
||||||
|
"resource_id": uuidsentinel.vl_resource_id,
|
||||||
|
"vim_level_resource_type": "OS::Neutron::Net",
|
||||||
|
},
|
||||||
|
"ext_link_ports": [{
|
||||||
|
"id": uuidsentinel.ext_link_ports_id,
|
||||||
|
"resource_handle": {
|
||||||
|
"vim_connection_id": uuidsentinel.vim_connection_id,
|
||||||
|
"resource_id": uuidsentinel.port_resource_id,
|
||||||
|
"vim_level_resource_type": "OS::Neutron::Port",
|
||||||
|
},
|
||||||
|
"cp_instance_id": uuidsentinel.cp_instance_id,
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
@ -90,10 +90,13 @@ class TestVnfLcmOpOcc(SqlTestCase):
|
|||||||
problem_obj.detail = 'test_err'
|
problem_obj.detail = 'test_err'
|
||||||
changed_info = objects.vnf_lcm_op_occs.VnfInfoModifications(
|
changed_info = objects.vnf_lcm_op_occs.VnfInfoModifications(
|
||||||
context=self.context, **fakes.get_changed_info_data())
|
context=self.context, **fakes.get_changed_info_data())
|
||||||
|
changed_ext_conn = [objects.ExtVirtualLinkInfo.obj_from_primitive(
|
||||||
|
i, self.context) for i in fakes.get_changed_ext_conn_data()]
|
||||||
vnf_lcm_op_occs.operation_state = 'FAILED_TEMP'
|
vnf_lcm_op_occs.operation_state = 'FAILED_TEMP'
|
||||||
vnf_lcm_op_occs.error = problem_obj
|
vnf_lcm_op_occs.error = problem_obj
|
||||||
vnf_lcm_op_occs.id = uuidsentinel.vnf_lcm_op_occs_id
|
vnf_lcm_op_occs.id = uuidsentinel.vnf_lcm_op_occs_id
|
||||||
vnf_lcm_op_occs.changed_info = changed_info
|
vnf_lcm_op_occs.changed_info = changed_info
|
||||||
|
vnf_lcm_op_occs.changed_ext_connectivity = changed_ext_conn
|
||||||
vnf_lcm_op_occs.save()
|
vnf_lcm_op_occs.save()
|
||||||
|
|
||||||
self.assertEqual('FAILED_TEMP', vnf_lcm_op_occs.operation_state)
|
self.assertEqual('FAILED_TEMP', vnf_lcm_op_occs.operation_state)
|
||||||
|
@ -1265,20 +1265,28 @@ VNFLCMOPOCC_RESPONSE = {
|
|||||||
"href": CONF.vnf_lcm.endpoint_url + '/vnflcm/v1/vnf_instances/'
|
"href": CONF.vnf_lcm.endpoint_url + '/vnflcm/v1/vnf_instances/'
|
||||||
'f26f181d-7891-4720-b022-b074ec1733ef'
|
'f26f181d-7891-4720-b022-b074ec1733ef'
|
||||||
},
|
},
|
||||||
|
"retry": {
|
||||||
|
"href": CONF.vnf_lcm.endpoint_url + '/vnflcm/v1/vnf_lcm_op_occs/'
|
||||||
|
'f26f181d-7891-4720-b022-b074ec1733ef/retry'
|
||||||
|
},
|
||||||
"rollback": {
|
"rollback": {
|
||||||
"href": CONF.vnf_lcm.endpoint_url + '/vnflcm/v1/vnf_lcm_op_occs/'
|
"href": CONF.vnf_lcm.endpoint_url + '/vnflcm/v1/vnf_lcm_op_occs/'
|
||||||
'f26f181d-7891-4720-b022-b074ec1733ef/rollback'
|
'f26f181d-7891-4720-b022-b074ec1733ef/rollback'
|
||||||
},
|
},
|
||||||
"grant": {
|
"grant": {
|
||||||
"href": CONF.vnf_lcm.endpoint_url + '/vnflcm/v1/vnf_lcm_op_occs/'
|
"href": CONF.vnf_lcm.endpoint_url + '/vnflcm/v1/vnf_lcm_op_occs/'
|
||||||
'f26f181d-7891-4720-b022-b074ec1733ef/grant'
|
'f26f181d-7891-4720-b022-b074ec1733ef/grant',
|
||||||
}},
|
},
|
||||||
|
"fail": {
|
||||||
|
"href": CONF.vnf_lcm.endpoint_url + '/vnflcm/v1/vnf_lcm_op_occs/'
|
||||||
|
'f26f181d-7891-4720-b022-b074ec1733ef/fail'}},
|
||||||
'operationState': 'COMPLETED',
|
'operationState': 'COMPLETED',
|
||||||
'stateEnteredTime': datetime.datetime(1900, 1, 1, 1, 1, 1,
|
'stateEnteredTime': datetime.datetime(1900, 1, 1, 1, 1, 1,
|
||||||
tzinfo=iso8601.UTC),
|
tzinfo=iso8601.UTC),
|
||||||
'startTime': datetime.datetime(1900, 1, 1, 1, 1, 1,
|
'startTime': datetime.datetime(1900, 1, 1, 1, 1, 1,
|
||||||
tzinfo=iso8601.UTC),
|
tzinfo=iso8601.UTC),
|
||||||
'vnfInstanceId': 'f26f181d-7891-4720-b022-b074ec1733ef',
|
'vnfInstanceId': 'f26f181d-7891-4720-b022-b074ec1733ef',
|
||||||
|
'grantId': 'f26f181d-7891-4720-b022-b074ec1733ef',
|
||||||
'operation': 'MODIFY_INFO',
|
'operation': 'MODIFY_INFO',
|
||||||
'isAutomaticInvocation': False,
|
'isAutomaticInvocation': False,
|
||||||
'operationParams': '{"is_reverse": False, "is_auto": False}',
|
'operationParams': '{"is_reverse": False, "is_auto": False}',
|
||||||
@ -1336,7 +1344,24 @@ VNFLCMOPOCC_RESPONSE = {
|
|||||||
'vnfProductName': 'fake_vnf_product_name',
|
'vnfProductName': 'fake_vnf_product_name',
|
||||||
'vnfSoftwareVersion': 'fake_vnf_software_version',
|
'vnfSoftwareVersion': 'fake_vnf_software_version',
|
||||||
'vnfdVersion': 'fake_vnfd_version'
|
'vnfdVersion': 'fake_vnfd_version'
|
||||||
}
|
},
|
||||||
|
"changedExtConnectivity": [{
|
||||||
|
"id": constants.UUID,
|
||||||
|
"resourceHandle": {
|
||||||
|
"vimConnectionId": constants.UUID,
|
||||||
|
"resourceId": constants.UUID,
|
||||||
|
"vimLevelResourceType": "OS::Neutron::Net",
|
||||||
|
},
|
||||||
|
"extLinkPorts": [{
|
||||||
|
"id": constants.UUID,
|
||||||
|
"resourceHandle": {
|
||||||
|
"vimConnectionId": constants.UUID,
|
||||||
|
"resourceId": constants.UUID,
|
||||||
|
"vimLevelResourceType": "OS::Neutron::Port",
|
||||||
|
},
|
||||||
|
"cpInstanceId": constants.UUID,
|
||||||
|
}]
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
VNFLCMOPOCC_INDEX_RESPONSE = [VNFLCMOPOCC_RESPONSE]
|
VNFLCMOPOCC_INDEX_RESPONSE = [VNFLCMOPOCC_RESPONSE]
|
||||||
@ -1436,6 +1461,28 @@ def fake_vnf_lcm_op_occs():
|
|||||||
}
|
}
|
||||||
changed_info_obj = objects.VnfInfoModifications(**changed_info)
|
changed_info_obj = objects.VnfInfoModifications(**changed_info)
|
||||||
|
|
||||||
|
changed_ext_connectivity = [{
|
||||||
|
"id": constants.UUID,
|
||||||
|
"resource_handle": {
|
||||||
|
"vim_connection_id": constants.UUID,
|
||||||
|
"resource_id": constants.UUID,
|
||||||
|
"vim_level_resource_type": "OS::Neutron::Net",
|
||||||
|
},
|
||||||
|
"ext_link_ports": [{
|
||||||
|
"id": constants.UUID,
|
||||||
|
"resource_handle": {
|
||||||
|
"vim_connection_id": constants.UUID,
|
||||||
|
"resource_id": constants.UUID,
|
||||||
|
"vim_level_resource_type": "OS::Neutron::Port",
|
||||||
|
},
|
||||||
|
"cp_instance_id": constants.UUID,
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
changed_ext_connectivity_obj = \
|
||||||
|
[objects.ExtVirtualLinkInfo.obj_from_primitive(
|
||||||
|
chg_ext_conn, context) for chg_ext_conn in
|
||||||
|
changed_ext_connectivity]
|
||||||
|
|
||||||
dt = datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.UTC)
|
dt = datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.UTC)
|
||||||
vnf_lcm_op_occs = {
|
vnf_lcm_op_occs = {
|
||||||
'id': constants.UUID,
|
'id': constants.UUID,
|
||||||
@ -1443,13 +1490,15 @@ def fake_vnf_lcm_op_occs():
|
|||||||
'state_entered_time': dt,
|
'state_entered_time': dt,
|
||||||
'start_time': dt,
|
'start_time': dt,
|
||||||
'vnf_instance_id': constants.UUID,
|
'vnf_instance_id': constants.UUID,
|
||||||
|
'grant_id': constants.UUID,
|
||||||
'operation': 'MODIFY_INFO',
|
'operation': 'MODIFY_INFO',
|
||||||
'is_automatic_invocation': False,
|
'is_automatic_invocation': False,
|
||||||
'operation_params': '{"is_reverse": False, "is_auto": False}',
|
'operation_params': '{"is_reverse": False, "is_auto": False}',
|
||||||
'is_cancel_pending': False,
|
'is_cancel_pending': False,
|
||||||
'error': error_obj,
|
'error': error_obj,
|
||||||
'resource_changes': resource_changes_obj,
|
'resource_changes': resource_changes_obj,
|
||||||
'changed_info': changed_info_obj
|
'changed_info': changed_info_obj,
|
||||||
|
'changed_ext_connectivity': changed_ext_connectivity_obj,
|
||||||
}
|
}
|
||||||
|
|
||||||
return vnf_lcm_op_occs
|
return vnf_lcm_op_occs
|
||||||
@ -1484,3 +1533,10 @@ def vnf_data(status='ACTIVE'):
|
|||||||
name='test',
|
name='test',
|
||||||
status=status,
|
status=status,
|
||||||
vim_id=uuidsentinel.vim_id)
|
vim_id=uuidsentinel.vim_id)
|
||||||
|
|
||||||
|
|
||||||
|
def return_vnf_lcm_opoccs_list():
|
||||||
|
vnf_lcm_op_occs = fake_vnf_lcm_op_occs()
|
||||||
|
obj = objects.VnfLcmOpOcc(**vnf_lcm_op_occs)
|
||||||
|
|
||||||
|
return [obj]
|
||||||
|
@ -3366,3 +3366,141 @@ class TestController(base.TestCase):
|
|||||||
|
|
||||||
resp = req.get_response(self.app)
|
resp = req.get_response(self.app)
|
||||||
self.assertEqual(http_client.INTERNAL_SERVER_ERROR, resp.status_code)
|
self.assertEqual(http_client.INTERNAL_SERVER_ERROR, resp.status_code)
|
||||||
|
|
||||||
|
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
|
||||||
|
def test_op_occ_list(self, mock_op_occ_list):
|
||||||
|
req = fake_request.HTTPRequest.blank('/vnflcm/v1/vnf_lcm_op_occs')
|
||||||
|
|
||||||
|
complex_attributes = [
|
||||||
|
'error',
|
||||||
|
'resourceChanges',
|
||||||
|
'operationParams',
|
||||||
|
'changedInfo']
|
||||||
|
|
||||||
|
vnf_lcm_op_occ = fakes.return_vnf_lcm_opoccs_list()
|
||||||
|
expected_result = fakes.index_response(
|
||||||
|
remove_attrs=complex_attributes)
|
||||||
|
mock_op_occ_list.return_value = vnf_lcm_op_occ
|
||||||
|
res_dict = self.controller.list_lcm_op_occs(req)
|
||||||
|
|
||||||
|
self.assertEqual(expected_result, res_dict)
|
||||||
|
|
||||||
|
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
|
||||||
|
@ddt.data(
|
||||||
|
{'filter': '(eq,id,f26f181d-7891-4720-b022-b074ec1733ef)'},
|
||||||
|
{'filter': '(neq,operationState,COMPLETED)'},
|
||||||
|
{'filter': '(gte,stateEnteredTime,2020-03-14 04:10:15+00:00)'},
|
||||||
|
{'filter': '(eq,isAutomaticInvocation,False)'},
|
||||||
|
{'filter': '(lt,errorPoint,4)'},
|
||||||
|
{'filter':
|
||||||
|
"""(eq,error,'"{"title": "ERROR",
|
||||||
|
"status": 500, "detail": "ERROR"}"')"""},
|
||||||
|
{'filter':
|
||||||
|
"""(in,changedInfo,'"{"vnfInstanceName": "test"}"')"""},
|
||||||
|
{'filter':
|
||||||
|
"""(neq,operationParams,'"{"terminationType": "FORCEFUL"}"')"""},
|
||||||
|
)
|
||||||
|
def test_op_occ_filter_attributes(self, filter_params,
|
||||||
|
mock_op_occ_list):
|
||||||
|
query = urllib.parse.urlencode(filter_params)
|
||||||
|
req = fake_request.HTTPRequest.blank(
|
||||||
|
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
|
||||||
|
|
||||||
|
complex_attributes = [
|
||||||
|
'error',
|
||||||
|
'resourceChanges',
|
||||||
|
'operationParams',
|
||||||
|
'changedInfo']
|
||||||
|
|
||||||
|
vnf_lcm_op_occ = fakes.return_vnf_lcm_opoccs_list()
|
||||||
|
expected_result = fakes.index_response(
|
||||||
|
remove_attrs=complex_attributes)
|
||||||
|
mock_op_occ_list.return_value = vnf_lcm_op_occ
|
||||||
|
res_dict = self.controller.list_lcm_op_occs(req)
|
||||||
|
|
||||||
|
self.assertEqual(expected_result, res_dict)
|
||||||
|
|
||||||
|
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
|
||||||
|
def test_op_occ_filter_attributes_invalid_filter(self, mock_op_occ_list):
|
||||||
|
query = urllib.parse.urlencode({'filter': '(lt,non_existing,4)'})
|
||||||
|
req = fake_request.HTTPRequest.blank(
|
||||||
|
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
|
||||||
|
|
||||||
|
vnf_lcm_op_occ = fakes.return_vnf_lcm_opoccs_list()
|
||||||
|
mock_op_occ_list.return_value = vnf_lcm_op_occ
|
||||||
|
self.assertRaises(
|
||||||
|
exceptions.ValidationError, self.controller.list_lcm_op_occs, req)
|
||||||
|
|
||||||
|
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
|
||||||
|
def test_op_occ_attribute_selector_all_fields(self, mock_op_occ_list):
|
||||||
|
params = {'all_fields': 'True'}
|
||||||
|
query = urllib.parse.urlencode(params)
|
||||||
|
req = fake_request.HTTPRequest.blank('/vnflcm/v1/vnf_lcm_op_occs?' +
|
||||||
|
query)
|
||||||
|
|
||||||
|
vnf_lcm_op_occ = fakes.return_vnf_lcm_opoccs_list()
|
||||||
|
expected_result = fakes.index_response()
|
||||||
|
mock_op_occ_list.return_value = vnf_lcm_op_occ
|
||||||
|
res_dict = self.controller.list_lcm_op_occs(req)
|
||||||
|
|
||||||
|
self.assertEqual(expected_result, res_dict)
|
||||||
|
|
||||||
|
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
|
||||||
|
@ddt.data(
|
||||||
|
{'fields': 'error'},
|
||||||
|
{'fields': 'resourceChanges'},
|
||||||
|
{'fields': 'operationParams'},
|
||||||
|
{'fields': 'changedInfo'}
|
||||||
|
)
|
||||||
|
def test_op_occ_attribute_selector_fields(self, filter_params,
|
||||||
|
mock_op_occ_list):
|
||||||
|
query = urllib.parse.urlencode(filter_params)
|
||||||
|
req = fake_request.HTTPRequest.blank(
|
||||||
|
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
|
||||||
|
|
||||||
|
complex_attributes = [
|
||||||
|
'error',
|
||||||
|
'resourceChanges',
|
||||||
|
'operationParams',
|
||||||
|
'changedInfo']
|
||||||
|
|
||||||
|
remove_attributes = [
|
||||||
|
x for x in complex_attributes if x != filter_params['fields']]
|
||||||
|
|
||||||
|
vnf_lcm_op_occ = fakes.return_vnf_lcm_opoccs_list()
|
||||||
|
expected_result = fakes.index_response(remove_attrs=remove_attributes)
|
||||||
|
mock_op_occ_list.return_value = vnf_lcm_op_occ
|
||||||
|
res_dict = self.controller.list_lcm_op_occs(req)
|
||||||
|
self.assertEqual(expected_result, res_dict)
|
||||||
|
|
||||||
|
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
|
||||||
|
@ddt.data(
|
||||||
|
{'exclude_fields': 'error'},
|
||||||
|
{'exclude_fields': 'resourceChanges'},
|
||||||
|
{'exclude_fields': 'operationParams'},
|
||||||
|
{'exclude_fields': 'changedInfo'}
|
||||||
|
)
|
||||||
|
def test_op_occ_attribute_selector_exclude_fields(self, filter_params,
|
||||||
|
mock_op_occ_list):
|
||||||
|
query = urllib.parse.urlencode(filter_params)
|
||||||
|
req = fake_request.HTTPRequest.blank(
|
||||||
|
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
|
||||||
|
|
||||||
|
remove_attributes = [filter_params['exclude_fields']]
|
||||||
|
|
||||||
|
vnf_lcm_op_occ = fakes.return_vnf_lcm_opoccs_list()
|
||||||
|
expected_result = fakes.index_response(remove_attrs=remove_attributes)
|
||||||
|
mock_op_occ_list.return_value = vnf_lcm_op_occ
|
||||||
|
res_dict = self.controller.list_lcm_op_occs(req)
|
||||||
|
self.assertEqual(expected_result, res_dict)
|
||||||
|
|
||||||
|
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
|
||||||
|
def test_op_occ_attribute_selector_fields_error(self, mock_op_occ_list):
|
||||||
|
query = urllib.parse.urlencode({'fields': 'non_existent_column'})
|
||||||
|
req = fake_request.HTTPRequest.blank(
|
||||||
|
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
|
||||||
|
|
||||||
|
vnf_lcm_op_occ = fakes.return_vnf_lcm_opoccs_list()
|
||||||
|
mock_op_occ_list.return_value = vnf_lcm_op_occ
|
||||||
|
self.assertRaises(
|
||||||
|
exceptions.ValidationError, self.controller.list_lcm_op_occs, req)
|
||||||
|
Loading…
Reference in New Issue
Block a user