"""
self.manager = manager
self.name = network_config.name
- self.segmentation_id = self._get_item(network_config.segmentation_id, chain_id)
+ self.segmentation_id = self._get_item(network_config.segmentation_id,
+ chain_id, auto_index=True)
self.physical_network = self._get_item(network_config.physical_network, chain_id)
if chain_id is not None:
self.name += str(chain_id)
self.delete()
raise
- def _get_item(self, item_field, index):
+ def _get_item(self, item_field, index, auto_index=False):
"""Retrieve an item from a list or a single value.
item_field: can be None, a tuple of a single value
- index: if None is same as 0, else is the index in the list
+ index: if None is same as 0, else is the index for a chain
+ auto_index: if true will automatically get the final value by adding the
+ index to the base value (if full list not provided)
If the item_field is not a tuple, it is considered same as a tuple with same value at any
index.
if index is None:
index = 0
if isinstance(item_field, tuple):
- return item_field[index]
+ try:
+ return item_field[index]
+ except IndexError:
+ raise ChainException("List %s is too short for chain index %d" %
+ (str(item_field), index))
+ # single value is configured
+ if auto_index:
+ return item_field + index
return item_field
def _setup(self, network_config, lookup_only):
}
if network_config.network_type:
body['network']['provider:network_type'] = network_config.network_type
- if self.segmentation_id:
- body['network']['provider:segmentation_id'] = self.segmentation_id
- if self.physical_network:
- body['network']['provider:physical_network'] = self.physical_network
-
+ if self.segmentation_id:
+ body['network']['provider:segmentation_id'] = self.segmentation_id
+ if self.physical_network:
+ body['network']['provider:physical_network'] = self.physical_network
self.network = self.manager.neutron_client.create_network(body)['network']
body = {
'subnet': {'name': network_config.subnet,
subnet = self.manager.neutron_client.create_subnet(body)['subnet']
# add subnet id to the network dict since it has just been added
self.network['subnets'] = [subnet['id']]
- LOG.info('Created network: %s.', self.name)
+ LOG.info('Created network: %s', self.name)
def get_uuid(self):
"""
:return: VNI ID for this network
"""
- if self.network['provider:network_type'] != 'vxlan':
+ if 'vxlan' not in self.network['provider:network_type']:
raise ChainException('Trying to retrieve VNI for non VXLAN network')
return self.network['provider:segmentation_id']
def get_hostname(self):
"""Get the hypervisor host name running this VNF instance."""
- return getattr(self.instance, 'OS-EXT-SRV-ATTR:hypervisor_hostname')
+ if self.manager.is_admin:
+ hypervisor_hostname = getattr(self.instance, 'OS-EXT-SRV-ATTR:hypervisor_hostname')
+ else:
+ hypervisor_hostname = self.manager.config.hypervisor_hostname
+ if not hypervisor_hostname:
+ raise ChainException('Hypervisor hostname parameter is mandatory')
+ return hypervisor_hostname
def get_host_ip(self):
"""Get the IP address of the host where this instance runs.
def get_hypervisor_name(self):
"""Get hypervisor name (az:hostname) for this VNF instance."""
if self.instance:
- az = getattr(self.instance, 'OS-EXT-AZ:availability_zone')
+ if self.manager.is_admin:
+ az = getattr(self.instance, 'OS-EXT-AZ:availability_zone')
+ else:
+ az = self.manager.config.availability_zone
+ if not az:
+ raise ChainException('Availability zone parameter is mandatory')
hostname = self.get_hostname()
if az:
return az + ':' + hostname
if self.openstack:
# openstack only
session = chain_runner.cred.get_session()
+ self.is_admin = chain_runner.cred.is_admin
self.nova_client = Client(2, session=session)
self.neutron_client = neutronclient.Client('2.0', session=session)
self.glance_client = glanceclient.Client('2', session=session)
else:
# Make sure all instances are active before proceeding
self._ensure_instances_active()
+ # network API call do not show VLANS ID if not admin read from config
+ if not self.is_admin:
+ self._get_config_vlans()
except Exception:
self.delete()
raise
else:
# no openstack, no need to create chains
-
if not config.l2_loopback and config.no_arp:
self._get_dest_macs_from_config()
if config.vlan_tagging:
if len(config.vlans) != 2:
raise ChainException('The config vlans property must be a list '
'with 2 lists of VLAN IDs')
- re_vlan = "[0-9]*$"
- self.vlans = [self._check_list('vlans[0]', config.vlans[0], re_vlan),
- self._check_list('vlans[1]', config.vlans[1], re_vlan)]
+ self._get_config_vlans()
if config.vxlan:
- # make sure there are 2 entries
- if len(config.vnis) != 2:
- raise ChainException('The config vnis property must be a list with 2 VNIs')
- self.vnis = [self._check_list('vnis[0]', config.vnis[0], re_vlan),
- self._check_list('vnis[1]', config.vnis[1], re_vlan)]
+ raise ChainException('VxLAN is only supported with OpenStack')
+
+ def _get_config_vlans(self):
+ re_vlan = "[0-9]*$"
+ try:
+ self.vlans = [self._check_list('vlans[0]', self.config.vlans[0], re_vlan),
+ self._check_list('vlans[1]', self.config.vlans[1], re_vlan)]
+ except IndexError:
+ raise ChainException('vlans parameter is mandatory. Set valid value in config file')
def _get_dest_macs_from_config(self):
re_mac = "[0-9a-fA-F]{2}([-:])[0-9a-fA-F]{2}(\\1[0-9a-fA-F]{2}){4}$"
# if it is a single int or mac, make it a list of 1 int
if isinstance(ll, (int, str)):
ll = [ll]
- if not ll or len(ll) < self.chain_count:
- raise ChainException('%s=%s must be a list with %d elements per chain' %
- (list_name, ll, self.chain_count))
for item in ll:
if not re.match(pattern, str(item)):
raise ChainException("Invalid format '{item}' specified in {fname}"
.format(item=item, fname=list_name))
+ # must have at least 1 element
+ if not ll:
+ raise ChainException('%s cannot be empty' % (list_name))
+ # for shared network, if 1 element is passed, replicate it as many times
+ # as chains
+ if self.config.service_chain_shared_net and len(ll) == 1:
+ ll = [ll[0]] * self.chain_count
+
+ # number of elements musty be the number of chains
+ elif len(ll) < self.chain_count:
+ raise ChainException('%s=%s must be a list with %d elements per chain' %
+ (list_name, ll, self.chain_count))
return ll
def _setup_image(self):
if initial_instance_count:
LOG.info('All instances are active')
- def _get_vxlan_net_cfg(self, chain_id):
- int_nets = self.config.internal_networks
- net_left = int_nets.left
- net_right = int_nets.right
- vnis = self.generator_config.vnis
- chain_id += 1
- seg_id_left = vnis[0]
- if self.config.service_chain == ChainType.PVP:
- if chain_id > 1:
- seg_id_left = ((chain_id - 1) * 2) + seg_id_left
- seg_id_right = seg_id_left + 1
- if (seg_id_left and seg_id_right) > vnis[1]:
- raise Exception('Segmentation ID is more than allowed '
- 'value: {}'.format(vnis[1]))
- net_left['segmentation_id'] = seg_id_left
- net_right['segmentation_id'] = seg_id_right
- net_cfg = [net_left, net_right]
- else:
- # PVVP
- net_middle = int_nets.middle
- if chain_id > 1:
- seg_id_left = ((chain_id - 1) * 3) + seg_id_left
- seg_id_middle = seg_id_left + 1
- seg_id_right = seg_id_left + 2
- if (seg_id_left and seg_id_right and seg_id_middle) > vnis[1]:
- raise Exception('Segmentation ID is more than allowed '
- 'value: {}'.format(vnis[1]))
- net_left['segmentation_id'] = seg_id_left
- net_middle['segmentation_id'] = seg_id_middle
- net_right['segmentation_id'] = seg_id_right
- net_cfg = [net_left, net_middle, net_right]
- return net_cfg
-
def get_networks(self, chain_id=None):
"""Get the networks for given EXT, PVP or PVVP chain.
'segmentation_id': None,
'physical_network': None})
for name in [ext_net.left, ext_net.right]]
+ # segmentation id and subnet should be discovered from neutron
else:
lookup_only = False
int_nets = self.config.internal_networks
- network_type = set([int_nets[net].get('network_type') for net in int_nets])
- if self.config.vxlan and 'vxlan' in network_type:
- net_cfg = self._get_vxlan_net_cfg(chain_id)
+ # VLAN and VxLAN
+ if self.config.service_chain == ChainType.PVP:
+ net_cfg = [int_nets.left, int_nets.right]
else:
- # VLAN
- if self.config.service_chain == ChainType.PVP:
- net_cfg = [int_nets.left, int_nets.right]
- else:
- net_cfg = [int_nets.left, int_nets.middle, int_nets.right]
+ net_cfg = [int_nets.left, int_nets.middle, int_nets.right]
networks = []
try:
for cfg in net_cfg:
port_index: left port is 0, right port is 1
return: a VLAN ID list indexed by the chain index or None if no vlan tagging
"""
- if self.chains:
+ if self.chains and self.is_admin:
return [self.chains[chain_index].get_vlan(port_index)
for chain_index in range(self.chain_count)]
# no openstack
return [self.chains[chain_index].get_vxlan(port_index)
for chain_index in range(self.chain_count)]
# no openstack
- return self.vnis[port_index]
+ raise ChainException('VxLAN is only supported with OpenStack')
def get_dest_macs(self, port_index):
"""Get the list of per chain dest MACs on a given port.