DBNAME="mano_db"
QUIET_MODE=""
#TODO update it with the last database version
-LAST_DB_VERSION=24
+LAST_DB_VERSION=25
# Detect paths
MYSQL=$(which mysql)
#[ $OPENMANO_VER_NUM -ge 5016 ] && DB_VERSION=22 #0.5.16 => 22
#[ $OPENMANO_VER_NUM -ge 5020 ] && DB_VERSION=23 #0.5.20 => 23
#[ $OPENMANO_VER_NUM -ge 5021 ] && DB_VERSION=24 #0.5.21 => 24
+#[ $OPENMANO_VER_NUM -ge 5022 ] && DB_VERSION=25 #0.5.22 => 25
#TODO ... put next versions here
function upgrade_to_1(){
sql "ALTER TABLE vms DROP COLUMN count;"
sql "DELETE FROM schema_version WHERE version_int='24';"
}
+function upgrade_to_25(){
+ # echo " upgrade database from version 0.24 to version 0.25"
+ echo " Add 'osm_id','short_name','vendor' to tables 'vnfs', 'scenarios'"
+ for table in vnfs scenarios; do
+ sql "ALTER TABLE $table ADD COLUMN osm_id VARCHAR(255) NULL AFTER uuid, "\
+ "ADD UNIQUE INDEX osm_id_tenant_id (osm_id, tenant_id), "\
+ "ADD COLUMN short_name VARCHAR(255) NULL AFTER name, "\
+ "ADD COLUMN vendor VARCHAR(255) NULL AFTER description;"
+ done
+ sql "ALTER TABLE vnfs ADD COLUMN mgmt_access VARCHAR(2000) NULL AFTER vendor;"
+ sql "ALTER TABLE vms ADD COLUMN osm_id VARCHAR(255) NULL AFTER uuid;"
+ sql "ALTER TABLE sce_vnfs ADD COLUMN member_vnf_index SMALLINT(6) NULL DEFAULT NULL AFTER uuid;"
+ echo " Add 'security_group' to table 'ip_profiles'"
+ sql "ALTER TABLE ip_profiles ADD COLUMN security_group VARCHAR(255) NULL DEFAULT NULL AFTER dhcp_count;"
+
+ sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) "\
+ "VALUES (25, '0.25', '0.5.22', 'Added osm_id to vnfs,scenarios', '2017-09-01');"
+}
+function downgrade_from_25(){
+ # echo " downgrade database from version 0.25 to version 0.24"
+ echo " Remove 'osm_id','short_name','vendor' from tables 'vnfs', 'scenarios'"
+ for table in vnfs scenarios; do
+ sql "ALTER TABLE $table DROP INDEX osm_id_tenant_id, DROP COLUMN osm_id, "\
+ "DROP COLUMN short_name, DROP COLUMN vendor;"
+ done
+ sql "ALTER TABLE vnfs DROP COLUMN mgmt_access;"
+ sql "ALTER TABLE vms DROP COLUMN osm_id;"
+ sql "ALTER TABLE sce_vnfs DROP COLUMN member_vnf_index;"
+ echo " Remove 'security_group' from table 'ip_profiles'"
+ sql "ALTER TABLE ip_profiles DROP COLUMN security_group;"
+
+ sql "DELETE FROM schema_version WHERE version_int='25';"
+}
function upgrade_to_X(){
echo " change 'datacenter_nets'"
"""
__author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes"
__date__ = "$09-oct-2014 09:09:48$"
-__version__ = "0.4.15-r525"
-version_date = "Jul 2017"
+__version__ = "0.4.20-r530"
+version_date = "Sep 2017"
from argcomplete.completers import FilesCompleter
import os
if i["name"] == item_name_id:
uuid = i["uuid"]
found += 1
+ if item_name_id.startswith("osm_id=") and i.get("osm_id") == item_name_id[7:]:
+ uuid = i["uuid"]
+ found += 1
if found == 0:
raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
elif found > 1:
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
tenant = _get_tenant()
myvnf = _load_file_or_yaml(args.file)
+ api_version = ""
+ if "vnfd:vnfd-catalog" in myvnf or "vnfd-catalog" in myvnf:
+ api_version = "/v3"
+ token = "vnfd"
+ vnfd_catalog = myvnf.get("vnfd:vnfd-catalog")
+ if not vnfd_catalog:
+ vnfd_catalog = myvnf.get("vnfd-catalog")
+ vnfds = vnfd_catalog.get("vnfd:vnfd")
+ if not vnfds:
+ vnfds = vnfd_catalog.get("vnfd")
+ vnfd = vnfds[0]
+ vdu_list = vnfd["vdu"]
+
+ else: # old API
+ api_version = ""
+ token = "vnfs"
+ vnfd = myvnf['vnf']
+ vdu_list = vnfd["VNFC"]
if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
- #print args.name
+ # TODO, change this for API v3
+ # print args.name
try:
if args.name:
- myvnf['vnf']['name'] = args.name
+ vnfd['name'] = args.name
if args.description:
- myvnf['vnf']['description'] = args.description
+ vnfd['description'] = args.description
if args.image_path:
- index=0
+ index = 0
for image_path_ in args.image_path.split(","):
- #print "image-path", image_path_
- myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
- if "image name" in myvnf['vnf']['VNFC'][index]:
- del myvnf['vnf']['VNFC'][index]["image name"]
- if "image checksum" in myvnf['vnf']['VNFC'][index]:
- del myvnf['vnf']['VNFC'][index]["image checksum"]
- index=index+1
- if args.image_name: #image name precedes if both are supplied
- index=0
+ # print "image-path", image_path_
+ if api_version == "/v3":
+ if vdu_list[index].get("image"):
+ vdu_list[index]['image'] = image_path_
+ if "image-checksum" in vdu_list[index]:
+ del vdu_list[index]["image-checksum"]
+ else: # image name in volumes
+ vdu_list[index]["volumes"][0]["image"] = image_path_
+ if "image-checksum" in vdu_list[index]["volumes"][0]:
+ del vdu_list[index]["volumes"][0]["image-checksum"]
+ else:
+ vdu_list[index]['VNFC image'] = image_path_
+ if "image name" in vdu_list[index]:
+ del vdu_list[index]["image name"]
+ if "image checksum" in vdu_list[index]:
+ del vdu_list[index]["image checksum"]
+ index += 1
+ if args.image_name: # image name precedes if both are supplied
+ index = 0
for image_name_ in args.image_name.split(","):
- myvnf['vnf']['VNFC'][index]['image name']=image_name_
- if "VNFC image" in myvnf['vnf']['VNFC'][index]:
- del myvnf['vnf']['VNFC'][index]["VNFC image"]
- index=index+1
+ if api_version == "/v3":
+ if vdu_list[index].get("image"):
+ vdu_list[index]['image'] = image_name_
+ if "image-checksum" in vdu_list[index]:
+ del vdu_list[index]["image-checksum"]
+ else: # image name in volumes
+ vdu_list[index]["volumes"][0]["image"] = image_name_
+ if "image-checksum" in vdu_list[index]["volumes"][0]:
+ del vdu_list[index]["volumes"][0]["image-checksum"]
+ else:
+ vdu_list[index]['image name'] = image_name_
+ if "VNFC image" in vdu_list[index]:
+ del vdu_list[index]["VNFC image"]
+ index += 1
if args.image_checksum:
- index=0
+ index = 0
for image_checksum_ in args.image_checksum.split(","):
- myvnf['vnf']['VNFC'][index]['image checksum']=image_checksum_
- index=index+1
+ if api_version == "/v3":
+ if vdu_list[index].get("image"):
+ vdu_list[index]['image-checksum'] = image_checksum_
+ else: # image name in volumes
+ vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
+ else:
+ vdu_list[index]['image checksum'] = image_checksum_
+ index += 1
except (KeyError, TypeError), e:
- if str(e)=='vnf': error_pos= "missing field 'vnf'"
- elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
- elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
- elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
- elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
- elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
- elif str(e)=='image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
- elif str(e)=='image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
+ if str(e) == 'vnf': error_pos= "missing field 'vnf'"
+ elif str(e) == 'name': error_pos= "missing field 'vnf':'name'"
+ elif str(e) == 'description': error_pos= "missing field 'vnf':'description'"
+ elif str(e) == 'VNFC': error_pos= "missing field 'vnf':'VNFC'"
+ elif str(e) == str(index): error_pos= "field 'vnf':'VNFC' must be an array"
+ elif str(e) == 'VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
+ elif str(e) == 'image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
+ elif str(e) == 'image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
else: error_pos="wrong format"
print "Wrong VNF descriptor: " + error_pos
return -1
#print payload_req
- URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
+ URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
logger.debug("openmano request: %s", payload_req)
mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
content = mano_response.json()
- #print json.dumps(content, indent=4)
+ # print json.dumps(content, indent=4)
if args.verbose==None:
args.verbose=0
result = 0 if mano_response.status_code==200 else mano_response.status_code
return result
if len(content['vnfs']) == 0:
print "No VNFs were found."
- return 404 #HTTP_Not_Found
+ return 404 # HTTP_Not_Found
for vnf in content['vnfs']:
- myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
- if args.verbose >=1:
- myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
- print myoutput
- if args.verbose >=2:
- print " Description: %s" %vnf['description']
- print " VNF descriptor file: %s" %vnf['path']
+ myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
+ if vnf.get('osm_id') or args.verbose >= 1:
+ myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
+ if args.verbose >= 1:
+ myoutput += " {}".format(vnf['created_at'])
+ print (myoutput)
+ if args.verbose >= 2:
+ print (" Description: {}".format(vnf['description']))
+ # print (" VNF descriptor file: {}".format(vnf['path']))
else:
if args.verbose:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
vnf = content['vnf']
- print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
- print " Description: %s" %vnf['description']
- #print " VNF descriptor file: %s" %vnf['path']
- print " VMs:"
+ print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
+ vnf['created_at']))
+ print (" Description: {}".format(vnf['description']))
+ # print " VNF descriptor file: %s" %vnf['path']
+ print (" VMs:")
for vm in vnf['VNFC']:
- #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
- print " %s %s" %(vm['name'].ljust(20), vm['description'])
- if len(vnf['nets'])>0:
- print " Internal nets:"
+ print (" {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
+ if len(vnf['nets']) > 0:
+ print (" Internal nets:")
for net in vnf['nets']:
- print " %s %s" %(net['name'].ljust(20), net['description'])
- if len(vnf['external-connections'])>0:
- print " External interfaces:"
+ print (" {:20} {}".format(net['name'], net['description']))
+ if len(vnf['external-connections']) > 0:
+ print (" External interfaces:")
for interface in vnf['external-connections']:
- print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
- interface.get('vpci',"").ljust(14))
+ print (" {:20} {:20} {:20} {:14}".format(
+ interface['external_name'], interface['vm_name'],
+ interface['internal_name'],
+ interface.get('vpci') if interface.get('vpci') else ""))
else:
print content['error']['description']
if args.verbose:
return result
def scenario_create(args):
- #print "scenario-create",args
+ # print "scenario-create",args
tenant = _get_tenant()
headers_req = {'content-type': 'application/yaml'}
myscenario = _load_file_or_yaml(args.file)
-
+ if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
+ api_version = "/v3"
+ token = "nsd"
+ nsd_catalog = myscenario.get("nsd:nsd-catalog")
+ if not nsd_catalog:
+ nsd_catalog = myscenario.get("nsd-catalog")
+ nsds = nsd_catalog.get("nsd:nsd")
+ if not nsds:
+ nsds = nsd_catalog.get("nsd")
+ nsd = nsds[0]
+ else: # API<v3
+ api_version = ""
+ token = "scenarios"
+ if "scenario" in myscenario:
+ nsd = myscenario["scenario"]
+ else:
+ nsd = myscenario
+ # TODO modify for API v3
if args.name:
- myscenario['name'] = args.name
+ nsd['name'] = args.name
if args.description:
- myscenario['description'] = args.description
- payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
+ nsd['description'] = args.description
+ payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
+ encoding='utf-8', allow_unicode=True)
- #print payload_req
-
- URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
+ # print payload_req
+ URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
+ host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
logger.debug("openmano request: %s", payload_req)
mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
print "No scenarios were found."
return 404 #HTTP_Not_Found
for scenario in content['scenarios']:
- myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
- if args.verbose >=1:
- myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
- print myoutput
+ myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
+ if scenario.get('osm_id') or args.verbose >= 1:
+ myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
+ if args.verbose >= 1:
+ myoutput += " {}".format(scenario['created_at'])
+ print (myoutput)
if args.verbose >=2:
- print " Description: %s" %scenario['description']
+ print (" Description: {}".format(scenario['description']))
else:
if args.verbose:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
scenario = content['scenario']
- myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
- print myoutput
- print " Description: %s" %scenario['description']
- print " VNFs:"
+ print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
+ scenario['created_at']))
+ print (" Description: {}".format(scenario['description']))
+ print (" VNFs:")
for vnf in scenario['vnfs']:
- print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
- if len(scenario['nets'])>0:
- print " Internal nets:"
+ print (" {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
+ vnf['description']))
+ if len(scenario['nets']) > 0:
+ print (" nets:")
for net in scenario['nets']:
- if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
- net['description'] = '-'
- if not net['external']:
- print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
- print " External nets:"
- for net in scenario['nets']:
- if net['external']:
- print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
+ description = net['description']
+ if not description: # if description does not exist, description is "-". Valid for external and internal nets.
+ description = '-'
+ vim_id = ""
+ if net.get('vim_id'):
+ vim_id = " vim_id=" + net["vim_id"]
+ external = ""
+ if net["external"]:
+ external = " external"
+ print (" {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
else:
- print content['error']['description']
+ print (content['error']['description'])
if args.verbose:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
__author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes"
__date__ = "$26-aug-2014 11:09:29$"
-__version__ = "0.5.21-r531"
+__version__ = "0.5.22-r532"
version_date = "Aug 2017"
-database_version = 24 # expected database schema version
+database_version = 25 # expected database schema version
global global_config
global logger
return json.dumps(data, indent=4) + "\n"
def format_in(default_schema, version_fields=None, version_dict_schema=None):
- ''' Parse the content of HTTP request against a json_schema
- Parameters
- default_schema: The schema to be parsed by default if no version field is found in the client data
- version_fields: If provided it contains a tuple or list with the fields to iterate across the client data to obtain the version
- version_dict_schema: It contains a dictionary with the version as key, and json schema to apply as value
- It can contain a None as key, and this is apply if the client data version does not match any key
- Return:
- user_data, used_schema: if the data is successfully decoded and matches the schema
- launch a bottle abort if fails
- '''
+ """
+ Parse the content of HTTP request against a json_schema
+ :param default_schema: The schema to be parsed by default if no version field is found in the client data. In None
+ no validation is done
+ :param version_fields: If provided it contains a tuple or list with the fields to iterate across the client data to
+ obtain the version
+ :param version_dict_schema: It contains a dictionary with the version as key, and json schema to apply as value.
+ It can contain a None as key, and this is apply if the client data version does not match any key
+ :return: user_data, used_schema: if the data is successfully decoded and matches the schema.
+ Launch a bottle abort if fails
+ """
#print "HEADERS :" + str(bottle.request.headers.items())
try:
error_text = "Invalid header format "
logger.warning('Content-Type ' + str(format_type) + ' not supported.')
bottle.abort(HTTP_Not_Acceptable, 'Content-Type ' + str(format_type) + ' not supported.')
return
- #if client_data == None:
+ # if client_data == None:
# bottle.abort(HTTP_Bad_Request, "Content error, empty")
# return
- logger.debug('IN: %s', yaml.safe_dump(client_data, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True) )
- #look for the client provider version
+ logger.debug('IN: %s', yaml.safe_dump(client_data, explicit_start=True, indent=4, default_flow_style=False,
+ tags=False, encoding='utf-8', allow_unicode=True) )
+ # look for the client provider version
error_text = "Invalid content "
+ if not default_schema and not version_fields:
+ return client_data, None
client_version = None
used_schema = None
if version_fields != None:
else:
client_version=None
break
- if client_version==None:
- used_schema=default_schema
- elif version_dict_schema!=None:
+ if client_version == None:
+ used_schema = default_schema
+ elif version_dict_schema != None:
if client_version in version_dict_schema:
used_schema = version_dict_schema[client_version]
elif None in version_dict_schema:
#check valid tenant_id
nfvo.check_tenant(mydb, tenant_id)
select_,where_,limit_ = filter_query_string(bottle.request.query, None,
- ('uuid','name','description','public', "tenant_id", "created_at") )
+ ('uuid', 'name', 'osm_id', 'description', 'public', "tenant_id", "created_at") )
where_or = {}
if tenant_id != "any":
where_or["tenant_id"] = tenant_id
@bottle.route(url_base + '/<tenant_id>/vnfs', method='POST')
def http_post_vnfs(tenant_id):
- '''insert a vnf into the catalogue. Creates the flavor and images in the VIM, and creates the VNF and its internal structure in the OPENMANO DB'''
- #print "Parsing the YAML file of the VNF"
- #parse input data
+ """ Insert a vnf into the catalogue. Creates the flavor and images, and fill the tables at database
+ :param tenant_id: tenant that this vnf belongs to
+ :return:
+ """
+ # print "Parsing the YAML file of the VNF"
+ # parse input data
logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
http_content, used_schema = format_in( vnfd_schema_v01, ("schema_version",), {"0.2": vnfd_schema_v02})
r = utils.remove_extra_items(http_content, used_schema)
logger.error("Unexpected exception: ", exc_info=True)
bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e))
-
+
+@bottle.route(url_base + '/v3/<tenant_id>/vnfd', method='POST')
+def http_post_vnfs_v3(tenant_id):
+ """
+ Insert one or several VNFs in the catalog, following OSM IM
+ :param tenant_id: tenant owner of the VNF
+ :return: The detailed list of inserted VNFs, following the old format
+ """
+ logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+ http_content, _ = format_in(None)
+ try:
+ vnfd_uuid_list = nfvo.new_vnfd_v3(mydb, tenant_id, http_content)
+ vnfd_list = []
+ for vnfd_uuid in vnfd_uuid_list:
+ vnf = nfvo.get_vnf_id(mydb, tenant_id, vnfd_uuid)
+ utils.convert_str2boolean(vnf, ('public',))
+ convert_datetime2str(vnf)
+ vnfd_list.append(vnf["vnf"])
+ return format_out({"vnfd": vnfd_list})
+ except (nfvo.NfvoException, db_base_Exception) as e:
+ logger.error("http_post_vnfs error {}: {}".format(e.http_code, str(e)))
+ bottle.abort(e.http_code, str(e))
+ except Exception as e:
+ logger.error("Unexpected exception: ", exc_info=True)
+ bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e))
+
@bottle.route(url_base + '/<tenant_id>/vnfs/<vnf_id>', method='DELETE')
-def http_delete_vnf_id(tenant_id,vnf_id):
+def http_delete_vnf_id(tenant_id, vnf_id):
'''delete a vnf from database, and images and flavors in VIM when appropriate, can use both uuid or name'''
logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
#check valid tenant_id and deletes the vnf, including images,
logger.error("Unexpected exception: ", exc_info=True)
bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e))
+@bottle.route(url_base + '/v3/<tenant_id>/nsd', method='POST')
+def http_post_nsds_v3(tenant_id):
+ """
+ Insert one or several NSDs in the catalog, following OSM IM
+ :param tenant_id: tenant owner of the NSD
+ :return: The detailed list of inserted NSDs, following the old format
+ """
+ logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+ http_content, _ = format_in(None)
+ try:
+ nsd_uuid_list = nfvo.new_nsd_v3(mydb, tenant_id, http_content)
+ nsd_list = []
+ for nsd_uuid in nsd_uuid_list:
+ scenario = mydb.get_scenario(nsd_uuid, tenant_id)
+ convert_datetime2str(scenario)
+ nsd_list.append(scenario)
+ data = {'nsd': nsd_list}
+ return format_out(data)
+ except (nfvo.NfvoException, db_base_Exception) as e:
+ logger.error("http_post_nsds_v3 error {}: {}".format(e.http_code, str(e)))
+ bottle.abort(e.http_code, str(e))
+ except Exception as e:
+ logger.error("Unexpected exception: ", exc_info=True)
+ bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e))
+
@bottle.route(url_base + '/<tenant_id>/scenarios/<scenario_id>/action', method='POST')
def http_post_scenario_action(tenant_id, scenario_id):
if tenant_id != "any":
nfvo.check_tenant(mydb, tenant_id)
#obtain data
- s,w,l=filter_query_string(bottle.request.query, None, ('uuid', 'name', 'description', 'tenant_id', 'created_at', 'public'))
+ s,w,l=filter_query_string(bottle.request.query, None,
+ ('uuid', 'name', 'osm_id', 'description', 'tenant_id', 'created_at', 'public'))
where_or={}
if tenant_id != "any":
where_or["tenant_id"] = tenant_id
from lib_osm_openvim import ovim as ovim_module
from lib_osm_openvim.ovim import ovimException
+import osm_im.vnfd as vnfd_catalog
+import osm_im.nsd as nsd_catalog
+
+from pyangbind.lib.serialise import pybindJSONDecoder
+from itertools import chain
+
global global_config
global vimconn_imported
global logger
# continue
#elif res_vim==0:
- #Create the flavor in VIM
- #Translate images at devices from MANO id to VIM id
+ # Create the flavor in VIM
+ # Translate images at devices from MANO id to VIM id
disk_list = []
if 'extended' in flavor_dict and flavor_dict['extended']!=None and "devices" in flavor_dict['extended']:
- #make a copy of original devices
+ # make a copy of original devices
devices_original=[]
for device in flavor_dict["extended"].get("devices",[]):
del device['image']
if 'image metadata' in device:
del device['image metadata']
- dev_nb=0
+ if 'image checksum' in device:
+ del device['image checksum']
+ dev_nb = 0
for index in range(0,len(devices_original)) :
device=devices_original[index]
if "image" not in device and "image name" not in device:
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['new_location']=device.get('image location')
+ # image_dict['new_location']=device.get('image location')
image_dict['checksum']=device.get('image checksum')
image_metadata_dict = device.get('image metadata', None)
image_metadata_str = None
return flavor_vim_id if only_create_at_vim else flavor_mano_id
+def get_str(obj, field, length):
+ """
+ Obtain the str value,
+ :param obj:
+ :param length:
+ :return:
+ """
+ value = obj.get(field)
+ if value is not None:
+ value = str(value)[:length]
+ return value
+
+def _lookfor_or_create_image(db_image, mydb, descriptor):
+ """
+ fill image content at db_image dictionary. Check if the image with this image and checksum exist
+ :param db_image: dictionary to insert data
+ :param mydb: database connector
+ :param descriptor: yang descriptor
+ :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
+ """
+
+ db_image["name"] = get_str(descriptor, "image", 255)
+ db_image["checksum"] = get_str(descriptor, "image-checksum", 32)
+ if not db_image["checksum"]: # Ensure that if empty string, None is stored
+ db_image["checksum"] = None
+ if db_image["name"].startswith("/"):
+ db_image["location"] = db_image["name"]
+ existing_images = mydb.get_rows(FROM="images", WHERE={'location': db_image["location"]})
+ else:
+ db_image["universal_name"] = db_image["name"]
+ existing_images = mydb.get_rows(FROM="images", WHERE={'universal_name': db_image['universal_name'],
+ 'checksum': db_image['checksum']})
+ if existing_images:
+ return existing_images[0]["uuid"]
+ else:
+ image_uuid = str(uuid4())
+ db_image["uuid"] = image_uuid
+ return None
+
+def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
+ """
+ Parses an OSM IM vnfd_catalog and insert at DB
+ :param mydb:
+ :param tenant_id:
+ :param vnf_descriptor:
+ :return: The list of cretated vnf ids
+ """
+ try:
+ myvnfd = vnfd_catalog.vnfd()
+ pybindJSONDecoder.load_ietf_json(vnf_descriptor, None, None, obj=myvnfd)
+ db_vnfs = []
+ db_nets = []
+ db_vms = []
+ db_vms_index = 0
+ db_interfaces = []
+ db_images = []
+ db_flavors = []
+ uuid_list = []
+ vnfd_uuid_list = []
+ for rift_vnfd in myvnfd.vnfd_catalog.vnfd.itervalues():
+ vnfd = rift_vnfd.get()
+
+ # table vnf
+ vnf_uuid = str(uuid4())
+ uuid_list.append(vnf_uuid)
+ vnfd_uuid_list.append(vnf_uuid)
+ db_vnf = {
+ "uuid": vnf_uuid,
+ "osm_id": get_str(vnfd, "id", 255),
+ "name": get_str(vnfd, "name", 255),
+ "description": get_str(vnfd, "description", 255),
+ "tenant_id": tenant_id,
+ "vendor": get_str(vnfd, "vendor", 255),
+ "short_name": get_str(vnfd, "short-name", 255),
+ "descriptor": str(vnf_descriptor)[:60000]
+ }
+
+ # table nets (internal-vld)
+ net_id2uuid = {} # for mapping interface with network
+ for vld in vnfd.get("internal-vld").itervalues():
+ net_uuid = str(uuid4())
+ uuid_list.append(net_uuid)
+ db_net = {
+ "name": get_str(vld, "name", 255),
+ "vnf_id": vnf_uuid,
+ "uuid": net_uuid,
+ "description": get_str(vld, "description", 255),
+ "type": "bridge", # TODO adjust depending on connection point type
+ }
+ net_id2uuid[vld.get("id")] = net_uuid
+ db_nets.append(db_net)
+
+ # table vms (vdus)
+ vdu_id2uuid = {}
+ vdu_id2db_table_index = {}
+ for vdu in vnfd.get("vdu").itervalues():
+ vm_uuid = str(uuid4())
+ uuid_list.append(vm_uuid)
+ db_vm = {
+ "uuid": vm_uuid,
+ "osm_id": get_str(vdu, "id", 255),
+ "name": get_str(vdu, "name", 255),
+ "description": get_str(vdu, "description", 255),
+ "vnf_id": vnf_uuid,
+ }
+ vdu_id2uuid[db_vm["osm_id"]] = vm_uuid
+ vdu_id2db_table_index[db_vm["osm_id"]] = db_vms_index
+ if vdu.get("count"):
+ db_vm["count"] = int(vdu["count"])
+
+ # table image
+ image_present = False
+ if vdu.get("image"):
+ image_present = True
+ db_image = {}
+ image_uuid = _lookfor_or_create_image(db_image, mydb, vdu)
+ if not image_uuid:
+ image_uuid = db_image["uuid"]
+ db_images.append(db_image)
+ db_vm["image_id"] = image_uuid
+
+ # volumes
+ devices = []
+ if vdu.get("volumes"):
+ for volume_key in sorted(vdu["volumes"]):
+ volume = vdu["volumes"][volume_key]
+ if not image_present:
+ # Convert the first volume to vnfc.image
+ image_present = True
+ db_image = {}
+ image_uuid = _lookfor_or_create_image(db_image, mydb, volume)
+ if not image_uuid:
+ image_uuid = db_image["uuid"]
+ db_images.append(db_image)
+ db_vm["image_id"] = image_uuid
+ else:
+ # Add Openmano devices
+ device = {}
+ device["type"] = str(volume.get("device-type"))
+ if volume.get("size"):
+ device["size"] = int(volume["size"])
+ if volume.get("image"):
+ device["image name"] = str(volume["image"])
+ if volume.get("image-checksum"):
+ device["image checksum"] = str(volume["image-checksum"])
+ devices.append(device)
+
+ # table flavors
+ db_flavor = {
+ "name": get_str(vdu, "name", 250) + "-flv",
+ "vcpus": int(vdu["vm-flavor"].get("vcpu-count", 1)),
+ "ram": int(vdu["vm-flavor"].get("memory-mb", 1)),
+ "disk": int(vdu["vm-flavor"].get("storage-gb", 1)),
+ }
+ # EPA TODO revise
+ extended = {}
+ numa = {}
+ if devices:
+ extended["devices"] = devices
+ if vdu.get("guest-epa"): # TODO or dedicated_int:
+ epa_vcpu_set = False
+ if vdu["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
+ numa_node_policy = vdu["guest-epa"].get("numa-node-policy")
+ if numa_node_policy.get("node"):
+ numa_node = numa_node_policy.node[0]
+ if numa_node.get("num-cores"):
+ numa["cores"] = numa_node["num-cores"]
+ epa_vcpu_set = True
+ if numa_node.get("paired-threads"):
+ if numa_node["paired-threads"].get("num-paired-threads"):
+ numa["paired-threads"] = numa_node["paired-threads"]["num-paired-threads"]
+ epa_vcpu_set = True
+ if len(numa_node["paired-threads"].get("paired-thread-ids")) > 0:
+ numa["paired-threads-id"] = []
+ for pair in numa_node["paired-threads"]["paired-thread-ids"].itervalues:
+ numa["paired-threads-id"].append(
+ (str(pair["thread-a"]), str(pair["thread-b"]))
+ )
+ if numa_node.get("num-threads"):
+ numa["threads"] = numa_node["num-threads"]
+ epa_vcpu_set = True
+ if numa_node.get("memory-mb"):
+ numa["memory"] = max(int(numa_node["memory-mb"] / 1024), 1)
+ if vdu["guest-epa"].get("mempage-size"):
+ if vdu["guest-epa"]["mempage-size"] != "SMALL":
+ numa["memory"] = max(int(db_flavor["ram"] / 1024), 1)
+ if vdu["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set:
+ if vdu["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
+ if vdu["guest-epa"].get("cpu-thread-pinning-policy") and \
+ vdu["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
+ numa["cores"] = max(db_flavor["vcpus"], 1)
+ else:
+ numa["threads"] = max(db_flavor["vcpus"], 1)
+ if numa:
+ extended["numas"] = [numa]
+ if extended:
+ extended_text = yaml.safe_dump(extended, default_flow_style=True, width=256)
+ db_flavor["extended"] = extended_text
+ # look if flavor exist
+
+ temp_flavor_dict = {'disk': db_flavor.get('disk', 1),
+ 'ram': db_flavor.get('ram'),
+ 'vcpus': db_flavor.get('vcpus'),
+ 'extended': db_flavor.get('extended')
+ }
+ existing_flavors = mydb.get_rows(FROM="flavors", WHERE=temp_flavor_dict)
+ if existing_flavors:
+ flavor_uuid = existing_flavors[0]["uuid"]
+ else:
+ flavor_uuid = str(uuid4())
+ uuid_list.append(flavor_uuid)
+ db_flavor["uuid"] = flavor_uuid
+ db_flavors.append(db_flavor)
+ db_vm["flavor_id"] = flavor_uuid
+
+ # cloud-init
+ boot_data = {}
+ if vdu.get("cloud-init"):
+ boot_data["user-data"] = vdu["cloud-init"]
+ elif vdu.get("cloud-init-file"):
+ # TODO Where this file content is present???
+ # boot_data["user-data"] = rift_vnfd.files[vdu["cloud-init-file"]]
+ boot_data["user-data"] = str(vdu["cloud-init-file"])
+
+ if vdu.get("supplemental-boot-data"):
+ if vdu["supplemental-boot-data"].get('boot-data-drive'):
+ boot_data['boot-data-drive'] = True
+ if vdu["supplemental-boot-data"].get('config-file'):
+ om_cfgfile_list = list()
+ for custom_config_file in vdu["supplemental-boot-data"]['config-file'].itervalues():
+ # TODO Where this file content is present???
+ cfg_source = str(custom_config_file["source"])
+ om_cfgfile_list.append({"dest": custom_config_file["dest"],
+ "content": cfg_source})
+ boot_data['config-files'] = om_cfgfile_list
+ if boot_data:
+ db_vm["boot_data"] = boot_data
+
+ db_vms.append(db_vm)
+ db_vms_index += 1
+
+ # table interfaces (internal/external interfaces)
+ cp_name2iface_uuid = {}
+ cp_name2vm_uuid = {}
+ for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
+ iface_uuid = str(uuid4())
+ uuid_list.append(iface_uuid)
+ db_interface = {
+ "uuid": iface_uuid,
+ "internal_name": get_str(iface, "name", 255),
+ "vm_id": vm_uuid,
+ }
+ if iface.get("virtual-interface").get("vpci"):
+ db_interface["vpci"] = get_str(iface.get("virtual-interface"), "vpci", 12)
+
+ if iface.get("virtual-interface").get("bandwidth"):
+ bps = int(iface.get("virtual-interface").get("bandwidth"))
+ db_interface["bw"] = bps/1000
+
+ if iface.get("virtual-interface").get("type") == "OM-MGMT":
+ db_interface["type"] = "mgmt"
+ elif iface.get("virtual-interface").get("type") in ("VIRTIO", "E1000"):
+ db_interface["type"] = "bridge"
+ db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12)
+ elif iface.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
+ db_interface["type"] = "data"
+ db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12)
+ else:
+ raise ValueError("Interface type {} not supported".format(iface.get("virtual-interface").get("type")))
+
+ if iface.get("vnfd-connection-point-ref"):
+ try:
+ cp = vnfd.get("connection-point")[iface.get("vnfd-connection-point-ref")]
+ db_interface["external_name"] = get_str(cp, "name", 255)
+ cp_name2iface_uuid[db_interface["external_name"]] = iface_uuid
+ cp_name2vm_uuid[db_interface["external_name"]] = vm_uuid
+ # TODO add port-security-enable
+ # if cp.get("port-security-enabled") == False:
+ # elif cp.get("port-security-enabled") == True:
+ except KeyError:
+ raise KeyError(
+ "Error wrong reference at vnfd['{vnf}'] vdu['{vdu}']:internal-interface['{iface}']:"
+ "vnfd-connection-point-ref '{cp}' is not present at connection-point".format(
+ vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"],
+ cp=iface.get("vnfd-connection-point-ref"))
+ )
+ elif iface.get("vdu-internal-connection-point-ref"):
+ try:
+ for vld in vnfd.get("internal-vld").itervalues():
+ for cp in vld.get("internal-connection-point").itervalues():
+ if cp.get("id-ref") == iface.get("vdu-internal-connection-point-ref"):
+ db_interface["net_id"] = net_id2uuid[vld.get("id")]
+ break
+ except KeyError:
+ raise KeyError(
+ "Error at vnfd['{vnf}'] vdu['{vdu}']:internal-interface['{iface}']:"
+ "vdu-internal-connection-point-ref '{cp}' is not referenced by any internal-vld".format(
+ vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"],
+ cp=iface.get("vdu-internal-connection-point-ref"))
+ )
+
+ db_interfaces.append(db_interface)
+
+ # VNF affinity and antiaffinity
+ for pg in vnfd.get("placement-groups").itervalues():
+ pg_name = get_str(pg, "name", 255)
+ for vdu in pg.get("member-vdus").itervalues():
+ vdu_id = get_str(vdu, "member-vdu-ref", 255)
+ if vdu_id not in vdu_id2db_table_index:
+ raise KeyError(
+ "Error at 'vnfd'['{vnf}']:'placement-groups'['{pg}']:'member-vdus':'{vdu}' references a non existing vdu".format(
+ vnf=vnfd["id"], pg=pg_name, vdu=vdu_id))
+ db_vms[vdu_id2db_table_index[vdu_id]]["availability_zone"] = pg_name
+ # TODO consider the case of isolation and not colocation
+ # if pg.get("strategy") == "ISOLATION":
+
+ # VNF mgmt configuration
+ mgmt_access = {}
+ if vnfd["mgmt-interface"].get("vdu-id"):
+ if vnfd["mgmt-interface"]["vdu-id"] not in vdu_id2uuid:
+ raise KeyError(
+ "Error at vnfd['{vnf}']:'mgmt-interface':'vdu-id':{vdu} reference a non existing vdu".format(
+ vnf=vnfd["id"], vdu=vnfd["mgmt-interface"]["vdu-id"]))
+ mgmt_access["vm_id"] = vdu_id2uuid[vnfd["mgmt-interface"]["vdu-id"]]
+ if vnfd["mgmt-interface"].get("ip-address"):
+ mgmt_access["ip-address"] = str(vnfd["mgmt-interface"].get("ip-address"))
+ if vnfd["mgmt-interface"].get("cp"):
+ if vnfd["mgmt-interface"]["cp"] not in cp_name2iface_uuid:
+ raise KeyError(
+ "Error at vnfd['{vnf}']:'mgmt-interface':'cp':{cp} reference a non existing connection-point".
+ format(vnf=vnfd["id"], cp=vnfd["mgmt-interface"]["cp"]))
+ mgmt_access["vm_id"] = cp_name2vm_uuid[vnfd["mgmt-interface"]["cp"]]
+ mgmt_access["interface_id"] = cp_name2iface_uuid[vnfd["mgmt-interface"]["cp"]]
+ default_user = get_str(vnfd.get("vnf-configuration").get("config-access", {}).get("ssh-access", {}),
+ "default-user", 64)
+ if default_user:
+ mgmt_access["default_user"] = default_user
+ if mgmt_access:
+ db_vnf["mgmt_access"] = yaml.safe_dump(mgmt_access, default_flow_style=True, width=256)
+
+ db_vnfs.append(db_vnf)
+ db_tables=[
+ {"vnfs": db_vnfs},
+ {"nets": db_nets},
+ {"images": db_images},
+ {"flavors": db_flavors},
+ {"vms": db_vms},
+ {"interfaces": db_interfaces},
+ ]
+
+ logger.debug("create_vnf Deployment done vnfDict: %s",
+ yaml.safe_dump(db_tables, indent=4, default_flow_style=False) )
+ mydb.new_rows(db_tables, uuid_list)
+ return vnfd_uuid_list
+ except Exception as e:
+ logger.error("Exception {}".format(e))
+ raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
+
+
def new_vnf(mydb, tenant_id, vnf_descriptor):
global global_config
where_or["public"] = True
vnf = mydb.get_table_by_uuid_name('vnfs', vnf_id, "VNF", WHERE_OR=where_or, WHERE_AND_OR="AND")
- vnf_id=vnf["uuid"]
- filter_keys = ('uuid','name','description','public', "tenant_id", "created_at")
+ vnf_id = vnf["uuid"]
+ filter_keys = ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
filtered_content = dict( (k,v) for k,v in vnf.iteritems() if k in filter_keys )
#change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
data={'vnf' : filtered_content}
#GET VM
content = mydb.get_rows(FROM='vnfs join vms on vnfs.uuid=vms.vnf_id',
- SELECT=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
+ SELECT=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
+ 'boot_data'),
WHERE={'vnfs.uuid': vnf_id} )
if len(content)==0:
raise NfvoException("vnf '{}' not found".format(vnf_id), HTTP_Not_Found)
return scenario_id
+def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
+ """
+ Parses an OSM IM nsd_catalog and insert at DB
+ :param mydb:
+ :param tenant_id:
+ :param nsd_descriptor:
+ :return: The list of cretated NSD ids
+ """
+ try:
+ mynsd = nsd_catalog.nsd()
+ pybindJSONDecoder.load_ietf_json(nsd_descriptor, None, None, obj=mynsd)
+ db_scenarios = []
+ db_sce_nets = []
+ db_sce_vnfs = []
+ db_sce_interfaces = []
+ db_ip_profiles = []
+ db_ip_profiles_index = 0
+ uuid_list = []
+ nsd_uuid_list = []
+ for rift_nsd in mynsd.nsd_catalog.nsd.itervalues():
+ nsd = rift_nsd.get()
+
+ # table sceanrios
+ scenario_uuid = str(uuid4())
+ uuid_list.append(scenario_uuid)
+ nsd_uuid_list.append(scenario_uuid)
+ db_scenario = {
+ "uuid": scenario_uuid,
+ "osm_id": get_str(nsd, "id", 255),
+ "name": get_str(nsd, "name", 255),
+ "description": get_str(nsd, "description", 255),
+ "tenant_id": tenant_id,
+ "vendor": get_str(nsd, "vendor", 255),
+ "short_name": get_str(nsd, "short-name", 255),
+ "descriptor": str(nsd_descriptor)[:60000],
+ }
+ db_scenarios.append(db_scenario)
+
+ # table sce_vnfs (constituent-vnfd)
+ vnf_index2scevnf_uuid = {}
+ vnf_index2vnf_uuid = {}
+ for vnf in nsd.get("constituent-vnfd").itervalues():
+ existing_vnf = mydb.get_rows(FROM="vnfs", WHERE={'osm_id': str(vnf["vnfd-id-ref"])[:255],
+ 'tenant_id': tenant_id})
+ if not existing_vnf:
+ raise KeyError("Error at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':'{}' references a "
+ "non existing VNFD in the catalog".format(str(nsd["id"]),
+ str(vnf["vnfd-id-ref"])[:255]))
+ sce_vnf_uuid = str(uuid4())
+ uuid_list.append(sce_vnf_uuid)
+ db_sce_vnf = {
+ "uuid": sce_vnf_uuid,
+ "scenario_id": scenario_uuid,
+ "name": existing_vnf[0]["name"][:200] + "." + get_str(vnf, "member-vnf-index", 5),
+ "vnf_id": existing_vnf[0]["uuid"],
+ "member_vnf_index": int(vnf["member-vnf-index"]),
+ # TODO 'start-by-default': True
+ }
+ vnf_index2scevnf_uuid[int(vnf['member-vnf-index'])] = sce_vnf_uuid
+ vnf_index2vnf_uuid[int(vnf['member-vnf-index'])] = existing_vnf[0]["uuid"]
+ db_sce_vnfs.append(db_sce_vnf)
+
+ # table ip_profiles (ip-profiles)
+ ip_profile_name2db_table_index = {}
+ for ip_profile in nsd.get("ip-profiles").itervalues():
+ db_ip_profile = {
+ "ip_version": str(ip_profile["ip-profile-params"].get("ip-version", "ipv4")),
+ "subnet_address": str(ip_profile["ip-profile-params"].get("subnet-address")),
+ "gateway_address": str(ip_profile["ip-profile-params"].get("gateway-address")),
+ "dhcp_enabled": str(ip_profile["ip-profile-params"]["dhcp-params"].get("enabled", True)),
+ "dhcp_start_address": str(ip_profile["ip-profile-params"]["dhcp-params"].get("start-address")),
+ "dhcp_count": str(ip_profile["ip-profile-params"]["dhcp-params"].get("count")),
+ }
+ dns_list = []
+ for dns in ip_profile["ip-profile-params"]["dns-server"].itervalues():
+ dns_list.append(str(dns.get("address")))
+ db_ip_profile["dns_address"] = ";".join(dns_list)
+ if ip_profile["ip-profile-params"].get('security-group'):
+ db_ip_profile["security_group"] = ip_profile["ip-profile-params"]['security-group']
+ ip_profile_name2db_table_index[str(ip_profile["name"])] = db_ip_profiles_index
+ db_ip_profiles_index += 1
+ db_ip_profiles.append(db_ip_profile)
+
+ # table sce_nets (internal-vld)
+ for vld in nsd.get("vld").itervalues():
+ sce_net_uuid = str(uuid4())
+ uuid_list.append(sce_net_uuid)
+ db_sce_net = {
+ "uuid": sce_net_uuid,
+ "name": get_str(vld, "name", 255),
+ "scenario_id": scenario_uuid,
+ # "type": #TODO
+ "multipoint": not vld.get("type") == "ELINE",
+ # "external": #TODO
+ "description": get_str(vld, "description", 255),
+ }
+ # guess type of network
+ if vld.get("mgmt-network"):
+ db_sce_net["type"] = "bridge"
+ db_sce_net["external"] = True
+ elif vld.get("provider-network").get("overlay-type") == "VLAN":
+ db_sce_net["type"] = "data"
+ else:
+ db_sce_net["type"] = "bridge"
+ db_sce_nets.append(db_sce_net)
+
+ # ip-profile, link db_ip_profile with db_sce_net
+ if vld.get("ip-profile-ref"):
+ ip_profile_name = vld.get("ip-profile-ref")
+ if ip_profile_name not in ip_profile_name2db_table_index:
+ raise KeyError("Error at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}' references a non existing "
+ "'ip_profiles'".format(
+ str(nsd["id"]), str(vld["id"]), str(vld["ip-profile-ref"])))
+ db_ip_profiles[ip_profile_name2db_table_index[ip_profile_name]]["sce_net_id"] = sce_net_uuid
+
+ # table sce_interfaces (vld:vnfd-connection-point-ref)
+ for iface in vld.get("vnfd-connection-point-ref").itervalues():
+ vnf_index = int(iface['member-vnf-index-ref'])
+ # check correct parameters
+ if vnf_index not in vnf_index2vnf_uuid:
+ raise KeyError("Error at 'nsd[{}]':'vld[{}]':'vnfd-connection-point-ref':'member-vnf-index-ref'"
+ ":'{}' references a non existing index at 'nsd':'constituent-vnfd'".format(
+ str(nsd["id"]), str(vld["id"]), str(iface["member-vnf-index-ref"])))
+
+ existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',),
+ FROM="interfaces as i join vms on i.vm_id=vms.uuid",
+ WHERE={'vnf_id': vnf_index2vnf_uuid[vnf_index],
+ 'external_name': get_str(iface, "vnfd-connection-point-ref",
+ 255)})
+ if not existing_ifaces:
+ raise KeyError("Error at 'nsd[{}]':'vld[{}]':'vnfd-connection-point-ref':'vnfd-connection-point"
+ "-ref':'{}' references a non existing interface at VNFD '{}'".format(
+ str(nsd["id"]), str(vld["id"]), str(iface["vnfd-connection-point-ref"]),
+ str(iface.get("vnfd-id-ref"))[:255]))
+
+ interface_uuid = existing_ifaces[0]["uuid"]
+ sce_interface_uuid = str(uuid4())
+ uuid_list.append(sce_net_uuid)
+ db_sce_interface = {
+ "uuid": sce_interface_uuid,
+ "sce_vnf_id": vnf_index2scevnf_uuid[vnf_index],
+ "sce_net_id": sce_net_uuid,
+ "interface_id": interface_uuid,
+ # "ip_address": #TODO
+ }
+ db_sce_interfaces.append(db_sce_interface)
+
+ db_tables = [
+ {"scenarios": db_scenarios},
+ {"sce_nets": db_sce_nets},
+ {"ip_profiles": db_ip_profiles},
+ {"sce_vnfs": db_sce_vnfs},
+ {"sce_interfaces": db_sce_interfaces},
+ ]
+
+ logger.debug("create_vnf Deployment done vnfDict: %s",
+ yaml.safe_dump(db_tables, indent=4, default_flow_style=False) )
+ mydb.new_rows(db_tables, uuid_list)
+ return nsd_uuid_list
+ except Exception as e:
+ logger.error("Exception {}".format(e))
+ raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
+
+
def edit_scenario(mydb, tenant_id, scenario_id, data):
data["uuid"] = scenario_id
data["tenant_id"] = tenant_id
myvim_thread_id = myvim_threads_id[default_datacenter_id]
net_type = sce_net['type']
lookfor_filter = {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
- if sce_net["external"]:
- if not net_name:
+
+ if not net_name:
+ if sce_net["external"]:
net_name = sce_net["name"]
- if "netmap-use" in site or "netmap-create" in site:
- create_network = False
- lookfor_network = False
- if "netmap-use" in site:
- lookfor_network = True
- if utils.check_valid_uuid(site["netmap-use"]):
- filter_text = "scenario id '%s'" % site["netmap-use"]
- lookfor_filter["id"] = site["netmap-use"]
- else:
- filter_text = "scenario name '%s'" % site["netmap-use"]
- lookfor_filter["name"] = site["netmap-use"]
- if "netmap-create" in site:
- create_network = True
- net_vim_name = net_name
- if site["netmap-create"]:
- net_vim_name = site["netmap-create"]
-
- elif sce_net['vim_id'] != None:
+ else:
+ net_name = "{}.{}".format(instance_name, sce_net["name"])
+ net_name = net_name[:255] # limit length
+
+ if "netmap-use" in site or "netmap-create" in site:
+ create_network = False
+ lookfor_network = False
+ if "netmap-use" in site:
+ lookfor_network = True
+ if utils.check_valid_uuid(site["netmap-use"]):
+ filter_text = "scenario id '%s'" % site["netmap-use"]
+ lookfor_filter["id"] = site["netmap-use"]
+ else:
+ filter_text = "scenario name '%s'" % site["netmap-use"]
+ lookfor_filter["name"] = site["netmap-use"]
+ if "netmap-create" in site:
+ create_network = True
+ net_vim_name = net_name
+ if site["netmap-create"]:
+ net_vim_name = site["netmap-create"]
+ elif sce_net["external"]:
+ if sce_net['vim_id'] != None:
#there is a netmap at datacenter_nets database #TODO REVISE!!!!
create_network = False
lookfor_network = True
net_vim_name = sce_net["name"]
filter_text = "scenario name '%s'" % sce_net["name"]
else:
- if not net_name:
- net_name = "%s.%s" %(instance_name, sce_net["name"])
- net_name = net_name[:255] #limit length
net_vim_name = net_name
create_network = True
lookfor_network = False
+
+
if lookfor_network:
vim_nets = vim.get_network_list(filter_dict=lookfor_filter)
if len(vim_nets) > 1:
datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter)
network = myvim.get_network_list(filter_dict=filter_dict)
except vimconn.vimconnException as e:
- print "vim_action Not possible to get_%s_list from VIM: %s " % (item, str(e))
- raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item, str(e)), e.http_code)
+ raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e)), e.http_code)
# ensure the network is defined
if len(network) == 0:
scenario_dict["cloud-config"] = yaml.load(scenario_dict["cloud_config"])
del scenario_dict["cloud_config"]
#sce_vnfs
- cmd = "SELECT uuid,name,vnf_id,description FROM sce_vnfs WHERE scenario_id='{}' ORDER BY created_at".format(scenario_dict['uuid'])
+ cmd = "SELECT uuid,name,member_vnf_index,vnf_id,description FROM sce_vnfs WHERE scenario_id='{}' "\
+ "ORDER BY created_at".format(scenario_dict['uuid'])
self.logger.debug(cmd)
self.cur.execute(cmd)
scenario_dict['vnfs'] = self.cur.fetchall()
--- /dev/null
+nsd:nsd-catalog:
+ nsd:
+ - id: 3vdu_2vnf_nsd
+ name: 3vdu_2vnf_ns-name
+ short-name: 3vdu_2vnf-sname
+ description: 2 vnfs, eatch one with 3 cirros vdu
+ vendor: OSM
+ version: '1.0'
+
+ # Place the logo as png in icons directory and provide the name here
+ logo: osm_2x.png
+
+ # Specify the VNFDs that are part of this NSD
+ constituent-vnfd:
+ # The member-vnf-index needs to be unique, starting from 1
+ # vnfd-id-ref is the id of the VNFD
+ # Multiple constituent VNFDs can be specified
+ - member-vnf-index: 1
+ vnfd-id-ref: 3vdu_vnfd
+ - member-vnf-index: 2
+ vnfd-id-ref: 3vdu_vnfd
+
+ ip-profiles:
+ - description: Inter VNF Link
+ ip-profile-params:
+ gateway-address: 31.31.31.210
+ ip-version: ipv4
+ subnet-address: 31.31.31.0/24
+ dns-server:
+ - address: 8.8.8.8
+ - address: 8.8.8.9
+ dhcp-params:
+ count: 200
+ start-address: 31.31.31.2
+ name: ipprofileA
+
+
+ vld:
+ # Networks for the VNFs
+ - id: vld1
+ name: vld1-name
+ short-name: vld1-sname
+ type: ELAN
+ # vim-network-name: <update>
+ # provider-network:
+ # overlay-type: VLAN
+ # segmentation_id: <update>
+ ip-profile-ref: ipprofileA
+ vnfd-connection-point-ref:
+ # Specify the constituent VNFs
+ # member-vnf-index-ref - entry from constituent vnf
+ # vnfd-id-ref - VNFD id
+ # vnfd-connection-point-ref - connection point name in the VNFD
+ - member-vnf-index-ref: 1
+ vnfd-id-ref: 3vdu_vnfd
+ vnfd-connection-point-ref: eth0
+ - member-vnf-index-ref: 2
+ vnfd-id-ref: 3vdu_vnfd
+ vnfd-connection-point-ref: eth0
$openmano instance-scenario-delete -f complex3-instance || echo "fail"
$openmano instance-scenario-delete -f complex4-instance || echo "fail"
$openmano instance-scenario-delete -f complex5-instance || echo "fail"
+ $openmano instance-scenario-delete -f 3vdu_2vnf_nsd-instance || echo "fail"
$openmano scenario-delete -f simple || echo "fail"
$openmano scenario-delete -f complex || echo "fail"
$openmano scenario-delete -f complex2 || echo "fail"
$openmano scenario-delete -f complex3 || echo "fail"
$openmano scenario-delete -f complex4 || echo "fail"
$openmano scenario-delete -f complex5 || echo "fail"
+ $openmano scenario-delete -f osm_id=3vdu_2vnf_nsd || echo "fail"
$openmano vnf-delete -f linux || echo "fail"
$openmano vnf-delete -f linux_2VMs_v02 || echo "fail"
$openmano vnf-delete -f dataplaneVNF_2VMs || echo "fail"
$openmano vnf-delete -f dataplaneVNF2 || echo "fail"
$openmano vnf-delete -f dataplaneVNF3 || echo "fail"
$openmano vnf-delete -f dataplaneVNF4 || echo "fail"
+ $openmano vnf-delete -f osm_id=3vdu_vnfd || echo "fail"
elif [[ $action == "delete-all" ]]
then
result=`$openmano datacenter-netmap-import -f`
[[ $? != 0 ]] && echo "FAIL" && echo " $result" && $_exit 1
echo OK
+ result=`$openmano datacenter-netmap-create --name=default --vim-name=mgmt`
+ [[ $? != 0 ]] && echo "FAIL" && echo " $result" && $_exit 1
+ echo OK
elif [[ $action == "create" ]]
then
- for VNF in linux dataplaneVNF1 dataplaneVNF2 dataplaneVNF_2VMs dataplaneVNF_2VMs_v02 dataplaneVNF3 linux_2VMs_v02 dataplaneVNF4
+ for VNF in linux dataplaneVNF1 dataplaneVNF2 dataplaneVNF_2VMs dataplaneVNF_2VMs_v02 dataplaneVNF3 linux_2VMs_v02 dataplaneVNF4 v3_3vdu_vnfd
do
printf "%-50s" "Creating VNF '${VNF}': "
result=`$openmano vnf-create $DIRmano/vnfs/examples/${VNF}.yaml`
! is_valid_uuid $vnf && echo FAIL && echo " $result" && $_exit 1
echo $vnf
done
- for NS in simple complex complex2 complex3 complex4 complex5
+ for NS in simple complex complex2 complex3 complex4 complex5 v3_3vdu_2vnf_nsd
do
printf "%-50s" "Creating scenario '${NS}':"
result=`$openmano scenario-create $DIRmano/scenarios/examples/${NS}.yaml`
echo $scenario
done
- for IS in simple complex complex2 complex3 complex5
+ for IS in simple complex complex2 complex3 complex5 osm_id=3vdu_2vnf_nsd
do
printf "%-50s" "Creating instance-scenario '${IS}':"
- result=`$openmano instance-scenario-create --scenario ${IS} --name ${IS}-instance`
+ result=`$openmano instance-scenario-create --scenario ${IS} --name ${IS#osm_id=}-instance`
instance=`echo $result |gawk '{print $1}'`
! is_valid_uuid $instance && echo FAIL && echo " $result" && $_exit 1
echo $instance
--- /dev/null
+vnfd:vnfd-catalog:
+ vnfd:
+ - id: 3vdu_vnfd
+ name: 3vdu_vnfd-name
+ short-name: 3vdu-sname
+ description: Simple VNF example with a cirros and 3 vdu count
+ vendor: OSM
+ version: '1.0'
+
+ # Place the logo as png in icons directory and provide the name here
+ logo: cirros-64.png
+
+ # Management interface
+ mgmt-interface:
+ vdu-id: 3vduVM
+
+ # Atleast one VDU need to be specified
+ vdu:
+ - id: 3vduVM
+ name: 3vduVM-name
+ description: 3vduVM-description
+ count: 3
+
+ # Flavour of the VM to be instantiated for the VDU
+ # flavor below can fit into m1.micro
+ vm-flavor:
+ vcpu-count: 1
+ memory-mb: 256
+ storage-gb: 2
+
+ # Image/checksum or image including the full path
+ image: 'cirros034'
+ #checksum:
+
+ external-interface:
+ # Specify the external interfaces
+ # There can be multiple interfaces defined
+ - name: eth0
+ virtual-interface:
+ type: OM-MGMT
+ bandwidth: '0'
+ vnfd-connection-point-ref: eth0
+
+ connection-point:
+ - name: eth0
+ type: VPORT
+