aboutsummaryrefslogtreecommitdiffstats
path: root/os_net_config/objects.py
diff options
context:
space:
mode:
Diffstat (limited to 'os_net_config/objects.py')
-rw-r--r--os_net_config/objects.py246
1 files changed, 220 insertions, 26 deletions
diff --git a/os_net_config/objects.py b/os_net_config/objects.py
index 9815832..9b5523f 100644
--- a/os_net_config/objects.py
+++ b/os_net_config/objects.py
@@ -23,7 +23,7 @@ from os_net_config import utils
logger = logging.getLogger(__name__)
-_NUMBERED_NICS = None
+_MAPPED_NICS = None
class InvalidConfigException(ValueError):
@@ -42,16 +42,24 @@ def object_from_json(json):
return OvsBond.from_json(json)
elif obj_type == "linux_bond":
return LinuxBond.from_json(json)
+ elif obj_type == "team":
+ return LinuxTeam.from_json(json)
elif obj_type == "linux_bridge":
return LinuxBridge.from_json(json)
elif obj_type == "ivs_bridge":
return IvsBridge.from_json(json)
elif obj_type == "ivs_interface":
return IvsInterface.from_json(json)
+ elif obj_type == "nfvswitch_bridge":
+ return NfvswitchBridge.from_json(json)
+ elif obj_type == "nfvswitch_internal":
+ return NfvswitchInternal.from_json(json)
elif obj_type == "ovs_tunnel":
return OvsTunnel.from_json(json)
elif obj_type == "ovs_patch_port":
return OvsPatchPort.from_json(json)
+ elif obj_type == "ib_interface":
+ return IbInterface.from_json(json)
def _get_required_field(json, name, object_name):
@@ -63,21 +71,17 @@ def _get_required_field(json, name, object_name):
return field
-def _numbered_nics(nic_mapping=None):
+def _mapped_nics(nic_mapping=None):
mapping = nic_mapping or {}
- global _NUMBERED_NICS
- if _NUMBERED_NICS:
- return _NUMBERED_NICS
- _NUMBERED_NICS = {}
- count = 0
+ global _MAPPED_NICS
+ if _MAPPED_NICS:
+ return _MAPPED_NICS
+ _MAPPED_NICS = {}
active_nics = utils.ordered_active_nics()
- for nic in active_nics:
- count += 1
- nic_alias = "nic%i" % count
- nic_mapped = mapping.get(nic_alias, nic)
-
- # The mapping is either invalid, or specifies a mac
+ for nic_alias, nic_mapped in mapping.items():
if nic_mapped not in active_nics:
+ # The mapping is either invalid, or specifies a mac
+ is_mapping_valid = False
for active in active_nics:
try:
active_mac = utils.interface_mac(active)
@@ -86,25 +90,39 @@ def _numbered_nics(nic_mapping=None):
if nic_mapped == active_mac:
logger.debug("%s matches device %s" % (nic_mapped, active))
nic_mapped = active
+ is_mapping_valid = True
break
- else:
+
+ if not is_mapping_valid:
# The mapping can't specify a non-active or non-existent nic
- logger.warning('interface %s is not in an active nic (%s)'
+ logger.warning('interface %s is not an active nic (%s)'
% (nic_mapped, ', '.join(active_nics)))
continue
# Duplicate mappings are not allowed
- if nic_mapped in _NUMBERED_NICS.values():
+ if nic_mapped in _MAPPED_NICS.values():
msg = ('interface %s already mapped, '
'check mapping file for duplicates'
% nic_mapped)
raise InvalidConfigException(msg)
- _NUMBERED_NICS[nic_alias] = nic_mapped
+ _MAPPED_NICS[nic_alias] = nic_mapped
logger.info("%s mapped to: %s" % (nic_alias, nic_mapped))
- if not _NUMBERED_NICS:
+
+ # Add default numbered mappings, but do not overwrite existing entries
+ for nic_mapped in set(active_nics).difference(set(_MAPPED_NICS.values())):
+ nic_alias = "nic%i" % (active_nics.index(nic_mapped) + 1)
+ if nic_alias in _MAPPED_NICS:
+ logger.warning("no mapping for interface %s because "
+ "%s is mapped to %s"
+ % (nic_mapped, nic_alias, _MAPPED_NICS[nic_alias]))
+ else:
+ _MAPPED_NICS[nic_alias] = nic_mapped
+ logger.info("%s mapped to: %s" % (nic_alias, nic_mapped))
+
+ if not _MAPPED_NICS:
logger.warning('No active nics found.')
- return _NUMBERED_NICS
+ return _MAPPED_NICS
class Route(object):
@@ -150,18 +168,18 @@ class _BaseOpts(object):
addresses = addresses or []
routes = routes or []
dns_servers = dns_servers or []
- numbered_nic_names = _numbered_nics(nic_mapping)
+ mapped_nic_names = _mapped_nics(nic_mapping)
self.hwaddr = None
self.hwname = None
self.renamed = False
- if name in numbered_nic_names:
+ if name in mapped_nic_names:
if persist_mapping:
self.name = name
- self.hwname = numbered_nic_names[name]
+ self.hwname = mapped_nic_names[name]
self.hwaddr = utils.interface_mac(self.hwname)
self.renamed = True
else:
- self.name = numbered_nic_names[name]
+ self.name = mapped_nic_names[name]
else:
self.name = name
@@ -177,7 +195,9 @@ class _BaseOpts(object):
self.bridge_name = None # internal
self.linux_bridge_name = None # internal
self.ivs_bridge_name = None # internal
+ self.nfvswitch_bridge_name = None # internal
self.linux_bond_name = None # internal
+ self.linux_team_name = None # internal
self.ovs_port = False # internal
self.primary_interface_name = None # internal
@@ -287,9 +307,9 @@ class Vlan(_BaseOpts):
dns_servers)
self.vlan_id = int(vlan_id)
- numbered_nic_names = _numbered_nics(nic_mapping)
- if device in numbered_nic_names:
- self.device = numbered_nic_names[device]
+ mapped_nic_names = _mapped_nics(nic_mapping)
+ if device in mapped_nic_names:
+ self.device = mapped_nic_names[device]
else:
self.device = device
@@ -328,6 +348,32 @@ class IvsInterface(_BaseOpts):
return IvsInterface(vlan_id, name, *opts)
+class NfvswitchInternal(_BaseOpts):
+ """Base class for nfvswitch internal interfaces."""
+
+ def __init__(self, vlan_id, name='nfvswitch', use_dhcp=False,
+ use_dhcpv6=False, addresses=None, routes=None, mtu=1500,
+ primary=False, nic_mapping=None, persist_mapping=False,
+ defroute=True, dhclient_args=None, dns_servers=None):
+ addresses = addresses or []
+ routes = routes or []
+ dns_servers = dns_servers or []
+ name_vlan = '%s%i' % (name, vlan_id)
+ super(NfvswitchInternal, self).__init__(name_vlan, use_dhcp,
+ use_dhcpv6, addresses, routes,
+ mtu, primary, nic_mapping,
+ persist_mapping, defroute,
+ dhclient_args, dns_servers)
+ self.vlan_id = int(vlan_id)
+
+ @staticmethod
+ def from_json(json):
+ name = json.get('name')
+ vlan_id = _get_required_field(json, 'vlan_id', 'NfvswitchInternal')
+ opts = _BaseOpts.base_opts_from_json(json)
+ return NfvswitchInternal(vlan_id, name, *opts)
+
+
class OvsBridge(_BaseOpts):
"""Base class for OVS bridges."""
@@ -505,6 +551,132 @@ class IvsBridge(_BaseOpts):
dns_servers=dns_servers)
+class NfvswitchBridge(_BaseOpts):
+ """Base class for NFVSwitch bridges.
+
+ NFVSwitch is a virtual switch for Linux.
+ It is compatible with the KVM hypervisor and uses DPDK for packet
+ forwarding.
+ """
+
+ def __init__(self, name='nfvswitch', use_dhcp=False, use_dhcpv6=False,
+ addresses=None, routes=None, mtu=1500, members=None,
+ nic_mapping=None, persist_mapping=False, defroute=True,
+ dhclient_args=None, dns_servers=None, cpus=""):
+ addresses = addresses or []
+ routes = routes or []
+ members = members or []
+ dns_servers = dns_servers or []
+ super(NfvswitchBridge, self).__init__(name, use_dhcp, use_dhcpv6,
+ addresses, routes, mtu, False,
+ nic_mapping, persist_mapping,
+ defroute, dhclient_args,
+ dns_servers)
+ self.cpus = cpus
+ self.members = members
+ for member in self.members:
+ if isinstance(member, OvsBond) or isinstance(member, LinuxBond):
+ msg = 'NFVSwitch does not support bond interfaces.'
+ raise InvalidConfigException(msg)
+ member.nfvswitch_bridge_name = name
+ member.ovs_port = False
+ self.primary_interface_name = None
+
+ @staticmethod
+ def from_json(json):
+ name = 'nfvswitch'
+ (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
+ persist_mapping, defroute, dhclient_args,
+ dns_servers) = _BaseOpts.base_opts_from_json(
+ json, include_primary=False)
+
+ # members
+ members = []
+ members_json = json.get('members')
+ if members_json:
+ if isinstance(members_json, list):
+ for member in members_json:
+ members.append(object_from_json(member))
+ else:
+ msg = 'Members must be a list.'
+ raise InvalidConfigException(msg)
+
+ cpus = ''
+ cpus_json = json.get('cpus')
+ if cpus_json:
+ if isinstance(cpus_json, basestring):
+ cpus = cpus_json
+ else:
+ msg = '"cpus" must be a string of numbers separated by commas.'
+ raise InvalidConfigException(msg)
+ else:
+ msg = 'Config "cpus" is mandatory.'
+ raise InvalidConfigException(msg)
+
+ return NfvswitchBridge(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
+ addresses=addresses, routes=routes, mtu=mtu,
+ members=members, nic_mapping=nic_mapping,
+ persist_mapping=persist_mapping,
+ defroute=defroute, dhclient_args=dhclient_args,
+ dns_servers=dns_servers, cpus=cpus)
+
+
+class LinuxTeam(_BaseOpts):
+ """Base class for Linux bonds using teamd."""
+
+ def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
+ routes=None, mtu=None, primary=False, members=None,
+ bonding_options=None, nic_mapping=None, persist_mapping=False,
+ defroute=True, dhclient_args=None, dns_servers=None):
+ addresses = addresses or []
+ routes = routes or []
+ members = members or []
+ dns_servers = dns_servers or []
+ super(LinuxTeam, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
+ routes, mtu, primary, nic_mapping,
+ persist_mapping, defroute,
+ dhclient_args, dns_servers)
+ self.members = members
+ self.bonding_options = bonding_options
+ for member in self.members:
+ member.linux_team_name = name
+ if member.primary:
+ if self.primary_interface_name:
+ msg = 'Only one primary interface allowed per team.'
+ raise InvalidConfigException(msg)
+ if member.primary_interface_name:
+ self.primary_interface_name = member.primary_interface_name
+ else:
+ self.primary_interface_name = member.name
+
+ @staticmethod
+ def from_json(json):
+ name = _get_required_field(json, 'name', 'LinuxTeam')
+ (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
+ persist_mapping, defroute, dhclient_args,
+ dns_servers) = _BaseOpts.base_opts_from_json(
+ json, include_primary=False)
+ bonding_options = json.get('bonding_options')
+ members = []
+
+ # members
+ members_json = json.get('members')
+ if members_json:
+ if isinstance(members_json, list):
+ for member in members_json:
+ members.append(object_from_json(member))
+ else:
+ msg = 'Members must be a list.'
+ raise InvalidConfigException(msg)
+
+ return LinuxTeam(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
+ addresses=addresses, routes=routes, mtu=mtu,
+ members=members, bonding_options=bonding_options,
+ nic_mapping=nic_mapping,
+ persist_mapping=persist_mapping, defroute=defroute,
+ dhclient_args=dhclient_args, dns_servers=dns_servers)
+
+
class LinuxBond(_BaseOpts):
"""Base class for Linux bonds."""
@@ -689,3 +861,25 @@ class OvsPatchPort(_BaseOpts):
opts = _BaseOpts.base_opts_from_json(json)
return OvsPatchPort(name, *opts, bridge_name=bridge_name, peer=peer,
ovs_options=ovs_options, ovs_extra=ovs_extra)
+
+
+class IbInterface(_BaseOpts):
+ """Base class for InfiniBand network interfaces."""
+
+ def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
+ routes=None, mtu=None, primary=False, nic_mapping=None,
+ persist_mapping=False, defroute=True, dhclient_args=None,
+ dns_servers=None):
+ addresses = addresses or []
+ routes = routes or []
+ dns_servers = dns_servers or []
+ super(IbInterface, self).__init__(name, use_dhcp, use_dhcpv6,
+ addresses, routes, mtu, primary,
+ nic_mapping, persist_mapping,
+ defroute, dhclient_args, dns_servers)
+
+ @staticmethod
+ def from_json(json):
+ name = _get_required_field(json, 'name', 'IbInterface')
+ opts = _BaseOpts.base_opts_from_json(json)
+ return IbInterface(name, *opts)