Adding logging to file
It's important to support logging to a file for troubleshooting purpose. It's also important to rotate this file as it might grow quite large over time. Also, creating a common module where we can move gradually functions that are common to any other modules. We currently can't import utils from sriov_config for example because utils is already importing sriov_config. This leads to duplicate code which is harder to maintain. Change-Id: Ieafc2adc0247efc47130cd5ea29c59a140feaf0c
This commit is contained in:
parent
5ed22d9da4
commit
aa4ba26cf1
|
@ -16,11 +16,11 @@
|
|||
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
from os_net_config import common
|
||||
from os_net_config import impl_eni
|
||||
from os_net_config import impl_ifcfg
|
||||
from os_net_config import impl_iproute
|
||||
|
@ -29,7 +29,8 @@ from os_net_config import utils
|
|||
from os_net_config import validator
|
||||
from os_net_config import version
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = common.configure_logger()
|
||||
|
||||
_SYSTEM_CTL_CONFIG_FILE = '/etc/sysctl.d/os-net-sysctl.conf'
|
||||
|
||||
|
||||
|
@ -120,20 +121,6 @@ def parse_opts(argv):
|
|||
return opts
|
||||
|
||||
|
||||
def configure_logger(verbose=False, debug=False):
|
||||
LOG_FORMAT = '[%(asctime)s] [%(levelname)s] %(message)s'
|
||||
DATE_FORMAT = '%Y/%m/%d %I:%M:%S %p'
|
||||
log_level = logging.WARN
|
||||
|
||||
if debug:
|
||||
log_level = logging.DEBUG
|
||||
elif verbose:
|
||||
log_level = logging.INFO
|
||||
|
||||
logging.basicConfig(format=LOG_FORMAT, datefmt=DATE_FORMAT,
|
||||
level=log_level)
|
||||
|
||||
|
||||
def check_configure_sriov(obj):
|
||||
configure_sriov = False
|
||||
for member in obj.members:
|
||||
|
@ -163,10 +150,12 @@ def get_sriovpf_member_of_bond_ovs_port(obj):
|
|||
return net_devs_list
|
||||
|
||||
|
||||
def main(argv=sys.argv):
|
||||
def main(argv=sys.argv, main_logger=None):
|
||||
opts = parse_opts(argv)
|
||||
configure_logger(opts.verbose, opts.debug)
|
||||
logger.info('Using config file at: %s' % opts.config_file)
|
||||
if not main_logger:
|
||||
main_logger = common.configure_logger(log_file=not opts.noop)
|
||||
common.logger_level(main_logger, opts.verbose, opts.debug)
|
||||
main_logger.info(f"Using config file at: {opts.config_file}")
|
||||
iface_array = []
|
||||
configure_sriov = False
|
||||
sriovpf_member_of_bond_ovs_port_list = []
|
||||
|
@ -182,7 +171,7 @@ def main(argv=sys.argv):
|
|||
provider = impl_iproute.IPRouteNetConfig(noop=opts.noop,
|
||||
root_dir=opts.root_dir)
|
||||
else:
|
||||
logger.error('Invalid provider specified.')
|
||||
main_logger.error("Invalid provider specified.")
|
||||
return 1
|
||||
else:
|
||||
if os.path.exists('%s/etc/sysconfig/network-scripts/' % opts.root_dir):
|
||||
|
@ -192,22 +181,23 @@ def main(argv=sys.argv):
|
|||
provider = impl_eni.ENINetConfig(noop=opts.noop,
|
||||
root_dir=opts.root_dir)
|
||||
else:
|
||||
logger.error('Unable to set provider for this operating system.')
|
||||
main_logger.error("Unable to set provider for this operating "
|
||||
"system.")
|
||||
return 1
|
||||
|
||||
# Read the interface mapping file, if it exists
|
||||
# This allows you to override the default network naming abstraction
|
||||
# mappings by specifying a specific nicN->name or nicN->MAC mapping
|
||||
if os.path.exists(opts.mapping_file):
|
||||
logger.info('Using mapping file at: %s' % opts.mapping_file)
|
||||
main_logger.info(f"Using mapping file at: {opts.mapping_file}")
|
||||
with open(opts.mapping_file) as cf:
|
||||
iface_map = yaml.safe_load(cf.read())
|
||||
iface_mapping = iface_map.get("interface_mapping")
|
||||
logger.debug('interface_mapping JSON: %s' % str(iface_mapping))
|
||||
main_logger.debug(f"interface_mapping JSON: {str(iface_mapping)}")
|
||||
persist_mapping = opts.persist_mapping
|
||||
logger.debug('persist_mapping: %s' % persist_mapping)
|
||||
main_logger.debug(f"persist_mapping: {persist_mapping}")
|
||||
else:
|
||||
logger.info('Not using any mapping file.')
|
||||
main_logger.info("Not using any mapping file.")
|
||||
iface_mapping = None
|
||||
persist_mapping = False
|
||||
|
||||
|
@ -228,22 +218,22 @@ def main(argv=sys.argv):
|
|||
if requested_nic in mapped_nics.values():
|
||||
if found is True: # Name matches alias and real NIC
|
||||
# (return the mapped NIC, but warn of overlap).
|
||||
logger.warning('"%s" overlaps with real NIC name.'
|
||||
% (requested_nic))
|
||||
main_logger.warning(f"{requested_nic} overlaps with "
|
||||
"real NIC name.")
|
||||
else:
|
||||
reported_nics[requested_nic] = requested_nic
|
||||
found = True
|
||||
if not found:
|
||||
retval = 1
|
||||
if reported_nics:
|
||||
logger.debug("Interface mapping requested for interface: "
|
||||
"%s" % reported_nics.keys())
|
||||
main_logger.debug("Interface mapping requested for interface: "
|
||||
"%s" % reported_nics.keys())
|
||||
else:
|
||||
logger.debug("Interface mapping requested for all interfaces")
|
||||
main_logger.debug("Interface mapping requested for all interfaces")
|
||||
reported_nics = mapped_nics
|
||||
# Return the report on the mapped NICs. If all NICs were found, exit
|
||||
# cleanly, otherwise exit with status 1.
|
||||
logger.debug("Interface report requested, exiting after report.")
|
||||
main_logger.debug("Interface report requested, exiting after report.")
|
||||
print(reported_nics)
|
||||
return retval
|
||||
|
||||
|
@ -252,16 +242,17 @@ def main(argv=sys.argv):
|
|||
try:
|
||||
with open(opts.config_file) as cf:
|
||||
iface_array = yaml.safe_load(cf.read()).get("network_config")
|
||||
logger.debug('network_config JSON: %s' % str(iface_array))
|
||||
main_logger.debug(f"network_config JSON: {str(iface_array)}")
|
||||
except IOError:
|
||||
logger.error("Error reading file: %s" % opts.config_file)
|
||||
main_logger.error(f"Error reading file: {opts.config_file}")
|
||||
return 1
|
||||
else:
|
||||
logger.error('No config file exists at: %s' % opts.config_file)
|
||||
main_logger.error(f"No config file exists at: {opts.config_file}")
|
||||
return 1
|
||||
|
||||
if not isinstance(iface_array, list):
|
||||
logger.error('No interfaces defined in config: %s' % opts.config_file)
|
||||
main_logger.error("No interfaces defined in config: "
|
||||
f"{opts.config_file}")
|
||||
return 1
|
||||
|
||||
for iface_json in iface_array:
|
||||
|
@ -272,10 +263,10 @@ def main(argv=sys.argv):
|
|||
validation_errors = validator.validate_config(iface_array)
|
||||
if validation_errors:
|
||||
if opts.exit_on_validation_errors:
|
||||
logger.error('\n'.join(validation_errors))
|
||||
main_logger.error('\n'.join(validation_errors))
|
||||
return 1
|
||||
else:
|
||||
logger.warning('\n'.join(validation_errors))
|
||||
main_logger.warning('\n'.join(validation_errors))
|
||||
|
||||
# Look for the presence of SriovPF types in the first parse of the json
|
||||
# if SriovPFs exists then PF devices needs to be configured so that the VF
|
||||
|
@ -362,4 +353,4 @@ def main(argv=sys.argv):
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
||||
sys.exit(main(sys.argv, main_logger=logger))
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Red Hat, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
#
|
||||
# Common functions and variables meant to be shared across various modules
|
||||
# As opposed to utils, this is meant to be imported from anywhere. We can't
|
||||
# import anything from os_net_config here.
|
||||
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import sys
|
||||
|
||||
SYS_CLASS_NET = '/sys/class/net'
|
||||
_LOG_FILE = '/var/log/os-net-config.log'
|
||||
|
||||
|
||||
def configure_logger(log_file=False, verbose=False, debug=False):
|
||||
LOG_FORMAT = ('%(asctime)s.%(msecs)03d %(levelname)s '
|
||||
'%(name)s.%(funcName)s %(message)s')
|
||||
DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
|
||||
logger = logging.getLogger("os_net_config")
|
||||
logger.handlers.clear()
|
||||
logger_level(logger, verbose, debug)
|
||||
logger.propagate = True
|
||||
formatter = logging.Formatter(fmt=LOG_FORMAT, datefmt=DATE_FORMAT)
|
||||
if log_file:
|
||||
file_handler = logging.handlers.RotatingFileHandler(
|
||||
_LOG_FILE, maxBytes=10485760, backupCount=7
|
||||
)
|
||||
file_handler.setFormatter(formatter)
|
||||
logger.addHandler(file_handler)
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
stream_handler.setFormatter(formatter)
|
||||
logger.addHandler(stream_handler)
|
||||
return logger
|
||||
|
||||
|
||||
def logger_level(logger, verbose=False, debug=False):
|
||||
log_level = logging.WARN
|
||||
if debug:
|
||||
log_level = logging.DEBUG
|
||||
elif verbose:
|
||||
log_level = logging.INFO
|
||||
logger.setLevel(log_level)
|
||||
|
||||
|
||||
def get_dev_path(ifname, path=None):
|
||||
if not path:
|
||||
path = ""
|
||||
elif path.startswith("_"):
|
||||
path = path[1:]
|
||||
else:
|
||||
path = f"device/{path}"
|
||||
return os.path.join(SYS_CLASS_NET, ifname, path)
|
||||
|
||||
|
||||
def get_vendor_id(ifname):
|
||||
try:
|
||||
with open(get_dev_path(ifname, "vendor"), 'r') as f:
|
||||
out = f.read().strip()
|
||||
return out
|
||||
except IOError:
|
||||
return
|
||||
|
||||
|
||||
def get_device_id(ifname):
|
||||
try:
|
||||
with open(get_dev_path(ifname, 'device'), 'r') as f:
|
||||
out = f.read().strip()
|
||||
return out
|
||||
except IOError:
|
||||
return
|
|
@ -22,7 +22,6 @@
|
|||
# An entry point os-net-config-sriov is added for invocation of this module.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import pyudev
|
||||
import queue
|
||||
|
@ -31,11 +30,12 @@ import sys
|
|||
import time
|
||||
import yaml
|
||||
|
||||
from os_net_config import common
|
||||
from os_net_config import sriov_bind_config
|
||||
from oslo_concurrency import processutils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
_SYS_CLASS_NET = '/sys/class/net'
|
||||
logger = common.configure_logger()
|
||||
|
||||
_UDEV_RULE_FILE = '/etc/udev/rules.d/80-persistent-os-net-config.rules'
|
||||
_UDEV_LEGACY_RULE_FILE = '/etc/udev/rules.d/70-os-net-config-sriov.rules'
|
||||
_IFUP_LOCAL_FILE = '/sbin/ifup-local'
|
||||
|
@ -112,11 +112,6 @@ def _get_sriov_map():
|
|||
return sriov_map
|
||||
|
||||
|
||||
def _get_dev_path(ifname, path=None):
|
||||
path = f"device/{path}" if path else "device"
|
||||
return os.path.join(_SYS_CLASS_NET, ifname, path)
|
||||
|
||||
|
||||
def _wait_for_vf_creation(pf_name, numvfs):
|
||||
vf_count = 0
|
||||
vf_list = []
|
||||
|
@ -155,7 +150,7 @@ def get_numvfs(ifname):
|
|||
:returns: int -- the number of current VFs on ifname
|
||||
:raises: SRIOVNumvfsException
|
||||
"""
|
||||
sriov_numvfs_path = _get_dev_path(ifname, "sriov_numvfs")
|
||||
sriov_numvfs_path = common.get_dev_path(ifname, "sriov_numvfs")
|
||||
logger.debug(f"Getting numvfs for interface {ifname}")
|
||||
try:
|
||||
with open(sriov_numvfs_path, 'r') as f:
|
||||
|
@ -198,7 +193,7 @@ def set_numvfs(ifname, numvfs):
|
|||
f"{ifname}")
|
||||
return curr_numvfs
|
||||
|
||||
sriov_numvfs_path = _get_dev_path(ifname, "sriov_numvfs")
|
||||
sriov_numvfs_path = common.get_dev_path(ifname, "sriov_numvfs")
|
||||
try:
|
||||
logger.debug(f"Setting {sriov_numvfs_path} to {numvfs}")
|
||||
with open(sriov_numvfs_path, "w") as f:
|
||||
|
@ -305,7 +300,7 @@ def configure_sriov_pf(execution_from_cli=False, restart_openvswitch=False):
|
|||
item['numvfs'])
|
||||
# When configuring vdpa, we need to configure switchdev before
|
||||
# we create the VFs
|
||||
vendor_id = get_vendor_id(item['name'])
|
||||
vendor_id = common.get_vendor_id(item['name'])
|
||||
is_mlnx = vendor_id == MLNX_VENDOR_ID
|
||||
# Configure switchdev mode when vdpa
|
||||
if item.get('vdpa') and is_mlnx:
|
||||
|
@ -407,7 +402,7 @@ def add_udev_rule_for_legacy_sriov_pf(pf_name, numvfs):
|
|||
|
||||
def add_udev_rule_for_vf_representors(pf_name):
|
||||
logger.info(f"adding udev rules for vf representators {pf_name}")
|
||||
phys_switch_id_path = os.path.join(_SYS_CLASS_NET, pf_name,
|
||||
phys_switch_id_path = os.path.join(common.SYS_CLASS_NET, pf_name,
|
||||
"phys_switch_id")
|
||||
phys_switch_id = get_file_data(phys_switch_id_path).strip()
|
||||
pf_pci = get_pf_pci(pf_name)
|
||||
|
@ -553,35 +548,26 @@ def _pf_interface_up(pf_device):
|
|||
run_ip_config_cmd('ip', 'link', 'set', 'dev', pf_device['name'], 'up')
|
||||
|
||||
|
||||
def get_vendor_id(ifname):
|
||||
try:
|
||||
with open(_get_dev_path(ifname, "vendor"), 'r') as f:
|
||||
out = f.read().strip()
|
||||
return out
|
||||
except IOError:
|
||||
return
|
||||
|
||||
|
||||
def get_pf_pci(pf_name):
|
||||
pf_pci_path = _get_dev_path(pf_name, "uevent")
|
||||
pf_pci_path = common.get_dev_path(pf_name, "uevent")
|
||||
pf_info = get_file_data(pf_pci_path)
|
||||
pf_pci = re.search(r'PCI_SLOT_NAME=(.*)', pf_info, re.MULTILINE).group(1)
|
||||
return pf_pci
|
||||
|
||||
|
||||
def get_pf_device_id(pf_name):
|
||||
pf_device_path = _get_dev_path(pf_name, "device")
|
||||
pf_device_path = common.get_dev_path(pf_name, "device")
|
||||
pf_device_id = get_file_data(pf_device_path).strip()
|
||||
return pf_device_id
|
||||
|
||||
|
||||
def get_vf_pcis_list(pf_name):
|
||||
vf_pcis_list = []
|
||||
listOfPfFiles = os.listdir(os.path.join(_SYS_CLASS_NET, pf_name,
|
||||
listOfPfFiles = os.listdir(os.path.join(common.SYS_CLASS_NET, pf_name,
|
||||
"device"))
|
||||
for pf_file in listOfPfFiles:
|
||||
if pf_file.startswith("virtfn"):
|
||||
vf_info = get_file_data(_get_dev_path(pf_name,
|
||||
vf_info = get_file_data(common.get_dev_path(pf_name,
|
||||
f"{pf_file}/uevent"))
|
||||
vf_pcis_list.append(re.search(r'PCI_SLOT_NAME=(.*)',
|
||||
vf_info, re.MULTILINE).group(1))
|
||||
|
@ -675,30 +661,18 @@ def parse_opts(argv):
|
|||
return opts
|
||||
|
||||
|
||||
def configure_logger(verbose=False, debug=False):
|
||||
LOG_FORMAT = '[%(asctime)s] [%(levelname)s] %(message)s'
|
||||
DATE_FORMAT = '%Y/%m/%d %I:%M:%S %p'
|
||||
log_level = logging.WARN
|
||||
|
||||
if debug:
|
||||
log_level = logging.DEBUG
|
||||
elif verbose:
|
||||
log_level = logging.INFO
|
||||
|
||||
logging.basicConfig(format=LOG_FORMAT, datefmt=DATE_FORMAT,
|
||||
level=log_level)
|
||||
|
||||
|
||||
def main(argv=sys.argv):
|
||||
def main(argv=sys.argv, main_logger=None):
|
||||
opts = parse_opts(argv)
|
||||
configure_logger(opts.verbose, opts.debug)
|
||||
if not main_logger:
|
||||
main_logger = common.configure_logger(log_file=True)
|
||||
common.logger_level(main_logger, opts.verbose, opts.debug)
|
||||
|
||||
if opts.numvfs:
|
||||
if re.match(r"^\w+:\d+$", opts.numvfs):
|
||||
device_name, numvfs = opts.numvfs.split(':')
|
||||
set_numvfs(device_name, int(numvfs))
|
||||
else:
|
||||
logging.error(f"Invalid arguments for --numvfs {opts.numvfs}")
|
||||
main_logger.error(f"Invalid arguments for --numvfs {opts.numvfs}")
|
||||
return 1
|
||||
else:
|
||||
# Configure the PF's
|
||||
|
|
|
@ -17,11 +17,13 @@
|
|||
from io import StringIO
|
||||
import os.path
|
||||
import random
|
||||
import re
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
import os_net_config
|
||||
from os_net_config import cli
|
||||
from os_net_config import common
|
||||
from os_net_config import sriov_config
|
||||
from os_net_config.tests import base
|
||||
from os_net_config import utils
|
||||
|
@ -38,6 +40,9 @@ class TestCli(base.TestCase):
|
|||
super(TestCli, self).setUp()
|
||||
rand = str(int(random.random() * 100000))
|
||||
sriov_config._SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
|
||||
common._LOG_FILE = '/tmp/' + rand + 'os_net_config.log'
|
||||
sys.stdout = StringIO()
|
||||
sys.stderr = StringIO()
|
||||
|
||||
def stub_is_ovs_installed():
|
||||
return True
|
||||
|
@ -46,24 +51,22 @@ class TestCli(base.TestCase):
|
|||
|
||||
def tearDown(self):
|
||||
super(TestCli, self).tearDown()
|
||||
if os.path.isfile(common._LOG_FILE):
|
||||
os.remove(common._LOG_FILE)
|
||||
if os.path.isfile(sriov_config._SRIOV_CONFIG_FILE):
|
||||
os.remove(sriov_config._SRIOV_CONFIG_FILE)
|
||||
|
||||
def run_cli(self, argstr, exitcodes=(0,)):
|
||||
orig = sys.stdout
|
||||
orig_stderr = sys.stderr
|
||||
|
||||
sys.stdout = StringIO()
|
||||
sys.stderr = StringIO()
|
||||
for s in [sys.stdout, sys.stderr]:
|
||||
s.flush()
|
||||
s.truncate(0)
|
||||
s.seek(0)
|
||||
ret = cli.main(argstr.split())
|
||||
self.assertIn(ret, exitcodes)
|
||||
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
stdout = sys.stdout.getvalue()
|
||||
sys.stdout.close()
|
||||
sys.stdout = orig
|
||||
stderr = sys.stderr.getvalue()
|
||||
sys.stderr.close()
|
||||
sys.stderr = orig_stderr
|
||||
return (stdout, stderr)
|
||||
|
||||
def stub_get_stored_pci_address(self, ifname, noop):
|
||||
|
@ -420,6 +423,11 @@ class TestCli(base.TestCase):
|
|||
self.assertEqual(stdout_yaml, stdout_json)
|
||||
|
||||
def test_contrail_vrouter_dpdk_noop_output(self):
|
||||
timestamp_rex = re.compile(
|
||||
(r'contrail_vrouter_dpdk\.(yaml|json)|^[\d]{4}-[\d]{2}-[\d]{2} '
|
||||
r'[\d]{2}:[\d]{2}:[\d]{2}\.[\d]{3} '),
|
||||
flags=re.M
|
||||
)
|
||||
cvi_yaml = os.path.join(SAMPLE_BASE, 'contrail_vrouter_dpdk.yaml')
|
||||
cvi_json = os.path.join(SAMPLE_BASE, 'contrail_vrouter_dpdk.json')
|
||||
self.stub_out('os_net_config.utils.get_stored_pci_address',
|
||||
|
@ -440,4 +448,6 @@ class TestCli(base.TestCase):
|
|||
'TYPE=dpdk']
|
||||
for dev in sanity_devices:
|
||||
self.assertIn(dev, stdout_yaml)
|
||||
stdout_yaml = timestamp_rex.sub('', stdout_yaml)
|
||||
stdout_json = timestamp_rex.sub('', stdout_json)
|
||||
self.assertEqual(stdout_yaml, stdout_json)
|
||||
|
|
|
@ -21,6 +21,7 @@ import shutil
|
|||
import tempfile
|
||||
|
||||
|
||||
from os_net_config import common
|
||||
from os_net_config import sriov_config
|
||||
from os_net_config.tests import base
|
||||
from os_net_config import utils
|
||||
|
@ -34,8 +35,9 @@ class TestSriovConfig(base.TestCase):
|
|||
rand = str(int(random.random() * 100000))
|
||||
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.sriov_config._SYS_CLASS_NET', tmpdir)
|
||||
self.stub_out('os_net_config.common.SYS_CLASS_NET', tmpdir)
|
||||
|
||||
common._LOG_FILE = '/tmp/' + rand + 'os_net_config.log'
|
||||
sriov_config._UDEV_RULE_FILE = '/tmp/' + rand + 'etc_udev_rules.d'\
|
||||
'80-persistent-os-net-config.rules'
|
||||
sriov_config._UDEV_LEGACY_RULE_FILE = '/tmp/' + rand + 'etc_udev_'\
|
||||
|
@ -50,11 +52,13 @@ class TestSriovConfig(base.TestCase):
|
|||
|
||||
def tearDown(self):
|
||||
super(TestSriovConfig, self).tearDown()
|
||||
if os.path.isfile(common._LOG_FILE):
|
||||
os.remove(common._LOG_FILE)
|
||||
if os.path.isfile(sriov_config._SRIOV_CONFIG_FILE):
|
||||
os.remove(sriov_config._SRIOV_CONFIG_FILE)
|
||||
if os.path.isfile(sriov_config._IFUP_LOCAL_FILE):
|
||||
os.remove(sriov_config._IFUP_LOCAL_FILE)
|
||||
shutil.rmtree(sriov_config._SYS_CLASS_NET)
|
||||
shutil.rmtree(common.SYS_CLASS_NET)
|
||||
if os.path.isfile(sriov_config._RESET_SRIOV_RULES_FILE):
|
||||
os.remove(sriov_config._RESET_SRIOV_RULES_FILE)
|
||||
if os.path.isfile(sriov_config._ALLOCATE_VFS_FILE):
|
||||
|
@ -63,8 +67,8 @@ class TestSriovConfig(base.TestCase):
|
|||
os.remove(sriov_config._UDEV_LEGACY_RULE_FILE)
|
||||
|
||||
def _write_numvfs(self, ifname, numvfs=0):
|
||||
os.makedirs(sriov_config._get_dev_path(ifname))
|
||||
numvfs_file = sriov_config._get_dev_path(ifname, 'sriov_numvfs')
|
||||
os.makedirs(common.get_dev_path(ifname, '_device'))
|
||||
numvfs_file = common.get_dev_path(ifname, 'sriov_numvfs')
|
||||
with open(numvfs_file, 'w') as f:
|
||||
f.write(str(numvfs))
|
||||
|
||||
|
@ -250,7 +254,7 @@ class TestSriovConfig(base.TestCase):
|
|||
|
||||
def get_vendor_id_stub(ifname):
|
||||
return vendor_id
|
||||
self.stub_out('os_net_config.sriov_config.get_vendor_id',
|
||||
self.stub_out('os_net_config.common.get_vendor_id',
|
||||
get_vendor_id_stub)
|
||||
|
||||
def configure_switchdev_stub(pf_name):
|
||||
|
@ -311,7 +315,6 @@ class TestSriovConfig(base.TestCase):
|
|||
|
||||
self._action_order = []
|
||||
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_config)
|
||||
sriov_config.configure_logger(debug=True)
|
||||
sriov_config.configure_sriov_pf()
|
||||
self.assertEqual(exp_actions, self._action_order)
|
||||
f = open(sriov_config._UDEV_LEGACY_RULE_FILE, 'r')
|
||||
|
@ -358,7 +361,6 @@ class TestSriovConfig(base.TestCase):
|
|||
|
||||
self._action_order = []
|
||||
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_config)
|
||||
sriov_config.configure_logger(debug=True)
|
||||
sriov_config.configure_sriov_pf()
|
||||
self.assertEqual(exp_actions, self._action_order)
|
||||
f = open(sriov_config._UDEV_LEGACY_RULE_FILE, 'r')
|
||||
|
@ -406,7 +408,6 @@ class TestSriovConfig(base.TestCase):
|
|||
|
||||
self._action_order = []
|
||||
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_config)
|
||||
sriov_config.configure_logger(debug=True)
|
||||
sriov_config.configure_sriov_pf()
|
||||
self.assertEqual(exp_actions, self._action_order)
|
||||
f = open(sriov_config._UDEV_LEGACY_RULE_FILE, 'r')
|
||||
|
@ -446,7 +447,6 @@ class TestSriovConfig(base.TestCase):
|
|||
|
||||
self._action_order = []
|
||||
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_config)
|
||||
sriov_config.configure_logger(debug=True)
|
||||
sriov_config.configure_sriov_pf()
|
||||
self.assertEqual(exp_actions, self._action_order)
|
||||
self.assertEqual(10, sriov_config.get_numvfs('p2p1'))
|
||||
|
|
|
@ -22,6 +22,7 @@ import tempfile
|
|||
from unittest import mock
|
||||
import yaml
|
||||
|
||||
from os_net_config import common
|
||||
from os_net_config import objects
|
||||
from os_net_config import sriov_config
|
||||
from os_net_config.tests import base
|
||||
|
@ -29,6 +30,7 @@ from os_net_config import utils
|
|||
|
||||
from oslo_concurrency import processutils
|
||||
|
||||
|
||||
_PCI_OUTPUT = '''driver: e1000e
|
||||
version: 3.2.6-k
|
||||
firmware-version: 0.13-3
|
||||
|
@ -102,7 +104,7 @@ class TestUtils(base.TestCase):
|
|||
def test_ordered_active_nics(self):
|
||||
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_CLASS_NET', tmpdir)
|
||||
self.stub_out('os_net_config.common.SYS_CLASS_NET', tmpdir)
|
||||
|
||||
def test_is_available_nic(interface_name, check_active):
|
||||
return True
|
||||
|
@ -355,7 +357,7 @@ class TestUtils(base.TestCase):
|
|||
|
||||
def test_get_vf_devname_net_dir_not_found(self):
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_CLASS_NET', tmpdir)
|
||||
self.stub_out('os_net_config.common.SYS_CLASS_NET', tmpdir)
|
||||
|
||||
self.assertRaises(utils.SriovVfNotFoundException,
|
||||
utils.get_vf_devname, "eth1", 1)
|
||||
|
@ -363,14 +365,14 @@ class TestUtils(base.TestCase):
|
|||
|
||||
def test_get_vf_devname_vf_dir_found_in_map(self):
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_CLASS_NET', tmpdir)
|
||||
self.stub_out('os_net_config.common.SYS_CLASS_NET', tmpdir)
|
||||
|
||||
def test_get_vf_name_from_map(pf_name, vfid):
|
||||
return pf_name + '_' + str(vfid)
|
||||
self.stub_out('os_net_config.utils._get_vf_name_from_map',
|
||||
test_get_vf_name_from_map)
|
||||
|
||||
vf_path = os.path.join(utils._SYS_CLASS_NET, 'eth1/device/virtfn1')
|
||||
vf_path = os.path.join(common.SYS_CLASS_NET, 'eth1/device/virtfn1')
|
||||
os.makedirs(vf_path)
|
||||
|
||||
self.assertEqual(utils.get_vf_devname("eth1", 1), "eth1_1")
|
||||
|
@ -378,14 +380,14 @@ class TestUtils(base.TestCase):
|
|||
|
||||
def test_get_vf_devname_vf_dir_not_found(self):
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_CLASS_NET', tmpdir)
|
||||
self.stub_out('os_net_config.common.SYS_CLASS_NET', tmpdir)
|
||||
|
||||
def test_get_vf_name_from_map(pf_name, vfid):
|
||||
return None
|
||||
self.stub_out('os_net_config.utils._get_vf_name_from_map',
|
||||
test_get_vf_name_from_map)
|
||||
|
||||
vf_path = os.path.join(utils._SYS_CLASS_NET, 'eth1/device/virtfn1')
|
||||
vf_path = os.path.join(common.SYS_CLASS_NET, 'eth1/device/virtfn1')
|
||||
os.makedirs(vf_path)
|
||||
|
||||
self.assertRaises(utils.SriovVfNotFoundException,
|
||||
|
@ -394,9 +396,9 @@ class TestUtils(base.TestCase):
|
|||
|
||||
def test_get_vf_devname_vf_dir_found(self):
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_CLASS_NET', tmpdir)
|
||||
self.stub_out('os_net_config.common.SYS_CLASS_NET', tmpdir)
|
||||
|
||||
vf_path = os.path.join(utils._SYS_CLASS_NET,
|
||||
vf_path = os.path.join(common.SYS_CLASS_NET,
|
||||
'eth1/device/virtfn1/net/eth1_1')
|
||||
os.makedirs(vf_path)
|
||||
|
||||
|
@ -448,28 +450,28 @@ class TestUtils(base.TestCase):
|
|||
|
||||
def test_get_vendor_id_success(self):
|
||||
mocked_open = mock.mock_open(read_data='0x15b3\n')
|
||||
with mock.patch('os_net_config.utils.open', mocked_open, create=True):
|
||||
vendor = utils.get_vendor_id('nic2')
|
||||
with mock.patch('os_net_config.common.open', mocked_open, create=True):
|
||||
vendor = common.get_vendor_id('nic2')
|
||||
self.assertEqual('0x15b3', vendor)
|
||||
|
||||
def test_get_vendor_id_exception(self):
|
||||
mocked_open = mock.mock_open()
|
||||
mocked_open.side_effect = IOError
|
||||
with mock.patch('os_net_config.utils.open', mocked_open, create=True):
|
||||
vendor = utils.get_vendor_id('nic2')
|
||||
with mock.patch('os_net_config.common.open', mocked_open, create=True):
|
||||
vendor = common.get_vendor_id('nic2')
|
||||
self.assertEqual(None, vendor)
|
||||
|
||||
def test_get_device_id_success(self):
|
||||
mocked_open = mock.mock_open(read_data='0x1003\n')
|
||||
with mock.patch('os_net_config.utils.open', mocked_open, create=True):
|
||||
device = utils.get_device_id('nic2')
|
||||
with mock.patch('os_net_config.common.open', mocked_open, create=True):
|
||||
device = common.get_device_id('nic2')
|
||||
self.assertEqual('0x1003', device)
|
||||
|
||||
def test_get_device_id_exception(self):
|
||||
mocked_open = mock.mock_open()
|
||||
mocked_open.side_effect = IOError
|
||||
with mock.patch('os_net_config.utils.open', mocked_open, create=True):
|
||||
device = utils.get_device_id('nic2')
|
||||
device = common.get_device_id('nic2')
|
||||
self.assertEqual(None, device)
|
||||
|
||||
def test_bind_dpdk_interfaces(self):
|
||||
|
@ -636,7 +638,7 @@ class TestUtils(base.TestCase):
|
|||
def test_ordered_active_nics_with_dpdk_mapping(self):
|
||||
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_CLASS_NET', tmpdir)
|
||||
self.stub_out('os_net_config.common.SYS_CLASS_NET', tmpdir)
|
||||
tmp_pci_dir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_BUS_PCI_DEV', tmp_pci_dir)
|
||||
physfn_path = utils._SYS_BUS_PCI_DEV + '/0000:05:01.1/physfn'
|
||||
|
@ -677,7 +679,7 @@ class TestUtils(base.TestCase):
|
|||
|
||||
def test_ordered_active_nics_with_dpdk_mapping_of_vf(self):
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_CLASS_NET', tmpdir)
|
||||
self.stub_out('os_net_config.common.SYS_CLASS_NET', tmpdir)
|
||||
tmp_pci_dir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_BUS_PCI_DEV', tmp_pci_dir)
|
||||
physfn_path = utils._SYS_BUS_PCI_DEV + '/0000:05:01.1/physfn'
|
||||
|
@ -721,7 +723,7 @@ class TestUtils(base.TestCase):
|
|||
self.stub_out('os_net_config.utils.get_stored_pci_address',
|
||||
test_get_stored_pci_address)
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_CLASS_NET', tmpdir)
|
||||
self.stub_out('os_net_config.common.SYS_CLASS_NET', tmpdir)
|
||||
nic = 'p4p1'
|
||||
nic_path = os.path.join(tmpdir, nic)
|
||||
os.makedirs(nic_path)
|
||||
|
@ -764,7 +766,7 @@ class TestUtils(base.TestCase):
|
|||
def test_is_active_nic_for_sriov_vf(self):
|
||||
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
self.stub_out('os_net_config.utils._SYS_CLASS_NET', tmpdir)
|
||||
self.stub_out('os_net_config.common.SYS_CLASS_NET', tmpdir)
|
||||
|
||||
# SR-IOV PF = ens802f0
|
||||
# SR-IOV VF = enp129s2
|
||||
|
|
|
@ -21,11 +21,11 @@ import re
|
|||
import time
|
||||
import yaml
|
||||
|
||||
from os_net_config import common
|
||||
from os_net_config import sriov_config
|
||||
from oslo_concurrency import processutils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
_SYS_CLASS_NET = '/sys/class/net'
|
||||
_SYS_BUS_PCI_DEV = '/sys/bus/pci/devices'
|
||||
# File to contain the DPDK mapped nics, as nic name will not be available after
|
||||
# binding driver, which is required for correct nic numbering.
|
||||
|
@ -109,14 +109,14 @@ def get_file_data(filename):
|
|||
|
||||
def interface_mac(name):
|
||||
try: # If the iface is part of a Linux bond, the real MAC is only here.
|
||||
with open(_SYS_CLASS_NET + '/%s/bonding_slave/perm_hwaddr' % name,
|
||||
with open(common.get_dev_path(name, 'bonding_slave/perm_hwaddr'),
|
||||
'r') as f:
|
||||
return f.read().rstrip()
|
||||
except IOError:
|
||||
pass # Iface is not part of a bond, continue
|
||||
|
||||
try:
|
||||
with open(_SYS_CLASS_NET + '/%s/address' % name, 'r') as f:
|
||||
with open(common.get_dev_path(name, '_address'), 'r') as f:
|
||||
return f.read().rstrip()
|
||||
except IOError:
|
||||
# If the interface is bound to a DPDK driver, get the mac address from
|
||||
|
@ -137,12 +137,12 @@ def is_real_nic(interface_name):
|
|||
if interface_name == 'lo':
|
||||
return True
|
||||
|
||||
device_dir = _SYS_CLASS_NET + '/%s/device' % interface_name
|
||||
device_dir = common.get_dev_path(interface_name, '_device')
|
||||
has_device_dir = os.path.isdir(device_dir)
|
||||
|
||||
address = None
|
||||
try:
|
||||
with open(_SYS_CLASS_NET + '/%s/address' % interface_name, 'r') as f:
|
||||
with open(common.get_dev_path(interface_name, "_address"), 'r') as f:
|
||||
address = f.read().rstrip()
|
||||
except IOError:
|
||||
return False
|
||||
|
@ -155,7 +155,7 @@ def is_real_nic(interface_name):
|
|||
|
||||
def _is_vf(pci_address):
|
||||
|
||||
# If DPDK drivers are bound on a VF, then the path _SYS_CLASS_NET
|
||||
# If DPDK drivers are bound on a VF, then the path common.SYS_CLASS_NET
|
||||
# wouldn't exist. Instead we look for the path
|
||||
# /sys/bus/pci/devices/<PCI addr>/physfn to understand if the device
|
||||
# is actually a VF. This path could be used by VFs not bound with
|
||||
|
@ -167,7 +167,7 @@ def _is_vf(pci_address):
|
|||
|
||||
|
||||
def _is_vf_by_name(interface_name, check_mapping_file=False):
|
||||
vf_path_check = _SYS_CLASS_NET + '/%s/device/physfn' % interface_name
|
||||
vf_path_check = common.get_dev_path(interface_name, 'physfn')
|
||||
is_sriov_vf = os.path.isdir(vf_path_check)
|
||||
if not is_sriov_vf and check_mapping_file:
|
||||
sriov_map = _get_sriov_map()
|
||||
|
@ -187,7 +187,8 @@ def _is_available_nic(interface_name, check_active=True):
|
|||
return False
|
||||
|
||||
operstate = None
|
||||
with open(_SYS_CLASS_NET + '/%s/operstate' % interface_name, 'r') as f:
|
||||
with open(common.get_dev_path(interface_name, '_operstate'),
|
||||
'r') as f:
|
||||
operstate = f.read().rstrip().lower()
|
||||
if check_active and operstate != 'up':
|
||||
return False
|
||||
|
@ -231,8 +232,8 @@ def _ordered_nics(check_active):
|
|||
embedded_nics = []
|
||||
nics = []
|
||||
logger.info("Finding active nics")
|
||||
for name in glob.iglob(_SYS_CLASS_NET + '/*'):
|
||||
nic = name[(len(_SYS_CLASS_NET) + 1):]
|
||||
for name in glob.iglob(common.SYS_CLASS_NET + '/*'):
|
||||
nic = name[(len(common.SYS_CLASS_NET) + 1):]
|
||||
if _is_available_nic(nic, check_active):
|
||||
if _is_embedded_nic(nic):
|
||||
logger.info("%s is an embedded active nic" % nic)
|
||||
|
@ -304,7 +305,7 @@ def bind_dpdk_interfaces(ifname, driver, noop):
|
|||
raise OvsDpdkBindException(msg)
|
||||
|
||||
mac_address = interface_mac(ifname)
|
||||
vendor_id = get_vendor_id(ifname)
|
||||
vendor_id = common.get_vendor_id(ifname)
|
||||
try:
|
||||
out, err = processutils.execute('driverctl', 'set-override',
|
||||
pci_address, driver)
|
||||
|
@ -382,29 +383,9 @@ def translate_ifname_to_pci_address(ifname, noop):
|
|||
return pci_address
|
||||
|
||||
|
||||
def get_vendor_id(ifname):
|
||||
try:
|
||||
with open('%s/%s/device/vendor' % (_SYS_CLASS_NET, ifname),
|
||||
'r') as f:
|
||||
out = f.read().strip()
|
||||
return out
|
||||
except IOError:
|
||||
return
|
||||
|
||||
|
||||
def get_device_id(ifname):
|
||||
try:
|
||||
with open('%s/%s/device/device' % (_SYS_CLASS_NET, ifname),
|
||||
'r') as f:
|
||||
out = f.read().strip()
|
||||
return out
|
||||
except IOError:
|
||||
return
|
||||
|
||||
|
||||
def is_mellanox_interface(ifname):
|
||||
MLNX_VENDOR_ID = "0x15b3"
|
||||
vendor_id = get_vendor_id(ifname)
|
||||
vendor_id = common.get_vendor_id(ifname)
|
||||
if vendor_id == MLNX_VENDOR_ID:
|
||||
return True
|
||||
return False
|
||||
|
@ -412,7 +393,7 @@ def is_mellanox_interface(ifname):
|
|||
|
||||
def get_interface_driver(ifname):
|
||||
try:
|
||||
uevent = '%s/%s/device/uevent' % (_SYS_CLASS_NET, ifname)
|
||||
uevent = common.get_dev_path(ifname, 'device/uevent')
|
||||
with open(uevent, 'r') as f:
|
||||
out = f.read().strip()
|
||||
for line in out.split('\n'):
|
||||
|
@ -426,8 +407,8 @@ def get_interface_driver(ifname):
|
|||
|
||||
def get_dpdk_devargs(ifname, noop):
|
||||
if not noop:
|
||||
vendor_id = get_vendor_id(ifname)
|
||||
device_id = get_device_id(ifname)
|
||||
vendor_id = common.get_vendor_id(ifname)
|
||||
device_id = common.get_device_id(ifname)
|
||||
if vendor_id == "0x15b3":
|
||||
logger.info("Getting devargs for Mellanox cards")
|
||||
if device_id == "0x1007":
|
||||
|
@ -446,7 +427,6 @@ def get_dpdk_devargs(ifname, noop):
|
|||
# be treated the same as VFs of other devices
|
||||
dpdk_devargs = get_pci_address(ifname, noop)
|
||||
else:
|
||||
logger.error("Unable to get devargs for interface %s" % ifname)
|
||||
msg = ("Unable to get devargs for interface %s" % ifname)
|
||||
raise InvalidInterfaceException(msg)
|
||||
else:
|
||||
|
@ -646,8 +626,8 @@ def configure_sriov_vfs():
|
|||
|
||||
|
||||
def get_vf_devname(pf_name, vfid):
|
||||
vf_path = os.path.join(_SYS_CLASS_NET, pf_name, "device/virtfn%d/net"
|
||||
% vfid)
|
||||
vf_path = os.path.join(common.SYS_CLASS_NET, pf_name,
|
||||
f"device/virtfn{vfid}/net")
|
||||
if os.path.isdir(vf_path):
|
||||
vf_nic = os.listdir(vf_path)
|
||||
else:
|
||||
|
|
Loading…
Reference in New Issue