RIFT OSM R1 Initial Submission
Signed-off-by: Jeremy Mordkoff <jeremy.mordkoff@riftio.com>
diff --git a/models/CMakeLists.txt b/models/CMakeLists.txt
new file mode 100644
index 0000000..dca2a03
--- /dev/null
+++ b/models/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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.
+#
+# Author(s): Anil Gunturu
+# Creation Date: 2014/12/11
+#
+
+cmake_minimum_required(VERSION 2.8)
+
+set(PKG_NAME models)
+set(PKG_VERSION 1.0)
+set(PKG_RELEASE 1)
+set(PKG_LONG_NAME ${PKG_NAME}-${PKG_VERSION})
+
+set(subdirs
+ plugins
+ openmano
+ )
+rift_add_subdirs(SUBDIR_LIST ${subdirs})
diff --git a/models/openmano/CMakeLists.txt b/models/openmano/CMakeLists.txt
new file mode 100644
index 0000000..ad0cdc8
--- /dev/null
+++ b/models/openmano/CMakeLists.txt
@@ -0,0 +1,27 @@
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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.
+#
+# Author(s): Anil Gunturu
+# Creation Date: 2014/12/11
+#
+
+cmake_minimum_required(VERSION 2.8)
+
+set(subdirs
+ bin
+ src
+ python
+ )
+rift_add_subdirs(SUBDIR_LIST ${subdirs})
diff --git a/models/openmano/bin/CMakeLists.txt b/models/openmano/bin/CMakeLists.txt
new file mode 100644
index 0000000..895823c
--- /dev/null
+++ b/models/openmano/bin/CMakeLists.txt
@@ -0,0 +1,12 @@
+# RIFT_IO_STANDARD_CMAKE_COPYRIGHT_HEADER(BEGIN)
+# Author(s): Austin Cormier
+# Creation Date: 1/11/2015
+# RIFT_IO_STANDARD_CMAKE_COPYRIGHT_HEADER(END)
+
+install(
+ PROGRAMS
+ openmano
+ openmano_cleanup.sh
+ DESTINATION usr/bin
+ COMPONENT ${PKG_LONG_NAME}
+)
diff --git a/models/openmano/bin/openmano b/models/openmano/bin/openmano
new file mode 100755
index 0000000..3ea0654
--- /dev/null
+++ b/models/openmano/bin/openmano
@@ -0,0 +1,1401 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# PYTHON_ARGCOMPLETE_OK
+
+##
+# 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
+##
+
+'''
+openmano client used to interact with openmano-server (openmanod)
+'''
+__author__="Alfonso Tierno, Gerardo Garcia"
+__date__ ="$09-oct-2014 09:09:48$"
+__version__="0.4.3-r467"
+version_date="Mar 2016"
+
+from argcomplete.completers import FilesCompleter
+import os
+import argparse
+import argcomplete
+import requests
+import json
+import yaml
+import logging
+#from jsonschema import validate as js_v, exceptions as js_e
+
+class ArgumentParserError(Exception): pass
+
+class OpenmanoCLIError(Exception): pass
+
+class ThrowingArgumentParser(argparse.ArgumentParser):
+ def error(self, message):
+ print "Error: %s" %message
+ print
+ self.print_usage()
+ #self.print_help()
+ print
+ print "Type 'openmano -h' for help"
+ raise ArgumentParserError
+
+
+def config(args):
+ print "OPENMANO_HOST: %s" %mano_host
+ print "OPENMANO_PORT: %s" %mano_port
+ if args.n:
+ logger.debug("resolving tenant and datacenter names")
+ mano_tenant_id = "None"
+ mano_tenant_name = "None"
+ mano_datacenter_id = "None"
+ mano_datacenter_name = "None"
+ try:
+ mano_tenant_id = _get_item_uuid("tenants", mano_tenant)
+ URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id)
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ content = mano_response.json()
+ mano_tenant_name = content["tenant"]["name"]
+ URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter)
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ content = mano_response.json()
+ if "error" not in content:
+ mano_datacenter_id = content["datacenter"]["uuid"]
+ mano_datacenter_name = content["datacenter"]["name"]
+ except OpenmanoCLIError:
+ pass
+ print "OPENMANO_TENANT: %s" %mano_tenant
+ print " Id: %s" %mano_tenant_id
+ print " Name: %s" %mano_tenant_name
+ print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
+ print " Id: %s" %mano_datacenter_id
+ print " Name: %s" %mano_datacenter_name
+ else:
+ print "OPENMANO_TENANT: %s" %mano_tenant
+ print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
+
+def _print_verbose(mano_response, verbose_level=0):
+ content = mano_response.json()
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ if type(content)!=dict or len(content)!=1:
+ #print "Non expected format output"
+ print str(content)
+ return result
+
+ val=content.values()[0]
+ if type(val)==str:
+ print val
+ return result
+ elif type(val) == list:
+ content_list = val
+ elif type(val)==dict:
+ content_list = [val]
+ else:
+ #print "Non expected dict/list format output"
+ print str(content)
+ return result
+
+ #print content_list
+ if verbose_level==None:
+ verbose_level=0
+ if verbose_level >= 3:
+ print yaml.safe_dump(content, indent=4, default_flow_style=False)
+ return result
+
+ if mano_response.status_code == 200:
+ for content in content_list:
+ if "uuid" in content:
+ uuid = content['uuid']
+ elif "id" in content:
+ uuid = content['id']
+ elif "vim_id" in content:
+ uuid = content['vim_id']
+ myoutput = "%s %s" %(uuid.ljust(38),content['name'].ljust(20))
+ if "status" in content:
+ myoutput += " " + content['status'].ljust(20)
+ elif "enabled" in content and not content["enabled"]:
+ myoutput += " enabled=False".ljust(20)
+ if verbose_level >=1:
+ if 'created_at' in content:
+ myoutput += " " + content['created_at'].ljust(20)
+ if verbose_level >=2:
+ new_line='\n'
+ if 'type' in content and content['type']!=None:
+ myoutput += new_line + " Type: " + content['type'].ljust(29)
+ new_line=''
+ if 'description' in content and content['description']!=None:
+ myoutput += new_line + " Description: " + content['description'].ljust(20)
+ print myoutput
+ else:
+ print content['error']['description']
+ return result
+
+def parser_json_yaml(file_name):
+ try:
+ f = file(file_name, "r")
+ text = f.read()
+ f.close()
+ except Exception as e:
+ return (False, str(e))
+
+ #Read and parse file
+ if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
+ try:
+ config = yaml.load(text)
+ except yaml.YAMLError as exc:
+ error_pos = ""
+ if hasattr(exc, 'problem_mark'):
+ mark = exc.problem_mark
+ error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
+ return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
+ else: #json
+ try:
+ config = json.loads(text)
+ except Exception as e:
+ return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
+
+ return True, config
+
+def _load_file_or_yaml(content):
+ '''
+ 'content' can be or a yaml/json file or a text containing a yaml/json text format
+ This function autodetect, trying to load and parse the file,
+ if fails trying to parse the 'content' text
+ Returns the dictionary once parsed, or print an error and finish the program
+ '''
+ #Check config file exists
+ if os.path.isfile(content):
+ r,payload = parser_json_yaml(content)
+ if not r:
+ print payload
+ exit(-1)
+ elif "{" in content or ":" in content:
+ try:
+ payload = yaml.load(content)
+ except yaml.YAMLError as exc:
+ error_pos = ""
+ if hasattr(exc, 'problem_mark'):
+ mark = exc.problem_mark
+ error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
+ print "Error loading yaml/json text"+error_pos
+ exit (-1)
+ else:
+ print "'%s' is neither a valid file nor a yaml/json content" % content
+ exit(-1)
+ return payload
+
+def _get_item_uuid(item, item_name_id, tenant=None):
+ if tenant:
+ URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
+ else:
+ URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ content = mano_response.json()
+ #print content
+ found = 0
+ for i in content[item]:
+ if i["uuid"] == item_name_id:
+ return item_name_id
+ if i["name"] == item_name_id:
+ 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:
+ raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
+ return uuid
+#
+# def check_valid_uuid(uuid):
+# id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
+# try:
+# js_v(uuid, id_schema)
+# return True
+# except js_e.ValidationError:
+# return False
+
+def _get_tenant(tenant_name_id = None):
+ if not tenant_name_id:
+ tenant_name_id = mano_tenant
+ if not mano_tenant:
+ raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
+ return _get_item_uuid("tenants", tenant_name_id)
+
+def _get_datacenter(datacenter_name_id = None, tenant = "any"):
+ if not datacenter_name_id:
+ datacenter_name_id = mano_datacenter
+ if not datacenter_name_id:
+ raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
+ return _get_item_uuid("datacenters", datacenter_name_id, tenant)
+
+def vnf_create(args):
+ #print "vnf-create",args
+ headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
+ tenant = _get_tenant()
+ myvnf = _load_file_or_yaml(args.file)
+
+ if args.name or args.description or args.image_path:
+ #print args.name
+ try:
+ if args.name:
+ myvnf['vnf']['name'] = args.name
+ if args.description:
+ myvnf['vnf']['description'] = args.description
+ if args.image_path:
+ index=0
+ for image_path_ in args.image_path.split(","):
+ #print "image-path", image_path_
+ myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
+ index=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']"
+ else: error_pos="wrong format"
+ print "Wrong VNF descriptor: " + error_pos
+ return -1
+ payload_req = json.dumps(myvnf)
+
+ #print payload_req
+
+ URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
+ 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 )
+
+ return _print_verbose(mano_response, args.verbose)
+
+def vnf_list(args):
+ #print "vnf-list",args
+ if args.all:
+ tenant = "any"
+ else:
+ tenant = _get_tenant()
+ if args.name:
+ toshow = _get_item_uuid("vnfs", args.name, tenant)
+ URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
+ else:
+ URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ content = mano_response.json()
+ #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
+ if mano_response.status_code == 200:
+ if not args.name:
+ if args.verbose >= 3:
+ print yaml.safe_dump(content, indent=4, default_flow_style=False)
+ return result
+ if len(content['vnfs']) == 0:
+ print "No VNFs were 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']
+ 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:"
+ 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:"
+ for net in vnf['nets']:
+ print " %s %s" %(net['name'].ljust(20), 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['vpci'].ljust(14))
+ else:
+ print content['error']['description']
+ if args.verbose:
+ print yaml.safe_dump(content, indent=4, default_flow_style=False)
+ return result
+
+def vnf_delete(args):
+ #print "vnf-delete",args
+ if args.all:
+ tenant = "any"
+ else:
+ tenant = _get_tenant()
+ todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
+ if not args.force:
+ r = raw_input("Delete VNF %s (y/N)? " %(todelete))
+ if not (len(r)>0 and r[0].lower()=="y"):
+ return 0
+ URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
+ mano_response = requests.delete(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ content = mano_response.json()
+ #print json.dumps(content, indent=4)
+ if mano_response.status_code == 200:
+ print content['result']
+ else:
+ print content['error']['description']
+ return result
+
+def scenario_create(args):
+ #print "scenario-create",args
+ tenant = _get_tenant()
+ headers_req = {'content-type': 'application/yaml'}
+ myscenario = _load_file_or_yaml(args.file)
+
+ if args.name:
+ myscenario['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)
+
+ #print payload_req
+
+ URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
+ 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 )
+ return _print_verbose(mano_response, args.verbose)
+
+def scenario_list(args):
+ #print "scenario-list",args
+ if args.all:
+ tenant = "any"
+ else:
+ tenant = _get_tenant()
+ if args.name:
+ toshow = _get_item_uuid("scenarios", args.name, tenant)
+ URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
+ else:
+ URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ content = mano_response.json()
+ #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
+ if mano_response.status_code == 200:
+ if not args.name:
+ if args.verbose >= 3:
+ print yaml.safe_dump(content, indent=4, default_flow_style=False)
+ return result
+ if len(content['scenarios']) == 0:
+ 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
+ if args.verbose >=2:
+ print " Description: %s" %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:"
+ 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:"
+ 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'])
+ else:
+ print content['error']['description']
+ if args.verbose:
+ print yaml.safe_dump(content, indent=4, default_flow_style=False)
+ return result
+
+def scenario_delete(args):
+ #print "scenario-delete",args
+ if args.all:
+ tenant = "any"
+ else:
+ tenant = _get_tenant()
+ todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
+ if not args.force:
+ r = raw_input("Delete scenario %s (y/N)? " %(args.name))
+ if not (len(r)>0 and r[0].lower()=="y"):
+ return 0
+ URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
+ mano_response = requests.delete(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ content = mano_response.json()
+ #print json.dumps(content, indent=4)
+ if mano_response.status_code == 200:
+ print content['result']
+ else:
+ print content['error']['description']
+ return result
+
+def scenario_deploy(args):
+ print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
+ print
+ args.file = None
+ args.netmap_use = None
+ args.netmap_create = None
+ return instance_create(args)
+
+# #print "scenario-deploy",args
+# headers_req = {'content-type': 'application/json'}
+# action = {}
+# actionCmd="start"
+# if args.nostart:
+# actionCmd="reserve"
+# action[actionCmd] = {}
+# action[actionCmd]["instance_name"] = args.name
+# if args.datacenter != None:
+# action[actionCmd]["datacenter"] = args.datacenter
+# elif mano_datacenter != None:
+# action[actionCmd]["datacenter"] = mano_datacenter
+#
+# if args.description:
+# action[actionCmd]["description"] = args.description
+# payload_req = json.dumps(action, indent=4)
+# #print payload_req
+#
+# URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
+# 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 )
+# if args.verbose==None:
+# args.verbose=0
+#
+# result = 0 if mano_response.status_code==200 else mano_response.status_code
+# content = mano_response.json()
+# #print json.dumps(content, indent=4)
+# if args.verbose >= 3:
+# print yaml.safe_dump(content, indent=4, default_flow_style=False)
+# return result
+#
+# if mano_response.status_code == 200:
+# myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
+# if args.verbose >=1:
+# myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
+# if args.verbose >=2:
+# myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
+# print myoutput
+# print ""
+# print "To check the status, run the following command:"
+# print "openmano instance-scenario-list <instance_id>"
+# else:
+# print content['error']['description']
+# return result
+
+def scenario_verify(args):
+ #print "scenario-verify",args
+ headers_req = {'content-type': 'application/json'}
+ action = {}
+ action["verify"] = {}
+ action["verify"]["instance_name"] = "scen-verify-return5"
+ payload_req = json.dumps(action, indent=4)
+ #print payload_req
+
+ URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
+ 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 )
+
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ content = mano_response.json()
+ #print json.dumps(content, indent=4)
+ if mano_response.status_code == 200:
+ print content['result']
+ else:
+ print content['error']['description']
+ return result
+
+def instance_create(args):
+ tenant = _get_tenant()
+ headers_req = {'content-type': 'application/yaml'}
+ myInstance={"instance": {}, "schema_version": "0.1"}
+ if args.file:
+ instance_dict = _load_file_or_yaml(args.file)
+ if "instance" not in instance_dict:
+ myInstance = {"instance": instance_dict, "schema_version": "0.1"}
+ else:
+ myInstance = instance_dict
+ if args.name:
+ myInstance["instance"]['name'] = args.name
+ if args.description:
+ myInstance["instance"]['description'] = args.description
+ if args.nostart:
+ myInstance["instance"]['action'] = "reserve"
+ #datacenter
+ datacenter = myInstance["instance"].get("datacenter")
+ if args.datacenter != None:
+ datacenter = args.datacenter
+ myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
+ #scenario
+ scenario = myInstance["instance"].get("scenario")
+ if args.scenario != None:
+ scenario = args.scenario
+ if not scenario:
+ print "you must provide an scenario in the file descriptor or with --scenario"
+ return -1
+ myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
+ if args.netmap_use:
+ if "networks" not in myInstance["instance"]:
+ myInstance["instance"]["networks"] = {}
+ for net in args.netmap_use:
+ net_comma_list = net.split(",")
+ for net_comma in net_comma_list:
+ net_tuple = net_comma.split("=")
+ if len(net_tuple) != 2:
+ print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
+ return
+ net_scenario = net_tuple[0].strip()
+ net_datacenter = net_tuple[1].strip()
+ if net_scenario not in myInstance["instance"]["networks"]:
+ myInstance["instance"]["networks"][net_scenario] = {}
+ myInstance["instance"]["networks"][net_scenario]["netmap-use"] = net_datacenter
+ if args.netmap_create:
+ if "networks" not in myInstance["instance"]:
+ myInstance["instance"]["networks"] = {}
+ for net in args.netmap_create:
+ net_comma_list = net.split(",")
+ for net_comma in net_comma_list:
+ net_tuple = net_comma.split("=")
+ if len(net_tuple) == 1:
+ net_scenario = net_tuple[0].strip()
+ net_datacenter = None
+ elif len(net_tuple) == 2:
+ net_scenario = net_tuple[0].strip()
+ net_datacenter = net_tuple[1].strip()
+ else:
+ print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
+ return
+ if net_scenario not in myInstance["instance"]["networks"]:
+ myInstance["instance"]["networks"][net_scenario] = {}
+ myInstance["instance"]["networks"][net_scenario]["netmap-create"] = net_datacenter
+
+ payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
+ logger.debug("openmano request: %s", payload_req)
+ URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
+ mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
+ logger.debug("openmano response: %s", mano_response.text )
+ if args.verbose==None:
+ args.verbose=0
+
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ content = mano_response.json()
+ #print json.dumps(content, indent=4)
+ if args.verbose >= 3:
+ print yaml.safe_dump(content, indent=4, default_flow_style=False)
+ return result
+
+ if mano_response.status_code == 200:
+ myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
+ if args.verbose >=1:
+ myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
+ if args.verbose >=2:
+ myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
+ print myoutput
+ else:
+ print content['error']['description']
+ return result
+
+def instance_scenario_list(args):
+ #print "instance-scenario-list",args
+ if args.all:
+ tenant = "any"
+ else:
+ tenant = _get_tenant()
+ if args.name:
+ toshow = _get_item_uuid("instances", args.name, tenant)
+ URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
+ else:
+ URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ content = mano_response.json()
+ #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
+ if mano_response.status_code == 200:
+ if not args.name:
+ if args.verbose >= 3:
+ print yaml.safe_dump(content, indent=4, default_flow_style=False)
+ return result
+ if len(content['instances']) == 0:
+ print "No scenario instances were found."
+ return result
+ for instance in content['instances']:
+ myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
+ if args.verbose >=1:
+ myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
+ print myoutput
+ if args.verbose >=2:
+ print "Description: %s" %instance['description']
+ else:
+ if args.verbose:
+ print yaml.safe_dump(content, indent=4, default_flow_style=False)
+ return result
+ instance = content
+ print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
+ print "Description: %s" %instance['description']
+ print "Template scenario id: %s" %instance['scenario_id']
+ print "Template scenario name: %s" %instance['scenario_name']
+ print "---------------------------------------"
+ print "VNF instances: %d" %len(instance['vnfs'])
+ for vnf in instance['vnfs']:
+ #print " %s %s Template vnf name: %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['name'].ljust(20), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
+ print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
+ if len(instance['nets'])>0:
+ print "---------------------------------------"
+ print "Internal nets:"
+ for net in instance['nets']:
+ if not net['external']:
+ print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
+ print "---------------------------------------"
+ print "External nets:"
+ for net in instance['nets']:
+ if net['external']:
+ print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
+ print "---------------------------------------"
+ print "VM instances:"
+ for vnf in instance['vnfs']:
+ for vm in vnf['vms']:
+ print " %s %s %s %s VIM ID: %s" %(vm['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vm['name'].ljust(20), vm['status'].ljust(12), vm['vim_vm_id'])
+ else:
+ print content['error']['description']
+ if args.verbose:
+ print yaml.safe_dump(content, indent=4, default_flow_style=False)
+ return result
+
+def instance_scenario_status(args):
+ print "instance-scenario-status"
+ return 0
+
+def instance_scenario_delete(args):
+ if args.all:
+ tenant = "any"
+ else:
+ tenant = _get_tenant()
+ todelete = _get_item_uuid("instances", args.name, tenant=tenant)
+ #print "instance-scenario-delete",args
+ if not args.force:
+ r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
+ if not (len(r)>0 and r[0].lower()=="y"):
+ return
+ URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
+ mano_response = requests.delete(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ content = mano_response.json()
+ #print json.dumps(content, indent=4)
+ if mano_response.status_code == 200:
+ print content['result']
+ else:
+ print content['error']['description']
+ return result
+
+def instance_scenario_action(args):
+ #print "instance-scenario-action", args
+ tenant = _get_tenant()
+ toact = _get_item_uuid("instances", args.name, tenant=tenant)
+ action={}
+ action[ args.action ] = args.param
+ if args.vnf:
+ action["vnfs"] = args.vnf
+ if args.vm:
+ action["vms"] = args.vm
+
+ headers_req = {'content-type': 'application/json'}
+ payload_req = json.dumps(action, indent=4)
+ URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
+ 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 )
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ content = mano_response.json()
+ #print json.dumps(content, indent=4)
+ if mano_response.status_code == 200:
+ if args.verbose:
+ print yaml.safe_dump(content, indent=4, default_flow_style=False)
+ return result
+ for uuid,c in content.iteritems():
+ print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
+ else:
+ print content['error']['description']
+ return result
+
+
+def instance_vnf_list(args):
+ print "instance-vnf-list"
+ return 0
+
+def instance_vnf_status(args):
+ print "instance-vnf-status"
+ return 0
+
+def tenant_create(args):
+ headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
+ tenant_dict={"name": args.name}
+ if args.description!=None:
+ tenant_dict["description"] = args.description
+ payload_req = json.dumps( {"tenant": tenant_dict })
+
+ #print payload_req
+
+ URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
+ 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 )
+ return _print_verbose(mano_response, args.verbose)
+
+def tenant_list(args):
+ #print "tenant-list",args
+ if args.name:
+ toshow = _get_item_uuid("tenants", args.name)
+ URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
+ else:
+ URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ if args.verbose==None:
+ args.verbose=0
+ if args.name!=None:
+ args.verbose += 1
+ return _print_verbose(mano_response, args.verbose)
+
+def tenant_delete(args):
+ #print "tenant-delete",args
+ todelete = _get_item_uuid("tenants", args.name)
+ if not args.force:
+ r = raw_input("Delete tenant %s (y/N)? " %(args.name))
+ if not (len(r)>0 and r[0].lower()=="y"):
+ return 0
+ URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
+ mano_response = requests.delete(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ content = mano_response.json()
+ #print json.dumps(content, indent=4)
+ if mano_response.status_code == 200:
+ print content['result']
+ else:
+ print content['error']['description']
+ return result
+
+def datacenter_attach(args):
+ tenant = _get_tenant()
+ datacenter = _get_datacenter(args.name)
+ headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
+
+ datacenter_dict={}
+ if args.vim_tenant_id != None:
+ datacenter_dict['vim_tenant'] = args.vim_tenant_id
+ if args.vim_tenant_name != None:
+ datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
+ if args.user != None:
+ datacenter_dict['vim_username'] = args.user
+ if args.password != None:
+ datacenter_dict['vim_password'] = args.password
+ payload_req = json.dumps( {"datacenter": datacenter_dict })
+
+ #print payload_req
+
+ URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
+ 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 )
+ result = _print_verbose(mano_response, args.verbose)
+ #provide addional information if error
+ if mano_response.status_code != 200:
+ content = mano_response.json()
+ if "already in use for 'name'" in content['error']['description'] and \
+ "to database vim_tenants table" in content['error']['description']:
+ print "Try to specify a different name with --vim-tenant-name"
+ return result
+
+def datacenter_detach(args):
+ if args.all:
+ tenant = "any"
+ else:
+ tenant = _get_tenant()
+ datacenter = _get_datacenter(args.name, tenant)
+ headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
+ URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
+ mano_response = requests.delete(URLrequest, headers=headers_req)
+ logger.debug("openmano response: %s", mano_response.text )
+ content = mano_response.json()
+ #print json.dumps(content, indent=4)
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ if mano_response.status_code == 200:
+ print content['result']
+ else:
+ print content['error']['description']
+ return result
+
+def datacenter_create(args):
+ headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
+ datacenter_dict={"name": args.name, "vim_url": args.url}
+ if args.description!=None:
+ datacenter_dict["description"] = args.description
+ if args.type!=None:
+ datacenter_dict["type"] = args.type
+ if args.url!=None:
+ datacenter_dict["vim_url_admin"] = args.url_admin
+ if args.config!=None:
+ datacenter_dict["config"] = _load_file_or_yaml(args.config)
+ payload_req = json.dumps( {"datacenter": datacenter_dict })
+
+ #print payload_req
+
+ URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
+ 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 )
+ return _print_verbose(mano_response, args.verbose)
+
+def datacenter_delete(args):
+ #print "datacenter-delete",args
+ todelete = _get_item_uuid("datacenters", args.name, "any")
+ if not args.force:
+ r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
+ if not (len(r)>0 and r[0].lower()=="y"):
+ return 0
+ URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
+ mano_response = requests.delete(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ content = mano_response.json()
+ #print json.dumps(content, indent=4)
+ if mano_response.status_code == 200:
+ print content['result']
+ else:
+ print content['error']['description']
+ return result
+
+def datacenter_list(args):
+ #print "datacenter-list",args
+ tenant='any' if args.all else _get_tenant()
+
+ if args.name:
+ toshow = _get_item_uuid("datacenters", args.name, tenant)
+ URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
+ else:
+ URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ if args.verbose==None:
+ args.verbose=0
+ if args.name!=None:
+ args.verbose += 1
+ return _print_verbose(mano_response, args.verbose)
+
+def vim_action(args):
+ #print "datacenter-net-action",args
+ tenant = _get_tenant()
+ datacenter = _get_datacenter(args.datacenter, tenant)
+ if args.verbose==None:
+ args.verbose=0
+ if args.action=="list":
+ URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
+ if args.name!=None:
+ args.verbose += 1
+ URLrequest += "/" + args.name
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ return _print_verbose(mano_response, args.verbose)
+ elif args.action=="delete":
+ URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
+ mano_response = requests.delete(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+ result = 0 if mano_response.status_code==200 else mano_response.status_code
+ content = mano_response.json()
+ #print json.dumps(content, indent=4)
+ if mano_response.status_code == 200:
+ print content['result']
+ else:
+ print content['error']['description']
+ return result
+ elif args.action=="create":
+ headers_req = {'content-type': 'application/yaml'}
+ if args.file:
+ create_dict = _load_file_or_yaml(args.file)
+ if args.item not in create_dict:
+ create_dict = {args.item: create_dict}
+ else:
+ create_dict = {args.item:{}}
+ if args.name:
+ create_dict[args.item]['name'] = args.name
+ #if args.description:
+ # create_dict[args.item]['description'] = args.description
+ if args.item=="vim-net":
+ if args.bind_net:
+ create_dict[args.item]['bind_net'] = args.bind_net
+ if args.bind_type:
+ create_dict[args.item]['bind_type'] = args.bind_type
+ if args.shared:
+ create_dict[args.item]['shared'] = args.shared
+ if "name" not in create_dict[args.item]:
+ print "You must provide a name in the descriptor file or with the --name option"
+ return
+ payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
+ logger.debug("openmano request: %s", payload_req)
+ URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
+ mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
+ logger.debug("openmano response: %s", mano_response.text )
+ if args.verbose==None:
+ args.verbose=0
+ return _print_verbose(mano_response, args.verbose)
+
+
+def datacenter_net_action(args):
+ if args.action == "net-update":
+ print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-upload' instead!!!"
+ print
+ args.action = "netmap-delete"
+ args.netmap = None
+ args.all = True
+ r = datacenter_netmap_action(args)
+ if r == 0:
+ args.force = True
+ args.action = "netmap-upload"
+ r = datacenter_netmap_action(args)
+ return r
+
+ if args.action == "net-edit":
+ args.netmap = args.net
+ args.name = None
+ elif args.action == "net-list":
+ args.netmap = None
+ elif args.action == "net-delete":
+ args.netmap = args.net
+ args.all = False
+
+ args.action = "netmap" + args.action[3:]
+ args.vim_name=None
+ args.vim_id=None
+ print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
+ print
+ return datacenter_netmap_action(args)
+
+def datacenter_netmap_action(args):
+ tenant = _get_tenant()
+ datacenter = _get_datacenter(args.datacenter, tenant)
+ #print "datacenter_netmap_action",args
+ payload_req = None
+ if args.verbose==None:
+ args.verbose=0
+ headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
+ URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
+
+ if args.action=="netmap-list":
+ if args.netmap:
+ URLrequest += "/" + args.netmap
+ args.verbose += 1
+ mano_response = requests.get(URLrequest)
+
+ elif args.action=="netmap-delete":
+ if args.netmap and args.all:
+ print "you can not use a netmap name and the option --all at the same time"
+ return 1
+ if args.netmap:
+ force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
+ URLrequest += "/" + args.netmap
+ elif args.all:
+ force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
+ else:
+ print "you must specify a netmap name or the option --all"
+ return 1
+ if not args.force:
+ r = raw_input(force_text)
+ if len(r)>0 and r[0].lower()=="y":
+ pass
+ else:
+ return 0
+ mano_response = requests.delete(URLrequest, headers=headers_req)
+ elif args.action=="netmap-upload":
+ if not args.force:
+ r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
+ if len(r)>0 and r[0].lower()=="y":
+ pass
+ else:
+ return 0
+ URLrequest += "/upload"
+ mano_response = requests.post(URLrequest, headers=headers_req)
+ elif args.action=="netmap-edit" or args.action=="netmap-create":
+ if args.file:
+ payload = _load_file_or_yaml(args.file)
+ else:
+ payload = {}
+ if "netmap" not in payload:
+ payload = {"netmap": payload}
+ if args.name:
+ payload["netmap"]["name"] = args.name
+ if args.vim_id:
+ payload["netmap"]["vim_id"] = args.vim_id
+ if args.action=="netmap-create" and args.vim_name:
+ payload["netmap"]["vim_name"] = args.vim_name
+ payload_req = json.dumps(payload)
+ logger.debug("openmano request: %s", payload_req)
+
+ if args.action=="netmap-edit" and not args.force:
+ if len(payload["netmap"]) == 0:
+ print "You must supply some parameter to edit"
+ return 1
+ r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
+ if len(r)>0 and r[0].lower()=="y":
+ pass
+ else:
+ return 0
+ URLrequest += "/" + args.netmap
+ mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
+ else: #netmap-create
+ if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
+ print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
+ return 1
+ mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
+
+ logger.debug("openmano response: %s", mano_response.text )
+ return _print_verbose(mano_response, args.verbose)
+
+def element_edit(args):
+ element = _get_item_uuid(args.element, args.name)
+ headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
+ URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
+ payload=_load_file_or_yaml(args.file)
+ if args.element[:-1] not in payload:
+ payload = {args.element[:-1]: payload }
+ payload_req = json.dumps(payload)
+
+ #print payload_req
+ if not args.force or (args.name==None and args.filer==None):
+ r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
+ if len(r)>0 and r[0].lower()=="y":
+ pass
+ else:
+ return 0
+ logger.debug("openmano request: %s", payload_req)
+ mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
+ logger.debug("openmano response: %s", mano_response.text )
+ if args.verbose==None:
+ args.verbose=0
+ if args.name!=None:
+ args.verbose += 1
+ return _print_verbose(mano_response, args.verbose)
+
+
+global mano_host
+global mano_port
+global mano_tenant
+
+if __name__=="__main__":
+
+ mano_tenant = os.getenv('OPENMANO_TENANT', None)
+ mano_host = os.getenv('OPENMANO_HOST',"localhost")
+ mano_port = os.getenv('OPENMANO_PORT',"9090")
+ mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
+
+ main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
+ main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
+
+ subparsers = main_parser.add_subparsers(help='commands')
+
+ parent_parser = argparse.ArgumentParser(add_help=False)
+ parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
+ parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
+
+ config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
+ config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
+ config_parser.set_defaults(func=config)
+
+ vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
+ vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
+ vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
+ vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
+ vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
+ vnf_create_parser.set_defaults(func=vnf_create)
+
+ vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
+ vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
+ vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
+ #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
+ vnf_list_parser.set_defaults(func=vnf_list)
+
+ vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
+ vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
+ vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
+ vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
+ vnf_delete_parser.set_defaults(func=vnf_delete)
+
+ scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
+ scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
+ scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
+ scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
+ scenario_create_parser.set_defaults(func=scenario_create)
+
+ scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
+ scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
+ #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
+ scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
+ scenario_list_parser.set_defaults(func=scenario_list)
+
+ scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
+ scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
+ scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
+ scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
+ scenario_delete_parser.set_defaults(func=scenario_delete)
+
+ scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
+ scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
+ scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
+ scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
+ scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
+ scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
+ scenario_deploy_parser.set_defaults(func=scenario_deploy)
+
+ scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
+ scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
+ scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
+ scenario_deploy_parser.set_defaults(func=scenario_verify)
+
+ instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
+ instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
+ instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
+ instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
+ instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
+ instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
+ instance_scenario_create_parser.add_argument("--netmap-use", action="append", type=str, dest="netmap_use", help="indicates a datacenter network to map a scenario network 'scenario-network=datacenter-network'. Can be used several times")
+ instance_scenario_create_parser.add_argument("--netmap-create", action="append", type=str, dest="netmap_create", help="the scenario network must be created at datacenter 'scenario-network[=datacenter-network-name]' . Can be used several times")
+ instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
+ instance_scenario_create_parser.set_defaults(func=instance_create)
+
+ instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
+ instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
+ instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
+ instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
+
+ instance_scenario_delete_parser = subparsers.add_parser('instance-scenario-delete', parents=[parent_parser], help="deletes a scenario instance (and deletes all VM and net instances in VIM)")
+ instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
+ instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
+ instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
+ instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
+
+ instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
+ instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
+ instance_scenario_action_parser.add_argument("action", action="store", type=str, \
+ choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
+ help="action to send")
+ instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
+ instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
+ instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
+ instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
+
+ #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
+ #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
+ #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
+
+ tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
+ tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
+ tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
+ tenant_create_parser.set_defaults(func=tenant_create)
+
+ tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
+ tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
+ tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
+ tenant_delete_parser.set_defaults(func=tenant_delete)
+
+ tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
+ tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
+ tenant_list_parser.set_defaults(func=tenant_list)
+
+ item_list=('tenant','datacenter') #put tenant before so that help appear in order
+ for item in item_list:
+ element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
+ element_edit_parser.add_argument("name", help="name or uuid of the "+item)
+ element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
+ element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
+ element_edit_parser.set_defaults(func=element_edit, element=item + 's')
+
+ datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
+ datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
+ datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
+ datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
+ datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
+ datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
+ datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
+ datacenter_create_parser.set_defaults(func=datacenter_create)
+
+ datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
+ datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
+ datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
+ datacenter_delete_parser.set_defaults(func=datacenter_delete)
+
+ datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
+ datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
+ datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
+ datacenter_list_parser.set_defaults(func=datacenter_list)
+
+ datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
+ datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
+ datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
+ datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
+ datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
+ datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
+ datacenter_attach_parser.set_defaults(func=datacenter_attach)
+
+ datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
+ datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
+ datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
+ datacenter_detach_parser.set_defaults(func=datacenter_detach)
+
+
+ action_dict={'net-update': 'retrieves external networks from datacenter',
+ 'net-edit': 'edits an external network',
+ 'net-delete': 'deletes an external network',
+ 'net-list': 'lists external networks from a datacenter'
+ }
+ for item in action_dict:
+ datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
+ datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
+ if item=='net-edit' or item=='net-delete':
+ datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
+ if item=='net-edit':
+ datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
+ if item!='net-list':
+ datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
+ datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
+
+
+ action_dict={'netmap-upload': 'create network senario netmap base on the datacenter networks',
+ 'netmap-create': 'create a new network senario netmap',
+ 'netmap-edit': 'edit name of a network senario netmap',
+ 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
+ 'netmap-list': 'list/show network scenario netmaps'
+ }
+ for item in action_dict:
+ datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
+ datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
+ #if item=='net-add':
+ # datacenter_action_parser.add_argument("net", help="name of the network")
+ if item=='netmap-delete':
+ datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
+ datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
+ datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
+ if item=='netmap-edit':
+ datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
+ datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
+ datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
+ datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
+ datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
+ if item=='netmap-list':
+ datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
+ if item=='netmap-create':
+ datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
+ datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
+ datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
+ datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
+ if item=='netmap-upload':
+ datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
+ datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
+
+ for item in ("network", "tenant"):
+ if item=="network":
+ commnad_name = 'vim-net'
+ else:
+ commnad_name = 'vim-'+item
+ vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
+ vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
+ vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
+ vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
+
+ vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
+ vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
+ vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
+ vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
+
+ vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
+ vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
+ vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
+ vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
+ if item=="network":
+ vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
+ vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
+ vim_item_create_parser.add_argument("--bind-net", action="store", help="For openvim datacenter type, net to be bind to, for vlan type, use sufix ':<vlan_tag>'")
+ else:
+ vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
+ vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
+
+ argcomplete.autocomplete(main_parser)
+
+ try:
+ args = main_parser.parse_args()
+ #logging info
+ level = logging.CRITICAL
+ streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
+ if "debug" in args and args.debug:
+ level = logging.DEBUG
+ logging.basicConfig(format=streamformat, level= level)
+ logger = logging.getLogger('mano')
+ logger.setLevel(level)
+ result = args.func(args)
+ if result == None:
+ result = 0
+ #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
+ except (requests.exceptions.ConnectionError):
+ print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
+ result = -2
+ except (KeyboardInterrupt):
+ print 'Exiting openmano'
+ result = -3
+ except (SystemExit, ArgumentParserError):
+ result = -4
+ except OpenmanoCLIError as e:
+ print str(e)
+ result = -5
+
+ #print result
+ exit(result)
+
diff --git a/models/openmano/bin/openmano_cleanup.sh b/models/openmano/bin/openmano_cleanup.sh
new file mode 100755
index 0000000..326018d
--- /dev/null
+++ b/models/openmano/bin/openmano_cleanup.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Run this on openmano VM to clean up all instances, scenarios and vnfs.
+
+./openmano instance-scenario-list | cut -d " " -f1 | while read line; do
+./openmano instance-scenario-delete $line -f
+done
+
+./openmano scenario-list | cut -d " " -f1 | while read line; do
+./openmano scenario-delete $line -f
+done
+
+./openmano vnf-list | cut -d " " -f1 | while read line; do
+./openmano vnf-delete $line -f
+done
diff --git a/models/openmano/python/CMakeLists.txt b/models/openmano/python/CMakeLists.txt
new file mode 100644
index 0000000..abbf139
--- /dev/null
+++ b/models/openmano/python/CMakeLists.txt
@@ -0,0 +1,13 @@
+# Creation Date: 2016/1/12
+# RIFT_IO_STANDARD_CMAKE_COPYRIGHT_HEADER(END)
+
+cmake_minimum_required(VERSION 2.8)
+
+
+rift_python_install_tree(
+ FILES
+ rift/openmano/__init__.py
+ rift/openmano/rift2openmano.py
+ rift/openmano/openmano_client.py
+ COMPONENT ${PKG_LONG_NAME}
+ PYTHON3_ONLY)
diff --git a/models/openmano/python/rift/openmano/__init__.py b/models/openmano/python/rift/openmano/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/models/openmano/python/rift/openmano/__init__.py
diff --git a/models/openmano/python/rift/openmano/openmano_client.py b/models/openmano/python/rift/openmano/openmano_client.py
new file mode 100755
index 0000000..bd34be1
--- /dev/null
+++ b/models/openmano/python/rift/openmano/openmano_client.py
@@ -0,0 +1,524 @@
+#!/usr/bin/python3
+
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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.
+#
+
+import argparse
+import logging
+import os
+import re
+import subprocess
+import sys
+import tempfile
+import requests
+import json
+
+
+class OpenmanoCommandFailed(Exception):
+ pass
+
+
+class OpenmanoUnexpectedOutput(Exception):
+ pass
+
+
+class VNFExistsError(Exception):
+ pass
+
+
+class InstanceStatusError(Exception):
+ pass
+
+
+class OpenmanoHttpAPI(object):
+ def __init__(self, log, host, port, tenant):
+ self._log = log
+ self._host = host
+ self._port = port
+ self._tenant = tenant
+
+ self._session = requests.Session()
+
+ def get_instance(self, instance_uuid):
+ url = "http://{host}:{port}/openmano/{tenant}/instances/{instance}".format(
+ host=self._host,
+ port=self._port,
+ tenant=self._tenant,
+ instance=instance_uuid,
+ )
+
+ resp = self._session.get(url)
+ try:
+ resp.raise_for_status()
+ except requests.exceptions.HTTPError as e:
+ raise InstanceStatusError(e)
+
+ return resp.json()
+
+ def get_instance_vm_console_url(self, instance_uuid, vim_uuid):
+ url = "http://{host}:{port}/openmano/{tenant}/instances/{instance}/action".format(
+ host=self._host,
+ port=self._port,
+ tenant=self._tenant,
+ instance=instance_uuid,
+ )
+
+ console_types = ("novnc", "spice-html5", "xvpnvc", "rdp-html5")
+ for console_type in console_types:
+ payload_input = {"console":console_type, "vms":[vim_uuid]}
+ payload_data = json.dumps(payload_input)
+ resp = self._session.post(url, headers={'content-type': 'application/json'},
+ data=payload_data)
+ try:
+ resp.raise_for_status()
+ except requests.exceptions.HTTPError as e:
+ raise InstanceStatusError(e)
+ result = resp.json()
+ if vim_uuid in result and (result[vim_uuid]["vim_result"] == 1 or result[vim_uuid]["vim_result"] == 200):
+ return result[vim_uuid]["description"]
+
+ return None
+
+
+class OpenmanoCliAPI(object):
+ """ This class implements the necessary funtionality to interact with """
+
+ CMD_TIMEOUT = 30
+
+ def __init__(self, log, host, port, tenant):
+ self._log = log
+ self._host = host
+ self._port = port
+ self._tenant = tenant
+
+ @staticmethod
+ def openmano_cmd_path():
+ return os.path.join(
+ os.environ["RIFT_INSTALL"],
+ "usr/bin/openmano"
+ )
+
+ def _openmano_cmd(self, arg_list, expected_lines=None):
+ cmd_args = list(arg_list)
+ cmd_args.insert(0, self.openmano_cmd_path())
+
+ env = {
+ "OPENMANO_HOST": self._host,
+ "OPENMANO_PORT": str(self._port),
+ "OPENMANO_TENANT": self._tenant,
+ }
+
+ self._log.debug(
+ "Running openmano command (%s) using env (%s)",
+ subprocess.list2cmdline(cmd_args),
+ env,
+ )
+
+ proc = subprocess.Popen(
+ cmd_args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ universal_newlines=True,
+ env=env
+ )
+ try:
+ stdout, stderr = proc.communicate(timeout=self.CMD_TIMEOUT)
+ except subprocess.TimeoutExpired:
+ self._log.error("Openmano command timed out")
+ proc.terminate()
+ stdout, stderr = proc.communicate(timeout=self.CMD_TIMEOUT)
+
+ if proc.returncode != 0:
+ self._log.error(
+ "Openmano command failed (rc=%s) with stdout: %s",
+ proc.returncode, stdout
+ )
+ raise OpenmanoCommandFailed(stdout)
+
+ self._log.debug("Openmano command completed with stdout: %s", stdout)
+
+ output_lines = stdout.splitlines()
+ if expected_lines is not None:
+ if len(output_lines) != expected_lines:
+ msg = "Expected %s lines from openmano command. Got %s" % (expected_lines, len(output_lines))
+ self._log.error(msg)
+ raise OpenmanoUnexpectedOutput(msg)
+
+ return output_lines
+
+
+ def vnf_create(self, vnf_yaml_str):
+ """ Create a Openmano VNF from a Openmano VNF YAML string """
+
+ self._log.debug("Creating VNF: %s", vnf_yaml_str)
+
+ with tempfile.NamedTemporaryFile() as vnf_file_hdl:
+ vnf_file_hdl.write(vnf_yaml_str.encode())
+ vnf_file_hdl.flush()
+
+ try:
+ output_lines = self._openmano_cmd(
+ ["vnf-create", vnf_file_hdl.name],
+ expected_lines=1
+ )
+ except OpenmanoCommandFailed as e:
+ if "already in use" in str(e):
+ raise VNFExistsError("VNF was already added")
+ raise
+
+ vnf_info_line = output_lines[0]
+ vnf_id, vnf_name = vnf_info_line.split(" ", 1)
+
+ self._log.info("VNF %s Created: %s", vnf_name, vnf_id)
+
+ return vnf_id, vnf_name
+
+ def vnf_delete(self, vnf_uuid):
+ self._openmano_cmd(
+ ["vnf-delete", vnf_uuid, "-f"],
+ )
+
+ self._log.info("VNF Deleted: %s", vnf_uuid)
+
+ def vnf_list(self):
+ try:
+ output_lines = self._openmano_cmd(
+ ["vnf-list"],
+ )
+ except OpenmanoCommandFailed as e:
+ self._log.warning("Vnf listing returned an error: %s", str(e))
+ return {}
+
+ name_uuid_map = {}
+ for line in output_lines:
+ line = line.strip()
+ uuid, name = line.split(" ", 1)
+ name_uuid_map[name] = uuid
+
+ return name_uuid_map
+
+ def ns_create(self, ns_yaml_str, name=None):
+ self._log.info("Creating NS: %s", ns_yaml_str)
+
+ with tempfile.NamedTemporaryFile() as ns_file_hdl:
+ ns_file_hdl.write(ns_yaml_str.encode())
+ ns_file_hdl.flush()
+
+ cmd_args = ["scenario-create", ns_file_hdl.name]
+ if name is not None:
+ cmd_args.extend(["--name", name])
+
+ output_lines = self._openmano_cmd(
+ cmd_args,
+ expected_lines=1
+ )
+
+ ns_info_line = output_lines[0]
+ ns_id, ns_name = ns_info_line.split(" ", 1)
+
+ self._log.info("NS %s Created: %s", ns_name, ns_id)
+
+ return ns_id, ns_name
+
+ def ns_list(self):
+ self._log.debug("Getting NS list")
+
+ try:
+ output_lines = self._openmano_cmd(
+ ["scenario-list"],
+ )
+
+ except OpenmanoCommandFailed as e:
+ self._log.warning("NS listing returned an error: %s", str(e))
+ return {}
+
+ name_uuid_map = {}
+ for line in output_lines:
+ line = line.strip()
+ uuid, name = line.split(" ", 1)
+ name_uuid_map[name] = uuid
+
+ return name_uuid_map
+
+ def ns_delete(self, ns_uuid):
+ self._log.info("Deleting NS: %s", ns_uuid)
+
+ self._openmano_cmd(
+ ["scenario-delete", ns_uuid, "-f"],
+ )
+
+ self._log.info("NS Deleted: %s", ns_uuid)
+
+ def ns_instance_list(self):
+ self._log.debug("Getting NS instance list")
+
+ try:
+ output_lines = self._openmano_cmd(
+ ["instance-scenario-list"],
+ )
+
+ except OpenmanoCommandFailed as e:
+ self._log.warning("Instance scenario listing returned an error: %s", str(e))
+ return {}
+
+ if "No scenario instances were found" in output_lines[0]:
+ self._log.debug("No openmano instances were found")
+ return {}
+
+ name_uuid_map = {}
+ for line in output_lines:
+ line = line.strip()
+ uuid, name = line.split(" ", 1)
+ name_uuid_map[name] = uuid
+
+ return name_uuid_map
+
+ def ns_instance_scenario_create(self, instance_yaml_str):
+ """ Create a Openmano NS instance from input YAML string """
+
+ self._log.debug("Instantiating instance: %s", instance_yaml_str)
+
+ with tempfile.NamedTemporaryFile() as ns_instance_file_hdl:
+ ns_instance_file_hdl.write(instance_yaml_str.encode())
+ ns_instance_file_hdl.flush()
+
+ try:
+ output_lines = self._openmano_cmd(
+ ["instance-scenario-create", ns_instance_file_hdl.name],
+ expected_lines=1
+ )
+ except OpenmanoCommandFailed as e:
+ raise
+
+ uuid, _ = output_lines[0].split(" ", 1)
+
+ self._log.info("NS Instance Created: %s", uuid)
+
+ return uuid
+
+ def ns_instantiate(self, scenario_name, instance_name, datacenter_name=None):
+ self._log.info(
+ "Instantiating NS %s using instance name %s",
+ scenario_name,
+ instance_name,
+ )
+
+ cmd_args = ["scenario-deploy", scenario_name, instance_name]
+ if datacenter_name is not None:
+ cmd_args.extend(["--datacenter", datacenter_name])
+
+ output_lines = self._openmano_cmd(
+ cmd_args,
+ expected_lines=4
+ )
+
+ uuid, _ = output_lines[0].split(" ", 1)
+
+ self._log.info("NS Instance Created: %s", uuid)
+
+ return uuid
+
+ def ns_terminate(self, ns_instance_name):
+ self._log.info("Terminating NS: %s", ns_instance_name)
+
+ self._openmano_cmd(
+ ["instance-scenario-delete", ns_instance_name, "-f"],
+ )
+
+ self._log.info("NS Instance Deleted: %s", ns_instance_name)
+
+ def datacenter_list(self):
+ lines = self._openmano_cmd(["datacenter-list",])
+
+ # The results returned from openmano are formatted with whitespace and
+ # datacenter names may contain whitespace as well, so we use a regular
+ # expression to parse each line of the results return from openmano to
+ # extract the uuid and name of a datacenter.
+ hex = '[0-9a-fA-F]'
+ uuid_pattern = '(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)'.replace('x', hex)
+ name_pattern = '(.+?)'
+ datacenter_regex = re.compile(r'{uuid}\s+\b{name}\s*$'.format(
+ uuid=uuid_pattern,
+ name=name_pattern,
+ ))
+
+ # Parse the results for the datacenter uuids and names
+ datacenters = list()
+ for line in lines:
+ result = datacenter_regex.match(line)
+ if result is not None:
+ uuid, name = result.groups()
+ datacenters.append((uuid, name))
+
+ return datacenters
+
+
+def valid_uuid(uuid_str):
+ uuid_re = re.compile(
+ "^xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx$".replace('x', '[0-9a-fA-F]')
+ )
+
+ if not uuid_re.match(uuid_str):
+ raise argparse.ArgumentTypeError("Got a valid uuid: %s" % uuid_str)
+
+ return uuid_str
+
+
+def parse_args(argv=sys.argv[1:]):
+ """ Parse the command line arguments
+
+ Arguments:
+ argv - The list of arguments to parse
+
+ Returns:
+ Argparse Namespace instance
+ """
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '-d', '--host',
+ default='localhost',
+ help="Openmano host/ip",
+ )
+
+ parser.add_argument(
+ '-p', '--port',
+ default='9090',
+ help="Openmano port",
+ )
+
+ parser.add_argument(
+ '-t', '--tenant',
+ required=True,
+ type=valid_uuid,
+ help="Openmano tenant uuid to use",
+ )
+
+ subparsers = parser.add_subparsers(dest='command', help='openmano commands')
+
+ vnf_create_parser = subparsers.add_parser(
+ 'vnf-create',
+ help="Adds a openmano vnf into the catalog"
+ )
+ vnf_create_parser.add_argument(
+ "file",
+ help="location of the JSON file describing the VNF",
+ type=argparse.FileType('rb'),
+ )
+
+ vnf_delete_parser = subparsers.add_parser(
+ 'vnf-delete',
+ help="Deletes a openmano vnf into the catalog"
+ )
+ vnf_delete_parser.add_argument(
+ "uuid",
+ help="The vnf to delete",
+ type=valid_uuid,
+ )
+
+
+ ns_create_parser = subparsers.add_parser(
+ 'scenario-create',
+ help="Adds a openmano ns scenario into the catalog"
+ )
+ ns_create_parser.add_argument(
+ "file",
+ help="location of the JSON file describing the NS",
+ type=argparse.FileType('rb'),
+ )
+
+ ns_delete_parser = subparsers.add_parser(
+ 'scenario-delete',
+ help="Deletes a openmano ns into the catalog"
+ )
+ ns_delete_parser.add_argument(
+ "uuid",
+ help="The ns to delete",
+ type=valid_uuid,
+ )
+
+
+ ns_instance_create_parser = subparsers.add_parser(
+ 'scenario-deploy',
+ help="Deploys a openmano ns scenario into the catalog"
+ )
+ ns_instance_create_parser.add_argument(
+ "scenario_name",
+ help="The ns scenario name to deploy",
+ )
+ ns_instance_create_parser.add_argument(
+ "instance_name",
+ help="The ns instance name to deploy",
+ )
+
+
+ ns_instance_delete_parser = subparsers.add_parser(
+ 'instance-scenario-delete',
+ help="Deploys a openmano ns scenario into the catalog"
+ )
+ ns_instance_delete_parser.add_argument(
+ "instance_name",
+ help="The ns instance name to delete",
+ )
+
+
+ _ = subparsers.add_parser(
+ 'datacenter-list',
+ )
+
+ args = parser.parse_args(argv)
+
+ return args
+
+
+def main():
+ logging.basicConfig(level=logging.DEBUG)
+ logger = logging.getLogger("openmano_client.py")
+
+ if "RIFT_INSTALL" not in os.environ:
+ logger.error("Must be in rift-shell to run.")
+ sys.exit(1)
+
+ args = parse_args()
+ openmano_cli = OpenmanoCliAPI(logger, args.host, args.port, args.tenant)
+
+ if args.command == "vnf-create":
+ openmano_cli.vnf_create(args.file.read())
+
+ elif args.command == "vnf-delete":
+ openmano_cli.vnf_delete(args.uuid)
+
+ elif args.command == "scenario-create":
+ openmano_cli.ns_create(args.file.read())
+
+ elif args.command == "scenario-delete":
+ openmano_cli.ns_delete(args.uuid)
+
+ elif args.command == "scenario-deploy":
+ openmano_cli.ns_instantiate(args.scenario_name, args.instance_name)
+
+ elif args.command == "instance-scenario-delete":
+ openmano_cli.ns_terminate(args.instance_name)
+
+ elif args.command == "datacenter-list":
+ for uuid, name in openmano_cli.datacenter_list():
+ print("{} {}".format(uuid, name))
+
+ else:
+ logger.error("Unknown command: %s", args.command)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
diff --git a/models/openmano/python/rift/openmano/rift2openmano.py b/models/openmano/python/rift/openmano/rift2openmano.py
new file mode 100755
index 0000000..a98335b
--- /dev/null
+++ b/models/openmano/python/rift/openmano/rift2openmano.py
@@ -0,0 +1,566 @@
+#!/usr/bin/env python3
+
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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.
+#
+
+import argparse
+import collections
+import logging
+import math
+import os
+import sys
+import tempfile
+import yaml
+
+from gi.repository import (
+ RwYang,
+ RwVnfdYang,
+ RwNsdYang,
+ )
+
+logger = logging.getLogger("rift2openmano.py")
+
+
+class VNFNotFoundError(Exception):
+ pass
+
+
+class RiftNSD(object):
+ model = RwYang.Model.create_libncx()
+ model.load_module('nsd')
+ model.load_module('rw-nsd')
+
+ def __init__(self, descriptor):
+ self._nsd = descriptor
+
+ def __str__(self):
+ return str(self._nsd)
+
+ @property
+ def name(self):
+ return self._nsd.name
+
+ @property
+ def id(self):
+ return self._nsd.id
+
+ @property
+ def vnfd_ids(self):
+ return [c.vnfd_id_ref for c in self._nsd.constituent_vnfd]
+
+ @property
+ def constituent_vnfds(self):
+ return self._nsd.constituent_vnfd
+
+ @property
+ def vlds(self):
+ return self._nsd.vld
+
+ @property
+ def cps(self):
+ return self._nsd.connection_point
+
+ @property
+ def description(self):
+ return self._nsd.description
+
+ @classmethod
+ def from_xml_file_hdl(cls, hdl):
+ hdl.seek(0)
+ descriptor = RwNsdYang.YangData_Nsd_NsdCatalog_Nsd()
+ descriptor.from_xml_v2(RiftNSD.model, hdl.read())
+ return cls(descriptor)
+
+ @classmethod
+ def from_yaml_file_hdl(cls, hdl):
+ hdl.seek(0)
+ descriptor = RwNsdYang.YangData_Nsd_NsdCatalog_Nsd()
+ descriptor.from_yaml(RiftNSD.model, hdl.read())
+ return cls(descriptor)
+
+ @classmethod
+ def from_dict(cls, nsd_dict):
+ descriptor = RwNsdYang.YangData_Nsd_NsdCatalog_Nsd.from_dict(nsd_dict)
+ return cls(descriptor)
+
+
+class RiftVNFD(object):
+ model = RwYang.Model.create_libncx()
+ model.load_module('vnfd')
+ model.load_module('rw-vnfd')
+
+ def __init__(self, descriptor):
+ self._vnfd = descriptor
+
+ def __str__(self):
+ return str(self._vnfd)
+
+ @property
+ def id(self):
+ return self._vnfd.id
+
+ @property
+ def name(self):
+ return self._vnfd.name
+
+ @property
+ def description(self):
+ return self._vnfd.description
+
+ @property
+ def cps(self):
+ return self._vnfd.connection_point
+
+ @property
+ def vdus(self):
+ return self._vnfd.vdu
+
+ @property
+ def internal_vlds(self):
+ return self._vnfd.internal_vld
+
+ @classmethod
+ def from_xml_file_hdl(cls, hdl):
+ hdl.seek(0)
+ descriptor = RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd()
+ descriptor.from_xml_v2(RiftVNFD.model, hdl.read())
+ return cls(descriptor)
+
+ @classmethod
+ def from_yaml_file_hdl(cls, hdl):
+ hdl.seek(0)
+ descriptor = RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd()
+ descriptor.from_yaml(RiftVNFD.model, hdl.read())
+ return cls(descriptor)
+
+ @classmethod
+ def from_dict(cls, vnfd_dict):
+ descriptor = RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd.from_dict(vnfd_dict)
+ return cls(descriptor)
+
+
+def is_writable_directory(dir_path):
+ """ Returns True if dir_path is writable, False otherwise
+
+ Arguments:
+ dir_path - A directory path
+ """
+ if not os.path.exists(dir_path):
+ raise ValueError("Directory does not exist: %s", dir_path)
+
+ try:
+ testfile = tempfile.TemporaryFile(dir=dir_path)
+ testfile.close()
+ except OSError:
+ return False
+
+ return True
+
+
+def create_vnfd_from_xml_files(vnfd_file_hdls):
+ """ Create a list of RiftVNFD instances from xml file handles
+
+ Arguments:
+ vnfd_file_hdls - Rift VNFD XML file handles
+
+ Returns:
+ A list of RiftVNFD instances
+ """
+ vnfd_dict = {}
+ for vnfd_file_hdl in vnfd_file_hdls:
+ vnfd = RiftVNFD.from_xml_file_hdl(vnfd_file_hdl)
+ vnfd_dict[vnfd.id] = vnfd
+
+ return vnfd_dict
+
+def create_vnfd_from_yaml_files(vnfd_file_hdls):
+ """ Create a list of RiftVNFD instances from xml file handles
+
+ Arguments:
+ vnfd_file_hdls - Rift VNFD YAML file handles
+
+ Returns:
+ A list of RiftVNFD instances
+ """
+ vnfd_dict = {}
+ for vnfd_file_hdl in vnfd_file_hdls:
+ vnfd = RiftVNFD.from_yaml_file_hdl(vnfd_file_hdl)
+ vnfd_dict[vnfd.id] = vnfd
+
+ return vnfd_dict
+
+
+def create_nsd_from_xml_file(nsd_file_hdl):
+ """ Create a list of RiftNSD instances from xml file handles
+
+ Arguments:
+ nsd_file_hdls - Rift NSD XML file handles
+
+ Returns:
+ A list of RiftNSD instances
+ """
+ nsd = RiftNSD.from_xml_file_hdl(nsd_file_hdl)
+ return nsd
+
+def create_nsd_from_yaml_file(nsd_file_hdl):
+ """ Create a list of RiftNSD instances from yaml file handles
+
+ Arguments:
+ nsd_file_hdls - Rift NSD XML file handles
+
+ Returns:
+ A list of RiftNSD instances
+ """
+ nsd = RiftNSD.from_yaml_file_hdl(nsd_file_hdl)
+ return nsd
+
+
+def ddict():
+ return collections.defaultdict(dict)
+
+def convert_vnfd_name(vnfd_name, member_idx):
+ return vnfd_name + "__" + str(member_idx)
+
+
+def rift2openmano_nsd(rift_nsd, rift_vnfds):
+ for vnfd_id in rift_nsd.vnfd_ids:
+ if vnfd_id not in rift_vnfds:
+ raise VNFNotFoundError("VNF id %s not provided" % vnfd_id)
+
+ openmano = {}
+ openmano["name"] = rift_nsd.name
+ openmano["description"] = rift_nsd.description
+ topology = {}
+ openmano["topology"] = topology
+
+ topology["nodes"] = {}
+ for vnfd in rift_nsd.constituent_vnfds:
+ vnfd_id = vnfd.vnfd_id_ref
+ rift_vnfd = rift_vnfds[vnfd_id]
+ member_idx = vnfd.member_vnf_index
+ topology["nodes"][rift_vnfd.name + "__" + str(member_idx)] = {
+ "type": "VNF",
+ "VNF model": rift_vnfd.name
+ }
+
+ for vld in rift_nsd.vlds:
+ # Openmano has both bridge_net and dataplane_net models for network types
+ # For now, since we are using openmano in developer mode lets just hardcode
+ # to bridge_net since it won't matter anyways.
+ # topology["nodes"][vld.name] = {"type": "network", "model": "bridge_net"}
+ pass
+
+ topology["connections"] = {}
+ for vld in rift_nsd.vlds:
+
+ # Create a connections entry for each external VLD
+ topology["connections"][vld.name] = {}
+ topology["connections"][vld.name]["nodes"] = []
+
+ if vld.vim_network_name:
+ if vld.name not in topology["nodes"]:
+ topology["nodes"][vld.name] = {
+ "type": "external_network",
+ "model": vld.name,
+ }
+
+ # Add the external network to the list of connection points
+ topology["connections"][vld.name]["nodes"].append(
+ {vld.name: "0"}
+ )
+ elif vld.provider_network.has_field("physical_network"):
+ # Add the external datacenter network to the topology
+ # node list if it isn't already added
+ ext_net_name = vld.provider_network.physical_network
+ ext_net_name_with_seg = ext_net_name
+ if vld.provider_network.has_field("segmentation_id"):
+ ext_net_name_with_seg += ":{}".format(vld.provider_network.segmentation_id)
+
+ if ext_net_name not in topology["nodes"]:
+ topology["nodes"][ext_net_name] = {
+ "type": "external_network",
+ "model": ext_net_name_with_seg,
+ }
+
+ # Add the external network to the list of connection points
+ topology["connections"][vld.name]["nodes"].append(
+ {ext_net_name: "0"}
+ )
+
+
+ for vnfd_cp in vld.vnfd_connection_point_ref:
+
+ # Get the RIFT VNF for this external VLD connection point
+ vnfd = rift_vnfds[vnfd_cp.vnfd_id_ref]
+
+ # For each VNF in this connection, use the same interface name
+ topology["connections"][vld.name]["type"] = "link"
+ # Vnf ref is the vnf name with the member_vnf_idx appended
+ member_idx = vnfd_cp.member_vnf_index_ref
+ vnf_ref = vnfd.name + "__" + str(member_idx)
+ topology["connections"][vld.name]["nodes"].append(
+ {
+ vnf_ref: vnfd_cp.vnfd_connection_point_ref
+ }
+ )
+
+ return openmano
+
+
+def rift2openmano_vnfd(rift_vnfd):
+ openmano_vnf = {"vnf":{}}
+ vnf = openmano_vnf["vnf"]
+
+ vnf["name"] = rift_vnfd.name
+ vnf["description"] = rift_vnfd.description
+
+ vnf["external-connections"] = []
+
+ def find_vdu_and_ext_if_by_cp_ref(cp_ref_name):
+ for vdu in rift_vnfd.vdus:
+ for ext_if in vdu.external_interface:
+ if ext_if.vnfd_connection_point_ref == cp_ref_name:
+ return vdu, ext_if
+
+ raise ValueError("External connection point reference %s not found" % cp_ref_name)
+
+ def find_vdu_and_int_if_by_cp_ref(cp_ref_id):
+ for vdu in rift_vnfd.vdus:
+ for int_if in vdu.internal_interface:
+ if int_if.vdu_internal_connection_point_ref == cp_ref_id:
+ return vdu, int_if
+
+ raise ValueError("Internal connection point reference %s not found" % cp_ref_id)
+
+ def rift2openmano_if_type(rift_type):
+ if rift_type == "OM_MGMT":
+ return "mgmt"
+ elif rift_type == "VIRTIO":
+ return "bridge"
+ else:
+ return "data"
+
+ # Add all external connections
+ for cp in rift_vnfd.cps:
+ # Find the VDU and and external interface for this connection point
+ vdu, ext_if = find_vdu_and_ext_if_by_cp_ref(cp.name)
+ connection = {
+ "name": cp.name,
+ "type": rift2openmano_if_type(ext_if.virtual_interface.type_yang),
+ "VNFC": vdu.name,
+ "local_iface_name": ext_if.name,
+ "description": "%s iface on VDU %s" % (ext_if.name, vdu.name),
+ }
+
+ vnf["external-connections"].append(connection)
+
+ # Add all internal networks
+ for vld in rift_vnfd.internal_vlds:
+ connection = {
+ "name": vld.name,
+ "description": vld.description,
+ "type": "data",
+ "elements": [],
+ }
+
+ # Add the specific VDU connection points
+ for int_cp_ref in vld.internal_connection_point_ref:
+ vdu, int_if = find_vdu_and_int_if_by_cp_ref(int_cp_ref)
+ connection["elements"].append({
+ "VNFC": vdu.name,
+ "local_iface_name": int_if.name,
+ })
+ if "internal-connections" not in vnf:
+ vnf["internal-connections"] = []
+
+ vnf["internal-connections"].append(connection)
+
+ # Add VDU's
+ vnf["VNFC"] = []
+ for vdu in rift_vnfd.vdus:
+ vnfc = {
+ "name": vdu.name,
+ "description": vdu.name,
+ "VNFC image": vdu.image if os.path.isabs(vdu.image) else "/var/images/{}".format(vdu.image),
+ "numas": [{
+ "memory": max(int(vdu.vm_flavor.memory_mb/1024), 1),
+ "interfaces":[],
+ }],
+ "bridge-ifaces": [],
+ }
+
+ numa_node_policy = vdu.guest_epa.numa_node_policy
+ if numa_node_policy.has_field("node"):
+ numa_node = numa_node_policy.node[0]
+
+ if numa_node.has_field("paired_threads"):
+ if numa_node.paired_threads.has_field("num_paired_threads"):
+ vnfc["numas"][0]["paired-threads"] = numa_node.paired_threads.num_paired_threads
+ if len(numa_node.paired_threads.paired_thread_ids) > 0:
+ vnfc["numas"][0]["paired-threads-id"] = []
+ for pair in numa_node.paired_threads.paired_thread_ids:
+ vnfc["numas"][0]["paired-threads-id"].append(
+ [pair.thread_a, pair.thread_b]
+ )
+
+ else:
+ if vdu.vm_flavor.has_field("vcpu_count"):
+ vnfc["numas"][0]["cores"] = max(vdu.vm_flavor.vcpu_count, 1)
+
+ if vdu.has_field("hypervisor_epa"):
+ vnfc["hypervisor"] = {}
+ if vdu.hypervisor_epa.has_field("type"):
+ if vdu.hypervisor_epa.type_yang == "REQUIRE_KVM":
+ vnfc["hypervisor"]["type"] = "QEMU-kvm"
+
+ if vdu.hypervisor_epa.has_field("version"):
+ vnfc["hypervisor"]["version"] = vdu.hypervisor_epa.version
+
+ if vdu.has_field("host_epa"):
+ vnfc["processor"] = {}
+ if vdu.host_epa.has_field("om_cpu_model_string"):
+ vnfc["processor"]["model"] = vdu.host_epa.om_cpu_model_string
+ if vdu.host_epa.has_field("om_cpu_feature"):
+ vnfc["processor"]["features"] = []
+ for feature in vdu.host_epa.om_cpu_feature:
+ vnfc["processor"]["features"].append(feature)
+
+
+ if vdu.vm_flavor.has_field("storage_gb"):
+ vnfc["disk"] = vdu.vm_flavor.storage_gb
+
+ vnf["VNFC"].append(vnfc)
+
+ for int_if in list(vdu.internal_interface) + list(vdu.external_interface):
+ intf = {
+ "name": int_if.name,
+ }
+ if int_if.virtual_interface.has_field("vpci"):
+ intf["vpci"] = int_if.virtual_interface.vpci
+
+ if int_if.virtual_interface.type_yang in ["VIRTIO", "OM_MGMT"]:
+ vnfc["bridge-ifaces"].append(intf)
+
+ elif int_if.virtual_interface.type_yang == "SR-IOV":
+ intf["bandwidth"] = "10 Gbps"
+ intf["dedicated"] = "yes:sriov"
+ vnfc["numas"][0]["interfaces"].append(intf)
+
+ elif int_if.virtual_interface.type_yang == "PCI_PASSTHROUGH":
+ intf["bandwidth"] = "10 Gbps"
+ intf["dedicated"] = "yes"
+ if "interfaces" not in vnfc["numas"][0]:
+ vnfc["numas"][0]["interfaces"] = []
+ vnfc["numas"][0]["interfaces"].append(intf)
+ else:
+ raise ValueError("Interface type %s not supported" % int_if.virtual_interface)
+
+ if int_if.virtual_interface.has_field("bandwidth"):
+ if int_if.virtual_interface.bandwidth != 0:
+ bps = int_if.virtual_interface.bandwidth
+
+ # Calculate the bits per second conversion
+ for x in [('M', 1000000), ('G', 1000000000)]:
+ if bps/x[1] >= 1:
+ intf["bandwidth"] = "{} {}bps".format(math.ceil(bps/x[1]), x[0])
+
+
+ return openmano_vnf
+
+
+def parse_args(argv=sys.argv[1:]):
+ """ Parse the command line arguments
+
+ Arguments:
+ arv - The list of arguments to parse
+
+ Returns:
+ Argparse Namespace instance
+ """
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '-o', '--outdir',
+ default='-',
+ help="Directory to output converted descriptors. Default is stdout",
+ )
+
+ parser.add_argument(
+ '-n', '--nsd-file-hdl',
+ metavar="nsd_xml_file",
+ type=argparse.FileType('r'),
+ help="Rift NSD Descriptor File",
+ )
+
+ parser.add_argument(
+ '-v', '--vnfd-file-hdls',
+ metavar="vnfd_xml_file",
+ action='append',
+ type=argparse.FileType('r'),
+ help="Rift VNFD Descriptor File",
+ )
+
+ args = parser.parse_args(argv)
+
+ if not os.path.exists(args.outdir):
+ os.makedirs(args.outdir)
+
+ if not is_writable_directory(args.outdir):
+ logging.error("Directory %s is not writable", args.outdir)
+ sys.exit(1)
+
+ return args
+
+
+def write_yaml_to_file(name, outdir, desc_dict):
+ file_name = "%s.yaml" % name
+ yaml_str = yaml.dump(desc_dict)
+ if outdir == "-":
+ sys.stdout.write(yaml_str)
+ return
+
+ file_path = os.path.join(outdir, file_name)
+ dir_path = os.path.dirname(file_path)
+ if not os.path.exists(dir_path):
+ os.makedirs(dir_path)
+
+ with open(file_path, "w") as hdl:
+ hdl.write(yaml_str)
+
+ logger.info("Wrote descriptor to %s", file_path)
+
+
+def main(argv=sys.argv[1:]):
+ args = parse_args(argv)
+
+ nsd = None
+ if args.vnfd_file_hdls is not None:
+ vnf_dict = create_vnfd_from_xml_files(args.vnfd_file_hdls)
+
+ if args.nsd_file_hdl is not None:
+ nsd = create_nsd_from_xml_file(args.nsd_file_hdl)
+
+ openmano_nsd = rift2openmano_nsd(nsd, vnf_dict)
+
+ write_yaml_to_file(openmano_nsd["name"], args.outdir, openmano_nsd)
+
+ for vnf in vnf_dict.values():
+ openmano_vnf = rift2openmano_vnfd(vnf)
+ write_yaml_to_file(openmano_vnf["vnf"]["name"], args.outdir, openmano_vnf)
+
+
+if __name__ == "__main__":
+ logging.basicConfig(level=logging.WARNING)
+ main()
diff --git a/models/openmano/src/CMakeLists.txt b/models/openmano/src/CMakeLists.txt
new file mode 100644
index 0000000..949bb8b
--- /dev/null
+++ b/models/openmano/src/CMakeLists.txt
@@ -0,0 +1,82 @@
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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.
+#
+# Author(s): Anil Gunturu
+# Creation Date: 2014/12/11
+#
+
+cmake_minimum_required(VERSION 2.8)
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/generate_tidgen_packages.sh.in
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_tidgen_packages.sh
+ ESCAPE_QUOTES @ONLY
+ )
+
+add_custom_command(
+ OUTPUT
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_2sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_2sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_4sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_4sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_2sriov_no_ctrlnet.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_2sriov_no_ctrlnet.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_4sriov_no_ctrlnet.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_4sriov_no_ctrlnet.tar.gz
+
+ COMMAND
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_tidgen_packages.sh
+
+ DEPENDS
+ ${RIFT_SUBMODULE_SOURCE_ROOT}/models/openmano/test/tidgen_ns_2sriov.yaml
+ ${RIFT_SUBMODULE_SOURCE_ROOT}/models/openmano/test/tidgen_ns_4sriov.yaml
+ ${RIFT_SUBMODULE_SOURCE_ROOT}/models/openmano/test/tidgen_vnf_2sriov.yaml
+ ${RIFT_SUBMODULE_SOURCE_ROOT}/models/openmano/test/tidgen_vnf_4sriov.yaml
+ ${RIFT_SUBMODULE_SOURCE_ROOT}/models/openmano/test/tidgen_ns_2sriov_no_ctrlnet.yaml
+ ${RIFT_SUBMODULE_SOURCE_ROOT}/models/openmano/test/tidgen_ns_4sriov_no_ctrlnet.yaml
+ ${RIFT_SUBMODULE_SOURCE_ROOT}/models/openmano/test/tidgen_vnf_2sriov_no_ctrlnet.yaml
+ ${RIFT_SUBMODULE_SOURCE_ROOT}/models/openmano/test/tidgen_vnf_4sriov_no_ctrlnet.yaml
+ ${RIFT_SUBMODULE_SOURCE_ROOT}/models/openmano/src/openmano2rift.py
+ )
+
+add_custom_target(tidgen ALL
+ DEPENDS
+ mano_yang
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_2sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_2sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_4sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_4sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_2sriov_no_ctrlnet.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_2sriov_no_ctrlnet.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_4sriov_no_ctrlnet.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_4sriov_no_ctrlnet.tar.gz
+ )
+
+install(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_4sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_4sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_2sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_2sriov.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_4sriov_no_ctrlnet.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_4sriov_no_ctrlnet.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/2tidgenMWC_2sriov_no_ctrlnet.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/tidgenMWC_2sriov_no_ctrlnet.tar.gz
+
+
+ DESTINATION
+ usr/rift/mano/examples/tidgen_ns
+ COMPONENT ${PKG_LONG_NAME}
+ )
diff --git a/models/openmano/src/generate_tidgen_packages.sh.in b/models/openmano/src/generate_tidgen_packages.sh.in
new file mode 100755
index 0000000..208d2cd
--- /dev/null
+++ b/models/openmano/src/generate_tidgen_packages.sh.in
@@ -0,0 +1,40 @@
+#! /bin/bash
+
+set -e
+
+SOURCE_DIR=@CMAKE_CURRENT_SOURCE_DIR@
+BINARY_DIR=@CMAKE_CURRENT_BINARY_DIR@
+PROJECT_TOP_DIR=@PROJECT_TOP_DIR@
+
+# These paths are needed for finding the overrides and so files
+PYTHONPATH=${PYTHONPATH}:@RIFT_SUBMODULE_SOURCE_ROOT@/rwvcs/ra:@RIFT_SUBMODULE_BINARY_ROOT@/models/plugins/yang
+PYTHON3PATH=${PYTHON3PATH}:@RIFT_SUBMODULE_SOURCE_ROOT@/rwvcs/ra:@RIFT_SUBMODULE_BINARY_ROOT@/models/plugins/yang
+LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:@RIFT_SUBMODULE_BINARY_ROOT@/models/plugins/yang
+
+# Remove any old directories
+rm -rf ${BINARY_DIR}/2tidgenMWC_4sriov
+rm -rf ${BINARY_DIR}/tidgenMWC_4sriov
+rm -rf ${BINARY_DIR}/2tidgenMWC_2sriov
+rm -rf ${BINARY_DIR}/tidgenMWC_2sriov
+rm -rf ${BINARY_DIR}/2tidgenMWC_2sriov_noctrlnet
+rm -rf ${BINARY_DIR}/tidgenMWC_2sriov_noctrlnet
+rm -rf ${BINARY_DIR}/2tidgenMWC_4sriov_noctrlnet
+rm -rf ${BINARY_DIR}/tidgenMWC_4sriov_noctrlnet
+
+
+# Generate the descriptors
+${SOURCE_DIR}/openmano2rift.py -o ${BINARY_DIR} @RIFT_SUBMODULE_SOURCE_ROOT@/models/openmano/test/tidgen_ns_4sriov.yaml @RIFT_SUBMODULE_SOURCE_ROOT@/models/openmano/test/tidgen_vnf_4sriov.yaml
+${SOURCE_DIR}/openmano2rift.py -o ${BINARY_DIR} @RIFT_SUBMODULE_SOURCE_ROOT@/models/openmano/test/tidgen_ns_2sriov.yaml @RIFT_SUBMODULE_SOURCE_ROOT@/models/openmano/test/tidgen_vnf_2sriov.yaml
+${SOURCE_DIR}/openmano2rift.py -o ${BINARY_DIR} @RIFT_SUBMODULE_SOURCE_ROOT@/models/openmano/test/tidgen_ns_4sriov_no_ctrlnet.yaml @RIFT_SUBMODULE_SOURCE_ROOT@/models/openmano/test/tidgen_vnf_4sriov_no_ctrlnet.yaml
+${SOURCE_DIR}/openmano2rift.py -o ${BINARY_DIR} @RIFT_SUBMODULE_SOURCE_ROOT@/models/openmano/test/tidgen_ns_2sriov_no_ctrlnet.yaml @RIFT_SUBMODULE_SOURCE_ROOT@/models/openmano/test/tidgen_vnf_2sriov_no_ctrlnet.yaml
+
+
+# Generate the tar files
+${RIFT_INSTALL}/usr/rift/toolchain/cmake/bin/generate_descriptor_pkg.sh ${BINARY_DIR} tidgenMWC_4sriov
+${RIFT_INSTALL}/usr/rift/toolchain/cmake/bin/generate_descriptor_pkg.sh ${BINARY_DIR} 2tidgenMWC_4sriov
+${RIFT_INSTALL}/usr/rift/toolchain/cmake/bin/generate_descriptor_pkg.sh ${BINARY_DIR} tidgenMWC_2sriov
+${RIFT_INSTALL}/usr/rift/toolchain/cmake/bin/generate_descriptor_pkg.sh ${BINARY_DIR} 2tidgenMWC_2sriov
+${RIFT_INSTALL}/usr/rift/toolchain/cmake/bin/generate_descriptor_pkg.sh ${BINARY_DIR} tidgenMWC_2sriov_no_ctrlnet
+${RIFT_INSTALL}/usr/rift/toolchain/cmake/bin/generate_descriptor_pkg.sh ${BINARY_DIR} 2tidgenMWC_2sriov_no_ctrlnet
+${RIFT_INSTALL}/usr/rift/toolchain/cmake/bin/generate_descriptor_pkg.sh ${BINARY_DIR} tidgenMWC_4sriov_no_ctrlnet
+${RIFT_INSTALL}/usr/rift/toolchain/cmake/bin/generate_descriptor_pkg.sh ${BINARY_DIR} 2tidgenMWC_4sriov_no_ctrlnet
diff --git a/models/openmano/src/openmano2rift.py b/models/openmano/src/openmano2rift.py
new file mode 100755
index 0000000..503ad89
--- /dev/null
+++ b/models/openmano/src/openmano2rift.py
@@ -0,0 +1,485 @@
+#!/usr/bin/env python3
+
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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.
+#
+
+
+import argparse
+import itertools
+import logging
+import os
+import sys
+import tempfile
+import uuid
+import yaml
+
+import gi
+gi.require_version('RwYang', '1.0')
+gi.require_version('RwVnfdYang', '1.0')
+gi.require_version('RwNsdYang', '1.0')
+from gi.repository import (
+ RwYang,
+ RwVnfdYang,
+ RwNsdYang,
+ )
+
+logging.basicConfig(level=logging.WARNING)
+logger = logging.getLogger("openmano2rift.py")
+
+
+class UnknownVNFError(Exception):
+ pass
+
+
+class DescriptorFileWriter(object):
+ def __init__(self, module_list, output_dir, output_format):
+ self._model = RwYang.Model.create_libncx()
+ for module in module_list:
+ self._model.load_module(module)
+
+ self._output_dir = output_dir
+ self._output_format = output_format
+
+ def _write_file(self, file_name, output):
+ file_path = os.path.join(self._output_dir, file_name)
+ dir_path = os.path.dirname(file_path)
+ if not os.path.exists(dir_path):
+ os.makedirs(dir_path)
+
+ with open(file_path, "w") as hdl:
+ hdl.write(output)
+
+ logger.info("Wrote descriptor to %s", file_path)
+
+ def _write_json(self, descriptor, subdir):
+ self._write_file(
+ '%s.json' % os.path.join(descriptor.name, subdir, descriptor.name),
+ descriptor.descriptor.to_json(self._model)
+ )
+
+ def _write_xml(self, descriptor, subdir):
+ self._write_file(
+ '%s.xml' % os.path.join(descriptor.name, subdir, descriptor.name),
+ descriptor.descriptor.to_xml_v2(self._model, pretty_print=True)
+ )
+
+ def _write_yaml(self, descriptor, subdir):
+ self._write_file(
+ '%s.yaml' % os.path.join(descriptor.name, subdir, descriptor.name),
+ yaml.dump(descriptor.descriptor.as_dict()),
+ )
+
+ def write_descriptor(self, descriptor, subdir=""):
+ if self._output_format == 'json':
+ self._write_json(descriptor, subdir=subdir)
+
+ elif self._output_format == 'xml':
+ self._write_xml(descriptor, subdir=subdir)
+
+ elif self._output_format == 'yaml':
+ self._write_yaml(descriptor, subdir=subdir)
+
+
+class RiftManoDescriptor(object):
+ def __init__(self, openmano=None):
+ self.openmano = openmano
+ self.descriptor = None
+
+
+class RiftNS(RiftManoDescriptor):
+ def __init__(self, openmano=None):
+ super().__init__(openmano)
+ self.nsd_catalog = None
+ self.nsd = None
+ self.name = None
+
+ def get_vnfd_id(self, vnf_list, vnf_name):
+ for vnf in vnf_list:
+ if vnf.name == vnf_name:
+ return vnf.vnfd.id
+
+ # Didn't find the vnf just return the vnf_name
+ return vnf_name
+
+ def openmano2rift(self, vnf_list):
+ self.descriptor = RwNsdYang.YangData_Nsd_NsdCatalog()
+ openmano_nsd = self.openmano.dictionary
+ self.name = openmano_nsd['name']
+ nsd = self.descriptor.nsd.add()
+ nsd.id = str(uuid.uuid1())
+ nsd.name = self.name
+ nsd.short_name = self.name
+ nsd.description = openmano_nsd['description']
+
+ nodes = openmano_nsd['topology']['nodes']
+ connections = openmano_nsd['topology']['connections']
+
+ def create_consituent_vnfds():
+ vnf_member_index_dict = {}
+
+ vnfd_idx_gen = itertools.count(1)
+ for key in nodes:
+ node = nodes[key]
+ if node['type'] != 'VNF':
+ continue
+
+ vnfd_idx = next(vnfd_idx_gen)
+ constituent_vnfd = nsd.constituent_vnfd.add()
+ constituent_vnfd.member_vnf_index = vnfd_idx
+ constituent_vnfd.vnfd_id_ref = self.get_vnfd_id(vnf_list, node['VNF model'])
+ vnf_member_index_dict[key] = vnfd_idx
+
+ return vnf_member_index_dict
+
+ def create_connections(vnf_member_index_dict):
+ keys = connections.keys()
+ for key in keys:
+ # TODO: Need clarification from TEF
+ # skip the mgmtnet in OpenMANO descriptor
+ if key == 'mgmtnet':
+ continue
+ conn = connections[key]
+ vld = nsd.vld.add()
+ vld.from_dict(dict(
+ id=str(uuid.uuid1()),
+ name=key,
+ short_name=key,
+ type_yang='ELAN',
+ ))
+
+ nodes = conn['nodes']
+ for node, node_keys in [(node, node.keys()) for node in nodes]:
+ for node_key in node_keys:
+ topo_node = openmano_nsd['topology']['nodes'][node_key]
+ if topo_node['type'] == 'VNF':
+ cpref = vld.vnfd_connection_point_ref.add()
+ cpref.from_dict(dict(
+ member_vnf_index_ref=vnf_member_index_dict[node_key],
+ vnfd_id_ref=self.get_vnfd_id(vnf_list, topo_node['VNF model']),
+ #vnfd_id_ref=topo_node['VNF model'],
+ vnfd_connection_point_ref=node[node_key],
+ ))
+ if key != 'control-net':
+ vld.provider_network.physical_network = 'physnet_sriov'
+ vld.provider_network.overlay_type = 'VLAN'
+
+ vnf_member_index_dict = create_consituent_vnfds()
+ create_connections(vnf_member_index_dict)
+
+
+class RiftVnfd(RiftManoDescriptor):
+ def __init__(self, openmano=None):
+ super().__init__(openmano)
+ self.vnfd_catalog = None
+ self.vnfd = None
+
+ def find_external_connection(self, vdu_name, if_name):
+ """
+ Find if the vdu interface has an external connection.
+ """
+ openmano_vnfd = self.openmano.dictionary['vnf']
+ if 'external-connections' not in openmano_vnfd:
+ return None
+
+ ext_conn_list = openmano_vnfd['external-connections']
+ for ext_conn in ext_conn_list:
+ if ((ext_conn['VNFC'] == vdu_name) and
+ (ext_conn['local_iface_name'] == if_name)):
+ return ext_conn
+
+ return None
+
+ def openmano2rift(self):
+ self.descriptor = RwVnfdYang.YangData_Vnfd_VnfdCatalog()
+ vnfd = self.descriptor.vnfd.add()
+ self.vnfd = vnfd
+ vnfd.id = str(uuid.uuid1())
+
+ openmano_vnfd = self.openmano.dictionary['vnf']
+ self.name = openmano_vnfd['name']
+ vnfd.name = self.name
+ if "description" in openmano_vnfd:
+ vnfd.description = openmano_vnfd['description']
+
+ # Parse and add all the external connection points
+ if 'external-connections' in openmano_vnfd:
+ ext_conn_list = openmano_vnfd['external-connections']
+
+ for ext_conn in ext_conn_list:
+ # TODO: Fix this
+ if ext_conn['name'] == 'eth0':
+ continue
+ conn_point = vnfd.connection_point.add()
+ conn_point.name = ext_conn['name']
+ conn_point.type_yang = 'VPORT'
+
+ # TODO: Need a concrete example of how openmano descriptor
+ # uses internal connections.
+ if 'internal-connections' in openmano_vnfd:
+ int_conn_list = openmano_vnfd['internal-connections']
+
+ def add_external_interfaces(vdu, numa):
+ if 'interfaces' not in numa:
+ return
+
+ numa_if_list = numa['interfaces']
+ for numa_if in numa_if_list:
+ ext_conn = self.find_external_connection(vdu.name, numa_if['name'])
+ if not ext_conn:
+ continue
+
+ ext_iface = vdu.external_interface.add()
+ ext_iface.name = numa_if['name']
+ ext_iface.vnfd_connection_point_ref = ext_conn['name']
+ ext_iface.virtual_interface.vpci = numa_if['vpci']
+ if numa_if['dedicated'] == 'no':
+ ext_iface.virtual_interface.type_yang = 'SR_IOV'
+ else:
+ ext_iface.virtual_interface.type_yang = 'PCI_PASSTHROUGH'
+
+ vnfc_list = openmano_vnfd['VNFC']
+ for vnfc in vnfc_list:
+ vdu = vnfd.vdu.add()
+ vdu_dict = dict(
+ id=str(uuid.uuid1()),
+ name=vnfc['name'],
+ image=vnfc['VNFC image'],
+ vm_flavor={"storage_gb": vnfc["disk"] if "disk" in vnfc else 20},
+ )
+ if "description" in vnfc:
+ vdu_dict["description"] = vnfc['description']
+
+ vdu.from_dict(vdu_dict)
+
+ vnfd.mgmt_interface.vdu_id = vdu.id
+
+ numa_list = vnfc['numas']
+ memory = 0
+ vcpu_count = 0
+ numa_node_cnt = 0
+
+ for numa in numa_list:
+ node = vdu.guest_epa.numa_node_policy.node.add()
+ node.id = numa_node_cnt
+ # node.memory_mb = int(numa['memory']) * 1024
+ numa_node_cnt += 1
+
+ memory = memory + node.memory_mb
+ # Need a better explanation of "cores", "paired-threads", "threads"
+ # in openmano descriptor. Particularly how they map to cpu and
+ # thread pinning policies
+ if 'paired-threads' in numa:
+ vcpu_count = vcpu_count + int(numa['paired-threads']) * 2
+
+ if 'cores' in numa:
+ vcpu_count = vcpu_count + int(numa['cores'])
+
+ add_external_interfaces(vdu, numa)
+
+
+ # vdu.vm_flavor.memory_mb = memory
+ vdu.vm_flavor.memory_mb = 12 * 1024
+ vdu.vm_flavor.vcpu_count = vcpu_count
+ vdu.guest_epa.numa_node_policy.node_cnt = numa_node_cnt
+ vdu.guest_epa.numa_node_policy.mem_policy = 'STRICT'
+ vdu.guest_epa.mempage_size = 'LARGE'
+ vdu.guest_epa.cpu_pinning_policy = 'DEDICATED'
+ vdu.guest_epa.cpu_thread_pinning_policy = 'PREFER'
+
+ # TODO: Enable hypervisor epa
+ # vdu.hypervisor_epa.version = vnfc['hypervisor']['version']
+ # if vnfc['hypervisor']['type'] == 'QEMU-kvm':
+ # vdu.hypervisor_epa.type_yang = 'REQUIRE_KVM'
+ # else:
+ # vdu.hypervisor_epa.type_yang = 'PREFER_KVM'
+
+ # TODO: Enable host epa
+ # vdu.host_epa.cpu_feature = vnfc['processor']['features']
+
+ # Parse the bridge interfaces
+ if 'bridge-ifaces' in vnfc:
+ bridge_ifaces = vnfc['bridge-ifaces']
+
+
+ for bridge_iface in bridge_ifaces:
+ # TODO: Fix this
+ if bridge_iface['name'] == 'eth0':
+ continue
+
+ ext_conn = self.find_external_connection(vdu.name,
+ bridge_iface['name'])
+ if ext_conn:
+ ext_iface = vdu.external_interface.add()
+ ext_iface.name = bridge_iface['name']
+ ext_iface.vnfd_connection_point_ref = ext_conn['name']
+ if 'vpci' in bridge_iface:
+ ext_iface.virtual_interface.vpci = bridge_iface['vpci']
+ ext_iface.virtual_interface.type_yang = 'VIRTIO'
+
+ # set vpci information for the 'default' network
+ # TODO: This needs to be inferred gtom bridge ifaces,
+ # need input from TEF
+ vdu.mgmt_vpci = "0000:00:0a.0"
+
+
+class OpenManoDescriptor(object):
+ def __init__(self, yaml_file_hdl):
+ self.dictionary = yaml.load(yaml_file_hdl)
+
+ @property
+ def type(self):
+ """ The descriptor type (ns or vnf)"""
+ if 'vnf' in self.dictionary:
+ return "vnf"
+ else:
+ return "ns"
+
+ def dump(self):
+ """ Dump the Descriptor out to stdout """
+ print(yaml.dump(self.dictionary))
+
+
+def is_writable_directory(dir_path):
+ """ Returns True if dir_path is writable, False otherwise
+
+ Arguments:
+ dir_path - A directory path
+ """
+ if not os.path.exists(dir_path):
+ raise ValueError("Directory does not exist: %s", dir_path)
+
+ try:
+ testfile = tempfile.TemporaryFile(dir=dir_path)
+ testfile.close()
+ except OSError:
+ return False
+
+ return True
+
+
+def create_vnfs_from_yaml_files(yaml_file_hdls):
+ """ Create a list of RiftVnfd instances from yaml file handles
+
+ Arguments:
+ yaml_file_hdls - OpenMano Yaml file handles
+
+ Returns:
+ A list of RiftVnfd instances
+ """
+ vnf_list = []
+ for yaml_file_hdl in yaml_file_hdls:
+ openmano = OpenManoDescriptor(yaml_file_hdl)
+ yaml_file_hdl.seek(0)
+
+ if openmano.type != "vnf":
+ continue
+
+ vnf = RiftVnfd(openmano)
+ vnf.openmano2rift()
+ vnf_list.append(vnf)
+
+ return vnf_list
+
+
+def create_ns_from_yaml_files(yaml_file_hdls, vnf_list):
+ """ Create a list of RiftNS instances from yaml file handles
+
+ Arguments:
+ yaml_file_hdls - OpenMano Yaml file handles
+ vnf_list - list of RiftVnfd
+
+ Returns:
+ A list of RiftNS instances
+ """
+ ns_list = []
+ for yaml_file_hdl in yaml_file_hdls:
+ openmano = OpenManoDescriptor(yaml_file_hdl)
+ if openmano.type != "ns":
+ continue
+
+ net_svc = RiftNS(openmano)
+ net_svc.openmano2rift(vnf_list)
+ ns_list.append(net_svc)
+
+ return ns_list
+
+
+def parse_args(argv=sys.argv[1:]):
+ """ Parse the command line arguments
+
+ Arguments:
+ arv - The list of arguments to parse
+
+ Returns:
+ Argparse Namespace instance
+
+ """
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '-o', '--outdir',
+ default='.',
+ help="Directory to output converted descriptors",
+ )
+
+ parser.add_argument(
+ '-f', '--format',
+ choices=['yaml', 'xml', 'json'],
+ default='xml',
+ help="Descriptor output format",
+ )
+
+ parser.add_argument(
+ 'yaml_file_hdls',
+ metavar="yaml_file",
+ nargs="+",
+ type=argparse.FileType('r'),
+ help="OpenMano YAML Descriptor File",
+ )
+
+ args = parser.parse_args(argv)
+
+ if not os.path.exists(args.outdir):
+ os.makedirs(args.outdir)
+
+ if not is_writable_directory(args.outdir):
+ logging.error("Directory %s is not writable", args.outdir)
+ sys.exit(1)
+
+ return args
+
+
+def main(argv=sys.argv[1:]):
+ args = parse_args(argv)
+
+ vnf_list = create_vnfs_from_yaml_files(args.yaml_file_hdls)
+ ns_list = create_ns_from_yaml_files(args.yaml_file_hdls, vnf_list)
+
+ writer = DescriptorFileWriter(
+ module_list=['nsd', 'rw-nsd', 'vnfd', 'rw-vnfd'],
+ output_dir=args.outdir,
+ output_format=args.format,
+ )
+
+ for nw_svc in ns_list:
+ writer.write_descriptor(nw_svc, subdir="nsd")
+
+ for vnf in vnf_list:
+ writer.write_descriptor(vnf, subdir="vnfd")
+
+
+if __name__ == "__main__":
+ main()
+
diff --git a/models/openmano/test/tidgen_ns_2sriov.yaml b/models/openmano/test/tidgen_ns_2sriov.yaml
new file mode 100644
index 0000000..9c39816
--- /dev/null
+++ b/models/openmano/test/tidgen_ns_2sriov.yaml
@@ -0,0 +1,34 @@
+---
+name: 2tidgenMWC_2sriov
+description: scenario with 2 tidgenMWC VNFs
+topology:
+ nodes:
+ tidgen1: #VNF name
+ type: VNF
+ VNF model: tidgenMWC_2sriov #VNF type
+ tidgen2:
+ type: VNF
+ VNF model: tidgenMWC_2sriov
+ default: #Name of external network
+ type: external_network
+ model: default
+ connections:
+ mgmtnet:
+ nodes:
+ - tidgen1: eth0
+ - tidgen2: eth0
+ datanet0:
+ nodes:
+ - tidgen1: xe0
+ - tidgen2: xe0
+ datanet1:
+ nodes:
+ - tidgen1: xe1
+ - tidgen2: xe1
+ control-net:
+ nodes:
+ - default: null
+ - tidgen1: eth1
+ - tidgen2: eth1
+
+
diff --git a/models/openmano/test/tidgen_ns_2sriov_no_ctrlnet.yaml b/models/openmano/test/tidgen_ns_2sriov_no_ctrlnet.yaml
new file mode 100644
index 0000000..d174895
--- /dev/null
+++ b/models/openmano/test/tidgen_ns_2sriov_no_ctrlnet.yaml
@@ -0,0 +1,29 @@
+---
+name: 2tidgenMWC_2sriov_no_ctrlnet
+description: scenario with 2 tidgenMWC VNFs
+topology:
+ nodes:
+ tidgen1: #VNF name
+ type: VNF
+ VNF model: tidgenMWC_2sriov_no_ctrlnet #VNF type
+ tidgen2:
+ type: VNF
+ VNF model: tidgenMWC_2sriov_no_ctrlnet
+ default: #Name of external network
+ type: external_network
+ model: default
+ connections:
+ mgmtnet:
+ nodes:
+ - tidgen1: eth0
+ - tidgen2: eth0
+ datanet0:
+ nodes:
+ - tidgen1: xe0
+ - tidgen2: xe0
+ datanet1:
+ nodes:
+ - tidgen1: xe1
+ - tidgen2: xe1
+
+
diff --git a/models/openmano/test/tidgen_ns_4sriov.yaml b/models/openmano/test/tidgen_ns_4sriov.yaml
new file mode 100644
index 0000000..4034f8a
--- /dev/null
+++ b/models/openmano/test/tidgen_ns_4sriov.yaml
@@ -0,0 +1,42 @@
+---
+name: 2tidgenMWC_4sriov
+description: scenario with 2 tidgenMWC VNFs
+topology:
+ nodes:
+ tidgen1: #VNF name
+ type: VNF
+ VNF model: tidgenMWC_4sriov #VNF type
+ tidgen2:
+ type: VNF
+ VNF model: tidgenMWC_4sriov
+ default: #Name of external network
+ type: external_network
+ model: default
+ connections:
+ mgmtnet:
+ nodes:
+ - tidgen1: eth0
+ - tidgen2: eth0
+ datanet0:
+ nodes:
+ - tidgen1: xe0
+ - tidgen2: xe0
+ datanet1:
+ nodes:
+ - tidgen1: xe1
+ - tidgen2: xe1
+ datanet2:
+ nodes:
+ - tidgen1: xe2
+ - tidgen2: xe2
+ datanet3:
+ nodes:
+ - tidgen1: xe3
+ - tidgen2: xe3
+ control-net:
+ nodes:
+ - default: null
+ - tidgen1: eth1
+ - tidgen2: eth1
+
+
diff --git a/models/openmano/test/tidgen_ns_4sriov_no_ctrlnet.yaml b/models/openmano/test/tidgen_ns_4sriov_no_ctrlnet.yaml
new file mode 100644
index 0000000..ee07a26
--- /dev/null
+++ b/models/openmano/test/tidgen_ns_4sriov_no_ctrlnet.yaml
@@ -0,0 +1,33 @@
+---
+name: 2tidgenMWC_4sriov_no_ctrlnet
+description: scenario with 2 tidgenMWC VNFs
+topology:
+ nodes:
+ tidgen1: #VNF name
+ type: VNF
+ VNF model: tidgenMWC_4sriov_no_ctrlnet #VNF type
+ tidgen2:
+ type: VNF
+ VNF model: tidgenMWC_4sriov_no_ctrlnet
+ default: #Name of external network
+ type: external_network
+ model: default
+ connections:
+ datanet0:
+ nodes:
+ - tidgen1: xe0
+ - tidgen2: xe0
+ datanet1:
+ nodes:
+ - tidgen1: xe1
+ - tidgen2: xe1
+ datanet2:
+ nodes:
+ - tidgen1: xe2
+ - tidgen2: xe2
+ datanet3:
+ nodes:
+ - tidgen1: xe3
+ - tidgen2: xe3
+
+
diff --git a/models/openmano/test/tidgen_vnf_2sriov.yaml b/models/openmano/test/tidgen_vnf_2sriov.yaml
new file mode 100644
index 0000000..983490b
--- /dev/null
+++ b/models/openmano/test/tidgen_vnf_2sriov.yaml
@@ -0,0 +1,58 @@
+---
+vnf:
+ name: tidgenMWC_2sriov
+ description: tidgen for MWC2016; 12G 10 cores
+ class: TID
+ external-connections:
+ - name: eth0
+ type: bridge
+ VNFC: tidgenMWC-VM
+ local_iface_name: eth0
+ description: Bridge interface, request for dhcp
+ - name: eth1
+ type: mgmt # "mgmt"(autoconnect to management net), "bridge", "data"
+ VNFC: tidgenMWC-VM # Virtual Machine this interface belongs to
+ local_iface_name: eth1 # name inside this Virtual Machine
+ description: Other management interface for general use
+ - name: xe0
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe0
+ description: Data interface 1
+ - name: xe1
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe1
+ description: Data interface 2
+ VNFC: # Virtual machine array
+ - name: tidgenMWC-VM # name of Virtual Machine
+ disk: 10
+ description: tidgen for MWC 12G 10 cores
+ # VNFC image: /mnt/powervault/virtualization/vnfs/tid/tidgenMWC.qcow2
+ VNFC image: tidgenMWC
+ image metadata: {"use_incremental": "no" } #is already incremental
+ processor: #Optional, leave it
+ model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz
+ features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"]
+ hypervisor: #Optional, leave it
+ type: QEMU-kvm
+ version: "10002|12001|2.6.32-358.el6.x86_64"
+ numas:
+ - paired-threads: 5 # "cores", "paired-threads", "threads"
+ memory: 12 # GBytes
+ interfaces:
+ - name: xe0
+ vpci: "0000:00:10.0"
+ dedicated: "no" # "yes"(passthrough), "no"(sriov)
+ bandwidth: 10 Gbps
+ - name: xe1
+ vpci: "0000:00:11.0"
+ dedicated: "no"
+ bandwidth: 10 Gbps
+ bridge-ifaces:
+ - name: eth0
+ vpci: "0000:00:0a.0" # Optional
+ bandwidth: 1 Mbps # Optional, informative only
+ - name: eth1
+ vpci: "0000:00:0b.0"
+ bandwidth: 1 Mbps
diff --git a/models/openmano/test/tidgen_vnf_2sriov_no_ctrlnet.yaml b/models/openmano/test/tidgen_vnf_2sriov_no_ctrlnet.yaml
new file mode 100644
index 0000000..6c7df27
--- /dev/null
+++ b/models/openmano/test/tidgen_vnf_2sriov_no_ctrlnet.yaml
@@ -0,0 +1,50 @@
+---
+vnf:
+ name: tidgenMWC_2sriov_no_ctrlnet
+ description: tidgen for MWC2016; 12G 10 cores
+ class: TID
+ external-connections:
+ - name: eth0
+ type: bridge
+ VNFC: tidgenMWC-VM
+ local_iface_name: eth0
+ description: Bridge interface, request for dhcp
+ - name: xe0
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe0
+ description: Data interface 1
+ - name: xe1
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe1
+ description: Data interface 2
+ VNFC: # Virtual machine array
+ - name: tidgenMWC-VM # name of Virtual Machine
+ disk: 10
+ description: tidgen for MWC 12G 10 cores
+ # VNFC image: /mnt/powervault/virtualization/vnfs/tid/tidgenMWC.qcow2
+ VNFC image: tidgenMWC
+ image metadata: {"use_incremental": "no" } #is already incremental
+ processor: #Optional, leave it
+ model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz
+ features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"]
+ hypervisor: #Optional, leave it
+ type: QEMU-kvm
+ version: "10002|12001|2.6.32-358.el6.x86_64"
+ numas:
+ - paired-threads: 5 # "cores", "paired-threads", "threads"
+ memory: 12 # GBytes
+ interfaces:
+ - name: xe0
+ vpci: "0000:00:10.0"
+ dedicated: "no" # "yes"(passthrough), "no"(sriov)
+ bandwidth: 10 Gbps
+ - name: xe1
+ vpci: "0000:00:11.0"
+ dedicated: "no"
+ bandwidth: 10 Gbps
+ bridge-ifaces:
+ - name: eth0
+ vpci: "0000:00:0a.0"
+ bandwidth: 1 Mbps
diff --git a/models/openmano/test/tidgen_vnf_4sriov.yaml b/models/openmano/test/tidgen_vnf_4sriov.yaml
new file mode 100644
index 0000000..af315d2
--- /dev/null
+++ b/models/openmano/test/tidgen_vnf_4sriov.yaml
@@ -0,0 +1,76 @@
+---
+vnf:
+ name: tidgenMWC_4sriov
+ description: tidgen for MWC2016; 12G 10 cores
+ class: TID
+ external-connections:
+ - name: eth0
+ type: bridge
+ VNFC: tidgenMWC-VM
+ local_iface_name: eth0
+ description: Bridge interface, request for dhcp
+ - name: eth1
+ type: mgmt # "mgmt"(autoconnect to management net), "bridge", "data"
+ VNFC: tidgenMWC-VM # Virtual Machine this interface belongs to
+ local_iface_name: eth1 # name inside this Virtual Machine
+ description: Other management interface for general use
+ - name: xe0
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe0
+ description: Data interface 1
+ - name: xe1
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe1
+ description: Data interface 2
+ - name: xe2
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe2
+ description: Data interface 3
+ - name: xe3
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe3
+ description: Data interface 4
+ VNFC: # Virtual machine array
+ - name: tidgenMWC-VM # name of Virtual Machine
+ disk: 10
+ description: tidgen for MWC 12G 10 cores
+ # VNFC image: /mnt/powervault/virtualization/vnfs/tid/tidgenMWC.qcow2
+ VNFC image: tidgenMWC
+ image metadata: {"use_incremental": "no" } #is already incremental
+ processor: #Optional, leave it
+ model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz
+ features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"]
+ hypervisor: #Optional, leave it
+ type: QEMU-kvm
+ version: "10002|12001|2.6.32-358.el6.x86_64"
+ numas:
+ - paired-threads: 5 # "cores", "paired-threads", "threads"
+ memory: 12 # GBytes
+ interfaces:
+ - name: xe0
+ vpci: "0000:00:10.0"
+ dedicated: "no" # "yes"(passthrough), "no"(sriov)
+ bandwidth: 10 Gbps
+ - name: xe1
+ vpci: "0000:00:11.0"
+ dedicated: "no"
+ bandwidth: 10 Gbps
+ - name: xe2
+ vpci: "0000:00:12.0"
+ dedicated: "no" # "yes"(passthrough), "no"(sriov)
+ bandwidth: 10 Gbps
+ - name: xe3
+ vpci: "0000:00:13.0"
+ dedicated: "no"
+ bandwidth: 10 Gbps
+ bridge-ifaces:
+ - name: eth0
+ vpci: "0000:00:0a.0" # Optional
+ bandwidth: 1 Mbps # Optional, informative only
+ - name: eth1
+ vpci: "0000:00:0b.0" # Optional
+ bandwidth: 1 Mbps # Optional, informative only
diff --git a/models/openmano/test/tidgen_vnf_4sriov_no_ctrlnet.yaml b/models/openmano/test/tidgen_vnf_4sriov_no_ctrlnet.yaml
new file mode 100644
index 0000000..9cb9c4d
--- /dev/null
+++ b/models/openmano/test/tidgen_vnf_4sriov_no_ctrlnet.yaml
@@ -0,0 +1,68 @@
+---
+vnf:
+ name: tidgenMWC_4sriov_no_ctrlnet
+ description: tidgen for MWC2016; 12G 10 cores
+ class: TID
+ external-connections:
+ - name: eth0
+ type: bridge
+ VNFC: tidgenMWC-VM
+ local_iface_name: eth0
+ description: Bridge interface, request for dhcp
+ - name: xe0
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe0
+ description: Data interface 1
+ - name: xe1
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe1
+ description: Data interface 2
+ - name: xe2
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe2
+ description: Data interface 3
+ - name: xe3
+ type: data
+ VNFC: tidgenMWC-VM
+ local_iface_name: xe3
+ description: Data interface 4
+ VNFC: # Virtual machine array
+ - name: tidgenMWC-VM # name of Virtual Machine
+ disk: 10
+ description: tidgen for MWC 12G 10 cores
+ # VNFC image: /mnt/powervault/virtualization/vnfs/tid/tidgenMWC.qcow2
+ VNFC image: tidgenMWC
+ image metadata: {"use_incremental": "no" } #is already incremental
+ processor: #Optional, leave it
+ model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz
+ features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"]
+ hypervisor: #Optional, leave it
+ type: QEMU-kvm
+ version: "10002|12001|2.6.32-358.el6.x86_64"
+ numas:
+ - paired-threads: 5 # "cores", "paired-threads", "threads"
+ memory: 12 # GBytes
+ interfaces:
+ - name: xe0
+ vpci: "0000:00:10.0"
+ dedicated: "no" # "yes"(passthrough), "no"(sriov)
+ bandwidth: 10 Gbps
+ - name: xe1
+ vpci: "0000:00:11.0"
+ dedicated: "no"
+ bandwidth: 10 Gbps
+ - name: xe2
+ vpci: "0000:00:12.0"
+ dedicated: "no" # "yes"(passthrough), "no"(sriov)
+ bandwidth: 10 Gbps
+ - name: xe3
+ vpci: "0000:00:13.0"
+ dedicated: "no"
+ bandwidth: 10 Gbps
+ bridge-ifaces:
+ - name: eth0
+ vpci: "0000:00:0a.0" # Optional
+ bandwidth: 1 Mbps # Optional, informative only
diff --git a/models/plugins/CMakeLists.txt b/models/plugins/CMakeLists.txt
new file mode 100644
index 0000000..12de6a0
--- /dev/null
+++ b/models/plugins/CMakeLists.txt
@@ -0,0 +1,25 @@
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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.
+#
+# Author(s): Anil Gunturu
+# Creation Date: 2014/12/11
+#
+
+cmake_minimum_required(VERSION 2.8)
+
+set(subdirs
+ yang
+ )
+rift_add_subdirs(SUBDIR_LIST ${subdirs})
diff --git a/models/plugins/yang/CMakeLists.txt b/models/plugins/yang/CMakeLists.txt
new file mode 100644
index 0000000..782415b
--- /dev/null
+++ b/models/plugins/yang/CMakeLists.txt
@@ -0,0 +1,71 @@
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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.
+#
+# Author(s): Anil Gunturu
+# Creation Date: 10/15/2014
+#
+
+# NOTE: These files will be used by the new MANO subsystem
+set(source_yang_files
+ ietf-l2-topology.yang
+ ietf-network-topology.yang
+ ietf-network.yang
+ nsd.yang rw-nsd.yang
+ nsr.yang rw-nsr.yang
+ pnfd.yang
+ rw-topology.yang
+ vld.yang rw-vld.yang
+ vlr.yang rw-vlr.yang
+ vnfd.yang rw-vnfd.yang
+ vnfr.yang rw-vnfr.yang
+ vnffgd.yang
+ )
+
+rift_add_yang_target(
+ TARGET mano-types_yang
+ YANG_FILES
+ mano-types.yang
+ COMPONENT ${PKG_LONG_NAME}
+ )
+
+rift_add_yang_target(
+ TARGET mano_yang
+ YANG_FILES ${source_yang_files}
+ GIR_PATHS ${CMAKE_CURRENT_BINARY_DIR}
+ COMPONENT ${PKG_LONG_NAME}
+ LIBRARIES
+ rwmanifest_yang_gen
+ rwschema_yang_gen
+ rwcloud_yang_gen
+ rwconfig_agent_yang_gen
+ mano-types_yang_gen
+ )
+
+#rift_gen_yang_tree(mano-pyang-trees
+# OUTFILE_PREFIX mano.yang
+# YANG_FILES
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/vnfd.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/vld.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/nsd.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/rw-vnfd.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/rw-vld.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/rw-nsd.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/pnfd.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/vnffgd.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/ietf-network.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/ietf-network-topology.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/ietf-l2-topology.yang
+# ${RIFT_SUBMODULE_SOURCE_ROOT}/models/plugins/yang/rw-topology.yang
+# )
diff --git a/models/plugins/yang/Makefile b/models/plugins/yang/Makefile
new file mode 100644
index 0000000..2b691a8
--- /dev/null
+++ b/models/plugins/yang/Makefile
@@ -0,0 +1,36 @@
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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.
+#
+# Author(s): Tim Mortsolf
+# Creation Date: 11/25/2013
+#
+
+##
+# Define a Makefile function: find_upwards(filename)
+#
+# Searches for a file of the given name in the directory ., .., ../.., ../../.., etc.,
+# until the file is found or the root directory is reached
+##
+find_upward = $(word 1, $(shell while [ `pwd` != / ] ; do find `pwd` -maxdepth 1 -name $1 ; cd .. ; done))
+
+##
+# Call find_upward("Makefile.top") to find the nearest upwards adjacent Makefile.top
+##
+makefile.top := $(call find_upward, "Makefile.top")
+
+##
+# If Makefile.top was found, then include it
+##
+include $(makefile.top)
diff --git a/models/plugins/yang/ietf-l2-topology.yang b/models/plugins/yang/ietf-l2-topology.yang
new file mode 100644
index 0000000..9f572cb
--- /dev/null
+++ b/models/plugins/yang/ietf-l2-topology.yang
@@ -0,0 +1,578 @@
+
+/*
+ * NO RW COPYRIGHT
+ *
+ */
+
+module ietf-l2-topology {
+ yang-version 1;
+ namespace "urn:ietf:params:xml:ns:yang:ietf-l2-topology";
+ prefix "l2t";
+
+ import ietf-network {
+ prefix "nw";
+ }
+
+ import ietf-network-topology {
+ prefix "nt";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ organization "TBD";
+ contact "I-D Editor: jie.dong@huawei.com";
+
+ description
+ "This module defines a basic model for
+ the layer-2 topology of a network";
+
+ revision "2015-06-23" {
+ description "Initial revision";
+ reference "draft-ietf-i2rs-l2-network-topology-01";
+ }
+
+ /*
+ * Typedefs
+ */
+
+ typedef vlan {
+ type uint16 {
+ range "0..4095";
+ }
+ description "VLAN ID";
+ }
+
+ typedef trill-nickname {
+ type uint16;
+ description "TRILL Nickname";
+ }
+
+ typedef flag-type {
+ type identityref {
+ base "flag-identity";
+ }
+ description "Base type for flags";
+ }
+
+ typedef l2-network-event-type {
+ type enumeration {
+ enum "add" {
+ value 0;
+ description "An L2 node or link or termination-point
+ has been added";
+ }
+ enum "remove" {
+ value 1;
+ description "An L2 node or link or termination-point
+ has been removed";
+ }
+ enum "update" {
+ value 2;
+ description "An L2 node or link or termination-point
+ has been updated";
+ }
+ }
+ description "l2 network event type for notifications";
+ } // l2-topology-event-type
+
+
+ /*
+ * Features
+ */
+
+ feature VLAN {
+ description
+ "Indicates that the system supports the
+ vlan functions";
+ }
+
+ feature QinQ {
+ description
+ "Indicates that the system supports the
+ qinq functions";
+ }
+
+ feature PBB {
+ description
+ "Indicates that the device supports the
+ provider-backbone-bridging functions";
+ }
+
+ feature VPLS {
+ description
+ "Indicates that the device supports the
+ VPLS functions";
+ reference "RFC 4761, RFC 4762";
+ }
+
+ feature TRILL {
+ description
+ "Indicates that the device supports the
+ TRILL functions";
+ reference "RFC 6325";
+ }
+
+ feature VXLAN {
+ description
+ "Indicates that the device supports the
+ VXLAN functions";
+ reference "RFC 7348";
+ }
+
+ /*
+ * Identities
+ */
+ identity flag-identity {
+ description "Base type for flags";
+ }
+
+ identity encapsulation-type {
+ description
+ "Base identity from which specific encapsulation
+ types are derived.";
+ }
+
+ identity eth-encapsulation-type {
+ base encapsulation-type;
+ description
+ "Base identity from which specific ethernet
+ encapsulation types are derived.";
+
+ }
+
+ identity ethernet {
+ base eth-encapsulation-type;
+ description
+ "native ethernet encapsulation";
+ }
+
+ identity vlan {
+ base eth-encapsulation-type;
+ description
+ "vlan encapsulation";
+ }
+
+ identity qinq {
+ base eth-encapsulation-type;
+ description
+ "qinq encapsulation";
+ }
+
+ identity pbb {
+ base eth-encapsulation-type;
+ description
+ "pbb encapsulation";
+ }
+
+ identity trill {
+ base eth-encapsulation-type;
+ description
+ "trill encapsulation";
+ }
+
+ identity vpls {
+ base eth-encapsulation-type;
+ description
+ "vpls encapsulation";
+ }
+
+ identity vxlan {
+ base eth-encapsulation-type;
+ description
+ "vxlan encapsulation";
+ }
+
+ identity frame-relay {
+ base encapsulation-type;
+ description
+ "Frame Relay encapsulation";
+ }
+
+ identity ppp {
+ base encapsulation-type;
+ description
+ "PPP encapsulation";
+ }
+
+ identity hdlc {
+ base encapsulation-type;
+ description
+ "HDLC encapsulation";
+ }
+
+ identity atm {
+ base encapsulation-type;
+ description
+ "Base identity from which specific ATM
+ encapsulation types are derived.";
+
+ }
+
+ identity pwe3 {
+ base encapsulation-type;
+ description
+ "Base identity from which specific pw
+ encapsulation types are derived.";
+ }
+
+
+ /*
+ * Groupings
+ */
+
+
+ grouping l2-network-type {
+ description "Identify the topology type to be L2.";
+ container l2-network {
+ presence "indicates L2 Network";
+ description
+ "The presence of the container node indicates
+ L2 Topology";
+ }
+ }
+
+ grouping l2-network-attributes {
+ description "L2 Topology scope attributes";
+ container l2-network-attributes {
+ description "Containing L2 network attributes";
+ leaf name {
+ type string;
+ description "Name of the L2 network";
+ }
+
+ leaf-list flag {
+ type flag-type;
+ description "L2 network flags";
+ }
+ }
+ }
+
+ grouping l2-node-attributes {
+ description "L2 node attributes";
+ container l2-node-attributes {
+ description "Containing L2 node attributes";
+ leaf name {
+ type string;
+ description "Node name";
+ }
+ leaf description {
+ type string;
+ description "Node description";
+ }
+ leaf-list management-address {
+ type inet:ip-address;
+ description "System management address";
+ }
+ leaf management-vid {
+ if-feature VLAN;
+ type vlan;
+ description "System management VID";
+ }
+ leaf-list nick-name {
+ if-feature TRILL;
+ type trill-nickname;
+ description "Nickname of the RBridge";
+ }
+ leaf-list flag {
+ type flag-type;
+ description "Node operational flags";
+ }
+ }
+ } // grouping l2-node-attributes
+
+
+ grouping l2-link-attributes {
+ description "L2 link attributes";
+ container l2-link-attributes {
+ description "Containing L2 link attributes";
+ leaf name {
+ type string;
+ description "Link name";
+ }
+ leaf-list flag {
+ type flag-type;
+ description "Link flags";
+ }
+ leaf rate {
+ type decimal64 {
+ fraction-digits 2;
+ }
+ description "Link rate";
+
+ }
+ leaf delay {
+ type uint32;
+ description "Link delay in microseconds";
+ }
+ leaf-list srlg {
+ type uint32;
+ description
+ "List of Shared Risk Link Groups
+ this link belongs to.";
+ }
+ }
+ } // grouping l2-link-attributes
+
+ grouping l2-termination-point-attributes {
+ description "L2 termination point attributes";
+ container l2-termination-point-attributes {
+ description "Containing L2 TP attributes";
+ leaf description {
+ type string;
+ description "Port description";
+ }
+
+ leaf maximum-frame-size {
+ type uint32;
+ description "Maximum frame size";
+ }
+
+ choice l2-termination-point-type {
+ description
+ "Indicates termination-point type
+ specific attributes";
+ case ethernet {
+ leaf mac-address {
+ type yang:mac-address;
+ description "Interface MAC address";
+ }
+
+ leaf eth-encapsulation {
+ type identityref {
+ base eth-encapsulation-type;
+ }
+ description
+ "Encapsulation type of this
+ ternimation point.";
+ }
+
+ leaf port-vlan-id {
+ if-feature VLAN;
+ type vlan;
+ description "Port VLAN ID";
+ }
+
+ list vlan-id-name {
+ if-feature VLAN;
+ key "vlan-id";
+ description "Interface configured VLANs";
+ leaf vlan-id {
+ type vlan;
+ description "VLAN ID";
+ }
+ leaf vlan-name {
+ type string;
+ description "VLAN Name";
+ }
+ }
+ } //case ethernet
+
+ case legacy {
+ leaf encapsulation {
+ type identityref {
+ base encapsulation-type;
+ }
+ description
+ "Encapsulation type of this termination point.";
+ }
+ } //case legacy
+
+ } //choice termination-point-type
+
+ leaf tp-state {
+ type enumeration {
+ enum in-use {
+ value 0;
+ description
+ "the termination point is in forwarding state";
+ }
+ enum blocking {
+ value 1;
+ description
+ "the termination point is in blocking state";
+ }
+ enum down {
+ value 2;
+ description
+ "the termination point is in down state";
+ }
+ enum others {
+ value 3;
+ description
+ "the termination point is in other state";
+ }
+ }
+ config false;
+ description "State of the termination point";
+ }
+ }
+ } // grouping l2-termination-point-attributes
+
+/*** grouping of network/node/link/tp leaf-refs ***/
+
+ grouping network-ref {
+ description
+ "Grouping for an absolute reference to a network topology
+ instance.";
+ leaf network-ref {
+ type leafref {
+ path "/nw:network/nw:network-id";
+ }
+ description
+ "An absolute reference to a network topology instance.";
+ }
+ }
+
+ grouping link-ref {
+ description
+ "Grouping for an absolute reference to a link instance.";
+ uses network-ref;
+ leaf link-ref {
+ type leafref {
+ path "/nw:network"
+ +"[nw:network-id = current()/../network-ref]"
+ +"/nt:link/nt:link-id";
+ }
+ description
+ "An absolute reference to a link instance.";
+ }
+ }
+
+ grouping node-ref {
+ description
+ "Grouping for an absolute reference to a node instance.";
+ uses network-ref;
+ leaf node-ref {
+ type leafref {
+ path "/nw:network"
+ +"[nw:network-id = current()/../network-ref]"
+ +"/nw:node/nw:node-id";
+ }
+ description
+ "An absolute reference to a node instance.";
+ }
+ }
+
+ grouping tp-ref {
+ description
+ "Grouping for an absolute reference to a termination point.";
+ uses node-ref;
+ leaf tp-ref {
+ type leafref {
+ path "/nw:network"
+ +"[nw:network-id = current()/../network-ref]"
+ +"/nw:node[nw:node-id = current()/../node-ref]"
+ +"/nt:termination-point/nt:tp-id";
+ }
+ description
+ "Grouping for an absolute reference to a TP.";
+ }
+ }
+
+
+ /*
+ * Data nodes
+ */
+ augment "/nw:network/nw:network-types" {
+ description
+ "Introduce new network type for L2 topology";
+ uses l2-network-type;
+ }
+
+ augment "/nw:network" {
+ /* RIFT-Change: when not to be used yet
+ when "nw:network-types/l2-network" {
+ description
+ "Augmentation parameters apply only for networks
+ with L2 topology";
+ }
+ */
+ description
+ "Configuration parameters for the L2 network
+ as a whole";
+ uses l2-network-attributes;
+ }
+
+ augment "/nw:network/nw:node" {
+ /* RIFT-Change: when not to be used yet
+ when "../nw:network-types/l2-network" {
+ description
+ "Augmentation parameters apply only for networks
+ with L2 topology";
+ }
+ */
+ description
+ "Configuration parameters for L2 at the node
+ level";
+ uses l2-node-attributes;
+ }
+
+ augment "/nw:network/nt:link" {
+ /* RIFT-Change: when not to be used yet
+ when "/nw:network/nw:network-types/l2-network" {
+ description
+ "Augmentation parameters apply only for networks
+ with L2 topology";
+ }
+ */
+ description "Augment L2 topology link information";
+ uses l2-link-attributes;
+ }
+
+ augment "/nw:network/nw:node/nt:termination-point" {
+ /* RIFT-Change: when not to be used yet
+ when "/nw:network/nw:network-types/l2-network" {
+ description
+ "Augmentation parameters apply only for networks
+ with L2 topology";
+ }
+ */
+ description
+ "Augment L2 topology termination point configuration";
+ uses l2-termination-point-attributes;
+ }
+
+ /*
+ * Notifications
+ */
+
+ notification l2-node-event {
+ description "Notification event for L2 node";
+ leaf event-type {
+ type l2-network-event-type;
+ description "Event type";
+ }
+ uses node-ref;
+ uses l2-network-type;
+ uses l2-node-attributes;
+ }
+
+ notification l2-link-event {
+ description "Notification event for L2 link";
+ leaf event-type {
+ type l2-network-event-type;
+ description "Event type";
+ }
+ uses link-ref;
+ uses l2-network-type;
+ uses l2-link-attributes;
+ }
+
+ notification l2-termination-point-event {
+ description "Notification event for L2 termination point";
+ leaf event-type {
+ type l2-network-event-type;
+ description "Event type";
+ }
+ uses tp-ref;
+ uses l2-network-type;
+ uses l2-termination-point-attributes;
+ }
+
+} // module l2-topology
diff --git a/models/plugins/yang/ietf-network-topology.yang b/models/plugins/yang/ietf-network-topology.yang
new file mode 100644
index 0000000..e8f7c79
--- /dev/null
+++ b/models/plugins/yang/ietf-network-topology.yang
@@ -0,0 +1,257 @@
+
+/*
+ * NO RW COPYRIGHT
+ *
+ */
+
+module ietf-network-topology {
+ yang-version 1;
+ namespace "urn:ietf:params:xml:ns:yang:ietf-network-topology";
+ prefix lnk;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+ import ietf-network {
+ prefix nd;
+ }
+
+ organization "TBD";
+ contact
+ "WILL-BE-DEFINED-LATER";
+ description
+ "This module defines a common base model for network topology,
+ augmenting the base network model with links to connect nodes,
+ as well as termination points to terminate links on nodes.";
+
+ revision 2015-06-08 {
+ description
+ "Initial revision.";
+ reference "draft-ietf-i2rs-yang-network-topo-01";
+ }
+
+ typedef link-id {
+ type inet:uri;
+ description
+ "An identifier for a link in a topology.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same link in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in
+ separate datastores. An implementation MAY choose to capture
+ semantics in the identifier, for example to indicate the type
+ of link and/or the type of topology that the link is a part
+ of.";
+ }
+
+ typedef tp-id {
+ type inet:uri;
+ description
+ "An identifier for termination points on a node.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same TP in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in
+ separate datastores. An implementation MAY choose to capture
+ semantics in the identifier, for example to indicate the type
+ of TP and/or the type of node and topology that the TP is a
+ part of.";
+ }
+
+ grouping link-ref {
+ description
+ "References a link in a specific network.";
+ leaf link-ref {
+ type leafref {
+ path "/nd:network[nd:network-id=current()/../"+
+ "nd:network-ref]/link/link-id";
+ }
+ description
+ "A type for an absolute reference a link instance.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+ uses nd:network-ref;
+ }
+
+ grouping tp-ref {
+ description
+ "References a termination point in a specific node.";
+ leaf tp-ref {
+ type leafref {
+ path "/nd:network[nd:network-id=current()/../"+
+ "nd:network-ref]/nd:node[nd:node-id=current()/../"+
+ "nd:node-ref]/termination-point/tp-id";
+ }
+ description
+ "A type for an absolute reference to a termination point.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+ uses nd:node-ref;
+ }
+
+ augment "/nd:network" {
+ description
+ "Add links to the network model.";
+ list link {
+ key "link-id";
+
+ description
+ "A Network Link connects a by Local (Source) node and
+ a Remote (Destination) Network Nodes via a set of the
+ nodes' termination points.
+ As it is possible to have several links between the same
+ source and destination nodes, and as a link could
+ potentially be re-homed between termination points, to
+ ensure that we would always know to distinguish between
+ links, every link is identified by a dedicated link
+ identifier.
+ Note that a link models a point-to-point link, not a
+ multipoint link.
+ Layering dependencies on links in underlay topologies are
+ not represented as the layering information of nodes and of
+ termination points is sufficient.";
+ container source {
+ description
+ "This container holds the logical source of a particular
+ link.";
+ leaf source-node {
+ type leafref {
+ // RIFT change:
+ path "../../../../nd:network/nd:node/nd:node-id";
+ }
+ mandatory true;
+ description
+ "Source node identifier, must be in same topology.";
+ }
+ leaf source-tp {
+ type leafref {
+ // RIFT change:
+ path "../../../../nd:network/nd:node[nd:node-id=current()/../"+
+ "source-node]/termination-point/tp-id";
+ }
+ description
+ "Termination point within source node that terminates
+ the link.";
+ }
+ }
+ container destination {
+ description
+ "This container holds the logical destination of a
+ particular link.";
+ leaf dest-node {
+ type leafref {
+ // RIFT change
+ path "../../../../nd:network/nd:node/nd:node-id";
+ }
+ mandatory true;
+ description
+ "Destination node identifier, must be in the same
+ network.";
+ }
+ leaf dest-tp {
+ type leafref {
+ // RIFT change:
+ path "../../../../nd:network/nd:node[nd:node-id=current()/../"+
+ "dest-node]/termination-point/tp-id";
+ }
+ description
+ "Termination point within destination node that
+ terminates the link.";
+ }
+ }
+ leaf link-id {
+ type link-id;
+ description
+ "The identifier of a link in the topology.
+ A link is specific to a topology to which it belongs.";
+ }
+ list supporting-link {
+ key "network-ref link-ref";
+ description
+ "Identifies the link, or links, that this link
+ is dependent on.";
+ leaf network-ref {
+ type leafref {
+ // RIFT change:
+ path "../../../../nd:network/nd:supporting-network/nd:network-ref";
+ }
+ description
+ "This leaf identifies in which underlay topology
+ supporting link is present.";
+ }
+ leaf link-ref {
+ type leafref {
+ path "/nd:network[nd:network-id=current()/.."+
+ "/network-ref]/link/link-id";
+ }
+ description
+ "This leaf identifies a link which is a part
+ of this link's underlay. Reference loops, in which
+ a link identifies itself as its underlay, either
+ directly or transitively, are not allowed.";
+ }
+ }
+ }
+ }
+ augment "/nd:network/nd:node" {
+ description
+ "Augment termination points which terminate links.
+ Termination points can ultimately be mapped to interfaces.";
+ list termination-point {
+ key "tp-id";
+ description
+ "A termination point can terminate a link.
+ Depending on the type of topology, a termination point
+ could, for example, refer to a port or an interface.";
+ leaf tp-id {
+ type tp-id;
+ description
+ "Termination point identifier.";
+ }
+ list supporting-termination-point {
+ key "network-ref node-ref tp-ref";
+ description
+ "The leaf list identifies any termination points that
+ the termination point is dependent on, or maps onto.
+ Those termination points will themselves be contained
+ in a supporting node.
+ This dependency information can be inferred from
+ the dependencies between links. For this reason,
+ this item is not separately configurable. Hence no
+ corresponding constraint needs to be articulated.
+ The corresponding information is simply provided by the
+ implementing system.";
+ leaf network-ref {
+ type leafref {
+ // RIFT change:
+ path "/nd:network/nd:node/nd:supporting-node/nd:network-ref";
+ }
+ description
+ "This leaf identifies in which topology the
+ supporting termination point is present.";
+ }
+ leaf node-ref {
+ type leafref {
+ // RIFT change:
+ path "/nd:network/nd:node/nd:supporting-node/nd:node-ref";
+ }
+ description
+ "This leaf identifies in which node the supporting
+ termination point is present.";
+ }
+ leaf tp-ref {
+ type leafref {
+ path "/nd:network[nd:network-id=current()/../"+
+ "network-ref]/nd:node[nd:node-id=current()/../"+
+ "node-ref]/termination-point/tp-id";
+ }
+ description
+ "Reference to the underlay node, must be in a
+ different topology";
+ }
+ }
+ }
+ }
+}
diff --git a/models/plugins/yang/ietf-network.tailf.yang b/models/plugins/yang/ietf-network.tailf.yang
new file mode 100644
index 0000000..f531f65
--- /dev/null
+++ b/models/plugins/yang/ietf-network.tailf.yang
@@ -0,0 +1,27 @@
+
+/*
+ * NO RW COPYRIGHT
+ *
+ */
+
+module ietf-network-annotation
+{
+ namespace "urn:ietf:params:xml:ns:yang:ietf-network";
+ prefix "ietf-network-ann";
+
+ import tailf-common {
+ prefix tailf;
+ }
+
+ import ietf-network {
+ prefix nd;
+ }
+
+ tailf:annotate "/nd:network" {
+ tailf:callpoint rw_callpoint;
+ }
+
+ tailf:annotate "/nd:network/nd:server-provided" {
+ tailf:callpoint rw_callpoint;
+ }
+}
diff --git a/models/plugins/yang/ietf-network.yang b/models/plugins/yang/ietf-network.yang
new file mode 100644
index 0000000..a059e94
--- /dev/null
+++ b/models/plugins/yang/ietf-network.yang
@@ -0,0 +1,157 @@
+
+/*
+ * NO RW COPYRIGHT
+ *
+ */
+
+module ietf-network {
+ yang-version 1;
+ namespace "urn:ietf:params:xml:ns:yang:ietf-network";
+ prefix nd;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ organization "TBD";
+ contact
+ "WILL-BE-DEFINED-LATER";
+ description
+ "This module defines a common base model for a collection
+ of nodes in a network. Node definitions s are further used
+ in network topologies and inventories.";
+
+ revision 2015-06-08 {
+ description
+ "Initial revision.";
+ reference "draft-ietf-i2rs-yang-network-topo-01";
+ }
+
+ typedef node-id {
+ type inet:uri;
+ description
+ "Identifier for a node.";
+ }
+
+ typedef network-id {
+ type inet:uri;
+ description
+ "Identifier for a network.";
+ }
+
+ grouping network-ref {
+ description
+ "Contains the information necessary to reference a network,
+ for example an underlay network.";
+ leaf network-ref {
+ type leafref {
+ path "/network/network-id";
+ }
+ description
+ "Used to reference a network, for example an underlay
+ network.";
+ }
+ }
+
+ grouping node-ref {
+ description
+ "Contains the information necessary to reference a node.";
+ leaf node-ref {
+ type leafref {
+ path "/network[network-id=current()/../network-ref]"+
+ "/node/node-id";
+ }
+ description
+ "Used to reference a node.
+ Nodes are identified relative to the network they are
+ contained in.";
+ }
+ uses network-ref;
+ }
+
+ list network {
+ config false;
+ key "network-id";
+ description
+ "Describes a network.
+ A network typically contains an inventory of nodes,
+ topological information (augmented through
+ network-topology model), as well as layering
+ information.";
+ container network-types {
+ description
+ "Serves as an augmentation target.
+ The network type is indicated through corresponding
+ presence containers augmented into this container.";
+ }
+ leaf network-id {
+ type network-id;
+ description
+ "Identifies a network.";
+ }
+ leaf server-provided {
+ type boolean;
+ config false;
+ description
+ "Indicates whether the information concerning this
+ particular network is populated by the server
+ (server-provided true, the general case for network
+ information discovered from the server),
+ or whether it is configured by a client
+ (server-provided true, possible e.g. for
+ service overlays managed through a controller).";
+ }
+ list supporting-network {
+ key "network-ref";
+ description
+ "An underlay network, used to represent layered network
+ topologies.";
+
+ leaf network-ref {
+ type leafref {
+ path "/network/network-id";
+ }
+ description
+ "References the underlay network.";
+ }
+ }
+ list node {
+ key "node-id";
+ description
+ "The inventory of nodes of this network.";
+ leaf node-id {
+ type node-id;
+ description
+ "Identifies a node uniquely within the containing
+ network.";
+ }
+ list supporting-node {
+ key "network-ref node-ref";
+ description
+ "Represents another node, in an underlay network, that
+ this node is supported by. Used to represent layering
+ structure.";
+ leaf network-ref {
+ type leafref {
+ path "../../../supporting-network/network-ref";
+ }
+ description
+ "References the underlay network that the
+ underlay node is part of.";
+ }
+ leaf node-ref {
+ type leafref {
+ path "/network/node/node-id";
+ }
+ description
+ "References the underlay node itself.";
+ }
+ }
+ }
+ }
+}
+
diff --git a/models/plugins/yang/mano-types.yang b/models/plugins/yang/mano-types.yang
new file mode 100644
index 0000000..cd5d446
--- /dev/null
+++ b/models/plugins/yang/mano-types.yang
@@ -0,0 +1,1991 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module mano-types
+{
+ namespace "urn:ietf:params:xml:ns:yang:nfvo:mano-types";
+ prefix "manotypes";
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ revision 2015-04-23 {
+ description
+ "Initial revision. This YANG file defines
+ the reusable base types for VNF Management
+ and Orchestration (MANO).";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ typedef parameter-data-type {
+ type enumeration {
+ enum STRING;
+ enum INTEGER;
+ enum BOOLEAN;
+ }
+ }
+
+ grouping primitive-parameter-value {
+ list parameter {
+ description
+ "List of parameters to the configuration primitive.";
+ key "name";
+ leaf name {
+ description
+ "Name of the parameter.";
+ type string;
+ }
+
+ leaf value {
+ description
+ "Value associated with the name.";
+ type string;
+ }
+ }
+ }
+
+ grouping primitive-parameter {
+ leaf name {
+ description
+ "Name of the parameter.";
+ type string;
+ }
+
+ leaf data-type {
+ description
+ "Data type associated with the name.";
+ type manotypes:parameter-data-type;
+ }
+
+ leaf mandatory {
+ description "Is this field mandatory";
+ type boolean;
+ default false;
+ }
+
+ leaf default-value {
+ description "The default value for this field";
+ type string;
+ }
+
+ leaf parameter-pool {
+ description "NSD Parameter pool name to use for this paramter";
+ type string;
+ }
+
+ leaf read-only {
+ description
+ "The value should be greyed out by the UI.
+ Only applies to parameters with default values.";
+ type boolean;
+ }
+
+ leaf hidden {
+ description
+ "The value should be hidden by the UI.
+ Only applies to parameters with default values.";
+ type boolean;
+ }
+ }
+
+
+ grouping vnf-configuration {
+ container vnf-configuration {
+ rwpb:msg-new VnfConfiguration;
+ description
+ "Information regarding the VNF configuration
+ is captured here. Note that if the NS contains
+ multiple instances of the same VNF, each instance
+ of the VNF may have different configuration";
+
+ choice config-method {
+ description
+ "Defines the configuration method for the VNF.";
+ case netconf {
+ description
+ "Use NETCONF for configuring the VNF.";
+ container netconf {
+ leaf target {
+ description
+ "Netconf configuration target";
+ type enumeration {
+ enum running;
+ enum candidate;
+ }
+ }
+
+ leaf protocol {
+ description
+ "Protocol to use for netconf (e.g. ssh)";
+ type enumeration {
+ enum None;
+ enum ssh;
+ }
+ }
+
+ leaf port {
+ description
+ "Port for the netconf server.";
+ type inet:port-number;
+ }
+ }
+ }
+
+ case rest {
+ description
+ "Use REST for configuring the VNF.";
+ container rest {
+ leaf port {
+ description
+ "Port for the REST server.";
+ type inet:port-number;
+ }
+ }
+ }
+
+ case script {
+ description
+ "Use custom script for configuring the VNF.
+ This script is executed in the context of
+ Orchestrator.";
+ container script {
+ leaf script-type {
+ description
+ "Script type - currently supported : bash, expect";
+ type enumeration {
+ enum bash;
+ enum expect;
+ }
+ }
+ }
+ }
+
+ case juju {
+ description
+ "Configure the VNF through Juju.";
+ container juju {
+ leaf charm {
+ description "Juju charm to use with the VNF.";
+ type string;
+ }
+ }
+ }
+ }
+
+ container config-access {
+ leaf mgmt-ip-address {
+ description
+ "IP address to be used to configure this VNF,
+ optional if it is possible to resolve dynamically.";
+ type inet:ip-address;
+ }
+
+ leaf username {
+ description
+ "username for configuration.";
+ type string;
+ }
+
+ leaf password {
+ description
+ "Password for configuration access authentication.";
+ type string;
+ }
+ }
+
+ container config-attributes {
+ description
+ "Miscelaneous input parameters to be considered
+ while processing the NSD to apply configuration";
+
+ leaf config-priority {
+ description
+ "Configuration priority - order of confgiration
+ to be applied to each VNF in this NS,
+ low number gets precedence over high number";
+ type uint64;
+ }
+
+ leaf config-delay {
+ description
+ "Wait (seconds) before applying the configuration to VNF";
+ type uint64;
+ }
+ }
+
+ list service-primitive {
+ rwpb:msg-new ServicePrimitive;
+ description
+ "List of service primitives supported by the
+ configuration agent for this VNF.";
+ key "name";
+
+ leaf name {
+ description
+ "Name of the service primitive.";
+ type string;
+ }
+
+ list parameter {
+ description
+ "List of parameters to the service primitive.";
+ key "name";
+ uses primitive-parameter;
+ }
+ }
+
+ list initial-config-primitive {
+ rwpb:msg-new InitialConfigPrimitive;
+ description
+ "Initial set of configuration primitives.";
+ key "seq";
+ leaf seq {
+ description
+ "Sequence number for the configuration primitive.";
+ type uint64;
+ }
+
+ leaf name {
+ description
+ "Name of the configuration primitive.";
+ type string;
+ }
+
+ list parameter {
+ key "name";
+ leaf name {
+ type string;
+ }
+
+ leaf value {
+ type string;
+ }
+ }
+ }
+
+ leaf config-template {
+ description
+ "Configuration template for each VNF";
+ type string;
+ }
+ }
+ } // END - grouping vnf-configuration
+
+ typedef virtual-link-type {
+ description
+ "Type of virtual link
+ ELAN: A multipoint service connecting a set of VNFs
+ // ELINE: For a simple point to point connection
+ // between a VNF and the existing network.
+ // ETREE: A multipoint service connecting one or
+ // more roots and a set of leaves, but
+ // preventing inter-leaf communication.";
+ type enumeration {
+ enum ELAN;
+ // enum ETREE;
+ // enum ELINE;
+ }
+ }
+
+ grouping named-value {
+ leaf name {
+ type string;
+ }
+
+ leaf value {
+ type string;
+ }
+ }
+
+ typedef http-method {
+ description
+ "Type of HTTP operation";
+
+ type enumeration {
+ enum POST;
+ enum PUT;
+ enum GET;
+ enum DELETE;
+ enum OPTIONS;
+ enum PATCH;
+ }
+ }
+
+ typedef api-type {
+ description
+ "Type of API to fetch monitoring params";
+
+ type enumeration {
+ enum HTTP;
+ enum NETCONF;
+ enum SOAP;
+ }
+ }
+
+ typedef json-query-method {
+ description
+ "The method to extract a value from a JSON response
+
+ NAMEKEY - Use the name as the key for a non-nested value.
+ JSONPATH - Use jsonpath-rw implemenation to extract a value.
+ OBJECTPATH - Use objectpath implemenation to extract a value.";
+ type enumeration {
+ enum NAMEKEY;
+ enum JSONPATH;
+ enum OBJECTPATH;
+ }
+ }
+
+ typedef param-value-type {
+ description
+ "The type of the parameter value";
+ type enumeration {
+ enum INT;
+ enum DECIMAL;
+ enum STRING;
+ }
+ }
+
+ typedef connection-point-type {
+ description
+ "Type of connection point
+ VPORT: Virtual Port
+ // VNIC_ADDR: Virtual NIC Address
+ // PNIC_ADDR: Physical NIC Address
+ // PPORT: Phsical Port.";
+
+ type enumeration {
+ enum VPORT;
+ }
+ }
+
+ typedef widget-type {
+ description
+ "Type of the widget, typically used by the UI.";
+ type enumeration {
+ enum HISTOGRAM;
+ enum BAR;
+ enum GAUGE;
+ enum SLIDER;
+ enum COUNTER;
+ enum TEXTBOX;
+ }
+ }
+
+ typedef cpu-feature-type {
+ description
+ "Enumeration for CPU features.
+
+ AES: CPU supports advanced instruction set for
+ AES (Advanced Encryption Standard).
+
+ CAT: Cache Allocation Technology (CAT) allows
+ an Operating System, Hypervisor, or similar
+ system management agent to specify the amount
+ of L3 cache (currently the last-level cache
+ in most server and client platforms) space an
+ application can fill (as a hint to hardware
+ functionality, certain features such as power
+ management may override CAT settings).
+
+ CMT: Cache Monitoring Technology (CMT) allows
+ an Operating System, Hypervisor, or similar
+ system management agent to determine the
+ usage of cache based on applications running
+ on the platform. The implementation is
+ directed at L3 cache monitoring (currently
+ the last-level cache in most server and
+ client platforms).
+
+ DDIO: Intel Data Direct I/O (DDIO) enables
+ Ethernet server NICs and controllers talk
+ directly to the processor cache without a
+ detour via system memory. This enumeration
+ specifies if the VM requires a DDIO
+ capable host.";
+
+ type enumeration {
+ enum PREFER_AES;
+ enum REQUIRE_AES;
+ enum PREFER_CAT;
+ enum REQUIRE_CAT;
+ enum PREFER_CMT;
+ enum REQUIRE_CMT;
+ enum PREFER_DDIO;
+ enum REQUIRE_DDIO;
+ enum REQUIRE_VME;
+ enum PREFER_VME;
+ enum REQUIRE_DE;
+ enum PREFER_DE;
+ enum REQUIRE_PSE;
+ enum PREFER_PSE;
+ enum REQUIRE_TSC;
+ enum PREFER_TSC;
+ enum REQUIRE_MSR;
+ enum PREFER_MSR;
+ enum REQUIRE_PAE;
+ enum PREFER_PAE;
+ enum REQUIRE_MCE;
+ enum PREFER_MCE;
+ enum REQUIRE_CX8;
+ enum PREFER_CX8;
+ enum REQUIRE_APIC;
+ enum PREFER_APIC;
+ enum REQUIRE_SEP;
+ enum PREFER_SEP;
+ enum REQUIRE_MTRR;
+ enum PREFER_MTRR;
+ enum REQUIRE_PGE;
+ enum PREFER_PGE;
+ enum REQUIRE_MCA;
+ enum PREFER_MCA;
+ enum REQUIRE_CMOV;
+ enum PREFER_CMOV;
+ enum REQUIRE_PAT;
+ enum PREFER_PAT;
+ enum REQUIRE_PSE36;
+ enum PREFER_PSE36;
+ enum REQUIRE_CLFLUSH;
+ enum PREFER_CLFLUSH;
+ enum REQUIRE_DTS;
+ enum PREFER_DTS;
+ enum REQUIRE_ACPI;
+ enum PREFER_ACPI;
+ enum REQUIRE_MMX;
+ enum PREFER_MMX;
+ enum REQUIRE_FXSR;
+ enum PREFER_FXSR;
+ enum REQUIRE_SSE;
+ enum PREFER_SSE;
+ enum REQUIRE_SSE2;
+ enum PREFER_SSE2;
+ enum REQUIRE_SS;
+ enum PREFER_SS;
+ enum REQUIRE_HT;
+ enum PREFER_HT;
+ enum REQUIRE_TM;
+ enum PREFER_TM;
+ enum REQUIRE_IA64;
+ enum PREFER_IA64;
+ enum REQUIRE_PBE;
+ enum PREFER_PBE;
+ enum REQUIRE_RDTSCP;
+ enum PREFER_RDTSCP;
+ enum REQUIRE_PNI;
+ enum PREFER_PNI;
+ enum REQUIRE_PCLMULQDQ;
+ enum PREFER_PCLMULQDQ;
+ enum REQUIRE_DTES64;
+ enum PREFER_DTES64;
+ enum REQUIRE_MONITOR;
+ enum PREFER_MONITOR;
+ enum REQUIRE_DS_CPL;
+ enum PREFER_DS_CPL;
+ enum REQUIRE_VMX;
+ enum PREFER_VMX;
+ enum REQUIRE_SMX;
+ enum PREFER_SMX;
+ enum REQUIRE_EST;
+ enum PREFER_EST;
+ enum REQUIRE_TM2;
+ enum PREFER_TM2;
+ enum REQUIRE_SSSE3;
+ enum PREFER_SSSE3;
+ enum REQUIRE_CID;
+ enum PREFER_CID;
+ enum REQUIRE_FMA;
+ enum PREFER_FMA;
+ enum REQUIRE_CX16;
+ enum PREFER_CX16;
+ enum REQUIRE_XTPR;
+ enum PREFER_XTPR;
+ enum REQUIRE_PDCM;
+ enum PREFER_PDCM;
+ enum REQUIRE_PCID;
+ enum PREFER_PCID;
+ enum REQUIRE_DCA;
+ enum PREFER_DCA;
+ enum REQUIRE_SSE4_1;
+ enum PREFER_SSE4_1;
+ enum REQUIRE_SSE4_2;
+ enum PREFER_SSE4_2;
+ enum REQUIRE_X2APIC;
+ enum PREFER_X2APIC;
+ enum REQUIRE_MOVBE;
+ enum PREFER_MOVBE;
+ enum REQUIRE_POPCNT;
+ enum PREFER_POPCNT;
+ enum REQUIRE_TSC_DEADLINE_TIMER;
+ enum PREFER_TSC_DEADLINE_TIMER;
+ enum REQUIRE_XSAVE;
+ enum PREFER_XSAVE;
+ enum REQUIRE_AVX;
+ enum PREFER_AVX;
+ enum REQUIRE_F16C;
+ enum PREFER_F16C;
+ enum REQUIRE_RDRAND;
+ enum PREFER_RDRAND;
+ enum REQUIRE_FSGSBASE;
+ enum PREFER_FSGSBASE;
+ enum REQUIRE_BMI1;
+ enum PREFER_BMI1;
+ enum REQUIRE_HLE;
+ enum PREFER_HLE;
+ enum REQUIRE_AVX2;
+ enum PREFER_AVX2;
+ enum REQUIRE_SMEP;
+ enum PREFER_SMEP;
+ enum REQUIRE_BMI2;
+ enum PREFER_BMI2;
+ enum REQUIRE_ERMS;
+ enum PREFER_ERMS;
+ enum REQUIRE_INVPCID;
+ enum PREFER_INVPCID;
+ enum REQUIRE_RTM;
+ enum PREFER_RTM;
+ enum REQUIRE_MPX;
+ enum PREFER_MPX;
+ enum REQUIRE_RDSEED;
+ enum PREFER_RDSEED;
+ enum REQUIRE_ADX;
+ enum PREFER_ADX;
+ enum REQUIRE_SMAP;
+ enum PREFER_SMAP;
+ }
+ }
+
+ grouping vm-flavor {
+ container vm-flavor {
+ leaf vcpu-count {
+ description
+ "Number of vcpus for the VM.";
+ type uint16;
+ }
+
+ leaf memory-mb {
+ description
+ "Amount of memory in MB.";
+ type uint64;
+ }
+
+ leaf storage-gb {
+ description
+ "Amount of disk space in GB.";
+ type uint64;
+ }
+ }
+ } //grouping vm-flavor
+
+ grouping vswitch-epa {
+ container vswitch-epa {
+ leaf ovs-acceleration {
+ description
+ "Specifies Open vSwitch acceleration mode.
+ MANDATORY: OVS acceleration is required
+ PREFERRED: OVS acceleration is preferred";
+ type enumeration {
+ enum MANDATORY;
+ enum PREFERRED;
+ enum DISABLED;
+ }
+ }
+
+ leaf ovs-offload {
+ description
+ "Specifies Open vSwitch hardware offload mode.
+ MANDATORY: OVS offload is required
+ PREFERRED: OVS offload is preferred";
+ type enumeration {
+ enum MANDATORY;
+ enum PREFERRED;
+ enum DISABLED;
+ }
+ }
+ }
+ }
+
+ grouping hypervisor-epa {
+ container hypervisor-epa {
+ leaf type {
+ description
+ "Specifies the type of hypervisor.
+ KVM: KVM
+ XEN: XEN";
+ type enumeration {
+ enum PREFER_KVM;
+ enum REQUIRE_KVM;
+ }
+ }
+ leaf version {
+ type string;
+ }
+ }
+ }
+
+ grouping host-epa {
+ container host-epa {
+ description "Specifies the host level EPA attributes.";
+ leaf cpu-model {
+ description
+ "Host CPU model. Examples include: SandyBridge,
+ IvyBridge";
+ type enumeration {
+ enum PREFER_WESTMERE;
+ enum REQUIRE_WESTMERE;
+ enum PREFER_SANDYBRIDGE;
+ enum REQUIRE_SANDYBRIDGE;
+ enum PREFER_IVYBRIDGE;
+ enum REQUIRE_IVYBRIDGE;
+ enum PREFER_HASWELL;
+ enum REQUIRE_HASWELL;
+ enum PREFER_BROADWELL;
+ enum REQUIRE_BROADWELL;
+ enum PREFER_NEHALEM;
+ enum REQUIRE_NEHALEM;
+ enum PREFER_PENRYN;
+ enum REQUIRE_PENRYN;
+ enum PREFER_CONROE;
+ enum REQUIRE_CONROE;
+ enum PREFER_CORE2DUO;
+ enum REQUIRE_CORE2DUO;
+ }
+ }
+
+ leaf cpu-arch {
+ description "Host CPU architecture.";
+ type enumeration {
+ enum PREFER_X86;
+ enum REQUIRE_X86;
+ enum PREFER_X86_64;
+ enum REQUIRE_X86_64;
+ enum PREFER_I686;
+ enum REQUIRE_I686;
+ enum PREFER_IA64;
+ enum REQUIRE_IA64;
+ enum PREFER_ARMV7;
+ enum REQUIRE_ARMV7;
+ enum PREFER_ARMV8;
+ enum REQUIRE_ARMV8;
+ }
+ }
+
+ leaf cpu-vendor {
+ description "Host CPU Vendor.";
+ type enumeration {
+ enum PREFER_INTEL;
+ enum REQUIRE_INTEL;
+ enum PREFER_AMD;
+ enum REQUIRE_AMD;
+ }
+ }
+
+ leaf cpu-socket-count {
+ description "Number of sockets on the host.";
+ type uint64;
+ }
+
+ leaf cpu-core-count {
+ description "Number of cores on the host.";
+ type uint64;
+ }
+
+ leaf cpu-core-thread-count {
+ description "Number of threads per cores on the host.";
+ type uint64;
+ }
+
+ leaf-list cpu-feature {
+ description
+ "List of CPU features.";
+ type cpu-feature-type;
+ }
+
+
+ leaf om-cpu-model-string {
+ description "Openmano CPU model string";
+ type string;
+ }
+
+ leaf-list om-cpu-feature {
+ description "Openmano CPU features";
+ type string;
+ }
+ }
+ }
+
+ grouping guest-epa {
+ description "EPA attributes for the guest";
+ container guest-epa {
+ leaf trusted-execution {
+ description "This VM should be allocated from trusted pool";
+ type boolean;
+ }
+
+ leaf mempage-size {
+ description
+ "Memory page allocation size. If a VM requires
+ hugepages, it should choose LARGE or SIZE_2MB
+ or SIZE_1GB. If the VM prefers hugepages it
+ should chose PREFER_LARGE.
+ LARGE : Require hugepages (either 2MB or 1GB)
+ SMALL : Doesn't require hugepages
+ SIZE_2MB : Requires 2MB hugepages
+ SIZE_1GB : Requires 1GB hugepages
+ PREFER_LARGE : Application perfers hugepages";
+ type enumeration {
+ enum LARGE;
+ enum SMALL;
+ enum SIZE_2MB;
+ enum SIZE_1GB;
+ enum PREFER_LARGE;
+ }
+ }
+
+ leaf cpu-pinning-policy {
+ description
+ "CPU pinning policy describes association
+ between virtual CPUs in guest and the
+ physical CPUs in the host.
+ DEDICATED : Virtual CPUs are pinned to
+ physical CPUs
+ SHARED : Multiple VMs may share the
+ same physical CPUs.
+ ANY : Any policy is acceptable for the VM";
+ type enumeration {
+ enum DEDICATED;
+ enum SHARED;
+ enum ANY;
+ }
+ default "ANY";
+ }
+
+ leaf cpu-thread-pinning-policy {
+ description
+ "CPU thread pinning policy describes how to
+ place the guest CPUs when the host supports
+ hyper threads:
+ AVOID : Avoids placing a guest on a host
+ with threads.
+ SEPARATE: Places vCPUs on separate cores,
+ and avoids placing two vCPUs on
+ two threads of same core.
+ ISOLATE : Places each vCPU on a different core,
+ and places no vCPUs from a different
+ guest on the same core.
+ PREFER : Attempts to place vCPUs on threads
+ of the same core.";
+ type enumeration {
+ enum AVOID;
+ enum SEPARATE;
+ enum ISOLATE;
+ enum PREFER;
+ }
+ }
+
+ list pcie-device {
+ description
+ "List of pcie passthrough devices.";
+ key device-id;
+ leaf device-id {
+ description
+ "Device identifier.";
+ type string;
+ }
+ leaf count {
+ description
+ "Number of devices to attach to the VM.";
+ type uint64;
+ }
+ }
+
+ choice numa-policy {
+ case numa-unware {
+ leaf numa-unware {
+ type empty;
+ }
+ }
+
+ case numa-aware {
+ container numa-node-policy {
+ description
+ "This policy defines numa topology of the
+ guest. Specifically identifies if the guest
+ should be run on a host with one numa
+ node or multiple numa nodes. As an example
+ a guest may want 8 vcpus and 4 GB of
+ memory. But may want the vcpus and memory
+ distributed across multiple numa nodes.
+ The NUMA node 1 may run with 6 vcpus and
+ 3GB, and NUMA node 2 may run with 2 vcpus
+ and 1GB.";
+
+ leaf node-cnt {
+ description
+ "The number of numa nodes to expose to the VM.";
+ type uint16;
+ }
+
+ leaf mem-policy {
+ description
+ "This policy specifies how the memory should
+ be allocated in a multi-node scenario.
+ STRICT : The memory must be allocated
+ strictly from the memory attached
+ to the NUMA node.
+ PREFERRED : The memory should be allocated
+ perferentially from the memory
+ attached to the NUMA node";
+ type enumeration {
+ enum STRICT;
+ enum PREFERRED;
+ }
+ }
+
+ list node {
+ key id;
+ leaf id {
+ description
+ "NUMA node identification. Typically
+ it's 0 or 1";
+ type uint64;
+ }
+
+ leaf-list vcpu {
+ description
+ "List of vcpus to allocate on
+ this numa node.";
+ type uint64;
+ }
+
+ leaf memory-mb {
+ description
+ "Memory size expressed in MB
+ for this NUMA node.";
+ type uint64;
+ }
+
+ choice om-numa-type {
+ description
+ "Openmano Numa type selection";
+
+ case cores {
+ leaf num-cores {
+ type uint8;
+ }
+ }
+
+ case paired-threads {
+ container paired-threads {
+ leaf num-paired-threads {
+ type uint8;
+ }
+
+ list paired-thread-ids {
+ description
+ "List of thread pairs to use in case of paired-thread numa";
+ max-elements 16;
+ key thread-a;
+
+ leaf thread-a {
+ type uint8;
+ }
+
+ leaf thread-b {
+ type uint8;
+ }
+ }
+ }
+ }
+ case threads {
+ leaf num-threads {
+ type uint8;
+ }
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ grouping provider-network {
+ container provider-network {
+ description "Container for the provider network.";
+ leaf physical-network {
+ description
+ "Name of the phsyical network on which the provider
+ network is built.";
+ type string;
+ }
+
+ leaf overlay-type {
+ description
+ "Type of the overlay network.";
+ type enumeration {
+ enum LOCAL;
+ enum FLAT;
+ enum VLAN;
+ enum VXLAN;
+ enum GRE;
+ }
+ }
+ leaf segmentation_id {
+ description
+ "Segmentation ID";
+ type uint32;
+ }
+ }
+ }
+
+ grouping ns-service-primitive {
+ list service-primitive {
+ description
+ "Network service level service primitives.";
+
+ key "name";
+
+ leaf name {
+ description
+ "Name of the service primitive.";
+ type string;
+ }
+
+ list parameter {
+ description
+ "List of parameters for the service primitive.";
+
+ key "name";
+ uses manotypes:primitive-parameter;
+ }
+
+ list parameter-group {
+ description
+ "Grouping of parameters which are logically grouped in UI";
+ key "name";
+
+ leaf name {
+ description
+ "Name of the parameter group";
+ type string;
+ }
+
+ list parameter {
+ description
+ "List of parameters for the service primitive.";
+ key "name";
+ uses manotypes:primitive-parameter;
+ }
+
+ leaf mandatory {
+ description "Is this parameter group mandatory";
+ type boolean;
+ default true;
+ }
+ }
+
+ list vnf-primitive-group {
+ description
+ "List of service primitives grouped by VNF.";
+
+ key "member-vnf-index-ref";
+ leaf member-vnf-index-ref {
+ description
+ "Reference to member-vnf within constituent-vnfds";
+ type uint64;
+ }
+
+ leaf vnfd-id-ref {
+ description
+ "A reference to a vnfd. This is a
+ leafref to path:
+ ../../../../nsd:constituent-vnfd
+ + [nsd:id = current()/../nsd:id-ref]
+ + /nsd:vnfd-id-ref
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
+
+ type string;
+ }
+
+ leaf vnfd-name {
+ description
+ "Name of the VNFD";
+ type string;
+ }
+
+ list primitive {
+ key "index";
+
+ leaf index {
+ description "Index of this primitive";
+ type uint32;
+ }
+
+ leaf name {
+ description "Name of the primitive in the VNF primitive ";
+ type string;
+ }
+ }
+ }
+
+ leaf user-defined-script {
+ description
+ "A user defined script.";
+ type string;
+ }
+ }
+ }
+
+ grouping monitoring-param {
+ list http-endpoint {
+ description
+ "List of http endpoints to be used by monitoring params";
+ key path;
+
+ leaf path {
+ description "The HTTP path on the management server";
+ type string;
+ }
+
+ leaf https {
+ description "Pick HTTPS instead of HTTP , Default is false";
+ type boolean;
+ default "false";
+ }
+
+ leaf port {
+ description "The HTTP port to connect to";
+ type inet:port-number;
+ }
+
+ leaf username {
+ description "The HTTP basic auth username";
+ type string;
+ }
+
+ leaf password {
+ description "The HTTP basic auth password";
+ type string;
+ }
+
+ leaf polling_interval_secs {
+ description "The HTTP polling interval in seconds";
+ type uint8;
+ default 2;
+ }
+
+ leaf method {
+ description
+ "This is the method to be performed at the uri.
+ GET by default for action";
+
+ type manotypes:http-method;
+ default "GET";
+ }
+
+ list headers {
+ description "Custom HTTP headers to put on HTTP request";
+ key key;
+ leaf key{
+ description "HTTP header key";
+ type string;
+ }
+
+ leaf value{
+ description "HTTP header value";
+ type string;
+ }
+ }
+ }
+
+ list monitoring-param {
+ description
+ "List of monitoring parameters at the NS level";
+ key id;
+ leaf id {
+ type string;
+ }
+
+ leaf name {
+ type string;
+ }
+
+ leaf http-endpoint-ref {
+ type leafref {
+ path "../../http-endpoint/path";
+ }
+ }
+
+ leaf json-query-method {
+ type json-query-method;
+ default "NAMEKEY";
+ }
+
+ container json-query-params {
+ leaf json-path {
+ description
+ "The jsonpath to use to extract value from JSON structure";
+ type string;
+ }
+ leaf object-path {
+ description
+ "The objectpath to use to extract value from JSON structure";
+ type string;
+ }
+ }
+
+ uses monitoring-param-ui-data;
+ uses monitoring-param-value;
+
+ }
+ }
+
+ grouping monitoring-param-aggregation {
+ typedef aggregation-type {
+ description "aggregation-type";
+ type enumeration {
+ enum AVERAGE;
+ enum MINIMUM;
+ enum MAXIMUM;
+ enum COUNT;
+ enum SUM;
+ }
+ }
+
+ leaf aggregation-type {
+ type aggregation-type;
+ }
+ }
+
+ grouping monitoring-param-ui-data {
+ leaf description {
+ type string;
+ }
+
+ leaf group-tag {
+ description "A simple tag to group monitoring parameters";
+ type string;
+ }
+
+
+ leaf widget-type {
+ type manotypes:widget-type;
+ }
+
+ leaf units {
+ type string;
+ }
+ }
+
+ grouping monitoring-param-value {
+ leaf value-type {
+ type param-value-type;
+ default "INT";
+ }
+
+ container numeric-constraints {
+ leaf min-value {
+ description
+ "Minimum value for the parameter";
+ type uint64;
+ }
+ leaf max-value {
+ description
+ "Maxium value for the parameter";
+ type uint64;
+ }
+ }
+
+ container text-constraints {
+ leaf min-length {
+ description
+ "Minimum string length for the parameter";
+ type uint8;
+ }
+ leaf max-length {
+ description
+ "Maximum string length for the parameter";
+ type uint8;
+ }
+ }
+
+ leaf value-integer {
+ description
+ "Current value for an integer parameter";
+ type int64;
+ }
+
+ leaf value-decimal {
+ description
+ "Current value for a decimal parameter";
+ type decimal64 {
+ fraction-digits 4;
+ }
+ }
+
+ leaf value-string {
+ description
+ "Current value for a string parameter";
+ type string;
+ }
+ }
+
+ grouping control-param {
+ list control-param {
+ description
+ "List of control parameters to manage and
+ update the running configuration of the VNF";
+ key id;
+
+ leaf id {
+ type string;
+ }
+
+ leaf name {
+ type string;
+ }
+
+ leaf description {
+ type string;
+ }
+
+ leaf group-tag {
+ description "A simple tag to group control parameters";
+ type string;
+ }
+
+ leaf min-value {
+ description
+ "Minimum value for the parameter";
+ type uint64;
+ }
+
+ leaf max-value {
+ description
+ "Maxium value for the parameter";
+ type uint64;
+ }
+
+ leaf current-value {
+ description
+ "Current value for the parameter";
+ type uint64;
+ }
+
+ leaf step-value {
+ description
+ "Step value for the parameter";
+ type uint64;
+ }
+
+ leaf units {
+ type string;
+ }
+
+ leaf widget-type {
+ type manotypes:widget-type;
+ }
+
+ leaf url {
+ description
+ "This is the URL where to perform the operation";
+
+ type inet:uri;
+ }
+
+ leaf method {
+ description
+ "This is the method to be performed at the uri.
+ POST by default for action";
+
+ type manotypes:http-method;
+ default "POST";
+ }
+
+ leaf payload {
+ description
+ "This is the operation payload or payload template as stringified
+ JSON. This field provides the data to be sent for this operation
+ call";
+
+ type string;
+ }
+ }
+ }
+
+ grouping action-param {
+ list action-param {
+ description
+ "List of action parameters to
+ control VNF";
+ key id;
+ leaf id {
+ type string;
+ }
+
+ leaf name {
+ type string;
+ }
+
+ leaf description {
+ type string;
+ }
+
+ leaf group-tag {
+ description "A simple tag to group monitoring parameter";
+ type string;
+ }
+
+ leaf url {
+ description
+ "This is the URL where to perform the operation";
+ type inet:uri;
+ }
+
+ leaf method {
+ description
+ "This is the method to be performed at the uri.
+ POST by default for action";
+
+ type manotypes:http-method;
+ default "POST";
+ }
+
+ leaf payload {
+ description
+ "This is the operation payload or payload template to be sent in
+ the data for this operation call";
+
+ type string;
+ }
+ }
+ }
+
+ grouping input-parameter {
+ description "";
+
+ list input-parameter {
+ description
+ "List of input parameters";
+
+ key xpath;
+
+
+ leaf xpath {
+ description
+ "A an xpath that specfies which element in a descriptor is to be
+ modified.";
+ type string;
+ }
+
+ leaf value {
+ description
+ "The value that the element specified by the xpath should take when a
+ record is created.";
+ type string;
+ }
+ }
+ }
+
+ grouping input-parameter-xpath {
+ list input-parameter-xpath {
+ description
+ "List of xpaths to parameters inside the NSD
+ the can be customized during the instantiation.";
+
+ key "xpath";
+ leaf xpath {
+ description
+ "An xpath that specifies the element in a descriptor.";
+ type string;
+ }
+
+ leaf label {
+ description "A descriptive string";
+ type string;
+ }
+
+ leaf default-value {
+ description " A default value for this input parameter";
+ type string;
+ }
+ }
+ }
+
+ grouping nfvi-metrics {
+ container vcpu {
+ leaf label {
+ description
+ "Label to show in UI";
+ type string;
+ default "VCPU";
+ }
+
+ leaf total {
+ description
+ "The total number of VCPUs available.";
+ type uint64;
+ }
+
+ leaf utilization {
+ description
+ "The VCPU utilization (percentage).";
+ type decimal64 {
+ fraction-digits 2;
+ range "0 .. 100";
+ }
+ }
+ }
+
+ container memory {
+ leaf label {
+ description
+ "Label to show in UI";
+ type string;
+ default "MEMORY";
+ }
+
+ leaf used {
+ description
+ "The amount of memory (bytes) currently in use.";
+ type uint64;
+ }
+
+ leaf total {
+ description
+ "The amount of memory (bytes) available.";
+ type uint64;
+ }
+
+ leaf utilization {
+ description
+ "The memory utilization (percentage).";
+ type decimal64 {
+ fraction-digits 2;
+ range "0 .. 100";
+ }
+ }
+ }
+
+ container storage {
+ leaf label {
+ description
+ "Label to show in UI";
+ type string;
+ default "STORAGE";
+ }
+
+ leaf used {
+ description
+ "The amount of storage (bytes) currently in use.";
+ type uint64;
+ }
+
+ leaf total {
+ description
+ "The amount of storage (bytes) available.";
+ type uint64;
+ }
+
+ leaf utilization {
+ description
+ "The storage utilization (percentage).";
+ type decimal64 {
+ fraction-digits 2;
+ range "0 .. 100";
+ }
+ }
+ }
+
+ container external-ports {
+ leaf label {
+ description
+ "Label to show in UI";
+ type string;
+ default "EXTERNAL PORTS";
+ }
+
+ leaf total {
+ description
+ "The total number of external ports.";
+ type uint64;
+ }
+ }
+
+ container internal-ports {
+ leaf label {
+ description
+ "Label to show in UI";
+ type string;
+ default "INTERNAL PORTS";
+ }
+
+ leaf total {
+ description
+ "The total number of internal ports.";
+ type uint64;
+ }
+ }
+
+ container network {
+ leaf label {
+ description
+ "Label to show in UI";
+ type string;
+ default "NETWORK TRAFFIC";
+ }
+
+ container incoming {
+ leaf label {
+ description
+ "Label to show in UI";
+ type string;
+ default "INCOMING NETWORK TRAFFIC";
+ }
+
+ leaf bytes {
+ description
+ "The cumulative number of incoming bytes.";
+ type uint64;
+ }
+
+ leaf packets {
+ description
+ "The cumulative number of incoming packets.";
+ type uint64;
+ }
+
+ leaf byte-rate {
+ description
+ "The current incoming byte-rate (bytes per second).";
+ type decimal64 {
+ fraction-digits 2;
+ }
+ }
+
+ leaf packet-rate {
+ description
+ "The current incoming packet (packets per second).";
+ type decimal64 {
+ fraction-digits 2;
+ }
+ }
+ }
+
+ container outgoing {
+ leaf label {
+ description
+ "Label to show in UI";
+ type string;
+ default "OUTGOING NETWORK TRAFFIC";
+ }
+
+ leaf bytes {
+ description
+ "The cumulative number of outgoing bytes.";
+ type uint64;
+ }
+
+ leaf packets {
+ description
+ "The cumulative number of outgoing packets.";
+ type uint64;
+ }
+
+ leaf byte-rate {
+ description
+ "The current outgoing byte-rate (bytes per second).";
+ type decimal64 {
+ fraction-digits 2;
+ }
+ }
+
+ leaf packet-rate {
+ description
+ "The current outgoing packet (packets per second).";
+ type decimal64 {
+ fraction-digits 2;
+ }
+ }
+ }
+ }
+ }
+
+ typedef alarm-severity-type {
+ description "An indication of the importance or ugency of the alarm";
+ type enumeration {
+ enum LOW;
+ enum MODERATE;
+ enum CRITICAL;
+ }
+ }
+
+ typedef alarm-metric-type {
+ description "The type of metrics to register the alarm for";
+ type enumeration {
+ enum CPU_UTILIZATION;
+ enum MEMORY_UTILIZATION;
+ enum STORAGE_UTILIZATION;
+ }
+ }
+
+ typedef alarm-statistic-type {
+ description
+ "The type of statistic to used to measure a metric to determine
+ threshold crossing for an alarm.";
+ type enumeration {
+ enum AVERAGE;
+ enum MINIMUM;
+ enum MAXIMUM;
+ enum COUNT;
+ enum SUM;
+ }
+ }
+
+ typedef alarm-operation-type {
+ description
+ "The relational operator used to define whether an alarm should be
+ triggered when, say, the metric statistic goes above or below a
+ specified value.";
+ type enumeration {
+ enum GE; // greater than or equal
+ enum LE; // less than or equal
+ enum GT; // greater than
+ enum LT; // less than
+ enum EQ; // equal
+ }
+ }
+
+ grouping alarm {
+ leaf alarm-id {
+ description
+ "This field is reserved for the identifier assigned by the cloud
+ provider";
+
+ type string;
+ }
+
+ leaf name {
+ description "A human readable string to identify the alarm";
+ type string;
+ }
+
+ leaf description {
+ description "A string containing a description of this alarm";
+ type string;
+ }
+
+ leaf vdur-id {
+ description
+ "The identifier of the VDUR that the alarm is associated with";
+ type string;
+ }
+
+ container actions {
+ list ok {
+ key "url";
+ leaf url {
+ type string;
+ }
+ }
+
+ list insufficient-data {
+ key "url";
+ leaf url {
+ type string;
+ }
+ }
+
+ list alarm {
+ key "url";
+ leaf url {
+ type string;
+ }
+ }
+ }
+
+ leaf repeat {
+ description
+ "This flag indicates whether the alarm should be repeatedly emitted
+ while the associated threshold has been crossed.";
+
+ type boolean;
+ default true;
+ }
+
+ leaf enabled {
+ description
+ "This flag indicates whether the alarm has been enabled or
+ disabled.";
+
+ type boolean;
+ default true;
+ }
+
+ leaf severity {
+ description "A measure of the important or urgency of the alarm";
+ type alarm-severity-type;
+ }
+
+ leaf metric {
+ description "The metric to be tracked by this alarm.";
+ type alarm-metric-type;
+ }
+
+ leaf statistic {
+ description "The type of metric statistic that is tracked by this alarm";
+ type alarm-statistic-type;
+ }
+
+ leaf operation {
+ description
+ "The relational operator that defines whether the alarm should be
+ triggered when the metric statistic is, say, above or below the
+ specified threshold value.";
+ type alarm-operation-type;
+ }
+
+ leaf value {
+ description
+ "This value defines the threshold that, if crossed, will trigger
+ the alarm.";
+ type decimal64 {
+ fraction-digits 4;
+ }
+ }
+
+ leaf period {
+ description
+ "The period defines the length of time (seconds) that the metric
+ data are collected over in oreder to evaluate the chosen
+ statistic.";
+ type uint32;
+ }
+
+ leaf evaluations {
+ description
+ "This is the number of samples of the metric statistic used to
+ evaluate threshold crossing. Each sample or evaluation is equal to
+ the metric statistic obtained for a given period. This can be used
+ to mitigate spikes in the metric that may skew the statistic of
+ interest.";
+ type uint32;
+ }
+ }
+
+ typedef cloud-account-type {
+ description "cloud account type";
+ type enumeration {
+ enum aws;
+ enum cloudsim;
+ enum cloudsim_proxy;
+ enum mock;
+ enum openmano;
+ enum openstack;
+ enum vsphere;
+ enum openvim;
+ }
+ }
+
+ grouping host-aggregate {
+ list host-aggregate {
+ description "Name of the Host Aggregate";
+ key "metadata-key";
+
+ leaf metadata-key {
+ type string;
+ }
+ leaf metadata-value {
+ type string;
+ }
+ }
+ }
+
+ grouping placement-group-input {
+ leaf cloud-type {
+ type manotypes:cloud-account-type;
+ }
+ choice cloud-provider {
+ case openstack {
+ container availability-zone {
+ description "Name of the Availability Zone";
+ leaf name {
+ type string;
+ }
+ }
+ container server-group {
+ description "Name of the Affinity/Anti-Affinity Server Group";
+ leaf name {
+ type string;
+ }
+ }
+ uses host-aggregate;
+ }
+ case aws {
+ leaf aws-construct {
+ type empty;
+ }
+ }
+ case openmano {
+ leaf openmano-construct {
+ type empty;
+ }
+ }
+ case vsphere {
+ leaf vsphere-construct {
+ type empty;
+ }
+ }
+ case mock {
+ leaf mock-construct {
+ type empty;
+ }
+ }
+ case cloudsim {
+ leaf cloudsim-construct {
+ type empty;
+ }
+ }
+ }
+ }
+
+ grouping placement-group-info {
+ description "";
+
+ leaf name {
+ description
+ "Place group construct to define the compute resource placement strategy
+ in cloud environment";
+ type string;
+ }
+
+ leaf requirement {
+ description "This is free text space used to describe the intent/rationale
+ behind this placement group. This is for human consumption only";
+ type string;
+ }
+
+ leaf strategy {
+ description
+ "Strategy associated with this placement group
+ Following values are possible
+ - COLOCATION: Colocation strategy imply intent to share the physical
+ infrastructure (hypervisor/network) among all members
+ of this group.
+ - ISOLATION: Isolation strategy imply intent to not share the physical
+ infrastructure (hypervisor/network) among the members
+ of this group.
+ ";
+ type enumeration {
+ enum COLOCATION;
+ enum ISOLATION;
+ }
+ default "COLOCATION";
+ }
+ }
+
+ grouping ip-profile-info {
+ description "Grouping for IP-Profile";
+ container ip-profile-params {
+
+ leaf ip-version {
+ type inet:ip-version;
+ default ipv4;
+ }
+
+ leaf subnet-address {
+ description "Subnet IP prefix associated with IP Profile";
+ type inet:ip-prefix;
+ }
+
+ leaf gateway-address {
+ description "IP Address of the default gateway associated with IP Profile";
+ type inet:ip-address;
+ }
+
+ leaf security-group {
+ description "Name of the security group";
+ type string;
+ }
+
+ leaf-list dns-server {
+ description "List of DNS Servers associated with IP Profile";
+ type inet:ip-address;
+ }
+
+ container dhcp-params {
+ leaf enabled {
+ description "This flag indicates if DHCP is enabled or not";
+ type boolean;
+ default true;
+ }
+
+ leaf start-address {
+ description "Start IP address of the IP-Address range associated with DHCP domain";
+ type inet:ip-address;
+ }
+
+ leaf count {
+ description "Size of the DHCP pool associated with DHCP domain";
+ type uint32;
+ }
+ }
+
+ leaf subnet-prefix-pool {
+ description "VIM Specific reference to pre-created subnet prefix";
+ type string;
+ }
+ }
+ }
+
+ grouping ip-profile-list {
+ list ip-profiles {
+ description
+ "List of IP Profiles.
+ IP Profile describes the IP characteristics for the Virtual-Link";
+
+ key "name";
+
+ leaf name {
+ description "Name of the IP-Profile";
+ type string;
+ }
+
+ leaf description {
+ description "Description for IP profile";
+ type string;
+ }
+
+ uses ip-profile-info;
+ }
+ }
+
+}
diff --git a/models/plugins/yang/nsd.yang b/models/plugins/yang/nsd.yang
new file mode 100644
index 0000000..5fffa45
--- /dev/null
+++ b/models/plugins/yang/nsd.yang
@@ -0,0 +1,917 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module nsd
+{
+ namespace "urn:ietf:params:xml:ns:yang:nfvo:nsd";
+ prefix "nsd";
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ import vld {
+ prefix "vld";
+ }
+
+ import vnfd {
+ prefix "vnfd";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ revision 2014-10-27 {
+ description
+ "Initial revision. This YANG file defines
+ the Network Service Descriptor (NSD)";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ typedef scaling-trigger {
+ type enumeration {
+ enum pre-scale-in {
+ value 1;
+ }
+ enum post-scale-in {
+ value 2;
+ }
+ enum pre-scale-out {
+ value 3;
+ }
+ enum post-scale-out {
+ value 4;
+ }
+ }
+ }
+
+ typedef scaling-policy-type {
+ type enumeration {
+ enum manual {
+ value 1;
+ }
+ enum automatic {
+ value 2;
+ }
+ }
+ }
+
+ typedef scaling-criteria-operation {
+ type enumeration {
+ enum AND {
+ value 1;
+ }
+ enum OR {
+ value 2;
+ }
+ }
+ }
+
+ grouping primitive-parameter {
+ leaf name {
+ description
+ "Name of the parameter.";
+ type string;
+ }
+
+ leaf data-type {
+ description
+ "Data type associated with the name.";
+ type manotypes:parameter-data-type;
+ }
+
+ leaf mandatory {
+ description "Is this field mandatory";
+ type boolean;
+ default false;
+ }
+
+ leaf default-value {
+ description "The default value for this field";
+ type string;
+ }
+
+ leaf parameter-pool {
+ description "NSD Parameter pool name to use for this paramter";
+ type string;
+ }
+ }
+
+ grouping ns-initial-config-primitive {
+ leaf seq {
+ description
+ "Sequence number for the configuration primitive.";
+ type uint64;
+ }
+
+ leaf name {
+ description
+ "Name of the configuration primitive.";
+ type string;
+ mandatory "true";
+ }
+
+ leaf user-defined-script {
+ description
+ "A user defined script.";
+ type string;
+ }
+
+ list parameter {
+ key "name";
+ leaf name {
+ type string;
+ }
+
+ leaf value {
+ type string;
+ }
+ }
+ }
+
+ grouping nsd-descriptor {
+ leaf id {
+ description "Identifier for the NSD.";
+ type string;
+ }
+
+ leaf name {
+ description "NSD name.";
+ mandatory true;
+ type string;
+ }
+
+ leaf short-name {
+ description "NSD short name.";
+ type string;
+ }
+
+ leaf vendor {
+ description "Vendor of the NSD.";
+ type string;
+ }
+
+ leaf logo {
+ description
+ "File path for the vendor specific logo. For example icons/mylogo.png.
+ The logo should be part of the network service";
+ type string;
+ }
+
+ leaf description {
+ description "Description of the NSD.";
+ type string;
+ }
+
+ leaf version {
+ description "Version of the NSD";
+ type string;
+ }
+
+ list connection-point {
+ description
+ "List for external connection points.
+ Each NS has one or more external connection
+ points. As the name implies that external
+ connection points are used for connecting
+ the NS to other NS or to external networks.
+ Each NS exposes these connection points to
+ the orchestrator. The orchestrator can
+ construct network service chains by
+ connecting the connection points between
+ different NS.";
+
+ key "name";
+ leaf name {
+ description
+ "Name of the NS connection point.";
+ type string;
+ }
+
+ leaf type {
+ description
+ "Type of the connection point.";
+ type manotypes:connection-point-type;
+ }
+ }
+
+ /* Still having issues modelling this,
+ see the comments under vnfd-connection-point-ref
+ */
+ list vld {
+ description
+ "List of Virtual Link Descriptors.";
+
+ key "id";
+
+ leaf id {
+ description
+ "Identifier for the VLD.";
+ type string;
+ }
+
+ leaf name {
+ description
+ "Virtual Link Descriptor (VLD) name.";
+ type string;
+ }
+
+ leaf short-name {
+ description
+ "Short name for VLD for UI";
+ type string;
+ }
+
+ leaf vendor {
+ description "Provider of the VLD.";
+ type string;
+ }
+
+ leaf description {
+ description "Description of the VLD.";
+ type string;
+ }
+
+ leaf version {
+ description "Version of the VLD";
+ type string;
+ }
+
+ leaf type {
+ type manotypes:virtual-link-type;
+ }
+
+ leaf root-bandwidth {
+ description
+ "For ELAN this is the aggregate bandwidth.";
+ type uint64;
+ }
+
+ leaf leaf-bandwidth {
+ description
+ "For ELAN this is the bandwidth of branches.";
+ type uint64;
+ }
+
+ list vnfd-connection-point-ref {
+ description
+ "A list of references to connection points.";
+ key "member-vnf-index-ref";
+
+ leaf member-vnf-index-ref {
+ description "Reference to member-vnf within constituent-vnfds";
+ type leafref {
+ path "../../../constituent-vnfd/member-vnf-index";
+ }
+ }
+
+ leaf vnfd-id-ref {
+ description
+ "A reference to a vnfd. This is a
+ leafref to path:
+ ../../nsd:constituent-vnfd
+ + [nsd:id = current()/../nsd:id-ref]
+ + /nsd:vnfd-id-ref
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
+ type string;
+ }
+
+ leaf vnfd-connection-point-ref {
+ description
+ "A reference to a connection point name
+ in a vnfd. This is a leafref to path:
+ /vnfd:vnfd-catalog/vnfd:vnfd
+ + [vnfd:id = current()/../nsd:vnfd-id-ref]
+ + /vnfd:connection-point/vnfd:name
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
+ type string;
+ }
+ }
+
+ // replicate for pnfd container here
+ uses manotypes:provider-network;
+
+ choice init-params {
+ description "Extra parameters for VLD instantiation";
+
+ case vim-network-ref {
+ leaf vim-network-name {
+ description
+ "Name of network in VIM account. This is used to indicate
+ pre-provisioned network name in cloud account.";
+ type string;
+ }
+ }
+ case vim-network-profile {
+ leaf ip-profile-ref {
+ description "Named reference to IP-profile object";
+ type string;
+ }
+ }
+ }
+ }
+
+ list constituent-vnfd {
+ description
+ "List of VNFDs that are part of this
+ network service.";
+
+ key "member-vnf-index";
+
+ leaf member-vnf-index {
+ description
+ "Identifier/index for the VNFD. This separate id
+ is required to ensure that multiple VNFs can be
+ part of single NS";
+ type uint64;
+ }
+
+ leaf vnfd-id-ref {
+ description
+ "Identifier for the VNFD.";
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd/vnfd:id";
+ }
+ }
+
+ leaf start-by-default {
+ description
+ "VNFD is started as part of the NS instantiation";
+ type boolean;
+ default true;
+ }
+ }
+
+ list scaling-group-descriptor {
+ description
+ "scaling group descriptor within this network service.
+ The scaling group defines a group of VNFs,
+ and the ratio of VNFs in the network service
+ that is used as target for scaling action";
+
+ key "name";
+
+ leaf name {
+ description "Name of this scaling group.";
+ type string;
+ }
+
+ list scaling-policy {
+
+ key "name";
+
+ leaf name {
+ description
+ "Name of the scaling policy";
+ type string;
+ }
+
+ leaf scaling-type {
+ description
+ "Type of scaling";
+ type scaling-policy-type;
+ }
+
+ leaf enabled {
+ description
+ "Specifies if the scaling policy can be applied";
+ type boolean;
+ default true;
+ }
+
+ leaf scale-in-operation-type {
+ description
+ "Operation to be applied to check between scaling criterias to
+ check if the scale in threshold condition has been met.
+ Defaults to AND";
+ type scaling-criteria-operation;
+ default AND;
+ }
+
+ leaf scale-out-operation-type {
+ description
+ "Operation to be applied to check between scaling criterias to
+ check if the scale out threshold condition has been met.
+ Defauls to OR";
+ type scaling-criteria-operation;
+ default OR;
+ }
+
+ leaf threshold-time {
+ description
+ "The duration for which the criteria must hold true";
+ type uint32;
+ mandatory true;
+ }
+
+ leaf cooldown-time {
+ description
+ "The duration after a scaling-in/scaling-out action has been
+ triggered, for which there will be no further optional";
+ type uint32;
+ mandatory true;
+ }
+
+ list scaling-criteria {
+ description
+ "list of conditions to be met for generating scaling
+ requests";
+ key "name";
+
+ leaf name {
+ type string;
+ }
+
+ leaf scale-in-threshold {
+ description
+ "Value below which scale-in requests are generated";
+ type uint64;
+ }
+
+ leaf scale-out-threshold {
+ description
+ "Value above which scale-out requests are generated";
+ type uint64;
+ }
+
+ leaf ns-monitoring-param-ref {
+ description
+ "Reference to the NS level monitoring parameter
+ that is aggregated";
+ type leafref {
+ path "../../../../monitoring-param/id";
+ }
+ }
+ }
+ }
+
+ list vnfd-member {
+ description "List of VNFs in this scaling group";
+ key "member-vnf-index-ref";
+
+ leaf member-vnf-index-ref {
+ description "member VNF index of this member VNF";
+ type leafref {
+ path "../../../constituent-vnfd/member-vnf-index";
+ }
+ }
+
+ leaf count {
+ description
+ "count of this member VNF within this scaling group.
+ The count allows to define the number of instances
+ when a scaling action targets this scaling group";
+ type uint32;
+ default 1;
+ }
+ }
+
+ leaf min-instance-count {
+ description
+ "Minimum instances of the scaling group which are allowed.
+ These instances are created by default when the network service
+ is instantiated.";
+ type uint32;
+ default 0;
+ }
+
+ leaf max-instance-count {
+ description
+ "Maximum instances of this scaling group that are allowed
+ in a single network service. The network service scaling
+ will fail, when the number of service group instances
+ exceed the max-instance-count specified.";
+ type uint32;
+ default 10;
+ }
+
+ list scaling-config-action {
+ description "List of scaling config actions";
+ key "trigger";
+
+ leaf trigger {
+ description "scaling trigger";
+ type scaling-trigger;
+ }
+
+ leaf ns-config-primitive-name-ref {
+ description "Reference to the NS config name primitive";
+ type leafref {
+ path "../../../service-primitive/name";
+ }
+ }
+ }
+ }
+
+ list placement-groups {
+ description "List of placement groups at NS level";
+
+ key "name";
+ uses manotypes:placement-group-info;
+
+ list member-vnfd {
+ description
+ "List of VNFDs that are part of this placement group";
+
+ key "member-vnf-index-ref";
+
+ leaf member-vnf-index-ref {
+ description "member VNF index of this member VNF";
+ type leafref {
+ path "../../../constituent-vnfd/member-vnf-index";
+ }
+ }
+
+ leaf vnfd-id-ref {
+ description
+ "Identifier for the VNFD.";
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd/vnfd:id";
+ }
+ }
+ }
+ }
+
+ uses manotypes:ip-profile-list;
+
+ list vnf-dependency {
+ description
+ "List of VNF dependencies.";
+ key vnf-source-ref;
+ leaf vnf-source-ref {
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd/vnfd:id";
+ }
+ }
+ leaf vnf-depends-on-ref {
+ description
+ "Reference to VNF that sorce VNF depends.";
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd/vnfd:id";
+ }
+ }
+ }
+
+ list vnffgd {
+ description
+ "List of VNF Forwarding Graph Descriptors (VNFFGD).";
+
+ key "id";
+
+ leaf id {
+ description
+ "Identifier for the VNFFGD.";
+ type string;
+ }
+
+ leaf name {
+ description
+ "VNFFGD name.";
+ type string;
+ }
+
+ leaf short-name {
+ description
+ "Short name for VNFFGD for UI";
+ type string;
+ }
+
+ leaf vendor {
+ description "Provider of the VNFFGD.";
+ type string;
+ }
+
+ leaf description {
+ description "Description of the VNFFGD.";
+ type string;
+ }
+
+ leaf version {
+ description "Version of the VNFFGD";
+ type string;
+ }
+
+ list rsp {
+ description
+ "List of Rendered Service Paths (RSP).";
+
+ key "id";
+
+ leaf id {
+ description
+ "Identifier for the RSP.";
+ type string;
+ }
+
+ leaf name {
+ description
+ "RSP name.";
+ type string;
+ }
+
+ list vnfd-connection-point-ref {
+ description
+ "A list of references to connection points.";
+ key "member-vnf-index-ref";
+
+ leaf member-vnf-index-ref {
+ description "Reference to member-vnf within constituent-vnfds";
+ type leafref {
+ path "../../../../constituent-vnfd/member-vnf-index";
+ }
+ }
+
+ leaf order {
+ type uint8;
+ description
+ "A number that denotes the order of a VNF in a chain";
+ }
+
+ leaf vnfd-id-ref {
+ description
+ "A reference to a vnfd. This is a
+ leafref to path:
+ ../../../../nsd:constituent-vnfd
+ + [nsd:id = current()/../nsd:id-ref]
+ + /nsd:vnfd-id-ref
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
+ type string;
+ }
+
+ leaf vnfd-connection-point-ref {
+ description
+ "A reference to a connection point name
+ in a vnfd. This is a leafref to path:
+ /vnfd:vnfd-catalog/vnfd:vnfd
+ + [vnfd:id = current()/../nsd:vnfd-id-ref]
+ + /vnfd:connection-point/vnfd:name
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
+ type string;
+ }
+ }
+ } //rsp
+
+ list classifier {
+ description
+ "List of classifier rules.";
+
+ key "id";
+
+ leaf id {
+ description
+ "Identifier for the classifier rule.";
+ type string;
+ }
+
+ leaf name {
+ description
+ "Name of the classifier.";
+ type string;
+ }
+
+ leaf rsp-id-ref {
+ description
+ "A reference to the RSP.";
+ type leafref {
+ path "../../rsp/id";
+ }
+ }
+
+ leaf member-vnf-index-ref {
+ description "Reference to member-vnf within constituent-vnfds";
+ type leafref {
+ path "../../../constituent-vnfd/member-vnf-index";
+ }
+ }
+
+ leaf vnfd-id-ref {
+ description
+ "A reference to a vnfd. This is a
+ leafref to path:
+ ../../../nsd:constituent-vnfd
+ + [nsd:id = current()/../nsd:id-ref]
+ + /nsd:vnfd-id-ref
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
+ type string;
+ }
+
+ leaf vnfd-connection-point-ref {
+ description
+ "A reference to a connection point name
+ in a vnfd. This is a leafref to path:
+ /vnfd:vnfd-catalog/vnfd:vnfd
+ + [vnfd:id = current()/../nsd:vnfd-id-ref]
+ + /vnfd:connection-point/vnfd:name
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
+ type string;
+ }
+
+ list match-attributes {
+ description
+ "List of match attributes.";
+
+ key "id";
+
+ leaf id {
+ description
+ "Identifier for the classifier match attribute rule.";
+ type string;
+ }
+
+ leaf ip-proto {
+ description
+ "IP Protocol.";
+ type uint8;
+ }
+
+ leaf source-ip-address {
+ description
+ "Source IP address.";
+ type inet:ip-address;
+ }
+
+ leaf destination-ip-address {
+ description
+ "Destination IP address.";
+ type inet:ip-address;
+ }
+
+ leaf source-port {
+ description
+ "Source port number.";
+ type inet:port-number;
+ }
+
+ leaf destination-port {
+ description
+ "Destination port number.";
+ type inet:port-number;
+ }
+ //TODO: Add more match criteria
+ } //match-attributes
+ } // classifier
+ } // vnffgd
+
+ list monitoring-param {
+ description
+ "List of monitoring parameters from VNF's that should be
+ propogated up into NSR";
+ key "id";
+
+ leaf id {
+ type string;
+ }
+
+ leaf name {
+ type string;
+ }
+
+ uses manotypes:monitoring-param-value;
+ uses manotypes:monitoring-param-ui-data;
+ uses manotypes:monitoring-param-aggregation;
+
+ list vnfd-monitoring-param {
+ description "A list of VNFD monitoring params";
+ key "vnfd-id-ref vnfd-monitoring-param-ref";
+
+ leaf vnfd-id-ref {
+ description
+ "A reference to a vnfd. This is a
+ leafref to path:
+ ../../../../nsd:constituent-vnfd
+ + [nsd:id = current()/../nsd:id-ref]
+ + /nsd:vnfd-id-ref
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resolved this will switched to use
+ leafref";
+
+ type yang:uuid;
+ }
+
+ leaf vnfd-monitoring-param-ref {
+ description "A reference to the VNFD monitoring param";
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd"
+ + "[vnfd:id = current()/../vnfd-id-ref]"
+ + "/vnfd:monitoring-param/vnfd:id";
+ }
+ }
+
+ leaf-list member-vnf-index-ref {
+ description
+ "Optional reference to member-vnf within constituent-vnfds";
+ type uint64;
+ }
+ }
+ }
+
+ uses manotypes:input-parameter-xpath;
+
+ list parameter-pool {
+ description
+ "Pool of parameter values which must be
+ pulled from during configuration";
+ key "name";
+
+ leaf name {
+ description
+ "Name of the configuration value pool";
+ type string;
+ }
+
+ container range {
+ description
+ "Create a range of values to populate the pool with";
+
+ leaf start-value {
+ description
+ "Generated pool values start at this value";
+ type uint32;
+ mandatory true;
+ }
+
+ leaf end-value {
+ description
+ "Generated pool values stop at this value";
+ type uint32;
+ mandatory true;
+ }
+ }
+ }
+
+ uses manotypes:ns-service-primitive;
+
+ list initial-config-primitive {
+ rwpb:msg-new NsdInitialConfigPrimitive;
+ description
+ "Initial set of configuration primitives for NSD.";
+ key "seq";
+
+ uses ns-initial-config-primitive;
+ }
+ }
+
+ container nsd-catalog {
+
+ list nsd {
+ key "id";
+
+ uses nsd-descriptor;
+
+ }
+ }
+
+}
diff --git a/models/plugins/yang/nsr.tailf.yang b/models/plugins/yang/nsr.tailf.yang
new file mode 100644
index 0000000..b68872e
--- /dev/null
+++ b/models/plugins/yang/nsr.tailf.yang
@@ -0,0 +1,52 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module nsr-annotation
+{
+ namespace "http://riftio.com/ns/riftware-1.0/nsr-annotation";
+ prefix "nsr-ann";
+
+ import tailf-common {
+ prefix tailf;
+ }
+
+ import nsr {
+ prefix nsr;
+ }
+
+ tailf:annotate "/nsr:ns-instance-opdata" {
+ tailf:callpoint rw_callpoint;
+ }
+ tailf:annotate "/nsr:exec-ns-service-primitive" {
+ tailf:actionpoint rw_actionpoint;
+ }
+ tailf:annotate "/nsr:exec-scale-out" {
+ tailf:actionpoint rw_actionpoint;
+ }
+ tailf:annotate "/nsr:exec-scale-in" {
+ tailf:actionpoint rw_actionpoint;
+ }
+ tailf:annotate "/nsr:get-ns-service-primitive-values" {
+ tailf:actionpoint rw_actionpoint;
+ }
+ tailf:annotate "/nsr:start-network-service" {
+ tailf:actionpoint rw_actionpoint;
+ }
+}
diff --git a/models/plugins/yang/nsr.yang b/models/plugins/yang/nsr.yang
new file mode 100644
index 0000000..2e12788
--- /dev/null
+++ b/models/plugins/yang/nsr.yang
@@ -0,0 +1,1376 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module nsr
+{
+ namespace "urn:ietf:params:xml:ns:yang:nfvo:nsr";
+ prefix "nsr";
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ import vlr {
+ prefix "vlr";
+ }
+
+ import vld {
+ prefix "vld";
+ }
+
+ import nsd {
+ prefix "nsd";
+ }
+
+ import vnfd {
+ prefix "vnfd";
+ }
+
+ import vnfr {
+ prefix "vnfr";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ import rw-sdn {
+ prefix "rwsdn";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file defines
+ the Network Service Record (NSR)";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ typedef config-states {
+ type enumeration {
+ enum init;
+ enum configuring;
+ enum config_not_needed;
+ enum configured;
+ enum failed;
+ }
+ }
+
+ typedef trigger-type {
+ type enumeration {
+ enum ns-primitive;
+ enum vnf-primitive;
+ }
+ }
+
+ grouping cloud-config {
+ description "List of cloud config parameters";
+
+ list ssh-authorized-key {
+ key "key-pair-ref";
+
+ description "List of authorized ssh keys as part of cloud-config";
+
+ leaf key-pair-ref {
+ description "A reference to the key pair entry in the global key pair table";
+ type leafref {
+ path "/nsr:key-pair/nsr:name";
+ }
+ }
+ }
+ list user {
+ key "name";
+
+ description "List of users to be added through cloud-config";
+ leaf name {
+ description "Name of the user ";
+ type string;
+ }
+ leaf gecos {
+ description "The user name's real name";
+ type string;
+ }
+ leaf passwd {
+ description "The user password";
+ type string;
+ }
+ }
+ }
+
+ list key-pair {
+ key "name";
+ description "Used to configure the list of public keys to be injected as part
+ of ns instantiation";
+ leaf name {
+ description "Name of this key pair";
+ type string;
+ }
+
+ leaf key {
+ description "Key associated with this key pair";
+ type string;
+ }
+ }
+
+ rpc start-network-service {
+ description "Start the network service";
+ input {
+ leaf name {
+ mandatory true;
+ description "Name of the Network Service";
+ type string;
+ }
+ leaf nsd-ref {
+ description "Reference to NSR ID ref";
+ mandatory true;
+ type leafref {
+ path "/nsd:nsd-catalog/nsd:nsd/nsd:id";
+ }
+ }
+ uses ns-instance-config-params;
+ }
+
+ output {
+ leaf nsr-id {
+ description "Automatically generated parameter";
+ type yang:uuid;
+ }
+ }
+ }
+
+ container ns-instance-config {
+
+ list nsr {
+ key "id";
+ unique "name";
+
+ leaf id {
+ description "Identifier for the NSR.";
+ type yang:uuid;
+ }
+
+ leaf name {
+ description "NSR name.";
+ type string;
+ }
+
+ leaf short-name {
+ description "NSR short name.";
+ type string;
+ }
+
+ leaf description {
+ description "NSR description.";
+ type string;
+ }
+
+ leaf admin-status {
+ description
+ "This is the administrative status of the NS instance";
+
+ type enumeration {
+ enum ENABLED;
+ enum DISABLED;
+ }
+ }
+
+ container nsd {
+ description "NS descriptor used to instantiate this NS";
+ uses nsd:nsd-descriptor;
+ }
+
+ uses ns-instance-config-params;
+ }
+ }
+
+ grouping ns-instance-config-params {
+ uses manotypes:input-parameter;
+
+ list scaling-group {
+ description "List of ns scaling group instances";
+ key "scaling-group-name-ref";
+
+ leaf scaling-group-name-ref {
+ description "name of the scaling group
+ leafref path ../../nsd/scaling-group-descriptor/name";
+ type string;
+ }
+
+ list instance {
+ description "The instance of the scaling group";
+ key "id";
+ leaf id {
+ description "Scaling group instance uuid";
+ type uint16;
+ }
+ }
+ }
+
+ list nsd-placement-group-maps {
+ description
+ "Mapping from mano-placement groups construct from NSD to cloud
+ platform placement group construct";
+
+ key "placement-group-ref";
+
+ leaf placement-group-ref {
+ description "Reference for NSD placement group
+ leafref path ../../nsd/placement-groups/name";
+ type string;
+ }
+ uses manotypes:placement-group-input;
+ }
+
+ list vnfd-placement-group-maps {
+ description
+ "Mapping from mano-placement groups construct from VNFD to cloud
+ platform placement group construct";
+
+ key "placement-group-ref vnfd-id-ref";
+
+ leaf vnfd-id-ref {
+ description
+ "A reference to a vnfd. This is a
+ leafref to path:
+ ../../../../nsd:constituent-vnfd
+ + [nsr:id = current()/../nsd:id-ref]
+ + /nsd:vnfd-id-ref
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
+ type yang:uuid;
+ }
+
+ leaf placement-group-ref {
+ description
+ "A reference to VNFD placement group";
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd[vnfd:id = current()/" +
+ "../nsr:vnfd-id-ref]/vnfd:placement-groups/vnfd:name";
+ }
+ }
+
+ uses manotypes:placement-group-input;
+ }
+ uses cloud-config;
+ }
+
+ grouping vnffgr {
+
+ list vnffgr {
+ key "id";
+
+ leaf id {
+ description "Identifier for the VNFFGR.";
+ type yang:uuid;
+ }
+
+ leaf vnffgd-id-ref {
+ description "VNFFG descriptor id reference";
+ type leafref {
+ path "/nsr:ns-instance-config/nsr:nsr"
+ + "[nsr:id=current()/../../ns-instance-config-ref]"
+ + "/nsr:nsd/nsr:vnffgd/nsr:id";
+ }
+ }
+
+ leaf vnffgd-name-ref {
+ description "VNFFG descriptor name reference";
+ type leafref {
+ path "/ns-instance-config/nsr"
+ + "[id=current()/../../ns-instance-config-ref]"
+ + "/nsd/vnffgd[nsr:id = current()/../vnffgd-id-ref]"
+ + "/name";
+ }
+ }
+
+ leaf sdn-account {
+ description
+ "The SDN account to use when requesting resources for
+ this vnffgr";
+ type leafref {
+ path "/rwsdn:sdn-account/rwsdn:name";
+ }
+ }
+
+ leaf operational-status {
+ description
+ "The operational status of the VNFFGR instance
+ init : The VNFFGR has just started.
+ running : The VNFFGR is in running state.
+ terminate : The VNFFGR is being terminated.
+ terminated : The VNFFGR is in the terminated state.
+ failed : The VNFFGR instantiation failed
+ ";
+
+ type enumeration {
+ rwpb:enum-type "VnffgrOperationalStatus";
+ enum init;
+ enum running;
+ enum terminate;
+ enum terminated;
+ enum failed;
+ }
+ }
+
+ list rsp {
+ key "id";
+
+ leaf id {
+ description
+ "Identifier for the RSP.";
+ type yang:uuid;
+ }
+
+ leaf name {
+ description
+ "Name for the RSP";
+ type string;
+ }
+
+ leaf vnffgd-rsp-id-ref {
+ description
+ "Identifier for the VNFFG Descriptor RSP reference";
+ type leafref {
+ path "/ns-instance-config/nsr"
+ + "[id=current()/../../../ns-instance-config-ref]"
+ + "/nsd/vnffgd"
+ + "[id=current()/../../vnffgd-id-ref]"
+ + "/rsp/id";
+ }
+ }
+
+ leaf vnffgd-rsp-name-ref {
+ description
+ "Name for the VNFFG Descriptor RSP reference";
+ type leafref {
+ path "/ns-instance-config/nsr:nsr"
+ + "[id=current()/../../../ns-instance-config-ref]"
+ + "/nsd/vnffgd"
+ + "[id=current()/../../vnffgd-id-ref]"
+ + "/rsp[id=current()/../vnffgd-rsp-id-ref]"
+ + "/name";
+ }
+ }
+
+ leaf classifier-name {
+ type string;
+ }
+
+ leaf path-id {
+ description
+ "Unique Identifier for the service path";
+ type uint32;
+ }
+
+ list vnfr-connection-point-ref {
+ key "hop-number";
+ leaf hop-number {
+ description
+ "Monotonically increasing number to show service path hop
+ order";
+ type uint8;
+ }
+ leaf service-function-type {
+ description
+ "Type of Service Function.
+ NOTE: This needs to map with Service Function Type in ODL to
+ support VNFFG. Service Function Type is manadatory param in ODL
+ SFC. This is temporarily set to string for ease of use";
+ type string;
+ }
+
+ leaf member-vnf-index-ref {
+ type uint64;
+ }
+ leaf vnfd-id-ref {
+ description
+ "Reference to VNF Descriptor Id";
+ type string;
+ }
+ leaf vnfr-id-ref {
+ description
+ "A reference to a vnfr id";
+ type leafref {
+ path "/vnfr:vnfr-catalog/vnfr:vnfr/vnfr:id";
+ }
+ }
+ leaf vnfr-name-ref {
+ description
+ "A reference to a vnfr name";
+ type leafref {
+ path "/vnfr:vnfr-catalog/vnfr:vnfr/vnfr:name";
+ }
+ }
+ leaf vnfr-connection-point-ref {
+ description
+ "A reference to a vnfr connection point.";
+ type leafref {
+ path "/vnfr:vnfr-catalog/vnfr:vnfr"
+ + "[vnfr:id = current()/../nsr:vnfr-id-ref]"
+ + "/vnfr:connection-point/vnfr:name";
+ }
+ }
+ leaf service-index {
+ description
+ "Location within the service path";
+ type uint8;
+ }
+ container connection-point-params {
+ leaf mgmt-address {
+ type inet:ip-address;
+ }
+ leaf name {
+ type string;
+ }
+ leaf port-id {
+ rwpb:field-inline "true";
+ rwpb:field-string-max 64;
+ type string;
+ }
+ leaf vm-id {
+ rwpb:field-inline "true";
+ rwpb:field-string-max 64;
+ type string;
+ }
+ leaf address {
+ type inet:ip-address;
+ }
+ leaf port {
+ type inet:port-number;
+ }
+ }
+
+ container service-function-forwarder {
+ leaf name {
+ description
+ "Service Function Forwarder name";
+ type string;
+ }
+ leaf ip-address {
+ description
+ "Data Plane IP Address of the SFF";
+ type inet:ip-address;
+ }
+ leaf port {
+ description
+ "Data Plane Port of the SFF";
+ type inet:port-number;
+ }
+ }
+ }
+ }
+
+ list classifier {
+ key "id";
+
+ leaf id {
+ description
+ "Identifier for the classifier rule.";
+ type yang:uuid;
+ }
+ leaf name {
+ description
+ "Name of the classifier.";
+ type string;
+ }
+ leaf rsp-id-ref {
+ description
+ "A reference to the RSP.";
+ type leafref {
+ path "../../nsr:rsp/nsr:id";
+ }
+ }
+ leaf rsp-name {
+ description
+ "Name for the RSP";
+ type string;
+ }
+ leaf vnfr-id-ref {
+ description
+ "A reference to a vnfr id";
+ type leafref {
+ path "/vnfr:vnfr-catalog/vnfr:vnfr/vnfr:id";
+ }
+ }
+ leaf vnfr-name-ref {
+ description
+ "A reference to a vnfr name";
+ type leafref {
+ path "/vnfr:vnfr-catalog/vnfr:vnfr/vnfr:name";
+ }
+ }
+ leaf vnfr-connection-point-ref {
+ description
+ "A reference to a vnfr connection point.";
+ type leafref {
+ path "/vnfr:vnfr-catalog/vnfr:vnfr"
+ + "[vnfr:id = current()/../nsr:vnfr-id-ref]"
+ + "/vnfr:connection-point/vnfr:name";
+ }
+ }
+ leaf port-id {
+ rwpb:field-inline "true";
+ rwpb:field-string-max 64;
+ type string;
+ }
+ leaf vm-id {
+ rwpb:field-inline "true";
+ rwpb:field-string-max 64;
+ type string;
+ }
+ leaf ip-address {
+ type string;
+ }
+ leaf sff-name {
+ type string;
+ }
+ }
+ }
+ }
+
+ container ns-instance-opdata {
+ config false;
+
+ list nsr {
+ key "ns-instance-config-ref";
+
+ leaf ns-instance-config-ref {
+ type leafref {
+ path "/nsr:ns-instance-config/nsr:nsr/nsr:id";
+ }
+ }
+
+ leaf name-ref {
+ description "Network service name reference";
+ type leafref {
+ path "/nsr:ns-instance-config/nsr:nsr/nsr:name";
+ }
+ }
+
+ leaf nsd-ref {
+ description "Network service descriptor id reference";
+ type leafref {
+ path "/ns-instance-config/nsr"
+ + "[id=current()/../ns-instance-config-ref]"
+ + "/nsd/id";
+ }
+ }
+
+ leaf nsd-name-ref {
+ description "Network service descriptor name reference";
+ type leafref {
+ path "/ns-instance-config/nsr"
+ + "[id=current()/../ns-instance-config-ref]"
+ + "/nsd/name";
+ }
+ }
+
+ leaf create-time {
+ description
+ "Creation timestamp of this Network Service.
+ The timestamp is expressed as seconds
+ since unix epoch - 1970-01-01T00:00:00Z";
+
+ type uint32;
+ }
+
+ list connection-point {
+ description
+ "List for external connection points.
+ Each NS has one or more external connection points.
+ As the name implies that external connection points
+ are used for connecting the NS to other NS or to
+ external networks. Each NS exposes these connection
+ points to the orchestrator. The orchestrator can
+ construct network service chains by connecting the
+ connection points between different NS.";
+
+ key "name";
+ leaf name {
+ description
+ "Name of the NS connection point.";
+ type string;
+ }
+
+ leaf type {
+ description
+ "Type of the connection point.";
+ type manotypes:connection-point-type;
+ }
+ }
+
+ list vlr {
+ key "vlr-ref";
+ leaf vlr-ref {
+ description
+ "Reference to a VLR record in the VLR catalog";
+ type leafref {
+ path "/vlr:vlr-catalog/vlr:vlr/vlr:id";
+ }
+ }
+
+
+ list vnfr-connection-point-ref {
+ description
+ "A list of references to connection points.";
+ key "vnfr-id";
+
+ leaf vnfr-id {
+ description "A reference to a vnfr";
+ type leafref {
+ path "/vnfr:vnfr-catalog/vnfr:vnfr/vnfr:id";
+ }
+ }
+
+ leaf connection-point {
+ description
+ "A reference to a connection point name in a vnfr";
+ type leafref {
+ path "/vnfr:vnfr-catalog/vnfr:vnfr"
+ + "[vnfr:id = current()/../nsr:vnfr-id]"
+ + "/vnfr:connection-point/vnfr:name";
+ }
+ }
+ }
+ }
+
+ list constituent-vnfr-ref {
+ description
+ "List of VNFRs that are part of this
+ network service.";
+ key "vnfr-id";
+
+ leaf vnfr-id {
+ description
+ "Reference to the VNFR id
+ This should be a leafref to /vnfr:vnfr-catalog/vnfr:vnfr/vnfr:id
+ But due to confd bug (RIFT-9451), changing to string.
+ ";
+ type string;
+ }
+ }
+
+ list scaling-group-record {
+ description "List of scaling group records";
+ key "scaling-group-name-ref";
+
+ leaf scaling-group-name-ref {
+ description "name of the scaling group";
+ type leafref {
+ path "/ns-instance-config/nsr"
+ + "[id=current()/../../ns-instance-config-ref]"
+ + "/nsd/scaling-group-descriptor/name";
+ }
+ }
+
+ list instance {
+ description "Reference to scaling group instance record";
+ key "instance-id";
+ leaf instance-id {
+ description "Scaling group instance id";
+ type uint16;
+ }
+
+ leaf is-default {
+ description "Flag indicating whether this instance was part of
+ default scaling group (and thus undeletable)";
+ type boolean;
+ }
+
+ leaf op-status {
+ description
+ "The operational status of the NS instance
+ init : The scaling group has just started.
+ vnf-init-phase : The VNFs in the scaling group are being instantiated.
+ running : The scaling group is in running state.
+ terminate : The scaling group is being terminated.
+ vnf-terminate-phase : The VNFs in the scaling group are being terminated.
+ terminated : The scaling group is in the terminated state.
+ failed : The scaling group instantiation failed.
+ ";
+
+ type enumeration {
+ enum init;
+ enum vnf-init-phase;
+ enum running;
+ enum terminate;
+ enum vnf-terminate-phase;
+ enum terminated;
+ enum failed;
+ }
+ }
+
+ leaf config-status {
+ description
+ "The configuration status of the scaling group instance
+ configuring : At least one of the VNFs in this scaling group instance
+ is in configuring state
+ configured : All the VNFs in this scaling group instance are
+ configured or config-not-needed state
+ failed : Configuring this scaling group instance failed
+ ";
+ type config-states;
+ }
+
+ leaf error-msg {
+ description
+ "Reason for failure in configuration of this scaling instance";
+ type string;
+ }
+
+ leaf create-time {
+ description
+ "Creation timestamp of this scaling group record.
+ The timestamp is expressed as seconds
+ since unix epoch - 1970-01-01T00:00:00Z";
+
+ type uint32;
+ }
+
+ leaf-list vnfrs {
+ description "Reference to VNFR within the scale instance";
+ type leafref {
+ path "../../../constituent-vnfr-ref/vnfr-id";
+ }
+ }
+ }
+ }
+
+ uses vnffgr;
+
+ leaf operational-status {
+ description
+ "The operational status of the NS instance
+ init : The network service has just started.
+ vl-init-phase : The VLs in the NS are being instantiated.
+ vnf-init-phase : The VNFs in the NS are being instantiated.
+ running : The NS is in running state.
+ terminate : The NS is being terminated.
+ vnf-terminate-phase : The NS is terminating the VNFs in the NS.
+ vl-terminate-phase : The NS is terminating the VLs in the NS.
+ terminated : The NS is in the terminated state.
+ failed : The NS instantiation failed.
+ scaling-out : The NS is scaling out
+ scaling-in : The NS is scaling in
+ vl-instantiate : The NS is initiating a new VL
+ vl-terminate : The NS is terminating a VL
+ ";
+
+ type enumeration {
+ enum init;
+ enum vl-init-phase;
+ enum vnf-init-phase;
+ enum running;
+ enum terminate;
+ enum vnf-terminate-phase;
+ enum vl-terminate-phase;
+ enum terminated;
+ enum failed;
+ enum scaling-out;
+ enum scaling-in;
+ enum vl-instantiate;
+ enum vl-terminate;
+ }
+ }
+
+ leaf config-status {
+ description
+ "The configuration status of the NS instance
+ configuring: At least one of the VNFs in this instance is in configuring state
+ configured: All the VNFs in this NS instance are configured or config-not-needed state
+ ";
+ type config-states;
+ }
+
+ uses manotypes:ns-service-primitive;
+
+ list initial-config-primitive {
+ rwpb:msg-new NsrInitialConfigPrimitive;
+ description
+ "Initial set of configuration primitives for NSD.";
+ key "seq";
+ leaf seq {
+ description
+ "Sequence number for the configuration primitive.";
+ type uint64;
+ }
+
+ leaf name {
+ description
+ "Name of the configuration primitive.";
+ type string;
+ mandatory "true";
+ }
+
+ leaf user-defined-script {
+ description
+ "A user defined script.";
+ type string;
+ }
+
+ list parameter {
+ key "name";
+ leaf name {
+ type string;
+ }
+
+ leaf value {
+ type string;
+ }
+ }
+ }
+
+
+ list monitoring-param {
+ description
+ "List of NS level params.";
+ key "id";
+
+ uses manotypes:monitoring-param-value;
+ uses manotypes:monitoring-param-ui-data;
+ uses manotypes:monitoring-param-aggregation;
+
+ leaf id {
+ type string;
+ }
+
+ leaf name {
+ type string;
+ }
+
+ leaf nsd-mon-param-ref {
+ description "Reference to the NSD monitoring param descriptor
+ that produced this result";
+ type leafref {
+ path "/nsd:nsd-catalog/nsd:nsd[nsd:id = current()/" +
+ "../../nsr:nsd-ref]/nsd:monitoring-param/nsd:id";
+ }
+ }
+
+ list vnfr-mon-param-ref {
+ description "A list of VNFR monitoring params associated with this monp";
+ key "vnfr-id-ref vnfr-mon-param-ref";
+
+ leaf vnfr-id-ref {
+ description
+ "A reference to a vnfr. This is a
+ leafref to path:
+ /vnfr:vnfr-catalog/vnfr:vnfr/vnfr:id";
+
+ type yang:uuid;
+ }
+
+ leaf vnfr-mon-param-ref {
+ description "A reference to the VNFR monitoring param";
+ type leafref {
+ path "/vnfr:vnfr-catalog/vnfr:vnfr"
+ + "[vnfr:id = current()/../nsr:vnfr-id-ref]"
+ + "/vnfr:monitoring-param/vnfr:id";
+ }
+ }
+ }
+ }
+
+ list config-agent-job {
+ key "job-id";
+
+ leaf job-id {
+ description "config agent job Identifier for the NS.";
+ type uint64;
+ }
+
+ leaf job-name {
+ description "Config agent job name";
+ type string;
+ }
+
+ leaf job-status {
+ description
+ "Job status to be set based on each VNF primitive execution,
+ pending - if at least one VNF is in pending state
+ and remaining VNFs are in success state.
+ Success - if all VNF executions are in success state
+ failure - if one of the VNF executions is failure";
+ type enumeration {
+ enum pending;
+ enum success;
+ enum failure;
+ }
+ }
+
+ leaf triggered-by {
+ description "The primitive is triggered from NS or VNF level";
+ type trigger-type;
+ }
+
+ leaf create-time {
+ description
+ "Creation timestamp of this Config Agent Job.
+ The timestamp is expressed as seconds
+ since unix epoch - 1970-01-01T00:00:00Z";
+
+ type uint32;
+ }
+
+ leaf job-status-details {
+ description "Config agent job status details, in case of errors";
+ type string;
+ }
+
+ uses manotypes:primitive-parameter-value;
+
+ list parameter-group {
+ description
+ "List of NS Primitive parameter groups";
+ key "name";
+ leaf name {
+ description
+ "Name of the parameter.";
+ type string;
+ }
+
+ uses manotypes:primitive-parameter-value;
+ }
+
+ list vnfr {
+ key "id";
+ leaf id {
+ description "Identifier for the VNFR.";
+ type yang:uuid;
+ }
+ leaf vnf-job-status {
+ description
+ "Job status to be set based on each VNF primitive execution,
+ pending - if at least one primitive is in pending state
+ and remaining primitives are in success state.
+ Success - if all primitive executions are in success state
+ failure - if one of the primitive executions is failure";
+ type enumeration {
+ enum pending;
+ enum success;
+ enum failure;
+ }
+ }
+
+ list primitive {
+ key "name";
+ leaf name {
+ description "the name of the primitive";
+ type string;
+ }
+
+ uses manotypes:primitive-parameter-value;
+
+ leaf execution-id {
+ description "Execution id of the primitive";
+ type string;
+ }
+ leaf execution-status {
+ description "status of the Execution";
+ type enumeration {
+ enum pending;
+ enum success;
+ enum failure;
+ }
+ }
+ leaf execution-error-details {
+ description "Error details if execution-status is failure";
+ type string;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ rpc get-ns-service-primitive-values {
+ description "Get the service primitive parameter values";
+ input {
+ leaf nsr_id_ref {
+ description "Reference to NSR ID ref";
+ mandatory true;
+ type leafref {
+ path "/nsr:ns-instance-config/nsr:nsr/nsr:id";
+ }
+ }
+
+ leaf name {
+ description "Name of the NS service primitive group";
+ mandatory true;
+ type string;
+ }
+ }
+
+ output {
+ list ns-parameter {
+ description "Automatically generated parameter";
+ key "name";
+
+ leaf name {
+ description "Parameter name which should be pulled from a parameter pool";
+ type string;
+ }
+ leaf value {
+ description "Automatically generated value";
+ type string;
+ }
+ }
+
+ list ns-parameter-group {
+ description "Automatically generated parameters in parameter group";
+ key "name";
+ leaf name {
+ description "Parameter group name";
+ type string;
+ }
+ list parameter {
+ description "Automatically generated group parameter";
+ key "name";
+
+ leaf name {
+ description "Parameter name which should be pulled from a parameter pool";
+ type string;
+ }
+ leaf value {
+ description "Automatically generated value";
+ type string;
+ }
+ }
+ }
+
+ list vnf-primitive-group {
+ description
+ "List of service primitives grouped by VNF.";
+
+ key "member-vnf-index-ref";
+ leaf member-vnf-index-ref {
+ description
+ "Reference to member-vnf within constituent-vnfds";
+ type uint64;
+ }
+
+ leaf vnfd-id-ref {
+ description
+ "A reference to a vnfd. This is a
+ leafref to path:
+ ../../../../nsd:constituent-vnfd
+ + [nsd:id = current()/../nsd:id-ref]
+ + /nsd:vnfd-id-ref
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
+
+ type string;
+ }
+
+ list primitive {
+ key "index";
+ leaf index {
+ description "Index of this primitive";
+ type uint32;
+ }
+
+ leaf name {
+ description "Name of the primitive associated with a value pool";
+ type string;
+ }
+
+ list parameter {
+ description "Automatically generated parameter";
+ key "name";
+
+ leaf name {
+ description "Parameter name which should be pulled from a parameter pool";
+ type string;
+ }
+ leaf value {
+ description "Automatically generated value";
+ type string;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ rpc exec-ns-service-primitive {
+ description "Executes a NS service primitive or script";
+
+ input {
+ leaf name {
+ description "Name of the primitive";
+ type string;
+ }
+
+ leaf nsr_id_ref {
+ description "Reference to NSR ID ref";
+ type leafref {
+ path "/nsr:ns-instance-config/nsr:nsr/nsr:id";
+ }
+ }
+
+ leaf triggered-by {
+ description "The primitive is triggered from NS or VNF level";
+ type trigger-type;
+ default ns-primitive;
+ }
+
+ uses manotypes:primitive-parameter-value;
+
+ list parameter-group {
+ description
+ "List of NS Primitive parameter groups";
+ key "name";
+ leaf name {
+ description
+ "Name of the parameter.";
+ type string;
+ }
+
+ uses manotypes:primitive-parameter-value;
+ }
+
+ list vnf-list {
+ description
+ "List of VNFs whose primitives are being set.";
+ key "member_vnf_index_ref";
+
+ leaf member_vnf_index_ref {
+ description "Member VNF index";
+ type uint64;
+ }
+
+ leaf vnfr-id-ref {
+ description
+ "A reference to a vnfr. This is a
+ leafref to path";
+ type yang:uuid;
+ }
+
+ list vnf-primitive {
+ description
+ "List of service primitives supported by the
+ configuration agent for this VNF.";
+ key "index";
+
+ leaf index {
+ description
+ "index of the service primitive.";
+ type uint32;
+ }
+ leaf name {
+ description
+ "Name of the service primitive.";
+ type string;
+ }
+
+ uses manotypes:primitive-parameter-value;
+ }
+ }
+ leaf user-defined-script {
+ description
+ "A user defined script.";
+ type string;
+ }
+ }
+ output {
+ leaf job-id {
+ description "Job identifier for this RPC";
+ type uint64;
+ }
+
+ leaf name {
+ description "Name of the service primitive";
+ type string;
+ }
+
+ leaf nsr_id_ref {
+ description "Reference to NSR ID ref";
+ type leafref {
+ path "/nsr:ns-instance-config/nsr:nsr/nsr:id";
+ }
+ }
+
+ leaf triggered-by {
+ description "The primitive is triggered from NS or VNF level";
+ type trigger-type;
+ }
+
+ leaf create-time {
+ description
+ "Creation timestamp of this config agent JOB.
+ The timestamp is expressed as seconds
+ since unix epoch - 1970-01-01T00:00:00Z";
+
+ type uint32;
+ }
+
+ leaf job-status-details {
+ description "Job status details, in case of any errors";
+ type string;
+ }
+
+ uses manotypes:primitive-parameter-value;
+
+ list parameter-group {
+ description
+ "List of NS Primitive parameter groups";
+ key "name";
+ leaf name {
+ description
+ "Name of the parameter.";
+ type string;
+ }
+
+ uses manotypes:primitive-parameter-value;
+ }
+
+ list vnf-out-list {
+ description
+ "List of VNFs whose primitives were set.";
+ key "member_vnf_index_ref";
+
+ leaf member_vnf_index_ref {
+ description "Member VNF index";
+ type uint64;
+ }
+ leaf vnfr-id-ref {
+ description
+ "A reference to a vnfr. This is a
+ leafref to path";
+ type yang:uuid;
+ }
+
+ list vnf-out-primitive {
+ description
+ "List of service primitives supported by the
+ configuration agent for this VNF.";
+ key "index";
+
+ leaf index {
+ description
+ "index of the service primitive.";
+ type uint32;
+ }
+
+ leaf name {
+ description
+ "Name of the service primitive.";
+ type string;
+ }
+
+ uses manotypes:primitive-parameter-value;
+
+ leaf execution-id {
+ description "Execution id of this primitive";
+ type string;
+ }
+
+ leaf execution-status {
+ description "Status of the execution of this primitive";
+ type string;
+ }
+
+ leaf execution-error-details {
+ description "Error details if execution-status is failed";
+ type string;
+ }
+ }
+ }
+ }
+ }
+
+ rpc exec-scale-in {
+ description "Executes scale out request";
+
+ input {
+
+ leaf nsr-id-ref {
+ description "Reference to NSR ID ref";
+ type leafref {
+ path "/nsr:ns-instance-config/nsr:nsr/nsr:id";
+ }
+ }
+
+ leaf scaling-group-name-ref {
+ description "name of the scaling group";
+ type string;
+ }
+
+ leaf instance-id {
+ description "id of the scaling group";
+ type uint64;
+ }
+
+
+ }
+ output {
+ leaf instance-id {
+ description "id of the scaling group";
+ type uint64;
+ }
+ }
+ }
+
+ rpc exec-scale-out {
+ description "Executes scale out request";
+
+ input {
+
+ leaf nsr-id-ref {
+ description "Reference to NSR ID ref";
+ type leafref {
+ path "/nsr:ns-instance-config/nsr:nsr/nsr:id";
+ }
+ }
+
+ leaf scaling-group-name-ref {
+ description "name of the scaling group";
+ type string;
+ }
+
+ leaf instance-id {
+ description "id of the scaling group";
+ type uint64;
+ }
+
+ }
+ output {
+ leaf instance-id {
+ description "id of the scaling group";
+ type uint64;
+ }
+ }
+ }
+
+}
diff --git a/models/plugins/yang/odl-network-topology.yang b/models/plugins/yang/odl-network-topology.yang
new file mode 100644
index 0000000..9c7101d
--- /dev/null
+++ b/models/plugins/yang/odl-network-topology.yang
@@ -0,0 +1,359 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module odl-network-topology {
+ yang-version 1;
+ namespace "urn:TBD:params:xml:ns:yang:network-topology";
+ // replace with IANA namespace when assigned
+ prefix "nt";
+
+ import ietf-inet-types { prefix "inet"; }
+
+ organization "TBD";
+
+ contact "WILL-BE-DEFINED-LATER";
+
+ description
+ "This module defines a model for the topology of a network.
+ Key design decisions are as follows:
+ A topology consists of a set of nodes and links.
+ Links are point-to-point and unidirectional.
+ Bidirectional connections need to be represented through
+ two separate links.
+ Multipoint connections, broadcast domains etc can be represented
+ through a hierarchy of nodes, then connecting nodes at
+ upper layers of the hierarchy.";
+
+ revision 2013-10-21 {
+ description
+ "Initial revision.";
+ }
+
+ typedef topology-id {
+ type inet:uri;
+ description
+ "An identifier for a topology.";
+ }
+
+ typedef node-id {
+ type inet:uri;
+ description
+ "An identifier for a node in a topology.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same node in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of node
+ and/or the type of topology that the node is a part of.";
+ }
+
+
+ typedef link-id {
+ type inet:uri;
+ description
+ "An identifier for a link in a topology.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same link in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of link
+ and/or the type of topology that the link is a part of.";
+ }
+
+ typedef tp-id {
+ type inet:uri;
+ description
+ "An identifier for termination points on a node.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same TP in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of TP
+ and/or the type of node and topology that the TP is a part of.";
+ }
+
+ typedef tp-ref {
+ type leafref {
+ path "/network-topology/topology/node/termination-point/tp-id";
+ }
+ description
+ "A type for an absolute reference to a termination point.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+ typedef topology-ref {
+ type leafref {
+ path "/network-topology/topology/topology-id";
+ }
+ description
+ "A type for an absolute reference a topology instance.";
+ }
+
+ typedef node-ref {
+ type leafref {
+ path "/network-topology/topology/node/node-id";
+ }
+ description
+
+ "A type for an absolute reference to a node instance.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+
+ typedef link-ref {
+ type leafref {
+ path "/network-topology/topology/link/link-id";
+ }
+ description
+ "A type for an absolute reference a link instance.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+
+ grouping tp-attributes {
+ description
+ "The data objects needed to define a termination point.
+ (This only includes a single leaf at this point, used
+ to identify the termination point.)
+ Provided in a grouping so that in addition to the datastore,
+ the data can also be included in notifications.";
+ leaf tp-id {
+ type tp-id;
+ }
+ leaf-list tp-ref {
+ type tp-ref;
+ config false;
+ description
+ "The leaf list identifies any termination points that the
+ termination point is dependent on, or maps onto.
+ Those termination points will themselves be contained
+ in a supporting node.
+ This dependency information can be inferred from
+ the dependencies between links. For this reason,
+ this item is not separately configurable. Hence no
+ corresponding constraint needs to be articulated.
+ The corresponding information is simply provided by the
+ implementing system.";
+ }
+ }
+
+ grouping node-attributes {
+ description
+ "The data objects needed to define a node.
+ The objects are provided in a grouping so that in addition to
+ the datastore, the data can also be included in notifications
+ as needed.";
+
+ leaf node-id {
+ type node-id;
+ description
+ "The identifier of a node in the topology.
+ A node is specific to a topology to which it belongs.";
+ }
+ list supporting-node {
+ description
+ "This list defines vertical layering information for nodes.
+ It allows to capture for any given node, which node (or nodes)
+ in the corresponding underlay topology it maps onto.
+ A node can map to zero, one, or more nodes below it;
+ accordingly there can be zero, one, or more elements in the list.
+ If there are specific layering requirements, for example
+ specific to a particular type of topology that only allows
+ for certain layering relationships, the choice
+ below can be augmented with additional cases.
+ A list has been chosen rather than a leaf-list in order
+ to provide room for augmentations, e.g. for
+ statistics or priorization information associated with
+ supporting nodes.";
+ // This is not what was published in the initial draft,
+ // added topology-ref leaf and added it to the key
+ key "topology-ref node-ref";
+ leaf topology-ref {
+ type topology-ref;
+ }
+ leaf node-ref {
+ type node-ref;
+ }
+ }
+ }
+
+ grouping link-attributes {
+ // This is a grouping, not defined inline with the link definition itself,
+ // so it can be included in a notification, if needed
+ leaf link-id {
+ type link-id;
+ description
+ "The identifier of a link in the topology.
+ A link is specific to a topology to which it belongs.";
+ }
+ container source {
+ leaf source-node {
+ mandatory true;
+ type node-ref;
+ description
+ "Source node identifier, must be in same topology.";
+ }
+ leaf source-tp {
+ type tp-ref;
+ description
+ "Termination point within source node that terminates the link.";
+
+ }
+ }
+ container destination {
+ leaf dest-node {
+ mandatory true;
+ type node-ref;
+ description
+ "Destination node identifier, must be in same topology.";
+ }
+ leaf dest-tp {
+ type tp-ref;
+ description
+ "Termination point within destination node that terminates the link.";
+ }
+ }
+ list supporting-link {
+ key "link-ref";
+ leaf link-ref {
+ type link-ref;
+ }
+ }
+ }
+
+
+ container network-topology {
+ list topology {
+ description "
+ This is the model of an abstract topology.
+ A topology contains nodes and links.
+ Each topology MUST be identified by
+ unique topology-id for reason that a network could contain many
+ topologies.
+ ";
+ key "topology-id";
+ leaf topology-id {
+ type topology-id;
+ description "
+ It is presumed that a datastore will contain many topologies. To
+ distinguish between topologies it is vital to have UNIQUE
+ topology identifiers.
+ ";
+ }
+ leaf server-provided {
+ type boolean;
+ config false;
+ description "
+ Indicates whether the topology is configurable by clients,
+ or whether it is provided by the server. This leaf is
+
+ populated by the server implementing the model.
+ It is set to false for topologies that are created by a client;
+ it is set to true otherwise. If it is set to true, any
+ attempt to edit the topology MUST be rejected.
+ ";
+ }
+ container topology-types {
+ description
+ "This container is used to identify the type, or types
+ (as a topology can support several types simultaneously),
+ of the topology.
+ Topology types are the subject of several integrity constraints
+ that an implementing server can validate in order to
+ maintain integrity of the datastore.
+ Topology types are indicated through separate data nodes;
+ the set of topology types is expected to increase over time.
+ To add support for a new topology, an augmenting module
+ needs to augment this container with a new empty optional
+ container to indicate the new topology type.
+ The use of a container allows to indicate a subcategorization
+ of topology types.
+ The container SHALL NOT be augmented with any data nodes
+ that serve a purpose other than identifying a particular
+ topology type.
+ ";
+ }
+ list underlay-topology {
+ key "topology-ref";
+ leaf topology-ref {
+ type topology-ref;
+ }
+ // a list, not a leaf-list, to allow for potential augmentation
+ // with properties specific to the underlay topology,
+ // such as statistics, preferences, or cost.
+ description
+ "Identifies the topology, or topologies, that this topology
+ is dependent on.";
+ }
+
+ list node {
+ description "The list of network nodes defined for the topology.";
+ key "node-id";
+ uses node-attributes;
+ must "boolean(../underlay-topology[*]/node[./supporting-nodes/node-ref])";
+ // This constraint is meant to ensure that a referenced node is in fact
+ // a node in an underlay topology.
+ list termination-point {
+ description
+
+ "A termination point can terminate a link.
+ Depending on the type of topology, a termination point could,
+ for example, refer to a port or an interface.";
+ key "tp-id";
+ uses tp-attributes;
+ }
+ }
+
+ list link {
+ description "
+ A Network Link connects a by Local (Source) node and
+ a Remote (Destination) Network Nodes via a set of the
+ nodes' termination points.
+ As it is possible to have several links between the same
+ source and destination nodes, and as a link could potentially
+ be re-homed between termination points, to ensure that we
+ would always know to distinguish between links, every link
+ is identified by a dedicated link identifier.
+ Note that a link models a point-to-point link, not a multipoint
+ link.
+ Layering dependencies on links in underlay topologies are
+ not represented as the layering information of nodes and of
+ termination points is sufficient.
+ ";
+ key "link-id";
+ uses link-attributes;
+ must "boolean(../underlay-topology/link[./supporting-link])";
+ // Constraint: any supporting link must be part of an underlay topology
+ must "boolean(../node[./source/source-node])";
+ // Constraint: A link must have as source a node of the same topology
+ must "boolean(../node[./destination/dest-node])";
+ // Constraint: A link must have as source a destination of the same topology
+ must "boolean(../node/termination-point[./source/source-tp])";
+ // Constraint: The source termination point must be contained in the source node
+ must "boolean(../node/termination-point[./destination/dest-tp])";
+ // Constraint: The destination termination point must be contained
+ // in the destination node
+ }
+ }
+ }
+}
diff --git a/models/plugins/yang/pnfd.yang b/models/plugins/yang/pnfd.yang
new file mode 100644
index 0000000..e1f39a7
--- /dev/null
+++ b/models/plugins/yang/pnfd.yang
@@ -0,0 +1,104 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module pnfd
+{
+ namespace "urn:ietf:params:xml:ns:yang:nfvo:pnfd";
+ prefix "pnfd";
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file defines
+ the Physical Network Function Descriptor (PNFD)";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ container pnfd-catalog {
+
+ list pnfd {
+ key "id";
+
+ leaf id {
+ description "Identifier for the PNFD.";
+ type yang:uuid;
+ }
+
+ leaf name {
+ description "PNFD name.";
+ type string;
+ }
+
+ leaf short-name {
+ description "PNFD short name.";
+ type string;
+ }
+
+ leaf vendor {
+ description "Vendor of the PNFD.";
+ type string;
+ }
+
+ leaf description {
+ description "Description of the PNFD.";
+ type string;
+ }
+
+ leaf version {
+ description "Version of the PNFD";
+ type string;
+ }
+
+ list connection-point {
+ description
+ "List for external connection points. Each PNF has one or more external
+ connection points.";
+ key "id";
+ leaf id {
+ description
+ "Identifier for the external connection points";
+ type uint64;
+ }
+
+ leaf cp-type {
+ description
+ "Type of the connection point.";
+ type manotypes:connection-point-type;
+ }
+ }
+ }
+ }
+}
diff --git a/models/plugins/yang/rw-nsd.yang b/models/plugins/yang/rw-nsd.yang
new file mode 100644
index 0000000..4475928
--- /dev/null
+++ b/models/plugins/yang/rw-nsd.yang
@@ -0,0 +1,57 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module rw-nsd
+{
+ namespace "http://riftio.com/ns/riftware-1.0/rw-nsd";
+ prefix "rw-nsd";
+
+ import nsd {
+ prefix "nsd";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file augments
+ the base MANO NSD";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ augment /nsd:nsd-catalog/nsd:nsd {
+ uses manotypes:control-param;
+ uses manotypes:action-param;
+ leaf meta {
+ description
+ "Any meta-data needed by the UI";
+ type string;
+ }
+ }
+}
+
+// vim: sw=2
diff --git a/models/plugins/yang/rw-nsr.tailf.yang b/models/plugins/yang/rw-nsr.tailf.yang
new file mode 100644
index 0000000..3b7588a
--- /dev/null
+++ b/models/plugins/yang/rw-nsr.tailf.yang
@@ -0,0 +1,45 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module rw-nsr-annotation
+{
+ namespace "http://riftio.com/ns/riftware-1.0/rw-nsr-annotation";
+ prefix "rw-nsr-ann";
+
+ import tailf-common {
+ prefix tailf;
+ }
+
+ import rw-nsr {
+ prefix rw-nsr;
+ }
+
+ import nsr {
+ prefix nsr;
+ }
+
+ tailf:annotate "/nsr:ns-instance-opdata/nsr:nsr/rw-nsr:operational-events" {
+ tailf:callpoint rw_callpoint;
+ }
+
+ tailf:annotate "/nsr:ns-instance-opdata/rw-nsr:nsd-ref-count" {
+ tailf:callpoint rw_callpoint;
+ }
+}
diff --git a/models/plugins/yang/rw-nsr.yang b/models/plugins/yang/rw-nsr.yang
new file mode 100644
index 0000000..d73e7fa
--- /dev/null
+++ b/models/plugins/yang/rw-nsr.yang
@@ -0,0 +1,461 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module rw-nsr
+{
+ namespace "http://riftio.com/ns/riftware-1.0/rw-nsr";
+ prefix "rw-nsr";
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ import nsr {
+ prefix "nsr";
+ }
+
+ import nsd {
+ prefix "nsd";
+ }
+
+ import rw-cloud {
+ prefix "rw-cloud";
+ }
+
+ import rw-config-agent {
+ prefix "rw-ca";
+ }
+
+ import rw-sdn {
+ prefix "rw-sdn";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file augments
+ the base MANO VNFD";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ grouping operational-events {
+ list operational-events {
+ key "id";
+ description
+ "Recent operational events for this network service.
+ Though the model does not impose any restrictions on the numbe of events,
+ the max operational events will be limited to the most recent 10";
+
+ leaf id {
+ description "The id of the instance";
+ type uint64;
+ }
+
+ leaf timestamp {
+ description
+ "The timestamp of this event expressed as seconds since
+ unix epoch - 1970-01-01T00:00:00Z";
+ type uint32;
+ }
+ leaf event {
+ description "Short description of the event";
+ type string;
+ }
+ leaf description {
+ description
+ "The description of this event";
+ type string;
+ }
+ leaf details {
+ description
+ "The detailed description of this event (in case of errors)";
+ type string;
+ }
+ }
+ }
+
+ grouping nsd-ref-count {
+ list nsd-ref-count {
+ key "nsd-id-ref";
+ description "This table maintains the number of NSRs used by each NSD";
+
+ leaf nsd-id-ref {
+ description "Reference to NSD";
+ type leafref {
+ path "/nsd:nsd-catalog/nsd:nsd/nsd:id";
+ }
+ }
+ leaf instance-ref-count {
+ description
+ "Reference count for the number of NSRs refering this NSD.
+ Every NS record instantiated using this descriptor takes
+ a reference on the NSD and releases the reference when the
+ network service is terminated. This desciptor cannot be
+ deleted when this counter is non zero";
+ type uint64;
+ }
+ }
+ }
+
+ grouping rw-ns-instance-config {
+ leaf cloud-account {
+ description
+ "The configured cloud account which the NSR is instantiated within.
+ All VDU's, Virtual Links, and provider networks will be requested
+ using the cloud-account's associated CAL instance";
+ type leafref {
+ path "/rw-cloud:cloud/rw-cloud:account/rw-cloud:name";
+ }
+ }
+
+ leaf om-datacenter {
+ description
+ "Openmano datacenter name to use when instantiating
+ the network service. This is only used when openmano
+ is selected as the cloud account. This should be superceded
+ by multiple cloud accounts when that becomes available.";
+ type string;
+ }
+
+ list vnf-cloud-account-map {
+ description
+ "Mapping VNF to Cloud Account where VNF will be instantiated";
+
+ key "member-vnf-index-ref";
+ leaf member-vnf-index-ref {
+ type uint64;
+ }
+
+ leaf cloud-account {
+ description
+ "The configured cloud account where VNF is instantiated within.
+ All VDU's, Virtual Links, and provider networks will be requested
+ using the cloud-account's associated CAL instance";
+ type leafref {
+ path "/rw-cloud:cloud/rw-cloud:account/rw-cloud:name";
+ }
+ }
+
+ leaf om-datacenter {
+ description
+ "Openmano datacenter name to use when instantiating
+ the network service. This is only used when openmano
+ is selected as the cloud account. This should be superceded
+ by multiple cloud accounts when that becomes available.";
+ type string;
+ }
+
+ leaf config-agent-account {
+ description
+ "The configured config agent account to use for instantiating this VNF.
+ The configuration for this VNF will be driven using the specified config
+ agent account";
+ type leafref {
+ path "/rw-ca:config-agent/rw-ca:account/rw-ca:name";
+ }
+ }
+ }
+
+ list vl-cloud-account-map {
+ description
+ "Mapping VL to Cloud Account where VL will be instantiated";
+
+ key "vld-id-ref";
+
+ leaf vld-id-ref {
+ description
+ "A reference to a vld.
+ leafref path ../../nsd/vld/id";
+ type string;
+ }
+
+ leaf-list cloud-accounts {
+ description
+ "The configured list of cloud accounts where VL is instantiated.
+ All VDU's, Virtual Links, and provider networks will be requested
+ using the cloud-account's associated CAL instance";
+ type leafref {
+ path "/rw-cloud:cloud/rw-cloud:account/rw-cloud:name";
+ }
+ }
+
+ leaf-list om-datacenters {
+ description
+ "Openmano datacenter names to use when instantiating
+ the VLs. This is only used when openmano
+ is selected as the cloud account. This should be superceded
+ by multiple cloud accounts when that becomes available.";
+ type string;
+ }
+ }
+ }
+
+
+ augment /nsr:ns-instance-config/nsr:nsr {
+ uses rw-ns-instance-config;
+ }
+
+ augment /nsr:start-network-service/nsr:input{
+ uses rw-ns-instance-config;
+ }
+
+ augment /nsr:ns-instance-opdata/nsr:nsr {
+ uses manotypes:action-param;
+ uses manotypes:control-param;
+
+ leaf sdn-account {
+ description
+ "The SDN account associted with the cloud account using which an
+ NS was instantiated.";
+ type leafref {
+ path "/rw-sdn:sdn-account/rw-sdn:name";
+ }
+ }
+
+ leaf config-status-details {
+ description
+ "The configuration status error details of the NS instance, in case of any errors";
+ type string;
+ }
+
+ container nfvi-metrics {
+ container vm {
+ leaf label {
+ description
+ "Label to show in UI";
+ type string;
+ default "VM";
+ }
+
+ leaf active-vm {
+ description
+ "The number of active VMs.";
+ type uint64;
+ }
+
+ leaf inactive-vm {
+ description
+ "The number of inactive VMs.";
+ type uint64;
+ }
+ }
+
+ uses manotypes:nfvi-metrics;
+ }
+
+ container epa-param {
+ container ovs-acceleration {
+ leaf label {
+ description
+ "Label to show in UI for the param";
+ type string;
+ default "OVS ACCELERATION";
+ }
+
+ leaf vm {
+ description
+ "Number of VMs with the EPA attribute";
+ type uint64;
+ }
+
+ leaf unit {
+ description
+ "Unit label to show in the UI";
+ type string;
+ default "vms";
+ }
+ }
+
+ container ovs-offload {
+ leaf label {
+ description
+ "Label to show in UI for the param";
+ type string;
+ default "OVS OFFLOAD";
+ }
+
+ leaf vm {
+ description
+ "Number of VMs with the EPA attribute";
+ type uint64;
+ }
+
+ leaf unit {
+ description
+ "Unit label to show in the UI";
+ type string;
+ default "vms";
+ }
+
+ }
+
+ container ddio {
+ leaf label {
+ description
+ "Label to show in UI for the param";
+ type string;
+ default "DDIO";
+ }
+
+ leaf vm {
+ description
+ "Number of VMs with the EPA attribute";
+ type uint64;
+ }
+
+ leaf unit {
+ description
+ "Unit label to show in the UI";
+ type string;
+ default "vms";
+ }
+
+ }
+
+ container cat {
+ leaf label {
+ description
+ "Label to show in UI for the param";
+ type string;
+ default "CAT";
+ }
+
+ leaf vm {
+ description
+ "Number of VMs with the EPA attribute";
+ type uint64;
+ }
+
+ leaf unit {
+ description
+ "Unit label to show in the UI";
+ type string;
+ default "vms";
+ }
+ }
+
+ container cmt {
+ leaf label {
+ description
+ "Label to show in UI for the param";
+ type string;
+ default "CMT";
+ }
+
+ leaf vm {
+ description
+ "Number of VMs with the EPA attribute";
+ type uint64;
+ }
+
+ leaf unit {
+ description
+ "Unit label to show in the UI";
+ type string;
+ default "vms";
+ }
+
+ }
+ }
+ uses operational-events;
+ }
+
+ augment /nsr:ns-instance-opdata {
+ uses nsd-ref-count;
+ }
+
+ augment /nsr:ns-instance-opdata/nsr:nsr/nsr:vlr {
+ leaf assigned-subnet {
+ description "Subnet added for the VL";
+ type string;
+ }
+ leaf cloud-account {
+ description
+ "The configured cloud account in which the VL is instantiated within.";
+ type leafref {
+ path "/rw-cloud:cloud/rw-cloud:account/rw-cloud:name";
+ }
+ }
+ leaf om-datacenter {
+ description
+ "Openmano datacenter name to use when instantiating
+ the network service. This is only used when openmano
+ is selected as the cloud account. This should be superceded
+ by multiple cloud accounts when that becomes available.";
+ type string;
+ }
+ }
+
+ augment /nsr:ns-instance-opdata/nsr:nsr/nsr:constituent-vnfr-ref {
+ leaf cloud-account {
+ description
+ "The configured cloud account in which the VNF is instantiated within.
+ All VDU's, Virtual Links, and provider networks will be requested
+ using the cloud-account's associated CAL instance";
+ type leafref {
+ path "/rw-cloud:cloud/rw-cloud:account/rw-cloud:name";
+ }
+ }
+ leaf om-datacenter {
+ description
+ "Openmano datacenter name to use when instantiating
+ the network service. This is only used when openmano
+ is selected as the cloud account. This should be superceded
+ by multiple cloud accounts when that becomes available.";
+ type string;
+ }
+ }
+
+ augment /nsr:ns-instance-config {
+ leaf nfvi-polling-period {
+ description
+ "Defines the period (secons) that the NFVI metrics are polled at";
+ type uint64;
+ default 4;
+ }
+ }
+
+ notification nsm-notification {
+ description "Notification for NSM Events.
+ The timestamp of this event is automatically expressed
+ in human readble format - 1970-01-01T00:00:00Z";
+
+ leaf event {
+ description "Short name of the event";
+ type string;
+ }
+
+ leaf description {
+ description "The description of this event";
+ type string;
+ }
+
+ leaf details {
+ description "The detailed description of this event, in case of errors";
+ type string;
+ }
+ }
+}
+
+// vim: sw=2
diff --git a/models/plugins/yang/rw-topology.yang b/models/plugins/yang/rw-topology.yang
new file mode 100644
index 0000000..ff1f2ba
--- /dev/null
+++ b/models/plugins/yang/rw-topology.yang
@@ -0,0 +1,126 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module rw-topology {
+ namespace "http://riftio.com/ns/riftware-1.0/rw-topology";
+ prefix rw-topology;
+
+ import ietf-inet-types {prefix inet;}
+ import ietf-network {prefix nw;}
+ import ietf-network-topology {prefix nt;}
+ import ietf-l2-topology {prefix l2t;}
+
+ revision "2015-10-20" {
+ description "Initial revision of IP level addressing for L2 host topology";
+ }
+
+ grouping ip-address-group {
+ description "IP addresses if present for L2 termination points";
+ container ip-attributes {
+ description "L2 termination points containing IP addresses";
+ list ip-addresses {
+ key ip;
+ leaf ip {
+ type inet:ip-address;
+ description "IPv4 or IPv6 address";
+ }
+ }
+ }
+ } // grouping ip-address-group
+
+
+ grouping rw-network-attributes {
+ description "RW Topology scope attributes";
+ container rw-network-attributes {
+ description "Containing RW network attributes";
+ leaf name {
+ type string;
+ description "Name of the RW Topology network";
+ }
+ leaf sdn-account-name {
+ type string;
+ description "Name of the SDN account from which topology is got";
+ }
+ }
+ }
+
+ grouping rw-node-attributes {
+ description "RW node attributes";
+ container rw-node-attributes {
+ description "Containing RW node attributes";
+ leaf name {
+ type string;
+ description "Node name";
+ }
+ leaf ovs-bridge-name {
+ type string;
+ description "Name of OVS bridge";
+ }
+ }
+ }
+
+ grouping rw-link-attributes {
+ description "RW link attributes";
+ container rw-link-attributes {
+ description "Containing RW link attributes";
+ leaf name {
+ type string;
+ description "Link name";
+ }
+ }
+ }
+
+ grouping rw-termination-point-attributes {
+ description "RW termination point attributes";
+ container rw-termination-point-attributes {
+ description "Containing RW TP attributes";
+ leaf description {
+ type string;
+ description "Port description";
+ }
+ uses ip-address-group;
+ }
+ }
+
+ augment "/nw:network" {
+ description
+ "Configuration parameters for the RW network
+ as a whole";
+ uses rw-network-attributes;
+ }
+
+ augment "/nw:network/nw:node" {
+ description
+ "Configuration parameters for RW at the node
+ level";
+ uses rw-node-attributes;
+ }
+
+ augment "/nw:network/nt:link" {
+ description "Augment RW topology link information";
+ uses rw-link-attributes;
+ }
+
+ augment "/nw:network/nw:node/nt:termination-point" {
+ description
+ "Augment RW topology termination point configuration";
+ uses rw-termination-point-attributes;
+ }
+}
diff --git a/models/plugins/yang/rw-vld.yang b/models/plugins/yang/rw-vld.yang
new file mode 100644
index 0000000..5027480
--- /dev/null
+++ b/models/plugins/yang/rw-vld.yang
@@ -0,0 +1,39 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module rw-vld
+{
+ namespace "http://riftio.com/ns/riftware-1.0/rw-vld";
+ prefix "rw-vld";
+
+ import vld {
+ prefix "vld";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file augments
+ the base MANO VLD";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+}
+
+// vim: sw=2
diff --git a/models/plugins/yang/rw-vlr.yang b/models/plugins/yang/rw-vlr.yang
new file mode 100644
index 0000000..739dbec
--- /dev/null
+++ b/models/plugins/yang/rw-vlr.yang
@@ -0,0 +1,78 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module rw-vlr
+{
+ namespace "http://riftio.com/ns/riftware-1.0/rw-vlr";
+ prefix "rw-vlr";
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ import vlr {
+ prefix "vlr";
+ }
+
+ import rw-cloud {
+ prefix "rwcloud";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ revision 2015-09-30 {
+ description
+ "Initial revision. This YANG file augments
+ the base MANO VNFD";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ augment /vlr:vlr-catalog/vlr:vlr {
+ leaf cloud-account {
+ description
+ "The cloud account to use when requesting resources for
+ this vlr";
+ type leafref {
+ path "/rwcloud:cloud/rwcloud:account/rwcloud:name";
+ }
+ }
+
+ leaf network_pool {
+ description "The network pool the resource was allocated from.";
+ type string;
+ }
+
+ leaf assigned-subnet {
+ description "Subnet added for the VL";
+ type string;
+ }
+
+ leaf operational-status-details {
+ description
+ "The error message in case of a failed VLR operational status";
+ type string;
+ }
+ }
+}
+
+// vim: sw=2
diff --git a/models/plugins/yang/rw-vnfd.yang b/models/plugins/yang/rw-vnfd.yang
new file mode 100644
index 0000000..29eb852
--- /dev/null
+++ b/models/plugins/yang/rw-vnfd.yang
@@ -0,0 +1,117 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module rw-vnfd
+{
+ namespace "http://riftio.com/ns/riftware-1.0/rw-vnfd";
+ prefix "rw-vnfd";
+
+ import vnfd {
+ prefix "vnfd";
+ }
+
+ import rwvcs-types {
+ prefix "rwvcstypes";
+ }
+
+ import rw-pb-ext { prefix "rwpb"; }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file augments
+ the base MANO VNFD";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ augment /vnfd:vnfd-catalog/vnfd:vnfd {
+ uses manotypes:control-param;
+ uses manotypes:action-param;
+ leaf meta {
+ description
+ "Any meta-data needed by the UI";
+ type string;
+ }
+ list component {
+ description
+ "This section defines the RIFT.ware
+ virtual components";
+ key "component-name";
+ rwpb:msg-new VcsComponent;
+ rwpb:application-request-point;
+
+ leaf component-name {
+ description "";
+ type string;
+ }
+
+ leaf component-type {
+ description "";
+ type rwvcstypes:component_type;
+ mandatory true;
+ }
+
+ choice component {
+ case rwvcs-rwcollection {
+ uses rwvcstypes:rwvcs-rwcollection;
+ }
+ case rwvcs-rwvm {
+ uses rwvcstypes:rwvcs-rwvm;
+ }
+ case rwvcs-rwproc {
+ uses rwvcstypes:rwvcs-rwproc;
+ }
+ case native-proc {
+ uses rwvcstypes:native-proc;
+ }
+ case rwvcs-rwtasklet {
+ uses rwvcstypes:rwvcs-rwtasklet;
+ }
+ }
+ } // list component
+ }
+
+ augment /vnfd:vnfd-catalog/vnfd:vnfd/vnfd:vdu {
+ leaf vcs-component-ref {
+ description
+ "This defines the software components using the
+ RIFT.ware Virtual Component System (VCS). This
+ also allows specifying a state machine during
+ the VM startup.
+ NOTE: This is an significant addition to MANO,
+ since MANO doesn't clearly specify a method to
+ identify various software components in a VM.
+ Also using a state machine is not something that
+ is well described in MANO.";
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd/rw-vnfd:component/rw-vnfd:component-name";
+ }
+ }
+ }
+}
+// vim: sw=2
diff --git a/models/plugins/yang/rw-vnfr.tailf.yang b/models/plugins/yang/rw-vnfr.tailf.yang
new file mode 100644
index 0000000..6090fcf
--- /dev/null
+++ b/models/plugins/yang/rw-vnfr.tailf.yang
@@ -0,0 +1,50 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module rw-vnfr-annotation
+{
+ namespace "http://riftio.com/ns/riftware-1.0/rw-vnfr-annotation";
+ prefix "rw-vnfr-ann";
+
+ import tailf-common {
+ prefix tailf;
+ }
+
+ import rw-vnfr {
+ prefix rw-vnfr;
+ }
+
+ import vnfr {
+ prefix vnfr;
+ }
+
+ tailf:annotate "/vnfr:vnfr-catalog/rw-vnfr:vnfd-ref-count" {
+ tailf:callpoint rw_callpoint;
+ }
+
+ tailf:annotate "/vnfr:vnfr-catalog/vnfr:vnfr/rw-vnfr:operational-events" {
+ tailf:callpoint rw_callpoint;
+ }
+
+ tailf:annotate "/rw-vnfr:vnfr-console" {
+ tailf:callpoint rw_callpoint;
+ }
+
+}
diff --git a/models/plugins/yang/rw-vnfr.yang b/models/plugins/yang/rw-vnfr.yang
new file mode 100644
index 0000000..eb027e0
--- /dev/null
+++ b/models/plugins/yang/rw-vnfr.yang
@@ -0,0 +1,324 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module rw-vnfr
+{
+ namespace "http://riftio.com/ns/riftware-1.0/rw-vnfr";
+ prefix "rw-vnfr";
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ import rw-pb-ext { prefix "rwpb"; }
+
+ import vnfr {
+ prefix "vnfr";
+ }
+
+ import vnfd {
+ prefix "vnfd";
+ }
+
+ import rw-cloud {
+ prefix "rwcloud";
+ }
+
+ import rwvcs-types {
+ prefix "rwvcstypes";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file augments
+ the base MANO VNFD";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ grouping vnfr-operational-events {
+ list operational-events {
+ key "id";
+ description
+ "Recent operational events for VNFR
+ Though the model does not impose any restrictions on the numbe of events,
+ the max operational events will be limited to the most recent 10";
+
+ leaf id {
+ description "The id of the instance";
+ type uint64;
+ }
+
+ leaf timestamp {
+ description
+ "The timestamp of this event expressed as seconds since
+ unix epoch - 1970-01-01T00:00:00Z";
+ type uint32;
+ }
+ leaf event {
+ description "The event";
+ type enumeration {
+ rwpb:enum-type "VnfrOperationalEvent";
+ enum instantiate-rcvd;
+ enum vl-inited;
+ enum vnf-inited;
+ enum running;
+ enum terminate-rcvd;
+ enum vnf-terminated;
+ enum vl-terminated;
+ enum terminated;
+ }
+ }
+ leaf description {
+ description
+ "The description of this event";
+ type string;
+ }
+ }
+ }
+
+ grouping vdur-operational-events {
+ list operational-events {
+ key "id";
+ description
+ "Recent operational events for VDUR
+ Though the model does not impose any restrictions on the numbe of events,
+ the max operational events will be limited to the most recent 10";
+
+ leaf id {
+ description "The id of the instance";
+ type uint64;
+ }
+
+ leaf timestamp {
+ description
+ "The timestamp of this event expressed as seconds since
+ unix epoch - 1970-01-01T00:00:00Z";
+ type uint32;
+ }
+ leaf event {
+ description "The event";
+ type enumeration {
+ rwpb:enum-type "VdurOperationalEvent";
+ enum instantiate-rcvd;
+ enum vm-allocation-requested;
+ enum running;
+ enum terminate-rcvd;
+ enum vm-terminate-requested;
+ enum terminated;
+ }
+ }
+ leaf description {
+ description
+ "The description of this event";
+ type string;
+ }
+ }
+ }
+
+ augment /vnfr:vnfr-catalog/vnfr:vnfr {
+ uses manotypes:action-param;
+ uses manotypes:control-param;
+
+ leaf cloud-account {
+ description
+ "The cloud account to use when requesting resources for
+ this vnf";
+ type leafref {
+ path "/rwcloud:cloud/rwcloud:account/rwcloud:name";
+ }
+ }
+
+ leaf om-datacenter {
+ description
+ "Openmano datacenter name to use when instantiating
+ the network service. This is only used when openmano
+ is selected as the cloud account. This should be superceded
+ by multiple cloud accounts when that becomes available.";
+ type string;
+ }
+
+ container nfvi-metrics {
+ container vm {
+ leaf label {
+ description
+ "Label to show in UI";
+ type string;
+ default "VM";
+ }
+
+ leaf active-vm {
+ description
+ "The number of active VMs.";
+ type uint64;
+ }
+
+ leaf inactive-vm {
+ description
+ "The number of inactive VMs.";
+ type uint64;
+ }
+ }
+
+ uses manotypes:nfvi-metrics;
+ }
+
+ list component {
+ description
+ "This section defines the RIFT.ware
+ virtual components";
+ key "component-name";
+ rwpb:msg-new VcsComponentOp;
+ rwpb:application-request-point;
+
+ leaf component-name {
+ description "";
+ type string;
+ }
+
+ leaf component-type {
+ description "";
+ type rwvcstypes:component_type;
+ mandatory true;
+ }
+
+ choice component {
+ case rwvcs-rwcollection {
+ uses rwvcstypes:rwvcs-rwcollection;
+ }
+ case rwvcs-rwvm {
+ uses rwvcstypes:rwvcs-rwvm;
+ }
+ case rwvcs-rwproc {
+ uses rwvcstypes:rwvcs-rwproc;
+ }
+ case native-proc {
+ uses rwvcstypes:native-proc;
+ }
+ case rwvcs-rwtasklet {
+ uses rwvcstypes:rwvcs-rwtasklet;
+ }
+ }
+ } // list component
+
+ uses vnfr-operational-events;
+
+ leaf operational-status-details {
+ description
+ "The error message in case of a failed VNFR operational status";
+ type string;
+ }
+ }
+
+ augment /vnfr:vnfr-catalog/vnfr:vnfr/vnfr:vdur {
+ leaf vm-pool {
+ description
+ "The pool from which this vm was allocated from";
+ type string;
+ }
+
+ container nfvi-metrics {
+ uses manotypes:nfvi-metrics;
+ }
+
+ leaf vcs-component-ref {
+ description
+ "This defines the software components using the
+ RIFT.ware Virtual Component System (VCS). This
+ also allows specifying a state machine during
+ the VM startup.
+ NOTE: This is an significant addition to MANO,
+ since MANO doesn't clearly specify a method to
+ identify various software components in a VM.
+ Also using a state machine is not something that
+ is well described in MANO.";
+ type leafref {
+ path "/vnfr:vnfr-catalog/vnfr:vnfr/rw-vnfr:component/rw-vnfr:component-name";
+ }
+ }
+
+ uses vdur-operational-events;
+
+ leaf operational-status-details {
+ description
+ "The error message in case of a failed VDU operational status";
+ type string;
+ }
+ }
+ grouping vnfd-ref-count {
+ list vnfd-ref-count {
+ key "vnfd-id-ref";
+ description "This table maintains the number of VNFRs used by each VNFD";
+
+ leaf vnfd-id-ref {
+ description "Reference to VNFD";
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd/vnfd:id";
+ }
+ }
+ leaf instance-ref-count {
+ description
+ "Reference count for the number of VNFRs refering this VNFD.
+ Every VNF Record instantiated using this descriptor takes
+ a reference on the VNFD and releases the reference when the
+ virtual network service is terminated. This desciptor cannot
+ be deleted when this counter is non zero";
+ type uint64;
+ }
+ }
+ }
+ augment /vnfr:vnfr-catalog {
+ uses vnfd-ref-count;
+ }
+
+ container vnfr-console {
+ config false;
+ list vnfr {
+ key "id";
+ leaf id {
+ description "Identifier for the VNFR.";
+ type yang:uuid;
+ }
+ list vdur {
+ description "List of Virtual Deployment Units";
+ key "id";
+ leaf id {
+ description "Unique id for the VDU";
+ type yang:uuid;
+ }
+ leaf console-url {
+ description "Console URL for this VDU, if available";
+ type inet:uri;
+ }
+ }
+ }
+ }
+
+}
+
+// vim: sw=2
diff --git a/models/plugins/yang/vld.yang b/models/plugins/yang/vld.yang
new file mode 100644
index 0000000..2747887
--- /dev/null
+++ b/models/plugins/yang/vld.yang
@@ -0,0 +1,141 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module vld
+{
+ namespace "urn:ietf:params:xml:ns:yang:nfvo:vld";
+ prefix "vld";
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ import vnfd {
+ prefix "vnfd";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file defines
+ the Virtual Link Descriptor (VLD)";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ container vld-catalog {
+
+ list vld {
+ key "id";
+
+ leaf id {
+ description "Identifier for the VLD.";
+ type yang:uuid;
+ }
+
+ leaf name {
+ description "Virtual Link Descriptor (VLD) name.";
+ type string;
+ }
+
+ leaf short-name {
+ description "Short name for VLD for UI";
+ type string;
+ }
+
+ leaf vendor {
+ description "Provider of the VLD.";
+ type string;
+ }
+
+ leaf description {
+ description "Description of the VLD.";
+ type string;
+ }
+
+ leaf version {
+ description "Version of the VLD";
+ type string;
+ }
+
+ leaf type {
+ type manotypes:virtual-link-type;
+ }
+
+ leaf root-bandwidth {
+ description
+ "For ELAN this is the aggregate bandwidth.";
+ type uint64;
+ }
+
+ leaf leaf-bandwidth {
+ description
+ "For ELAN this is the bandwidth of branches.";
+ type uint64;
+ }
+
+ list vnfd-connection-point-ref {
+ description
+ "A list of references to connection points.";
+ key "vnfd-ref member-vnf-index-ref";
+
+ leaf vnfd-ref {
+ description "A reference to a vnfd";
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd/vnfd:id";
+ }
+ }
+
+ leaf member-vnf-index-ref {
+ description
+ "A reference to the consituent-vnfd id in nsd.
+ Should have been a leafref to:
+ '/nsd:nsd-catalog:/nsd:nsd/constituent-vnfd/member-vnf-index-ref'.
+ Instead using direct leaf to avoid circular reference.";
+ type uint64;
+ }
+
+ leaf vnfd-connection-point-ref {
+ description
+ "A reference to a connection point name in a vnfd";
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd"
+ + "[vnfd:id = current()/../vld:vnfd-ref]"
+ + "/vnfd:connection-point/vnfd:name";
+ }
+ }
+ }
+
+ // replicate for pnfd container here
+ uses manotypes:provider-network;
+ }
+ }
+}
diff --git a/models/plugins/yang/vlr.tailf.yang b/models/plugins/yang/vlr.tailf.yang
new file mode 100644
index 0000000..4bed1d2
--- /dev/null
+++ b/models/plugins/yang/vlr.tailf.yang
@@ -0,0 +1,37 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module vlr-annotation
+{
+ namespace "http://riftio.com/ns/riftware-1.0/vlr-annotation";
+ prefix "vlr-ann";
+
+ import tailf-common {
+ prefix tailf;
+ }
+
+ import vlr {
+ prefix vlr;
+ }
+
+ tailf:annotate "/vlr:vlr-catalog" {
+ tailf:callpoint rw_callpoint;
+ }
+}
diff --git a/models/plugins/yang/vlr.yang b/models/plugins/yang/vlr.yang
new file mode 100644
index 0000000..ef3d603
--- /dev/null
+++ b/models/plugins/yang/vlr.yang
@@ -0,0 +1,186 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module vlr
+{
+ namespace "urn:ietf:params:xml:ns:yang:nfvo:vlr";
+ prefix "vlr";
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ import vld {
+ prefix "vld";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file defines
+ the Virtual Link Record (VLR)";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ container vlr-catalog {
+ config false;
+
+ list vlr {
+ key "id";
+ unique "name";
+
+ leaf id {
+ description "Identifier for the VLR.";
+ type yang:uuid;
+ }
+
+ leaf name {
+ description "VLR name.";
+ type string;
+ }
+
+ leaf nsr-id-ref {
+ description
+ "NS instance identifier.
+ This is a leafref /nsr:ns-instance-config/nsr:nsr/nsr:id";
+ type yang:uuid;
+ }
+
+ leaf vld-ref {
+ description
+ "Reference to VLD
+ /nsr:ns-instance-config/nsr:nsr[nsr:id=../nsr-id-ref]/nsd/vld:vld/vld:id";
+ type string;
+ }
+
+ leaf res-id {
+ description "Identifier for resmgr id mapping";
+ type yang:uuid;
+ }
+
+ leaf short-name {
+ description "Short name for VLR for UI";
+ type string;
+ }
+
+ leaf vendor {
+ description "Provider of the VLR.";
+ type string;
+ }
+
+ leaf description {
+ description "Description of the VLR.";
+ type string;
+ }
+
+ leaf version {
+ description "Version of the VLR";
+ type string;
+ }
+
+ leaf type {
+ type manotypes:virtual-link-type;
+ }
+
+ leaf root-bandwidth {
+ description
+ "For ELAN this is the aggregate bandwidth.";
+ type uint64;
+ }
+
+ leaf leaf-bandwidth {
+ description
+ "For ELAN this is the bandwidth of branches.";
+ type uint64;
+ }
+
+ leaf create-time {
+ description
+ "Creation timestamp of this Virtual Link.
+ The timestamp is expressed as seconds
+ since unix epoch - 1970-01-01T00:00:00Z";
+
+ type uint32;
+ }
+
+ leaf network-id {
+ description
+ "Identifier for the allocated network resource.";
+ type string;
+ }
+
+ leaf vim-network-name {
+ description
+ "Name of network in VIM account. This is used to indicate
+ pre-provisioned network name in cloud account.";
+ type string;
+ }
+
+ // replicate for pnfd container here
+
+ uses manotypes:provider-network;
+ uses manotypes:ip-profile-info;
+
+ leaf status {
+ description
+ "Status of the virtual link record.";
+ type enumeration {
+ enum LINK_UP;
+ enum DEGRADED;
+ enum LINK_DOWN;
+ }
+ }
+ leaf operational-status {
+ description
+ "The operational status of the Virtual Link
+ init : The VL is in init stat.
+ vl-alloc-pending : The VL alloc is pending in VIM
+ running : The VL is up and running in VM
+ vl-terminate-pending : The VL is being terminated in VIM.
+ terminated : The VL is terminated in the VM.
+ failed : The VL instantiation failed in VIM.
+ ";
+
+ type enumeration {
+ rwpb:enum-type "VlOperationalStatus";
+ enum init;
+ enum vl-alloc-pending;
+ enum running;
+ enum vl-terminate-pending;
+ enum terminated;
+ enum failed;
+ }
+ }
+ }
+ }
+}
+
diff --git a/models/plugins/yang/vnfd.yang b/models/plugins/yang/vnfd.yang
new file mode 100644
index 0000000..c035bd3
--- /dev/null
+++ b/models/plugins/yang/vnfd.yang
@@ -0,0 +1,515 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module vnfd
+{
+ namespace "urn:ietf:params:xml:ns:yang:nfvo:vnfd";
+ prefix "vnfd";
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file defines
+ the Virtual Network Function (VNF)";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ grouping common-connection-point {
+ leaf name {
+ description "Name of the connection point";
+ type string;
+ }
+
+ leaf id {
+ description "Identifier for the internal connection points";
+ type string;
+ }
+
+ leaf short-name {
+ description "Short name of the connection point";
+ type string;
+ }
+
+ leaf type {
+ description "Type of the connection point.";
+ type manotypes:connection-point-type;
+ }
+ }
+
+ grouping virtual-interface {
+ container virtual-interface {
+ description
+ "Container for the virtual interface properties";
+
+ leaf type {
+ description
+ "Specifies the type of virtual interface
+ between VM and host.
+ VIRTIO : Use the traditional VIRTIO interface.
+ PCI-PASSTHROUGH : Use PCI-PASSTHROUGH interface.
+ SR-IOV : Use SR-IOV interface.
+ E1000 : Emulate E1000 interface.
+ RTL8139 : Emulate RTL8139 interface.
+ PCNET : Emulate PCNET interface.
+ OM-MGMT : Used to specify openmano mgmt external-connection type";
+
+ type enumeration {
+ enum OM-MGMT;
+ enum PCI-PASSTHROUGH;
+ enum SR-IOV;
+ enum VIRTIO;
+ enum E1000;
+ enum RTL8139;
+ enum PCNET;
+ }
+ default "VIRTIO";
+ }
+
+ leaf vpci {
+ description
+ "Specifies the virtual PCI address. Expressed in
+ the following format dddd:dd:dd.d. For example
+ 0000:00:12.0. This information can be used to
+ pass as metadata during the VM creation.";
+ type string;
+ }
+
+ leaf bandwidth {
+ description
+ "Aggregate bandwidth of the NIC.";
+ type uint64;
+ }
+ }
+ }
+
+ container vnfd-catalog {
+
+ description
+ "Virtual Network Function Descriptor (VNFD).";
+
+ list vnfd {
+ key "id";
+
+ leaf id {
+ description "Identifier for the VNFD.";
+ type string;
+ }
+
+ leaf name {
+ description "VNFD name.";
+ mandatory true;
+ type string;
+ }
+
+ leaf short-name {
+ description "VNFD short name.";
+ type string;
+ }
+
+ leaf vendor {
+ description "Vendor of the VNFD.";
+ type string;
+ }
+
+ leaf logo {
+ description
+ "Vendor logo for the Virtual Network Function";
+ type string;
+ }
+
+ leaf description {
+ description "Description of the VNFD.";
+ type string;
+ }
+
+ leaf version {
+ description "Version of the VNFD";
+ type string;
+ }
+
+ uses manotypes:vnf-configuration;
+
+ container mgmt-interface {
+ description
+ "Interface over which the VNF is managed.";
+
+ choice endpoint-type {
+ description
+ "Indicates the type of management endpoint.";
+
+ case ip {
+ description
+ "Specifies the static IP address for managing the VNF.";
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ }
+
+ case vdu-id {
+ description
+ "Use the default management interface on this VDU.";
+ leaf vdu-id {
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd/vnfd:vdu/vnfd:id";
+ }
+ }
+ }
+
+ case cp {
+ description
+ "Use the ip address associated with this connection point.";
+ leaf cp {
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd/vnfd:connection-point/vnfd:name";
+ }
+ }
+ }
+ }
+
+ leaf port {
+ description
+ "Port for the management interface.";
+ type inet:port-number;
+ }
+
+ container dashboard-params {
+ description "Parameters for the VNF dashboard";
+
+ leaf path {
+ description "The HTTP path for the dashboard";
+ type string;
+ }
+
+ leaf https {
+ description "Pick HTTPS instead of HTTP , Default is false";
+ type boolean;
+ }
+
+ leaf port {
+ description "The HTTP port for the dashboard";
+ type inet:port-number;
+ }
+ }
+ }
+
+ list internal-vld {
+ key "id";
+ description
+ "List of Internal Virtual Link Descriptors (VLD).
+ The internal VLD describes the basic topology of
+ the connectivity (e.g. E-LAN, E-Line, E-Tree)
+ between internal VNF components of the system.";
+
+ leaf id {
+ description "Identifier for the VLD";
+ type string;
+ }
+
+ leaf name {
+ description "Name of the internal VLD";
+ type string;
+ }
+
+ leaf short-name {
+ description "Short name of the internal VLD";
+ type string;
+ }
+
+ leaf description {
+ type string;
+ }
+
+ leaf type {
+ type manotypes:virtual-link-type;
+ }
+
+ leaf root-bandwidth {
+ description
+ "For ELAN this is the aggregate bandwidth.";
+ type uint64;
+ }
+
+ leaf leaf-bandwidth {
+ description
+ "For ELAN this is the bandwidth of branches.";
+ type uint64;
+ }
+
+ leaf-list internal-connection-point-ref {
+ type leafref {
+ path "../../vdu/internal-connection-point/id";
+ }
+ }
+
+ uses manotypes:provider-network;
+ }
+
+ list connection-point {
+ key "name";
+ description
+ "List for external connection points. Each VNF has one
+ or more external connection points. As the name
+ implies that external connection points are used for
+ connecting the VNF to other VNFs or to external networks.
+ Each VNF exposes these connection points to the
+ orchestrator. The orchestrator can construct network
+ services by connecting the connection points between
+ different VNFs. The NFVO will use VLDs and VNFFGs at
+ the network service level to construct network services.";
+
+ uses common-connection-point;
+ }
+
+ list vdu {
+ description "List of Virtual Deployment Units";
+ key "id";
+
+ leaf id {
+ description "Unique id for the VDU";
+ type string;
+ }
+
+ leaf name {
+ description "Unique name for the VDU";
+ type string;
+ }
+
+ leaf description {
+ description "Description of the VDU.";
+ type string;
+ }
+
+ leaf count {
+ description "Number of instances of VDU";
+ type uint64;
+ }
+
+ leaf mgmt-vpci {
+ description
+ "Specifies the virtual PCI address. Expressed in
+ the following format dddd:dd:dd.d. For example
+ 0000:00:12.0. This information can be used to
+ pass as metadata during the VM creation.";
+ type string;
+ }
+
+ uses manotypes:vm-flavor;
+ uses manotypes:guest-epa;
+ uses manotypes:vswitch-epa;
+ uses manotypes:hypervisor-epa;
+ uses manotypes:host-epa;
+
+ list alarm {
+ key "alarm-id";
+
+ uses manotypes:alarm;
+ }
+
+ leaf image {
+ description
+ "Image name for the software image.
+ If the image name is found within the VNF packaage it will
+ be uploaded to all cloud accounts during onboarding process.
+ Otherwise, the image must be added to the cloud account with
+ the same name as entered here.
+ ";
+ mandatory true;
+ type string;
+ }
+
+ leaf image-checksum {
+ description
+ "Image md5sum for the software image.
+ The md5sum, if provided, along with the image name uniquely
+ identifies an image uploaded to the CAL.
+ ";
+ type string;
+ }
+
+ choice cloud-init-input {
+ description
+ "Indicates how the contents of cloud-init script are provided.
+ There are 2 choices - inline or in a file";
+
+ case inline {
+ leaf cloud-init {
+ description
+ "Contents of cloud-init script, provided inline, in cloud-config format";
+ type string;
+ }
+ }
+
+ case filename {
+ leaf cloud-init-file {
+ description
+ "Name of file with contents of cloud-init script in cloud-config format";
+ type string;
+ }
+ }
+ }
+
+ list internal-connection-point {
+ key "id";
+ description
+ "List for internal connection points. Each VNFC
+ has zero or more internal connection points.
+ Internal connection points are used for connecting
+ the VNF components internal to the VNF. If a VNF
+ has only one VNFC, it may not have any internal
+ connection points.";
+
+ uses common-connection-point;
+
+ leaf internal-vld-ref {
+ type leafref {
+ path "../../../internal-vld/id";
+ }
+ }
+ }
+
+ list internal-interface {
+ description
+ "List of internal interfaces for the VNF";
+ key name;
+
+ leaf name {
+ description
+ "Name of internal interface. Note that this
+ name has only local significance to the VDU.";
+ type string;
+ }
+
+ leaf vdu-internal-connection-point-ref {
+ type leafref {
+ path "../../internal-connection-point/id";
+ }
+ }
+ uses virtual-interface;
+ }
+
+ list external-interface {
+ description
+ "List of external interfaces for the VNF.
+ The external interfaces enable sending
+ traffic to and from VNF.";
+ key name;
+
+ leaf name {
+ description
+ "Name of the external interface. Note that
+ this name has only local significance.";
+ type string;
+ }
+
+ leaf vnfd-connection-point-ref {
+ description
+ "Name of the external connection point.";
+ type leafref {
+ path "../../../connection-point/name";
+ }
+ }
+ uses virtual-interface;
+ }
+ }
+
+ list vdu-dependency {
+ description
+ "List of VDU dependencies.";
+
+ key vdu-source-ref;
+ leaf vdu-source-ref {
+ type leafref {
+ path "../../vdu/id";
+ }
+ }
+
+ leaf vdu-depends-on-ref {
+ description
+ "Reference to the VDU that
+ source VDU depends.";
+ type leafref {
+ path "../../vdu/id";
+ }
+ }
+ }
+
+ leaf service-function-chain {
+ description "Type of node in Service Function Chaining Architecture";
+
+ type enumeration {
+ enum UNAWARE;
+ enum CLASSIFIER;
+ enum SF;
+ enum SFF;
+ }
+ default "UNAWARE";
+ }
+
+ leaf service-function-type {
+ description
+ "Type of Service Function.
+ NOTE: This needs to map with Service Function Type in ODL to
+ support VNFFG. Service Function Type is manadatory param in ODL
+ SFC. This is temporarily set to string for ease of use";
+ type string;
+ }
+
+ uses manotypes:monitoring-param;
+
+ list placement-groups {
+ description "List of placement groups at VNF level";
+
+ key "name";
+ uses manotypes:placement-group-info;
+
+ list member-vdus {
+
+ description
+ "List of VDUs that are part of this placement group";
+ key "member-vdu-ref";
+
+ leaf member-vdu-ref {
+ type leafref {
+ path "../../../vdu/id";
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// vim: sw=2
diff --git a/models/plugins/yang/vnffgd.yang b/models/plugins/yang/vnffgd.yang
new file mode 100644
index 0000000..99347ae
--- /dev/null
+++ b/models/plugins/yang/vnffgd.yang
@@ -0,0 +1,83 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module vnffgd
+{
+ namespace "urn:ietf:params:xml:ns:yang:nfvo:vnffgd";
+ prefix "vnffgd";
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ revision 2014-10-27 {
+ description
+ "Initial revision. This YANG file defines
+ the VNF Forwarding Graph Descriptor (VNFFGD)";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ container vnffgd-catalog {
+
+ list vnffgd {
+ key "id";
+
+ leaf name {
+ description "VNF Forwarding Graph Descriptor name.";
+ type string;
+ }
+
+ leaf id {
+ description "Identifier for the VNFFGD.";
+ type yang:uuid;
+ }
+
+ leaf provider {
+ description "Provider of the VNFFGD.";
+ type string;
+ }
+
+ leaf description {
+ description "Description of the VNFFGD.";
+ type string;
+ }
+
+ leaf version {
+ description "Version of the VNFFGD";
+ type string;
+ }
+
+ //TODO: Add more content here
+ }
+ }
+}
diff --git a/models/plugins/yang/vnfr.tailf.yang b/models/plugins/yang/vnfr.tailf.yang
new file mode 100644
index 0000000..150dc9a
--- /dev/null
+++ b/models/plugins/yang/vnfr.tailf.yang
@@ -0,0 +1,45 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module vnfr-annotation
+{
+ namespace "http://riftio.com/ns/riftware-1.0/vnfr-annotation";
+ prefix "vnfr-ann";
+
+ import tailf-common {
+ prefix tailf;
+ }
+
+ import vnfr {
+ prefix vnfr;
+ }
+
+ tailf:annotate "/vnfr:vnfr-catalog" {
+ tailf:callpoint rw_callpoint;
+ }
+
+ tailf:annotate "/vnfr:create-alarm" {
+ tailf:actionpoint rw_actionpoint;
+ }
+
+ tailf:annotate "/vnfr:destroy-alarm" {
+ tailf:actionpoint rw_actionpoint;
+ }
+}
diff --git a/models/plugins/yang/vnfr.yang b/models/plugins/yang/vnfr.yang
new file mode 100644
index 0000000..4a427d4
--- /dev/null
+++ b/models/plugins/yang/vnfr.yang
@@ -0,0 +1,526 @@
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+module vnfr
+{
+ namespace "urn:ietf:params:xml:ns:yang:nfvo:vnfr";
+ prefix "vnfr";
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ import vnfd {
+ prefix "vnfd";
+ }
+
+ import nsd {
+ prefix "nsd";
+ }
+
+ import vlr {
+ prefix "vlr";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ revision 2015-09-10 {
+ description
+ "Initial revision. This YANG file defines
+ the Virtual Network Function Record (VNFR)";
+ reference
+ "Derived from earlier versions of base YANG files";
+ }
+
+ grouping placement-group-info {
+ list placement-groups-info {
+ description
+ "
+ Placement groups to which this VDU belongs and its
+ cloud construct
+ ";
+ key "name";
+ uses manotypes:placement-group-info;
+ uses manotypes:placement-group-input;
+ }
+ }
+
+
+ grouping virtual-interface {
+ container virtual-interface {
+ description
+ "Container for the virtual interface properties";
+
+ leaf type {
+ description
+ "Specifies the type of virtual interface
+ between VM and host.
+ VIRTIO : Use the traditional VIRTIO interface.
+ PCI-PASSTHROUGH : Use PCI-PASSTHROUGH interface.
+ SR-IOV : Use SR-IOV interface.";
+ type enumeration {
+ enum VIRTIO;
+ enum PCI-PASSTHROUGH;
+ enum SR-IOV;
+ }
+ }
+
+ leaf bandwidth {
+ description
+ "Aggregate bandwidth of the NIC.";
+ type uint64;
+ }
+
+ leaf ovs-offload {
+ description
+ "Defines if the NIC supports OVS offload.
+ MANDATORY : OVS offload support in the NIC is mandatory.
+ PREFERRED : OVS offload support in the NIC is preferred.";
+ type enumeration {
+ enum MANDATORY;
+ enum PREFERRED;
+ }
+ }
+
+ leaf vendor-id {
+ description
+ "Specifies the vendor specific id for
+ the device. This is used when a NIC from
+ specific HW vendor is required.";
+ type string;
+ }
+
+ leaf datapath-library {
+ description
+ "Specifies the name and version of the datapath
+ library the NIC is expected to support.";
+ type string;
+ }
+
+ leaf provider-network-name {
+ description
+ "Name of the provider network to which this
+ NIC is attached.";
+ type string;
+ }
+ }
+ }
+
+ container vnfr-catalog {
+ config false;
+ list vnfr {
+ description
+ "Virtual Network Function Record (VNFR).";
+ key "id";
+ unique "name";
+
+ leaf id {
+ description "Identifier for the VNFR.";
+ type yang:uuid;
+ }
+
+ leaf nsr-id-ref {
+ description
+ "NS instance identifier.
+ This is a leafref /nsr:ns-instance-config/nsr:nsr/nsr:id";
+ type yang:uuid;
+ }
+
+ leaf member-vnf-index-ref {
+ description "Reference to member VNF index in Network service.";
+ type leafref {
+ path "/nsd:nsd-catalog/nsd:nsd/nsd:constituent-vnfd/nsd:member-vnf-index";
+ }
+ }
+
+ leaf dashboard-url {
+ description "Dashboard URL";
+ type inet:uri;
+ }
+
+ leaf name {
+ description "VNFR name.";
+ type string;
+ }
+
+ leaf short-name {
+ description "VNFR short name.";
+ type string;
+ }
+
+ leaf vendor {
+ description "Vendor of the VNFR.";
+ type string;
+ }
+
+ leaf description {
+ description "Description of the VNFR.";
+ type string;
+ }
+
+ leaf version {
+ description "Version of the VNFR";
+ type string;
+ }
+
+ leaf create-time {
+ description
+ "Creation timestamp of this Virtual Network
+ Function. The timestamp is expressed as
+ seconds since unix epoch - 1970-01-01T00:00:00Z";
+
+ type uint32;
+ }
+
+ leaf vnfd-ref {
+ description "Reference to VNFD";
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd/vnfd:id";
+ }
+ }
+
+ // Use parameters provided here to configure this VNF
+ uses manotypes:vnf-configuration;
+
+ // Mainly used by Mon-params & dashboard url
+ container mgmt-interface {
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ leaf port {
+ type inet:port-number;
+ }
+ }
+
+ list internal-vlr {
+ key "vlr-ref";
+
+ leaf vlr-ref {
+ description "Reference to a VLR record in the VLR catalog";
+ type leafref {
+ path "/vlr:vlr-catalog/vlr:vlr/vlr:id";
+ }
+ }
+
+ leaf-list internal-connection-point-ref {
+ type leafref {
+ path "../../vdur/internal-connection-point/id";
+ }
+ }
+ }
+
+ list connection-point {
+ key "name";
+ description
+ "List for external connection points. Each VNF has one
+ or more external connection points. As the name
+ implies that external connection points are used for
+ connecting the VNF to other VNFs or to external networks.
+ Each VNF exposes these connection points to the
+ orchestrator. The orchestrator can construct network
+ services by connecting the connection points between
+ different VNFs. The NFVO will use VLDs and VNFFGs at
+ the network service level to construct network services.";
+
+ uses vnfd:common-connection-point;
+
+ leaf vlr-ref {
+ description
+ "Reference to the VLR associated with this connection point";
+ type leafref {
+ path "/vlr:vlr-catalog/vlr:vlr/vlr:id";
+ }
+ }
+
+ leaf ip-address {
+ description
+ "IP address assigned to the external connection point";
+ type inet:ip-address;
+ }
+ leaf connection-point-id {
+ rwpb:field-inline "true";
+ rwpb:field-string-max 64;
+ type string;
+ }
+ }
+
+ list vdur {
+ description "List of Virtual Deployment Units";
+ key "id";
+ unique "name";
+
+ leaf id {
+ description "Unique id for the VDU";
+ type yang:uuid;
+ }
+
+ leaf name {
+ description "name of the instantiated VDUR";
+ type string;
+ }
+
+ leaf vdu-id-ref {
+ type leafref {
+ path "/vnfd:vnfd-catalog/vnfd:vnfd"
+ + "[vnfd:id = current()/../../vnfr:vnfd-ref]"
+ + "/vnfd:vdu/vnfd:id";
+ }
+ }
+
+ leaf vim-id {
+ description "Allocated VM resource id";
+ type string;
+ }
+
+ leaf flavor-id {
+ description "VIM assigned flavor id";
+ type string;
+ }
+
+ leaf image-id {
+ description "VIM assigned image id";
+ type string;
+ }
+
+ leaf management-ip {
+ description "Management IP address";
+ type inet:ip-address;
+ }
+
+ leaf vm-management-ip {
+ description "VM Private Management IP address";
+ type inet:ip-address;
+ }
+
+ leaf console-url {
+ description "Console URL for this VDU, if available";
+ type inet:uri;
+ }
+
+ uses manotypes:vm-flavor;
+ uses manotypes:guest-epa;
+ uses manotypes:vswitch-epa;
+ uses manotypes:hypervisor-epa;
+ uses manotypes:host-epa;
+
+ list alarms {
+ description
+ "A list of the alarms that have been created for this VDU";
+
+ key "alarm-id";
+ uses manotypes:alarm;
+ }
+
+ list internal-connection-point {
+ key "id";
+ description
+ "List for internal connection points. Each VNFC
+ has zero or more internal connection points.
+ Internal connection points are used for connecting
+ the VNF components internal to the VNF. If a VNF
+ has only one VNFC, it may not have any internal
+ connection points.";
+
+ uses vnfd:common-connection-point;
+
+ leaf ip-address {
+ description
+ "IP address assigned to the external connection point";
+ type inet:ip-address;
+ }
+ }
+
+ list internal-interface {
+ description
+ "List of internal interfaces for the VNF";
+ key name;
+
+ leaf name {
+ description
+ "Name of internal interface. Note that this
+ name has only local significance to the VDU.";
+ type string;
+ }
+
+ leaf vdur-internal-connection-point-ref {
+ type leafref {
+ path "../../internal-connection-point/id";
+ }
+ }
+ uses virtual-interface;
+ }
+
+ list external-interface {
+ description
+ "List of external interfaces for the VNF.
+ The external interfaces enable sending
+ traffic to and from VNF.";
+ key name;
+
+ leaf name {
+ description
+ "Name of the external interface. Note that
+ this name has only local significance.";
+ type string;
+ }
+
+ leaf vnfd-connection-point-ref {
+ description
+ "Name of the external connection point.";
+ type leafref {
+ path "../../../connection-point/name";
+ }
+ }
+ uses virtual-interface;
+ }
+ leaf operational-status {
+ description
+ "The operational status of the VDU
+ init : The VDU has just started.
+ vm-init-phase : The VDUs in the VNF is being created in VIM.
+ vm-alloc-pending : The VM alloc is pending in VIM
+ running : The VDU is active in VM
+ terminate : The VDU is being terminated
+ vm-terminate-phase : The VDU in the VNF is being terminated in VIM.
+ terminated : The VDU is in the terminated state.
+ failed : The VDU instantiation failed.
+ ";
+
+ type enumeration {
+ rwpb:enum-type "VduOperationalStatus";
+ enum init;
+ enum vm-init-phase;
+ enum vm-alloc-pending;
+ enum running;
+ enum terminate;
+ enum vl-terminate-phase;
+ enum terminated;
+ enum failed;
+ }
+ }
+ uses placement-group-info;
+ }
+
+ uses manotypes:monitoring-param;
+
+ leaf operational-status {
+ description
+ "The operational status of the VNFR instance
+ init : The VNF has just started.
+ vl-init-phase : The internal VLs in the VNF are being instantiated.
+ vm-init-phase : The VMs for VDUs in the VNF are being instantiated.
+ running : The VNF is in running state.
+ terminate : The VNF is being terminated.
+ vm-terminate-phase : The VMs in the VNF are being terminated.
+ vl-terminate-phase : The internal VLs in the VNF are being terminated.
+ terminated : The VNF is in the terminated state.
+ failed : The VNF instantiation failed
+ ";
+
+ type enumeration {
+ rwpb:enum-type "VnfrOperationalStatus";
+ enum init;
+ enum vl-init-phase;
+ enum vm-init-phase;
+ enum running;
+ enum terminate;
+ enum vm-terminate-phase;
+ enum vl-terminate-phase;
+ enum terminated;
+ enum failed;
+ }
+ }
+ leaf config-status {
+ description
+ "The configuration status of the NS instance
+ configuring: At least one of the VNFs in this instance is in configuring state
+ configured: All the VNFs in this NS instance are configured or config-not-needed state
+ ";
+
+ type enumeration {
+ enum configuring {
+ value 1;
+ }
+ enum configured {
+ value 2;
+ }
+ enum failed {
+ value 3;
+ }
+ enum config-not-needed {
+ value 4;
+ }
+ }
+ }
+ uses placement-group-info;
+ }
+ }
+
+ rpc create-alarm {
+ description "Create an alert for a running VDU";
+ input {
+ leaf cloud-account {
+ mandatory true;
+ type string;
+ }
+
+ leaf vdur-id {
+ mandatory true;
+ type string;
+ }
+
+ container alarm {
+ uses manotypes:alarm;
+ }
+ }
+
+ output {
+ leaf alarm-id {
+ type string;
+ }
+ }
+ }
+
+ rpc destroy-alarm {
+ description "Destroy an alert that is associated with a running VDU";
+ input {
+ leaf cloud-account {
+ mandatory true;
+ type string;
+ }
+
+ leaf alarm-id {
+ mandatory true;
+ type string;
+ }
+ }
+ }
+}
+