def input(self) -> Input: """Property input. Returns property Input object. Returns None if property has no associated input. Raises: ParameterError: Input has no associated SdcResource ParameterError: Input for given property does not exits. It shouldn't ever happen, but it's possible if after you get property object someone delete input. Returns: Input: Property input object. """ if not self.sdc_resource: raise ParameterError("Property has no associated SdcResource") if not self.get_input_values: return None try: return next(filter(lambda x: x.unique_id == self.get_input_values[0].get("inputId"), self.sdc_resource.inputs)) except StopIteration: raise ParameterError("Property input does not exist")
def add_op_policy_config(self, func, **kwargs) -> None: """ Add operational policy configuration. Add operation policy configuration using payload data. Args: func (function): policy configuration function in (add_drools_conf, add_minmax_config, add_frequency_limiter) """ data = func(**kwargs) if not data: raise ParameterError("Payload data from configuration is None.") if self.operational_policies: self.operational_policies = self.operational_policies[:-1] + "," data = data[1:] self.operational_policies += data url = f"{self.base_url()}/loop/updateOperationalPolicies/{self.name}" self.send_message('POST', 'ADD operational policy config', url, data=self.operational_policies) self._logger.info(("Files for op policy config %s have been uploaded to loop's" "Op policy"), self.name)
def set_property_value(self, property_obj: Property, value: Any) -> None: """Set property value. Set given value to resource property Args: property_obj (Property): Property object value (Any): Property value to set Raises: ParameterError: if the given property is not the resource's property """ if not self.is_own_property(property_obj): raise ParameterError("Given property is not a resource's property") self._logger.debug("Set %s property value", property_obj.name) self.send_message_json("PUT", f"Set {property_obj.name} value to {value}", self.add_property_url, data=jinja_env().get_template( "sdc_resource_set_property_value.json.j2").\ render( sdc_resource=self, property=property_obj, value=value ) )
def onboard(self) -> None: """Onboard the Service in SDC. Raises: StatusError: service has an invalid status ParameterError: no resources, no properties for service in DRAFT status """ # first Lines are equivalent for all onboard functions but it's more # readable if not self.status: # equivalent step as in onboard-function in sdc_resource self.create() time.sleep(self._time_wait) self.onboard() elif self.status == const.DRAFT: if not any([self.resources, self._properties_to_add]): raise ParameterError("No resources nor properties were given") self.declare_resources_and_properties() self.checkin() time.sleep(self._time_wait) self.onboard() elif self.status == const.CHECKED_IN: self.certify() time.sleep(self._time_wait) self.onboard() elif self.status == const.CERTIFIED: self.distribute() self.onboard() elif self.status == const.DISTRIBUTED: self._logger.info("Service %s onboarded", self.name) else: self._logger.error("Service has invalid status: %s", self.status) raise StatusError(self.status)
def create(self) -> None: """Create the PNF in SDC if not already existing.""" if not self.vsp and not self.vendor: raise ParameterError("Neither Vsp nor Vendor provided.") self._create("pnf_create.json.j2", name=self.name, vsp=self.vsp, vendor=self.vendor, category=self.category)
def create(self) -> None: """Create the Vf in SDC if not already existing. Raises: ParameterError: VSP is not provided during VF object initalization """ if not any([self.vsp, self.vendor]): raise ParameterError("At least vsp or vendor needs to be given") self._create("vf_create.json.j2", name=self.name, vsp=self.vsp, category=self.category, vendor=self.vendor)
def add_operational_policy(self, policy_type: str, policy_version: str) -> None: """ Add operational policy to the loop instance. Args: policy_type (str): the full policy model type policy_version (str): policy version Raises: ParameterError : Corrupt response or a key in a dictionary not found. It will also be raised when the response contains more operational policies than there are currently. """ url = (f"{self.base_url()}/loop/addOperationaPolicy/{self.name}/" f"policyModel/{policy_type}/{policy_version}") add_response = self.send_message_json('PUT', 'Create Operational Policy', url) key = "operationalPolicies" try: if self.details[key] is None: self.details[key] = [] response_policies = add_response[key] current_policies = self.details[key] except KeyError as exc: msg = 'Corrupt response, current loop details. Key not found.' raise ParameterError(msg) from exc if len(response_policies) > len(current_policies): self.details = add_response else: raise ParameterError("Couldn't add the operational policy.")
def onboard(self) -> None: """Onboard the VSP in SDC.""" status: Optional[str] = self.status if not status: if not self._vendor: raise ParameterError("No Vendor provided.") self.create() self.onboard() elif status == const.DRAFT: if not self.package: raise ParameterError("No file/package provided.") self.upload_package(self.package) self.onboard() elif status == const.UPLOADED: self.validate() self.onboard() elif status == const.VALIDATED: self.commit() self.onboard() elif status == const.COMMITED: self.submit() self.onboard() elif status == const.CERTIFIED: self.create_csar()
def __post_init__(self) -> None: """Post init subnet method. Checks if both dhcp_start_address and dhcp_end_address values are provided if dhcp is enabled. Raises: ParameterError: Neither dhcp_start_addres nor dhcp_end_address are provided """ if self.dhcp_enabled and \ not all([self.dhcp_start_address, self.dhcp_end_address]): msg = "DHCP is enabled but neither DHCP " \ "start nor end adresses are provided." raise ParameterError(msg)
def cloud_region(self) -> "CloudRegion": """Cloud region associated with service subscription. IT'S DEPRECATED! `cloud_regions` parameter SHOULD BE USED Raises: ParameterError: Service subscription has no associated cloud region. Returns: CloudRegion: CloudRegion object """ try: return next(self.cloud_regions) except StopIteration: msg = f"No cloud region for service subscription '{self.name}'" raise ParameterError(msg)
def tenant(self) -> "Tenant": """Tenant associated with service subscription. IT'S DEPRECATED! `tenants` parameter SHOULD BE USED Raises: ParameterError: Service subscription has no associated tenants Returns: Tenant: Tenant object """ try: return next(self.tenants) except StopIteration: msg = f"No tenants for service subscription '{self.name}'" raise ParameterError(msg)
def get_workflow_by_name(self, workflow_name: str) -> Workflow: """Get workflow by name. If there is no workflow with given name `ParameterError` is going to be raised. Args: workflow_name (str): Name of the workflow Returns: Workflow: Workflow with given name """ try: return next( filter(lambda workflow: workflow.name == workflow_name, self.workflows)) except StopIteration: raise ParameterError("Workflow with given name does not exist")
def get_property(self, property_name: str) -> "ComponentProperty": """Get component property by it's name. Args: property_name (str): property name Raises: ParameterError: Component has no property with given name Returns: ComponentProperty: Component's property object """ for property_obj in self.properties: if property_obj.name == property_name: return property_obj msg = f"Component has no property with {property_name} name" raise ParameterError(msg)
def extract_operational_policy_name(self, policy_type: str) -> str: """ Return operational policy name for a closed loop and a given policy. Args: policy_type (str): the policy acronym. Raises: ParameterError : Couldn't load the operational policy name. Returns: Operational policy name in the loop details after adding a policy. """ for policy in filter(lambda x: x["policyModel"]["policyAcronym"] == policy_type, self.details["operationalPolicies"]): return policy["name"] raise ParameterError("Couldn't load the operational policy name.")
def store_resolved_template(self, resolved_template: str) -> None: """Store resolved template. Args: resolved_template (str): Template to store Raises: ParameterError: To store template it's needed to pass artifact name and: - resolution key, or - resource type and resource id. If not all needed parameters are given that exception will be raised. """ if self.artifact_name and self.resolution_key: return self.store_resolved_template_with_resolution_key( resolved_template) if self.artifact_name and self.resource_type and self.resource_id: return self.store_resolved_template_with_resource_type_and_id( resolved_template) raise ParameterError( "To store template artifact name with resolution key or both " "resource type and id is needed")
def _get_related_instance(self, related_instance_class: Union[Type[NetworkInstance], Type[VnfInstance]], relationship_related_to_type: str) -> Iterator[\ Union[NetworkInstance, VnfInstance]]: """Iterate through related service instances. This is method which for given `relationship_related_to_type` creates iterator it iterate through objects which are related with service. Args: related_instance_class (Union[Type[NetworkInstance], Type[VnfInstance]]): Class object to create required object instances relationship_related_to_type (str): Has to be "generic-vnf" or "l3-network" Raises: ParameterError: relationship_related_to_type does not satisfy the requirements Yields: Iterator[ Union[NetworkInstance, VnfInstance]]: [description] """ if not relationship_related_to_type in [ "l3-network", "generic-vnf", "pnf" ]: msg = (f'Invalid "relationship_related_to_type" value. ' f'Provided "{relationship_related_to_type}". ' f'Has to be "l3-network" or "generic-vnf".') raise ParameterError(msg) for relationship in self.relationships: if relationship.related_to == relationship_related_to_type: yield related_instance_class.create_from_api_response(\ self.send_message_json("GET", (f"Get {self.instance_id} " f"{related_instance_class.__class__.__name__}"), f"{self.base_url}{relationship.related_link}"), self)
def declare_input(self, input_to_declare: Union[Property, NestedInput]) -> None: """Declare input for given property or nested input object. Call SDC FE API to declare input for given property. Args: input_declaration (Union[Property, NestedInput]): Property to declare input or NestedInput object Raises: ParameterError: if the given property is not SDC resource property """ self._logger.debug("Declare input") if isinstance(input_to_declare, Property): if self.is_own_property(input_to_declare): self.declare_input_for_own_property(input_to_declare) else: msg = "Given property is not SDC resource property" raise ParameterError(msg) else: self.declare_nested_input(input_to_declare)
def instantiate_macro(cls, sdc_service: "SdcService", customer: "Customer", owning_entity: OwningEntity, project: str, line_of_business: str, platform: str, aai_service: "AaiService" = None, cloud_region: "CloudRegion" = None, tenant: "Tenant" = None, service_instance_name: str = None, vnf_parameters: Iterable["VnfParameters"] = None, enable_multicloud: bool = False, so_service: "SoService" = None, service_subscription: "ServiceSubscription" = None ) -> "ServiceInstantiation": """Instantiate service using SO macro request. Args: sdc_service (SdcService): Service to instantiate customer (Customer): Customer to use in instantiation request owning_entity (OwningEntity): Owning entity to use in instantiation request project (Project): Project name to use in instantiation request line_of_business_object (LineOfBusiness): LineOfBusiness name to use in instantiation request platform_object (Platform): Platform name to use in instantiation request aai_service (AaiService): Service object from aai sdc cloud_region (CloudRegion): Cloud region to use in instantiation request tenant (Tenant): Tenant to use in instantiation request service_instance_name (str, optional): Service instance name. Defaults to None. vnf_parameters: (Iterable[VnfParameters]): Parameters which are going to be used for vnfs instantiation. Defaults to None. enable_multicloud (bool, optional): Determines if Multicloud should be enabled for instantiation request. Defaults to False. so_service (SoService, optional): SO values to use in instantiation request service_subscription(ServiceSubscription, optional): Customer service subscription for the instantiated service. Required if so_service is not provided. Raises: StatusError: if a service is not distributed. Returns: ServiceInstantiation: instantiation request object """ template_file = "instantiate_service_macro.json.j2" if so_service: template_file = "instantiate_multi_vnf_service_macro.json.j2" if so_service.instance_name: service_instance_name = so_service.instance_name else: if not service_subscription: raise ParameterError("If no so_service is provided, " "service_subscription parameter is required!") if service_instance_name is None: service_instance_name = f"Python_ONAP_SDK_service_instance_{str(uuid4())}" if not sdc_service.distributed: msg = f"Service {sdc_service.name} is not distributed." raise StatusError(msg) response: dict = cls.send_message_json( "POST", f"Instantiate {sdc_service.name} service macro", (f"{cls.base_url}/onap/so/infra/" f"serviceInstantiation/{cls.api_version}/serviceInstances"), data=jinja_env().get_template(template_file). \ render( so_service=so_service, sdc_service=sdc_service, cloud_region=cloud_region, tenant=tenant, customer=customer, owning_entity=owning_entity, project=project, aai_service=aai_service, line_of_business=line_of_business, platform=platform, service_instance_name=service_instance_name, vnf_parameters=vnf_parameters, enable_multicloud=enable_multicloud, service_subscription=service_subscription ), headers=headers_so_creator(OnapService.headers) ) return cls( name=service_instance_name, request_id=response["requestReferences"].get("requestId"), instance_id=response["requestReferences"].get("instanceId"), sdc_service=sdc_service, cloud_region=cloud_region, tenant=tenant, customer=customer, owning_entity=owning_entity, project=project )