"""Manage layer 3 interfaces on HPCOM7 devices.
"""
from pyhpecw7.utils.network import ipaddr
from pyhpecw7.features.interface import Interface
from pyhpecw7.features.errors import IpIfaceMissingData
from pyhpecw7.utils.xml.lib import *
V4 = 'v4'
V6 = 'v6'
[docs]class IpInterface(object):
"""This class is used to get and build layer 3
interface configurations on ``HPCOM7`` devices.
Args:
device (HPCOM7): connected instance of
a ``pyhpecw7.comware.HPCOM7`` object.
interface_name (str): The name of the interface.
version (str): V4 for IPv4, V6 for IPv6
Attributes:
device (HPCOM7): connected instance of
a ``pyhpecw7.comware.HPCOM7`` object.
interface_name (str): The name of the interface.
version (str): V4 for IPv4, V6 for IPv6
interface (pyhpecw7.features.Interface): The associated
``Interface`` configuration object.
is_routed (bool): ``True`` if the interface is in layer 3
mode, ``False`` otherwise.
"""
def __init__(self, device, interface_name, version=V4):
self.device = device
self.interface = Interface(device, interface_name)
self.interface_name = self.interface.interface_name
self.is_routed = self.interface.is_routed
self.version = version
[docs] def gen_ipv4_top(self):
E = data_element_maker()
top = E.top(
E.IPV4ADDRESS(
E.Ipv4Addresses(
E.Ipv4Address(
E.IfIndex(self.interface.iface_index),
E.Ipv4Address(),
E.Ipv4Mask(),
)
)
)
)
return top
[docs] def gen_ipv6_top(self):
E = data_element_maker()
top = E.top(
E.IPV6ADDRESS(
E.Ipv6Addresses(
E.AddressEntry(
E.IfIndex(self.interface.iface_index),
E.Ipv6Address(),
E.Ipv6PrefixLength(),
)
)
)
)
return top
[docs] def gen_ipv4_config(self, params, key_map, operation):
EN = nc_element_maker()
EC = config_element_maker()
config = EN.config(
EC.top(
EC.IPV4ADDRESS(
EC.Ipv4Addresses(
EC.Ipv4Address(
EC.IfIndex(self.interface.iface_index),
*config_params(params, key_map)
)
),
**operation_kwarg(operation)
)
)
)
return config
[docs] def gen_ipv6_config(self, params, key_map, operation):
EN = nc_element_maker()
EC = config_element_maker()
config = EN.config(
EC.top(
EC.IPV6ADDRESS(
EC.Ipv6AddressesConfig(
EC.AddressEntry(
EC.IfIndex(self.interface.iface_index),
*config_params(params, key_map)
)
),
**operation_kwarg(operation)
)
)
)
return config
[docs] def get_config(self):
"""Return a list of currently configured IP addresses on the interface.
Note:
Either only IPv4 or only IPv6 addresses will be returned depending
on the version stored in ``self.version``.
Returns:
A list of currently configured IP addresses on the interface.
"""
if self.version == V4:
top = self.gen_ipv4_top()
addr_tag = 'Ipv4Address'
mask_tag = 'Ipv4Mask'
search_tag = 'Ipv4Address'
elif self.version == V6:
top = self.gen_ipv6_top()
addr_tag = 'Ipv6Address'
mask_tag = 'Ipv6PrefixLength'
search_tag = 'AddressEntry'
else:
return {}
key_map = {'addr': addr_tag,
'mask': mask_tag}
nc_get_reply = self.device.get(('subtree', top))
reply_data = findall_in_data(search_tag, nc_get_reply.data_ele)
existing_list = []
for match in reply_data:
to_dict = data_elem_to_dict(match, key_map)
if to_dict:
existing_list.append(to_dict)
return existing_list
[docs] def build(self, stage=False, **params):
"""Stage or execute a configuration to configure
an IP address on an interface.
Args:
stage (bool): whether to stage the commands or execute
immediately
**params: see Keyword Args
Keyword Args:
addr (str): The IP address to add.
mask (str): The network mask for the IP address,
in dotted decimal or prefix length notation.
Returns:
True if stage=True and staging is successful
etree.Element XML response if immediate execution
"""
config = self._build_config(state='present', **params)
if stage:
return self.device.stage_config(config, 'edit_config')
else:
return self.device.edit_config(config)
[docs] def remove(self, stage=False, **params):
"""Stage or execute a configuration to remove
an IP address on an interface.
Args:
stage (bool): whether to stage the commands or execute
immediately
**params: see Keyword Args
Keyword Args:
addr (str): The IP address to remove.
mask (str): The network mask for the IP address,
in dotted decimal or prefix length notation.
Returns:
True if stage=True and staging is successful
etree.Element XML response if immediate execution
"""
config = self._build_config(state='absent', **params)
if stage:
return self.device.stage_config(config, 'edit_config')
else:
return self.device.edit_config(config)
def _build_config(self, state='present', **params):
"""Build an etree.Element object to configure or remove
an IP address on an interface.
Args:
state (str): 'present' to add an IP address,
'absent' to remove an IP address.
**params: see Keyword Args
Keyword Args:
addr (str): The IP address to add or remove.
mask (str): The network mask for the IP address,
in dotted decimal or prefix length notation.
Returns:
An etree.Element object to configure or remove
an IP address on an interface.
"""
address = params.get('addr')
mask = params.get('mask')
if not address or not mask:
raise IpIfaceMissingData
ip_obj = ipaddr.IPNetwork(address + '/' + mask)
if self.version == V4:
addr_tag = 'Ipv4Address'
mask_tag = 'Ipv4Mask'
params['mask'] = str(ip_obj.netmask)
elif self.version == V6:
addr_tag = 'Ipv6Address'
mask_tag = 'Ipv6PrefixLength'
params['mask'] = str(ip_obj.prefixlen)
params['addr_origin'] = '1'
else:
return
key_map = {'addr': addr_tag,
'mask': mask_tag,
'addr_origin': 'AddressOrigin'}
if state == 'present':
operation = 'merge'
elif state == 'absent':
operation = 'remove'
del params['mask']
if self.version == V4:
config = self.gen_ipv4_config(params, key_map, operation)
elif self.version == V6:
config = self.gen_ipv6_config(params, key_map, operation)
return config