os-vif/os_vif/internal/command/ip/linux/impl_pyroute2.py

113 lines
4.7 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
from oslo_utils import excutils
from pyroute2 import iproute
from pyroute2.netlink import exceptions as ipexc
from pyroute2.netlink.rtnl import ifinfmsg
from os_vif import exception
from os_vif.internal.command.ip import ip_command
from os_vif import utils
LOG = logging.getLogger(__name__)
class PyRoute2(ip_command.IpCommand):
def _ip_link(self, ip, command, check_exit_code, **kwargs):
try:
LOG.debug('pyroute2 command %(command)s, arguments %(args)s' %
{'command': command, 'args': kwargs})
return ip.link(command, **kwargs)
except ipexc.NetlinkError as e:
with excutils.save_and_reraise_exception() as ctx:
if e.code in check_exit_code:
LOG.error('NetlinkError was raised, code %s, message: %s' %
(e.code, str(e)))
ctx.reraise = False
def set(self, device, check_exit_code=None, state=None, mtu=None,
address=None, promisc=None, master=None):
check_exit_code = check_exit_code or []
with iproute.IPRoute() as ip:
idx = ip.link_lookup(ifname=device)
if not idx:
raise exception.NetworkInterfaceNotFound(interface=device)
idx = idx[0]
args = {'index': idx}
if state:
args['state'] = state
if mtu:
args['mtu'] = mtu
if address:
args['address'] = address
if promisc is not None:
flags = ip.link('get', index=idx)[0]['flags']
args['flags'] = (utils.set_mask(flags, ifinfmsg.IFF_PROMISC)
if promisc is True else
utils.unset_mask(flags, ifinfmsg.IFF_PROMISC))
if master:
args['master'] = master
if isinstance(check_exit_code, int):
check_exit_code = [check_exit_code]
return self._ip_link(ip, 'set', check_exit_code, **args)
def add(self, device, dev_type, check_exit_code=None, peer=None, link=None,
vlan_id=None):
check_exit_code = check_exit_code or []
with iproute.IPRoute() as ip:
args = {'ifname': device,
'kind': dev_type}
if self.TYPE_VLAN == dev_type:
args['vlan_id'] = vlan_id
idx = ip.link_lookup(ifname=link)
if 0 == len(idx):
raise exception.NetworkInterfaceNotFound(interface=link)
args['link'] = idx[0]
elif self.TYPE_VETH == dev_type:
args['peer'] = peer
elif self.TYPE_BRIDGE == dev_type:
# NOTE(sean-k-mooney): the keys are defined in the pyroute2
# codebase but are not documented. see the nla_map field
# in the bridge_data class located in the
# pyroute2.netlink.rtnl.ifinfmsg module for mode details
# https://github.com/svinota/pyroute2/blob/3ba9cdde34b2346ef8c2f8ba17cef5dbeb4c6d52/pyroute2/netlink/rtnl/ifinfmsg/__init__.py#L776-L820
args['IFLA_BR_AGEING_TIME'] = 0 # disable mac learning ageing
args['IFLA_BR_FORWARD_DELAY'] = 0 # set no delay
args['IFLA_BR_STP_STATE'] = 0 # disable spanning tree
args['IFLA_BR_MCAST_SNOOPING'] = 0 # disable snooping
else:
raise exception.NetworkInterfaceTypeNotDefined(type=dev_type)
return self._ip_link(ip, 'add', check_exit_code, **args)
def delete(self, device, check_exit_code=None):
check_exit_code = check_exit_code or []
with iproute.IPRoute() as ip:
idx = ip.link_lookup(ifname=device)
if len(idx) == 0:
raise exception.NetworkInterfaceNotFound(interface=device)
idx = idx[0]
return self._ip_link(ip, 'del', check_exit_code, **{'index': idx})
def exists(self, device):
"""Return True if the device exists."""
with iproute.IPRoute() as ip:
idx = ip.link_lookup(ifname=device)
return True if idx else False