aboutsummaryrefslogtreecommitdiffstats
path: root/onap-client/onap_client/sdc/vnf.py
diff options
context:
space:
mode:
Diffstat (limited to 'onap-client/onap_client/sdc/vnf.py')
-rw-r--r--onap-client/onap_client/sdc/vnf.py354
1 files changed, 235 insertions, 119 deletions
diff --git a/onap-client/onap_client/sdc/vnf.py b/onap-client/onap_client/sdc/vnf.py
index da8f213..5fa401c 100644
--- a/onap-client/onap_client/sdc/vnf.py
+++ b/onap-client/onap_client/sdc/vnf.py
@@ -43,6 +43,8 @@ from onap_client.sdc import vsp
from onap_client.util import utility
import time
+import random
+import json
vnf_client = SDCClient().sdc.vnf
@@ -66,6 +68,30 @@ class VNF(Resource):
"nested": {
"vm_type": {"type": str, "required": True},
"properties": {"type": dict, "required": True, "default": {}},
+ "resources": {
+ "type": list,
+ "list_item": dict,
+ "required": False,
+ "default": [],
+ "nested": {
+ "resource_name": {"type": str, "required": True},
+ "resource_id": {"type": str, "required": False},
+ "catalog_resource_name": {"type": str, "required": False},
+ "origin_type": {"type": str, "required": False, "default": "VF"},
+ "properties": {"type": dict, "required": False, "default": {}},
+ "relationship": {
+ "type": dict,
+ "required": False,
+ "default": {},
+ "nested": {
+ "relationship_type": {"type": str, "required": True},
+ "requirement": {"type": str, "required": True},
+ "requirement_id": {"type": str, "required": True},
+ "properties": {"type": dict, "required": False, "default": {}},
+ }
+ },
+ },
+ },
},
},
"network_roles": {
@@ -94,6 +120,7 @@ class VNF(Resource):
"properties": {"type": dict, "required": False, "default": {}},
},
},
+ "allow_update": {"type": bool, "required": False, "default": False},
}
def __init__(
@@ -105,6 +132,7 @@ class VNF(Resource):
vm_types=[],
network_roles=[],
policies=[],
+ allow_update=False,
):
vnf_input = {}
@@ -122,6 +150,7 @@ class VNF(Resource):
vnf_input["vm_types"] = vm_types
vnf_input["network_roles"] = network_roles
vnf_input["policies"] = policies
+ vnf_input["allow_update"] = allow_update
super().__init__(vnf_input)
@@ -129,8 +158,11 @@ class VNF(Resource):
"""Creates a vnf object in SDC"""
vnf = None
- if get_vnf_id(vnf_input.get("vnf_name")) is None:
+ existing = get_vnf_id(vnf_input.get("vnf_name"))
+ if not existing:
vnf = create_vnf(vnf_input)
+ elif vnf_input.get("allow_update"):
+ vnf = update_vnf(existing, vnf_input)
else:
raise exceptions.ResourceAlreadyExistsException(
"VNF resource {} already exists".format(vnf_input.get("vnf_name"))
@@ -149,39 +181,18 @@ class VNF(Resource):
for vm_type in vm_types:
vm_type_tag = vm_type.get("vm_type")
properties = vm_type.get("properties")
+ resources = vm_type.get("resources", [])
instance_ids = instance_ids_for_property(model, "vm_type_tag", vm_type_tag)
for instance_id in instance_ids:
- for k, v in properties.items():
- # updating vm_type properties
- self.add_instance_property(instance_id, k, v)
- vm_type_instances.append(instance_id)
- for network_role in network_roles:
- # checking if abstract node has matching network role,
- # and updating if found
- nrt = network_role.get("network_role_tag")
- nr = network_role.get("network_role")
- related_networks = network_role.get("related_networks")
- instance_property = network_role_property_for_instance(
- nrt, model, instance_id
- )
- if instance_property:
- self.add_instance_property(instance_id, instance_property, nr)
- if related_networks:
- property_val = [
- {"related_network_role": related_network_role}
- for related_network_role in related_networks
- ]
- rnr_instance_property = instance_property.replace(
- "_network_role", "_related_networks"
- )
- self.add_instance_property(
- instance_id,
- rnr_instance_property,
- str(property_val).replace("'", '\\"'),
- )
+ vm_type_instances.append(instance_id)
+ self._add_instance_properties(instance_id, properties)
+ self._add_resources(instance_id, resources)
+ self._add_vm_type_network_role(instance_id, network_roles)
for policy in policies:
policy_name = policy.get("policy_name")
+ if self.policy_exists(policy_name):
+ continue
policy_model = self.add_policy_resource(policy_name)
self.associate_policy(policy_model.catalog_resource_id, vm_type_instances)
for k, v in policy.get("properties", {}).items():
@@ -190,6 +201,115 @@ class VNF(Resource):
for k, v in inputs.items():
self.add_input_value(k, v)
+ def _add_instance_properties(self, instance_id, properties_dict):
+ for k, v in properties_dict.items():
+ # updating vm_type properties
+ self.add_instance_property(instance_id, k, v)
+
+ def _add_resources(self, instance_id, resources_dict):
+ for resource in resources_dict:
+ resource_name = resource.get("resource_name")
+
+ if self.resource_exists(resource_name):
+ continue
+
+ catalog_resource_name = resource.get("catalog_resource_name")
+ resource_id = resource.get("resource_id")
+ resource_origin = resource.get("origin_type")
+ resource_relationship = resource.get("relationship", {})
+
+ if not resource_id:
+ resource_id = get_vnf_id(catalog_resource_name)
+ if not resource_id:
+ raise exceptions.ResourceIDNotFoundException(
+ "resource ID was not passed, and resource lookup by name was not found {}".format(
+ resource_name
+ )
+ )
+ new_resource = add_resource(self.catalog_resource_id, resource_id, resource_name, origin_type=resource_origin)
+ new_resource_id = new_resource["id"]
+ if resource_relationship:
+ relationship_type = resource_relationship.get("relationship_type")
+ relationship_requirement = resource_relationship.get("requirement")
+ relationship_requirement_id = resource_relationship.get("requirement_id")
+ self.add_resource_relationship(new_resource_id, instance_id, relationship_type, relationship_requirement, relationship_requirement_id)
+ for k, v in resource_relationship.get("properties", {}).items():
+ self.add_instance_property_non_vf(new_resource_id, k, v, origin_section="componentInstancesProperties")
+
+ def add_resource_relationship(self, from_node, to_node, relationship_type, relationship_requirement, relationship_requirement_id):
+ components = self.tosca.get("componentInstances", [])
+ for component in components:
+ if component.get("uniqueId") == to_node:
+ capabilities = component.get("capabilities", {}).get(relationship_type, [])
+ for capability in capabilities:
+ capability_owner_id = capability.get("ownerId")
+ capability_name = capability.get("name")
+ capability_uid = capability.get("uniqueId")
+
+ return vnf_client.add_resource_relationship(
+ **self.attributes,
+ from_node_resource_id=from_node,
+ to_node_resource_id=to_node,
+ relationship_type=relationship_type,
+ capability_name=capability_name,
+ capability_owner_id=capability_owner_id,
+ capability_id=capability_uid,
+ requirement_name=relationship_requirement,
+ requirement_id=relationship_requirement_id,
+ )
+
+ def _add_vm_type_network_role(self, instance_id, network_roles_dict):
+ model = self.tosca
+ for network_role in network_roles_dict:
+ # checking if abstract node has matching network role,
+ # and updating if found
+ nrt = network_role.get("network_role_tag")
+ nr = network_role.get("network_role")
+ related_networks = network_role.get("related_networks")
+ instance_property = network_role_property_for_instance(
+ nrt, model, instance_id
+ )
+ if instance_property:
+ self.add_instance_property(instance_id, instance_property, nr)
+ if related_networks:
+ property_val = [
+ {"related_network_role": related_network_role}
+ for related_network_role in related_networks
+ ]
+ rnr_instance_property = instance_property.replace(
+ "_network_role", "_related_networks"
+ )
+ self.add_instance_property(
+ instance_id,
+ rnr_instance_property,
+ str(property_val).replace("'", '\\"'),
+ )
+
+ def resource_exists(self, resource_name):
+ """Checking the tosca model for a VF to see if a resource
+ has already been added"""
+
+ component_instances = self.tosca.get("componentInstances", [])
+
+ for component in component_instances:
+ if component.get("name") == resource_name:
+ return True
+
+ return False
+
+ def policy_exists(self, policy_name):
+ """Checking the tosca model for a VF to see if a resource
+ has already been added"""
+
+ policies = self.tosca.get("policies", {})
+
+ for p_name, policy in policies.items():
+ tosca_policy_name = policy.get("name").lower()
+ if tosca_policy_name.find("{}..{}".format(self.vnf_name.lower(), policy_name.lower())) != -1:
+ return True
+
+ return False
+
def _submit(self):
"""Submits the vnf in SDC"""
certification = vnf_client.certify_catalog_resource(
@@ -202,34 +322,6 @@ class VNF(Resource):
self.attributes["catalog_resource_name"] = vnf.catalog_resource_name
self.attributes["tosca"] = vnf.response_data
- def add_resource(
- self, catalog_resource_id, catalog_resource_name, origin_type="VF"
- ):
- """Attaches a resource to a VNF in SDC
-
- :catalog_resource_id: ID of a resource in the SDC catalog
- :catalog_resource_name: name to give to the resource when attaching to vnf
- :origin_type: specifies the origin of the attached resource
-
- """
- milli_timestamp = int(time.time() * 1000)
-
- resource_instance = vnf_client.add_resource_instance(
- **self.attributes,
- posX=306,
- posY=248,
- milli_timestamp=milli_timestamp,
- new_catalog_resource_id=catalog_resource_id,
- new_catalog_resource_name=catalog_resource_name,
- originType=origin_type,
- )
-
- response = {
- "id": resource_instance.catalog_resource_instance_id,
- "tosca": resource_instance.response_data,
- }
- self.attributes[catalog_resource_name] = response
-
def add_input_value(self, input_name, input_default_value):
"""Updates an input value on a VNF
@@ -262,7 +354,7 @@ class VNF(Resource):
# instance, policy, and group properties can probably be merged
# rn there is a lot of dup
- def add_instance_property(self, instance_id, property_name, property_value):
+ def add_instance_property(self, instance_id, property_name, property_value, origin_section="componentInstancesInputs"):
"""Updates an instance property on a abstract instance attached to a VNF
:instance_id: ID of a instance attached to a VNF
@@ -272,7 +364,7 @@ class VNF(Resource):
"""
self._refresh()
- instance_inputs = self.tosca.get("componentInstancesInputs", {}).get(
+ instance_inputs = self.tosca.get(origin_section, {}).get(
instance_id, {}
)
@@ -301,97 +393,82 @@ class VNF(Resource):
)
)
- def add_policy_property(self, policy_id, property_name, property_value):
- """Updates a policy property on a polic attached to a VNF
+ def add_instance_property_non_vf(self, instance_id, property_name, property_value, origin_section="componentInstancesProperties"):
+ """Updates an instance property on a abstract instance attached to a VNF
- :policy_id: ID of a policy attached to a VNF
+ :instance_id: ID of a instance attached to a VNF
:property_name: property name to update
:property_value: value to update property with
"""
self._refresh()
- policies = (
- self.tosca.get("policies", {}).get(policy_id, {}).get("properties", {})
+ instance_inputs = self.tosca.get(origin_section, {}).get(
+ instance_id, {}
)
- for prop in policies:
+ for prop in instance_inputs:
if prop.get("name") == property_name:
unique_id = prop.get("uniqueId")
+ parent_unique_id = prop.get("parentUniqueId")
+ owner_id = prop.get("ownerId")
+ schemaType = prop.get("schemaType", "")
property_type = prop.get("type")
- description = prop.get("description")
- return vnf_client.add_catalog_policy_property(
+ return vnf_client.add_catalog_resource_property_non_vf(
**self.attributes,
unique_id=unique_id,
- catalog_policy_id=policy_id,
+ parent_unique_id=parent_unique_id,
+ owner_id=owner_id,
+ catalog_resource_instance_id=instance_id,
property_name=property_name,
property_default_value=property_value,
- description=description,
+ schema_type=schemaType,
property_type=property_type,
)
raise exceptions.PropertyNotFoundException(
- "Property {} was not found in policy {}".format(property_name, policy_id)
+ "Property {} was not found in Instance {}".format(
+ property_name, instance_id
+ )
)
- def add_group_property(self, group_id, property_name, property_value):
- """Updates a group property on a group attached to a VNF
+ def add_policy_property(self, policy_id, property_name, property_value):
+ """Updates a policy property on a polic attached to a VNF
- :group_id: ID of a group attached to a VNF
+ :policy_id: ID of a policy attached to a VNF
:property_name: property name to update
:property_value: value to update property with
"""
self._refresh()
- groups = self.tosca.get("groups", [])
-
- for group in groups:
- if group.get("uniqueId") == group_id:
- properties = group.get("properties", [])
- for prop in properties:
- unique_id = prop.get("uniqueId")
- property_type = prop.get("type")
- description = prop.get("description")
- parent_unique_id = prop.get("parentUniqueId")
- owner_id = prop.get("ownerId")
- return vnf_client.add_catalog_group_property(
- **self.attributes,
- unique_id=unique_id,
- catalog_group_id=group_id,
- property_name=property_name,
- property_default_value=property_value,
- description=description,
- property_type=property_type,
- parent_unique_id=parent_unique_id,
- owner_id=owner_id,
- )
-
- raise exceptions.PropertyNotFoundException(
- "Property {} was not found in group {}".format(property_name, group_id)
+ policies = (
+ self.tosca.get("policies", {}).get(policy_id, {}).get("properties", {})
)
- def add_group_resource(self, group_name):
- """Adds an SDC group resource to a VNF
-
- :group_name: name of the group, matching onap-client.conf
-
- """
- sdc_properties = sdc.SDC_PROPERTIES
- group = sdc_properties.GROUPS.get(group_name)
- if not group:
- raise exceptions.UnknownGroupException(
- "Group {} was not found in configuration file".format(group_name)
- )
+ for prop in policies:
+ if prop.get("name") == property_name:
+ unique_id = prop.get("uniqueId")
+ property_type = prop.get("type")
+ description = prop.get("description")
+ return vnf_client.add_catalog_policy_property(
+ **self.attributes,
+ unique_id=unique_id,
+ catalog_policy_id=policy_id,
+ property_name=property_name,
+ property_default_value=property_value,
+ description=description,
+ property_type=property_type,
+ )
- return vnf_client.add_catalog_resource_group(
- **self.attributes, catalog_group_name=group
+ raise exceptions.PropertyNotFoundException(
+ "Property {} was not found in policy {}".format(property_name, policy_id)
)
def add_policy_resource(self, policy_name):
"""Adds an SDC policy resource to a VNF
- :group_name: name of the policy, matching onap-client.conf
+ :policy_name: name of the policy, matching onap-client.conf
"""
sdc_properties = sdc.SDC_PROPERTIES
@@ -417,18 +494,30 @@ class VNF(Resource):
**self.attributes, catalog_policy_id=policy_id, instance_ids=instance_ids
)
- def associate_group(self, group_id, instance_id):
- """associates an SDC group resource to an VNF instance resource"""
- return vnf_client.add_group_to_instance(
- **self.attributes, catalog_group_id=group_id, instance_id=instance_id
- )
-
def _refresh(self):
"""GETs the VNF model from SDC and updates the VNF object"""
vnf = vnf_client.get_catalog_resource(**self.attributes)
self.attributes["tosca"] = vnf.response_data
+def update_vnf(catalog_resource_id, vnf_input):
+ vnf = vnf_client.checkout_catalog_resource(catalog_resource_id=catalog_resource_id).response_data
+
+ new_vnf_metadata = vnf_client.get_catalog_resource_metadata(catalog_resource_id=vnf.get("uniqueId")).response_data.get("metadata", {})
+
+ csar_version = vsp.get_vsp_version_id(vnf.get("csarUUID"), search_key="name")
+
+ vnf["csarVersion"] = csar_version
+ vnf["componentMetadata"] = new_vnf_metadata
+
+ updated_vnf = vnf_client.update_catalog_resource(catalog_resource_id=vnf.get("uniqueId"), payload_data=json.dumps(vnf)).response_data
+
+ vnf_input["catalog_resource_id"] = updated_vnf.get("uniqueId")
+ vnf_input["tosca"] = updated_vnf
+
+ return vnf_input
+
+
def create_vnf(vnf_input):
"""Creates a vnf object in SDC
@@ -490,6 +579,33 @@ def network_role_property_for_instance(network_role_tag, vnf_model, instance_id)
return None
+def add_resource(parent_resource_id, catalog_resource_id, catalog_resource_name, origin_type="VF"):
+ """Attaches a resource to a VNF in SDC
+
+ :catalog_resource_id: ID of a resource in the SDC catalog
+ :catalog_resource_name: name to give to the resource when attaching to vnf
+ :origin_type: specifies the origin of the attached resource
+
+ """
+ milli_timestamp = int(time.time() * 1000)
+
+ resource_instance = vnf_client.add_resource_instance(
+ catalog_resource_id=parent_resource_id,
+ posX=random.randrange(150, 550), # nosec
+ posY=random.randrange(150, 450), # nosec
+ milli_timestamp=milli_timestamp,
+ new_catalog_resource_id=catalog_resource_id,
+ new_catalog_resource_name=catalog_resource_name,
+ originType=origin_type,
+ )
+
+ response = {
+ "id": resource_instance.catalog_resource_instance_id,
+ "tosca": resource_instance.response_data,
+ }
+ return response
+
+
@utility
def get_vnf(vnf_name):
"""Queries SDC for the TOSCA model for a VNF"""