X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=common%2Fpython%2Frift%2Fmano%2Ftosca_translator%2Frwmano%2Ftosca%2Ftosca_compute.py;h=190a5b453c3fc56c108a77a3880d557926503c9d;hb=f314b4af9744068a7ed7a6a6314220c3aa857523;hp=2b244d7ac411e1431a8ed0363d139cbc2c9e7a2d;hpb=49868d2c71eb364cee9707515be6841a568dad40;p=osm%2FSO.git diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py index 2b244d7a..190a5b45 100755 --- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py @@ -39,7 +39,23 @@ class ToscaCompute(ManoResource): 'cloud-init-file',] IGNORE_PROPS = [] - toscatype = 'tosca.nodes.Compute' + toscatype = 'tosca.nodes.nfv.VDU' + + VALUE_TYPE_CONVERSION_MAP = { + 'integer': 'INT', + 'string':'STRING', + 'float':'DECIMAL' + } + + + TOSCA_MEM_SIZE = { + 'huge': 'LARGE', + 'normal': 'SMALL', + 'size_2MB': 'SIZE_2MB', + 'size_1GB': 'SIZE_1GB', + 'prefer_huge': 'PREFER_LARGE' + + } def __init__(self, log, nodetemplate, metadata=None): super(ToscaCompute, self).__init__(log, @@ -54,6 +70,9 @@ class ToscaCompute(ManoResource): self._vnf = None self._yang = None self._id = self.name + self._monitor_param = [] + self._mgmt_interface = {} + self._http_endpoint = None @property def image(self): @@ -82,12 +101,7 @@ class ToscaCompute(ManoResource): format(self.name, tosca_props)) vdu_props = {} for key, value in tosca_props.items(): - if key == 'cloud_init': - vdu_props['cloud-init'] = value - elif key == 'cloud-init-file': - self._cloud_init = "../cloud_init/{}".format(value) - else: - vdu_props[key] = value + vdu_props[key] = value if 'name' not in vdu_props: vdu_props['name'] = self.name @@ -104,6 +118,39 @@ class ToscaCompute(ManoResource): def handle_capabilities(self): + def get_mgmt_interface(specs): + mgmt_intfce = {} + mgmt_intfce['vdu-id'] = self.id + if 'dashboard_params' in specs: + mgmt_intfce['dashboard-params'] = {'path':specs['dashboard_params']['path'], 'port':specs['dashboard_params']['port']} + if 'port' in specs: + mgmt_intfce['port'] = specs['port'] + return mgmt_intfce; + + def get_monitor_param(specs, monitor_id): + monitor_param = {} + monitor_param['id'] = monitor_id + if 'name' in specs: + monitor_param['name'] = specs['name'] + if 'json_query_method' in specs: + monitor_param['json_query_method'] = specs['json_query_method'].upper() + if 'description' in specs: + monitor_param['description'] = specs['description'] + if 'url_path' in specs: + monitor_param['http-endpoint-ref'] = specs['url_path'] + if 'ui_data' in specs: + if 'widget_type' in specs['ui_data']: + monitor_param['widget-type'] = specs['ui_data']['widget_type'].upper() + if 'units' in specs['ui_data']: + monitor_param['units'] = specs['ui_data']['units'] + if 'group_tag' in specs['ui_data']: + monitor_param['group_tag'] = specs['ui_data']['group_tag'] + if 'constraints' in specs: + if 'value_type' in specs['constraints']: + monitor_param['value-type'] = ToscaCompute.VALUE_TYPE_CONVERSION_MAP[specs['constraints']['value_type']] + + return monitor_param + def get_vm_flavor(specs): vm_flavor = {} if 'num_cpus' in specs: @@ -125,14 +172,144 @@ class ToscaCompute(ManoResource): return vm_flavor + def get_host_epa(specs): + host_epa = {} + if 'cpu_model' in specs: + host_epa["cpu-model"] = specs['cpu_model'].upper() + if 'cpu_arch' in specs: + host_epa["cpu-arch"] = specs['cpu_arch'].upper() + if 'cpu_vendor' in specs: + host_epa["cpu-vendor"] = specs['cpu_vendor'].upper() + if 'cpu_socket_count' in specs: + host_epa["cpu-socket-count"] = specs['cpu_socket_count'] + if 'cpu_core_count' in specs: + host_epa["cpu-core-count"] = specs['cpu_core_count'] + if 'cpu_core_thread_count' in specs: + host_epa["cpu-core-thread-count"] = specs['cpu_core_thread_count'] + if 'om_cpu_model_string' in specs: + host_epa["om-cpu-model-string"] = specs['om_cpu_model_string'] + if 'cpu_feature' in specs: + cpu_feature_prop = [] + for spec in specs['cpu_feature']: + cpu_feature_prop.append({'feature':spec.upper()}) + host_epa['cpu-feature'] = cpu_feature_prop + if 'om_cpu_feature' in specs: + cpu_feature_prop = [] + for spec in specs['om_cpu_feature']: + cpu_feature_prop.append({'feature':spec}) + host_epa['om-cpu-feature'] = cpu_feature_prop + return host_epa; + + def get_vswitch_epa(specs): + vswitch_epa = {} + if 'ovs_acceleration' in specs: + vswitch_epa['ovs-acceleration'] = specs['ovs_acceleration'].upper() + if 'ovs_offload' in specs: + vswitch_epa['ovs-offload'] = specs['ovs_offload'].upper() + return vswitch_epa + + def get_hypervisor_epa(specs): + hypervisor_epa = {} + if 'type' in specs: + hypervisor_epa['type'] = specs['type'].upper() + if 'version' in specs: + hypervisor_epa['version'] = str(specs['version']) + + return hypervisor_epa + + def get_guest_epa(specs, nfv_comput_specs): + guest_epa = {} + guest_epa['numa-node-policy'] = {} + guest_epa['numa-node-policy']['node'] = [] + if 'mem_policy' in specs: + guest_epa['numa-node-policy']['mem-policy'] = specs['mem_policy'].upper() + if 'node_cnt' in specs: + guest_epa['numa-node-policy']['node-cnt'] = specs['node_cnt'] + if 'node' in specs: + for node in specs['node']: + node_prop = {} + if 'id' in node: + node_prop['id'] = node['id'] + if 'mem_size' in node: + if 'MiB' in node['mem_size'] or 'MB' in node['mem_size']: + node_prop['memory-mb'] = int(node['mem_size'].replace('MB','')) + else: + err_msg = "Specify mem_size of NUMA extension should be in MB" + raise ValidationError(message=err_msg) + if 'vcpus' in node: + vcpu_lis =[] + for vcpu in node['vcpus']: + vcpu_lis.append({'id': vcpu}) + node_prop['vcpu'] = vcpu_lis + if 'om_numa_type' in node: + numa_type = node['om_numa_type'] + if 'paired-threads' == numa_type: + node_prop['paired_threads'] = {} + node_prop['paired_threads']['num_paired_threads'] = node['paired_threads']['num_paired_threads'] + elif 'threads' == numa_type: + if 'num_threads' in node: + node_prop['num_threads'] = node['num_threads'] + elif 'cores' == numa_type: + if 'num_cores' in node: + node_prop['num_cores'] = node['num_cores'] + else: + err_msg = "om_numa_type should be among cores, paired-threads or threads" + raise ValidationError(message=err_msg) + guest_epa['numa-node-policy']['node'].append(node_prop) + + if 'mem_page_size' in nfv_comput_specs: + guest_epa['mempage-size'] = self.TOSCA_MEM_SIZE[nfv_comput_specs['mem_page_size']] + if 'cpu_allocation' in nfv_comput_specs: + if 'cpu_affinity' in nfv_comput_specs['cpu_allocation']: + guest_epa['cpu-pinning-policy'] = nfv_comput_specs['cpu_allocation']['cpu_affinity'].upper() + guest_epa['trusted-execution'] = False + if 'thread_allocation' in nfv_comput_specs['cpu_allocation']: + guest_epa['cpu-thread-pinning-policy'] = nfv_comput_specs['cpu_allocation']['thread_allocation'].upper() + + return guest_epa + tosca_caps = self.get_tosca_caps() self.log.debug(_("VDU {0} tosca capabilites: {1}"). format(self.name, tosca_caps)) - - if 'host' in tosca_caps: - self.properties['vm-flavor'] = get_vm_flavor(tosca_caps['host']) + if 'nfv_compute' in tosca_caps: + self.properties['vm-flavor'] = get_vm_flavor(tosca_caps['nfv_compute']) self.log.debug(_("VDU {0} properties: {1}"). format(self.name, self.properties)) + if 'host_epa' in tosca_caps: + self.properties['host-epa'] = get_host_epa(tosca_caps['host_epa']) + if 'hypervisor_epa' in tosca_caps: + self.properties['hypervisor-epa'] = get_hypervisor_epa(tosca_caps['hypervisor_epa']) + if 'vswitch_epa' in tosca_caps: + self.properties['vswitch-epa'] = get_vswitch_epa(tosca_caps['vswitch_epa']) + if 'numa_extension' in tosca_caps: + self.properties['guest-epa'] = get_guest_epa(tosca_caps['numa_extension'], tosca_caps['nfv_compute']) + if 'monitoring_param' in tosca_caps: + self._monitor_param.append(get_monitor_param(tosca_caps['monitoring_param'], '1')) + if 'mgmt_interface' in tosca_caps: + self._mgmt_interface = get_mgmt_interface(tosca_caps['mgmt_interface']) + if len(self._mgmt_interface) > 0: + prop = {} + if 'dashboard-params' in self._mgmt_interface: + if 'path' in self._mgmt_interface['dashboard-params']: + prop['path'] = self._mgmt_interface['dashboard-params']['path'] + if 'port' in self._mgmt_interface['dashboard-params']: + prop['port'] = self._mgmt_interface['dashboard-params']['port'] + self._http_endpoint = prop + + mon_idx = 2 + monitoring_param_name = 'monitoring_param_1' + while True: + if monitoring_param_name in tosca_caps: + self._monitor_param.append(get_monitor_param(tosca_caps[monitoring_param_name], str(mon_idx))) + mon_idx += 1 + monitoring_param_name = 'monitoring_param_{}'.format(mon_idx) + else: + break + + # THis is a quick hack to remove monitor params without name + for mon_param in list(self._monitor_param): + if 'name' not in mon_param: + self._monitor_param.remove(mon_param) def handle_artifacts(self): if self.artifacts is None: @@ -145,20 +322,20 @@ class ToscaCompute(ManoResource): if isinstance(props, dict): details = {} for name, value in props.items(): - if name == 'type': + if name == 'type' and value == 'tosca.artifacts.Deployment.Image.riftio.QCOW2': prefix, type_ = value.rsplit('.', 1) if type_ == 'QCOW2': details['type'] = 'qcow2' - else: - err_msg = _("VDU {0}, Currently only QCOW2 images " - "are supported in artifacts ({1}:{2})"). \ - format(self.name, key, value) - self.log.error(err_msg) - raise ValidationError(message=err_msg) + self._image = props['file'] + self.properties['image'] = os.path.basename(props['file']) + elif name == 'type' and value == 'tosca.artifacts.Deployment.riftio.cloud_init_file': + details['cloud_init_file'] = os.path.basename(props['file']) + self._cloud_init = props['file'] + self.properties['cloud_init_file'] = os.path.basename(props['file']) elif name == 'file': details['file'] = value elif name == 'image_checksum': - details['image_checksum'] = value + self.properties['image_checksum'] = value else: self.log.warn(_("VDU {0}, unsuported attribute {1}"). format(self.name, name)) @@ -172,8 +349,8 @@ class ToscaCompute(ManoResource): self.artifacts = arts def handle_interfaces(self): - # Currently, we support only create operation - operations_deploy_sequence = ['create'] + # Currently, we support the following: + operations_deploy_sequence = ['create', 'configure'] operations = ManoResource._get_all_operations(self.nodetemplate) @@ -186,12 +363,17 @@ class ToscaCompute(ManoResource): self.operations[operation.name] = operation.implementation for name, details in self.artifacts.items(): if name == operation.implementation: - self._image = details['file'] + if operation.name == 'create': + self._image = details['file'] + elif operation.name == 'configure': + self._cloud_init = details['file'] + break except KeyError as e: self.log.exception(e) return None def update_image_checksum(self, in_file): + # Create image checksum # in_file is the TOSCA yaml file location if self._image is None: @@ -240,6 +422,9 @@ class ToscaCompute(ManoResource): if self._image_cksum: self.properties['image-checksum'] = self._image_cksum + if self._cloud_init: + self.properties['cloud-init-file'] = os.path.basename(self._cloud_init) + for key in ToscaCompute.IGNORE_PROPS: if key in self.properties: self.properties.pop(key) @@ -249,7 +434,15 @@ class ToscaCompute(ManoResource): return None self._update_properties_for_model() props = convert_keys_to_python(self.properties) + + for monitor_param in self._monitor_param: + monitor_props = convert_keys_to_python(monitor_param) + vnfd.monitoring_param.add().from_dict(monitor_props) try: + if len(self._mgmt_interface) > 0: + vnfd.mgmt_interface.from_dict(convert_keys_to_python(self._mgmt_interface)) + if self._http_endpoint: + vnfd.http_endpoint.add().from_dict(convert_keys_to_python(self._http_endpoint)) vnfd.vdu.add().from_dict(props) except Exception as e: err_msg = _("{0} Exception vdu from dict {1}: {2}"). \