import socket
import select
import threading
+import logging
class ConsoleProxyException(Exception):
buffer_size = 4096
check_finish = 1 #frequency to check if requested to end in seconds
- def __init__(self, host, port, console_host, console_port):
+ def __init__(self, host, port, console_host, console_port, log_level=None):
try:
threading.Thread.__init__(self)
self.console_host = console_host
self.input_list = [self.server]
self.channel = {}
self.terminate = False #put at True from outside to force termination
+ self.logger = logging.getLogger('openmano.console')
+ if log_level:
+ self.logger.setLevel( getattr(logging, log_level) )
+
except (socket.error, socket.herror, socket.gaierror, socket.timeout) as e:
if e is socket.error and e.errno==98:
raise ConsoleProxyExceptionPortUsed("socket.error " + str(e))
try:
inputready, _, _ = select.select(self.input_list, [], [], self.check_finish)
except select.error as e:
- print self.name, ": Exception on select %s: %s" % (type(e).__name__, str(e) )
+ self.logger.error("Exception on select %s: %s", type(e).__name__, str(e) )
self.on_terminate()
if self.terminate:
self.on_terminate()
- print self.name, ": Terminate because commanded"
+ self.logger.debug("Terminate because commanded")
break
for sock in inputready:
try:
clientsock, clientaddr = self.server.accept()
except (socket.error, socket.herror, socket.gaierror, socket.timeout) as e:
- print self.name, ": Exception on_accept %s: %s" % (type(e).__name__, str(e) )
+ self.logger.error("Exception on_accept %s: %s", type(e).__name__, str(e) )
return False
#print self.name, ": Accept new client ", clientaddr
forward.connect((self.console_host, self.console_port))
name = "%s:%d => (%s:%d => %s:%d) => %s:%d" %\
(clientsock.getpeername() + clientsock.getsockname() + forward.getsockname() + forward.getpeername() )
- print self.name, ": new connection " + name
+ self.logger.warn("new connection " + name)
self.input_list.append(clientsock)
self.input_list.append(forward)
self.channel[forward] = info
return True
except (socket.error, socket.herror, socket.gaierror, socket.timeout) as e:
- print self.name, ": Exception on_connect to server %s:%d; %s: %s" % (self.console_host, self.console_port, type(e).__name__, str(e) )
- print self.name, ": Close client side ", clientaddr
+ self.logger.error("Exception on_connect to server %s:%d; %s: %s Close client side %s",
+ self.console_host, self.console_port, type(e).__name__, str(e), str(clientaddr) )
clientsock.close()
return False
info = self.channel[sock]
#debug info
sockname = "client" if sock is info["clientsock"] else "server"
- print self.name, ": del connection %s %s at %s side" % (info["name"], cause, sockname)
+ self.logger.warn("del connection %s %s at %s side", info["name"], str(cause), str(sockname) )
#close sockets
try:
# close the connection with client
info["clientsock"].close() # equivalent to do self.s.close()
except (socket.error, socket.herror, socket.gaierror, socket.timeout) as e:
- print self.name, ": Exception on_close client socket %s: %s" % (type(e).__name__, str(e) )
+ self.logger.error("Exception on_close client socket %s: %s", type(e).__name__, str(e) )
try:
# close the connection with remote server
info["serversock"].close()
except (socket.error, socket.herror, socket.gaierror, socket.timeout) as e:
- print self.name, ": Exception on_close server socket %s: %s" % (type(e).__name__, str(e) )
+ self.logger.error("Exception on_close server socket %s: %s", type(e).__name__, str(e) )
#remove objects from input_list
self.input_list.remove(info["clientsock"])
def http_post_scenario_action(tenant_id, scenario_id):
'''take an action over a scenario'''
logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
- #check valid tenant_id
+ # parse input data
+ http_content, _ = format_in(scenario_action_schema)
+ r = utils.remove_extra_items(http_content, scenario_action_schema)
+ if r:
+ logger.debug("Remove received extra items %s", str(r))
try:
- nfvo.check_tenant(mydb, tenant_id)
- #parse input data
- http_content,_ = format_in( scenario_action_schema )
- r = utils.remove_extra_items(http_content, scenario_action_schema)
- if r:
- logger.debug("Remove received extra items %s", str(r))
+ # check valid tenant_id
+ nfvo.check_tenant(mydb, tenant_id)
if "start" in http_content:
data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['start']['instance_name'], \
http_content['start'].get('description',http_content['start']['instance_name']),
@bottle.route(url_base + '/<tenant_id>/scenarios/<scenario_id>', method='DELETE')
def http_delete_scenario_id(tenant_id, scenario_id):
'''delete a scenario from database, can use both uuid or name'''
+ logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
try:
#check valid tenant_id
if tenant_id != "any":
- nfvo.check_tenant(mydb, tenant_id)
+ nfvo.check_tenant(mydb, tenant_id)
#obtain data
data = mydb.delete_scenario(scenario_id, tenant_id)
#print json.dumps(data, indent=4)
def http_post_instances(tenant_id):
'''create an instance-scenario'''
logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+ # parse input data
+ http_content, used_schema = format_in(instance_scenario_create_schema_v01)
+ r = utils.remove_extra_items(http_content, used_schema)
+ if r is not None:
+ logger.warning("http_post_instances: Warning: remove extra items %s", str(r))
try:
#check valid tenant_id
if tenant_id != "any":
nfvo.check_tenant(mydb, tenant_id)
- #parse input data
- http_content,used_schema = format_in( instance_scenario_create_schema_v01)
- r = utils.remove_extra_items(http_content, used_schema)
- if r is not None:
- logger.warning("http_post_instances: Warning: remove extra items %s", str(r))
data = nfvo.create_instance(mydb, tenant_id, http_content["instance"])
return format_out(data)
except (nfvo.NfvoException, db_base_Exception) as e:
def http_post_instance_scenario_action(tenant_id, instance_id):
'''take an action over a scenario instance'''
logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+ # parse input data
+ http_content, _ = format_in(instance_scenario_action_schema)
+ r = utils.remove_extra_items(http_content, instance_scenario_action_schema)
+ if r:
+ logger.debug("Remove received extra items %s", str(r))
try:
#check valid tenant_id
if tenant_id != "any":
nfvo.check_tenant(mydb, tenant_id)
- #parse input data
- http_content,_ = format_in( instance_scenario_action_schema )
- r = utils.remove_extra_items(http_content, instance_scenario_action_schema)
- if r:
- logger.debug("Remove received extra items %s", str(r))
#print "http_post_instance_scenario_action input: ", http_content
#obtain data
instance = mydb.get_instance_scenario(instance_id, tenant_id)
else:
return False," Rollback fails to delete: " + str(undeleted_items)
-def check_vnf_descriptor(vnf_descriptor):
+def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
global global_config
#create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
vnfc_interfaces={}
for vnfc in vnf_descriptor["vnf"]["VNFC"]:
- name_list = []
+ name_dict = {}
#dataplane interfaces
for numa in vnfc.get("numas",() ):
for interface in numa.get("interfaces",()):
- if interface["name"] in name_list:
- raise NfvoException("Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC"\
- .format(vnfc["name"], interface["name"]),
- HTTP_Bad_Request)
- name_list.append( interface["name"] )
+ if interface["name"] in name_dict:
+ raise NfvoException(
+ "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
+ vnfc["name"], interface["name"]),
+ HTTP_Bad_Request)
+ name_dict[ interface["name"] ] = "underlay"
#bridge interfaces
for interface in vnfc.get("bridge-ifaces",() ):
- if interface["name"] in name_list:
- raise NfvoException("Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC"\
- .format(vnfc["name"], interface["name"]),
- HTTP_Bad_Request)
- name_list.append( interface["name"] )
- vnfc_interfaces[ vnfc["name"] ] = name_list
+ if interface["name"] in name_dict:
+ raise NfvoException(
+ "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
+ vnfc["name"], interface["name"]),
+ HTTP_Bad_Request)
+ name_dict[ interface["name"] ] = "overlay"
+ vnfc_interfaces[ vnfc["name"] ] = name_dict
# check bood-data info
if "boot-data" in vnfc:
# check that user-data is incompatible with users and config-files
name_list=[]
for external_connection in vnf_descriptor["vnf"].get("external-connections",() ):
if external_connection["name"] in name_list:
- raise NfvoException("Error at vnf:external-connections:name, value '{}' already used as an external-connection"\
- .format(external_connection["name"]),
- HTTP_Bad_Request)
+ raise NfvoException(
+ "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
+ external_connection["name"]),
+ HTTP_Bad_Request)
name_list.append(external_connection["name"])
if external_connection["VNFC"] not in vnfc_interfaces:
- raise NfvoException("Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC"\
- .format(external_connection["name"], external_connection["VNFC"]),
- HTTP_Bad_Request)
+ raise NfvoException(
+ "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
+ external_connection["name"], external_connection["VNFC"]),
+ HTTP_Bad_Request)
if external_connection["local_iface_name"] not in vnfc_interfaces[ external_connection["VNFC"] ]:
- raise NfvoException("Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC"\
- .format(external_connection["name"], external_connection["local_iface_name"]),
- HTTP_Bad_Request )
+ raise NfvoException(
+ "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
+ external_connection["name"],
+ external_connection["local_iface_name"]),
+ HTTP_Bad_Request )
#check if the info in internal_connections matches with the one in the vnfcs
name_list=[]
for internal_connection in vnf_descriptor["vnf"].get("internal-connections",() ):
if internal_connection["name"] in name_list:
- raise NfvoException("Error at vnf:internal-connections:name, value '%s' already used as an internal-connection"\
- .format(internal_connection["name"]),
- HTTP_Bad_Request)
+ raise NfvoException(
+ "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
+ internal_connection["name"]),
+ HTTP_Bad_Request)
name_list.append(internal_connection["name"])
#We should check that internal-connections of type "ptp" have only 2 elements
- if len(internal_connection["elements"])>2 and internal_connection["type"] == "ptp":
- raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements, size must be 2 for a type:'ptp'"\
- .format(internal_connection["name"]),
- HTTP_Bad_Request)
+
+ if len(internal_connection["elements"])>2 and (internal_connection.get("type") == "ptp" or internal_connection.get("type") == "e-line"):
+ raise NfvoException(
+ "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
+ internal_connection["name"],
+ 'ptp' if vnf_descriptor_version==1 else 'e-line',
+ 'data' if vnf_descriptor_version==1 else "e-lan"),
+ HTTP_Bad_Request)
for port in internal_connection["elements"]:
- if port["VNFC"] not in vnfc_interfaces:
- raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC"\
- .format(internal_connection["name"], port["VNFC"]),
- HTTP_Bad_Request)
- if port["local_iface_name"] not in vnfc_interfaces[ port["VNFC"] ]:
- raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC"\
- .format(internal_connection["name"], port["local_iface_name"]),
- HTTP_Bad_Request)
- return -HTTP_Bad_Request,
+ vnf = port["VNFC"]
+ iface = port["local_iface_name"]
+ if vnf not in vnfc_interfaces:
+ raise NfvoException(
+ "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
+ internal_connection["name"], vnf),
+ HTTP_Bad_Request)
+ if iface not in vnfc_interfaces[ vnf ]:
+ raise NfvoException(
+ "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
+ internal_connection["name"], iface),
+ HTTP_Bad_Request)
+ return -HTTP_Bad_Request,
+ if vnf_descriptor_version==1 and "type" not in internal_connection:
+ if vnfc_interfaces[vnf][iface] == "overlay":
+ internal_connection["type"] = "bridge"
+ else:
+ internal_connection["type"] = "data"
+ if vnf_descriptor_version==2 and "implementation" not in internal_connection:
+ if vnfc_interfaces[vnf][iface] == "overlay":
+ internal_connection["implementation"] = "overlay"
+ else:
+ internal_connection["implementation"] = "underlay"
+ if (internal_connection.get("type") == "data" or internal_connection.get("type") == "ptp" or \
+ internal_connection.get("implementation") == "underlay") and vnfc_interfaces[vnf][iface] == "overlay":
+ raise NfvoException(
+ "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
+ internal_connection["name"],
+ iface, 'bridge' if vnf_descriptor_version==1 else 'overlay',
+ 'data' if vnf_descriptor_version==1 else 'underlay'),
+ HTTP_Bad_Request)
+ if (internal_connection.get("type") == "bridge" or internal_connection.get("implementation") == "overlay") and \
+ vnfc_interfaces[vnf][iface] == "underlay":
+ raise NfvoException(
+ "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
+ internal_connection["name"], iface,
+ 'data' if vnf_descriptor_version==1 else 'underlay',
+ 'bridge' if vnf_descriptor_version==1 else 'overlay'),
+ HTTP_Bad_Request)
+
def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False, return_on_error = None):
#look if image exist
rollback_list.append({"where":"vim", "vim_id": vim_id, "what":"image","uuid":image_vim_id})
image_created="true"
else:
- raise vimconn.vimconnException("Cannot create image without location")
+ #If we reach this point, then the image has image name, and optionally checksum, and could not be found
+ raise vimconn.vimconnException(str(e))
except vimconn.vimconnException as e:
if return_on_error:
logger.error("Error creating image at VIM '%s': %s", vim["name"], str(e))
#create flavor at vim
logger.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim["name"])
try:
- flavor_vim_id = vim.new_flavor(flavor_dict)
- rollback_list.append({"where":"vim", "vim_id": vim_id, "what":"flavor","uuid":flavor_vim_id})
- flavor_created="true"
+ flavor_vim_id = None
+ flavor_vim_id=vim.get_flavor_id_from_data(flavor_dict)
+ flavor_create="false"
+ except vimconn.vimconnException as e:
+ pass
+ try:
+ if not flavor_vim_id:
+ flavor_vim_id = vim.new_flavor(flavor_dict)
+ rollback_list.append({"where":"vim", "vim_id": vim_id, "what":"flavor","uuid":flavor_vim_id})
+ flavor_created="true"
except vimconn.vimconnException as e:
if return_on_error:
logger.error("Error creating flavor at VIM %s: %s.", vim["name"], str(e))
global global_config
# Step 1. Check the VNF descriptor
- check_vnf_descriptor(vnf_descriptor)
+ check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1)
# Step 2. Check tenant exist
+ vims = {}
if tenant_id != "any":
check_tenant(mydb, tenant_id)
if "tenant_id" in vnf_descriptor["vnf"]:
else:
vnf_descriptor['vnf']['tenant_id'] = tenant_id
# Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
- vims = get_vim(mydb, tenant_id)
- else:
- vims={}
+ if global_config["auto_push_VNF_to_VIMs"]:
+ vims = get_vim(mydb, tenant_id)
# Step 4. Review the descriptor and add missing fields
#print vnf_descriptor
if "physical" in vnf_descriptor['vnf']:
del vnf_descriptor['vnf']['physical']
#print vnf_descriptor
- # Step 5. Check internal connections
- # TODO: to be moved to step 1????
- internal_connections=vnf_descriptor['vnf'].get('internal_connections',[])
- for ic in internal_connections:
- if len(ic['elements'])>2 and ic['type']=='ptp':
- raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic), ic['name']),
- HTTP_Bad_Request)
- elif len(ic['elements'])==2 and ic['type']=='data':
- raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic['name']),
- HTTP_Bad_Request)
-
+
# Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
logger.debug('BEGIN creation of VNF "%s"' % vnf_name)
logger.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name,len(vnf_descriptor['vnf']['VNFC'])))
global global_config
# Step 1. Check the VNF descriptor
- check_vnf_descriptor(vnf_descriptor)
+ check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=2)
# Step 2. Check tenant exist
+ vims = {}
if tenant_id != "any":
check_tenant(mydb, tenant_id)
if "tenant_id" in vnf_descriptor["vnf"]:
else:
vnf_descriptor['vnf']['tenant_id'] = tenant_id
# Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
- vims = get_vim(mydb, tenant_id)
- else:
- vims={}
+ if global_config["auto_push_VNF_to_VIMs"]:
+ vims = get_vim(mydb, tenant_id)
# Step 4. Review the descriptor and add missing fields
#print vnf_descriptor
if "physical" in vnf_descriptor['vnf']:
del vnf_descriptor['vnf']['physical']
#print vnf_descriptor
- # Step 5. Check internal connections
- # TODO: to be moved to step 1????
- internal_connections=vnf_descriptor['vnf'].get('internal_connections',[])
- for ic in internal_connections:
- if len(ic['elements'])>2 and ic['type']=='e-line':
- raise NfvoException("Mismatch 'type':'e-line' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'e-lan'".format(len(ic), ic['name']),
- HTTP_Bad_Request)
-
+
# Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
logger.debug('BEGIN creation of VNF "%s"' % vnf_name)
logger.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name,len(vnf_descriptor['vnf']['VNFC'])))
content = myvim.get_network_list(filter_dict=filter_dict)
elif item=="tenants":
content = myvim.get_tenant_list(filter_dict=filter_dict)
+ elif item == "images":
+ content = myvim.get_image_list(filter_dict=filter_dict)
else:
raise NfvoException(item + "?", HTTP_Method_Not_Allowed)
logger.debug("vim_action response %s", content) #update nets Change from VIM format to NFVO format
content = myvim.delete_network(item_id)
elif item=="tenants":
content = myvim.delete_tenant(item_id)
+ elif item == "images":
+ content = myvim.delete_image(item_id)
else:
raise NfvoException(item + "?", HTTP_Method_Not_Allowed)
except vimconn.vimconnException as e:
#print "Internal vm id in NFVO DB: %s" % vm_id
vmDict[vm['name']] = vm_id
- #Collect the data interfaces of each VM/VNFC under the 'numas' field
- dataifacesDict = {}
- for vm in vnf_descriptor['vnf']['VNFC']:
- dataifacesDict[vm['name']] = {}
- for numa in vm.get('numas', []):
- for dataiface in numa.get('interfaces',[]):
- db_base._convert_bandwidth(dataiface, logger=self.logger)
- dataifacesDict[vm['name']][dataiface['name']] = {}
- dataifacesDict[vm['name']][dataiface['name']]['vpci'] = dataiface['vpci']
- dataifacesDict[vm['name']][dataiface['name']]['bw'] = dataiface['bandwidth']
- dataifacesDict[vm['name']][dataiface['name']]['model'] = "PF" if dataiface['dedicated']=="yes" else ("VF" if dataiface['dedicated']=="no" else "VFnotShared")
-
#Collect the bridge interfaces of each VM/VNFC under the 'bridge-ifaces' field
bridgeInterfacesDict = {}
for vm in vnf_descriptor['vnf']['VNFC']:
if 'bridge-ifaces' in vm:
bridgeInterfacesDict[vm['name']] = {}
for bridgeiface in vm['bridge-ifaces']:
+ created_time += 0.00001
if 'port-security' in bridgeiface:
bridgeiface['port_security'] = bridgeiface.pop('port-security')
if 'floating-ip' in bridgeiface:
int(bridgeiface.get('port_security', True))
bridgeInterfacesDict[vm['name']][bridgeiface['name']]['floating_ip'] = \
int(bridgeiface.get('floating_ip', False))
-
+ bridgeInterfacesDict[vm['name']][bridgeiface['name']]['created_time'] = created_time
+
+ # Collect the data interfaces of each VM/VNFC under the 'numas' field
+ dataifacesDict = {}
+ for vm in vnf_descriptor['vnf']['VNFC']:
+ dataifacesDict[vm['name']] = {}
+ for numa in vm.get('numas', []):
+ for dataiface in numa.get('interfaces', []):
+ created_time += 0.00001
+ db_base._convert_bandwidth(dataiface, logger=self.logger)
+ dataifacesDict[vm['name']][dataiface['name']] = {}
+ dataifacesDict[vm['name']][dataiface['name']]['vpci'] = dataiface['vpci']
+ dataifacesDict[vm['name']][dataiface['name']]['bw'] = dataiface['bandwidth']
+ dataifacesDict[vm['name']][dataiface['name']]['model'] = "PF" if dataiface[
+ 'dedicated'] == "yes" else (
+ "VF" if dataiface['dedicated'] == "no" else "VFnotShared")
+ dataifacesDict[vm['name']][dataiface['name']]['created_time'] = created_time
+
#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)"
internalconnList = []
ifaceItem["net_id"] = net_id
ifaceItem["type"] = net['type']
if ifaceItem ["type"] == "data":
- ifaceItem["vpci"] = dataifacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['vpci']
- ifaceItem["bw"] = dataifacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['bw']
- ifaceItem["model"] = dataifacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['model']
+ dataiface = dataifacesDict[ element['VNFC'] ][ element['local_iface_name'] ]
+ ifaceItem["vpci"] = dataiface['vpci']
+ ifaceItem["bw"] = dataiface['bw']
+ ifaceItem["model"] = dataiface['model']
+ created_time_iface = dataiface['created_time']
else:
- ifaceItem["vpci"] = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['vpci']
- 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']
+ bridgeiface = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]
+ ifaceItem["vpci"] = bridgeiface['vpci']
+ ifaceItem["mac"] = bridgeiface['mac']
+ ifaceItem["bw"] = bridgeiface['bw']
+ ifaceItem["model"] = bridgeiface['model']
+ ifaceItem["port_security"] = bridgeiface['port_security']
+ ifaceItem["floating_ip"] = bridgeiface['floating_ip']
+ created_time_iface = bridgeiface['created_time']
internalconnList.append(ifaceItem)
#print "Internal net id in NFVO DB: %s" % net_id
#print "Adding internal interfaces to the NFVO database (if any)"
for iface in internalconnList:
- print "Iface name: %s" % iface['internal_name']
- created_time += 0.00001
- iface_id = self._new_row_internal('interfaces', iface, add_uuid=True, root_uuid=vnf_id, created_time=created_time)
+ #print "Iface name: %s" % iface['internal_name']
+ iface_id = self._new_row_internal('interfaces', iface, add_uuid=True, root_uuid=vnf_id, created_time = created_time_iface)
#print "Iface id in NFVO DB: %s" % iface_id
#print "Adding external interfaces to the NFVO database"
myIfaceDict["external_name"] = iface['name']
myIfaceDict["type"] = iface['type']
if iface["type"] == "data":
- myIfaceDict["vpci"] = dataifacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['vpci']
- myIfaceDict["bw"] = dataifacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['bw']
- myIfaceDict["model"] = dataifacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['model']
+ dataiface = dataifacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]
+ myIfaceDict["vpci"] = dataiface['vpci']
+ myIfaceDict["bw"] = dataiface['bw']
+ myIfaceDict["model"] = dataiface['model']
+ created_time_iface = dataiface['created_time']
else:
- myIfaceDict["vpci"] = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['vpci']
- 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)
+ bridgeiface = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]
+ myIfaceDict["vpci"] = bridgeiface['vpci']
+ myIfaceDict["bw"] = bridgeiface['bw']
+ myIfaceDict["model"] = bridgeiface['model']
+ myIfaceDict["mac"] = bridgeiface['mac']
+ myIfaceDict["port_security"]= bridgeiface['port_security']
+ myIfaceDict["floating_ip"] = bridgeiface['floating_ip']
+ created_time_iface = bridgeiface['created_time']
+ #print "Iface name: %s" % iface['name']
+ iface_id = self._new_row_internal('interfaces', myIfaceDict, add_uuid=True, root_uuid=vnf_id, created_time = created_time_iface)
#print "Iface id in NFVO DB: %s" % iface_id
return vnf_id
#print "Internal vm id in NFVO DB: %s" % vm_id
vmDict[vm['name']] = vm_id
- #Collect the data interfaces of each VM/VNFC under the 'numas' field
- dataifacesDict = {}
- for vm in vnf_descriptor['vnf']['VNFC']:
- dataifacesDict[vm['name']] = {}
- for numa in vm.get('numas', []):
- for dataiface in numa.get('interfaces',[]):
- db_base._convert_bandwidth(dataiface, logger=self.logger)
- dataifacesDict[vm['name']][dataiface['name']] = {}
- dataifacesDict[vm['name']][dataiface['name']]['vpci'] = dataiface['vpci']
- dataifacesDict[vm['name']][dataiface['name']]['bw'] = dataiface['bandwidth']
- dataifacesDict[vm['name']][dataiface['name']]['model'] = "PF" if dataiface['dedicated']=="yes" else ("VF" if dataiface['dedicated']=="no" else "VFnotShared")
-
#Collect the bridge interfaces of each VM/VNFC under the 'bridge-ifaces' field
bridgeInterfacesDict = {}
for vm in vnf_descriptor['vnf']['VNFC']:
if 'bridge-ifaces' in vm:
bridgeInterfacesDict[vm['name']] = {}
for bridgeiface in vm['bridge-ifaces']:
+ created_time += 0.00001
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))
-
+ ifaceDict = {}
+ ifaceDict['vpci'] = bridgeiface.get('vpci',None)
+ ifaceDict['mac'] = bridgeiface.get('mac_address',None)
+ ifaceDict['bw'] = bridgeiface.get('bandwidth', None)
+ ifaceDict['model'] = bridgeiface.get('model', None)
+ ifaceDict['port_security'] = int(bridgeiface.get('port_security', True))
+ ifaceDict['floating_ip'] = int(bridgeiface.get('floating_ip', False))
+ ifaceDict['created_time'] = created_time
+ bridgeInterfacesDict[vm['name']][bridgeiface['name']] = ifaceDict
+
+ # Collect the data interfaces of each VM/VNFC under the 'numas' field
+ dataifacesDict = {}
+ for vm in vnf_descriptor['vnf']['VNFC']:
+ dataifacesDict[vm['name']] = {}
+ for numa in vm.get('numas', []):
+ for dataiface in numa.get('interfaces', []):
+ created_time += 0.00001
+ db_base._convert_bandwidth(dataiface, logger=self.logger)
+ ifaceDict = {}
+ ifaceDict['vpci'] = dataiface['vpci']
+ ifaceDict['bw'] = dataiface['bandwidth']
+ ifaceDict['model'] = "PF" if dataiface['dedicated'] == "yes" else \
+ ("VF" if dataiface['dedicated'] == "no" else "VFnotShared")
+ ifaceDict['created_time'] = created_time
+ dataifacesDict[vm['name']][dataiface['name']] = ifaceDict
+
#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)"
- internalconnList = []
if 'internal-connections' in vnf_descriptor['vnf']:
for net in vnf_descriptor['vnf']['internal-connections']:
#print "Net name: %s. Description: %s" % (net['name'], net['description'])
ifaceItem["type"] = net['type']
ifaceItem["ip_address"] = element.get('ip_address',None)
if ifaceItem ["type"] == "data":
- ifaceItem["vpci"] = dataifacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['vpci']
- ifaceItem["bw"] = dataifacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['bw']
- ifaceItem["model"] = dataifacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['model']
+ ifaceDict = dataifacesDict[ element['VNFC'] ][ element['local_iface_name'] ]
+ ifaceItem["vpci"] = ifaceDict['vpci']
+ ifaceItem["bw"] = ifaceDict['bw']
+ ifaceItem["model"] = ifaceDict['model']
else:
- ifaceItem["vpci"] = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['vpci']
- 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
-
- #print "Adding internal interfaces to the NFVO database (if any)"
- for iface in internalconnList:
- print "Iface name: %s" % iface['internal_name']
- created_time += 0.00001
- iface_id = self._new_row_internal('interfaces', iface, add_uuid=True, root_uuid=vnf_id, created_time=created_time)
- #print "Iface id in NFVO DB: %s" % iface_id
+ ifaceDict = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]
+ ifaceItem["vpci"] = ifaceDict['vpci']
+ ifaceItem["mac"] = ifaceDict['mac']
+ ifaceItem["bw"] = ifaceDict['bw']
+ ifaceItem["model"] = ifaceDict['model']
+ ifaceItem["port_security"] = ifaceDict['port_security']
+ ifaceItem["floating_ip"] = ifaceDict['floating_ip']
+ created_time_iface = ifaceDict["created_time"]
+ #print "Iface name: %s" % iface['internal_name']
+ iface_id = self._new_row_internal('interfaces', ifaceItem, add_uuid=True, root_uuid=vnf_id, created_time=created_time_iface)
+ #print "Iface id in NFVO DB: %s" % iface_id
#print "Adding external interfaces to the NFVO database"
for iface in vnf_descriptor['vnf']['external-connections']:
myIfaceDict["vpci"] = dataifacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['vpci']
myIfaceDict["bw"] = dataifacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['bw']
myIfaceDict["model"] = dataifacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['model']
+ created_time_iface = dataifacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['created_time']
else:
myIfaceDict["vpci"] = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['vpci']
myIfaceDict["bw"] = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['bw']
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)
+ created_time_iface = bridgeInterfacesDict[iface['VNFC']][iface['local_iface_name']]['created_time']
+ #print "Iface name: %s" % iface['name']
+ iface_id = self._new_row_internal('interfaces', myIfaceDict, add_uuid=True, root_uuid=vnf_id, created_time=created_time_iface)
#print "Iface id in NFVO DB: %s" % iface_id
return vnf_id
for vm in vnf['vms']:
vm_manage_iface_list=[]
#instance_interfaces
- cmd = "SELECT vim_interface_id, instance_net_id, internal_name,external_name, mac_address, ii.ip_address as ip_address, vim_info, i.type as type "\
- " FROM instance_interfaces as ii join interfaces as i on ii.interface_id=i.uuid "\
- " WHERE instance_vm_id='{}' ORDER BY created_at".format(vm['uuid'])
+ cmd = "SELECT vim_interface_id, instance_net_id, internal_name,external_name, mac_address,"\
+ " ii.ip_address as ip_address, vim_info, i.type as type"\
+ " FROM instance_interfaces as ii join interfaces as i on ii.interface_id=i.uuid"\
+ " WHERE instance_vm_id='{}' ORDER BY created_at".format(vm['uuid'])
self.logger.debug(cmd)
self.cur.execute(cmd )
vm['interfaces'] = self.cur.fetchall()
'''
__author__="Alfonso Tierno, Gerardo Garcia"
__date__ ="$09-oct-2014 09:09:48$"
-__version__="0.4.9-r515"
+__version__="0.4.11-r517"
version_date="Jan 2017"
from argcomplete.completers import FilesCompleter
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:
+ name = content.get('name');
+ if not uuid:
+ uuid = ""
+ if not name:
+ name = ""
+ myoutput = "%s %s" %(uuid.ljust(38),name.ljust(20))
+ if content.get("status"):
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:
+ if content.get('created_at'):
myoutput += " " + content['created_at'].ljust(20)
if verbose_level >=2:
new_line='\n'
- if 'type' in content and content['type']!=None:
+ if content.get('type'):
myoutput += new_line + " Type: " + content['type'].ljust(29)
new_line=''
- if 'description' in content and content['description']!=None:
+ if content.get('description'):
myoutput += new_line + " Description: " + content['description'].ljust(20)
print myoutput
else:
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))
+ interface.get('vpci',"").ljust(14))
else:
print content['error']['description']
if args.verbose:
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"):
+ for item in ("network", "tenant", "image"):
if item=="network":
commnad_name = 'vim-net'
else:
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")
+ if item == "network" or item == "tenant":
+ 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)
"http_port": port_schema,
"http_admin_port": port_schema,
"http_host": nameshort_schema,
+ "auto_push_VNF_to_VIMs": {"type":"boolean"},
"vnf_repository": path_schema,
"db_host": nameshort_schema,
"db_user": nameshort_schema,
"log_level_vim": log_level_schema,
"log_level_nfvo": log_level_schema,
"log_level_http": log_level_schema,
+ "log_level_console": log_level_schema,
"log_file_db": path_schema,
"log_file_vim": path_schema,
"log_file_nfvo": path_schema,
"log_file_http": path_schema,
+ "log_file_console": path_schema,
"log_socket_host": nameshort_schema,
"log_socket_port": port_schema,
"log_file": path_schema,
#other MANO parameters
# Folder where the VNF descriptors will be stored
# The folder will be created in the execution folder if it does not exist
-#vnf_repository: "./vnfrepo" # Use an absolute path to avoid misunderstandings
+#vnf_repository: "./vnfrepo" # Use an absolute path to avoid misunderstandings
+# Indicates if at VNF onboarding, flavors and images are loaded at all related VIMs,
+# in order to speed up the later instantiation.
+auto_push_VNF_to_VIMs: False # by default True
#general logging parameters
#choose among: DEBUG, INFO, WARNING, ERROR, CRITICAL
#log_level_vim: DEBUG #VIM connection log levels
#log_file_vim: /opt/openmano/logs/openmano_vimconn.log
#log_level_nfvo: DEBUG #Main engine log levels
-#log_file_nfvo: /opt/openmano/logs/openmano_nfvo.log
+#log_file_nfvo: /opt/openmano/logs/openmano_nfvo.log
#log_level_http: DEBUG #Main engine log levels
-#log_file_http: /opt/openmano/logs/openmano_http.log
+#log_file_http: /opt/openmano/logs/openmano_http.log
+#log_level_console: DEBUG #proxy console log levels
+#log_file_console: /opt/openmano/logs/openmano_console.log
#Uncomment to send logs via IP to an external host
#log_socket_host: localhost
'''
__author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
__date__ ="$26-aug-2014 11:09:29$"
-__version__="0.5.5-r514"
+__version__="0.5.8-r518"
version_date="Jan 2017"
database_version="0.19" #expected database schema version
'http_console_host': None,
'log_level': 'DEBUG',
'log_socket_port': 9022,
+ 'auto_push_VNF_to_VIMs': True
}
try:
#Check config file exists
logger.critical("Starting openmano server version: '%s %s' command: '%s'",
__version__, version_date, " ".join(sys.argv))
- for log_module in ("nfvo", "http", "vim", "db"):
+ for log_module in ("nfvo", "http", "vim", "db", "console"):
log_level_module = "log_level_" + log_module
log_file_module = "log_file_" + log_module
logger_module = logging.getLogger('openmano.' + log_module)
Returns the flavor dict details {'id':<>, 'name':<>, other vim specific } #TODO to concrete
'''
raise vimconnNotImplemented( "Should have implemented this" )
-
+
+ def get_flavor_id_from_data(self, flavor_dict):
+ """Obtain flavor id that match the flavor description
+ Returns the flavor_id or raises a vimconnNotFoundException
+ """
+ raise vimconnNotImplemented( "Should have implemented this" )
+
def new_flavor(self, flavor_data):
'''Adds a tenant flavor to VIM
flavor_data contains a dictionary with information, keys:
raise vimconnNotImplemented( "Should have implemented this" )
def get_image_id_from_path(self, path):
- '''Get the image id from image path in the VIM database. Returns the image_id'''
+ """Get the image id from image path in the VIM database.
+ Returns the image_id or raises a vimconnNotFoundException
+ """
raise vimconnNotImplemented( "Should have implemented this" )
def get_image_list(self, filter_dict={}):
import netaddr
import time
import yaml
+import random
from novaclient import client as nClient_v2, exceptions as nvExceptions
from novaclient import api_versions
self.k_creds={}
self.n_creds={}
+ if self.config.get("insecure"):
+ self.k_creds["insecure"] = True
+ self.n_creds["insecure"] = True
if not url:
raise TypeError, 'url param can not be NoneType'
self.k_creds['auth_url'] = url
if not ip_profile:
ip_profile = {}
if 'subnet_address' not in ip_profile:
- #Fake subnet is required
- ip_profile['subnet_address'] = "192.168.111.0/24"
+ #Fake subnet is required
+ subnet_rand = random.randint(0, 255)
+ ip_profile['subnet_address'] = "192.168.{}.0/24".format(subnet_rand)
if 'ip_version' not in ip_profile:
ip_profile['ip_version'] = "IPv4"
subnet={"name":net_name+"-subnet",
except (nvExceptions.NotFound, nvExceptions.ClientException, ksExceptions.ClientException, ConnectionError) as e:
self._format_exception(e)
+ def get_flavor_id_from_data(self, flavor_dict):
+ """Obtain flavor id that match the flavor description
+ Returns the flavor_id or raises a vimconnNotFoundException
+ """
+ try:
+ self._reload_connection()
+ numa=None
+ numas = flavor_dict.get("extended",{}).get("numas")
+ if numas:
+ #TODO
+ raise vimconn.vimconnNotFoundException("Flavor with EPA still not implemted")
+ # if len(numas) > 1:
+ # raise vimconn.vimconnNotFoundException("Cannot find any flavor with more than one numa")
+ # numa=numas[0]
+ # numas = extended.get("numas")
+ for flavor in self.nova.flavors.list():
+ epa = flavor.get_keys()
+ if epa:
+ continue
+ #TODO
+ if flavor.ram != flavor_dict["ram"]:
+ continue
+ if flavor.vcpus != flavor_dict["vcpus"]:
+ continue
+ if flavor.disk != flavor_dict["disk"]:
+ continue
+ return flavor.id
+ raise vimconn.vimconnNotFoundException("Cannot find any flavor matching '{}'".format(str(flavor_dict)))
+ except (nvExceptions.NotFound, nvExceptions.ClientException, ksExceptions.ClientException, ConnectionError) as e:
+ self._format_exception(e)
+
+
def new_flavor(self, flavor_data, change_name_if_used=True):
'''Adds a tenant flavor to openstack VIM
if change_name_if_used is True, it will change name in case of conflict, because it is not supported name repetition
#Then we filter by the rest of filter fields: checksum
filtered_list = []
for image in image_list:
- image_dict=self.glance.images.get(image.id)
- if 'checksum' not in filter_dict or image_dict['checksum']==filter_dict.get('checksum'):
- filtered_list.append(image_dict)
+ image_class=self.glance.images.get(image.id)
+ if 'checksum' not in filter_dict or image_class['checksum']==filter_dict.get('checksum'):
+ filtered_list.append(image_class.copy())
return filtered_list
except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError, ConnectionError) as e:
self._format_exception(e)
#TODO ip, security groups
Returns the instance identifier
'''
- self.logger.debug("Creating VM image '%s' flavor '%s' nics='%s'",image_id, flavor_id,str(net_list))
+ self.logger.debug("new_vminstance input: image='%s' flavor='%s' nics='%s'",image_id, flavor_id,str(net_list))
try:
metadata={}
net_list_vim=[]
self.logger.warn("new_vminstance: Warning, can not connect a passthrough interface ")
#TODO insert this when openstack consider passthrough ports as openstack neutron ports
if net.get('floating_ip', False):
+ net['exit_on_floating_ip_error'] = True
external_network.append(net)
-
+ elif net['use'] == 'mgmt' and self.config.get('use_floating_ip'):
+ net['exit_on_floating_ip_error'] = False
+ external_network.append(net)
+
if metadata_vpci:
metadata = {"pci_assignement": json.dumps(metadata_vpci)}
if len(metadata["pci_assignement"]) >255:
userdata_dict["ssh-authorized-keys"] = cloud_config["key-pairs"]
userdata_dict["users"] = [{"default": None, "ssh-authorized-keys": cloud_config["key-pairs"] }]
if cloud_config.get("users"):
- if "users" not in cloud_config:
+ if "users" not in userdata_dict:
userdata_dict["users"] = [ "default" ]
for user in cloud_config["users"]:
user_info = {
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
+ try:
+ # 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)
+ #if we exceeded the timeout rollback
+ if elapsed_time >= server_timeout:
+ 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) and ip.get('tenant_id') == server.tenant_id:
+ free_floating_ip = ip.get("floating_ip_address")
+ try:
+ fix_ip = floating_network.get('ip')
+ server.add_floating_ip(free_floating_ip, fix_ip)
+ assigned = True
+ except Exception as e:
+ raise vimconn.vimconnException(type(e).__name__ + ": Cannot create floating_ip "+ str(e), http_code=vimconn.HTTP_Conflict)
+ else:
+ #Find the external network
+ external_nets = list()
+ for net in self.neutron.list_networks()['networks']:
+ if net['router:external']:
+ external_nets.append(net)
- assigned = False
- while(assigned == False):
- if floating_ips:
- ip = floating_ips.pop(0)
- if not ip.get("port_id", False) and ip.get('tenant_id') == server.tenant_id:
- free_floating_ip = ip.get("floating_ip_address")
+ if len(external_nets) == 0:
+ raise vimconn.vimconnException("Cannot create floating_ip automatically since no external "
+ "network is present",
+ http_code=vimconn.HTTP_Conflict)
+ if len(external_nets) > 1:
+ 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)
+ free_floating_ip = new_floating_ip['floatingip']['floating_ip_address']
fix_ip = floating_network.get('ip')
server.add_floating_ip(free_floating_ip, fix_ip)
- assigned = True
+ assigned=True
except Exception as e:
- self.delete_vminstance(server.id)
- raise vimconn.vimconnException(type(e).__name__ + ": Cannot create floating_ip "+ str(e), http_code=vimconn.HTTP_Conflict)
- else:
- #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)
+ raise vimconn.vimconnException(type(e).__name__ + ": Cannot assign floating_ip "+ str(e), http_code=vimconn.HTTP_Conflict)
+ except Exception as e:
+ if not floating_network['exit_on_floating_ip_error']:
+ self.logger.warn("Cannot create floating_ip. %s", str(e))
+ continue
+ self.delete_vminstance(server.id)
+ raise
- 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)
- free_floating_ip = new_floating_ip['floatingip']['floating_ip_address']
- fix_ip = floating_network.get('ip')
- server.add_floating_ip(free_floating_ip, fix_ip)
- assigned=True
- except Exception as e:
- self.delete_vminstance(server.id)
- raise vimconn.vimconnException(type(e).__name__ + ": Cannot create floating_ip "+ str(e), http_code=vimconn.HTTP_Conflict)
-
return server.id
# except nvExceptions.NotFound as e:
# error_value=-vimconn.HTTP_Not_Found
# error_text= "vm instance %s not found" % vm_id
- except (ksExceptions.ClientException, nvExceptions.ClientException, ConnectionError
- ) as e:
+ 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():
#TODO ip, security groups
Returns the instance identifier
'''
+ self.logger.debug("new_vminstance input: image='%s' flavor='%s' nics='%s'", image_id, flavor_id, str(net_list))
try:
self._get_my_tenant()
# net_list = []
self.admin_password = None
self.admin_user = None
self.org_name = ""
+ self.nsx_manager = None
+ self.nsx_user = None
+ self.nsx_password = None
if tenant_name is not None:
orgnameandtenant = tenant_name.split(":")
except KeyError:
raise vimconn.vimconnException(message="Error admin username or admin password is empty.")
+ try:
+ self.nsx_manager = config['nsx_manager']
+ self.nsx_user = config['nsx_user']
+ self.nsx_password = config['nsx_password']
+ except KeyError:
+ raise vimconn.vimconnException(message="Error: nsx manager or nsx user or nsx password is empty in Config")
+
self.org_uuid = None
self.vca = None
return self.get_catalogid(catalog_md5_name, vca.get_catalogs())
+ def get_image_list(self, filter_dict={}):
+ '''Obtain tenant images from VIM
+ Filter_dict can be:
+ name: image name
+ id: image uuid
+ checksum: image checksum
+ location: image path
+ Returns the image list of dictionaries:
+ [{<the fields at Filter_dict plus some VIM specific>}, ...]
+ List can be empty
+ '''
+ vca = self.connect()
+ if not vca:
+ raise vimconn.vimconnConnectionException("self.connect() is failed.")
+ try:
+ image_list = []
+ catalogs = vca.get_catalogs()
+ if len(catalogs) == 0:
+ return image_list
+ else:
+ for catalog in catalogs:
+ catalog_uuid = catalog.get_id().split(":")[3]
+ name = catalog.name
+ filtered_dict = {}
+ if filter_dict.get("name") and filter_dict["name"] != name:
+ continue
+ if filter_dict.get("id") and filter_dict["id"] != catalog_uuid:
+ continue
+ filtered_dict ["name"] = name
+ filtered_dict ["id"] = catalog_uuid
+ image_list.append(filtered_dict)
+
+ self.logger.debug("List of already created catalog items: {}".format(image_list))
+ return image_list
+ except Exception as exp:
+ raise vimconn.vimconnException("Exception occured while retriving catalog items {}".format(exp))
+
def get_vappid(self, vdc=None, vapp_name=None):
""" Method takes vdc object and vApp name and returns vapp uuid or None
"""
self.logger.debug("Client requesting refresh vm status for {} ".format(vm_list))
+
+ mac_ip_addr={}
+ rheaders = {'Content-Type': 'application/xml'}
+ iso_edges = ['edge-2','edge-3','edge-6','edge-7','edge-8','edge-9','edge-10']
+
+ try:
+ for edge in iso_edges:
+ nsx_api_url = '/api/4.0/edges/'+ edge +'/dhcp/leaseInfo'
+ self.logger.debug("refresh_vms_status: NSX Manager url: {}".format(nsx_api_url))
+
+ resp = requests.get(self.nsx_manager + nsx_api_url,
+ auth = (self.nsx_user, self.nsx_password),
+ verify = False, headers = rheaders)
+
+ if resp.status_code == requests.codes.ok:
+ dhcp_leases = XmlElementTree.fromstring(resp.text)
+ for child in dhcp_leases:
+ if child.tag == 'dhcpLeaseInfo':
+ dhcpLeaseInfo = child
+ for leaseInfo in dhcpLeaseInfo:
+ for elem in leaseInfo:
+ if (elem.tag)=='macAddress':
+ mac_addr = elem.text
+ if (elem.tag)=='ipAddress':
+ ip_addr = elem.text
+ if (mac_addr) is not None:
+ mac_ip_addr[mac_addr]= ip_addr
+ self.logger.debug("NSX Manager DHCP Lease info: mac_ip_addr : {}".format(mac_ip_addr))
+ else:
+ self.logger.debug("Error occurred while getting DHCP lease info from NSX Manager: {}".format(resp.content))
+ except KeyError:
+ self.logger.debug("Error in response from NSX Manager {}".format(KeyError.message))
+ self.logger.debug(traceback.format_exc())
+
vca = self.connect()
if not vca:
raise vimconn.vimconnConnectionException("self.connect() is failed.")
for vapp_network in vm_app_networks:
for vm_network in vapp_network:
if vm_network['name'] == vmname:
+ #Assign IP Address based on MAC Address in NSX DHCP lease info
+ for mac_adres,ip_adres in mac_ip_addr.iteritems():
+ if mac_adres == vm_network['mac']:
+ vm_network['ip']=ip_adres
interface = {"mac_address": vm_network['mac'],
"vim_net_id": self.get_network_id_by_name(vm_network['network_name']),
"vim_interface_id": self.get_network_id_by_name(vm_network['network_name']),
the_vapp = vca.get_vapp(vdc, vapp_name)
# TODO fix all status
if "start" in action_dict:
- if action_dict["start"] == "rebuild":
- the_vapp.deploy(powerOn=True)
+ vm_info = the_vapp.get_vms_details()
+ vm_status = vm_info[0]['status']
+ self.logger.info("Power on vApp: vm_status:{} {}".format(type(vm_status),vm_status))
+ if vm_status == "Suspended" or vm_status == "Powered off":
+ power_on_task = the_vapp.poweron()
+ if power_on_task is not None and type(power_on_task) is GenericTask:
+ result = vca.block_until_completed(power_on_task)
+ if result:
+ self.logger.info("action_vminstance: Powered on vApp: {}".format(vapp_name))
+ else:
+ self.logger.info("action_vminstance: Failed to power on vApp: {}".format(vapp_name))
+ else:
+ self.logger.info("action_vminstance: Wait for vApp {} to power on".format(vapp_name))
+ elif "rebuild" in action_dict:
+ self.logger.info("action_vminstance: Rebuilding vApp: {}".format(vapp_name))
+ power_on_task = the_vapp.deploy(powerOn=True)
+ if type(power_on_task) is GenericTask:
+ result = vca.block_until_completed(power_on_task)
+ if result:
+ self.logger.info("action_vminstance: Rebuilt vApp: {}".format(vapp_name))
+ else:
+ self.logger.info("action_vminstance: Failed to rebuild vApp: {}".format(vapp_name))
else:
- vm_info = the_vapp.get_vms_details()
- vm_status = vm_info[0]['status']
- if vm_status == "Suspended":
- the_vapp.poweron()
- elif vm_status.status == "Powered off":
- the_vapp.poweron()
+ self.logger.info("action_vminstance: Wait for vApp rebuild {} to power on".format(vapp_name))
elif "pause" in action_dict:
pass
## server.pause()
pass
## server.resume()
elif "shutoff" in action_dict or "shutdown" in action_dict:
- the_vapp.shutdown()
+ power_off_task = the_vapp.undeploy(action='powerOff')
+ if type(power_off_task) is GenericTask:
+ result = vca.block_until_completed(power_off_task)
+ if result:
+ self.logger.info("action_vminstance: Powered off vApp: {}".format(vapp_name))
+ else:
+ self.logger.info("action_vminstance: Failed to power off vApp: {}".format(vapp_name))
+ else:
+ self.logger.info("action_vminstance: Wait for vApp {} to power off".format(vapp_name))
elif "forceOff" in action_dict:
the_vapp.reset()
elif "terminate" in action_dict:
description: Single-VM VNF with a traditional cloud VM based on generic Linux OS
external-connections:
- name: eth0
- type: bridge
+ type: mgmt
description: General purpose interface
VNFC: linux-VM
local_iface_name: eth0