aboutsummaryrefslogtreecommitdiffstats
path: root/vnfmgr
diff options
context:
space:
mode:
authorManuel Buil Mur <manuel.buil@ericsson.com>2015-10-09 16:48:36 +0200
committermbuil <manuel.buil@ericsson.com>2015-10-23 11:27:18 +0200
commit9c15bd683ccd0bf11d79ee0934a4cc3f78be521f (patch)
treeb0183e0e4fa543523b358315f4b6503e903fa7b8 /vnfmgr
parent40513772b3fa20c33f44fd36a8969f0763d1f9cd (diff)
First version of VNF manager simulator
This simulator contacts Openstack to create the SF VMs and then contacts ODL to create the SFC. It is not intended to be a replacement of other VNF Managers such as Tacker or OpenMANO, just a simple simulation for testing and development purposes. Change-Id: Iaf691035d1b8435f5fccf559aebf6f3ed1afd066 Signed-off-by: mbuil <manuel.buil@ericsson.com>
Diffstat (limited to 'vnfmgr')
-rwxr-xr-xvnfmgr/vnfmgr_main.py72
-rw-r--r--vnfmgr/vnfmgr_odl/__init__.py0
-rwxr-xr-xvnfmgr/vnfmgr_odl/sample_config/RestConf-RSP-HttpPost.json7
-rwxr-xr-xvnfmgr/vnfmgr_odl/sample_config/RestConf-SFCs-HttpPut.json22
-rwxr-xr-xvnfmgr/vnfmgr_odl/sample_config/RestConf-SFFs-HttpPut.json75
-rwxr-xr-xvnfmgr/vnfmgr_odl/sample_config/RestConf-SFPs-HttpPut.json12
-rwxr-xr-xvnfmgr/vnfmgr_odl/sample_config/RestConf-SFs-HttpPut.json38
-rwxr-xr-xvnfmgr/vnfmgr_odl/vnfmgr_odl.py440
-rw-r--r--vnfmgr/vnfmgr_os/__init__.py0
-rwxr-xr-xvnfmgr/vnfmgr_os/vnfmgr_os.py68
10 files changed, 734 insertions, 0 deletions
diff --git a/vnfmgr/vnfmgr_main.py b/vnfmgr/vnfmgr_main.py
new file mode 100755
index 0000000..b5ab8be
--- /dev/null
+++ b/vnfmgr/vnfmgr_main.py
@@ -0,0 +1,72 @@
+#################################################################
+# #
+# Copyright 2015 Ericsson AB #
+# All Rights Reserved #
+# #
+# Author: Manuel Buil <Manuel.Buil@ericsson.com> #
+# Version: 0.1 #
+# #
+#################################################################
+
+import pdb
+from vnfmgr_os.vnfmgr_os import OpenStack_API
+import vnfmgr_odl.vnfmgr_odl as odlscript
+import time
+import json
+
+if __name__ == "__main__":
+ #OpenStack environment information
+ authurl = "http://localhost:5000/v2.0"
+ adminTenantName = 'admin'
+ adminTenantUser = 'admin'
+ adminTenantPass = 'abc123'
+ tenantName = adminTenantName
+ tenantUser = adminTenantUser
+ tenantPass = adminTenantPass
+
+ openstack = OpenStack_API(authurl, tenantName, tenantUser, tenantPass)
+
+ # 1 - Get the SF type
+ # Provide the file with the SFC configuration
+ file_json = "vnfmgr_odl/sample_config/RestConf-SFCs-HttpPut.json"
+ # Read the config files which refer to SF
+ json_data=open(file_json).read()
+ data = json.loads(json_data)
+ pdb.set_trace()
+
+ # Grab the SF type
+ chains = data['service-function-chains']['service-function-chain']
+ for chain in chains:
+ SFs = chain['sfc-service-function']
+ for SF in SFs:
+ sf_type = SF['type']
+ name = SF['name']
+ #2 - Search the image in glance with that SF type
+ image = openstack.find_image(sf_type)
+ if image == None:
+ print("There is no image with that sf_name")
+ exit(1)
+ # 3 - Boot the VM without network
+ flavor = 1
+ print("About to deploy")
+ vm = openstack.create_vm(name,image,flavor)
+ if vm == None:
+ print("Problems to deploy the VM")
+ exit(1)
+
+ #Make the call to ODL to deploy SFC
+ context = odlscript.Context()
+ context.set_path_prefix_paths("vnfmgr_odl/sample_config")
+ pdb.set_trace()
+ odlscript.send_rest(context, "PUT", context.rest_url_sf_sel, context.rest_path_sf_sel)
+ odlscript.send_rest(context, "PUT", context.rest_url_sf, context.rest_path_sf)
+ odlscript.send_rest(context, "PUT", context.rest_url_sff, context.rest_path_sff)
+ odlscript.send_rest(context, "PUT", context.rest_url_sfc, context.rest_path_sfc)
+ odlscript.send_rest(context, "PUT", context.rest_url_sfp, context.rest_path_sfp)
+ time.sleep(1);
+ odlscript.send_rest(context, "POST", context.rest_url_rsp_rpc, context.rest_path_rsp)
+
+
+ #TO DO
+ # Check if the SF_VM already exists before creating it
+ # Network of the VM
diff --git a/vnfmgr/vnfmgr_odl/__init__.py b/vnfmgr/vnfmgr_odl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vnfmgr/vnfmgr_odl/__init__.py
diff --git a/vnfmgr/vnfmgr_odl/sample_config/RestConf-RSP-HttpPost.json b/vnfmgr/vnfmgr_odl/sample_config/RestConf-RSP-HttpPost.json
new file mode 100755
index 0000000..998d1e0
--- /dev/null
+++ b/vnfmgr/vnfmgr_odl/sample_config/RestConf-RSP-HttpPost.json
@@ -0,0 +1,7 @@
+{
+ "input": {
+ "name": "sfc-path-1",
+ "parent-service-function-path": "sfc-path-1",
+ "symmetric": true
+ }
+}
diff --git a/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFCs-HttpPut.json b/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFCs-HttpPut.json
new file mode 100755
index 0000000..3444964
--- /dev/null
+++ b/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFCs-HttpPut.json
@@ -0,0 +1,22 @@
+{
+ "service-function-chains": {
+ "service-function-chain": [
+ {
+ "name": "sfc-chain-1",
+ "symmetric": true,
+ "sfc-service-function": [
+ {
+ "name": "firewall-abstract1",
+ "type": "service-function-type:firewall"
+ },
+ {
+ "name": "firewall-abstract2",
+ "type": "service-function-type:firewall"
+ }
+ ]
+ }
+
+ ]
+ }
+}
+
diff --git a/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFFs-HttpPut.json b/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFFs-HttpPut.json
new file mode 100755
index 0000000..191fd54
--- /dev/null
+++ b/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFFs-HttpPut.json
@@ -0,0 +1,75 @@
+{
+ "service-function-forwarders": {
+ "service-function-forwarder": [
+ {
+ "name": "SFF2",
+ "sff-data-plane-locator": [
+ {
+ "name": "sff2-dp1",
+ "service-function-forwarder-ovs:ovs-bridge": {},
+ "data-plane-locator": {
+ "transport": "service-locator:vxlan-gpe",
+ "port": 6633,
+ "ip": "192.168.1.100"
+ },
+ "service-function-forwarder-ovs:ovs-options": {
+ "nshc1": "flow",
+ "nsp": "flow",
+ "key": "flow",
+ "remote-ip": "flow",
+ "nsi": "flow",
+ "nshc2": "flow",
+ "nshc3": "flow",
+ "dst-port": "6633",
+ "nshc4": "flow"
+ }
+ }
+ ],
+ "service-function-forwarder-ovs:ovs-bridge": {
+ "bridge-name": "ovs-br2"
+ },
+ "service-function-dictionary": [
+ {
+ "name": "firewall-2",
+ "type": "service-function-type:firewall",
+ "sff-sf-data-plane-locator": {
+ "service-function-forwarder-ovs:ovs-bridge": {},
+ "transport": "service-locator:vxlan-gpe",
+ "port": 6633,
+ "ip": "192.168.1.11"
+ }
+ },
+ {
+ "name": "firewall-3",
+ "type": "service-function-type:firewall",
+ "sff-sf-data-plane-locator": {
+ "service-function-forwarder-ovs:ovs-bridge": {},
+ "transport": "service-locator:vxlan-gpe",
+ "port": 6633,
+ "ip": "192.168.1.12"
+ }
+ }
+ ],
+ "ip-mgmt-address": "192.168.1.100",
+ "service-node": ""
+ },
+ {
+ "name": "SFF-CL",
+ "sff-data-plane-locator": [
+ {
+ "name": "ovs-br1",
+ "service-function-forwarder-ovs:ovs-bridge": {},
+ "data-plane-locator": {
+ "transport": "service-locator:vxlan-gpe",
+ "port": 30001,
+ "ip": "192.168.1.50"
+ }
+ }
+ ],
+ "rest-uri": "http://192.168.1.50:5000",
+ "ip-mgmt-address": "192.168.1.50",
+ "service-node": ""
+ }
+ ]
+ }
+}
diff --git a/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFPs-HttpPut.json b/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFPs-HttpPut.json
new file mode 100755
index 0000000..da1f2c4
--- /dev/null
+++ b/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFPs-HttpPut.json
@@ -0,0 +1,12 @@
+{
+ "service-function-paths": {
+ "service-function-path": [
+ {
+ "name": "sfc-path-1",
+ "service-chain-name": "sfc-chain-1",
+ "transport-type": "service-locator:vxlan-gpe",
+ "symmetric": true
+ }
+ ]
+ }
+}
diff --git a/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFs-HttpPut.json b/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFs-HttpPut.json
new file mode 100755
index 0000000..1ea27e7
--- /dev/null
+++ b/vnfmgr/vnfmgr_odl/sample_config/RestConf-SFs-HttpPut.json
@@ -0,0 +1,38 @@
+{
+ "service-functions": {
+ "service-function": [
+ {
+ "name": "firewall-2",
+ "sf-data-plane-locator": [
+ {
+ "name": "firewall-2-dp1",
+ "ip": "192.168.1.11",
+ "port": 6633,
+ "transport": "service-locator:vxlan-gpe",
+ "service-function-forwarder": "SFF2"
+ }
+ ],
+ "rest-uri": "http://192.168.1.11:5000",
+ "nsh-aware": true,
+ "ip-mgmt-address": "192.168.1.11",
+ "type": "service-function-type:firewall"
+ },
+ {
+ "name": "firewall-3",
+ "sf-data-plane-locator": [
+ {
+ "name": "firewall-3-dp1",
+ "ip": "192.168.1.12",
+ "port": 6633,
+ "transport": "service-locator:vxlan-gpe",
+ "service-function-forwarder": "SFF2"
+ }
+ ],
+ "rest-uri": "http://192.168.1.12:5000",
+ "nsh-aware": true,
+ "ip-mgmt-address": "192.168.1.12",
+ "type": "service-function-type:firewall"
+ }
+ ]
+ }
+}
diff --git a/vnfmgr/vnfmgr_odl/vnfmgr_odl.py b/vnfmgr/vnfmgr_odl/vnfmgr_odl.py
new file mode 100755
index 0000000..4d35aeb
--- /dev/null
+++ b/vnfmgr/vnfmgr_odl/vnfmgr_odl.py
@@ -0,0 +1,440 @@
+#! /usr/bin/env python
+
+__author__ = "Brady Johnson"
+__copyright__ = "Copyright(c) 2015, Ericsson, Inc."
+__license__ = "Apache License version 2.0"
+__version__ = "0.1"
+__email__ = "brady.allen.johnson@ericsson.com"
+__status__ = "beta"
+import pdb
+import os
+import time
+import requests
+import json
+import argparse
+
+PUT = 'PUT'
+GET = 'GET'
+POST = 'POST'
+
+class Context(object):
+ """
+ Context class to hold the configuration as specified on the command line
+ """
+ def __init__(self):
+ self.rest_path_prefix = 'sampleConfig'
+ self.rest_path_sf = 'RestConf-SFs-HttpPut.json'
+ self.rest_path_sf_sel = 'RestConf-SFselect-HttpPut.json'
+ self.rest_path_sfc = 'RestConf-SFCs-HttpPut.json'
+ self.rest_path_sff = 'RestConf-SFFs-HttpPut.json'
+ self.rest_path_sfp = 'RestConf-SFPs-HttpPut.json'
+ self.rest_path_acl = 'RestConf-ACLs-HttpPut.json'
+ self.rest_path_rsp = 'RestConf-RSP-HttpPost.json'
+
+ self.rest_url_sf = 'config/service-function:service-functions/'
+ self.rest_url_sf_sel = 'config/service-function-scheduler-type:service-function-scheduler-types/'
+ self.rest_url_sfc = 'config/service-function-chain:service-function-chains/'
+ self.rest_url_sff = 'config/service-function-forwarder:service-function-forwarders/'
+ self.rest_url_sfp = 'config/service-function-path:service-function-paths/'
+ self.rest_url_rsp = 'operational/rendered-service-path:rendered-service-paths/'
+ self.rest_url_rsp_rpc = 'operations/rendered-service-path:create-rendered-path'
+ self.rest_url_acl = 'config/ietf-acl:access-lists/'
+
+ self.http_headers = {'Content-Type' : 'application/json', 'Cache-Control' : 'no-cache'}
+ self.http_server = 'localhost'
+ self.url_base = ''
+ self.http_port = '8181'
+ self.interractive = True
+ self.user = 'admin'
+ self.pw = 'admin'
+ self.batch_sf = False
+ self.batch_sf_sel = False
+ self.batch_sfc = False
+ self.batch_sff = False
+ self.batch_sfp = False
+ self.batch_acl = False
+ self.batch_rsp = False
+ self.batch_query = False
+
+ def set_path_prefix_paths(self, path_prefix):
+ self.rest_path_prefix = path_prefix
+ self.rest_path_sf = os.path.join(self.rest_path_prefix, self.rest_path_sf)
+ self.rest_path_sf_sel = os.path.join(self.rest_path_prefix, self.rest_path_sf_sel)
+ self.rest_path_sfc = os.path.join(self.rest_path_prefix, self.rest_path_sfc)
+ self.rest_path_sff = os.path.join(self.rest_path_prefix, self.rest_path_sff)
+ self.rest_path_sfp = os.path.join(self.rest_path_prefix, self.rest_path_sfp)
+ self.rest_path_acl = os.path.join(self.rest_path_prefix, self.rest_path_acl)
+ self.rest_path_rsp = os.path.join(self.rest_path_prefix, self.rest_path_rsp)
+
+
+def get_cmd_line(context):
+ """
+ Create a command-line parser, parse the command line args, and process them.
+ Populate the Context object with the processed command-line args.
+ """
+
+ opts = argparse.ArgumentParser()
+
+ # Batch or Interractive mode
+ opts.add_argument('--interractive', '-i',
+ dest='interractive',
+ action='store_true',
+ help='Interractive mode, default')
+ opts.add_argument('--batch', '-b',
+ dest='batch',
+ action='store_true',
+ help='Batch mode, overrides interractive mode')
+
+ # Where to send the messages
+ opts.add_argument('--http-server', '-s',
+ default=context.http_server,
+ dest='http_server',
+ help='HTTP server address')
+ opts.add_argument('--http-port',
+ default=context.http_port,
+ dest='http_port',
+ help='HTTP server port')
+
+ # Batch mode, which message(s) to send
+ opts.add_argument('--send-sf', '-1',
+ dest='send_sf',
+ action='store_true',
+ help='Send an SF REST JSON PUT message')
+ opts.add_argument('--send-sf-sel',
+ dest='send_sf_sel',
+ action='store_true',
+ help='Send an SF Selection REST JSON PUT message')
+ opts.add_argument('--send-sfc', '-2',
+ dest='send_sfc',
+ action='store_true',
+ help='Send an SFC REST JSON PUT message')
+ opts.add_argument('--send-sff', '-3',
+ dest='send_sff',
+ action='store_true',
+ help='Send an SFF REST JSON PUT message')
+ opts.add_argument('--send-sfp', '-4',
+ dest='send_sfp',
+ action='store_true',
+ help='Send an SFP REST JSON PUT message')
+ opts.add_argument('--send-acl', '-5',
+ dest='send_acl',
+ action='store_true',
+ help='Send an ACL REST JSON PUT message')
+ opts.add_argument('--send-rsp', '-6',
+ dest='send_rsp',
+ action='store_true',
+ help='Send an RSP REST JSON POST RPC message')
+ opts.add_argument('--send-all', '-7',
+ dest='send_all',
+ action='store_true',
+ help='Send all (SF, SFF, SFC, SFP, RSP, ACL) REST JSON messages')
+ opts.add_argument('--query-sfc', '-q',
+ dest='query_sfc',
+ action='store_true',
+ help='Query all SFC objects')
+
+ # Paths to the rest JSON files
+ opts.add_argument('--rest-path-prefix', '-prefix',
+ default=context.rest_path_prefix,
+ dest='rest_path_prefix',
+ help='Path prefix where the REST JSON files are located')
+ opts.add_argument('--rest-path-sf-sel',
+ default=context.rest_path_sf_sel,
+ dest='rest_path_sf_sel',
+ help='Name of the SF Selection REST JSON file, relative to configured prefix')
+ opts.add_argument('--rest-path-sf', '-n',
+ default=context.rest_path_sf,
+ dest='rest_path_sf',
+ help='Name of the SF REST JSON file, relative to configured prefix')
+ opts.add_argument('--rest-path-sfc', '-c',
+ default=context.rest_path_sfc,
+ dest='rest_path_sfc',
+ help='Name of the SFC REST JSON file, relative to configured prefix')
+ opts.add_argument('--rest-path-sff', '-f',
+ default=context.rest_path_sff,
+ dest='rest_path_sff',
+ help='Name of the SFF REST JSON file, relative toconfigured prefix')
+ opts.add_argument('--rest-path-sfp', '-p',
+ default=context.rest_path_sfp,
+ dest='rest_path_sfp',
+ help='Name of the SFP REST JSON file, relative to configured prefix')
+ opts.add_argument('--rest-path-rsp', '-r',
+ default=context.rest_path_rsp,
+ dest='rest_path_rsp',
+ help='Name of the RSP REST JSON file, relative to configured prefix')
+ opts.add_argument('--rest-path-acl', '-a',
+ default=context.rest_path_acl,
+ dest='rest_path_acl',
+ help='Name of the ACL REST JSON file, relative to configured prefix')
+
+ args = opts.parse_args()
+
+ context.http_server = args.http_server
+ context.http_port = args.http_port
+ context.url_base = 'http://%s:%s/restconf/' % (context.http_server, context.http_port)
+
+ context.rest_path_prefix = args.rest_path_prefix
+ context.rest_path_sf = args.rest_path_sf
+ context.rest_path_sf_sel = args.rest_path_sf_sel
+ context.rest_path_sfc = args.rest_path_sfc
+ context.rest_path_sff = args.rest_path_sff
+ context.rest_path_sfp = args.rest_path_sfp
+ context.rest_path_acl = args.rest_path_acl
+ context.rest_path_rsp = args.rest_path_rsp
+ context.set_path_prefix_paths(context.rest_path_prefix)
+
+ for path in [context.rest_path_sf, context.rest_path_sfc, context.rest_path_sff, context.rest_path_sfp]:
+ print '\tUsing REST file: %s' % path
+
+ if args.batch:
+ context.interractive = False
+ if args.send_all:
+ context.batch_sf = True
+ context.batch_sf_sel = True
+ context.batch_sfc = True
+ context.batch_sff = True
+ context.batch_sfp = True
+ context.batch_rsp = True
+ # TODO deactivated for now
+ #context.batch_acl = True
+ else:
+ context.batch_sf = args.send_sf
+ context.batch_sf_sel = args.send_sf_sel
+ context.batch_sfc = args.send_sfc
+ context.batch_sff = args.send_sff
+ context.batch_sfp = args.send_sfp
+ context.batch_rsp = args.send_rsp
+ # TODO deactivated for now
+ #context.batch_acl = args.send_acl
+ context.batch_query = args.query_sfc
+
+ return True
+
+
+def send_rest(context, operation, rest_url, rest_file=None):
+ """
+ Send an HTTP REST message
+ Keyword arguments:
+ context -- specifies the destination IP/Port and user/pw
+ operation -- specifies if the HTTP OP is one of: GET, PUT, or POST
+ rest_url -- the operation URL
+ rest_file -- for PUT and POST operations, specifies where the JSON input is found
+ """
+
+ complete_url = '%s%s' % (context.url_base, rest_url)
+
+ if rest_file:
+ if not os.path.exists(rest_file):
+ print 'REST file [%s] does not exists' % rest_file
+ return False
+
+ try:
+ if operation == GET:
+ r = requests.get(url = complete_url,
+ headers = context.http_headers,
+ auth=(context.user, context.pw))
+
+ print '\nHTTP GET %s\nresult: %s' % (rest_url, r.status_code)
+ #if len(r.text) > 1:
+ if r.status_code >= 200 and r.status_code <= 299:
+ print json.dumps(json.loads(r.text), indent=4, separators=(',', ': '))
+
+ elif operation == PUT:
+ if not rest_file:
+ print 'ERROR trying to PUT with empty REST file'
+ return False
+
+ r = requests.put(url = complete_url,
+ auth=(context.user, context.pw),
+ data = json.dumps(json.load(open(rest_file, 'r'))),
+ headers = context.http_headers)
+ print '\nHTTP PUT %s\nresult: %s' % (rest_url, r.status_code)
+
+ elif operation == POST:
+ if not rest_file:
+ print 'ERROR trying to POST with empty REST file'
+ return False
+
+ post_list = json.load(open(rest_file, 'r'))
+ if len(post_list) > 1:
+ # This allows for multiple RSPs to be sent from one JSON file
+ for entry in post_list:
+ r = requests.post(url = complete_url,
+ auth=(context.user, context.pw),
+ data = json.dumps(entry),
+ headers = context.http_headers)
+ print '\nHTTP POST %s\nresult: %s' % (rest_url, r.status_code)
+ else:
+ r = requests.post(url = complete_url,
+ auth=(context.user, context.pw),
+ data = json.dumps(post_list),
+ headers = context.http_headers)
+ print '\nHTTP POST %s\nresult: %s' % (rest_url, r.status_code)
+ else:
+ print 'ERROR: Invalid Operation: %s' % (operation)
+
+ except requests.exceptions.ConnectionError as ce:
+ print 'ERROR connecting: %s' % (ce)
+ return False
+ except Exception as e:
+ print 'ERROR Exception: %s' % (e)
+ return False
+ except:
+ print 'ERROR unkown exception raised'
+ return False
+
+ return True
+
+def validate_rest(context):
+ """
+ For each JSON input file in context, validate the JSON syntax.
+ No validation checking is made on parameter names or types.
+ """
+
+ print ''
+ for path in [context.rest_path_sf,
+ context.rest_path_sfc,
+ context.rest_path_sff,
+ context.rest_path_sfp,
+ context.rest_path_rsp,
+ context.rest_path_sf_sel]:
+ if os.path.exists(path):
+ print 'Validating JSON file: %s' % path
+ try:
+ json.load(open(path, 'r'))
+ except ValueError as ve:
+ print '\tValidation error [%s]' % ve
+ return False
+
+ return True
+
+def batch(context):
+ """
+ Launch the application in batch mode and perform
+ the operations as specified in the Context object.
+ """
+
+ # The order of these if's is important
+ # If send-all was set, then each of these needs to be sent, in order
+ if context.batch_sf_sel:
+ send_rest(context, PUT, context.rest_url_sf_sel, context.rest_path_sf_sel)
+ if context.batch_sf:
+ send_rest(context, PUT, context.rest_url_sf, context.rest_path_sf)
+ if context.batch_sff:
+ send_rest(context, PUT, context.rest_url_sff, context.rest_path_sff)
+ if context.batch_sfc:
+ send_rest(context, PUT, context.rest_url_sfc, context.rest_path_sfc)
+ if context.batch_sfp:
+ send_rest(context, PUT, context.rest_url_sfp, context.rest_path_sfp)
+ if context.batch_rsp:
+ send_rest(context, POST, context.rest_url_rsp_rpc, context.rest_path_rsp)
+ if context.batch_acl:
+ send_rest(context, PUT, context.rest_url_acl, context.rest_path_acl)
+
+ if context.batch_query:
+ send_rest(context, GET, context.rest_url_sf_sel)
+ send_rest(context, GET, context.rest_url_sf)
+ send_rest(context, GET, context.rest_url_sff)
+ send_rest(context, GET, context.rest_url_sfc)
+ send_rest(context, GET, context.rest_url_sfp)
+ send_rest(context, GET, context.rest_url_rsp)
+ # TODO deactivated for now
+ #send_rest(context, GET, context.rest_url_acl)
+
+
+def CLI(context):
+ """
+ Run a simple Command Line Interface.
+ The Context object is used for sending rest messages
+ """
+
+ option = '1'
+ while option != '0':
+ print '\n\nChoose Option to perform:'
+ print ' 0) Quit'
+ print ' 1) Send SF REST'
+ print ' 2) Send SFC REST'
+ print ' 3) Send SFF REST'
+ print ' 4) Send SFP REST'
+ print ' 5) Send RSP REST'
+ print ' 6) Send ACL REST'
+ print ' 7) Send all ordered: (SFsel, SF, SFF, SFC, SFP, RSP)'
+ print ' 8) Query all: (SFsel, SF, SFF, SFC, SFP, RSP)'
+ print ' 9) Change config file path, currently [%s]' % (context.rest_path_prefix)
+ print '10) Validate config files JSON syntax'
+
+ option = raw_input('=> ')
+
+ if option == '1':
+ send_rest(context, PUT, context.rest_url_sf, context.rest_path_sf)
+ elif option == '2':
+ send_rest(context, PUT, context.rest_url_sfc, context.rest_path_sfc)
+ elif option == '3':
+ send_rest(context, PUT, context.rest_url_sff, context.rest_path_sff)
+ elif option == '4':
+ send_rest(context, PUT, context.rest_url_sfp, context.rest_path_sfp)
+ elif option == '5':
+ send_rest(context, POST, context.rest_url_rsp_rpc, context.rest_path_rsp)
+ elif option == '6':
+ send_rest(context, PUT, context.rest_url_acl, context.rest_path_acl)
+ elif option == '7':
+ pdb.set_trace()
+ send_rest(context, PUT, context.rest_url_sf_sel, context.rest_path_sf_sel)
+ send_rest(context, PUT, context.rest_url_sf, context.rest_path_sf)
+ send_rest(context, PUT, context.rest_url_sff, context.rest_path_sff)
+ send_rest(context, PUT, context.rest_url_sfc, context.rest_path_sfc)
+ send_rest(context, PUT, context.rest_url_sfp, context.rest_path_sfp)
+ time.sleep(1);
+ send_rest(context, POST, context.rest_url_rsp_rpc, context.rest_path_rsp)
+ # TODO ACL deactivated for now
+ # Need to wait until the SFC creates the RSP internally before sending the ACL
+ #print 'Sleeping 2 seconds while RSP being created'
+ #time.sleep(2);
+ #send_rest(context, PUT, context.rest_url_acl, context.rest_path_acl)
+ elif option == '8':
+ send_rest(context, GET, context.rest_url_sf_sel)
+ send_rest(context, GET, context.rest_url_sf)
+ send_rest(context, GET, context.rest_url_sff)
+ send_rest(context, GET, context.rest_url_sfc)
+ send_rest(context, GET, context.rest_url_sfp)
+ send_rest(context, GET, context.rest_url_rsp)
+ send_rest(context, GET, context.rest_url_acl)
+ elif option == '9':
+ path_prefix = raw_input('Enter path => ')
+ if not os.path.exists(path_prefix):
+ print 'ERROR: path does not exist: [%s]' % (path_prefix)
+ else:
+ context.set_path_prefix_paths(path_prefix)
+ elif option == '10':
+ validate_rest(context)
+ elif option != '0':
+ print 'ERROR: Invalid option %s' % (option)
+
+
+def main():
+ """
+ Main entry point into the VnfMgrSim application.
+ Command line arguments are expected.
+ Example invocations:
+ To display application command-line help:
+ vnfmgr_odl.py --help
+ To start the application in interractive mode:
+ vnfmgr_odl.py -prefix <input json dir>
+ To start the application in batch mode and send an SF JSON REST message:
+ vnfmgr_odl.py -b -prefix <input json dir> --send-sf
+ """
+
+ context = Context()
+ if not get_cmd_line(context):
+ return 1
+
+ if context.interractive:
+ CLI(context)
+ else:
+ batch(context)
+
+ return 0
+
+if __name__ == '__main__':
+ main()
+
diff --git a/vnfmgr/vnfmgr_os/__init__.py b/vnfmgr/vnfmgr_os/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vnfmgr/vnfmgr_os/__init__.py
diff --git a/vnfmgr/vnfmgr_os/vnfmgr_os.py b/vnfmgr/vnfmgr_os/vnfmgr_os.py
new file mode 100755
index 0000000..0067850
--- /dev/null
+++ b/vnfmgr/vnfmgr_os/vnfmgr_os.py
@@ -0,0 +1,68 @@
+#################################################################
+# #
+# Copyright 2015 Ericsson AB #
+# All Rights Reserved #
+# #
+# Author: Manuel Buil <Manuel.Buil@ericsson.com> #
+# Version: 0.1 #
+# #
+#################################################################
+
+import pdb
+
+from novaclient.v2 import client as nova
+from novaclient import exceptions as novaexceptions
+from keystoneclient.v2_0 import client as keystone
+from glanceclient import client as glance
+
+
+class OpenStack_API:
+ def __init__(self, authurl, tenantName, tenantUser, tenantPass):
+ self.authurl=authurl
+ self.tenantName=tenantName
+ self.tenantUser=tenantUser
+ self.tenantPass=tenantPass
+
+ def get_token(self):
+ # Establish connection to Openstack controller
+ osconn = keystone.Client(username=self.tenantUser, password=self.tenantPass, tenant_name=self.tenantName, auth_url=self.authurl)
+ token = osconn.auth_token
+ return token
+
+ def get_endpoint(self,service_type, endpoint_type):
+ # Establish connection to Openstack controller
+ osconn = keystone.Client(username=self.tenantUser, password=self.tenantPass, tenant_name=self.tenantName, auth_url=self.authurl)
+ endpoint = osconn.service_catalog.url_for(service_type=service_type, endpoint_type=endpoint_type)
+ return endpoint
+
+ def find_image(self,SF_type):
+ # Find in glance the image that matches the SF we want to deploy
+ token = self.get_token()
+ endpoint = self.get_endpoint('image','publicURL')
+ osconn = glance.Client('1',endpoint=endpoint,token=token)
+ image_list = osconn.images.list()
+ for item in image_list:
+ try:
+ image_type = item.properties.get('image_type', None)
+ image_id=None
+ if (image_type == SF_type):
+ image_id = item.id
+ break
+ except:
+ print("Errrorr")
+
+ #Search image which matches the SF type
+ return image_id
+
+ def create_vm(self, name, image, flavor, nics=None):
+ # Establish connection to Openstack controller
+ osconn = nova.Client(self.tenantUser, self.tenantPass, self.tenantName, self.authurl, service_type="compute")
+ try:
+ if nics is None:
+ vm = osconn.servers.create(name,image,flavor)
+ else:
+ vm = osconn.servers.create(name,image,flavor,nics)
+ except:
+ print("Something wrong happened while creating the VM")
+ vm = None
+ return vm