# This is a template with common files to be igonored, after clone make a copy to .gitignore
# cp .gitignore-common .gitignore
-*.pyc
+*.pyc
+*.pyo
#auto-ignore
.gitignore
[ $OPENMANO_VER_NUM -ge 4059 ] && DATABASE_TARGET_VER_NUM=15 #0.4.59=> 15
[ $OPENMANO_VER_NUM -ge 5002 ] && DATABASE_TARGET_VER_NUM=16 #0.5.2 => 16
[ $OPENMANO_VER_NUM -ge 5003 ] && DATABASE_TARGET_VER_NUM=17 #0.5.3 => 17
+[ $OPENMANO_VER_NUM -ge 5004 ] && DATABASE_TARGET_VER_NUM=18 #0.5.4 => 18
#TODO ... put next versions here
echo "DELETE FROM schema_version WHERE version_int='17';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
}
+function upgrade_to_18(){
+ echo " upgrade database from version 0.17 to version 0.18"
+ echo " add columns 'floating_ip' and 'port_security' at tables 'interfaces' and 'instance_interfaces'"
+ echo "ALTER TABLE interfaces ADD floating_ip BOOL DEFAULT 0 NOT NULL COMMENT 'Indicates if a floating_ip must be associated to this interface';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+ echo "ALTER TABLE interfaces ADD port_security BOOL DEFAULT 1 NOT NULL COMMENT 'Indicates if port security must be enabled or disabled. By default it is enabled';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+ echo "ALTER TABLE instance_interfaces ADD floating_ip BOOL DEFAULT 0 NOT NULL COMMENT 'Indicates if a floating_ip must be associated to this interface';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+ echo "ALTER TABLE instance_interfaces ADD port_security BOOL DEFAULT 1 NOT NULL COMMENT 'Indicates if port security must be enabled or disabled. By default it is enabled';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+ echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (18, '0.18', '0.5.4', 'Add columns \'floating_ip\' and \'port_security\' at tables \'interfaces\' and \'instance_interfaces\'', '2017-01-09');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+}
+function downgrade_from_18(){
+ echo " downgrade database from version 0.18 to version 0.17"
+ echo " remove columns 'floating_ip' and 'port_security' from tables 'interfaces' and 'instance_interfaces'"
+ echo "ALTER TABLE interfaces DROP COLUMN floating_ip;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+ echo "ALTER TABLE interfaces DROP COLUMN port_security;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+ echo "ALTER TABLE instance_interfaces DROP COLUMN floating_ip;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+ echo "ALTER TABLE instance_interfaces DROP COLUMN port_security;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+ echo "DELETE FROM schema_version WHERE version_int='18';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+}
+
function upgrade_to_X(){
echo " change 'datacenter_nets'"
echo "ALTER TABLE datacenter_nets ADD COLUMN vim_tenant_id VARCHAR(36) NOT NULL AFTER datacenter_id, DROP INDEX name_datacenter_id, ADD UNIQUE INDEX name_datacenter_id (name, datacenter_id, vim_tenant_id);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
_convert_str2boolean(data[k], items)
if k in items:
if type(data[k]) is str:
- if data[k]=="false" or data[k]=="False": data[k]=False
- elif data[k]=="true" or data[k]=="True": data[k]=True
+ if data[k]=="false" or data[k]=="False" or data[k]=="0": data[k]=False
+ elif data[k]=="true" or data[k]=="True" or data[k]=="1": data[k]=True
+ elif type(data[k]) is int:
+ if data[k]==0: data[k]=False
+ elif data[k]==1: data[k]=True
if type(data) is tuple or type(data) is list:
for k in data:
if type(k) is dict or type(k) is tuple or type(k) is list:
netDict['vpci'] = iface['vpci']
if "mac" in iface and iface["mac"] is not None:
netDict['mac_address'] = iface['mac']
+ if "port-security" in iface and iface["port-security"] is not None:
+ netDict['port_security'] = iface['port-security']
+ if "floating-ip" in iface and iface["floating-ip"] is not None:
+ netDict['floating_ip'] = iface['floating-ip']
netDict['name'] = iface['internal_name']
if iface['net_id'] is None:
for vnf_iface in sce_vnf["interfaces"]:
netDict['vpci'] = iface['vpci']
if "mac" in iface and iface["mac"] is not None:
netDict['mac_address'] = iface['mac']
+ if "port-security" in iface and iface["port-security"] is not None:
+ netDict['port_security'] = iface['port-security']
+ if "floating-ip" in iface and iface["floating-ip"] is not None:
+ netDict['floating_ip'] = iface['floating-ip']
netDict['name'] = iface['internal_name']
if iface['net_id'] is None:
for vnf_iface in sce_vnf["interfaces"]:
if 'bridge-ifaces' in vm:
bridgeInterfacesDict[vm['name']] = {}
for bridgeiface in vm['bridge-ifaces']:
+ if 'port-security' in bridgeiface:
+ bridgeiface['port_security'] = bridgeiface.pop('port-security')
+ if 'floating-ip' in bridgeiface:
+ bridgeiface['floating_ip'] = bridgeiface.pop('floating-ip')
db_base._convert_bandwidth(bridgeiface, logger=self.logger)
bridgeInterfacesDict[vm['name']][bridgeiface['name']] = {}
bridgeInterfacesDict[vm['name']][bridgeiface['name']]['vpci'] = bridgeiface.get('vpci',None)
bridgeInterfacesDict[vm['name']][bridgeiface['name']]['mac'] = bridgeiface.get('mac_address',None)
bridgeInterfacesDict[vm['name']][bridgeiface['name']]['bw'] = bridgeiface.get('bandwidth', None)
bridgeInterfacesDict[vm['name']][bridgeiface['name']]['model'] = bridgeiface.get('model', None)
+ bridgeInterfacesDict[vm['name']][bridgeiface['name']]['port_security'] = \
+ int(bridgeiface.get('port_security', True))
+ bridgeInterfacesDict[vm['name']][bridgeiface['name']]['floating_ip'] = \
+ int(bridgeiface.get('floating_ip', False))
#For each internal connection, we add it to the interfaceDict and we create the appropriate net in the NFVO database.
#print "Adding new nets (VNF internal nets) to the NFVO database (if any)"
ifaceItem["mac"] = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['mac_address']
ifaceItem["bw"] = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['bw']
ifaceItem["model"] = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['model']
+ ifaceItem["port_security"] = \
+ bridgeInterfacesDict[element['VNFC']][element['local_iface_name']]['port_security']
+ ifaceItem["floating_ip"] = \
+ bridgeInterfacesDict[element['VNFC']][element['local_iface_name']]['floating_ip']
internalconnList.append(ifaceItem)
#print "Internal net id in NFVO DB: %s" % net_id
myIfaceDict["bw"] = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['bw']
myIfaceDict["model"] = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['model']
myIfaceDict["mac"] = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['mac']
+ myIfaceDict["port_security"] = \
+ bridgeInterfacesDict[iface['VNFC']][iface['local_iface_name']]['port_security']
+ myIfaceDict["floating_ip"] = \
+ bridgeInterfacesDict[iface['VNFC']][iface['local_iface_name']]['floating_ip']
print "Iface name: %s" % iface['name']
created_time += 0.00001
iface_id = self._new_row_internal('interfaces', myIfaceDict, add_uuid=True, root_uuid=vnf_id, created_time=created_time)
bridgeInterfacesDict[vm['name']] = {}
for bridgeiface in vm['bridge-ifaces']:
db_base._convert_bandwidth(bridgeiface, logger=self.logger)
+ if 'port-security' in bridgeiface:
+ bridgeiface['port_security'] = bridgeiface.pop('port-security')
+ if 'floating-ip' in bridgeiface:
+ bridgeiface['floating_ip'] = bridgeiface.pop('floating-ip')
bridgeInterfacesDict[vm['name']][bridgeiface['name']] = {}
bridgeInterfacesDict[vm['name']][bridgeiface['name']]['vpci'] = bridgeiface.get('vpci',None)
bridgeInterfacesDict[vm['name']][bridgeiface['name']]['mac'] = bridgeiface.get('mac_address',None)
bridgeInterfacesDict[vm['name']][bridgeiface['name']]['bw'] = bridgeiface.get('bandwidth', None)
bridgeInterfacesDict[vm['name']][bridgeiface['name']]['model'] = bridgeiface.get('model', None)
+ bridgeInterfacesDict[vm['name']][bridgeiface['name']]['port_security'] = \
+ int(bridgeiface.get('port_security', True))
+ bridgeInterfacesDict[vm['name']][bridgeiface['name']]['floating_ip'] = \
+ int(bridgeiface.get('floating_ip', False))
#For each internal connection, we add it to the interfaceDict and we create the appropriate net in the NFVO database.
#print "Adding new nets (VNF internal nets) to the NFVO database (if any)"
ifaceItem["mac"] = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['mac']
ifaceItem["bw"] = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['bw']
ifaceItem["model"] = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['model']
+ ifaceItem["port_security"] = \
+ bridgeInterfacesDict[element['VNFC']][element['local_iface_name']]['port_security']
+ ifaceItem["floating_ip"] = \
+ bridgeInterfacesDict[element['VNFC']][element['local_iface_name']]['floating_ip']
internalconnList.append(ifaceItem)
#print "Internal net id in NFVO DB: %s" % net_id
myIfaceDict["bw"] = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['bw']
myIfaceDict["model"] = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['model']
myIfaceDict["mac"] = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['mac']
+ myIfaceDict["port_security"] = \
+ bridgeInterfacesDict[iface['VNFC']][iface['local_iface_name']]['port_security']
+ myIfaceDict["floating_ip"] = \
+ bridgeInterfacesDict[iface['VNFC']][iface['local_iface_name']]['floating_ip']
print "Iface name: %s" % iface['name']
created_time += 0.00001
iface_id = self._new_row_internal('interfaces', myIfaceDict, add_uuid=True, root_uuid=vnf_id, created_time=created_time)
vm['vim_flavor_id']=vim_flavor_dict['vim_id']
#interfaces
- cmd = "SELECT uuid,internal_name,external_name,net_id,type,vpci,mac,bw,model,ip_address" \
+ cmd = "SELECT uuid,internal_name,external_name,net_id,type,vpci,mac,bw,model,ip_address," \
+ "floating_ip, port_security" \
" FROM interfaces" \
" WHERE vm_id='{}'" \
" ORDER BY created_at".format(vm['uuid'])
self.logger.debug(cmd)
self.cur.execute(cmd)
vm['interfaces'] = self.cur.fetchall()
+ for index in range(0,len(vm['interfaces'])):
+ vm['interfaces'][index]['port-security'] = vm['interfaces'][index].pop("port_security")
+ vm['interfaces'][index]['floating-ip'] = vm['interfaces'][index].pop("floating_ip")
#nets every net of a vms
cmd = "SELECT uuid,name,type,description FROM nets WHERE vnf_id='{}'".format(vnf['vnf_id'])
self.logger.debug(cmd)
net['vim_id']=d_net['vim_net_id']
db_base._convert_datetime2str(scenario_dict)
- db_base._convert_str2boolean(scenario_dict, ('public','shared','external') )
+ db_base._convert_str2boolean(scenario_dict, ('public','shared','external','port-security','floating-ip') )
return scenario_dict
except (mdb.Error, AttributeError) as e:
self._format_error(e, tries)
interface_type='external' if interface['external_name'] is not None else 'internal'
INSERT_={'instance_vm_id': instance_vm_uuid, 'instance_net_id': net_scene2instance[net_id][datacenter_site_id],
'interface_id': interface['uuid'], 'vim_interface_id': interface.get('vim_id'), 'type': interface_type,
- 'ip_address': interface.get('ip_address') }
+ 'ip_address': interface.get('ip_address'), 'floating_ip': int(interface.get('floating-ip',False)),
+ 'port_security': int(interface.get('port-security',True))}
#created_time += 0.00001
interface_uuid = self._new_row_internal('instance_interfaces', INSERT_, True, instance_uuid) #, created_time)
interface['uuid'] = interface_uuid #overwrite scnario uuid by instance uuid
if args.scenario != None:
scenario = args.scenario
if not scenario:
- print "you must provide an scenario in the file descriptor or with --scenario"
+ print "you must provide a scenario in the file descriptor or with --scenario"
return -1
myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
if args.netmap_use:
"bandwidth":bandwidth_schema,
"vpci":pci_schema,
"mac_address": mac_schema,
- "model": {"type":"string", "enum":["virtio","e1000","ne2k_pci","pcnet","rtl8139"]}
+ "model": {"type":"string", "enum":["virtio","e1000","ne2k_pci","pcnet","rtl8139"]},
+ "port-security": {"type" : "boolean"},
+ "floating-ip": {"type" : "boolean"}
},
"additionalProperties": False,
"required": ["name"]
'''
__author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
__date__ ="$26-aug-2014 11:09:29$"
-__version__="0.5.3-r511"
-version_date="Dec 2016"
-database_version="0.17" #expected database schema version
+__version__="0.5.4-r512"
+version_date="Jan 2017"
+database_version="0.18" #expected database schema version
import httpserver
import time
--- /dev/null
+##
+# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
+# This file is part of openmano
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+---
+schema_version: 2
+scenario:
+ name: vnf_floating_ip
+ description: vnf_floating_ip
+ public: false # if available for other tenants
+ vnfs:
+ vnf_floating_ip: # vnf name in the scenario
+ #identify an already openmano uploaded VNF either by vnf_id (uuid, prefered) or vnf_name
+ #vnf_id: 0c0dcc20-c5d5-11e6-a9fb-fa163e2ae06e #prefered id method
+ vnf_name: vnf_floating_ip #can fail if several vnfs matches this name
+ #graph: {"y":399,"x":332,"ifaces":{"left":[["xe0","d"],["xe1","d"]],"bottom":[["eth0","v"],["eth1","m"]]}}
+ networks:
+ internal:
+ # Connections based on external networks (datacenter nets) must include the external network in the list of nodes
+ type: bridge
+ external: true #this will be connected outside
+ interfaces:
+ - vnf_floating_ip: mgmt0
+
--- /dev/null
+##
+# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
+# This file is part of openmano
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+---
+schema_version: 2
+scenario:
+ name: vnf_no_port_security
+ description: vnf_no_port_security
+ public: false # if available for other tenants
+ vnfs:
+ vnf_no_port_security: # vnf name in the scenario
+ #identify an already openmano uploaded VNF either by vnf_id (uuid, prefered) or vnf_name
+ #vnf_id: 0c0dcc20-c5d5-11e6-a9fb-fa163e2ae06e #prefered id method
+ vnf_name: vnf_no_port_security #can fail if several vnfs matches this name
+ #graph: {"y":399,"x":332,"ifaces":{"left":[["xe0","d"],["xe1","d"]],"bottom":[["eth0","v"],["eth1","m"]]}}
+ networks:
+ internal:
+ # Connections based on external networks (datacenter nets) must include the external network in the list of nodes
+ type: bridge
+ external: true #this will be connected outside
+ interfaces:
+ - vnf_no_port_security: mgmt0
+
[ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && easy_install -U bottle
#install openstack client needed for using openstack as a VIM
-[ "$_DISTRO" == "Ubuntu" ] && install_packages "python-novaclient python-keystoneclient python-glanceclient python-neutronclient"
-[ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "python-devel" && easy_install python-novaclient python-keystoneclient python-glanceclient python-neutronclient #TODO revise if gcc python-pip is needed
+[ "$_DISTRO" == "Ubuntu" ] && install_packages "python-novaclient python-keystoneclient python-glanceclient python-neutronclient python-cinderclient"
+[ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "python-devel" && easy_install python-novaclient python-keystoneclient python-glanceclient python-neutronclient python-cinderclient #TODO revise if gcc python-pip is needed
fi #[[ -z "$NO_PACKAGES" ]]
if [[ -z $NOCLONE ]]; then
--- /dev/null
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+
+##
+# 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
+##
+
+'''
+Module to test openmanoclient class and indirectly the whole openmano
+It allows both python 2 and python 3
+'''
+__author__="Alfonso Tierno"
+__date__ ="$09-Mar-2016 09:09:48$"
+__version__="0.0.2"
+version_date="May 2016"
+
+import logging
+import imp
+
+
+
+def _get_random_name(maxLength):
+ '''generates a string with random craracters from space (ASCCI 32) to ~(ASCCI 126)
+ with a random length up to maxLength
+ '''
+ long_name = "testing up to {} size name: ".format(maxLength)
+ #long_name += ''.join(chr(random.randint(32,126)) for _ in range(random.randint(20, maxLength-len(long_name))))
+ long_name += ''.join(random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ') for _ in range(20, maxLength-len(long_name)))
+ return long_name
+
+
+if __name__=="__main__":
+ import getopt
+ #import os
+ import sys
+
+
+
+ usage =\
+ """Make a test against an openmano server.\nUsage: test_openmanoclient [options]
+ -v|--verbose: prints more info in the test
+ --version: shows current version
+ -h|--help: shows this help
+ -d|--debug: set logs to debug level
+ -t|--tenant: set the tenant name to test. By default creates one
+ --datacenter: set the datacenter name to test. By default creates one at http://localhost:9080/openvim
+ -u|--url: set the openmano server url. By default 'http://localhost:9090/openmano'
+ --image: use this image path for testing a VNF. By default a fake one is generated, valid for VIM in test mode'
+ """
+
+ #import openmanoclient from relative path
+ module_info = imp.find_module("openmanoclient", [".."] )
+ Client = imp.load_module("Client", *module_info)
+
+ streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
+ logging.basicConfig(format=streamformat)
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "t:u:dhv", ["url=", "tenant=", "debug", "help", "version", "verbose", "datacenter=", "image="])
+ except getopt.GetoptError as err:
+ print ("Error: {}\n Try '{} --help' for more information".format(str(err), sys.argv[0]))
+ sys.exit(2)
+
+ debug = False
+ verbose = False
+ url = "http://localhost:9090/openmano"
+ to_delete_list=[]
+ test_tenant = None
+ test_datacenter = None
+ test_vim_tenant = None
+ test_image = None
+ for o, a in opts:
+ if o in ("-v", "--verbose"):
+ verbose = True
+ elif o in ("--version"):
+ print ("{} version".format(sys.argv[0]), __version__, version_date)
+ print ("(c) Copyright Telefonica")
+ sys.exit()
+ elif o in ("-h", "--help"):
+ print(usage)
+ sys.exit()
+ elif o in ("-d", "--debug"):
+ debug = True
+ elif o in ("-u", "--url"):
+ url = a
+ elif o in ("-t", "--tenant"):
+ test_tenant = a
+ elif o in ("--datacenter"):
+ test_datacenter = a
+ elif o in ("--image"):
+ test_image = a
+ else:
+ assert False, "Unhandled option"
+
+
+
+ client = Client.openmanoclient(
+ endpoint_url=url,
+ tenant_name=test_tenant,
+ datacenter_name = test_datacenter,
+ debug = debug)
+
+ import random
+ test_number=1
+
+ #TENANTS
+ print(" {}. TEST create_tenant".format(test_number))
+ test_number += 1
+ long_name = _get_random_name(60)
+
+ tenant = client.create_tenant(name=long_name, description=long_name)
+ if verbose: print(tenant)
+
+ print(" {}. TEST list_tenants".format(test_number))
+ test_number += 1
+ tenants = client.list_tenants()
+ if verbose: print(tenants)
+
+ print(" {}. TEST list_tenans filter by name".format(test_number))
+ test_number += 1
+ tenants_ = client.list_tenants(name=long_name)
+ if not tenants_["tenants"]:
+ raise Exception("Text error, no TENANT found with name")
+ if verbose: print(tenants_)
+
+ print(" {}. TEST get_tenant by UUID".format(test_number))
+ test_number += 1
+ tenant = client.get_tenant(uuid=tenants_["tenants"][0]["uuid"])
+ if verbose: print(tenant)
+
+ print(" {}. TEST delete_tenant by name".format(test_number))
+ test_number += 1
+ tenant = client.delete_tenant(name = long_name)
+ if verbose: print(tenant)
+
+ if not test_tenant:
+ print(" {}. TEST create_tenant for remaining tests".format(test_number))
+ test_number += 1
+ test_tenant = "test-tenant "+\
+ ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(40))
+ tenant = client.create_tenant(name = test_tenant)
+ if verbose: print(tenant)
+ client["tenant_name"] = test_tenant
+
+ to_delete_list.insert(0,{"item": "tenant", "function": client.delete_tenant, "params":{"name": test_tenant} })
+
+ #DATACENTERS
+ print(" {}. TEST create_datacenter".format(test_number))
+ test_number += 1
+ long_name = _get_random_name(60)
+
+ datacenter = client.create_datacenter(name=long_name, vim_url="http://fakeurl/fake")
+ if verbose: print(datacenter)
+
+ print(" {}. TEST list_datacenters".format(test_number))
+ test_number += 1
+ datacenters = client.list_datacenters(all_tenants=True)
+ if verbose: print(datacenters)
+
+ print(" {}. TEST list_tenans filter by name".format(test_number))
+ test_number += 1
+ datacenters_ = client.list_datacenters(all_tenants=True, name=long_name)
+ if not datacenters_["datacenters"]:
+ raise Exception("Text error, no TENANT found with name")
+ if verbose: print(datacenters_)
+
+ print(" {}. TEST get_datacenter by UUID".format(test_number))
+ test_number += 1
+ datacenter = client.get_datacenter(uuid=datacenters_["datacenters"][0]["uuid"], all_tenants=True)
+ if verbose: print(datacenter)
+
+ print(" {}. TEST delete_datacenter by name".format(test_number))
+ test_number += 1
+ datacenter = client.delete_datacenter(name=long_name)
+ if verbose: print(datacenter)
+
+ if not test_datacenter:
+ print(" {}. TEST create_datacenter for remaining tests".format(test_number))
+ test_number += 1
+ test_datacenter = "test-datacenter "+\
+ ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(40))
+ datacenter = client.create_datacenter(name=test_datacenter, vim_url="http://127.0.0.1:9080/openvim")
+ if verbose: print(datacenter)
+ client["datacenter_name"] = test_datacenter
+ to_delete_list.insert(0,{"item": "datacenter", "function": client.delete_datacenter,
+ "params":{
+ "name": test_datacenter
+ }
+ })
+
+ print(" {}. TEST datacenter new tenenat".format(test_number))
+ test_number += 1
+ test_vim_tenant = "test-vimtenant "+\
+ ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(40))
+ vim_tenant = client.vim_action("create", "tenants", datacenter_name=test_datacenter, all_tenants=True, name=test_vim_tenant)
+ if verbose: print(vim_tenant)
+ client["datacenter_name"] = test_datacenter
+ to_delete_list.insert(0,{"item": "vim_tenant",
+ "function": client.vim_action,
+ "params":{
+ "action":"delete",
+ "item":"tenants",
+ "datacenter_name": test_datacenter,
+ "all_tenants": True,
+ "uuid": vim_tenant["tenant"]["id"]
+ }
+ })
+
+ print(" {}. TEST datacenter attach".format(test_number))
+ test_number += 1
+ datacenter = client.attach_datacenter(name=test_datacenter, vim_tenant_name=test_vim_tenant)
+ if verbose: print(datacenter)
+ client["datacenter_name"] = test_datacenter
+ to_delete_list.insert(0,{"item": "datacenter-detach", "function": client.detach_datacenter, "params":{"name": test_datacenter} })
+
+ client["datacenter_name"] = test_datacenter
+
+
+ #VIM_ACTIONS
+ print(" {}. TEST create_VIM_tenant".format(test_number))
+ test_number += 1
+ long_name = _get_random_name(60)
+
+ tenant = client.vim_action("create", "tenants", name=long_name)
+ if verbose: print(tenant)
+ tenant_uuid = tenant["tenant"]["id"]
+
+ print(" {}. TEST list_VIM_tenants".format(test_number))
+ test_number += 1
+ tenants = client.vim_action("list", "tenants")
+ if verbose: print(tenants)
+
+ print(" {}. TEST get_VIM_tenant by UUID".format(test_number))
+ test_number += 1
+ tenant = client.vim_action("show", "tenants", uuid=tenant_uuid)
+ if verbose: print(tenant)
+
+ print(" {}. TEST delete_VIM_tenant by id".format(test_number))
+ test_number += 1
+ tenant = client.vim_action("delete", "tenants", uuid = tenant_uuid)
+ if verbose: print(tenant)
+
+ print(" {}. TEST create_VIM_network".format(test_number))
+ test_number += 1
+ long_name = _get_random_name(60)
+
+ network = client.vim_action("create", "networks", name=long_name)
+ if verbose: print(network)
+ network_uuid = network["network"]["id"]
+
+ print(" {}. TEST list_VIM_networks".format(test_number))
+ test_number += 1
+ networks = client.vim_action("list", "networks")
+ if verbose: print(networks)
+
+ print(" {}. TEST get_VIM_network by UUID".format(test_number))
+ test_number += 1
+ network = client.vim_action("show", "networks", uuid=network_uuid)
+ if verbose: print(network)
+
+ print(" {}. TEST delete_VIM_network by id".format(test_number))
+ test_number += 1
+ network = client.vim_action("delete", "networks", uuid = network_uuid)
+ if verbose: print(network)
+ #VNFS
+ print(" {}. TEST create_vnf".format(test_number))
+ test_number += 1
+ test_vnf_name = _get_random_name(255)
+ if test_image:
+ test_vnf_path = test_image
+ else:
+ test_vnf_path = "/random/path/" + "".join(random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ') for _ in range(20))
+
+ vnf_descriptor={'vnf': {'name': test_vnf_name,
+ 'VNFC': [{'description': _get_random_name(255),
+ 'name': 'linux-VM',
+ 'VNFC image': test_vnf_path,
+ 'ram': 1024,
+ 'vcpus': 1,
+ 'bridge-ifaces': [{'name': 'eth0'}]
+ }],
+ 'description': _get_random_name(255),
+ 'nets': [],
+ 'external-connections': [{'name': 'eth0',
+ 'local_iface_name': 'eth0',
+ 'VNFC': 'linux-VM',
+ 'type': 'bridge'}],
+ 'public': False}}
+
+ vnf = client.create_vnf(descriptor=vnf_descriptor)
+ if verbose: print(vnf)
+ to_delete_list.insert(0,{"item": "vnf", "function": client.delete_vnf, "params":{"name": test_vnf_name} })
+
+ print(" {}. TEST list_vnfs".format(test_number))
+ test_number += 1
+ vnfs = client.list_vnfs()
+ if verbose: print(vnfs)
+
+ print(" {}. TEST list_vnfs filter by name".format(test_number))
+ test_number += 1
+ vnfs_ = client.list_vnfs(name=test_vnf_name)
+ if not vnfs_["vnfs"]:
+ raise Exception("Text error, no VNF found with name")
+ if verbose: print(vnfs_)
+
+ print(" {}. TEST get_vnf by UUID".format(test_number))
+ test_number += 1
+ vnf = client.get_vnf(uuid=vnfs_["vnfs"][0]["uuid"])
+ if verbose: print(vnf)
+
+ #SCENARIOS
+ print(" {}. TEST create_scenario".format(test_number))
+ test_number += 1
+ test_scenario_name = _get_random_name(255)
+
+ scenario_descriptor={ 'schema_version': 2,
+ 'scenario': {
+ 'name': test_scenario_name,
+ 'description': _get_random_name(255),
+ 'public': True,
+ 'vnfs':{
+ 'vnf1': {
+ 'vnf_name': test_vnf_name
+ }
+ },
+ 'networks':{
+ 'net1':{
+ 'external': True,
+ 'interfaces': [
+ {'vnf1': 'eth0'}
+ ]
+ }
+ }
+ }
+ }
+
+ scenario = client.create_scenario(descriptor=scenario_descriptor)
+ if verbose: print(scenario)
+ to_delete_list.insert(0,{"item": "scenario", "function": client.delete_scenario, "params":{"name": test_scenario_name} })
+
+ print(" {}. TEST list_scenarios".format(test_number))
+ test_number += 1
+ scenarios = client.list_scenarios()
+ if verbose: print(scenarios)
+
+ print(" {}. TEST list_scenarios filter by name".format(test_number))
+ test_number += 1
+ scenarios_ = client.list_scenarios(name=test_scenario_name)
+ if not scenarios_["scenarios"]:
+ raise Exception("Text error, no VNF found with name")
+ if verbose: print(scenarios_)
+
+ print(" {}. TEST get_scenario by UUID".format(test_number))
+ test_number += 1
+ scenario = client.get_scenario(uuid=scenarios_["scenarios"][0]["uuid"])
+ if verbose: print(scenario)
+
+
+
+ #INSTANCES
+ print(" {}. TEST create_instance".format(test_number))
+ test_number += 1
+ test_instance_name = _get_random_name(255)
+
+ instance_descriptor={ 'schema_version': 2,
+ 'instance': {
+ 'name': test_instance_name,
+ 'description': _get_random_name(255),
+ 'public': True,
+ 'vnfs':{
+ 'vnf1': {
+ 'vnf_name': test_vnf_name
+ }
+ },
+ 'networks':{
+ 'net1':{
+ 'external': True,
+ 'interfaces': [
+ {'vnf1': 'eth0'}
+ ]
+ }
+ }
+ }
+ }
+
+ instance = client.create_instance(scenario_name=test_scenario_name, name=test_instance_name )
+ if verbose: print(instance)
+ to_delete_list.insert(0,{"item": "instance", "function": client.delete_instance, "params":{"name": test_instance_name} })
+
+ print(" {}. TEST list_instances".format(test_number))
+ test_number += 1
+ instances = client.list_instances()
+ if verbose: print(instances)
+
+ print(" {}. TEST list_instances filter by name".format(test_number))
+ test_number += 1
+ instances_ = client.list_instances(name=test_instance_name)
+ if not instances_["instances"]:
+ raise Exception("Text error, no VNF found with name")
+ if verbose: print(instances_)
+
+ print(" {}. TEST get_instance by UUID".format(test_number))
+ test_number += 1
+ instance = client.get_instance(uuid=instances_["instances"][0]["uuid"])
+ if verbose: print(instance)
+
+
+
+
+ #DELETE Create things
+ for item in to_delete_list:
+ print(" {}. TEST delete_{}".format(test_number, item["item"]))
+ test_number += 1
+ response = item["function"](**item["params"])
+ if verbose: print(response)
+
#global var to have a timeout creating and deleting volumes
volume_timeout = 60
+server_timeout = 60
class vimconnector(vimconn.vimconnector):
def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None, config={}):
if self.osc_api_version == 'v3.3':
self.k_creds['project_name'] = tenant_name
self.k_creds['project_id'] = tenant_id
+ if config.get('region_name'):
+ self.k_creds['region_name'] = config.get('region_name')
+ self.n_creds['region_name'] = config.get('region_name')
self.reload_client = True
self.logger = logging.getLogger('openmano.vim.openstack')
port_dict["name"]=name
if net.get("mac_address"):
port_dict["mac_address"]=net["mac_address"]
+ if net.get("port_security") == False:
+ port_dict["port_security_enabled"]=net["port_security"]
new_port = self.neutron.create_port({"port": port_dict })
net["mac_adress"] = new_port["port"]["mac_address"]
net["vim_id"] = new_port["port"]["id"]
#delete ports we just created
for net_item in net_list_vim:
if 'port-id' in net_item:
- self.neutron.delete_port(net_item['port_id'])
+ self.neutron.delete_port(net_item['port-id'])
raise vimconn.vimconnException('Timeout creating volumes for instance ' + name,
http_code=vimconn.HTTP_Request_Timeout)
block_device_mapping = block_device_mapping
) # , description=description)
#print "DONE :-)", server
-
pool_id = None
floating_ips = self.neutron.list_floatingips().get("floatingips", ())
for floating_network in external_network:
+ # wait until vm is active
+ elapsed_time = 0
+ while elapsed_time < server_timeout:
+ status = self.nova.servers.get(server.id).status
+ if status == 'ACTIVE':
+ break
+ time.sleep(1)
+ elapsed_time += 1
+
+ #if we exceeded the timeout rollback
+ if elapsed_time >= server_timeout:
+ self.delete_vminstance(server.id)
+ raise vimconn.vimconnException('Timeout creating instance ' + name,
+ http_code=vimconn.HTTP_Request_Timeout)
+
assigned = False
while(assigned == False):
if floating_ips:
ip = floating_ips.pop(0)
- if not ip.get("port_id", False):
+ if not ip.get("port_id", False) and ip.get('tenant_id') == server.tenant_id:
free_floating_ip = ip.get("floating_ip_address")
try:
fix_ip = floating_network.get('ip')
self.delete_vminstance(server.id)
raise vimconn.vimconnException(type(e).__name__ + ": Cannot create floating_ip "+ str(e), http_code=vimconn.HTTP_Conflict)
else:
- pool_id = floating_network.get('net_id')
- param = {'floatingip': {'floating_network_id': pool_id}}
+ #Find the external network
+ external_nets = list()
+ for net in self.neutron.list_networks()['networks']:
+ if net['router:external']:
+ external_nets.append(net)
+
+ if len(external_nets) == 0:
+ self.delete_vminstance(server.id)
+ raise vimconn.vimconnException("Cannot create floating_ip automatically since no external "
+ "network is present",
+ http_code=vimconn.HTTP_Conflict)
+ if len(external_nets) > 1:
+ self.delete_vminstance(server.id)
+ raise vimconn.vimconnException("Cannot create floating_ip automatically since multiple "
+ "external networks are present",
+ http_code=vimconn.HTTP_Conflict)
+
+ pool_id = external_nets[0].get('id')
+ param = {'floatingip': {'floating_network_id': pool_id, 'tenant_id': server.tenant_id}}
try:
#self.logger.debug("Creating floating IP")
new_floating_ip = self.neutron.create_floatingip(param)
# error_text= "vm instance %s not found" % vm_id
except (ksExceptions.ClientException, nvExceptions.ClientException, ConnectionError
) as e:
+ # delete the volumes we just created
+ if block_device_mapping != None:
+ for volume_id in block_device_mapping.itervalues():
+ self.cinder.volumes.delete(volume_id)
+
+ # delete ports we just created
+ for net_item in net_list_vim:
+ if 'port-id' in net_item:
+ self.neutron.delete_port(net_item['port-id'])
self._format_exception(e)
except TypeError as e:
raise vimconn.vimconnException(type(e).__name__ + ": "+ str(e), http_code=vimconn.HTTP_Bad_Request)
'''Adds a tenant flavor to VIM'''
'''Returns the flavor identifier'''
try:
+ new_flavor_dict = flavor_data.copy()
+ new_flavor_dict["name"] = flavor_data["name"][:64]
self._get_my_tenant()
- payload_req = json.dumps({'flavor': flavor_data})
+ payload_req = json.dumps({'flavor': new_flavor_dict})
url = self.url+'/'+self.tenant+'/flavors'
self.logger.info("Adding a new VIM flavor POST %s", url)
vim_response = requests.post(url, headers = self.headers_req, data=payload_req)
''' Adds a tenant image to VIM, returns image_id'''
try:
self._get_my_tenant()
- new_image_dict={'name': image_dict['name']}
+ new_image_dict={'name': image_dict['name'][:64]}
if image_dict.get('description'):
new_image_dict['description'] = image_dict['description']
if image_dict.get('metadata'):
if net.get("model"): net_dict["model"] = net["model"]
if net.get("mac_address"): net_dict["mac_address"] = net["mac_address"]
virtio_net_list.append(net_dict)
- payload_dict={ "name": name,
+ payload_dict={ "name": name[:64],
"description": description,
"imageRef": image_id,
"flavorRef": flavor_id,
--- /dev/null
+##
+# 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
+##
+---
+vnf:
+ name: vnf_floating_ip
+ description: VNF disabling port_security option in mgmt interface
+ # class: parent # Optional. Used to organize VNFs
+ external-connections:
+ - name: mgmt0
+ type: mgmt # "mgmt" (autoconnect to management net), "bridge", "data"
+ VNFC: vnf_floating_ip # Virtual Machine this interface belongs to
+ local_iface_name: mgmt0 # interface name inside this Virtual Machine (must be defined in the VNFC section)
+ description: Management interface
+ VNFC: # Virtual machine array
+ - name: vnf_floating_ip # name of Virtual Machine
+ description: vnf_floating_ip
+# VNFC image: /path/to/imagefolder/TEMPLATE-VM.qcow2
+ image name: ubuntu16.04
+ image checksum: 7373edba82a31eedd182d29237b746cf
+ # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } #Optional
+ # processor: #Optional
+ # model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz
+ # features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"]
+ # hypervisor: #Optional
+ # type: QEMU-kvm
+ # version: "10002|12001|2.6.32-358.el6.x86_64"
+ vcpus: 1 # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed).
+ ram: 1000 # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed)
+ disk: 5 # disk size in GiB, by default 1
+ #numas:
+ #- paired-threads: 5 # "cores", "paired-threads", "threads"
+ # paired-threads-id: [ [0,1], [2,3], [4,5], [6,7], [8,9] ] # By default follows incremental order
+ # memory: 14 # GBytes
+ # interfaces: []
+ bridge-ifaces:
+ - name: mgmt0
+ vpci: "0000:00:0a.0" # Optional. Virtual PCI address
+ bandwidth: 1 Mbps # Optional. Informative only
+ floating-ip: True
+ # mac_address: '20:33:45:56:77:46' #avoid this option if possible
+ # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt
+ # Additional Virtual Machines would be included here
+
--- /dev/null
+##
+# 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
+##
+---
+vnf:
+ name: vnf_no_port_security
+ description: VNF disabling port_security option in mgmt interface
+ # class: parent # Optional. Used to organize VNFs
+ external-connections:
+ - name: mgmt0
+ type: mgmt # "mgmt" (autoconnect to management net), "bridge", "data"
+ VNFC: vnf_no_port_security # Virtual Machine this interface belongs to
+ local_iface_name: mgmt0 # interface name inside this Virtual Machine (must be defined in the VNFC section)
+ description: Management interface
+ VNFC: # Virtual machine array
+ - name: vnf_no_port_security # name of Virtual Machine
+ description: vnf_no_port_security
+# VNFC image: /path/to/imagefolder/TEMPLATE-VM.qcow2
+ image name: ubuntu16.04
+ image checksum: 7373edba82a31eedd182d29237b746cf
+ # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } #Optional
+ # processor: #Optional
+ # model: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz
+ # features: ["64b", "iommu", "lps", "tlbps", "hwsv", "dioc", "ht"]
+ # hypervisor: #Optional
+ # type: QEMU-kvm
+ # version: "10002|12001|2.6.32-358.el6.x86_64"
+ vcpus: 1 # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed).
+ ram: 1000 # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed)
+ disk: 5 # disk size in GiB, by default 1
+ #numas:
+ #- paired-threads: 5 # "cores", "paired-threads", "threads"
+ # paired-threads-id: [ [0,1], [2,3], [4,5], [6,7], [8,9] ] # By default follows incremental order
+ # memory: 14 # GBytes
+ # interfaces: []
+ bridge-ifaces:
+ - name: mgmt0
+ vpci: "0000:00:0a.0" # Optional. Virtual PCI address
+ bandwidth: 1 Mbps # Optional. Informative only
+ port-security: False
+ # mac_address: '20:33:45:56:77:46' #avoid this option if possible
+ # model: 'virtio' # ("virtio","e1000","ne2k_pci","pcnet","rtl8139") By default, it is automatically filled by libvirt
+ # Additional Virtual Machines would be included here
+