else:
self.endpoint_type = None
+ logging.getLogger('urllib3').setLevel(logging.WARNING)
+ logging.getLogger('keystoneauth').setLevel(logging.WARNING)
+ logging.getLogger('novaclient').setLevel(logging.WARNING)
self.logger = logging.getLogger('openmano.vim.openstack')
# allow security_groups to be a list or a single string
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, vlan=None):
+ 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
'dhcp_start_address': ip_schema, first IP to grant
'dhcp_count': number of IPs to grant.
'shared': if this network can be seen/use by other tenants/organization
- 'vlan': in case of a data or ptp net_type, the intended vlan tag to be used for the network
+ 'provider_network_profile': (optional) contains {segmentation-id: vlan, network-type: vlan|vxlan,
+ physical-network: physnet-label}
Returns a tuple with the network 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_network. Can be used to store created segments, created l2gw connections, etc.
"""
self.logger.debug("Adding a new network to VIM name '%s', type '%s'", net_name, net_type)
# self.logger.debug(">>>>>>>>>>>>>>>>>> IP profile %s", str(ip_profile))
+
try:
+ vlan = None
+ if provider_network_profile:
+ vlan = provider_network_profile.get("segmentation-id")
new_net = None
created_items = {}
self._reload_connection()
network_dict = {'name': net_name, 'admin_state_up': True}
- if net_type=="data" or net_type=="ptp":
- if self.config.get('dataplane_physical_net') == None:
- raise vimconn.vimconnConflictException("You must provide a 'dataplane_physical_net' at config value before creating sriov network")
+ if net_type in ("data", "ptp"):
+ provider_physical_network = None
+ if provider_network_profile and provider_network_profile.get("physical-network"):
+ provider_physical_network = provider_network_profile.get("physical-network")
+ # provider-network must be one of the dataplane_physcial_netowrk if this is a list. If it is string
+ # or not declared, just ignore the checking
+ if isinstance(self.config.get('dataplane_physical_net'), (tuple, list)) and \
+ provider_physical_network not in self.config['dataplane_physical_net']:
+ raise vimconn.vimconnConflictException(
+ "Invalid parameter 'provider-network:physical-network' for network creation. '{}' is not "
+ "one of the declared list at VIM_config:dataplane_physical_net".format(
+ provider_physical_network))
+ if not provider_physical_network: # use the default dataplane_physical_net
+ provider_physical_network = self.config.get('dataplane_physical_net')
+ # if it is non empty list, use the first value. If it is a string use the value directly
+ if isinstance(provider_physical_network, (tuple, list)) and provider_physical_network:
+ provider_physical_network = provider_physical_network[0]
+
+ if not provider_physical_network:
+ raise vimconn.vimconnConflictException("You must provide a 'dataplane_physical_net' at VIM_config "
+ "for creating underlay networks. or use the NS instantiation"
+ " parameter provider-network:physical-network for the VLD")
+
if not self.config.get('multisegment_support'):
- network_dict["provider:physical_network"] = self.config[
- 'dataplane_physical_net'] # "physnet_sriov" #TODO physical
- network_dict["provider:network_type"] = "vlan"
- if vlan!=None:
- network_dict["provider:network_type"] = vlan
+ network_dict["provider:physical_network"] = provider_physical_network
+ 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')
+ if vlan:
+ network_dict["provider:segmentation_id"] = vlan
else:
- ###### Multi-segment case ######
+ # Multi-segment case
segment_list = []
- segment1_dict = {}
- segment1_dict["provider:physical_network"] = ''
- segment1_dict["provider:network_type"] = 'vxlan'
+ segment1_dict = {
+ "provider:physical_network": '',
+ "provider:network_type": 'vxlan'
+ }
segment_list.append(segment1_dict)
- segment2_dict = {}
- segment2_dict["provider:physical_network"] = self.config['dataplane_physical_net']
- segment2_dict["provider:network_type"] = "vlan"
- if self.config.get('multisegment_vlan_range'):
+ segment2_dict = {
+ "provider:physical_network": provider_physical_network,
+ "provider:network_type": "vlan"
+ }
+ if vlan:
+ segment2_dict["provider:segmentation_id"] = vlan
+ elif self.config.get('multisegment_vlan_range'):
vlanID = self._generate_multisegment_vlanID()
segment2_dict["provider:segmentation_id"] = vlanID
# else
segment_list.append(segment2_dict)
network_dict["segments"] = segment_list
- ####### VIO Specific Changes #########
- if self.vim_type == "VIO":
- if vlan is not None:
- network_dict["provider:segmentation_id"] = vlan
- else:
- if self.config.get('dataplane_net_vlan_range') is None:
- raise vimconn.vimconnConflictException("You must provide "\
- "'dataplane_net_vlan_range' in format [start_ID - end_ID]"\
- "at config value before creating sriov network with vlan tag")
-
- network_dict["provider:segmentation_id"] = self._generate_vlanID()
+ # VIO Specific Changes. It needs a concrete VLAN
+ if self.vim_type == "VIO" and vlan is None:
+ if self.config.get('dataplane_net_vlan_range') is None:
+ raise vimconn.vimconnConflictException(
+ "You must provide 'dataplane_net_vlan_range' in format [start_ID - end_ID] at VIM_config "
+ "for creating underlay networks")
+ network_dict["provider:segmentation_id"] = self._generate_vlanID()
network_dict["shared"] = shared
if self.config.get("disable_network_port_security"):
def process_resource_quota(self, quota, prefix, extra_specs):
"""
:param prefix:
- :param extra_specs:
+ :param extra_specs:
:return:
"""
if 'limit' in quota:
Returns:
vlanID
"""
- #Get used VLAN IDs
+ # Get used VLAN IDs
usedVlanIDs = []
networks = self.get_network_list()
for net in networks:
usedVlanIDs.append(segment.get('provider:segmentation_id'))
used_vlanIDs = set(usedVlanIDs)
- #find unused VLAN ID
+ # find unused VLAN ID
for vlanID_range in self.config.get('multisegment_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 VLAN segment."\
+ raise vimconn.vimconnConflictException("Unable to create the VLAN segment."
" All VLAN IDs {} are in use.".format(self.config.get('multisegment_vlan_range')))
ksExceptions.ClientException, neExceptions.NeutronException,
ConnectionError) as e:
self._format_exception(e)
+
+
+ def refresh_sfps_status(self, sfp_list):
+ '''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
+ status: #Mandatory. Text with one of:
+ # DELETED (not found at vim)
+ # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
+ # OTHER (Vim reported other status not understood)
+ # ERROR (VIM indicates an ERROR status)
+ # ACTIVE,
+ # 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={}
+ self.logger.debug("refresh_sfps status: Getting tenant SFP information from VIM")
+ for sfp_id in sfp_list:
+ sfp={}
+ try:
+ sfp_vim = self.get_sfp(sfp_id)
+ if sfp_vim['spi']:
+ sfp['status'] = vmStatus2manoFormat[ 'ACTIVE' ]
+ else:
+ sfp['status'] = "OTHER"
+ sfp['error_msg'] = "VIM status reported " + vm_vim['status']
+
+ sfp['vim_info'] = self.serialize(sfp_vim)
+
+ if sfp_vim.get('fault'):
+ sfp['error_msg'] = str(sfp_vim['fault'])
+
+ except vimconn.vimconnNotFoundException as e:
+ self.logger.error("Exception getting sfp status: %s", str(e))
+ sfp['status'] = "DELETED"
+ sfp['error_msg'] = str(e)
+ except vimconn.vimconnException as e:
+ self.logger.error("Exception getting sfp status: %s", str(e))
+ sfp['status'] = "VIM_ERROR"
+ sfp['error_msg'] = str(e)
+ sfp_dict[sfp_id] = sfp
+ return sfp_dict
+
+
+ def refresh_sfis_status(self, sfi_list):
+ '''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
+ status: #Mandatory. Text with one of:
+ # DELETED (not found at vim)
+ # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
+ # OTHER (Vim reported other status not understood)
+ # ERROR (VIM indicates an ERROR status)
+ # ACTIVE,
+ # 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={}
+ self.logger.debug("refresh_sfis status: Getting tenant sfi information from VIM")
+ for sfi_id in sfi_list:
+ sfi={}
+ try:
+ sfi_vim = self.get_sfi(sfi_id)
+ if sfi_vim:
+ sfi['status'] = vmStatus2manoFormat[ 'ACTIVE' ]
+ else:
+ sfi['status'] = "OTHER"
+ sfi['error_msg'] = "VIM status reported " + vm_vim['status']
+
+ sfi['vim_info'] = self.serialize(sfi_vim)
+
+ if sfi_vim.get('fault'):
+ sfi['error_msg'] = str(sfi_vim['fault'])
+
+ except vimconn.vimconnNotFoundException as e:
+ self.logger.error("Exception getting sfi status: %s", str(e))
+ sfi['status'] = "DELETED"
+ sfi['error_msg'] = str(e)
+ except vimconn.vimconnException as e:
+ self.logger.error("Exception getting sfi status: %s", str(e))
+ sfi['status'] = "VIM_ERROR"
+ sfi['error_msg'] = str(e)
+ sfi_dict[sfi_id] = sfi
+ return sfi_dict
+
+
+ def refresh_sfs_status(self, sf_list):
+ '''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
+ status: #Mandatory. Text with one of:
+ # DELETED (not found at vim)
+ # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
+ # OTHER (Vim reported other status not understood)
+ # ERROR (VIM indicates an ERROR status)
+ # ACTIVE,
+ # 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={}
+ self.logger.debug("refresh_sfs status: Getting tenant sf information from VIM")
+ for sf_id in sf_list:
+ sf={}
+ try:
+ sf_vim = self.get_sf(sf_id)
+ if sf_vim:
+ sf['status'] = vmStatus2manoFormat[ 'ACTIVE' ]
+ else:
+ sf['status'] = "OTHER"
+ sf['error_msg'] = "VIM status reported " + vm_vim['status']
+
+ sf['vim_info'] = self.serialize(sf_vim)
+
+ if sf_vim.get('fault'):
+ sf['error_msg'] = str(sf_vim['fault'])
+
+ except vimconn.vimconnNotFoundException as e:
+ self.logger.error("Exception getting sf status: %s", str(e))
+ sf['status'] = "DELETED"
+ sf['error_msg'] = str(e)
+ except vimconn.vimconnException as e:
+ self.logger.error("Exception getting sf status: %s", str(e))
+ sf['status'] = "VIM_ERROR"
+ sf['error_msg'] = str(e)
+ sf_dict[sf_id] = sf
+ return sf_dict
+
+
+
+ def refresh_classifications_status(self, classification_list):
+ '''Get the status of the classifications
+ Params: the list of classification identifiers
+ Returns a dictionary with:
+ vm_id: #VIM id of this classifier
+ status: #Mandatory. Text with one of:
+ # DELETED (not found at vim)
+ # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
+ # OTHER (Vim reported other status not understood)
+ # ERROR (VIM indicates an ERROR status)
+ # ACTIVE,
+ # 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={}
+ self.logger.debug("refresh_classifications status: Getting tenant classification information from VIM")
+ for classification_id in classification_list:
+ classification={}
+ try:
+ classification_vim = self.get_classification(classification_id)
+ if classification_vim:
+ classification['status'] = vmStatus2manoFormat[ 'ACTIVE' ]
+ else:
+ classification['status'] = "OTHER"
+ classification['error_msg'] = "VIM status reported " + vm_vim['status']
+
+ classification['vim_info'] = self.serialize(classification_vim)
+
+ if classification_vim.get('fault'):
+ classification['error_msg'] = str(classification_vim['fault'])
+
+ except vimconn.vimconnNotFoundException as e:
+ self.logger.error("Exception getting classification status: %s", str(e))
+ classification['status'] = "DELETED"
+ classification['error_msg'] = str(e)
+ except vimconn.vimconnException as e:
+ self.logger.error("Exception getting classification status: %s", str(e))
+ classification['status'] = "VIM_ERROR"
+ classification['error_msg'] = str(e)
+ classification_dict[classification_id] = classification
+ return classification_dict