diff options
-rw-r--r-- | share/starlingx_base/resource/infra_workload.py | 170 |
1 files changed, 167 insertions, 3 deletions
diff --git a/share/starlingx_base/resource/infra_workload.py b/share/starlingx_base/resource/infra_workload.py index 61db8a72..8fea68f3 100644 --- a/share/starlingx_base/resource/infra_workload.py +++ b/share/starlingx_base/resource/infra_workload.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os import logging from django.conf import settings @@ -47,7 +48,7 @@ class InfraWorkload(newton_infra_workload.InfraWorkload): } try: - worker_self = infra_workload_helper.InfraWorkloadHelper( + worker_self = InfraWorkloadHelper( settings.MULTICLOUD_API_V1_PREFIX, settings.AAI_BASE_URL ) @@ -143,7 +144,7 @@ class InfraWorkload(newton_infra_workload.InfraWorkload): backlog_item = gInfraWorkloadThread.get(workloadid) if not backlog_item: # backlog item not found, so check the stack status - worker_self = infra_workload_helper.InfraWorkloadHelper( + worker_self = InfraWorkloadHelper( settings.MULTICLOUD_API_V1_PREFIX, settings.AAI_BASE_URL ) @@ -202,7 +203,7 @@ class InfraWorkload(newton_infra_workload.InfraWorkload): super(InfraWorkload, self).delete(request, vimid, workloadid) # backlog for a post to heatbridge delete - worker_self = infra_workload_helper.InfraWorkloadHelper( + worker_self = InfraWorkloadHelper( settings.MULTICLOUD_API_V1_PREFIX, settings.AAI_BASE_URL ) @@ -287,3 +288,166 @@ class APIv1InfraWorkload(InfraWorkload): vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) return super(APIv1InfraWorkload, self).delete(request, vimid, requri) + +class InfraWorkloadHelper(infra_workload_helper.InfraWorkloadHelper): + + def __init__(self, multicloud_prefix, aai_base_url): + super(InfraWorkloadHelper, self).__init__(multicloud_prefix, aai_base_url) + self._logger = logger + + def param_update_user_directives(self, parameters, oof_directives): + return parameters + + def param_update_sdnc_directives(self, parameters, sdnc_directives): + return parameters + + def param_update_oof_directives(self, parameters, oof_directives): + for directive in oof_directives.get("directives", []): + if directive["type"] == "vnfc": + for directive2 in directive.get("directives", []): + if directive2["type"] in ["flavor_directives", + "sriovNICNetwork_directives"]: + for attr in directive2.get("attributes", []): + flavor_label = attr.get("attribute_name", None) + flavor_value = attr.get("attribute_value", None) + if flavor_label in parameters: + parameters[flavor_label] = flavor_value + else: + self._logger.warn( + "There is no parameter exist: %s" % + flavor_label) + + return parameters + + def openstack_template_update(self, template_data, vf_module_model_customization_id): + # try 1: check if artifact is available with vfmodule_uuid + # assumption: mount point: /opt/artifacts/<vfmodule_uuid> + try: + vfmodule_path_base = r"/opt/artifacts/%s" % vf_module_model_customization_id + vfmodule_metadata_path = r"%s/vfmodule-meta.json" % vfmodule_path_base + service_metadata_path = r"%s/service-meta.json" % vfmodule_path_base + with open(vfmodule_metadata_path, + 'r', encoding='UTF-8') as vf: + vfmodule_metadata = vf.read() # assume the metadata file size is small + if vfmodule_metadata and len(vfmodule_metadata) > 0: + # load service-metadata + with open(service_metadata_path, + 'r', encoding='UTF-8') as sf: + service_metadata = sf.read() # assume the metadata file size is small + if service_metadata and len(service_metadata) > 0: + # get the artifacts uuid + artifacts_uuids = vfmodule_metadata.get("artifacts", None) + templatedata1 = {}.update(template_data) + for a in service_metadata["artifacts"]: + artifactUUID = a.get("artifactUUID", "") + if artifactUUID not in artifacts_uuids: + continue + artifact_type = a.get("artifactType", "") + artifact_name = a.get("artifactName", "") + artifact_path = r"%s/%s" % (vfmodule_path_base, artifact_name) + + # now check the type + if artifact_type.lower() == "heat": + # heat template file + with open(artifact_path, + 'r', encoding='UTF-8') as af: + templatedata1["template"] = af.read() # assume the template file size is small + # pass + + elif artifact_type.lower() == "heat_env": + # heat env file + with open(artifact_path, + 'r', encoding='UTF-8') as af: + templatedata1["parameters"] = af.read() # assume the env file size is small + # pass + # pass + return templatedata1 + else: + pass + else: + self._logger.info("artifacts not available for vfmodule %s" % vfmodule_uuid) + pass + except Exception as e: + self._logger.error("template_update fails: %s" % e.message) + + # try 2: reuse the input: template_data + return template_data + + def workload_create(self, vimid, workload_data): + ''' + Instantiate a stack over target cloud region (OpenStack instance) + The template for workload will be fetched from sdc client + :param vimid: + :param workload_data: + :return: result code, status enum, status reason + result code: 0-ok, otherwise error + status enum: "WORKLOAD_CREATE_IN_PROGRESS", "WORKLOAD_CREATE_FAIL" + status reason: message to explain the status enum + ''' + + # step 2: normalize the input: xxx_directives + data = workload_data + vf_module_model_customization_id = data.get("vf-module-model-customization-id", None) + vf_module_id = data.get("vf-module-id", "") + user_directive = data.get("user_directives", {}) + oof_directive = data.get("oof_directives", {}) + sdnc_directive = data.get("sdnc_directives", {}) + template_type = data.get("template_type", None) + template_data = data.get("template_data", {}) + # resp_template = None + if not template_type or "heat" != template_type.lower(): + return 14, "WORKLOAD_CREATE_FAIL", \ + "Bad parameters: template type %s is not heat" %\ + template_type or "" + + # retrieve the template data + template_data = self.openstack_template_update(template_data, vf_module_model_customization_id) + + # update the parameter in order of reverse precedence + parameters = template_data.get("parameters", {}) + parameters = self.param_update_sdnc_directives(parameters, sdnc_directive) + parameters = self.param_update_oof_directives(parameters, oof_directive) + parameters = self.param_update_user_directives(parameters, user_directive) + template_data["parameters"] = parameters + + # reset to make sure "files" are empty + template_data["files"] = {} + + template_data["stack_name"] = vf_module_id \ + if not hasattr(template_data, "stack_name")\ + else template_data["stack_name"] + + # authenticate + cloud_owner, regionid = extsys.decode_vim_id(vimid) + # should go via multicloud proxy so that + # the selflink is updated by multicloud + retcode, v2_token_resp_json, os_status = \ + helper.MultiCloudIdentityHelper( + settings.MULTICLOUD_API_V1_PREFIX, + cloud_owner, regionid, "/v2.0/tokens" + ) + if retcode > 0 or not v2_token_resp_json: + errmsg = "authenticate fails:%s,%s, %s" %\ + (cloud_owner, regionid, v2_token_resp_json) + logger.error(errmsg) + return ( + retcode, "WORKLOAD_CREATE_FAIL", errmsg + ) + + # tenant_id = v2_token_resp_json["access"]["token"]["tenant"]["id"] + service_type = "orchestration" + resource_uri = "/stacks" + self._logger.info("create stack resources, URI:%s" % resource_uri) + retcode, content, os_status = \ + helper.MultiCloudServiceHelper(cloud_owner, regionid, + v2_token_resp_json, + service_type, resource_uri, + template_data, "POST") + + if retcode == 0: + stack1 = content.get('stack', None) + # stackid = stack1["id"] if stack1 else "" + return 0, "WORKLOAD_CREATE_IN_PROGRESS", stack1 + else: + self._logger.info("RESP with data> result:%s" % content) + return retcode, "WORKLOAD_CREATE_FAIL", content |