&& mv /tmp/libzenohc.so /usr/local/lib/libzenohc.so \
&& DEBIAN_FRONTEND=noninteractive python3 -m pip install -U jsonrpclib-pelix cvprac \
"osm-im @ git+https://osm.etsi.org/gerrit/osm/IM.git#egg=osm-im" "azure==4.0.0" boto \
- untangle pyone "oca @ git+https://github.com/python-oca/python-oca#egg=oca" \
+ pyone "oca @ git+https://github.com/python-oca/python-oca#egg=oca" \
pyangbind sphinx zenoh==0.3.0 yaks==0.3.0.post1 fog05-sdk==0.2.0 fog05==0.2.0
-
# DEBIAN_FRONTEND=noninteractive apt-get -y install python-openstacksdk python-openstackclient && \
# TODO py3 DEBIAN_FRONTEND=noninteractive add-apt-repository -y cloud-archive:rocky && apt-get update && apt-get install -y python3-networking-l2gw \
def __init__(self, topology=_VXLAN_MLAG):\r
self.topology = topology\r
\r
- _basic_int ="""\r
+ _basic_int = """\r
interface {interface}\r
!! service: {uuid}\r
switchport\r
def getEline_passthrough(self, uuid, interface, vlan_id, index):\r
return self._get_interface(uuid, interface, vlan_id, "ELINE", index, "dot1q-tunnel")\r
\r
- _basic_vlan ="""\r
+ _basic_vlan = """\r
vlan {vlan}\r
!! service: {service} {vlan} {uuid}\r
name {service}{vlan}\r
trunk group {service}{vlan}\r
"""\r
- _basic_mlag =""" trunk group MLAGPEER\r
+ _basic_mlag = """ trunk group MLAGPEER\r
"""\r
- _basic_vxlan ="""interface VXLAN1\r
+ _basic_vxlan = """interface VXLAN1\r
VXLAN vlan {vlan} vni {vni}\r
"""\r
- _basic_end ="!"\r
+ _basic_end = "!"\r
\r
_configLet_VLAN = _basic_vlan + _basic_end\r
_configLet_VXLAN = _basic_vlan + _basic_vxlan + _basic_end\r
loopback=loopback0,\r
vni=vni_id)\r
\r
-\r
def getElan_bgp(self, uuid, vlan_id, vni_id, loopback0, bgp):\r
return self._get_bgp(uuid, vlan_id, vni_id, loopback0, bgp, "ELAN")\r
\r
from cvprac.cvp_client import CvpClient
from cvprac.cvp_api import CvpApi
-from cvprac.cvp_client_errors import CvpLoginError, CvpSessionLogOutError, CvpApiError
+from cvprac.cvp_client_errors import CvpLoginError, CvpSessionLogOutError, CvpApiError
from cvprac import __version__ as cvprac_version
from osm_rosdn_arista_cloudvision.aristaConfigLet import AristaSDNConfigLet
_VLAN_MLAG = "VLAN-MLAG"
_VXLAN_MLAG = "VXLAN-MLAG"
-
def __init__(self, wim, wim_account, config=None, logger=None):
"""
raise SdnConnectorError(message="Unable to load switches from CVP",
http_code=500) from e
self.logger.debug("Using topology {} in Arista Leaf switches: {}".format(
- self.topology,
- self.delete_keys_from_dict(self.switches, ('passwd',))))
+ self.topology,
+ self.delete_keys_from_dict(self.switches, ('passwd',))))
self.clC = AristaSDNConfigLet(self.topology)
def __load_topology(self):
self.switches[cs].update(cs_content)
# Load the rest of the data
- if self.client == None:
+ if self.client is None:
self.client = self.__connect()
self.__load_inventory()
if not self.switches:
for testing the access to CloudVision API
"""
try:
- if self.client == None:
+ if self.client is None:
self.client = self.__connect()
result = self.client.api.get_cvp_info()
self.logger.debug(result)
http_code=500)
self.__get_Connection()
- if conn_info == None:
+ if conn_info is None:
raise SdnConnectorError(message='No connection information for service UUID {}'.format(service_uuid),
http_code=500)
self.logger.info("Service with uuid {} created.".
format(service_uuid))
s_uid, s_connInf = self.__processConnection(
- service_uuid,
- service_type,
- connection_points,
- kwargs)
+ service_uuid,
+ service_type,
+ connection_points,
+ kwargs)
try:
self.__addMetadata(s_uid, service_type, s_connInf['vlan_id'])
- except Exception as e:
+ except Exception:
pass
return (s_uid, s_connInf)
processed_connection_points += switches
for switch in switches:
if not interface:
- raise SdnConnectorError(message="Connection point switch port empty for switch_dpid {}".format(switch_id),
- http_code=406)
+ raise SdnConnectorError(
+ message="Connection point switch port empty for switch_dpid {}".format(switch_id),
+ http_code=406)
# it should be only one switch where the mac is attached
if encap_type == 'dot1q':
# SRIOV configLet for Leaf switch mac's attached to
continue
cl = cls_perSw[s]
res = self.__device_modify(
- device_to_update=s,
- new_configlets=cl,
- delete=toDelete_in_cvp)
+ device_to_update=s,
+ new_configlets=cl,
+ delete=toDelete_in_cvp)
if "errorMessage" in str(res):
raise Exception(str(res))
self.logger.info("Device {} modify result {}".format(s, res))
t_id,
self.__SEPARATOR)
self.client.api.add_note_to_configlet(
- cls_perSw[s][0]['key'],
- note_msg)
+ cls_perSw[s][0]['key'],
+ note_msg)
cls_perSw[s][0]['note'] = note_msg
- tasks = { t_id : {'workOrderId': t_id} }
+ tasks = {t_id: {'workOrderId': t_id}}
self.__exec_task(tasks, self.__EXC_TASK_EXEC_WAIT)
# with just one configLet assigned to a device,
# delete all if there are errors in next loops
allLeafModified)
except Exception as e:
self.logger.error("Exception rolling back in updating connection: {}".
- format(e), exc_info=True)
+ format(e), exc_info=True)
raise ex
def __rollbackConnection(self,
self.__configlet_modify(cls_perSw[s], delete=True)
def __exec_task(self, tasks, tout=10):
- if self.taskC == None:
+ if self.taskC is None:
self.__connect()
data = self.taskC.update_all_tasks(tasks).values()
self.taskC.task_action(data, tout, 'executed')
""" Updates the devices (switches) adding or removing the configLet,
the tasks Id's associated to the change are returned
"""
- self.logger.info('Enter in __device_modify delete: {}'.format(
- delete))
+ self.logger.info('Enter in __device_modify delete: {}'.format(delete))
updated = []
changed = False
# Task Ids that have been identified during device actions
newTasks = []
if (len(new_configlets) == 0 or
- device_to_update == None or
+ device_to_update is None or
len(device_to_update) == 0):
data = {'updated': updated, 'tasks': newTasks}
return [changed, data]
if try_device['hostname'] not in device_to_update:
continue
dev_cvp_configlets = self.client.api.get_configlets_by_device_id(
- try_device['systemMacAddress'])
+ try_device['systemMacAddress'])
# self.logger.debug(dev_cvp_configlets)
try_device['deviceSpecificConfiglets'] = []
for cvp_configlet in dev_cvp_configlets:
if int(cvp_configlet['containerCount']) == 0:
try_device['deviceSpecificConfiglets'].append(
- {'name': cvp_configlet['name'],
- 'key': cvp_configlet['key']})
+ {'name': cvp_configlet['name'],
+ 'key': cvp_configlet['key']})
# self.logger.debug(device)
device = try_device
break
try:
if delete and len(cl_toDel) > 0:
r = self.client.api.remove_configlets_from_device(
- 'OSM',
- up_device['device'],
- cl_toDel,
- create_task=True)
+ 'OSM',
+ up_device['device'],
+ cl_toDel,
+ create_task=True)
dev_action = r
self.logger.debug("remove_configlets_from_device {} {}".format(dev_action, cl_toDel))
elif len(cl_toAdd) > 0:
r = self.client.api.apply_configlets_to_device(
- 'OSM',
- up_device['device'],
- cl_toAdd,
- create_task=True)
+ 'OSM',
+ up_device['device'],
+ cl_toAdd,
+ create_task=True)
dev_action = r
self.logger.debug("apply_configlets_to_device {} {}".format(dev_action, cl_toAdd))
except Exception as error:
errorMessage = str(error)
msg = "errorMessage: Device {} Configlets couldnot be updated: {}".format(
- up_device['hostname'], errorMessage)
+ up_device['hostname'], errorMessage)
raise SdnConnectorError(msg) from error
else:
if "errorMessage" in str(dev_action):
m = "Device {} Configlets update fail: {}".format(
- up_device['name'], dev_action['errorMessage'])
+ up_device['name'], dev_action['errorMessage'])
raise SdnConnectorError(m)
else:
changed = True
if 'taskIds' in str(dev_action):
# Fix 1030 SDN-ARISTA Key error note when deploy a NS
if not dev_action['data']['taskIds']:
- raise SdnConnectorError("No taskIds found: Device {} Configlets couldnot be updated".format(
- up_device['hostname']))
+ raise SdnConnectorError("No taskIds found: Device {} Configlets could not be updated".format(
+ up_device['hostname']))
for taskId in dev_action['data']['taskIds']:
- updated.append({up_device['hostname']:
- "Configlets-{}".format(
- taskId)})
+ updated.append({
+ up_device['hostname']: "Configlets-{}".format(taskId)})
newTasks.append(taskId)
else:
updated.append({up_device['hostname']:
:return: data: dict of module actions and taskIDs
'''
self.logger.info('Enter in __configlet_modify delete:{}'.format(
- delete))
+ delete))
# Compare configlets against cvp_facts-configlets
changed = False
if to_delete:
operation = 'delete'
resp = self.client.api.delete_configlet(
- configlet['data']['name'],
- configlet['data']['key'])
+ configlet['data']['name'],
+ configlet['data']['key'])
elif to_update:
operation = 'update'
resp = self.client.api.update_configlet(
- configlet['config'],
- configlet['data']['key'],
- configlet['data']['name'],
- wait_task_ids=True)
+ configlet['config'],
+ configlet['data']['key'],
+ configlet['data']['name'],
+ wait_task_ids=True)
elif to_create:
operation = 'create'
resp = self.client.api.add_configlet(
- configlet['name'],
- configlet['config'])
+ configlet['name'],
+ configlet['config'])
else:
operation = 'checked'
resp = 'checked'
except Exception as error:
errorMessage = str(error).split(':')[-1]
message = "Configlet {} cannot be {}: {}".format(
- cl['name'], operation, errorMessage)
+ cl['name'], operation, errorMessage)
if to_delete:
deleted.append({configlet['name']: message})
elif to_update:
else:
if "error" in str(resp).lower():
message = "Configlet {} cannot be deleted: {}".format(
- cl['name'], resp['errorMessage'])
+ cl['name'], resp['errorMessage'])
if to_delete:
deleted.append({configlet['name']: message})
elif to_update:
if len(configlet) > 0:
configlet['devices'] = []
applied_devices = self.client.api.get_applied_devices(
- configlet['name'])
+ configlet['name'])
for device in applied_devices['data']:
configlet['devices'].append(device['hostName'])
http_code=500)
self.__get_Connection()
- if conn_info == None:
+ if conn_info is None:
raise SdnConnectorError(message='No connection information for service UUID {}'.format(service_uuid),
http_code=500)
c_info = None
raise SdnConnectorError(message='Unable to perform operation, missing or empty connection information',
http_code=500)
- if connection_points == None:
+ if connection_points is None:
return None
self.__get_Connection()
kwargs=kwargs)
s_uid, s_connInf = self.__processConnection(
- service_uuid,
- service_type,
- connection_points,
- kwargs)
+ service_uuid,
+ service_type,
+ connection_points,
+ kwargs)
self.logger.info("Service with uuid {} configuration updated".
format(s_uid))
return s_connInf
# TODO check if there are pending task, and cancel them before restoring
self.__updateConnection(cls_currentPerSw)
except Exception as e:
- self.logger.error("Unable to restore configuration in service {} after an error in the configuration updated: {}".
- format(service_uuid, str(e)))
+ self.logger.error("Unable to restore configuration in service {} after an error in the configuration"
+ " updated: {}".format(service_uuid, str(e)))
if self.raiseException:
raise ex
raise SdnConnectorError(message=str(ex),
invoking the version retrival as test
"""
try:
- if self.client == None:
+ if self.client is None:
self.client = self.__connect()
self.client.api.get_cvp_info()
except (CvpSessionLogOutError, RequestException) as e:
break
if found:
break
- if peer == None:
- self.logger.error('No Peer device found for device {} with MLAG address {}'.format(device_id, mlagSystemId))
+ if peer is None:
+ self.logger.error('No Peer device found for device {} with MLAG address {}'.format(device_id,
+ mlagSystemId))
else:
self.logger.debug('Peer MLAG for device {} - value {}'.format(device_id, peer))
return peer
return True
def delete_keys_from_dict(self, dict_del, lst_keys):
- if dict_del == None:
+ if dict_del is None:
return dict_del
dict_copy = {k: v for k, v in dict_del.items() if k not in lst_keys}
for k, v in dict_copy.items():
[tox]
envlist = flake8
-toxworkdir={toxinidir}/.tox
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
import paramiko
import requests
import struct
-import sys
+# import sys
from osm_ro_plugin.sdnconn import SdnConnectorBase, SdnConnectorError
ro is restarted
"""
self._check_connection()
- if data == None:
+ if data is None:
data = {}
url_ext_info = url_params.split('/')
for i in range(0, len(url_ext_info)):
try:
self.__post(self.__ACTIONS_MAP.get("RELEASE"),
"/service/"+service_uuid, get_response=False)
- except:
+ except Exception as e:
raise SdnConnectorError(
- "Could not delete service id:{} (could be an issue with the DPB)".format(service_uuid), 500)
+ "Could not delete service id:{} (could be an issue with the DPB): {}".format(service_uuid, e), 500)
self.logger.debug(
"Deleted connectivity service id:{}".format(service_uuid))
return None
return conn_info
def __check_service(self, serv_type, points, kwargs):
- if not serv_type in self.__SUPPORTED_SERV_TYPES:
+ if serv_type not in self.__SUPPORTED_SERV_TYPES:
raise SdnConnectorError("Service type no supported", 400)
# Future: BW Checks here
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
##
requests
-git+https://osm.etsi.org/gerrit/osm/RO.git#egg=osm-ro-plugin&subdirectory=RO-plugin
+osm-ro-plugin @ git+https://osm.etsi.org/gerrit/osm/RO.git#egg=osm-ro-plugin&subdirectory=RO-plugin
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
+usedevelop = True
basepython = python3
install_command = python3 -m pip install -r requirements.txt -U {opts} {packages}
-# deps = -r{toxinidir}/test-requirements.txt
-commands=python3 -m unittest discover -v
[testenv:flake8]
basepython = python3
[tox]
envlist = flake8
-toxworkdir={homedir}/.tox
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
# Aux methods to avoid code duplication of name conventions
def get_vpg_name(self, switch_id, switch_port):
- return "{}_{}".format(switch_id, switch_port).replace(":","_")
+ return "{}_{}".format(switch_id, switch_port).replace(":", "_")
def get_vmi_name(self, switch_id, switch_port, vlan):
- return "{}_{}-{}".format(switch_id, switch_port, vlan).replace(":","_")
+ return "{}_{}-{}".format(switch_id, switch_port, vlan).replace(":", "_")
# Virtual network operations
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
import requests
import base64
import logging
-from osm_ro_plugin.openflow_conn import OpenflowConn, OpenflowConnException, OpenflowConnConnectionException, \
- OpenflowConnUnexpectedResponse, OpenflowConnAuthException, OpenflowConnNotFoundException, \
- OpenflowConnConflictException, OpenflowConnNotSupportedException, OpenflowConnNotImplemented
+from osm_ro_plugin.openflow_conn import OpenflowConn, OpenflowConnConnectionException, OpenflowConnUnexpectedResponse
+# OpenflowConnException, OpenflowConnAuthException, OpenflowConnNotFoundException,
+# OpenflowConnConflictException, OpenflowConnNotSupportedException, OpenflowConnNotImplemented
__author__ = "Pablo Montes, Alfonso Tierno"
-__date__ = "$28-oct-2014 12:07:15$"
+__date__ = "$28-oct-2014 12:07:15$"
class OfConnOdl(OpenflowConn):
self.dpid = str(params["of_dpid"])
self.id = 'openflow:'+str(int(self.dpid.replace(':', ''), 16))
if params and params.get("of_user"):
- of_password=params.get("of_password", "")
+ of_password = params.get("of_password", "")
self.auth = base64.b64encode(bytes(params["of_user"] + ":" + of_password, "utf-8"))
self.auth = self.auth.decode()
self.headers['authorization'] = 'Basic ' + self.auth
"""
Obtain a a list of switches or DPID detected by this controller
:return: list length, and a list where each element a tuple pair (DPID, IP address)
- Raise an OpenflowconnConnectionException exception if fails with text_error
+ Raise an OpenflowConnConnectionException exception if fails with text_error
"""
try:
of_response = requests.get(self.url + "restconf/operational/opendaylight-inventory:nodes",
error_text = "Openflow response {}: {}".format(of_response.status_code, of_response.text)
if of_response.status_code != 200:
self.logger.warning("get_of_switches " + error_text)
- raise OpenflowconnUnexpectedResponse("Error get_of_switches " + error_text)
+ raise OpenflowConnUnexpectedResponse("Error get_of_switches " + error_text)
self.logger.debug("get_of_switches " + error_text)
info = of_response.json()
if not isinstance(info, dict):
self.logger.error("get_of_switches. Unexpected response, not a dict: %s", str(info))
- raise OpenflowconnUnexpectedResponse("Unexpected response, not a dict. Wrong version?")
+ raise OpenflowConnUnexpectedResponse("Unexpected response, not a dict. Wrong version?")
nodes = info.get('nodes')
if type(nodes) is not dict:
self.logger.error("get_of_switches. Unexpected response at 'nodes', not found or not a dict: %s",
str(type(info)))
- raise OpenflowconnUnexpectedResponse("Unexpected response at 'nodes', not found or not a dict."
+ raise OpenflowConnUnexpectedResponse("Unexpected response at 'nodes', not found or not a dict."
" Wrong version?")
node_list = nodes.get('node')
if type(node_list) is not list:
self.logger.error("get_of_switches. Unexpected response, at 'nodes':'node', "
"not found or not a list: %s", str(type(node_list)))
- raise OpenflowconnUnexpectedResponse("Unexpected response, at 'nodes':'node', not found "
+ raise OpenflowConnUnexpectedResponse("Unexpected response, at 'nodes':'node', not found "
"or not a list. Wrong version?")
switch_list = []
if node_id is None:
self.logger.error("get_of_switches. Unexpected response at 'nodes':'node'[]:'id', not found: %s",
str(node))
- raise OpenflowconnUnexpectedResponse("Unexpected response at 'nodes':'node'[]:'id', not found. "
+ raise OpenflowConnUnexpectedResponse("Unexpected response at 'nodes':'node'[]:'id', not found. "
"Wrong version?")
if node_id == 'controller-config':
if node_ip_address is None:
self.logger.error("get_of_switches. Unexpected response at 'nodes':'node'[]:'flow-node-inventory:"
"ip-address', not found: %s", str(node))
- raise OpenflowconnUnexpectedResponse("Unexpected response at 'nodes':'node'[]:"
+ raise OpenflowConnUnexpectedResponse("Unexpected response at 'nodes':'node'[]:"
"'flow-node-inventory:ip-address', not found. Wrong version?")
node_id_hex = hex(int(node_id.split(':')[1])).split('x')[1].zfill(16)
- switch_list.append((':'.join(a+b for a,b in zip(node_id_hex[::2], node_id_hex[1::2])), node_ip_address))
+ switch_list.append((':'.join(a+b for a, b in zip(node_id_hex[::2], node_id_hex[1::2])),
+ node_ip_address))
return switch_list
except requests.exceptions.RequestException as e:
error_text = type(e).__name__ + ": " + str(e)
self.logger.error("get_of_switches " + error_text)
- raise OpenflowconnConnectionException(error_text)
+ raise OpenflowConnConnectionException(error_text)
except ValueError as e:
# ValueError in the case that JSON can not be decoded
error_text = type(e).__name__ + ": " + str(e)
self.logger.error("get_of_switches " + error_text)
- raise OpenflowconnUnexpectedResponse(error_text)
+ raise OpenflowConnUnexpectedResponse(error_text)
def obtain_port_correspondence(self):
"""
Obtain the correspondence between physical and openflow port names
:return: dictionary: with physical name as key, openflow name as value,
- Raise a OpenflowconnConnectionException expection in case of failure
+ Raise a OpenflowConnConnectionException expection in case of failure
"""
try:
of_response = requests.get(self.url + "restconf/operational/opendaylight-inventory:nodes",
error_text = "Openflow response {}: {}".format(of_response.status_code, of_response.text)
if of_response.status_code != 200:
self.logger.warning("obtain_port_correspondence " + error_text)
- raise OpenflowconnUnexpectedResponse(error_text)
+ raise OpenflowConnUnexpectedResponse(error_text)
self.logger.debug("obtain_port_correspondence " + error_text)
info = of_response.json()
if not isinstance(info, dict):
self.logger.error("obtain_port_correspondence. Unexpected response not a dict: %s", str(info))
- raise OpenflowconnUnexpectedResponse("Unexpected openflow response, not a dict. Wrong version?")
+ raise OpenflowConnUnexpectedResponse("Unexpected openflow response, not a dict. Wrong version?")
nodes = info.get('nodes')
if not isinstance(nodes, dict):
self.logger.error("obtain_port_correspondence. Unexpected response at 'nodes', "
"not found or not a dict: %s", str(type(nodes)))
- raise OpenflowconnUnexpectedResponse("Unexpected response at 'nodes',not found or not a dict. "
+ raise OpenflowConnUnexpectedResponse("Unexpected response at 'nodes',not found or not a dict. "
"Wrong version?")
node_list = nodes.get('node')
if not isinstance(node_list, list):
self.logger.error("obtain_port_correspondence. Unexpected response, at 'nodes':'node', "
"not found or not a list: %s", str(type(node_list)))
- raise OpenflowconnUnexpectedResponse("Unexpected response, at 'nodes':'node', not found or not a list."
+ raise OpenflowConnUnexpectedResponse("Unexpected response, at 'nodes':'node', not found or not a list."
" Wrong version?")
for node in node_list:
if node_id is None:
self.logger.error("obtain_port_correspondence. Unexpected response at 'nodes':'node'[]:'id', "
"not found: %s", str(node))
- raise OpenflowconnUnexpectedResponse("Unexpected response at 'nodes':'node'[]:'id', not found. "
+ raise OpenflowConnUnexpectedResponse("Unexpected response at 'nodes':'node'[]:'id', not found. "
"Wrong version?")
if node_id == 'controller-config':
if not isinstance(node_connector_list, list):
self.logger.error("obtain_port_correspondence. Unexpected response at "
"'nodes':'node'[]:'node-connector', not found or not a list: %s", str(node))
- raise OpenflowconnUnexpectedResponse("Unexpected response at 'nodes':'node'[]:'node-connector', "
+ raise OpenflowConnUnexpectedResponse("Unexpected response at 'nodes':'node'[]:'node-connector', "
"not found or not a list. Wrong version?")
for node_connector in node_connector_list:
if node_ip_address is None:
self.logger.error("obtain_port_correspondence. Unexpected response at 'nodes':'node'[]:"
"'flow-node-inventory:ip-address', not found: %s", str(node))
- raise OpenflowconnUnexpectedResponse("Unexpected response at 'nodes':'node'[]:"
+ raise OpenflowConnUnexpectedResponse("Unexpected response at 'nodes':'node'[]:"
"'flow-node-inventory:ip-address', not found. Wrong version?")
# If we found the appropriate dpid no need to continue in the for loop
except requests.exceptions.RequestException as e:
error_text = type(e).__name__ + ": " + str(e)
self.logger.error("obtain_port_correspondence " + error_text)
- raise OpenflowconnConnectionException(error_text)
+ raise OpenflowConnConnectionException(error_text)
except ValueError as e:
# ValueError in the case that JSON can not be decoded
error_text = type(e).__name__ + ": " + str(e)
self.logger.error("obtain_port_correspondence " + error_text)
- raise OpenflowconnUnexpectedResponse(error_text)
+ raise OpenflowConnUnexpectedResponse(error_text)
def get_of_rules(self, translate_of_ports=True):
"""
(vlan, None/int): for stripping/setting a vlan tag
(out, port): send to this port
switch: DPID, all
- Raise a OpenflowconnConnectionException exception in case of failure
+ Raise a OpenflowConnConnectionException exception in case of failure
"""
elif of_response.status_code != 200:
self.logger.warning("get_of_rules " + error_text)
- raise OpenflowconnUnexpectedResponse(error_text)
+ raise OpenflowConnUnexpectedResponse(error_text)
self.logger.debug("get_of_rules " + error_text)
if not isinstance(info, dict):
self.logger.error("get_of_rules. Unexpected response not a dict: %s", str(info))
- raise OpenflowconnUnexpectedResponse("Unexpected openflow response, not a dict. Wrong version?")
+ raise OpenflowConnUnexpectedResponse("Unexpected openflow response, not a dict. Wrong version?")
table = info.get('flow-node-inventory:table')
if not isinstance(table, list):
self.logger.error("get_of_rules. Unexpected response at 'flow-node-inventory:table', "
"not a list: %s", str(type(table)))
- raise OpenflowconnUnexpectedResponse("Unexpected response at 'flow-node-inventory:table', not a list. "
+ raise OpenflowConnUnexpectedResponse("Unexpected response at 'flow-node-inventory:table', not a list. "
"Wrong version?")
flow_list = table[0].get('flow')
if not isinstance(flow_list, list):
self.logger.error("get_of_rules. Unexpected response at 'flow-node-inventory:table'[0]:'flow', not a "
"list: %s", str(type(flow_list)))
- raise OpenflowconnUnexpectedResponse("Unexpected response at 'flow-node-inventory:table'[0]:'flow', "
+ raise OpenflowConnUnexpectedResponse("Unexpected response at 'flow-node-inventory:table'[0]:'flow', "
"not a list. Wrong version?")
# TODO translate ports according to translate_of_ports parameter
rules = [] # Response list
for flow in flow_list:
if not ('id' in flow and 'match' in flow and 'instructions' in flow and
- 'instruction' in flow['instructions'] and
- 'apply-actions' in flow['instructions']['instruction'][0] and
- 'action' in flow['instructions']['instruction'][0]['apply-actions']):
- raise OpenflowconnUnexpectedResponse("unexpected openflow response, one or more elements are "
+ 'instruction' in flow['instructions'] and
+ 'apply-actions' in flow['instructions']['instruction'][0] and
+ 'action' in flow['instructions']['instruction'][0]['apply-actions']):
+ raise OpenflowConnUnexpectedResponse("unexpected openflow response, one or more elements are "
"missing. Wrong version?")
flow['instructions']['instruction'][0]['apply-actions']['action']
if 'in-port' in flow['match']:
in_port = flow['match']['in-port']
if in_port not in self.ofi2pp:
- raise OpenflowconnUnexpectedResponse("Error: Ingress port {} is not in switch port list".
+ raise OpenflowConnUnexpectedResponse("Error: Ingress port {} is not in switch port list".
format(in_port))
if translate_of_ports:
if 'vlan-match' in flow['match'] and 'vlan-id' in flow['match']['vlan-match'] and \
'vlan-id' in flow['match']['vlan-match']['vlan-id'] and \
'vlan-id-present' in flow['match']['vlan-match']['vlan-id'] and \
- flow['match']['vlan-match']['vlan-id']['vlan-id-present'] == True:
+ flow['match']['vlan-match']['vlan-id']['vlan-id-present'] is True:
rule['vlan_id'] = flow['match']['vlan-match']['vlan-id']['vlan-id']
if 'ethernet-match' in flow['match'] and 'ethernet-destination' in flow['match']['ethernet-match'] \
for instruction in instructions:
if 'output-action' in instruction:
if 'output-node-connector' not in instruction['output-action']:
- raise OpenflowconnUnexpectedResponse("unexpected openflow response, one or more elementa "
+ raise OpenflowConnUnexpectedResponse("unexpected openflow response, one or more elementa "
"are missing. Wrong version?")
out_port = instruction['output-action']['output-node-connector']
if out_port not in self.ofi2pp:
- raise OpenflowconnUnexpectedResponse("Error: Output port {} is not in switch port list".
+ raise OpenflowConnUnexpectedResponse("Error: Output port {} is not in switch port list".
format(out_port))
if translate_of_ports:
if not ('vlan-match' in instruction['set-field'] and
'vlan-id' in instruction['set-field']['vlan-match'] and
'vlan-id' in instruction['set-field']['vlan-match']['vlan-id']):
- raise OpenflowconnUnexpectedResponse("unexpected openflow response, one or more elements "
+ raise OpenflowConnUnexpectedResponse("unexpected openflow response, one or more elements "
"are missing. Wrong version?")
actions[instruction['order']] = ('vlan',
except requests.exceptions.RequestException as e:
error_text = type(e).__name__ + ": " + str(e)
self.logger.error("get_of_rules " + error_text)
- raise OpenflowconnConnectionException(error_text)
+ raise OpenflowConnConnectionException(error_text)
except ValueError as e:
# ValueError in the case that JSON can not be decoded
error_text = type(e).__name__ + ": " + str(e)
self.logger.error("get_of_rules " + error_text)
- raise OpenflowconnUnexpectedResponse(error_text)
+ raise OpenflowConnUnexpectedResponse(error_text)
def del_flow(self, flow_name):
"""
Delete an existing rule
:param flow_name: flow_name, this is the rule name
- :return: Raise a OpenflowconnConnectionException expection in case of failure
+ :return: Raise a OpenflowConnConnectionException expection in case of failure
"""
try:
error_text = "Openflow response {}: {}".format(of_response.status_code, of_response.text)
if of_response.status_code != 200:
self.logger.warning("del_flow " + error_text)
- raise OpenflowconnUnexpectedResponse(error_text)
+ raise OpenflowConnUnexpectedResponse(error_text)
self.logger.debug("del_flow OK " + error_text)
return None
except requests.exceptions.RequestException as e:
# raise an exception in case of contection error
error_text = type(e).__name__ + ": " + str(e)
self.logger.error("del_flow " + error_text)
- raise OpenflowconnConnectionException(error_text)
+ raise OpenflowConnConnectionException(error_text)
def new_flow(self, data):
"""
actions: list of actions, composed by a pair tuples with these posibilities:
('vlan', None/int): for stripping/setting a vlan tag
('out', port): send to this port
- :return: Raise a OpenflowconnConnectionException exception in case of failure
+ :return: Raise a OpenflowConnConnectionException exception in case of failure
"""
try:
if not data['ingress_port'] in self.pp2ofi:
error_text = 'Error. Port ' + data['ingress_port'] + ' is not present in the switch'
self.logger.warning("new_flow " + error_text)
- raise OpenflowconnUnexpectedResponse(error_text)
+ raise OpenflowConnUnexpectedResponse(error_text)
flow['match']['in-port'] = self.pp2ofi[data['ingress_port']]
if data.get('dst_mac'):
flow['match']['ethernet-match'] = {
new_action['output-action'] = {}
if not action[1] in self.pp2ofi:
error_msg = 'Port ' + action[1] + ' is not present in the switch'
- raise OpenflowconnUnexpectedResponse(error_msg)
+ raise OpenflowConnUnexpectedResponse(error_msg)
new_action['output-action']['output-node-connector'] = self.pp2ofi[action[1]]
else:
- error_msg = "Unknown item '%s' in action list".format(action[0])
+ error_msg = "Unknown item '{}' in action list".format(action[0])
self.logger.error("new_flow " + error_msg)
- raise OpenflowconnUnexpectedResponse(error_msg)
+ raise OpenflowConnUnexpectedResponse(error_msg)
actions.append(new_action)
order += 1
error_text = "Openflow response {}: {}".format(of_response.status_code, of_response.text)
if of_response.status_code != 200:
self.logger.warning("new_flow " + error_text)
- raise OpenflowconnUnexpectedResponse(error_text)
+ raise OpenflowConnUnexpectedResponse(error_text)
self.logger.debug("new_flow OK " + error_text)
return None
# raise an exception in case of contection error
error_text = type(e).__name__ + ": " + str(e)
self.logger.error("new_flow " + error_text)
- raise OpenflowconnConnectionException(error_text)
+ raise OpenflowConnConnectionException(error_text)
def clear_all_flows(self):
"""
Delete all existing rules
- :return: Raise a OpenflowconnConnectionException expection in case of failure
+ :return: Raise a OpenflowConnConnectionException expection in case of failure
"""
try:
of_response = requests.delete(self.url + "restconf/config/opendaylight-inventory:nodes/node/" + self.id +
error_text = "Openflow response {}: {}".format(of_response.status_code, of_response.text)
if of_response.status_code != 200 and of_response.status_code != 404: # HTTP_Not_Found
self.logger.warning("clear_all_flows " + error_text)
- raise OpenflowconnUnexpectedResponse(error_text)
+ raise OpenflowConnUnexpectedResponse(error_text)
self.logger.debug("clear_all_flows OK " + error_text)
return None
except requests.exceptions.RequestException as e:
error_text = type(e).__name__ + ": " + str(e)
self.logger.error("clear_all_flows " + error_text)
- raise OpenflowconnConnectionException(error_text)
+ raise OpenflowConnConnectionException(error_text)
[tox]
envlist = flake8
-toxworkdir={toxinidir}/.tox
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
# contact with: alaitz.mendiola@ehu.eus or alaitz.mendiola@gmail.com
##
-'''
+"""
ImplementS the pluging for the Open Network Operating System (ONOS) openflow
controller. It creates the class OF_conn to create dataplane connections
with static rules based on packet destination MAC address
-'''
-
-__author__="Alaitz Mendiola"
-__date__ ="$22-nov-2016$"
-
+"""
import json
import requests
import base64
import logging
-from osm_ro_plugin.openflow_conn import OpenflowConn, OpenflowConnException, OpenflowConnConnectionException, \
- OpenflowConnUnexpectedResponse, OpenflowConnAuthException, OpenflowConnNotFoundException, \
- OpenflowConnConflictException, OpenflowConnNotSupportedException, OpenflowConnNotImplemented
+from osm_ro_plugin.openflow_conn import OpenflowConn, OpenflowConnConnectionException, OpenflowConnUnexpectedResponse
+# OpenflowConnException, OpenflowConnAuthException, OpenflowConnNotFoundException, \
+# OpenflowConnConflictException, OpenflowConnNotSupportedException, OpenflowConnNotImplemented
+
+__author__ = "Alaitz Mendiola"
+__date__ = "$22-nov-2016$"
class OfConnOnos(OpenflowConn):
# internal variables
self.name = "onosof"
- self.headers = {'content-type':'application/json','accept':'application/json',}
+ self.headers = {'content-type': 'application/json', 'accept': 'application/json'}
- self.auth="None"
- self.pp2ofi={} # From Physical Port to OpenFlow Index
- self.ofi2pp={} # From OpenFlow Index to Physical Port
+ self.auth = "None"
+ self.pp2ofi = {} # From Physical Port to OpenFlow Index
+ self.ofi2pp = {} # From OpenFlow Index to Physical Port
self.dpid = str(params["of_dpid"])
self.id = 'of:'+str(self.dpid.replace(':', ''))
# TODO This may not be straightforward
if params.get("of_user"):
- of_password=params.get("of_password", "")
+ of_password = params.get("of_password", "")
self.auth = base64.b64encode(bytes(params["of_user"] + ":" + of_password, "utf-8"))
self.auth = self.auth.decode()
self.headers['authorization'] = 'Basic ' + self.auth
self.logger = logging.getLogger('openmano.sdnconn.onosof')
- #self.logger.setLevel( getattr(logging, params.get("of_debug", "ERROR")) )
+ # self.logger.setLevel( getattr(logging, params.get("of_debug", "ERROR")) )
self.logger.debug("onosof plugin initialized")
self.ip_address = None
"get_of_switches. Unexpected response, at 'devices', not found or not a list: %s",
str(type(node_list)))
raise OpenflowConnUnexpectedResponse("Unexpected response, at 'devices', not found "
- "or not a list. Wrong version?")
+ "or not a list. Wrong version?")
switch_list = []
for node in node_list:
self.logger.error("get_of_switches. Unexpected response at 'device':'id', not found: %s",
str(node))
raise OpenflowConnUnexpectedResponse("Unexpected response at 'device':'id', "
- "not found . Wrong version?")
+ "not found . Wrong version?")
node_ip_address = node.get('annotations').get('managementAddress')
if node_ip_address is None:
"obtain_port_correspondence. Unexpected response at 'ports', not found or not a list: %s",
str(node_connector_list))
raise OpenflowConnUnexpectedResponse("Unexpected response at 'ports', not found or not "
- "a list. Wrong version?")
+ "a list. Wrong version?")
for node_connector in node_connector_list:
if node_connector['port'] != "local":
"obtain_port_correspondence. Unexpected response at 'managementAddress', not found: %s",
str(self.id))
raise OpenflowConnUnexpectedResponse("Unexpected response at 'managementAddress', "
- "not found. Wrong version?")
+ "not found. Wrong version?")
self.ip_address = node_ip_address
# print self.name, ": obtain_port_correspondence ports:", self.pp2ofi
if type(info) != dict:
self.logger.error("get_of_rules. Unexpected response, not a dict: %s", str(info))
raise OpenflowConnUnexpectedResponse("Unexpected openflow response, not a dict. "
- "Wrong version?")
+ "Wrong version?")
flow_list = info.get('flows')
"get_of_rules. Unexpected response at 'flows', not a list: %s",
str(type(flow_list)))
raise OpenflowConnUnexpectedResponse("Unexpected response at 'flows', not a list. "
- "Wrong version?")
+ "Wrong version?")
rules = [] # Response list
for flow in flow_list:
- if not ('id' in flow and 'selector' in flow and 'treatment' in flow and \
- 'instructions' in flow['treatment'] and 'criteria' in \
- flow['selector']):
+ if not ('id' in flow and 'selector' in flow and 'treatment' in flow and
+ 'instructions' in flow['treatment'] and 'criteria' in
+ flow['selector']):
raise OpenflowConnUnexpectedResponse("unexpected openflow response, one or more "
- "elements are missing. Wrong version?")
+ "elements are missing. Wrong version?")
rule = dict()
rule['switch'] = self.dpid
if criteria['type'] == 'IN_PORT':
in_port = str(criteria['port'])
if in_port != "CONTROLLER":
- if not in_port in self.ofi2pp:
+ if in_port not in self.ofi2pp:
raise OpenflowConnUnexpectedResponse("Error: Ingress port {} is not "
- "in switch port list".format(in_port))
+ "in switch port list".format(in_port))
if translate_of_ports:
in_port = self.ofi2pp[in_port]
rule['ingress_port'] = in_port
if instruction['type'] == "OUTPUT":
out_port = str(instruction['port'])
if out_port != "CONTROLLER":
- if not out_port in self.ofi2pp:
+ if out_port not in self.ofi2pp:
raise OpenflowConnUnexpectedResponse("Error: Output port {} is not in "
- "switch port list".format(out_port))
+ "switch port list".format(out_port))
if translate_of_ports:
out_port = self.ofi2pp[out_port]
- actions.append( ('out', out_port) )
+ actions.append(('out', out_port))
if instruction['type'] == "L2MODIFICATION" and instruction['subtype'] == "VLAN_POP":
- actions.append( ('vlan', 'None') )
+ actions.append(('vlan', 'None'))
if instruction['type'] == "L2MODIFICATION" and instruction['subtype'] == "VLAN_ID":
- actions.append( ('vlan', instruction['vlanId']) )
+ actions.append(('vlan', instruction['vlanId']))
rule['actions'] = actions
rules.append(rule)
# Build the dictionary with the flow rule information for ONOS
flow = dict()
- #flow['id'] = data['name']
+ # flow['id'] = data['name']
flow['tableId'] = 0
flow['priority'] = data.get('priority')
flow['timeout'] = 0
flow['isPermanent'] = "true"
- flow['appId'] = 10 # FIXME We should create an appId for OSM
+ flow['appId'] = 10 # FIXME We should create an appId for OSM
flow['selector'] = dict()
flow['selector']['criteria'] = list()
for action in data['actions']:
new_action = dict()
- if action[0] == "vlan":
+ if action[0] == "vlan":
new_action['type'] = "L2MODIFICATION"
- if action[1] == None:
+ if action[1] is None:
new_action['subtype'] = "VLAN_POP"
else:
new_action['subtype'] = "VLAN_ID"
elif action[0] == 'out':
new_action['type'] = "OUTPUT"
if not action[1] in self.pp2ofi:
- error_msj = 'Port '+ action[1] + ' is not present in the switch'
+ error_msj = 'Port ' + action[1] + ' is not present in the switch'
raise OpenflowConnUnexpectedResponse(error_msj)
new_action['port'] = self.pp2ofi[action[1]]
else:
self.headers['content-type'] = 'application/json'
path = self.url + "flows/" + self.id
self.logger.debug("new_flow post: {}".format(flow))
- of_response = requests.post(path, headers=self.headers, data=json.dumps(flow) )
+ of_response = requests.post(path, headers=self.headers, data=json.dumps(flow))
error_text = "Openflow response {}: {}".format(of_response.status_code, of_response.text)
if of_response.status_code != 201:
[tox]
envlist = flake8
-toxworkdir={toxinidir}/.tox
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
except Exception as e:
if onos_config_req:
status_code = onos_config_req.status_code
- self.logger.exception('Error checking credentials')
- raise SdnConnectorError('Error checking credentials', http_code=status_code)
+ self.logger.exception('Error checking credentials: {}'.format(e))
+ raise SdnConnectorError('Error checking credentials: {}'.format(e), http_code=status_code)
def get_connectivity_service_status(self, service_uuid, conn_info=None):
try:
if port_name in onos_config['ports'] and 'interfaces' in onos_config['ports'][port_name]:
for interface in onos_config['ports'][port_name]['interfaces']:
if interface['name'] == port['service_endpoint_id']:
- #self.logger.debug("interface with same name and port exits")
+ # self.logger.debug("interface with same name and port exits")
# interface already exists TODO ¿check vlan? ¿delete and recreate?
# by the moment use and do not touch
- #onos_config['ports'][port_name]['interfaces'].remove(interface)
+ # onos_config['ports'][port_name]['interfaces'].remove(interface)
break
else:
- #self.logger.debug("port with same name exits but not interface")
+ # self.logger.debug("port with same name exits but not interface")
onos_config['ports'][port_name]['interfaces'].append(interface_config)
created_item = (port_name, port['service_endpoint_id'])
else:
- #self.logger.debug("create port and interface")
+ # self.logger.debug("create port and interface")
onos_config['ports'][port_name] = {
'interfaces': [interface_config]
}
wim = {'wim_url': wim_url}
wim_account = {'user': user, 'password': password}
onos_vpls = OnosVpls(wim=wim, wim_account=wim_account, logger=logger)
- #conn_service = onos_vpls.get_connectivity_service_status("4e1f4c8a-a874-425d-a9b5-955cb77178f8")
- #print(conn_service)
+ # conn_service = onos_vpls.get_connectivity_service_status("4e1f4c8a-a874-425d-a9b5-955cb77178f8")
+ # print(conn_service)
service_type = 'ELAN'
conn_point_0 = {
"service_endpoint_id": "switch1:ifz1",
}
}
connection_points = [conn_point_0, conn_point_1]
- #service_uuid, conn_info = onos_vpls.create_connectivity_service(service_type, connection_points)
- #print(service_uuid)
- #print(conn_info)
+ # service_uuid, conn_info = onos_vpls.create_connectivity_service(service_type, connection_points)
+ # print(service_uuid)
+ # print(conn_info)
- #conn_info = None
+ # conn_info = None
conn_info = {"interfaces": ['switch1:ifz1', 'switch3:ifz1']}
- #onos_vpls.delete_connectivity_service("70248a41-11cb-44f3-9039-c41387394a30", conn_info)
+ # onos_vpls.delete_connectivity_service("70248a41-11cb-44f3-9039-c41387394a30", conn_info)
conn_point_0 = {
"service_endpoint_id": "switch1:ifz1",
}
}
connection_points_2 = [conn_point_0, conn_point_3]
- #conn_info = onos_vpls.edit_connectivity_service("c65d88be-73aa-4933-927d-57ec6bee6b41", conn_info, connection_points_2)
- #print(conn_info)
+ # conn_info = onos_vpls.edit_connectivity_service("c65d88be-73aa-4933-927d-57ec6bee6b41",
+ # conn_info, connection_points_2)
+ # print(conn_info)
service_status = onos_vpls.get_connectivity_service_status("c65d88be-73aa-4933-927d-57ec6bee6b41", conn_info)
print("service status")
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
aws_secret_access_key=self.a_creds['aws_secret_access_key'])
self.conn_vpc = boto.vpc.connect_to_region(self.region, aws_access_key_id=self.a_creds['aws_access_key_id'],
aws_secret_access_key=self.a_creds['aws_secret_access_key'])
- # client = boto3.client("sts", aws_access_key_id=self.a_creds['aws_access_key_id'], aws_secret_access_key=self.a_creds['aws_secret_access_key'])
+ # client = boto3.client("sts", aws_access_key_id=self.a_creds['aws_access_key_id'],
+ # aws_secret_access_key=self.a_creds['aws_secret_access_key'])
# self.account_id = client.get_caller_identity()["Account"]
except Exception as e:
self.format_vimconn_exception(e)
subnet = None
vpc_id = self.vpc_id
if self.vpc_data.get(vpc_id, None):
- cidr_block = list(set(self.vpc_data[vpc_id]['subnets']) - set(self.get_network_details({'tenant_id': vpc_id}, detail='cidr_block')))[0]
+ cidr_block = list(set(self.vpc_data[vpc_id]['subnets']) -
+ set(self.get_network_details({'tenant_id': vpc_id}, detail='cidr_block')))[0]
else:
vpc = self.get_tenant_list({'id': vpc_id})[0]
subnet_list = self.subnet_sizes(len(self.get_availability_zones_list()), vpc['cidr_block'])
- cidr_block = list(set(subnet_list) - set(self.get_network_details({'tenant_id': vpc['id']}, detail='cidr_block')))[0]
+ cidr_block = list(set(subnet_list) - set(self.get_network_details({'tenant_id': vpc['id']},
+ detail='cidr_block')))[0]
subnet = self.conn_vpc.create_subnet(vpc_id, cidr_block)
return subnet.id, created_items
except Exception as e:
id: string => returns networks with this VIM id, this imply returns one network at most
shared: boolean >= returns only networks that are (or are not) shared
tenant_id: sting => returns only networks that belong to this tenant/project
- ,#(not used yet) admin_state_up: boolean => returns only networks that are (or are not) in admin state active
+ ,#(not used yet) admin_state_up: boolean => returns only networks that are (or are not) in admin
+ state active
#(not used yet) status: 'ACTIVE','ERROR',... => filter networks that are on this status
Returns the network list of dictionaries. each dictionary contains:
'id': (mandatory) VIM network id
else:
subnet_dict['status'] = 'ERROR'
subnet_dict['error_msg'] = ''
- except Exception as e:
+ except Exception:
subnet_dict['status'] = 'DELETED'
subnet_dict['error_msg'] = 'Network not found'
finally:
try:
subnet_dict['vim_info'] = yaml.safe_dump(subnet, default_flow_style=True, width=256)
- except yaml.YAMLError as e:
+ except yaml.YAMLError:
subnet_dict['vim_info'] = str(subnet)
dict_entry[net_id] = subnet_dict
return dict_entry
flavor = None
for key, values in self.flavor_info.items():
if (values["ram"], values["cpus"], values["disk"]) == (
- flavor_dict["ram"], flavor_dict["vcpus"], flavor_dict["disk"]):
+ flavor_dict["ram"], flavor_dict["vcpus"], flavor_dict["disk"]):
flavor = (key, values)
break
elif (values["ram"], values["cpus"], values["disk"]) >= (
- flavor_dict["ram"], flavor_dict["vcpus"], flavor_dict["disk"]):
+ flavor_dict["ram"], flavor_dict["vcpus"], flavor_dict["disk"]):
if not flavor:
flavor = (key, values)
else:
if (flavor[1]["ram"], flavor[1]["cpus"], flavor[1]["disk"]) >= (
- values["ram"], values["cpus"], values["disk"]):
+ values["ram"], values["cpus"], values["disk"]):
flavor = (key, values)
if flavor:
return flavor[0]
def new_image(self, image_dict):
""" Adds a tenant image to VIM
Params: image_dict
- name (string) - The name of the AMI. Valid only for EBS-based images.
- description (string) - The description of the AMI.
- image_location (string) - Full path to your AMI manifest in Amazon S3 storage. Only used for S3-based AMI’s.
- architecture (string) - The architecture of the AMI. Valid choices are: * i386 * x86_64
- kernel_id (string) - The ID of the kernel with which to launch the instances
- root_device_name (string) - The root device name (e.g. /dev/sdh)
- block_device_map (boto.ec2.blockdevicemapping.BlockDeviceMapping) - A BlockDeviceMapping data structure describing the EBS volumes associated with the Image.
- virtualization_type (string) - The virutalization_type of the image. Valid choices are: * paravirtual * hvm
- sriov_net_support (string) - Advanced networking support. Valid choices are: * simple
- snapshot_id (string) - A snapshot ID for the snapshot to be used as root device for the image. Mutually exclusive with block_device_map, requires root_device_name
- delete_root_volume_on_termination (bool) - Whether to delete the root volume of the image after instance termination. Only applies when creating image from snapshot_id. Defaults to False. Note that leaving volumes behind after instance termination is not free
+ name (string) - The name of the AMI. Valid only for EBS-based images.
+ description (string) - The description of the AMI.
+ image_location (string) - Full path to your AMI manifest in Amazon S3 storage. Only used for S3-based AMI’s.
+ architecture (string) - The architecture of the AMI. Valid choices are: * i386 * x86_64
+ kernel_id (string) - The ID of the kernel with which to launch the instances
+ root_device_name (string) - The root device name (e.g. /dev/sdh)
+ block_device_map (boto.ec2.blockdevicemapping.BlockDeviceMapping) - A BlockDeviceMapping data structure
+ describing the EBS volumes associated with the Image.
+ virtualization_type (string) - The virutalization_type of the image. Valid choices are: * paravirtual * hvm
+ sriov_net_support (string) - Advanced networking support. Valid choices are: * simple
+ snapshot_id (string) - A snapshot ID for the snapshot to be used as root device for the image. Mutually
+ exclusive with block_device_map, requires root_device_name
+ delete_root_volume_on_termination (bool) - Whether to delete the root volume of the image after instance
+ termination. Only applies when creating image from snapshot_id. Defaults to False. Note that leaving
+ volumes behind after instance termination is not free
Returns: image_id - image ID of the newly created image
"""
net_list
name
net_id - subnet_id from AWS
- vpci - (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM capabilities
+ vpci - (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM
+ capabilities
model: (optional and only have sense for type==virtual) interface model: virtio, e1000, ...
mac_address: (optional) mac address to assign to this interface
type: (mandatory) can be one of:
virtual, in this case always connected to a network of type 'net_type=bridge'
- 'PCI-PASSTHROUGH' or 'PF' (passthrough): depending on VIM capabilities it can be connected to a data/ptp network ot it
+ 'PCI-PASSTHROUGH' or 'PF' (passthrough): depending on VIM capabilities it can be connected to a
+ data/ptp network ot it
can created unconnected
'SR-IOV' or 'VF' (SRIOV with VLAN tag): same as PF for network connectivity.
- VFnotShared - (SRIOV without VLAN tag) same as PF for network connectivity. VF where no other VFs
- are allocated on the same physical NIC
+ VFnotShared - (SRIOV without VLAN tag) same as PF for network connectivity. VF where no other
+ VFs are allocated on the same physical NIC
bw': (optional) only for PF/VF/VFnotShared. Minimal Bandwidth required for the interface in GBPS
- port_security': (optional) If False it must avoid any traffic filtering at this interface. If missing or True, it must apply the default VIM behaviour
- vim_id': must be filled/added by this method with the VIM identifier generated by the VIM for this interface. 'net_list' is modified
+ port_security': (optional) If False it must avoid any traffic filtering at this interface.
+ If missing or True, it must apply the default VIM behaviour
+ vim_id': must be filled/added by this method with the VIM identifier generated by the VIM for this
+ interface. 'net_list' is modified
elastic_ip - True/False to define if an elastic_ip is required
cloud_config': (optional) dictionary with:
key-pairs': (optional) list of strings with the public key to be inserted to the default user
network_interface_id=boto.ec2.networkinterface.NetworkInterfaceCollection(net_intr),
instance_id=instance.id, device_index=0)
break
- except:
+ except Exception:
time.sleep(10)
net_list[index]['vim_id'] = reservation.instances[0].interfaces[index].id
interface_dict['vim_interface_id'] = interface.id
interface_dict['vim_net_id'] = interface.subnet_id
interface_dict['mac_address'] = interface.mac_address
- if hasattr(interface, 'publicIp') and interface.publicIp != None:
+ if hasattr(interface, 'publicIp') and interface.publicIp is not None:
interface_dict['ip_address'] = interface.publicIp + ";" + interface.private_ip_address
else:
interface_dict['ip_address'] = interface.private_ip_address
finally:
try:
instance_dict['vim_info'] = yaml.safe_dump(instance, default_flow_style=True, width=256)
- except yaml.YAMLError as e:
+ except yaml.YAMLError:
# self.logger.error("Exception getting vm status: %s", str(e), exc_info=True)
instance_dict['vim_info'] = str(instance)
instances[instance.id] = instance_dict
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
try:
location = self.conn.resource_groups.get(resource_group_name).location
return location
- except Exception as e:
+ except Exception:
raise vimconn.VimConnNotFoundException("Location '{}' not found".format(resource_group_name))
def _get_resource_group_name_from_resource_id(self, resource_id):
try:
rg = str(resource_id.split('/')[4])
return rg
- except Exception as e:
+ except Exception:
raise vimconn.VimConnException("Unable to get resource group from invalid resource_id format '{}'".
format(resource_id))
try:
net_name = str(resource_id.split('/')[8])
return net_name
- except Exception as e:
+ except Exception:
raise vimconn.VimConnException("Unable to get azure net_name from invalid resource_id format '{}'".
format(resource_id))
if mac_address:
net_ifz['mac_address'] = mac_address
- async_nic_creation = self.conn_vnet.network_interfaces.create_or_update(self.resource_group, nic_name, net_ifz)
+ async_nic_creation = self.conn_vnet.network_interfaces.create_or_update(self.resource_group, nic_name,
+ net_ifz)
nic_data = async_nic_creation.result()
created_items[nic_data.id] = True
self.logger.debug('created nic name %s', nic_name)
# image_id are several fields of the image_id
image_reference = self._get_image_reference(image_id)
-
-
try:
virtual_machine = None
created_items = {}
nic_name = vm_name + '-nic-' + str(idx)
vm_nic, nic_items = self._create_nic(net, nic_name, net.get('ip_address'), created_items)
vm_nics.append({'id': str(vm_nic.id)})
- #net['vim_id'] = vm_nic.id
+ # net['vim_id'] = vm_nic.id
# cloud-init configuration
# cloud config
'disk_size_gb': disk.get('size')
})
self.logger.debug("attach disk name: %s", disk_name)
- async_disk_attach = self.conn_compute.virtual_machines.create_or_update(
+ self.conn_compute.virtual_machines.create_or_update(
self.resource_group,
virtual_machine.name,
virtual_machine
'sku': sku,
'version': version
}
- except Exception as e:
+ except Exception:
raise vimconn.VimConnException(
"Unable to get image_reference from invalid image_id format: '{}'".format(image_id))
if not v: # skip already deleted
continue
- #self.logger.debug("Must delete item id: %s", item_id)
+ # self.logger.debug("Must delete item id: %s", item_id)
# Obtain type, supported nic, disk or public ip
parsed_id = azure_tools.parse_resource_id(item_id)
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
for the selected hypervisor
"""
-__author__="Gabriele Baldoni"
-__date__ ="$2-june-2020 10:35:12$"
import uuid
import socket
import struct
from osm_ro_plugin import vimconn
-import json
+# import json
from functools import partial
from fog05 import FIMAPI
from fog05 import fimapi
from fog05_sdk.interfaces.FDU import FDU
+__author__ = "Gabriele Baldoni"
+__date__ = "$2-june-2020 10:35:12$"
+
class vimconnector(vimconn.VimConnector):
def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None,
Returns the network identifier on success or raises and exception on failure
"""
self.logger.debug('new_network: {}'.format(locals()))
- if net_type in ['data','ptp']:
+ if net_type in ['data', 'ptp']:
raise vimconn.VimConnNotImplemented('{} type of network not supported'.format(net_type))
net_uuid = '{}'.format(uuid.uuid4())
desc = {
- 'uuid':net_uuid,
- 'name':net_name,
- 'net_type':'ELAN',
- 'is_mgmt':False
- }
+ 'uuid': net_uuid,
+ 'name': net_name,
+ 'net_type': 'ELAN',
+ 'is_mgmt': False
+ }
if ip_profile is not None:
ip = {}
if ip_profile.get('ip_version') == 'IPv4':
ip_info = {}
ip_range = self.__get_ip_range(ip_profile.get('dhcp_start_address'), ip_profile.get('dhcp_count'))
- dhcp_range = '{},{}'.format(ip_range[0],ip_range[1])
- ip.update({'subnet':ip_profile.get('subnet_address')})
- ip.update({'dns':ip_profile.get('dns', None)})
- ip.update({'dhcp_enable':ip_profile.get('dhcp_enabled', False)})
- ip.update({'dhcp_range': dhcp_range})
- ip.update({'gateway':ip_profile.get('gateway_address', None)})
- desc.update({'ip_configuration':ip_info})
+ dhcp_range = '{},{}'.format(ip_range[0], ip_range[1])
+ ip['subnet'] = ip_profile.get('subnet_address')
+ ip['dns'] = ip_profile.get('dns', None)
+ ip['dhcp_enable'] = ip_profile.get('dhcp_enabled', False)
+ ip['dhcp_range'] = dhcp_range
+ ip['gateway'] = ip_profile.get('gateway_address', None)
+ desc['ip_configuration'] = ip_info
else:
raise vimconn.VimConnNotImplemented('IPV6 network is not implemented at VIM')
- desc.update({'ip_configuration':ip})
+ desc['ip_configuration'] = ip
self.logger.debug('VIM new_network args: {} - Generated Eclipse fog05 Descriptor {}'.format(locals(), desc))
try:
self.fos_api.network.add_network(desc)
raise vimconn.VimConnConflictException("Network already exists at VIM. Error {}".format(free))
except Exception as e:
raise vimconn.VimConnException("Unable to create network {}. Error {}".format(net_name, e))
- # No way from the current rest service to get the actual error, most likely it will be an already existing error
- return net_uuid,{}
+ # No way from the current rest service to get the actual error, most likely it will be an already
+ # existing error
+ return net_uuid, {}
def get_network_list(self, filter_dict={}):
"""Obtain tenant networks of VIM
- Params:
- 'filter_dict' (optional) contains entries to return only networks that matches ALL entries:
- name: string => returns only networks with this name
- id: string => returns networks with this VIM id, this imply returns one network at most
- shared: boolean >= returns only networks that are (or are not) shared
- tenant_id: sting => returns only networks that belong to this tenant/project
- ,#(not used yet) admin_state_up: boolean => returns only networks that are (or are not) in admin state active
- #(not used yet) status: 'ACTIVE','ERROR',... => filter networks that are on this status
+ :param filter_dict: (optional) contains entries to return only networks that matches ALL entries:
+ name: string => returns only networks with this name
+ id: string => returns networks with this VIM id, this imply returns one network at most
+ shared: boolean >= returns only networks that are (or are not) shared
+ tenant_id: sting => returns only networks that belong to this tenant/project
+ (not used yet) admin_state_up: boolean => returns only networks that are (or are not) in admin state active
+ (not used yet) status: 'ACTIVE','ERROR',... => filter networks that are on this status
Returns the network list of dictionaries. each dictionary contains:
'id': (mandatory) VIM network id
'name': (mandatory) VIM network name
try:
nets = self.fos_api.network.list()
except Exception as e:
- raise vimconn.VimConnConnectionException("Cannot get network list from VIM, connection error. Error {}".format(e))
+ raise vimconn.VimConnConnectionException(
+ "Cannot get network list from VIM, connection error. Error {}".format(e))
filters = [
partial(self.__name_filter, filter_name=filter_dict.get('name')),
- partial(self.__id_filter,filter_id=filter_dict.get('id'))
+ partial(self.__id_filter, filter_id=filter_dict.get('id'))
]
r1 = []
for n in r1:
osm_net = {
- 'id':n.get('uuid'),
- 'name':n.get('name'),
- 'status':'ACTIVE'
+ 'id': n.get('uuid'),
+ 'name': n.get('name'),
+ 'status': 'ACTIVE'
}
res.append(osm_net)
return res
Raises an exception upon error or when network is not found
"""
self.logger.debug('get_network: {}'.format(net_id))
- res = self.get_network_list(filter_dict={'id':net_id})
+ res = self.get_network_list(filter_dict={'id': net_id})
if len(res) == 0:
raise vimconn.VimConnNotFoundException("Network {} not found at VIM".format(net_id))
return res[0]
try:
self.fos_api.network.remove_network(net_id)
except fimapi.FIMNotFoundException as fnfe:
- raise vimconn.VimConnNotFoundException("Network {} not found at VIM (already deleted?). Error {}".format(net_id, fnfe))
+ raise vimconn.VimConnNotFoundException(
+ "Network {} not found at VIM (already deleted?). Error {}".format(net_id, fnfe))
except Exception as e:
raise vimconn.VimConnException("Cannot delete network {} from VIM. Error {}".format(net_id, e))
return net_id
for n in net_list:
try:
osm_n = self.get_network(n)
- r.update({
- osm_n.get('id'):{'status':osm_n.get('status')}
- })
+ r[osm_n.get('id')] = {'status': osm_n.get('status')}
except vimconn.VimConnNotFoundException:
- r.update({
- n:{'status':'VIM_ERROR'}
- })
+ r[n] = {'status': 'VIM_ERROR'}
return r
def get_flavor(self, flavor_id):
raise vimconn.VimConnConnectionException("VIM not reachable. Error {}".format(e))
if r is None:
raise vimconn.VimConnNotFoundException("Flavor not found at VIM")
- return {'id':r.get('uuid'), 'name':r.get('name'), 'fos':r}
+ return {'id': r.get('uuid'), 'name': r.get('name'), 'fos': r}
def get_flavor_id_from_data(self, flavor_dict):
"""Obtain flavor id that match the flavor description
flvs = self.fos_api.flavor.list()
except Exception as e:
raise vimconn.VimConnConnectionException("VIM not reachable. Error {}".format(e))
- r = [x.get('uuid') for x in flvs if (x.get('cpu_min_count') == flavor_dict.get('vcpus') and x.get('ram_size_mb') == flavor_dict.get('ram') and x.get('storage_size_gb') == flavor_dict.get('disk'))]
+ r = [x.get('uuid') for x in flvs if (x.get('cpu_min_count') == flavor_dict.get('vcpus') and
+ x.get('ram_size_mb') == flavor_dict.get('ram') and
+ x.get('storage_size_gb') == flavor_dict.get('disk'))]
if len(r) == 0:
- raise vimconn.VimConnNotFoundException ( "No flavor found" )
+ raise vimconn.VimConnNotFoundException("No flavor found")
return r[0]
def new_flavor(self, flavor_data):
vpcus: cpus (cloud type)
extended: EPA parameters
- numas: #items requested in same NUMA
- memory: number of 1G huge pages memory
- paired-threads|cores|threads: number of paired hyperthreads, complete cores OR individual threads
- interfaces: # passthrough(PT) or SRIOV interfaces attached to this numa
+ memory: number of 1G huge pages memory
+ paired-threads|cores|threads: number of paired hyperthreads, complete cores OR individual threads
+ interfaces: # passthrough(PT) or SRIOV interfaces attached to this numa
- name: interface name
dedicated: yes|no|yes:sriov; for PT, SRIOV or only one SRIOV for the physical NIC
bandwidth: X Gbps; requested guarantee bandwidth
self.logger.debug('VIM new_flavor with args: {}'.format(locals()))
flv_id = '{}'.format(uuid.uuid4())
desc = {
- 'uuid':flv_id,
- 'name':flavor_data.get('name'),
+ 'uuid': flv_id,
+ 'name': flavor_data.get('name'),
'cpu_arch': self.arch,
'cpu_min_count': flavor_data.get('vcpus'),
'cpu_min_freq': 0,
- 'ram_size_mb':float(flavor_data.get('ram')),
- 'storage_size_gb':float(flavor_data.get('disk'))
+ 'ram_size_mb': float(flavor_data.get('ram')),
+ 'storage_size_gb': float(flavor_data.get('disk'))
}
try:
self.fos_api.flavor.add(desc)
try:
self.fos_api.flavor.remove(flavor_id)
except fimapi.FIMNotFoundException as fnfe:
- raise vimconn.VimConnNotFoundException("Flavor {} not found at VIM (already deleted?). Error {}".format(flavor_id, fnfe))
+ raise vimconn.VimConnNotFoundException(
+ "Flavor {} not found at VIM (already deleted?). Error {}".format(flavor_id, fnfe))
except Exception as e:
raise vimconn.VimConnConnectionException("VIM not reachable. Error {}".format(e))
return flavor_id
self.logger.debug('VIM new_image with args: {}'.format(locals()))
img_id = '{}'.format(uuid.uuid4())
desc = {
- 'name':image_dict.get('name'),
- 'uuid':img_id,
- 'uri':image_dict.get('location'),
- 'format':image_dict.get('disk_format')
+ 'name': image_dict.get('name'),
+ 'uuid': img_id,
+ 'uri': image_dict.get('location'),
+ 'format': image_dict.get('disk_format')
}
try:
self.fos_api.image.add(desc)
imgs = self.fos_api.image.list()
except Exception as e:
raise vimconn.VimConnConnectionException("VIM not reachable. Error {}".format(e))
- res = [x.get('uuid') for x in imgs if x.get('uri')==path]
+ res = [x.get('uuid') for x in imgs if x.get('uri') == path]
if len(res) == 0:
raise vimconn.VimConnNotFoundException("Image with this path was not found")
return res[0]
filters = [
partial(self.__name_filter, filter_name=filter_dict.get('name')),
- partial(self.__id_filter,filter_id=filter_dict.get('id')),
- partial(self.__checksum_filter,filter_checksum=filter_dict.get('checksum'))
+ partial(self.__id_filter, filter_id=filter_dict.get('id')),
+ partial(self.__checksum_filter, filter_checksum=filter_dict.get('checksum'))
]
r1 = []
for i in r1:
img_info = {
- 'name':i.get('name'),
- 'id':i.get('uuid'),
- 'checksum':i.get('checksum'),
- 'location':i.get('uri'),
- 'fos':i
+ 'name': i.get('name'),
+ 'id': i.get('uuid'),
+ 'checksum': i.get('checksum'),
+ 'location': i.get('uri'),
+ 'fos': i
}
r.append(img_info)
return r
- #raise VimConnNotImplemented( "Should have implemented this" )
+ # raise VimConnNotImplemented( "Should have implemented this" )
def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None, disk_list=None,
- availability_zone_index=None, availability_zone_list=None):
+ availability_zone_index=None, availability_zone_list=None):
"""Adds a VM instance to VIM
- Params:
- 'start': (boolean) indicates if VM must start or created in pause mode.
- 'image_id','flavor_id': image and flavor VIM id to use for the VM
- 'net_list': list of interfaces, each one is a dictionary with:
- 'name': (optional) name for the interface.
- 'net_id': VIM network id where this interface must be connect to. Mandatory for type==virtual
- 'vpci': (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM capabilities
- 'model': (optional and only have sense for type==virtual) interface model: virtio, e1000, ...
- 'mac_address': (optional) mac address to assign to this interface
- 'ip_address': (optional) IP address to assign to this interface
- #TODO: CHECK if an optional 'vlan' parameter is needed for VIMs when type if VF and net_id is not provided,
- the VLAN tag to be used. In case net_id is provided, the internal network vlan is used for tagging VF
- 'type': (mandatory) can be one of:
- 'virtual', in this case always connected to a network of type 'net_type=bridge'
- 'PCI-PASSTHROUGH' or 'PF' (passthrough): depending on VIM capabilities it can be connected to a data/ptp network ot it
- can created unconnected
- 'SR-IOV' or 'VF' (SRIOV with VLAN tag): same as PF for network connectivity.
- 'VFnotShared'(SRIOV without VLAN tag) same as PF for network connectivity. VF where no other VFs
- are allocated on the same physical NIC
- 'bw': (optional) only for PF/VF/VFnotShared. Minimal Bandwidth required for the interface in GBPS
- 'port_security': (optional) If False it must avoid any traffic filtering at this interface. If missing
- or True, it must apply the default VIM behaviour
- After execution the method will add the key:
- 'vim_id': must be filled/added by this method with the VIM identifier generated by the VIM for this
- interface. 'net_list' is modified
- 'cloud_config': (optional) dictionary with:
- 'key-pairs': (optional) list of strings with the public key to be inserted to the default user
- 'users': (optional) list of users to be inserted, each item is a dict with:
- 'name': (mandatory) user name,
- 'key-pairs': (optional) list of strings with the public key to be inserted to the user
- 'user-data': (optional) can be a string with the text script to be passed directly to cloud-init,
- or a list of strings, each one contains a script to be passed, usually with a MIMEmultipart file
- 'config-files': (optional). List of files to be transferred. Each item is a dict with:
- 'dest': (mandatory) string with the destination absolute path
- 'encoding': (optional, by default text). Can be one of:
- 'b64', 'base64', 'gz', 'gz+b64', 'gz+base64', 'gzip+b64', 'gzip+base64'
- 'content' (mandatory): string with the content of the file
- 'permissions': (optional) string with file permissions, typically octal notation '0644'
- 'owner': (optional) file owner, string with the format 'owner:group'
- 'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk)
- 'disk_list': (optional) list with additional disks to the VM. Each item is a dict with:
- 'image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
- 'size': (mandatory) string with the size of the disk in GB
- availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV required
- availability_zone_list: list of availability zones given by user in the VNFD descriptor. Ignore if
- availability_zone_index is None
+ :param start: (boolean) indicates if VM must start or created in pause mode.
+ :param image_id: :param flavor_id: image and flavor VIM id to use for the VM
+ :param net_list: list of interfaces, each one is a dictionary with:
+ 'name': (optional) name for the interface.
+ 'net_id': VIM network id where this interface must be connect to. Mandatory for type==virtual
+ 'vpci': (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM capabilities
+ 'model': (optional and only have sense for type==virtual) interface model: virtio, e1000, ...
+ 'mac_address': (optional) mac address to assign to this interface
+ 'ip_address': (optional) IP address to assign to this interface
+ #TODO: CHECK if an optional 'vlan' parameter is needed for VIMs when type if VF and net_id is not provided,
+ the VLAN tag to be used. In case net_id is provided, the internal network vlan is used for tagging VF
+ 'type': (mandatory) can be one of:
+ 'virtual', in this case always connected to a network of type 'net_type=bridge'
+ 'PCI-PASSTHROUGH' or 'PF' (passthrough): depending on VIM capabilities it can be connected to a
+ data/ptp network ot it can created unconnected
+ 'SR-IOV' or 'VF' (SRIOV with VLAN tag): same as PF for network connectivity.
+ 'VFnotShared'(SRIOV without VLAN tag) same as PF for network connectivity. VF where no other VFs
+ are allocated on the same physical NIC
+ 'bw': (optional) only for PF/VF/VFnotShared. Minimal Bandwidth required for the interface in GBPS
+ 'port_security': (optional) If False it must avoid any traffic filtering at this interface. If missing
+ or True, it must apply the default VIM behaviour
+ After execution the method will add the key:
+ 'vim_id': must be filled/added by this method with the VIM identifier generated by the VIM for this
+ interface. 'net_list' is modified
+ :param cloud_config: (optional) dictionary with:
+ 'key-pairs': (optional) list of strings with the public key to be inserted to the default user
+ 'users': (optional) list of users to be inserted, each item is a dict with:
+ 'name': (mandatory) user name,
+ 'key-pairs': (optional) list of strings with the public key to be inserted to the user
+ 'user-data': (optional) can be a string with the text script to be passed directly to cloud-init,
+ or a list of strings, each one contains a script to be passed, usually with a MIMEmultipart file
+ 'config-files': (optional). List of files to be transferred. Each item is a dict with:
+ 'dest': (mandatory) string with the destination absolute path
+ 'encoding': (optional, by default text). Can be one of:
+ 'b64', 'base64', 'gz', 'gz+b64', 'gz+base64', 'gzip+b64', 'gzip+base64'
+ 'content' (mandatory): string with the content of the file
+ 'permissions': (optional) string with file permissions, typically octal notation '0644'
+ 'owner': (optional) file owner, string with the format 'owner:group'
+ 'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk)
+ :param disk_list: (optional) list with additional disks to the VM. Each item is a dict with:
+ 'image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
+ 'size': (mandatory) string with the size of the disk in GB
+ :param availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV required
+ :param availability_zone_list: list of availability zones given by user in the VNFD descriptor. Ignore if
+ availability_zone_index is None
Returns a tuple with the instance identifier and created_items or raises an exception on error
created_items can be None or a dictionary where this method can include key-values that will be passed to
the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc.
raise vimconn.VimConnNotFoundException("Image {} not found at VIM".format(image_id))
created_items = {
- 'fdu_id':'',
- 'node_id':'',
- 'connection_points':[]
- }
+ 'fdu_id': '',
+ 'node_id': '',
+ 'connection_points': []
+ }
fdu_desc = {
- 'name':name,
- 'id':fdu_uuid,
- 'uuid':fdu_uuid,
- 'computation_requirements':flv,
- 'image':img,
- 'hypervisor':self.hv,
- 'migration_kind':'LIVE',
- 'interfaces':[],
- 'io_ports':[],
- 'connection_points':[],
- 'depends_on':[],
- 'storage':[]
+ 'name': name,
+ 'id': fdu_uuid,
+ 'uuid': fdu_uuid,
+ 'computation_requirements': flv,
+ 'image': img,
+ 'hypervisor': self.hv,
+ 'migration_kind': 'LIVE',
+ 'interfaces': [],
+ 'io_ports': [],
+ 'connection_points': [],
+ 'depends_on': [],
+ 'storage': []
}
nets = []
intf_id = 0
for n in net_list:
cp_id = '{}'.format(uuid.uuid4())
- n.update({'vim_id':cp_id})
+ n['vim_id'] = cp_id
pair_id = n.get('net_id')
cp_d = {
- 'id':cp_id,
+ 'id': cp_id,
'name': cp_id,
'vld_ref': pair_id
}
intf_d = {
- 'name':n.get('name','eth{}'.format(intf_id)),
- 'is_mgmt':False,
- 'if_type':'INTERNAL',
- 'virtual_interface':{
- 'intf_type':n.get('model','VIRTIO'),
- 'vpci':n.get('vpci','0:0:0'),
- 'bandwidth':int(n.get('bw', 100))
+ 'name': n.get('name', 'eth{}'.format(intf_id)),
+ 'is_mgmt': False,
+ 'if_type': 'INTERNAL',
+ 'virtual_interface': {
+ 'intf_type': n.get('model', 'VIRTIO'),
+ 'vpci': n.get('vpci', '0:0:0'),
+ 'bandwidth': int(n.get('bw', 100))
},
'cp_id': cp_id
}
intf_id = intf_id + 1
if cloud_config is not None:
- configuration = {
- 'conf_type':'CLOUD_INIT'
- }
+ configuration = {'conf_type': 'CLOUD_INIT'}
if cloud_config.get('user-data') is not None:
- configuration.update({'script':cloud_config.get('user-data')})
+ configuration['script'] = cloud_config.get('user-data')
if cloud_config.get('key-pairs') is not None:
- configuration.update({'ssh_keys':cloud_config.get('key-pairs')})
+ configuration['ssh_keys'] = cloud_config.get('key-pairs')
if 'script' in configuration:
- fdu_desc.update({'configuration':configuration})
+ fdu_desc['configuration'] = configuration
self.logger.debug('Eclipse fog05 FDU Descriptor: {}'.format(fdu_desc))
-
fdu = FDU(fdu_desc)
try:
raise ValueError("Unable to find node for network creation")
self.logger.debug('Selected node by VIM: {}'.format(selected_node))
- created_items.update({'fdu_id':fdu_uuid, 'node_id': selected_node})
+ created_items['fdu_id'] = fdu_uuid
+ created_items['node_id'] = selected_node
for cp in fdu_desc['connection_points']:
nets = self.fos_api.network.list()
self.logger.debug('Eclipse fog05 FDU Started {}'.format(instance.uuid))
- created_items.update({'instance_id': str(instance.uuid)})
+ created_items['instance_id'] = str(instance.uuid)
- self.fdu_node_map.update({instance.uuid: selected_node})
- self.logger.debug('new_vminstance returns: {} {}'.format( instance.uuid, created_items))
+ self.fdu_node_map[instance.uuid] = selected_node
+ self.logger.debug('new_vminstance returns: {} {}'.format(instance.uuid, created_items))
return str(instance.uuid), created_items
except fimapi.FIMAResouceExistingException as free:
raise vimconn.VimConnConflictException("VM already exists at VIM. Error {}".format(free))
except Exception as e:
raise vimconn.VimConnException("Error while instantiating VM {}. Error {}".format(name, e))
- def get_vminstance(self,vm_id):
+ def get_vminstance(self, vm_id):
"""Returns the VM instance information from VIM"""
self.logger.debug('VIM get_vminstance with args: {}'.format(locals()))
:return: None or the same vm_id. Raises an exception on fail
"""
self.logger.debug('FOS delete_vminstance with args: {}'.format(locals()))
- fduid = created_items.get('fdu_id')
+ fduid = created_items.get('fdu_id')
try:
instance = self.fos_api.fdu.instance_info(vm_id)
instance_list = self.fos_api.fdu.instance_list(instance.fdu_id)
self.fos_api.fdu.offload(fduid)
except Exception as e:
- raise vimconn.VimConnException("Error on deletting VM with id {}. Error {}".format(vm_id,e))
+ raise vimconn.VimConnException("Error on deleting VM with id {}. Error {}".format(vm_id, e))
return vm_id
- #raise VimConnNotImplemented( "Should have implemented this" )
+ # raise VimConnNotImplemented( "Should have implemented this" )
def refresh_vms_status(self, vm_list):
"""Get the status of the virtual machines and their interfaces/ports
"""
self.logger.debug('FOS refresh_vms_status with args: {}'.format(locals()))
fos2osm_status = {
- 'DEFINE':'OTHER',
- 'CONFIGURE':'INACTIVE',
- 'RUN':'ACTIVE',
- 'PAUSE':'PAUSED',
- 'ERROR':'ERROR'
+ 'DEFINE': 'OTHER',
+ 'CONFIGURE': 'INACTIVE',
+ 'RUN': 'ACTIVE',
+ 'PAUSE': 'PAUSED',
+ 'ERROR': 'ERROR'
}
r = {}
info = {}
nid = self.fdu_node_map.get(vm)
if nid is None:
- r.update({vm:{
- 'status':'VIM_ERROR',
- 'error_msg':'Not compute node associated for VM'
- }})
+ r[vm] = {
+ 'status': 'VIM_ERROR',
+ 'error_msg': 'Not compute node associated for VM'
+ }
continue
try:
vm_info = self.fos_api.fdu.instance_info(vm)
- except:
- r.update({vm:{
- 'status':'VIM_ERROR',
- 'error_msg':'unable to connect to VIM'
- }})
+ except Exception:
+ r[vm] = {
+ 'status': 'VIM_ERROR',
+ 'error_msg': 'unable to connect to VIM'
+ }
continue
if vm_info is None:
- r.update({vm:{'status':'DELETED'}})
+ r[vm:] = {'status': 'DELETED'}
continue
desc = self.fos_api.fdu.info(str(vm_info.fdu_id))
self.logger.debug('FOS status info {}'.format(vm_info))
self.logger.debug('FOS status is {} <-> OSM Status {}'.format(vm_info.get('status'), osm_status))
- info.update({'status':osm_status})
+ info['status'] = osm_status
if vm_info.get('status') == 'ERROR':
- info.update({'error_msg':vm_info.get('error_code')})
+ info['error_msg'] = vm_info.get('error_code')
# yaml.safe_dump(json.loads(json.dumps(vm_info)))
- # info.update({'vim_info':''})
+ # info['vim_info'] = ''
faces = []
i = 0
- for intf_name in vm_info.get('hypervisor_info').get('network',[]):
+ for intf_name in vm_info.get('hypervisor_info').get('network', []):
intf_info = vm_info.get('hypervisor_info').get('network').get(intf_name)
face = {}
face['compute_node'] = nid
matches = [x for x in cps_d if x['id'] == cp_id]
if len(matches) > 0:
cpd = matches[0]
- face['vim_net_id'] = cpd.get('vld_ref','')
+ face['vim_net_id'] = cpd.get('vld_ref', '')
else:
face['vim_net_id'] = ''
face['vim_interface_id'] = cp_id
faces.append(face)
i += 1
- info.update({'interfaces':faces})
- r.update({vm:info})
+ info['interfaces'] = faces
+ r[vm] = info
self.logger.debug('FOS refresh_vms_status res for {} is {}'.format(vm, info))
self.logger.debug('FOS refresh_vms_status res is {}'.format(r))
return r
elif instance.get('status') == 'PAUSE':
self.fos_api.fdu.resume(vm_id)
else:
- raise vimconn.VimConnConflictException('Cannot start from current state: {}'.format(instance.get('status')))
+ raise vimconn.VimConnConflictException('Cannot start from current state: {}'.format(
+ instance.get('status')))
elif "pause" in action_dict:
if instance.get('status') == 'RUN':
self.fos_api.fdu.pause(vm_id)
else:
- raise vimconn.VimConnConflictException('Cannot pause from current state: {}'.format(instance.get('status')))
+ raise vimconn.VimConnConflictException('Cannot pause from current state: {}'.format(
+ instance.get('status')))
elif "resume" in action_dict:
if instance.get('status') == 'PAUSE':
self.fos_api.fdu.resume(vm_id)
else:
- raise vimconn.VimConnConflictException('Cannot resume from current state: {}'.format(instance.get('status')))
+ raise vimconn.VimConnConflictException('Cannot resume from current state: {}'.format(
+ instance.get('status')))
elif "shutoff" in action_dict or "shutdown" or "forceOff" in action_dict:
if instance.get('status') == 'RUN':
self.fos_api.fdu.stop(vm_id)
else:
- raise vimconn.VimConnConflictException('Cannot shutoff from current state: {}'.format(instance.get('status')))
+ raise vimconn.VimConnConflictException('Cannot shutoff from current state: {}'.format(
+ instance.get('status')))
elif "terminate" in action_dict:
if instance.get('status') == 'RUN':
self.fos_api.fdu.stop(vm_id)
self.fos_api.fdu.undefine(vm_id)
# self.fos_api.fdu.offload(vm_id)
else:
- raise vimconn.VimConnConflictException('Cannot terminate from current state: {}'.format(instance.get('status')))
+ raise vimconn.VimConnConflictException('Cannot terminate from current state: {}'.format(
+ instance.get('status')))
elif "rebuild" in action_dict:
raise vimconn.VimConnNotImplemented("Rebuild not implemented")
elif "reboot" in action_dict:
self.fos_api.fdu.stop(vm_id)
self.fos_api.fdu.start(vm_id)
else:
- raise vimconn.VimConnConflictException('Cannot reboot from current state: {}'.format(instance.get('status')))
+ raise vimconn.VimConnConflictException('Cannot reboot from current state: {}'.format(
+ instance.get('status')))
except Exception as e:
raise vimconn.VimConnConnectionException("VIM not reachable. Error {}".format(e))
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
#Pip packages required for opennebula connector
python3 -m pip install -e git+https://github.com/python-oca/python-oca#egg=oca
-python3 -m pip install untangle
+# python3 -m pip install untangle
python3 -m pip install pyone
__date__ = "$13-dec-2017 11:09:29$"
from osm_ro_plugin import vimconn
import requests
-import logging
+# import logging
import oca
-import untangle
+# import untangle
import math
import random
import pyone
+
class vimconnector(vimconn.VimConnector):
def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None,
log_level="DEBUG", config={}, persistent_info={}):
</methodCall>'.format(self.user, self.passwd, (str(id_user)), (str(id_group)))
requests.post(self.url, params)
- def new_network(self, net_name, net_type, ip_profile=None, shared=False, provider_network_profile=None): # , **vim_specific):
+ def new_network(self, net_name, net_type, ip_profile=None, shared=False, provider_network_profile=None):
"""Adds a tenant network to VIM
Params:
'net_name': name of the network
size = int(math.pow(2, 32 - prefix))
if "dhcp_start_address" in ip_profile and ip_profile["dhcp_start_address"] is not None:
ip_start = str(ip_profile["dhcp_start_address"])
- if ip_profile["ip_version"] == "IPv6":
- ip_prefix_type = "GLOBAL_PREFIX"
+ # if ip_profile["ip_version"] == "IPv6":
+ # ip_prefix_type = "GLOBAL_PREFIX"
if vlan is not None:
vlan_id = vlan
else:
vlan_id = str(random.randint(100, 4095))
- #if "internal" in net_name:
+ # if "internal" in net_name:
# OpenNebula not support two networks with same name
random_net_name = str(random.randint(1, 1000000))
net_name = net_name + random_net_name
net_id = one.vn.allocate({
- 'NAME': net_name,
- 'VN_MAD': '802.1Q',
- 'PHYDEV': self.config["network"]["phydev"],
- 'VLAN_ID': vlan_id
- }, self.config["cluster"]["id"])
- arpool = {'AR_POOL': {
- 'AR': {
- 'TYPE': 'IP4',
- 'IP': ip_start,
- 'SIZE': size
- }
+ 'NAME': net_name,
+ 'VN_MAD': '802.1Q',
+ 'PHYDEV': self.config["network"]["phydev"],
+ 'VLAN_ID': vlan_id
+ }, self.config["cluster"]["id"])
+ arpool = {
+ 'AR_POOL': {
+ 'AR': {
+ 'TYPE': 'IP4',
+ 'IP': ip_start,
+ 'SIZE': size
}
+ }
}
one.vn.add_ar(net_id, arpool)
return net_id, created_items
def get_network_list(self, filter_dict={}):
"""Obtain tenant networks of VIM
- Params:
- 'filter_dict' (optional) contains entries to return only networks that matches ALL entries:
- name: string => returns only networks with this name
- id: string => returns networks with this VIM id, this imply returns one network at most
- shared: boolean >= returns only networks that are (or are not) shared
- tenant_id: sting => returns only networks that belong to this tenant/project
- ,#(not used yet) admin_state_up: boolean => returns only networks that are (or are not) in admin state active
- #(not used yet) status: 'ACTIVE','ERROR',... => filter networks that are on this status
+ :params filter_dict: (optional) contains entries to return only networks that matches ALL entries:
+ name: string => returns only networks with this name
+ id: string => returns networks with this VIM id, this imply returns one network at most
+ shared: boolean >= returns only networks that are (or are not) shared
+ tenant_id: sting => returns only networks that belong to this tenant/project
+ (not used yet) admin_state_up: boolean => returns only networks that are (or are not) in admin state active
+ (not used yet) status: 'ACTIVE','ERROR',... => filter networks that are on this status
Returns the network list of dictionaries. each dictionary contains:
'id': (mandatory) VIM network id
'name': (mandatory) VIM network name
vpcus: cpus (cloud type)
extended: EPA parameters
- numas: #items requested in same NUMA
- memory: number of 1G huge pages memory
- paired-threads|cores|threads: number of paired hyperthreads, complete cores OR individual threads
- interfaces: # passthrough(PT) or SRIOV interfaces attached to this numa
+ memory: number of 1G huge pages memory
+ paired-threads|cores|threads: number of paired hyperthreads, complete cores OR individual threads
+ interfaces: # passthrough(PT) or SRIOV interfaces attached to this numa
- name: interface name
dedicated: yes|no|yes:sriov; for PT, SRIOV or only one SRIOV for the physical NIC
bandwidth: X Gbps; requested guarantee bandwidth
def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None, disk_list=None,
availability_zone_index=None, availability_zone_list=None):
-
- """Adds a VM instance to VIM
- Params:
- 'start': (boolean) indicates if VM must start or created in pause mode.
- 'image_id','flavor_id': image and flavor VIM id to use for the VM
- 'net_list': list of interfaces, each one is a dictionary with:
- 'name': (optional) name for the interface.
- 'net_id': VIM network id where this interface must be connect to. Mandatory for type==virtual
- 'vpci': (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM capabilities
- 'model': (optional and only have sense for type==virtual) interface model: virtio, e1000, ...
- 'mac_address': (optional) mac address to assign to this interface
- 'ip_address': (optional) IP address to assign to this interface
- #TODO: CHECK if an optional 'vlan' parameter is needed for VIMs when type if VF and net_id is not provided,
- the VLAN tag to be used. In case net_id is provided, the internal network vlan is used for tagging VF
- 'type': (mandatory) can be one of:
- 'virtual', in this case always connected to a network of type 'net_type=bridge'
- 'PCI-PASSTHROUGH' or 'PF' (passthrough): depending on VIM capabilities it can be connected to a data/ptp network ot it
- can created unconnected
- 'SR-IOV' or 'VF' (SRIOV with VLAN tag): same as PF for network connectivity.
- 'VFnotShared'(SRIOV without VLAN tag) same as PF for network connectivity. VF where no other VFs
- are allocated on the same physical NIC
- 'bw': (optional) only for PF/VF/VFnotShared. Minimal Bandwidth required for the interface in GBPS
- 'port_security': (optional) If False it must avoid any traffic filtering at this interface. If missing
- or True, it must apply the default VIM behaviour
- After execution the method will add the key:
- 'vim_id': must be filled/added by this method with the VIM identifier generated by the VIM for this
- interface. 'net_list' is modified
- 'cloud_config': (optional) dictionary with:
- 'key-pairs': (optional) list of strings with the public key to be inserted to the default user
- 'users': (optional) list of users to be inserted, each item is a dict with:
- 'name': (mandatory) user name,
- 'key-pairs': (optional) list of strings with the public key to be inserted to the user
- 'user-data': (optional) can be a string with the text script to be passed directly to cloud-init,
- or a list of strings, each one contains a script to be passed, usually with a MIMEmultipart file
- 'config-files': (optional). List of files to be transferred. Each item is a dict with:
- 'dest': (mandatory) string with the destination absolute path
- 'encoding': (optional, by default text). Can be one of:
- 'b64', 'base64', 'gz', 'gz+b64', 'gz+base64', 'gzip+b64', 'gzip+base64'
- 'content' (mandatory): string with the content of the file
- 'permissions': (optional) string with file permissions, typically octal notation '0644'
- 'owner': (optional) file owner, string with the format 'owner:group'
- 'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk)
- 'disk_list': (optional) list with additional disks to the VM. Each item is a dict with:
- 'image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
- 'size': (mandatory) string with the size of the disk in GB
- availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV required
- availability_zone_list: list of availability zones given by user in the VNFD descriptor. Ignore if
+ """
+ Adds a VM instance to VIM
+ :param name:
+ :param description:
+ :param start: (boolean) indicates if VM must start or created in pause mode.
+ :param image_id: image VIM id to use for the VM
+ :param flavor_id: flavor VIM id to use for the VM
+ :param net_list: list of interfaces, each one is a dictionary with:
+ 'name': (optional) name for the interface.
+ 'net_id': VIM network id where this interface must be connect to. Mandatory for type==virtual
+ 'vpci': (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM
+ capabilities
+ 'model': (optional and only have sense for type==virtual) interface model: virtio, e1000, ...
+ 'mac_address': (optional) mac address to assign to this interface
+ 'ip_address': (optional) IP address to assign to this interface
+ #TODO: CHECK if an optional 'vlan' parameter is needed for VIMs when type if VF and net_id is not
+ provided, the VLAN tag to be used. In case net_id is provided, the internal network vlan is
+ used for tagging VF
+ 'type': (mandatory) can be one of:
+ 'virtual', in this case always connected to a network of type 'net_type=bridge'
+ 'PCI-PASSTHROUGH' or 'PF' (passthrough): depending on VIM capabilities it can be connected to
+ a data/ptp network ot itcan created unconnected
+ 'SR-IOV' or 'VF' (SRIOV with VLAN tag): same as PF for network connectivity.
+ 'VFnotShared'(SRIOV without VLAN tag) same as PF for network connectivity. VF where no other VFs
+ are allocated on the same physical NIC
+ 'bw': (optional) only for PF/VF/VFnotShared. Minimal Bandwidth required for the interface in GBPS
+ 'port_security': (optional) If False it must avoid any traffic filtering at this interface. If missing
+ or True, it must apply the default VIM behaviour
+ After execution the method will add the key:
+ 'vim_id': must be filled/added by this method with the VIM identifier generated by the VIM for this
+ interface. 'net_list' is modified
+ :param cloud_config: (optional) dictionary with:
+ 'key-pairs': (optional) list of strings with the public key to be inserted to the default user
+ 'users': (optional) list of users to be inserted, each item is a dict with:
+ 'name': (mandatory) user name,
+ 'key-pairs': (optional) list of strings with the public key to be inserted to the user
+ 'user-data': (optional) can be a string with the text script to be passed directly to cloud-init,
+ or a list of strings, each one contains a script to be passed, usually with a MIMEmultipart file
+ 'config-files': (optional). List of files to be transferred. Each item is a dict with:
+ 'dest': (mandatory) string with the destination absolute path
+ 'encoding': (optional, by default text). Can be one of:
+ 'b64', 'base64', 'gz', 'gz+b64', 'gz+base64', 'gzip+b64', 'gzip+base64'
+ 'content' (mandatory): string with the content of the file
+ 'permissions': (optional) string with file permissions, typically octal notation '0644'
+ 'owner': (optional) file owner, string with the format 'owner:group'
+ 'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk)
+ :param disk_list: (optional) list with additional disks to the VM. Each item is a dict with:
+ 'image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
+ 'size': (mandatory) string with the size of the disk in GB
+ :param availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV
+ required
+ :param availability_zone_list: list of availability zones given by user in the VNFD descriptor. Ignore if
availability_zone_index is None
- Returns a tuple with the instance identifier and created_items or raises an exception on error
- created_items can be None or a dictionary where this method can include key-values that will be passed to
- the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc.
- Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
- as not present.
- """
+ :return: a tuple with the instance identifier and created_items or raises an exception on error
+ created_items can be None or a dictionary where this method can include key-values that will be passed to
+ the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc.
+ Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
+ as not present.
+ """
self.logger.debug(
"new_vminstance input: image='{}' flavor='{}' nics='{}'".format(image_id, flavor_id, str(net_list)))
try:
else:
vm = one.vm.info(int(vm_id))
- except pyone.OneNoExistsException as e:
+ except pyone.OneNoExistsException:
self.logger.info("The vm " + str(vm_id) + " does not exist or is already deleted")
raise vimconn.VimConnNotFoundException("The vm {} does not exist or is already deleted".format(vm_id))
except Exception as e:
interface = {'vim_info': None, "mac_address": str(net["MAC"]), "vim_net_id": str(net["NETWORK_ID"]),
"vim_interface_id": str(net["NETWORK_ID"])}
# maybe it should be 2 different keys for ip_address if an interface has ipv4 and ipv6
- if u'IP' in net:
+ if 'IP' in net:
interface["ip_address"] = str(net["IP"])
- if u'IP6_GLOBAL' in net:
+ if 'IP6_GLOBAL' in net:
interface["ip_address"] = str(net["IP6_GLOBAL"])
interfaces.append(interface)
else:
interface = {'vim_info': None, "mac_address": str(net["MAC"]), "vim_net_id": str(net["NETWORK_ID"]),
"vim_interface_id": str(net["NETWORK_ID"])}
# maybe it should be 2 different keys for ip_address if an interface has ipv4 and ipv6
- if u'IP' in net:
+ if 'IP' in net:
interface["ip_address"] = str(net["IP"])
- if u'IP6_GLOBAL' in net:
+ if 'IP6_GLOBAL' in net:
interface["ip_address"] = str(net["IP6_GLOBAL"])
interfaces.append(interface)
return interfaces
- except Exception as e:
+ except Exception:
self.logger.error("Error getting vm interface_information of vm_id: " + str(vm_element.ID))
PyYAML
requests
netaddr
-untangle
+# untangle
pyone
git+https://github.com/python-oca/python-oca#egg=oca
git+https://osm.etsi.org/gerrit/osm/RO.git#egg=osm-ro-plugin&subdirectory=RO-plugin
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
# translated and returned the OpenStack result
self.assertEqual(result, [
{'sfis': ['08fbdbb0-82d6-11e7-ad95-9bb52fbec2f2',
- '0d63799c-82d6-11e7-8deb-a746bb3ae9f5'],
+ '0d63799c-82d6-11e7-8deb-a746bb3ae9f5'],
'description': '',
'tenant_id': '8f3019ef06374fa880a0144ad4bc1d7b',
'project_id': '8f3019ef06374fa880a0144ad4bc1d7b',
# under the License.
##
-'''
+"""
osconnector implements all the methods to interact with openstack using the python-neutronclient.
For the VNF forwarding graph, The OpenStack VIM connector calls the
- Service Function Instance (OSM) -> Port Pair (Neutron)
- Service Function (OSM) -> Port Pair Group (Neutron)
- Service Function Path (OSM) -> Port Chain (Neutron)
-'''
-__author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes, xFlow Research, Igor D.C., Eduardo Sousa"
-__date__ = "$22-sep-2017 23:59:59$"
+"""
from osm_ro_plugin import vimconn
# import json
import keystoneclient.v2_0.client as ksClient_v2
from glanceclient import client as glClient
import glanceclient.exc as gl1Exceptions
-from cinderclient import client as cClient
-from http.client import HTTPException # TODO py3 check that this base exception matches python2 httplib.HTTPException
+from cinderclient import client as cClient
+from http.client import HTTPException # TODO py3 check that this base exception matches python2 httplib.HTTPException
from neutronclient.neutron import client as neClient
from neutronclient.common import exceptions as neExceptions
from requests.exceptions import ConnectionError
+__author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes, xFlow Research, Igor D.C., Eduardo Sousa"
+__date__ = "$22-sep-2017 23:59:59$"
"""contain the openstack virtual machine status to openmano status"""
-vmStatus2manoFormat={'ACTIVE':'ACTIVE',
- 'PAUSED':'PAUSED',
- 'SUSPENDED': 'SUSPENDED',
- 'SHUTOFF':'INACTIVE',
- 'BUILD':'BUILD',
- 'ERROR':'ERROR','DELETED':'DELETED'
- }
-netStatus2manoFormat={'ACTIVE':'ACTIVE','PAUSED':'PAUSED','INACTIVE':'INACTIVE','BUILD':'BUILD','ERROR':'ERROR','DELETED':'DELETED'
- }
+vmStatus2manoFormat = {'ACTIVE': 'ACTIVE',
+ 'PAUSED': 'PAUSED',
+ 'SUSPENDED': 'SUSPENDED',
+ 'SHUTOFF': 'INACTIVE',
+ 'BUILD': 'BUILD',
+ 'ERROR': 'ERROR',
+ 'DELETED': 'DELETED'
+ }
+netStatus2manoFormat = {'ACTIVE': 'ACTIVE',
+ 'PAUSED': 'PAUSED',
+ 'INACTIVE': 'INACTIVE',
+ 'BUILD': 'BUILD',
+ 'ERROR': 'ERROR',
+ 'DELETED': 'DELETED'
+ }
supportedClassificationTypes = ['legacy_flow_classifier']
-#global var to have a timeout creating and deleting volumes
+# global var to have a timeout creating and deleting volumes
volume_timeout = 1800
server_timeout = 1800
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={}, persistent_info={}):
- '''using common constructor parameters. In this case
+ """using common constructor parameters. In this case
'url' is the keystone authorization url,
'url_admin' is not use
- '''
+ """
api_version = config.get('APIversion')
if api_version and api_version not in ('v3.3', 'v2.0', '2', '3'):
raise vimconn.VimConnException("Invalid value '{}' for config:APIversion. "
vim_type = config.get('vim_type')
if vim_type and vim_type not in ('vio', 'VIO'):
raise vimconn.VimConnException("Invalid value '{}' for config:vim_type."
- "Allowed values are 'vio' or 'VIO'".format(vim_type))
+ "Allowed values are 'vio' or 'VIO'".format(vim_type))
if config.get('dataplane_net_vlan_range') is not None:
- #validate vlan ranges provided by user
+ # validate vlan ranges provided by user
self._validate_vlan_ranges(config.get('dataplane_net_vlan_range'), 'dataplane_net_vlan_range')
if config.get('multisegment_vlan_range') is not None:
- #validate vlan ranges provided by user
+ # validate vlan ranges provided by user
self._validate_vlan_ranges(config.get('multisegment_vlan_range'), 'multisegment_vlan_range')
vimconn.VimConnector.__init__(self, uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level,
self.config['security_groups'] = [self.config['security_groups']]
self.security_groups_id = None
- ####### VIO Specific Changes #########
+ # ###### VIO Specific Changes #########
if self.vim_type == "VIO":
self.logger = logging.getLogger('openmano.vim.vio')
if log_level:
- self.logger.setLevel( getattr(logging, log_level))
+ self.logger.setLevel(getattr(logging, log_level))
def __getitem__(self, index):
"""Get individuals parameters.
if index == 'project_domain_id':
self.config["project_domain_id"] = value
elif index == 'user_domain_id':
- self.config["user_domain_id"] = value
+ self.config["user_domain_id"] = value
else:
vimconn.VimConnector.__setitem__(self, index, value)
self.session['reload_client'] = True
return yaml.dump(value, Dumper=SafeDumper,
default_flow_style=True, width=256)
except yaml.representer.RepresenterError:
- self.logger.debug('The following entity cannot be serialized in YAML:\n\n%s\n\n', pformat(value),
- exc_info=True)
- return str(value)
+ self.logger.debug('The following entity cannot be serialized in YAML:\n\n%s\n\n', pformat(value),
+ exc_info=True)
+ return str(value)
def _reload_connection(self):
- '''Called before any operation, it check if credentials has changed
+ """Called before any operation, it check if credentials has changed
Throw keystoneclient.apiclient.exceptions.AuthorizationFailure
- '''
- #TODO control the timing and possible token timeout, but it seams that python client does this task for us :-)
+ """
+ # TODO control the timing and possible token timeout, but it seams that python client does this task for us :-)
if self.session['reload_client']:
if self.config.get('APIversion'):
self.api_version3 = self.config['APIversion'] == 'v3.3' or self.config['APIversion'] == '3'
else: # get from ending auth_url that end with v3 or with v2.0
- self.api_version3 = self.url.endswith("/v3") or self.url.endswith("/v3/")
+ self.api_version3 = self.url.endswith("/v3") or self.url.endswith("/v3/")
self.session['api_version3'] = self.api_version3
if self.api_version3:
if self.config.get('project_domain_id') or self.config.get('project_domain_name'):
tenant_name=self.tenant_name,
tenant_id=self.tenant_id)
sess = session.Session(auth=auth, verify=self.verify)
- # addedd region_name to keystone, nova, neutron and cinder to support distributed cloud for Wind River Titanium cloud and StarlingX
+ # addedd region_name to keystone, nova, neutron and cinder to support distributed cloud for Wind River
+ # Titanium cloud and StarlingX
region_name = self.config.get('region_name')
if self.api_version3:
- self.keystone = ksClient_v3.Client(session=sess, endpoint_type=self.endpoint_type, region_name=region_name)
+ self.keystone = ksClient_v3.Client(session=sess, endpoint_type=self.endpoint_type,
+ region_name=region_name)
else:
self.keystone = ksClient_v2.Client(session=sess, endpoint_type=self.endpoint_type)
self.session['keystone'] = self.keystone
version = self.config.get("microversion")
if not version:
version = "2.1"
- # addedd region_name to keystone, nova, neutron and cinder to support distributed cloud for Wind River Titanium cloud and StarlingX
- self.nova = self.session['nova'] = nClient.Client(str(version), session=sess, endpoint_type=self.endpoint_type, region_name=region_name)
- self.neutron = self.session['neutron'] = neClient.Client('2.0', session=sess, endpoint_type=self.endpoint_type, region_name=region_name)
- self.cinder = self.session['cinder'] = cClient.Client(2, session=sess, endpoint_type=self.endpoint_type, region_name=region_name)
+ # addedd region_name to keystone, nova, neutron and cinder to support distributed cloud for Wind River
+ # Titanium cloud and StarlingX
+ self.nova = self.session['nova'] = nClient.Client(str(version), session=sess,
+ endpoint_type=self.endpoint_type, region_name=region_name)
+ self.neutron = self.session['neutron'] = neClient.Client('2.0', session=sess,
+ endpoint_type=self.endpoint_type,
+ region_name=region_name)
+ self.cinder = self.session['cinder'] = cClient.Client(2, session=sess, endpoint_type=self.endpoint_type,
+ region_name=region_name)
try:
self.my_tenant_id = self.session['my_tenant_id'] = sess.get_project_id()
- except Exception as e:
+ except Exception:
self.logger.error("Cannot get project_id from session", exc_info=True)
if self.endpoint_type == "internalURL":
glance_service_id = self.keystone.services.list(name="glance")[0].id
self.security_groups_id = None # force to get again security_groups_ids next time they are needed
def __net_os2mano(self, net_list_dict):
- '''Transform the net openstack format to mano format
- net_list_dict can be a list of dict or a single dict'''
+ """Transform the net openstack format to mano format
+ net_list_dict can be a list of dict or a single dict"""
if type(net_list_dict) is dict:
- net_list_=(net_list_dict,)
+ net_list_ = (net_list_dict,)
elif type(net_list_dict) is list:
- net_list_=net_list_dict
+ net_list_ = net_list_dict
else:
raise TypeError("param net_list_dict must be a list or a dictionary")
for net in net_list_:
if net.get('provider:network_type') == "vlan":
- net['type']='data'
+ net['type'] = 'data'
else:
- net['type']='bridge'
+ net['type'] = 'bridge'
def __classification_os2mano(self, class_list_dict):
"""Transform the openstack format (Flow Classifier) to mano format
elif isinstance(class_list_dict, list):
class_list_ = class_list_dict
else:
- raise TypeError(
- "param class_list_dict must be a list or a dictionary")
+ raise TypeError("param class_list_dict must be a list or a dictionary")
for classification in class_list_:
id = classification.pop('id')
name = classification.pop('name')
self.get_network_list(filter_dict={})
def get_tenant_list(self, filter_dict={}):
- '''Obtain tenants of VIM
+ """Obtain tenants of VIM
filter_dict can contain the following keys:
name: filter by tenant name
id: filter by tenant uuid/id
<other VIM specific>
Returns the tenant list of dictionaries: [{'name':'<name>, 'id':'<id>, ...}, ...]
- '''
+ """
self.logger.debug("Getting tenants from VIM filter: '%s'", str(filter_dict))
try:
self._reload_connection()
project_class_list = self.keystone.projects.list(name=filter_dict.get("name"))
else:
project_class_list = self.keystone.tenants.findall(**filter_dict)
- project_list=[]
+ project_list = []
for project in project_class_list:
if filter_dict.get('id') and filter_dict["id"] != project.id:
continue
self._format_exception(e)
def new_tenant(self, tenant_name, tenant_description):
- '''Adds a new tenant to openstack VIM. Returns the tenant identifier'''
+ """Adds a new tenant to openstack VIM. Returns the tenant identifier"""
self.logger.debug("Adding a new tenant name: %s", tenant_name)
try:
self._reload_connection()
else:
project = self.keystone.tenants.create(tenant_name, tenant_description)
return project.id
- except (ksExceptions.ConnectionError, ksExceptions.ClientException, ksExceptions.BadRequest, ConnectionError) as e:
+ except (ksExceptions.ConnectionError, ksExceptions.ClientException, ksExceptions.BadRequest, ConnectionError)\
+ as e:
self._format_exception(e)
def delete_tenant(self, tenant_id):
- '''Delete a tenant from openstack VIM. Returns the old tenant identifier'''
+ """Delete a tenant from openstack VIM. Returns the old tenant identifier"""
self.logger.debug("Deleting tenant %s from VIM", tenant_id)
try:
self._reload_connection()
else:
self.keystone.tenants.delete(tenant_id)
return tenant_id
- except (ksExceptions.ConnectionError, ksExceptions.ClientException, ksExceptions.NotFound, ConnectionError) as e:
+ except (ksExceptions.ConnectionError, ksExceptions.ClientException, ksExceptions.NotFound, ConnectionError)\
+ as e:
self._format_exception(e)
def new_network(self, net_name, net_type, ip_profile=None, shared=False, provider_network_profile=None):
if provider_network_profile and "network-type" in provider_network_profile:
network_dict["provider:network_type"] = provider_network_profile["network-type"]
else:
- network_dict["provider:network_type"] = self.config.get('dataplane_network_type','vlan')
+ network_dict["provider:network_type"] = self.config.get('dataplane_network_type', 'vlan')
if vlan:
network_dict["provider:segmentation_id"] = vlan
else:
segment2_dict["provider:segmentation_id"] = vlanID
# else
# raise vimconn.VimConnConflictException(
- # "You must provide 'multisegment_vlan_range' at config dict before creating a multisegment network")
+ # "You must provide 'multisegment_vlan_range' at config dict before creating a multisegment
+ # network")
segment_list.append(segment2_dict)
network_dict["segments"] = segment_list
network_dict["shared"] = shared
if self.config.get("disable_network_port_security"):
network_dict["port_security_enabled"] = False
- new_net = self.neutron.create_network({'network':network_dict})
+ new_net = self.neutron.create_network({'network': network_dict})
# print new_net
# create subnetwork, even if there is no profile
if not ip_profile:
ip_profile = {}
if not ip_profile.get('subnet_address'):
- #Fake subnet is required
+ # 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",
- "network_id": new_net["network"]["id"],
- "ip_version": 4 if ip_profile['ip_version']=="IPv4" else 6,
- "cidr": ip_profile['subnet_address']
- }
+ "network_id": new_net["network"]["id"],
+ "ip_version": 4 if ip_profile['ip_version'] == "IPv4" else 6,
+ "cidr": ip_profile['subnet_address']
+ }
# Gateway should be set to None if not needed. Otherwise openstack assigns one by default
if ip_profile.get('gateway_address'):
subnet['gateway_ip'] = ip_profile['gateway_address']
subnet['dns_nameservers'] = ip_profile['dns_address'].split(";")
if 'dhcp_enabled' in ip_profile:
subnet['enable_dhcp'] = False if \
- ip_profile['dhcp_enabled']=="false" or ip_profile['dhcp_enabled']==False else True
+ ip_profile['dhcp_enabled'] == "false" or ip_profile['dhcp_enabled'] is False else True
if ip_profile.get('dhcp_start_address'):
subnet['allocation_pools'] = []
subnet['allocation_pools'].append(dict())
subnet['allocation_pools'][0]['start'] = ip_profile['dhcp_start_address']
if ip_profile.get('dhcp_count'):
- #parts = ip_profile['dhcp_start_address'].split('.')
- #ip_int = (int(parts[0]) << 24) + (int(parts[1]) << 16) + (int(parts[2]) << 8) + int(parts[3])
+ # parts = ip_profile['dhcp_start_address'].split('.')
+ # ip_int = (int(parts[0]) << 24) + (int(parts[1]) << 16) + (int(parts[2]) << 8) + int(parts[3])
ip_int = int(netaddr.IPAddress(ip_profile['dhcp_start_address']))
ip_int += ip_profile['dhcp_count'] - 1
ip_str = str(netaddr.IPAddress(ip_int))
subnet['allocation_pools'][0]['end'] = ip_str
- #self.logger.debug(">>>>>>>>>>>>>>>>>> Subnet: %s", str(subnet))
- self.neutron.create_subnet({"subnet": subnet} )
+ # self.logger.debug(">>>>>>>>>>>>>>>>>> Subnet: %s", str(subnet))
+ self.neutron.create_subnet({"subnet": subnet})
if net_type == "data" and self.config.get('multisegment_support'):
if self.config.get('l2gw_support'):
l2gw_list = self.neutron.list_l2_gateways().get("l2_gateways", ())
for l2gw in l2gw_list:
- l2gw_conn = {}
- l2gw_conn["l2_gateway_id"] = l2gw["id"]
- l2gw_conn["network_id"] = new_net["network"]["id"]
- l2gw_conn["segmentation_id"] = str(vlanID)
+ l2gw_conn = {
+ "l2_gateway_id": l2gw["id"],
+ "network_id": new_net["network"]["id"],
+ "segmentation_id": str(vlanID),
+ }
new_l2gw_conn = self.neutron.create_l2_gateway_connection({"l2_gateway_connection": l2gw_conn})
created_items["l2gwconn:" + str(new_l2gw_conn["l2_gateway_connection"]["id"])] = True
return new_net["network"]["id"], created_items
except Exception as e:
- #delete l2gw connections (if any) before deleting the network
+ # delete l2gw connections (if any) before deleting the network
for k, v in created_items.items():
if not v: # skip already deleted
continue
self._format_exception(e)
def get_network_list(self, filter_dict={}):
- '''Obtain tenant networks of VIM
+ """Obtain tenant networks of VIM
Filter_dict can be:
name: network name
id: network uuid
admin_state_up: boolean
status: 'ACTIVE'
Returns the network list of dictionaries
- '''
+ """
self.logger.debug("Getting network from VIM filter: '%s'", str(filter_dict))
try:
self._reload_connection()
filter_dict_os = filter_dict.copy()
if self.api_version3 and "tenant_id" in filter_dict_os:
- filter_dict_os['project_id'] = filter_dict_os.pop('tenant_id') #T ODO check
+ filter_dict_os['project_id'] = filter_dict_os.pop('tenant_id') # TODO check
net_dict = self.neutron.list_networks(**filter_dict_os)
net_list = net_dict["networks"]
self.__net_os2mano(net_list)
return net_list
- except (neExceptions.ConnectionFailed, ksExceptions.ClientException, neExceptions.NeutronException, ConnectionError) as e:
+ except (neExceptions.ConnectionFailed, ksExceptions.ClientException, neExceptions.NeutronException,
+ ConnectionError) as e:
self._format_exception(e)
def get_network(self, net_id):
- '''Obtain details of network from VIM
- Returns the network information from a network id'''
+ """Obtain details of network from VIM
+ Returns the network information from a network id"""
self.logger.debug(" Getting tenant network %s from VIM", net_id)
- filter_dict={"id": net_id}
+ filter_dict = {"id": net_id}
net_list = self.get_network_list(filter_dict)
- if len(net_list)==0:
+ if len(net_list) == 0:
raise vimconn.VimConnNotFoundException("Network '{}' not found".format(net_id))
- elif len(net_list)>1:
+ elif len(net_list) > 1:
raise vimconn.VimConnConflictException("Found more than one network with this criteria")
net = net_list[0]
- subnets=[]
- for subnet_id in net.get("subnets", () ):
+ subnets = []
+ for subnet_id in net.get("subnets", ()):
try:
subnet = self.neutron.show_subnet(subnet_id)
except Exception as e:
Returns the network identifier or raises an exception upon error or when network is not found
"""
self.logger.debug("Deleting network '%s' from VIM", net_id)
- if created_items == None:
+ if created_items is None:
created_items = {}
try:
self._reload_connection()
- #delete l2gw connections (if any) before deleting the network
+ # delete l2gw connections (if any) before deleting the network
for k, v in created_items.items():
if not v: # skip already deleted
continue
self.neutron.delete_l2_gateway_connection(k_id)
except Exception as e:
self.logger.error("Error deleting l2 gateway connection: {}: {}".format(type(e).__name__, e))
- #delete VM ports attached to this networks before the network
+ # delete VM ports attached to this networks before the network
ports = self.neutron.list_ports(network_id=net_id)
for p in ports['ports']:
try:
self._format_exception(e)
def refresh_nets_status(self, net_list):
- '''Get the status of the networks
+ """Get the status of the networks
Params: the list of network identifiers
Returns a dictionary with:
net_id: #VIM id of this network
error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
- '''
- net_dict={}
+ """
+ net_dict = {}
for net_id in net_list:
net = {}
try:
net_vim = self.get_network(net_id)
if net_vim['status'] in netStatus2manoFormat:
- net["status"] = netStatus2manoFormat[ net_vim['status'] ]
+ net["status"] = netStatus2manoFormat[net_vim['status']]
else:
net["status"] = "OTHER"
net["error_msg"] = "VIM status reported " + net_vim['status']
net['vim_info'] = self.serialize(net_vim)
- if net_vim.get('fault'): #TODO
+ if net_vim.get('fault'): # TODO
net['error_msg'] = str(net_vim['fault'])
except vimconn.VimConnNotFoundException as e:
self.logger.error("Exception getting net status: %s", str(e))
return net_dict
def get_flavor(self, flavor_id):
- '''Obtain flavor details from the VIM. Returns the flavor dict details'''
+ """Obtain flavor details from the VIM. Returns the flavor dict details"""
self.logger.debug("Getting flavor '%s'", flavor_id)
try:
self._reload_connection()
flavor = self.nova.flavors.find(id=flavor_id)
- #TODO parse input and translate to VIM format (openmano_schemas.new_vminstance_response_schema)
+ # TODO parse input and translate to VIM format (openmano_schemas.new_vminstance_response_schema)
return flavor.to_dict()
- except (nvExceptions.NotFound, nvExceptions.ClientException, ksExceptions.ClientException, ConnectionError) as e:
+ except (nvExceptions.NotFound, nvExceptions.ClientException, ksExceptions.ClientException,
+ ConnectionError) as e:
self._format_exception(e)
def get_flavor_id_from_data(self, flavor_dict):
# numa=None
extended = flavor_dict.get("extended", {})
if extended:
- #TODO
+ # TODO
raise vimconn.VimConnNotFoundException("Flavor with EPA still not implemented")
# if len(numas) > 1:
# raise vimconn.VimConnNotFoundException("Cannot find any flavor with more than one numa")
flavor_candidate_data = flavor_data
if not exact_match and flavor_candidate_id:
return flavor_candidate_id
- raise vimconn.VimConnNotFoundException("Cannot find any flavor matching '{}'".format(str(flavor_dict)))
- except (nvExceptions.NotFound, nvExceptions.ClientException, ksExceptions.ClientException, ConnectionError) as e:
+ raise vimconn.VimConnNotFoundException("Cannot find any flavor matching '{}'".format(flavor_dict))
+ except (nvExceptions.NotFound, nvExceptions.ClientException, ksExceptions.ClientException,
+ ConnectionError) as e:
self._format_exception(e)
def process_resource_quota(self, quota, prefix, extra_specs):
extra_specs["quota:" + prefix + "_shares_share"] = quota['shares']
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
+ """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
Returns the flavor identifier
- '''
+ """
self.logger.debug("Adding flavor '%s'", str(flavor_data))
- retry=0
- max_retries=3
+ retry = 0
+ max_retries = 3
name_suffix = 0
try:
- name=flavor_data['name']
- while retry<max_retries:
- retry+=1
+ name = flavor_data['name']
+ while retry < max_retries:
+ retry += 1
try:
self._reload_connection()
if change_name_if_used:
- #get used names
- fl_names=[]
- fl=self.nova.flavors.list()
+ # get used names
+ fl_names = []
+ fl = self.nova.flavors.list()
for f in fl:
fl_names.append(f.name)
while name in fl_names:
name_suffix += 1
name = flavor_data['name']+"-" + str(name_suffix)
- ram = flavor_data.get('ram',64)
- vcpus = flavor_data.get('vcpus',1)
- extra_specs={}
+ ram = flavor_data.get('ram', 64)
+ vcpus = flavor_data.get('vcpus', 1)
+ extra_specs = {}
extended = flavor_data.get("extended")
if extended:
- numas=extended.get("numas")
+ numas = extended.get("numas")
if numas:
numa_nodes = len(numas)
if numa_nodes > 1:
extra_specs["vmware:extra_config"] = '{"numa.nodeAffinity":"0"}'
extra_specs["vmware:latency_sensitivity_level"] = "high"
for numa in numas:
- #overwrite ram and vcpus
- #check if key 'memory' is present in numa else use ram value at flavor
+ # overwrite ram and vcpus
+ # check if key 'memory' is present in numa else use ram value at flavor
if 'memory' in numa:
ram = numa['memory']*1024
- #See for reference: https://specs.openstack.org/openstack/nova-specs/specs/mitaka/implemented/virt-driver-cpu-thread-pinning.html
+ # See for reference: https://specs.openstack.org/openstack/nova-specs/specs/mitaka/
+ # implemented/virt-driver-cpu-thread-pinning.html
extra_specs["hw:cpu_sockets"] = 1
if 'paired-threads' in numa:
vcpus = numa['paired-threads']*2
- #cpu_thread_policy "require" implies that the compute node must have an STM architecture
+ # cpu_thread_policy "require" implies that the compute node must have an
+ # STM architecture
extra_specs["hw:cpu_thread_policy"] = "require"
extra_specs["hw:cpu_policy"] = "dedicated"
elif 'cores' in numa:
vcpus = numa['cores']
- # cpu_thread_policy "prefer" implies that the host must not have an SMT architecture, or a non-SMT architecture will be emulated
+ # cpu_thread_policy "prefer" implies that the host must not have an SMT
+ # architecture, or a non-SMT architecture will be emulated
extra_specs["hw:cpu_thread_policy"] = "isolate"
extra_specs["hw:cpu_policy"] = "dedicated"
elif 'threads' in numa:
vcpus = numa['threads']
- # cpu_thread_policy "prefer" implies that the host may or may not have an SMT architecture
+ # cpu_thread_policy "prefer" implies that the host may or may not have an SMT
+ # architecture
extra_specs["hw:cpu_thread_policy"] = "prefer"
extra_specs["hw:cpu_policy"] = "dedicated"
# for interface in numa.get("interfaces",() ):
# if interface["dedicated"]=="yes":
- # raise vimconn.VimConnException("Passthrough interfaces are not supported for the openstack connector", http_code=vimconn.HTTP_Service_Unavailable)
- # #TODO, add the key 'pci_passthrough:alias"="<label at config>:<number ifaces>"' when a way to connect it is available
+ # raise vimconn.VimConnException("Passthrough interfaces are not supported
+ # for the openstack connector", http_code=vimconn.HTTP_Service_Unavailable)
+ # #TODO, add the key 'pci_passthrough:alias"="<label at config>:<number ifaces>"'
+ # when a way to connect it is available
elif extended.get("cpu-quota"):
self.process_resource_quota(extended.get("cpu-quota"), "cpu", extra_specs)
if extended.get("mem-quota"):
self.process_resource_quota(extended.get("vif-quota"), "vif", extra_specs)
if extended.get("disk-io-quota"):
self.process_resource_quota(extended.get("disk-io-quota"), "disk_io", extra_specs)
- #create flavor
- new_flavor=self.nova.flavors.create(name,
- ram,
- vcpus,
- flavor_data.get('disk',0),
- is_public=flavor_data.get('is_public', True)
- )
- #add metadata
+ # create flavor
+ new_flavor = self.nova.flavors.create(name,
+ ram,
+ vcpus,
+ flavor_data.get('disk', 0),
+ is_public=flavor_data.get('is_public', True)
+ )
+ # add metadata
if extra_specs:
new_flavor.set_keys(extra_specs)
return new_flavor.id
if change_name_if_used and retry < max_retries:
continue
self._format_exception(e)
- #except nvExceptions.BadRequest as e:
+ # except nvExceptions.BadRequest as e:
except (ksExceptions.ClientException, nvExceptions.ClientException, ConnectionError, KeyError) as e:
self._format_exception(e)
- def delete_flavor(self,flavor_id):
- '''Deletes a tenant flavor from openstack VIM. Returns the old flavor_id
- '''
+ def delete_flavor(self, flavor_id):
+ """Deletes a tenant flavor from openstack VIM. Returns the old flavor_id
+ """
try:
self._reload_connection()
self.nova.flavors.delete(flavor_id)
return flavor_id
- #except nvExceptions.BadRequest as e:
- except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException, ConnectionError) as e:
+ # except nvExceptions.BadRequest as e:
+ except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException,
+ ConnectionError) as e:
self._format_exception(e)
- def new_image(self,image_dict):
- '''
+ def new_image(self, image_dict):
+ """
Adds a tenant image to VIM. imge_dict is a dictionary with:
name: name
disk_format: qcow2, vhd, vmdk, raw (by default), ...
public: "yes" or "no"
metadata: metadata of the image
Returns the image_id
- '''
- retry=0
- max_retries=3
- while retry<max_retries:
- retry+=1
+ """
+ retry = 0
+ max_retries = 3
+ while retry < max_retries:
+ retry += 1
try:
self._reload_connection()
- #determine format http://docs.openstack.org/developer/glance/formats.html
+ # determine format http://docs.openstack.org/developer/glance/formats.html
if "disk_format" in image_dict:
- disk_format=image_dict["disk_format"]
- else: #autodiscover based on extension
+ disk_format = image_dict["disk_format"]
+ else: # autodiscover based on extension
if image_dict['location'].endswith(".qcow2"):
- disk_format="qcow2"
+ disk_format = "qcow2"
elif image_dict['location'].endswith(".vhd"):
- disk_format="vhd"
+ disk_format = "vhd"
elif image_dict['location'].endswith(".vmdk"):
- disk_format="vmdk"
+ disk_format = "vmdk"
elif image_dict['location'].endswith(".vdi"):
- disk_format="vdi"
+ disk_format = "vdi"
elif image_dict['location'].endswith(".iso"):
- disk_format="iso"
+ disk_format = "iso"
elif image_dict['location'].endswith(".aki"):
- disk_format="aki"
+ disk_format = "aki"
elif image_dict['location'].endswith(".ari"):
- disk_format="ari"
+ disk_format = "ari"
elif image_dict['location'].endswith(".ami"):
- disk_format="ami"
+ disk_format = "ami"
else:
- disk_format="raw"
+ disk_format = "raw"
self.logger.debug("new_image: '%s' loading from '%s'", image_dict['name'], image_dict['location'])
if self.vim_type == "VIO":
container_format = "bare"
if image_dict['location'].startswith("http"):
# TODO there is not a method to direct download. It must be downloaded locally with requests
raise vimconn.VimConnNotImplemented("Cannot create image from URL")
- else: #local path
+ else: # local path
with open(image_dict['location']) as fimage:
self.glance.images.upload(new_image.id, fimage)
- #new_image = self.glancev1.images.create(name=image_dict['name'], is_public=image_dict.get('public',"yes")=="yes",
+ # new_image = self.glancev1.images.create(name=image_dict['name'], is_public=
+ # image_dict.get('public',"yes")=="yes",
# container_format="bare", data=fimage, disk_format=disk_format)
metadata_to_load = image_dict.get('metadata')
- # TODO location is a reserved word for current openstack versions. fixed for VIO please check for openstack
+ # TODO location is a reserved word for current openstack versions. fixed for VIO please check
+ # for openstack
if self.vim_type == "VIO":
metadata_to_load['upload_location'] = image_dict['location']
else:
except (nvExceptions.Conflict, ksExceptions.ClientException, nvExceptions.ClientException) as e:
self._format_exception(e)
except (HTTPException, gl1Exceptions.HTTPException, gl1Exceptions.CommunicationError, ConnectionError) as e:
- if retry==max_retries:
+ if retry == max_retries:
continue
self._format_exception(e)
- except IOError as e: #can not open the file
- raise vimconn.VimConnConnectionException(type(e).__name__ + ": " + str(e)+ " for " + image_dict['location'],
+ except IOError as e: # can not open the file
+ raise vimconn.VimConnConnectionException("{}: {} for {}".format(type(e).__name__, e,
+ image_dict['location']),
http_code=vimconn.HTTP_Bad_Request)
def delete_image(self, image_id):
- '''Deletes a tenant image from openstack VIM. Returns the old id
- '''
+ """Deletes a tenant image from openstack VIM. Returns the old id
+ """
try:
self._reload_connection()
self.glance.images.delete(image_id)
return image_id
- except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError, gl1Exceptions.HTTPNotFound, ConnectionError) as e: #TODO remove
+ except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException,
+ gl1Exceptions.CommunicationError, gl1Exceptions.HTTPNotFound, ConnectionError) as e: # TODO remove
self._format_exception(e)
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"""
try:
self._reload_connection()
images = self.glance.images.list()
for image in images:
- if image.metadata.get("location")==path:
+ if image.metadata.get("location") == path:
return image.id
- raise vimconn.VimConnNotFoundException("image with location '{}' not found".format( path))
- except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError, ConnectionError) as e:
+ raise vimconn.VimConnNotFoundException("image with location '{}' not found".format(path))
+ except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError,
+ ConnectionError) as e:
self._format_exception(e)
def get_image_list(self, filter_dict={}):
- '''Obtain tenant images from VIM
+ """Obtain tenant images from VIM
Filter_dict can be:
id: image id
name: image name
Returns the image list of dictionaries:
[{<the fields at Filter_dict plus some VIM specific>}, ...]
List can be empty
- '''
+ """
self.logger.debug("Getting image list from VIM filter: '%s'", str(filter_dict))
try:
self._reload_connection()
- filter_dict_os = filter_dict.copy()
- #First we filter by the available filter fields: name, id. The others are removed.
+ # filter_dict_os = filter_dict.copy()
+ # First we filter by the available filter fields: name, id. The others are removed.
image_list = self.glance.images.list()
filtered_list = []
for image in image_list:
except gl1Exceptions.HTTPNotFound:
pass
return filtered_list
- except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError, ConnectionError) as e:
+ except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError,
+ ConnectionError) as e:
self._format_exception(e)
def __wait_for_vm(self, vm_id, status):
openstack_availability_zone = [str(zone.zoneName) for zone in openstack_availability_zone
if zone.zoneName != 'internal']
return openstack_availability_zone
- except Exception as e:
+ except Exception:
return None
def _set_availablity_zones(self):
Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
as not present.
"""
- self.logger.debug("new_vminstance input: 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:
server = None
created_items = {}
# metadata = {}
net_list_vim = []
- external_network = [] # list of external networks to be connected to instance, later on used to create floating_ip
+ external_network = []
+ # ^list of external networks to be connected to instance, later on used to create floating_ip
no_secured_ports = [] # List of port-is with port-security disabled
self._reload_connection()
# metadata_vpci = {} # For a specific neutron plugin
self._get_ids_from_name()
port_dict["security_groups"] = self.security_groups_id
- if net["type"]=="virtual":
+ if net["type"] == "virtual":
pass
# if "vpci" in net:
# metadata_vpci[ net["net_id"] ] = [[ net["vpci"], "" ]]
# if "VF" not in metadata_vpci:
# metadata_vpci["VF"]=[]
# metadata_vpci["VF"].append([ net["vpci"], "" ])
- port_dict["binding:vnic_type"]="direct"
+ port_dict["binding:vnic_type"] = "direct"
# VIO specific Changes
if self.vim_type == "VIO":
# Need to create port with port_security_enabled = False and no-security-groups
- port_dict["port_security_enabled"]=False
- port_dict["provider_security_groups"]=[]
- port_dict["security_groups"]=[]
+ port_dict["port_security_enabled"] = False
+ port_dict["provider_security_groups"] = []
+ port_dict["security_groups"] = []
else: # For PT PCI-PASSTHROUGH
# if "vpci" in net:
# if "PF" not in metadata_vpci:
# metadata_vpci["PF"]=[]
# metadata_vpci["PF"].append([ net["vpci"], "" ])
- port_dict["binding:vnic_type"]="direct-physical"
+ port_dict["binding:vnic_type"] = "direct-physical"
if not port_dict["name"]:
- port_dict["name"]=name
+ port_dict["name"] = name
if net.get("mac_address"):
- port_dict["mac_address"]=net["mac_address"]
+ port_dict["mac_address"] = net["mac_address"]
if net.get("ip_address"):
port_dict["fixed_ips"] = [{'ip_address': net["ip_address"]}]
# TODO add 'subnet_id': <subnet_id>
- new_port = self.neutron.create_port({"port": port_dict })
+ new_port = self.neutron.create_port({"port": port_dict})
created_items["port:" + str(new_port["port"]["id"])] = True
net["mac_adress"] = new_port["port"]["mac_address"]
net["vim_id"] = new_port["port"]["id"]
external_network.append(net)
net['floating_ip'] = self.config.get('use_floating_ip')
- # If port security is disabled when the port has not yet been attached to the VM, then all vm traffic is dropped.
+ # If port security is disabled when the port has not yet been attached to the VM, then all vm traffic
+ # is dropped.
# As a workaround we wait until the VM is active and then disable the port-security
- if net.get("port_security") == False and not self.config.get("no_port_security_extension"):
+ if net.get("port_security") is False and not self.config.get("no_port_security_extension"):
no_secured_ports.append(new_port["port"]["id"])
# if metadata_vpci:
try:
self.neutron.update_port(port_id,
{"port": {"port_security_enabled": False, "security_groups": None}})
- except Exception as e:
+ except Exception:
raise vimconn.VimConnException("It was not possible to disable port security for port {}".format(
port_id))
# print "DONE :-)", server
free_floating_ip = ip["id"]
else:
if isinstance(floating_network['floating_ip'], str) and \
- floating_network['floating_ip'].lower() != "true":
+ floating_network['floating_ip'].lower() != "true":
pool_id = floating_network['floating_ip']
else:
# Find the external network
external_nets = list()
for net in self.neutron.list_networks()['networks']:
if net['router:external']:
- external_nets.append(net)
+ external_nets.append(net)
if len(external_nets) == 0:
- raise vimconn.VimConnException("Cannot create floating_ip automatically since no external "
- "network is present",
- http_code=vimconn.HTTP_Conflict)
+ 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)
+ 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}}
raise
return server.id, created_items
-# except nvExceptions.NotFound as e:
-# error_value=-vimconn.HTTP_Not_Found
-# error_text= "vm instance %s not found" % vm_id
-# except TypeError as e:
-# raise vimconn.VimConnException(type(e).__name__ + ": "+ str(e), http_code=vimconn.HTTP_Bad_Request)
+ # except nvExceptions.NotFound as e:
+ # error_value=-vimconn.HTTP_Not_Found
+ # error_text= "vm instance %s not found" % vm_id
+ # except TypeError as e:
+ # raise vimconn.VimConnException(type(e).__name__ + ": "+ str(e), http_code=vimconn.HTTP_Bad_Request)
except Exception as e:
server_id = None
self._format_exception(e)
- def get_vminstance(self,vm_id):
- '''Returns the VM instance information from VIM'''
- #self.logger.debug("Getting VM from VIM")
+ def get_vminstance(self, vm_id):
+ """Returns the VM instance information from VIM"""
+ # self.logger.debug("Getting VM from VIM")
try:
self._reload_connection()
server = self.nova.servers.find(id=vm_id)
- #TODO parse input and translate to VIM format (openmano_schemas.new_vminstance_response_schema)
+ # TODO parse input and translate to VIM format (openmano_schemas.new_vminstance_response_schema)
return server.to_dict()
- except (ksExceptions.ClientException, nvExceptions.ClientException, nvExceptions.NotFound, ConnectionError) as e:
+ except (ksExceptions.ClientException, nvExceptions.ClientException, nvExceptions.NotFound,
+ ConnectionError) as e:
self._format_exception(e)
- def get_vminstance_console(self,vm_id, console_type="vnc"):
- '''
+ def get_vminstance_console(self, vm_id, console_type="vnc"):
+ """
Get a console for the virtual machine
Params:
vm_id: uuid of the VM
server: usually ip address
port: the http, ssh, ... port
suffix: extra text, e.g. the http path and query string
- '''
+ """
self.logger.debug("Getting VM CONSOLE from VIM")
try:
self._reload_connection()
server = self.nova.servers.find(id=vm_id)
- if console_type == None or console_type == "novnc":
+ if console_type is None or console_type == "novnc":
console_dict = server.get_vnc_console("novnc")
elif console_type == "xvpvnc":
console_dict = server.get_vnc_console(console_type)
elif console_type == "spice-html5":
console_dict = server.get_spice_console(console_type)
else:
- raise vimconn.VimConnException("console type '{}' not allowed".format(console_type), http_code=vimconn.HTTP_Bad_Request)
+ raise vimconn.VimConnException("console type '{}' not allowed".format(console_type),
+ http_code=vimconn.HTTP_Bad_Request)
console_dict1 = console_dict.get("console")
if console_dict1:
console_url = console_dict1.get("url")
if console_url:
- #parse console_url
+ # parse console_url
protocol_index = console_url.find("//")
suffix_index = console_url[protocol_index+2:].find("/") + protocol_index+2
port_index = console_url[protocol_index+2:suffix_index].find(":") + protocol_index+2
- if protocol_index < 0 or port_index<0 or suffix_index<0:
+ if protocol_index < 0 or port_index < 0 or suffix_index < 0:
return -vimconn.HTTP_Internal_Server_Error, "Unexpected response from VIM"
- console_dict={"protocol": console_url[0:protocol_index],
- "server": console_url[protocol_index+2:port_index],
- "port": console_url[port_index:suffix_index],
- "suffix": console_url[suffix_index+1:]
- }
+ console_dict = {"protocol": console_url[0:protocol_index],
+ "server": console_url[protocol_index+2:port_index],
+ "port": console_url[port_index:suffix_index],
+ "suffix": console_url[suffix_index+1:]
+ }
protocol_index += 2
return console_dict
raise vimconn.VimConnUnexpectedResponse("Unexpected response from VIM")
- except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException, nvExceptions.BadRequest, ConnectionError) as e:
+ except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException,
+ nvExceptions.BadRequest, ConnectionError) as e:
self._format_exception(e)
def delete_vminstance(self, vm_id, created_items=None):
- '''Removes a VM instance from VIM. Returns the old identifier
- '''
- #print "osconnector: Getting VM from VIM"
- if created_items == None:
+ """Removes a VM instance from VIM. Returns the old identifier
+ """
+ # print "osconnector: Getting VM from VIM"
+ if created_items is None:
created_items = {}
try:
self._reload_connection()
time.sleep(1)
elapsed_time += 1
return None
- except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException, ConnectionError) as e:
+ except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException,
+ ConnectionError) as e:
self._format_exception(e)
def refresh_vms_status(self, vm_list):
- '''Get the status of the virtual machines and their interfaces/ports
+ """Get the status of the virtual machines and their interfaces/ports
Params: the list of VM identifiers
Returns a dictionary with:
vm_id: #VIM id of this Virtual Machine
compute_node: #identification of compute node where PF,VF interface is allocated
pci: #PCI address of the NIC that hosts the PF,VF
vlan: #physical VLAN used for VF
- '''
- vm_dict={}
+ """
+ vm_dict = {}
self.logger.debug("refresh_vms status: Getting tenant VM instance information from VIM")
for vm_id in vm_list:
- vm={}
+ vm = {}
try:
vm_vim = self.get_vminstance(vm_id)
if vm_vim['status'] in vmStatus2manoFormat:
- vm['status'] = vmStatus2manoFormat[ vm_vim['status'] ]
+ vm['status'] = vmStatus2manoFormat[vm_vim['status']]
else:
- vm['status'] = "OTHER"
+ vm['status'] = "OTHER"
vm['error_msg'] = "VIM status reported " + vm_vim['status']
vm['vim_info'] = self.serialize(vm_vim)
vm["interfaces"] = []
if vm_vim.get('fault'):
vm['error_msg'] = str(vm_vim['fault'])
- #get interfaces
+ # get interfaces
try:
self._reload_connection()
port_dict = self.neutron.list_ports(device_id=vm_id)
for port in port_dict["ports"]:
- interface={}
+ interface = {}
interface['vim_info'] = self.serialize(port)
interface["mac_address"] = port.get("mac_address")
interface["vim_net_id"] = port["network_id"]
# in case of non-admin credentials, it will be missing
if port.get('binding:profile'):
if port['binding:profile'].get('pci_slot'):
- # TODO: At the moment sr-iov pci addresses are converted to PF pci addresses by setting the slot to 0x00
+ # TODO: At the moment sr-iov pci addresses are converted to PF pci addresses by setting
+ # the slot to 0x00
# TODO: This is just a workaround valid for niantinc. Find a better way to do so
# CHANGE DDDD:BB:SS.F to DDDD:BB:00.(F%2) assuming there are 2 ports per nic
pci = port['binding:profile']['pci_slot']
if network['network'].get('provider:network_type') == 'vlan':
# and port.get("binding:vnic_type") in ("direct", "direct-physical"):
interface["vlan"] = network['network'].get('provider:segmentation_id')
- ips=[]
- #look for floating ip address
+ ips = []
+ # look for floating ip address
try:
floating_ip_dict = self.neutron.list_floatingips(port_id=port["id"])
if floating_ip_dict.get("floatingips"):
- ips.append(floating_ip_dict["floatingips"][0].get("floating_ip_address") )
+ ips.append(floating_ip_dict["floatingips"][0].get("floating_ip_address"))
except Exception:
pass
return vm_dict
def action_vminstance(self, vm_id, action_dict, created_items={}):
- '''Send and action over a VM instance from VIM
- Returns None or the console dict if the action was successfully sent to the VIM'''
+ """Send and action over a VM instance from VIM
+ Returns None or the console dict if the action was successfully sent to the VIM"""
self.logger.debug("Action over VM '%s': %s", vm_id, str(action_dict))
try:
self._reload_connection()
server = self.nova.servers.find(id=vm_id)
if "start" in action_dict:
- if action_dict["start"]=="rebuild":
+ if action_dict["start"] == "rebuild":
server.rebuild()
else:
- if server.status=="PAUSED":
+ if server.status == "PAUSED":
server.unpause()
- elif server.status=="SUSPENDED":
+ elif server.status == "SUSPENDED":
server.resume()
- elif server.status=="SHUTOFF":
+ elif server.status == "SHUTOFF":
server.start()
elif "pause" in action_dict:
server.pause()
elif "shutoff" in action_dict or "shutdown" in action_dict:
server.stop()
elif "forceOff" in action_dict:
- server.stop() #TODO
+ server.stop() # TODO
elif "terminate" in action_dict:
server.delete()
elif "createImage" in action_dict:
server.create_image()
- #"path":path_schema,
- #"description":description_schema,
- #"name":name_schema,
- #"metadata":metadata_schema,
- #"imageRef": id_schema,
- #"disk": {"oneOf":[{"type": "null"}, {"type":"string"}] },
+ # "path":path_schema,
+ # "description":description_schema,
+ # "name":name_schema,
+ # "metadata":metadata_schema,
+ # "imageRef": id_schema,
+ # "disk": {"oneOf":[{"type": "null"}, {"type":"string"}] },
elif "rebuild" in action_dict:
server.rebuild(server.image['id'])
elif "reboot" in action_dict:
- server.reboot() #reboot_type='SOFT'
+ server.reboot() # reboot_type='SOFT'
elif "console" in action_dict:
console_type = action_dict["console"]
- if console_type == None or console_type == "novnc":
+ if console_type is None or console_type == "novnc":
console_dict = server.get_vnc_console("novnc")
elif console_type == "xvpvnc":
console_dict = server.get_vnc_console(console_type)
http_code=vimconn.HTTP_Bad_Request)
try:
console_url = console_dict["console"]["url"]
- #parse console_url
+ # parse console_url
protocol_index = console_url.find("//")
suffix_index = console_url[protocol_index+2:].find("/") + protocol_index+2
port_index = console_url[protocol_index+2:suffix_index].find(":") + protocol_index+2
- if protocol_index < 0 or port_index<0 or suffix_index<0:
+ if protocol_index < 0 or port_index < 0 or suffix_index < 0:
raise vimconn.VimConnException("Unexpected response from VIM " + str(console_dict))
- console_dict2={"protocol": console_url[0:protocol_index],
- "server": console_url[protocol_index+2 : port_index],
- "port": int(console_url[port_index+1 : suffix_index]),
- "suffix": console_url[suffix_index+1:]
- }
+ console_dict2 = {"protocol": console_url[0:protocol_index],
+ "server": console_url[protocol_index+2: port_index],
+ "port": int(console_url[port_index+1: suffix_index]),
+ "suffix": console_url[suffix_index+1:]
+ }
return console_dict2
- except Exception as e:
+ except Exception:
raise vimconn.VimConnException("Unexpected response from VIM " + str(console_dict))
return None
- except (ksExceptions.ClientException, nvExceptions.ClientException, nvExceptions.NotFound, ConnectionError) as e:
+ except (ksExceptions.ClientException, nvExceptions.ClientException, nvExceptions.NotFound,
+ ConnectionError) as e:
self._format_exception(e)
- #TODO insert exception vimconn.HTTP_Unauthorized
+ # TODO insert exception vimconn.HTTP_Unauthorized
- ####### VIO Specific Changes #########
+ # ###### VIO Specific Changes #########
def _generate_vlanID(self):
"""
Method to get unused vlanID
Returns:
vlanID
"""
- #Get used VLAN IDs
+ # Get used VLAN IDs
usedVlanIDs = []
networks = self.get_network_list()
for net in networks:
usedVlanIDs.append(net.get('provider:segmentation_id'))
used_vlanIDs = set(usedVlanIDs)
- #find unused VLAN ID
+ # find unused VLAN ID
for vlanID_range in self.config.get('dataplane_net_vlan_range'):
try:
- start_vlanid , end_vlanid = map(int, vlanID_range.replace(" ", "").split("-"))
+ start_vlanid, end_vlanid = map(int, vlanID_range.replace(" ", "").split("-"))
for vlanID in range(start_vlanid, end_vlanid + 1):
if vlanID not in used_vlanIDs:
return vlanID
except Exception as exp:
raise vimconn.VimConnException("Exception {} occurred while generating VLAN ID.".format(exp))
else:
- raise vimconn.VimConnConflictException("Unable to create the SRIOV VLAN network."\
- " All given Vlan IDs {} are in use.".format(self.config.get('dataplane_net_vlan_range')))
-
+ raise vimconn.VimConnConflictException(
+ "Unable to create the SRIOV VLAN network. All given Vlan IDs {} are in use.".format(
+ self.config.get('dataplane_net_vlan_range')))
def _generate_multisegment_vlanID(self):
"""
except Exception as exp:
raise vimconn.VimConnException("Exception {} occurred while generating VLAN ID.".format(exp))
else:
- raise vimconn.VimConnConflictException("Unable to create the VLAN segment."
- " All VLAN IDs {} are in use.".format(self.config.get('multisegment_vlan_range')))
-
+ raise vimconn.VimConnConflictException(
+ "Unable to create the VLAN segment. All VLAN IDs {} are in use.".format(
+ self.config.get('multisegment_vlan_range')))
def _validate_vlan_ranges(self, input_vlan_range, text_vlan_range):
"""
"""
for vlanID_range in input_vlan_range:
vlan_range = vlanID_range.replace(" ", "")
- #validate format
+ # validate format
vlanID_pattern = r'(\d)*-(\d)*$'
match_obj = re.match(vlanID_pattern, vlan_range)
if not match_obj:
- raise vimconn.VimConnConflictException("Invalid VLAN range for {}: {}.You must provide "\
- "'{}' in format [start_ID - end_ID].".format(text_vlan_range, vlanID_range, text_vlan_range))
-
- start_vlanid , end_vlanid = map(int,vlan_range.split("-"))
- if start_vlanid <= 0 :
- raise vimconn.VimConnConflictException("Invalid VLAN range for {}: {}."\
- "Start ID can not be zero. For VLAN "\
- "networks valid IDs are 1 to 4094 ".format(text_vlan_range, vlanID_range))
- if end_vlanid > 4094 :
- raise vimconn.VimConnConflictException("Invalid VLAN range for {}: {}."\
- "End VLAN ID can not be greater than 4094. For VLAN "\
- "networks valid IDs are 1 to 4094 ".format(text_vlan_range, vlanID_range))
+ raise vimconn.VimConnConflictException(
+ "Invalid VLAN range for {}: {}.You must provide '{}' in format [start_ID - end_ID].".format(
+ text_vlan_range, vlanID_range, text_vlan_range))
+
+ start_vlanid, end_vlanid = map(int, vlan_range.split("-"))
+ if start_vlanid <= 0:
+ raise vimconn.VimConnConflictException(
+ "Invalid VLAN range for {}: {}. Start ID can not be zero. For VLAN "
+ "networks valid IDs are 1 to 4094 ".format(text_vlan_range, vlanID_range))
+ if end_vlanid > 4094:
+ raise vimconn.VimConnConflictException(
+ "Invalid VLAN range for {}: {}. End VLAN ID can not be greater than 4094. For VLAN "
+ "networks valid IDs are 1 to 4094 ".format(text_vlan_range, vlanID_range))
if start_vlanid > end_vlanid:
- raise vimconn.VimConnConflictException("Invalid VLAN range for {}: {}."\
- "You must provide '{}' in format start_ID - end_ID and "\
+ raise vimconn.VimConnConflictException(
+ "Invalid VLAN range for {}: {}. You must provide '{}' in format start_ID - end_ID and "
"start_ID < end_ID ".format(text_vlan_range, vlanID_range, text_vlan_range))
-#NOT USED FUNCTIONS
+ # NOT USED FUNCTIONS
def new_external_port(self, port_data):
- #TODO openstack if needed
- '''Adds a external port to VIM'''
- '''Returns the port identifier'''
+ """Adds a external port to VIM
+ Returns the port identifier"""
+ # TODO openstack if needed
return -vimconn.HTTP_Internal_Server_Error, "osconnector.new_external_port() not implemented"
def connect_port_network(self, port_id, network_id, admin=False):
- #TODO openstack if needed
- '''Connects a external port to a network'''
- '''Returns status code of the VIM response'''
+ """Connects a external port to a network
+ Returns status code of the VIM response"""
+ # TODO openstack if needed
return -vimconn.HTTP_Internal_Server_Error, "osconnector.connect_port_network() not implemented"
def new_user(self, user_name, user_passwd, tenant_id=None):
- '''Adds a new user to openstack VIM'''
- '''Returns the user identifier'''
+ """Adds a new user to openstack VIM
+ Returns the user identifier"""
self.logger.debug("osconnector: Adding a new user to VIM")
try:
self._reload_connection()
- user=self.keystone.users.create(user_name, password=user_passwd, default_project=tenant_id)
- #self.keystone.tenants.add_user(self.k_creds["username"], #role)
+ user = self.keystone.users.create(user_name, password=user_passwd, default_project=tenant_id)
+ # self.keystone.tenants.add_user(self.k_creds["username"], #role)
return user.id
except ksExceptions.ConnectionError as e:
- error_value=-vimconn.HTTP_Bad_Request
- error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0]))
- except ksExceptions.ClientException as e: #TODO remove
- error_value=-vimconn.HTTP_Bad_Request
- error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0]))
- #TODO insert exception vimconn.HTTP_Unauthorized
- #if reaching here is because an exception
+ error_value = -vimconn.HTTP_Bad_Request
+ error_text = type(e).__name__ + ": " + (str(e) if len(e.args) == 0 else str(e.args[0]))
+ except ksExceptions.ClientException as e: # TODO remove
+ error_value = -vimconn.HTTP_Bad_Request
+ error_text = type(e).__name__ + ": " + (str(e) if len(e.args) == 0 else str(e.args[0]))
+ # TODO insert exception vimconn.HTTP_Unauthorized
+ # if reaching here is because an exception
self.logger.debug("new_user " + error_text)
return error_value, error_text
def delete_user(self, user_id):
- '''Delete a user from openstack VIM'''
- '''Returns the user identifier'''
+ """Delete a user from openstack VIM
+ Returns the user identifier"""
if self.debug:
print("osconnector: Deleting a user from VIM")
try:
self.keystone.users.delete(user_id)
return 1, user_id
except ksExceptions.ConnectionError as e:
- error_value=-vimconn.HTTP_Bad_Request
- error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0]))
+ error_value = -vimconn.HTTP_Bad_Request
+ error_text = type(e).__name__ + ": " + (str(e) if len(e.args) == 0 else str(e.args[0]))
except ksExceptions.NotFound as e:
- error_value=-vimconn.HTTP_Not_Found
- error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0]))
- except ksExceptions.ClientException as e: #TODO remove
- error_value=-vimconn.HTTP_Bad_Request
- error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0]))
- #TODO insert exception vimconn.HTTP_Unauthorized
- #if reaching here is because an exception
- self.logger.debug("delete_tenant " + error_text)
+ error_value = -vimconn.HTTP_Not_Found
+ error_text = type(e).__name__ + ": " + (str(e) if len(e.args) == 0 else str(e.args[0]))
+ except ksExceptions.ClientException as e: # TODO remove
+ error_value = -vimconn.HTTP_Bad_Request
+ error_text = type(e).__name__ + ": " + (str(e) if len(e.args) == 0 else str(e.args[0]))
+ # TODO insert exception vimconn.HTTP_Unauthorized
+ # if reaching here is because an exception
+ self.logger.debug("delete_tenant " + error_text)
return error_value, error_text
def get_hosts_info(self):
- '''Get the information of deployed hosts
- Returns the hosts content'''
+ """Get the information of deployed hosts
+ Returns the hosts content"""
if self.debug:
print("osconnector: Getting Host info from VIM")
try:
- h_list=[]
+ h_list = []
self._reload_connection()
hypervisors = self.nova.hypervisors.list()
for hype in hypervisors:
- h_list.append( hype.to_dict() )
- return 1, {"hosts":h_list}
+ h_list.append(hype.to_dict())
+ return 1, {"hosts": h_list}
except nvExceptions.NotFound as e:
- error_value=-vimconn.HTTP_Not_Found
- error_text= (str(e) if len(e.args)==0 else str(e.args[0]))
+ error_value = -vimconn.HTTP_Not_Found
+ error_text = (str(e) if len(e.args) == 0 else str(e.args[0]))
except (ksExceptions.ClientException, nvExceptions.ClientException) as e:
- error_value=-vimconn.HTTP_Bad_Request
- error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0]))
- #TODO insert exception vimconn.HTTP_Unauthorized
- #if reaching here is because an exception
+ error_value = -vimconn.HTTP_Bad_Request
+ error_text = type(e).__name__ + ": " + (str(e) if len(e.args) == 0 else str(e.args[0]))
+ # TODO insert exception vimconn.HTTP_Unauthorized
+ # if reaching here is because an exception
self.logger.debug("get_hosts_info " + error_text)
return error_value, error_text
def get_hosts(self, vim_tenant):
- '''Get the hosts and deployed instances
- Returns the hosts content'''
+ """Get the hosts and deployed instances
+ Returns the hosts content"""
r, hype_dict = self.get_hosts_info()
- if r<0:
+ if r < 0:
return r, hype_dict
hypervisors = hype_dict["hosts"]
try:
servers = self.nova.servers.list()
for hype in hypervisors:
for server in servers:
- if server.to_dict()['OS-EXT-SRV-ATTR:hypervisor_hostname']==hype['hypervisor_hostname']:
+ if server.to_dict()['OS-EXT-SRV-ATTR:hypervisor_hostname'] == hype['hypervisor_hostname']:
if 'vm' in hype:
hype['vm'].append(server.id)
else:
hype['vm'] = [server.id]
return 1, hype_dict
except nvExceptions.NotFound as e:
- error_value=-vimconn.HTTP_Not_Found
- error_text= (str(e) if len(e.args)==0 else str(e.args[0]))
+ error_value = -vimconn.HTTP_Not_Found
+ error_text = (str(e) if len(e.args) == 0 else str(e.args[0]))
except (ksExceptions.ClientException, nvExceptions.ClientException) as e:
- error_value=-vimconn.HTTP_Bad_Request
- error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0]))
- #TODO insert exception vimconn.HTTP_Unauthorized
- #if reaching here is because an exception
+ error_value = -vimconn.HTTP_Bad_Request
+ error_text = type(e).__name__ + ": " + (str(e) if len(e.args) == 0 else str(e.args[0]))
+ # TODO insert exception vimconn.HTTP_Unauthorized
+ # if reaching here is because an exception
self.logger.debug("get_hosts " + error_text)
return error_value, error_text
self._reload_connection()
if ctype not in supportedClassificationTypes:
raise vimconn.VimConnNotSupportedException(
- 'OpenStack VIM connector doesn\'t support provided '
- 'Classification Type {}, supported ones are: '
- '{}'.format(ctype, supportedClassificationTypes))
+ 'OpenStack VIM connector does not support provided Classification Type {}, supported ones are: '
+ '{}'.format(ctype, supportedClassificationTypes))
if not self._validate_classification(ctype, definition):
raise vimconn.VimConnException(
'Incorrect Classification definition '
ConnectionError) as e:
self._format_exception(e)
-
def refresh_sfps_status(self, sfp_list):
- '''Get the status of the service function path
+ """Get the status of the service function path
Params: the list of sfp identifiers
Returns a dictionary with:
vm_id: #VIM id of this service function path
# CREATING (on building process)
error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
vim_info: #Text with plain information obtained from vim (yaml.safe_dump)F
- '''
- sfp_dict={}
+ """
+ sfp_dict = {}
self.logger.debug("refresh_sfps status: Getting tenant SFP information from VIM")
for sfp_id in sfp_list:
- sfp={}
+ sfp = {}
try:
sfp_vim = self.get_sfp(sfp_id)
if sfp_vim['spi']:
- sfp['status'] = vmStatus2manoFormat[ 'ACTIVE' ]
+ sfp['status'] = vmStatus2manoFormat['ACTIVE']
else:
- sfp['status'] = "OTHER"
- sfp['error_msg'] = "VIM status reported " + vm_vim['status']
+ sfp['status'] = "OTHER"
+ sfp['error_msg'] = "VIM status reported " + sfp['status']
sfp['vim_info'] = self.serialize(sfp_vim)
sfp_dict[sfp_id] = sfp
return sfp_dict
-
def refresh_sfis_status(self, sfi_list):
- '''Get the status of the service function instances
+ """Get the status of the service function instances
Params: the list of sfi identifiers
Returns a dictionary with:
vm_id: #VIM id of this service function instance
# CREATING (on building process)
error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
- '''
- sfi_dict={}
+ """
+ sfi_dict = {}
self.logger.debug("refresh_sfis status: Getting tenant sfi information from VIM")
for sfi_id in sfi_list:
- sfi={}
+ sfi = {}
try:
sfi_vim = self.get_sfi(sfi_id)
if sfi_vim:
- sfi['status'] = vmStatus2manoFormat[ 'ACTIVE' ]
+ sfi['status'] = vmStatus2manoFormat['ACTIVE']
else:
- sfi['status'] = "OTHER"
- sfi['error_msg'] = "VIM status reported " + vm_vim['status']
+ sfi['status'] = "OTHER"
+ sfi['error_msg'] = "VIM status reported " + sfi['status']
sfi['vim_info'] = self.serialize(sfi_vim)
sfi_dict[sfi_id] = sfi
return sfi_dict
-
def refresh_sfs_status(self, sf_list):
- '''Get the status of the service functions
+ """Get the status of the service functions
Params: the list of sf identifiers
Returns a dictionary with:
vm_id: #VIM id of this service function
# CREATING (on building process)
error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
- '''
- sf_dict={}
+ """
+ sf_dict = {}
self.logger.debug("refresh_sfs status: Getting tenant sf information from VIM")
for sf_id in sf_list:
- sf={}
+ sf = {}
try:
sf_vim = self.get_sf(sf_id)
if sf_vim:
- sf['status'] = vmStatus2manoFormat[ 'ACTIVE' ]
+ sf['status'] = vmStatus2manoFormat['ACTIVE']
else:
- sf['status'] = "OTHER"
- sf['error_msg'] = "VIM status reported " + vm_vim['status']
+ sf['status'] = "OTHER"
+ sf['error_msg'] = "VIM status reported " + sf_vim['status']
sf['vim_info'] = self.serialize(sf_vim)
sf_dict[sf_id] = sf
return sf_dict
-
-
def refresh_classifications_status(self, classification_list):
- '''Get the status of the classifications
+ """Get the status of the classifications
Params: the list of classification identifiers
Returns a dictionary with:
vm_id: #VIM id of this classifier
# CREATING (on building process)
error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
- '''
- classification_dict={}
+ """
+ classification_dict = {}
self.logger.debug("refresh_classifications status: Getting tenant classification information from VIM")
for classification_id in classification_list:
- classification={}
+ classification = {}
try:
classification_vim = self.get_classification(classification_id)
if classification_vim:
- classification['status'] = vmStatus2manoFormat[ 'ACTIVE' ]
+ classification['status'] = vmStatus2manoFormat['ACTIVE']
else:
- classification['status'] = "OTHER"
- classification['error_msg'] = "VIM status reported " + vm_vim['status']
+ classification['status'] = "OTHER"
+ classification['error_msg'] = "VIM status reported " + classification['status']
classification['vim_info'] = self.serialize(classification_vim)
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
# limitations under the License.
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
install_command = python3 -m pip install -r requirements.txt -U {opts} {packages}
-deps = -r{toxinidir}/test-requirements.txt
-commands=python3 -m unittest discover -v
[testenv:flake8]
basepython = python3
from copy import deepcopy
__author__ = "Alfonso Tierno"
-__date__ = "2020-04-20"
+__date__ = "2020-04-20"
class VimDummyConnector(vimconn.VimConnector):
else:
net = self.nets[net_id].copy()
net["vim_info"] = yaml.dump({"status": "ACTIVE", "name": net["name"]},
- default_flow_style=True, width=256)
+ default_flow_style=True, width=256)
nets[net_id] = net
return nets
return images
def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None, disk_list=None,
- availability_zone_index=None, availability_zone_list=None):
+ availability_zone_index=None, availability_zone_list=None):
vm_id = str(uuid4())
interfaces = []
for iface_index, iface in enumerate(net_list):
else:
vm = deepcopy(self.vms[vm_id])
vm["vim_info"] = yaml.dump({"status": "ACTIVE", "name": vm["name"]},
- default_flow_style=True, width=256)
+ default_flow_style=True, width=256)
vms[vm_id] = vm
return vms
##
[tox]
-envlist = py3
-toxworkdir={homedir}/.tox
+envlist = flake8
+toxworkdir={toxinidir}/../.tox
[testenv]
basepython = python3
[tox]
envlist = flake8
-toxworkdir={toxinidir}/.tox
+toxworkdir={toxinidir}/../.tox
[testenv]
usedevelop = True
# See the License for the specific language governing permissions and
# limitations under the License.
-tox -c RO/tox.ini
+for tox_file in `ls */tox.ini` ; do
+ [ "$tox_file" = "RO-client/tox.ini" ] || [ "$tox_file" = "RO-VIM-vmware/tox.ini" ] ||
+ [ "$tox_file" = "RO-VIM-openvim/tox.ini" ] || [ "$tox_file" = "build/tox.ini" ] && continue
+ echo
+ echo launching "$tox_file"
+ tox -c "$tox_file" --recreate || exit 1
+done