From: garciadeblas Date: Wed, 28 Sep 2016 10:04:10 +0000 (+0200) Subject: Support of image name and checksum for each VDU/VNFC instead of the image location... X-Git-Tag: v1.0.0~20 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=b69fa9f026b1b5839799cc5dc48af625981cbc3a;p=osm%2FRO.git Support of image name and checksum for each VDU/VNFC instead of the image location/path Change-Id: I64c0659e64cb3c0d19dce2ce4fc2640c5700a1bd Signed-off-by: garciadeblas --- diff --git a/database_utils/migrate_mano_db.sh b/database_utils/migrate_mano_db.sh index 447eb812..ae1ef15c 100755 --- a/database_utils/migrate_mano_db.sh +++ b/database_utils/migrate_mano_db.sh @@ -183,6 +183,7 @@ DATABASE_TARGET_VER_NUM=0 [ $OPENMANO_VER_NUM -ge 4046 ] && DATABASE_TARGET_VER_NUM=12 #0.4.46=> 12 [ $OPENMANO_VER_NUM -ge 4047 ] && DATABASE_TARGET_VER_NUM=13 #0.4.47=> 13 [ $OPENMANO_VER_NUM -ge 4057 ] && DATABASE_TARGET_VER_NUM=14 #0.4.57=> 14 +[ $OPENMANO_VER_NUM -ge 4059 ] && DATABASE_TARGET_VER_NUM=15 #0.4.59=> 15 #TODO ... put next versions here @@ -579,7 +580,7 @@ function downgrade_from_11(){ function upgrade_to_12(){ echo " upgrade database from version 0.11 to version 0.12" echo " create ip_profiles table, with foreign keys to all nets tables, and add ip_address column to 'interfaces' and 'sce_interfaces'" - echo "CREATE TABLE ip_profiles ( + echo "CREATE TABLE IF NOT EXISTS ip_profiles ( id INT(11) NOT NULL AUTO_INCREMENT, net_id VARCHAR(36) NULL DEFAULT NULL, sce_net_id VARCHAR(36) NULL DEFAULT NULL, @@ -641,6 +642,29 @@ function downgrade_from_14(){ echo "DELETE FROM schema_version WHERE version_int='14';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 } +function upgrade_to_15(){ + echo " upgrade database from version 0.14 to version 0.15" + echo " add columns 'universal_name' and 'checksum' at table 'images', add unique index universal_name_checksum, and change location to allow NULL; change column 'image_path' in table 'vms' to allow NULL" + echo "ALTER TABLE images ADD COLUMN checksum VARCHAR(32) NULL DEFAULT NULL AFTER name;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "ALTER TABLE images ALTER location DROP DEFAULT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "ALTER TABLE images ADD COLUMN universal_name VARCHAR(255) NULL AFTER name, CHANGE COLUMN location location VARCHAR(200) NULL AFTER checksum, ADD UNIQUE INDEX universal_name_checksum (universal_name, checksum);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "ALTER TABLE vms ALTER image_path DROP DEFAULT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "ALTER TABLE vms CHANGE COLUMN image_path image_path VARCHAR(100) NULL COMMENT 'Path where the image of the VM is located' AFTER image_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (15, '0.15', '0.4.59', 'add columns universal_name and checksum at table images, add unique index universal_name_checksum, and change location to allow NULL; change column image_path in table vms to allow NULL', '2016-09-27');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 +} +function downgrade_from_15(){ + echo " downgrade database from version 0.15 to version 0.14" + echo " remove columns 'universal_name' and 'checksum' from table 'images', remove index universal_name_checksum, change location NOT NULL; change column 'image_path' in table 'vms' to NOT NULL" + echo "ALTER TABLE images DROP INDEX universal_name_checksum;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "ALTER TABLE images ALTER location DROP DEFAULT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "ALTER TABLE images CHANGE COLUMN location location VARCHAR(200) NOT NULL AFTER checksum;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "ALTER TABLE images DROP COLUMN universal_name;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "ALTER TABLE images DROP COLUMN checksum;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "ALTER TABLE vms ALTER image_path DROP DEFAULT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "ALTER TABLE vms CHANGE COLUMN image_path image_path VARCHAR(100) NOT NULL COMMENT 'Path where the image of the VM is located' AFTER image_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 + echo "DELETE FROM schema_version WHERE version_int='15';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 +} + function upgrade_to_X(){ echo " change 'datacenter_nets'" echo "ALTER TABLE datacenter_nets ADD COLUMN vim_tenant_id VARCHAR(36) NOT NULL AFTER datacenter_id, DROP INDEX name_datacenter_id, ADD UNIQUE INDEX name_datacenter_id (name, datacenter_id, vim_tenant_id);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1 diff --git a/nfvo.py b/nfvo.py index dd3eb55b..f681f5b7 100644 --- a/nfvo.py +++ b/nfvo.py @@ -257,13 +257,17 @@ def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vi if only_create_at_vim: image_mano_id = image_dict['uuid'] else: - images = mydb.get_rows(FROM="images", WHERE={'location':image_dict['location'], 'metadata':image_dict['metadata']}) + if image_dict['location'] is not None: + images = mydb.get_rows(FROM="images", WHERE={'location':image_dict['location'], 'metadata':image_dict['metadata']}) + else: + images = mydb.get_rows(FROM="images", WHERE={'universal_name':image_dict['universal_name'], 'checksum':image_dict['checksum']}) if len(images)>=1: image_mano_id = images[0]['uuid'] else: #create image temp_image_dict={'name':image_dict['name'], 'description':image_dict.get('description',None), - 'location':image_dict['location'], 'metadata':image_dict.get('metadata',None) + 'location':image_dict['location'], 'metadata':image_dict.get('metadata',None), + 'universal_name':image_dict['universal_name'] , 'checksum':image_dict['checksum'] } image_mano_id = mydb.new_row('images', temp_image_dict, add_uuid=True) rollback_list.append({"where":"mano", "what":"image","uuid":image_mano_id}) @@ -274,7 +278,20 @@ def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vi image_db = mydb.get_rows(FROM="datacenters_images", WHERE={'datacenter_id':vim_id, 'image_id':image_mano_id}) #look at VIM if this image exist try: - image_vim_id = vim.get_image_id_from_path(image_dict['location']) + if image_dict['location'] is not None: + image_vim_id = vim.get_image_id_from_path(image_dict['location']) + else: + filter_dict={} + filter_dict['name']=image_dict['universal_name'] + filter_dict['checksum']=image_dict['checksum'] + vim_images = vim.get_image_list(filter_dict) + if len(vim_images) > 1: + raise NfvoException("More than one candidate VIM image found for filter: " + str(filter_dict), HTTP_Conflict) + elif len(vim_nets) == 0: + raise NfvoException("Image not found at VIM with filter: '%s'", str(filter_dict)) + else: + image_vim_id = vim_images[0].id + except vimconn.vimconnNotFoundException as e: #Create the image in VIM try: @@ -289,10 +306,10 @@ def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vi logger.warn("Error creating image at VIM: %s", str(e)) continue except vimconn.vimconnException as e: - logger.warn("Error contacting VIM to know if the image exist at VIM: %s", str(e)) + logger.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e)) image_vim_id = str(e) continue - #if reach here the image has been create or exist + #if we reach here, the image has been created or existed if len(image_db)==0: #add new vim_id at datacenters_images mydb.new_row('datacenters_images', {'datacenter_id':vim_id, 'image_id':image_mano_id, 'vim_id': image_vim_id, 'created':image_created}) @@ -326,9 +343,14 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_ if 'extended' in flavor_dict and flavor_dict['extended']!=None: dev_nb=0 for device in flavor_dict['extended'].get('devices',[]): - if "image" not in device: + if "image" not in device or "image name" not in device: continue - image_dict={'location':device['image'], 'name':flavor_dict['name']+str(dev_nb)+"-img", 'description':flavor_dict.get('description')} + image_dict={} + image_dict['name']=device.get('image name',flavor_dict['name']+str(dev_nb)+"-img") + image_dict['universal_name']=device.get('image name') + image_dict['description']=flavor_dict['name']+str(dev_nb)+"-img" + image_dict['location']=device.get('image') + image_dict['checksum']=device.get('image checksum') image_metadata_dict = device.get('image metadata', None) image_metadata_str = None if image_metadata_dict != None: @@ -374,9 +396,14 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_ dev_nb=0 for index in range(0,len(devices_original)) : device=devices_original[index] - if "image" not in device: + if "image" not in device or "image name" not in device: continue - image_dict={'location':device['image'], 'name':flavor_dict['name']+str(dev_nb)+"-img", 'description':flavor_dict.get('description')} + image_dict={} + image_dict['name']=device.get('image name',flavor_dict['name']+str(dev_nb)+"-img") + image_dict['universal_name']=device.get('image name') + image_dict['description']=flavor_dict['name']+str(dev_nb)+"-img" + image_dict['location']=device.get('image') + image_dict['checksum']=device.get('image checksum') image_metadata_dict = device.get('image metadata', None) image_metadata_str = None if image_metadata_dict != None: @@ -472,7 +499,7 @@ def new_vnf(mydb, tenant_id, vnf_descriptor): #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"]) myflavorDict = {} - myflavorDict["name"] = vnfc['name']+"-flv" + myflavorDict["name"] = vnfc['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists myflavorDict["description"] = VNFCitem["description"] myflavorDict["ram"] = vnfc.get("ram", 0) myflavorDict["vcpus"] = vnfc.get("vcpus", 0) @@ -520,7 +547,12 @@ def new_vnf(mydb, tenant_id, vnf_descriptor): #In case this integration is made, the VNFCDict might become a VNFClist. for vnfc in vnf_descriptor['vnf']['VNFC']: #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description']) - image_dict={'location':vnfc['VNFC image'], 'name':vnfc['name']+"-img", 'description':VNFCDict[vnfc['name']]['description']} + image_dict={} + image_dict['name']=vnfc.get('image name',vnf_name+"-"+vnfc['name']+"-img") + image_dict['universal_name']=vnfc.get('image name') + image_dict['description']=vnfc.get('image name', VNFCDict[vnfc['name']]['description']) + image_dict['location']=vnfc.get('VNFC image') + image_dict['checksum']=vnfc.get('image checksum') image_metadata_dict = vnfc.get('image metadata', None) image_metadata_str = None if image_metadata_dict is not None: @@ -530,7 +562,7 @@ def new_vnf(mydb, tenant_id, vnf_descriptor): image_id = create_or_use_image(mydb, vims, image_dict, rollback_list) #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id) VNFCDict[vnfc['name']]["image_id"] = image_id - VNFCDict[vnfc['name']]["image_path"] = vnfc['VNFC image'] + VNFCDict[vnfc['name']]["image_path"] = vnfc.get('VNFC image') # Step 7. Storing the VNF descriptor in the repository @@ -605,7 +637,7 @@ def new_vnf_v02(mydb, tenant_id, vnf_descriptor): #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"]) myflavorDict = {} - myflavorDict["name"] = vnfc['name']+"-flv" + myflavorDict["name"] = vnfc['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists myflavorDict["description"] = VNFCitem["description"] myflavorDict["ram"] = vnfc.get("ram", 0) myflavorDict["vcpus"] = vnfc.get("vcpus", 0) @@ -653,7 +685,12 @@ def new_vnf_v02(mydb, tenant_id, vnf_descriptor): #In case this integration is made, the VNFCDict might become a VNFClist. for vnfc in vnf_descriptor['vnf']['VNFC']: #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description']) - image_dict={'location':vnfc['VNFC image'], 'name':vnfc['name']+"-img", 'description':VNFCDict[vnfc['name']]['description']} + image_dict={} + image_dict['name']=vnfc.get('image name',vnf_name+"-"+vnfc['name']+"-img") + image_dict['universal_name']=vnfc.get('image name') + image_dict['description']=vnfc.get('image name', VNFCDict[vnfc['name']]['description']) + image_dict['location']=vnfc.get('VNFC image') + image_dict['checksum']=vnfc.get('image checksum') image_metadata_dict = vnfc.get('image metadata', None) image_metadata_str = None if image_metadata_dict is not None: @@ -663,7 +700,7 @@ def new_vnf_v02(mydb, tenant_id, vnf_descriptor): image_id = create_or_use_image(mydb, vims, image_dict, rollback_list) #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id) VNFCDict[vnfc['name']]["image_id"] = image_id - VNFCDict[vnfc['name']]["image_path"] = vnfc['VNFC image'] + VNFCDict[vnfc['name']]["image_path"] = vnfc.get('VNFC image') # Step 7. Storing the VNF descriptor in the repository diff --git a/openmano_schemas.py b/openmano_schemas.py index 8af46826..e1fc2bd7 100644 --- a/openmano_schemas.py +++ b/openmano_schemas.py @@ -54,6 +54,7 @@ object_schema={"type":"object"} schema_version_2={"type":"integer","minimum":2,"maximum":2} #schema_version_string={"type":"string","enum": ["0.1", "2", "0.2", "3", "0.3"]} log_level_schema={"type":"string", "enum":["DEBUG", "INFO", "WARNING","ERROR","CRITICAL"]} +checksum_schema={"type":"string", "pattern":"^[0-9a-fA-F]{32}$"} metadata_schema={ "type":"object", @@ -461,6 +462,8 @@ devices_schema={ "properties":{ "type":{"type":"string", "enum":["disk","cdrom","xml"] }, "image": path_schema, + "image name": name_schema, + "image checksum": checksum_schema, "image metadata": metadata_schema, "vpci":pci_schema, "xml":xml_text_schema, @@ -493,6 +496,8 @@ vnfc_schema = { "name": name_schema, "description": description_schema, "VNFC image": {"oneOf": [path_schema, http_schema]}, + "image name": name_schema, + "image checksum": checksum_schema, "image metadata": metadata_schema, #"cloud-config": cloud_config_schema, #common for all vnfs in the scenario "processor": { @@ -522,7 +527,11 @@ vnfc_schema = { "devices": devices_schema }, - "required": ["name", "VNFC image"], + "required": ["name"], + "oneOf": [ + {"required": ["VNFC image"]}, + {"required": ["image name"]} + ], "additionalProperties": False } diff --git a/openmanod.py b/openmanod.py index 2becccff..59a566dc 100755 --- a/openmanod.py +++ b/openmanod.py @@ -33,9 +33,9 @@ It loads the configuration file and launches the http_server thread that will li ''' __author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes" __date__ ="$26-aug-2014 11:09:29$" -__version__="0.4.58-r501" +__version__="0.4.59-r502" version_date="Sep 2016" -database_version="0.14" #expected database schema version +database_version="0.15" #expected database schema version import httpserver import time diff --git a/test/basictest.sh b/test/basictest.sh index 0d4fcea5..11162dd9 100755 --- a/test/basictest.sh +++ b/test/basictest.sh @@ -144,6 +144,7 @@ then ${DIRmano}/openmano vnf-delete -f linux_2VMs_v02 || echo "fail" ${DIRmano}/openmano vnf-delete -f dataplaneVNF_2VMs || echo "fail" ${DIRmano}/openmano vnf-delete -f dataplaneVNF_2VMs_v02 || echo "fail" + ${DIRmano}/openmano vnf-delete -f dataplaneVNF_2VMs_v02_withimagename || echo "fail" ${DIRmano}/openmano vnf-delete -f dataplaneVNF2 || echo "fail" ${DIRmano}/openmano vnf-delete -f dataplaneVNF3 || echo "fail" ${DIRmano}/openmano datacenter-detach TEST-dc || echo "fail" @@ -187,7 +188,7 @@ then [[ $? != 0 ]] && echo "FAIL" && echo " $result" && $_exit 1 echo OK - for VNF in linux dataplaneVNF1 dataplaneVNF2 dataplaneVNF_2VMs dataplaneVNF_2VMs_v02 dataplaneVNF3 linux_2VMs_v02 + for VNF in linux dataplaneVNF1 dataplaneVNF2 dataplaneVNF_2VMs dataplaneVNF_2VMs_v02 dataplaneVNF3 linux_2VMs_v02 dataplaneVNF_2VMs_v02_withimagename do printf "%-50s" "Creating VNF '${VNF}': " result=`$DIRmano/openmano vnf-create $DIRmano/vnfs/examples/${VNF}.yaml` diff --git a/vimconn.py b/vimconn.py index e6e04215..7d68ac45 100644 --- a/vimconn.py +++ b/vimconn.py @@ -263,14 +263,22 @@ class vimconnector(): raise vimconnNotImplemented( "Should have implemented this" ) def get_image_id_from_path(self, path): - '''Get the image id from image path in the VIM database''' - '''Returns: - 0,"Image not found" if there are no images with that path - 1,image-id if there is one image with that path - <0,message if there was an error (Image not found, error contacting VIM, more than 1 image with that path, etc.) - ''' + '''Get the image id from image path in the VIM database. Returns the image_id''' raise vimconnNotImplemented( "Should have implemented this" ) + def get_image_list(self, filter_dict={}): + '''Obtain tenant images from VIM + Filter_dict can be: + name: image name + id: image uuid + checksum: image checksum + location: image path + Returns the image list of dictionaries: + [{}, ...] + List can be empty + ''' + raise vimconnNotImplemented( "Should have implemented this" ) + def new_vminstance(self,name,description,start,image_id,flavor_id,net_list,cloud_config=None): '''Adds a VM instance to VIM Params: diff --git a/vimconn_openstack.py b/vimconn_openstack.py index 857b181a..70f8c012 100644 --- a/vimconn_openstack.py +++ b/vimconn_openstack.py @@ -560,8 +560,7 @@ class vimconnector(vimconn.vimconnector): self._format_exception(e) def get_image_id_from_path(self, path): - '''Get the image id from image path in the VIM database. Returns the image_id - ''' + '''Get the image id from image path in the VIM database. Returns the image_id''' try: self._reload_connection() images = self.nova.images.list() @@ -572,6 +571,35 @@ class vimconnector(vimconn.vimconnector): except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError, ConnectionError) as e: self._format_exception(e) + def get_image_list(self, filter_dict={}): + '''Obtain tenant images from VIM + Filter_dict can be: + id: image id + name: image name + checksum: image checksum + Returns the image list of dictionaries: + [{}, ...] + List can be empty + ''' + self.logger.debug("Getting image list from VIM filter: '%s'", str(filter_dict)) + try: + self._reload_connection() + filter_dict_os=filter_dict.copy() + #First we filter by the available filter fields: name, id. The others are removed. + filter_dict_os.pop('checksum',None) + image_list=self.nova.images.findall(**filter_dict_os) + if len(image_list)==0: + return [] + #Then we filter by the rest of filter fields: checksum + filtered_list = [] + for image in image_list: + image_dict=glance.images.get(image.id) + if image_dict['checksum']==filter_dict.get('checksum'): + filtered_list.append(image) + return filtered_list + except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError, ConnectionError) as e: + self._format_exception(e) + def new_vminstance(self,name,description,start,image_id,flavor_id,net_list,cloud_config=None): '''Adds a VM instance to VIM Params: diff --git a/vimconn_openvim.py b/vimconn_openvim.py index 9d42f9e6..d4155320 100644 --- a/vimconn_openvim.py +++ b/vimconn_openvim.py @@ -688,7 +688,7 @@ class vimconnector(vimconn.vimconnector): def get_image_id_from_path(self, path): - '''Get the image id from image path in the VIM database''' + '''Get the image id from image path in the VIM database. Returns the image_id''' try: self._get_my_tenant() url=self.url + '/' + self.tenant + '/images?path='+quote(path) @@ -710,6 +710,36 @@ class vimconnector(vimconn.vimconnector): except (requests.exceptions.RequestException, js_e.ValidationError) as e: self._format_request_exception(e) + def get_image_list(self, filter_dict={}): + '''Obtain tenant images from VIM + Filter_dict can be: + name: image name + id: image uuid + checksum: image checksum + location: image path + Returns the image list of dictionaries: + [{}, ...] + List can be empty + ''' + try: + self._get_my_tenant() + filterquery=[] + filterquery_text='' + for k,v in filter_dict.iteritems(): + filterquery.append(str(k)+'='+str(v)) + if len(filterquery)>0: + filterquery_text='?'+ '&'.join(filterquery) + url = self.url+'/'+self.tenant+'/images'+filterquery_text + self.logger.info("Getting image list GET %s", url) + vim_response = requests.get(url, headers = self.headers_req) + self._check_http_request_response(vim_response) + self.logger.debug(vim_response.text) + #print json.dumps(vim_response.json(), indent=4) + response = vim_response.json() + return response['images'] + except (requests.exceptions.RequestException, js_e.ValidationError) as e: + self._format_request_exception(e) + def new_vminstancefromJSON(self, vm_data): '''Adds a VM instance to VIM''' '''Returns the instance identifier''' diff --git a/vnfs/examples/dataplaneVNF_2VMs_v02_withimagename.yaml b/vnfs/examples/dataplaneVNF_2VMs_v02_withimagename.yaml new file mode 100644 index 00000000..0c546520 --- /dev/null +++ b/vnfs/examples/dataplaneVNF_2VMs_v02_withimagename.yaml @@ -0,0 +1,113 @@ +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# 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. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +--- +schema_version: "0.2" +vnf: + name: dataplaneVNF_2VMs_v02_withimagename + description: "Example of a dataplane VNF consisting of two VMs for data plane workloads with one internal network" + # class: parent # Optional. Used to organize VNFs + internal-connections: + - name: datanet + description: datanet + type: e-lan + implementation: underlay + ip-profile: + ip-version: IPv4 + subnet-address: 192.168.1.0/24 + gateway-address: 192.168.1.1 + dns-address: 8.8.8.8 + dhcp: + enabled: true + start-address: 192.168.1.100 + count: 100 + elements: + - VNFC: VNF_2VMs-VM1 + local_iface_name: xe0 + ip_address: 192.168.1.2 + - VNFC: VNF_2VMs-VM2 + local_iface_name: xe0 + ip_address: 192.168.1.3 + external-connections: + - name: control0 + type: mgmt + VNFC: VNF_2VMs-VM1 + local_iface_name: eth0 + description: control interface VM1 + - name: control1 + type: mgmt + VNFC: VNF_2VMs-VM2 + local_iface_name: eth0 + description: control interface VM2 + - name: in + type: data + VNFC: VNF_2VMs-VM1 + local_iface_name: xe1 + description: Dataplane interface input + - name: out + type: data + VNFC: VNF_2VMs-VM2 + local_iface_name: xe1 + description: Dataplane interface output + VNFC: + - name: VNF_2VMs-VM1 + description: "Dataplane VM1 with 4 threads, 2 GB hugepages, 2 SR-IOV interface" + #Copy the image to a compute path and edit this path + image name: dataplaneVNF_2VMs-image + disk: 10 + numas: + - paired-threads: 2 # "cores", "paired-threads", "threads" + memory: 2 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 1 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "no" + bandwidth: 1 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only + + - name: VNF_2VMs-VM2 + description: "Dataplane VM1 with 2 threads, 2 GB hugepages, 2 SR-IOV interface" + #Copy the image to a compute path and edit this path + image name: dataplaneVNF_2VMs-image + disk: 10 + numas: + - paired-threads: 1 # "cores", "paired-threads", "threads" + memory: 2 # GBytes + interfaces: + - name: xe0 + vpci: "0000:00:11.0" + dedicated: "no" # "yes"(passthrough), "no"(sriov with vlan tags), "yes:sriov"(sriovi, but exclusive and without vlan tag) + bandwidth: 1 Gbps + - name: xe1 + vpci: "0000:00:12.0" + dedicated: "no" + bandwidth: 1 Gbps + bridge-ifaces: + - name: eth0 + vpci: "0000:00:09.0" + bandwidth: 1 Mbps # Optional, informative only +