Fix lldp format in debian environment

Centos and Debian are using different versions of lldp tool.

Centos (python2) uses an older lldp 0.9.0
Debian (python3) uses a newer lldp 1.0.11

When calling the lldp tool passing 'json' flag, the results
are formatted differently in those versions of the tool.

A "json0" flag was added for backward compatability but
does not exist in 0.9.0.

For this solution:
'json' argument is kept for the older lldp on Centos.
'json0' argument is used for the newer lldp on Debian.

The results have some slight variations, so some special
handling in the processing methods is being added.

For Centos the results will be handled exactly the same.
For Debian, certain areas of the data need to be handled
differently.

Test Plan:
  PASS: Verify the KeyErrors are no longer generated in Debian
  PASS: Verify no new exceptions are generated in Debian.
  PASS: Verify Centos still works.
  PASS: Verify the controllerconfig changes can still be parsed

Closes-Bug: 1965978
Signed-off-by: Al Bailey <al.bailey@windriver.com>
Change-Id: I133e934f58fcc03c2625ec818094acea23e21c12
This commit is contained in:
Al Bailey 2022-03-22 17:00:33 +00:00
parent b30532b51a
commit 192867300e
11 changed files with 980 additions and 16 deletions

View File

@ -9,6 +9,7 @@ from __future__ import print_function
import json
import netaddr
import os
import six
import subprocess
import sys
import time
@ -18,6 +19,12 @@ import controllerconfig.utils as utils
from six.moves import input
if six.PY3:
JSON_MODE = "json0"
else:
JSON_MODE = "json"
def is_valid_management_address(ip_address, management_subnet):
"""Determine whether a management address is valid."""
if ip_address == management_subnet.network:
@ -67,7 +74,7 @@ def configure_management():
print("Retrieving neighbor details... ", end=' ')
lldpcli_show_output = subprocess.check_output(
['sudo', 'lldpcli', 'show', 'neighbors', 'summary', '-f', 'json'],
['sudo', 'lldpcli', 'show', 'neighbors', 'summary', '-f', JSON_MODE],
universal_newlines=True)
try:
lldp_interfaces = json.loads(

View File

@ -8,19 +8,25 @@
# All Rights Reserved.
#
from eventlet.green import subprocess
from oslo_log import log as logging
import simplejson as json
from sysinv.agent.lldp.drivers import base
from sysinv.agent.lldp import plugin
from sysinv.common import constants
from sysinv.common import utils
LOG = logging.getLogger(__name__)
def get_json_mode():
if utils.is_centos():
return "json"
else:
return "json0"
class SysinvLldpdAgentDriver(base.SysinvLldpDriverBase):
def __init__(self, **kwargs):
@ -40,12 +46,15 @@ class SysinvLldpdAgentDriver(base.SysinvLldpDriverBase):
@staticmethod
def _lldpd_get_agent_status():
json_obj = json
p = subprocess.Popen(["lldpcli", "-f", "json", "show",
p = subprocess.Popen(["lldpcli", "-f", get_json_mode(), "show",
"configuration"],
universal_newlines=True,
stdout=subprocess.PIPE)
data = json_obj.loads(p.communicate()[0])
# No special handling required in this method.
# lldp 0.9.0 json and lldp 1.0.11 json0 both
# return the same format for 'show configuration'
configuration = data['configuration'][0]
config = configuration['config'][0]
rx_only = config['rx-only'][0]
@ -56,7 +65,13 @@ class SysinvLldpdAgentDriver(base.SysinvLldpDriverBase):
return "rx=enabled,tx=disabled"
@staticmethod
def _lldpd_get_attrs(iface):
def _lldpd_get_attrs(iface, iface_mode=False):
"""
In json0 mode, the fields for iface are different
for neighbors and agents.
iface_mode means that json0 results are for show interface
which puts ttl at the interface level, rather than under ports
"""
name_or_uuid = None
chassis_id = None
system_name = None
@ -92,9 +107,19 @@ class SysinvLldpdAgentDriver(base.SysinvLldpDriverBase):
return attrs
port_id = port["id"][0].get("value")
if not port.get('ttl'):
return attrs
ttl = port['ttl'][0].get("value")
# Special case: iface_mode (debian only)
# lldp 0.9.0 puts ttl under port for neighbors and agents
# lldp 1.0.11 puts ttyl under ports for neighbors
# but puts it under in a different location (iface) for agents
if iface_mode:
# ttl is stored under iface as ttl: [ { "ttl: "val" } ]
if not iface.get('ttl'):
return attrs
ttl = iface['ttl'][0].get("ttl")
else:
if not port.get('ttl'):
return attrs
ttl = port['ttl'][0].get("value")
if chassis.get("name"):
system_name = chassis['name'][0].get("value")
@ -257,7 +282,7 @@ class SysinvLldpdAgentDriver(base.SysinvLldpDriverBase):
json_obj = json
lldp_agents = []
p = subprocess.Popen(["lldpcli", "-f", "json", "show", "interface",
p = subprocess.Popen(["lldpcli", "-f", get_json_mode(), "show", "interface",
"detail"], stdout=subprocess.PIPE,
universal_newlines=True)
data = json_obj.loads(p.communicate()[0])
@ -268,7 +293,12 @@ class SysinvLldpdAgentDriver(base.SysinvLldpDriverBase):
return lldp_agents
for iface in lldp['interface']:
agent_attrs = self._lldpd_get_attrs(iface)
# json0 results for the interfaces of agents are not
# the same as when querying neighbors.
# json0 puts ttl under interface rather than port
iface_mode = (get_json_mode() == "json0")
agent_attrs = self._lldpd_get_attrs(iface,
iface_mode=iface_mode)
status = self._lldpd_get_agent_status()
agent_attrs.update({"status": status})
agent = plugin.Agent(**agent_attrs)
@ -283,7 +313,7 @@ class SysinvLldpdAgentDriver(base.SysinvLldpDriverBase):
def lldp_neighbours_list(self):
json_obj = json
lldp_neighbours = []
p = subprocess.Popen(["lldpcli", "-f", "json", "show", "neighbor",
p = subprocess.Popen(["lldpcli", "-f", get_json_mode(), "show", "neighbor",
"detail"], stdout=subprocess.PIPE,
universal_newlines=True)
data = json_obj.loads(p.communicate()[0])
@ -294,6 +324,9 @@ class SysinvLldpdAgentDriver(base.SysinvLldpDriverBase):
return lldp_neighbours
for iface in lldp['interface']:
# json0 results for the interfaces of neighbors are not
# the same as when querying agents.
# json0 puts ttl under ports (same as json)
neighbour_attrs = self._lldpd_get_attrs(iface)
neighbour = plugin.Neighbour(**neighbour_attrs)
lldp_neighbours.append(neighbour)
@ -305,7 +338,7 @@ class SysinvLldpdAgentDriver(base.SysinvLldpDriverBase):
self.previous_neighbours = []
def lldp_update_systemname(self, systemname):
p = subprocess.Popen(["lldpcli", "-f", "json", "show", "chassis"],
p = subprocess.Popen(["lldpcli", "-f", get_json_mode(), "show", "chassis"],
stdout=subprocess.PIPE, universal_newlines=True)
data = json.loads(p.communicate()[0])

View File

@ -0,0 +1,47 @@
{
"lldp": [
{
"interface": [
{
"name": "eno1",
"via": "LLDP",
"chassis": [
{
"id": [
{
"type": "mac",
"value": "c0:62:6b:a9:62:80"
}
],
"name": [
{
"value": "yow-cisco-b2u47"
}
]
}
],
"port": [
{
"id": [
{
"type": "ifname",
"value": "Gi0\/39"
}
],
"descr": [
{
"value": "GigabitEthernet0\/39"
}
],
"ttl": [
{
"value": "109"
}
]
}
]
}
]
}
]
}

View File

@ -0,0 +1,61 @@
{
"local-chassis": [
{
"chassis": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:59:9e:6b"
}
],
"name": [
{
"value": "controller-0:bd0a9e89-7fd7-4729-bc67-df0c39c0db8f"
}
],
"descr": [
{
"value": "Debian GNU/Linux 11 (bullseye) Linux 5.10.0-6-amd64 #1 SMP PREEMPT Debian 5.10.74-1.stx.3 (2022-04-02) x86_64"
}
],
"mgmt-ip": [
{
"value": "192.168.204.2"
},
{
"value": "fe80::a00:27ff:fe09:595d"
}
],
"mgmt-iface": [
{
"value": "1"
},
{
"value": "4"
}
],
"capability": [
{
"type": "Bridge",
"enabled": true
},
{
"type": "Router",
"enabled": true
},
{
"type": "Wlan",
"enabled": false
},
{
"type": "Station",
"enabled": false
}
]
}
]
}
]
}

View File

@ -0,0 +1,121 @@
{
"configuration": [
{
"config": [
{
"tx-delay": [
{
"value": "30"
}
],
"tx-delay-ms": [
{
"value": "30000"
}
],
"tx-hold": [
{
"value": "4"
}
],
"max-neighbors": [
{
"value": "32"
}
],
"rx-only": [
{
"value": "no"
}
],
"mgmt-pattern": [
{
"value": "(none)"
}
],
"iface-pattern": [
{
"value": "*,!br*,!ovs*,!tap*,!cali*,!tunl*,!docker*"
}
],
"perm-iface-pattern": [
{
"value": "(none)"
}
],
"cid-pattern": [
{
"value": "(none)"
}
],
"cid-string": [
{
"value": "(none)"
}
],
"description": [
{
"value": "(none)"
}
],
"platform": [
{
"value": "Linux"
}
],
"hostname": [
{
"value": "controller-0:bd0a9e89-7fd7-4729-bc67-df0c39c0db8f"
}
],
"advertise-version": [
{
"value": "yes"
}
],
"ifdescr-update": [
{
"value": "no"
}
],
"iface-promisc": [
{
"value": "no"
}
],
"lldpmed-no-inventory": [
{
"value": "yes"
}
],
"lldpmed-faststart": [
{
"value": "yes"
}
],
"lldpmed-faststart-interval": [
{
"value": "1"
}
],
"bond-slave-src-mac-type": [
{
"value": "local"
}
],
"lldp-portid-type": [
{
"value": "unknown"
}
],
"lldp-agent-type": [
{
"value": "unknown"
}
]
}
]
}
]
}

View File

@ -0,0 +1,503 @@
{
"lldp": [
{
"interface": [
{
"name": "enp0s10",
"status": [
{
"value": "RX and TX"
}
],
"chassis": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:59:9e:6b"
}
],
"name": [
{
"value": "controller-0:bd0a9e89-7fd7-4729-bc67-df0c39c0db8f"
}
],
"descr": [
{
"value": "Debian GNU/Linux 11 (bullseye) Linux 5.10.0-6-amd64 #1 SMP PREEMPT Debian 5.10.74-1.stx.3 (2022-04-02) x86_64"
}
],
"mgmt-ip": [
{
"value": "192.168.204.2"
},
{
"value": "fe80::a00:27ff:fe09:595d"
}
],
"mgmt-iface": [
{
"value": "1"
},
{
"value": "4"
}
],
"capability": [
{
"type": "Bridge",
"enabled": true
},
{
"type": "Router",
"enabled": true
},
{
"type": "Wlan",
"enabled": false
},
{
"type": "Station",
"enabled": false
}
]
}
],
"port": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:59:9e:6b"
}
],
"descr": [
{
"value": "enp0s10"
}
]
}
],
"ttl": [
{
"ttl": "120"
}
]
},
{
"name": "enp0s16",
"status": [
{
"value": "RX and TX"
}
],
"chassis": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:59:9e:6b"
}
],
"name": [
{
"value": "controller-0:bd0a9e89-7fd7-4729-bc67-df0c39c0db8f"
}
],
"descr": [
{
"value": "Debian GNU/Linux 11 (bullseye) Linux 5.10.0-6-amd64 #1 SMP PREEMPT Debian 5.10.74-1.stx.3 (2022-04-02) x86_64"
}
],
"mgmt-ip": [
{
"value": "192.168.204.2"
},
{
"value": "fe80::a00:27ff:fe09:595d"
}
],
"mgmt-iface": [
{
"value": "1"
},
{
"value": "4"
}
],
"capability": [
{
"type": "Bridge",
"enabled": true
},
{
"type": "Router",
"enabled": true
},
{
"type": "Wlan",
"enabled": false
},
{
"type": "Station",
"enabled": false
}
]
}
],
"port": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:d4:cc:09"
}
],
"descr": [
{
"value": "enp0s16"
}
]
}
],
"ttl": [
{
"ttl": "120"
}
]
},
{
"name": "enp0s3",
"status": [
{
"value": "RX and TX"
}
],
"chassis": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:59:9e:6b"
}
],
"name": [
{
"value": "controller-0:bd0a9e89-7fd7-4729-bc67-df0c39c0db8f"
}
],
"descr": [
{
"value": "Debian GNU/Linux 11 (bullseye) Linux 5.10.0-6-amd64 #1 SMP PREEMPT Debian 5.10.74-1.stx.3 (2022-04-02) x86_64"
}
],
"mgmt-ip": [
{
"value": "192.168.204.2"
},
{
"value": "fe80::a00:27ff:fe09:595d"
}
],
"mgmt-iface": [
{
"value": "1"
},
{
"value": "4"
}
],
"capability": [
{
"type": "Bridge",
"enabled": true
},
{
"type": "Router",
"enabled": true
},
{
"type": "Wlan",
"enabled": false
},
{
"type": "Station",
"enabled": false
}
]
}
],
"port": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:09:59:5d"
}
],
"descr": [
{
"value": "enp0s3"
}
],
"auto-negotiation": [
{
"supported": true,
"enabled": true,
"advertised": [
{
"type": "10Base-T",
"hd": true,
"fd": true
},
{
"type": "100Base-TX",
"hd": true,
"fd": true
},
{
"type": "1000Base-T",
"hd": false,
"fd": true
}
],
"current": [
{
"value": "1000BaseTFD - Four-pair Category 5 UTP, full duplex mode"
}
]
}
]
}
],
"ttl": [
{
"ttl": "120"
}
]
},
{
"name": "enp0s8",
"status": [
{
"value": "RX and TX"
}
],
"chassis": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:59:9e:6b"
}
],
"name": [
{
"value": "controller-0:bd0a9e89-7fd7-4729-bc67-df0c39c0db8f"
}
],
"descr": [
{
"value": "Debian GNU/Linux 11 (bullseye) Linux 5.10.0-6-amd64 #1 SMP PREEMPT Debian 5.10.74-1.stx.3 (2022-04-02) x86_64"
}
],
"mgmt-ip": [
{
"value": "192.168.204.2"
},
{
"value": "fe80::a00:27ff:fe09:595d"
}
],
"mgmt-iface": [
{
"value": "1"
},
{
"value": "4"
}
],
"capability": [
{
"type": "Bridge",
"enabled": true
},
{
"type": "Router",
"enabled": true
},
{
"type": "Wlan",
"enabled": false
},
{
"type": "Station",
"enabled": false
}
]
}
],
"port": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:a7:26:d8"
}
],
"descr": [
{
"value": "enp0s8"
}
],
"auto-negotiation": [
{
"supported": true,
"enabled": true,
"advertised": [
{
"type": "10Base-T",
"hd": true,
"fd": true
},
{
"type": "100Base-TX",
"hd": true,
"fd": true
},
{
"type": "1000Base-T",
"hd": false,
"fd": true
}
],
"current": [
{
"value": "1000BaseTFD - Four-pair Category 5 UTP, full duplex mode"
}
]
}
]
}
],
"ttl": [
{
"ttl": "120"
}
]
},
{
"name": "enp0s9",
"status": [
{
"value": "RX and TX"
}
],
"chassis": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:59:9e:6b"
}
],
"name": [
{
"value": "controller-0:bd0a9e89-7fd7-4729-bc67-df0c39c0db8f"
}
],
"descr": [
{
"value": "Debian GNU/Linux 11 (bullseye) Linux 5.10.0-6-amd64 #1 SMP PREEMPT Debian 5.10.74-1.stx.3 (2022-04-02) x86_64"
}
],
"mgmt-ip": [
{
"value": "192.168.204.2"
},
{
"value": "fe80::a00:27ff:fe09:595d"
}
],
"mgmt-iface": [
{
"value": "1"
},
{
"value": "4"
}
],
"capability": [
{
"type": "Bridge",
"enabled": true
},
{
"type": "Router",
"enabled": true
},
{
"type": "Wlan",
"enabled": false
},
{
"type": "Station",
"enabled": false
}
]
}
],
"port": [
{
"id": [
{
"type": "mac",
"value": "08:00:27:cc:d2:2c"
}
],
"descr": [
{
"value": "enp0s9"
}
],
"auto-negotiation": [
{
"supported": true,
"enabled": true,
"advertised": [
{
"type": "10Base-T",
"hd": true,
"fd": true
},
{
"type": "100Base-TX",
"hd": true,
"fd": true
},
{
"type": "1000Base-T",
"hd": false,
"fd": true
}
],
"current": [
{
"value": "1000BaseTFD - Four-pair Category 5 UTP, full duplex mode"
}
]
}
]
}
],
"ttl": [
{
"ttl": "120"
}
]
}
]
}
]
}

View File

@ -0,0 +1,73 @@
{
"lldp": [
{
"interface": [
{
"name": "enp0s3",
"via": "LLDP",
"rid": "1",
"age": "0 day, 00:09:43",
"chassis": [
{
"id": [
{
"type": "mac",
"value": "0a:00:27:00:00:0d"
}
]
}
],
"port": [
{
"id": [
{
"type": "mac",
"value": "0a:00:27:00:00:0d"
}
],
"ttl": [
{
"value": "3601"
}
],
"auto-negotiation": [
{
"supported": true,
"enabled": true,
"advertised": [
{
"type": "1000Base-T",
"hd": false,
"fd": true
}
],
"current": [
{
"value": "unknown"
}
]
}
]
}
],
"lldp-med": [
{
"device-type": [
{
"value": "Generic Endpoint (Class I)"
}
],
"capability": [
{
"type": "Capabilities",
"available": true
}
]
}
]
}
]
}
]
}

View File

@ -0,0 +1,38 @@
{
"lldp": [
{
"interface": [
{
"name": "enp0s3",
"via": "LLDP",
"chassis": [
{
"id": [
{
"type": "mac",
"value": "0a:00:27:00:00:0d"
}
]
}
],
"port": [
{
"id": [
{
"type": "mac",
"value": "0a:00:27:00:00:0d"
}
],
"ttl": [
{
"value": "3601"
}
]
}
]
}
]
}
]
}

View File

@ -8,4 +8,13 @@ For Centos (0.9.0) the data was generated by the following commands:
sudo lldpcli -f json show interface detail > lldp_show_interface_detail.json
sudo lldpcli -f json show configuration > lldp_show_configuration.json
sudo lldpcli -f json show neighbor detail > lldp_show_neighbor_detail.json
sudo lldpcli -f json show neighbor summary > lldp_show_neighbor_summary.json
sudo lldpcli -f json show chassis > lldp_show_chassis.json
For Debian (1.0.11) the data was generated by the following commands:
sudo lldpcli -f json0 show interface detail > lldp_show_interface_detail.json
sudo lldpcli -f json0 show configuration > lldp_show_configuration.json
sudo lldpcli -f json0 show neighbor detail > lldp_show_neighbor_detail.json
sudo lldpcli -f json0 show neighbor summary > lldp_show_neighbor_summary.json
sudo lldpcli -f json0 show chassis > lldp_show_chassis.json

View File

@ -18,6 +18,7 @@ import mock
import os
from sysinv.agent.lldp.drivers.lldpd.driver import SysinvLldpdAgentDriver
from sysinv.common import constants
from sysinv.tests import base
@ -48,6 +49,8 @@ class LldpInterfaceDetailTestsMixin(object):
lldp_show_configuration.json
lldp_show_interface_detail.json
lldp_show_neighbor_detail.json
lldp_show_neighbor_summary.json
lldp_show_chassis.json
"""
def setUp(self):
super(LldpInterfaceDetailTestsMixin, self).setUp()
@ -60,6 +63,8 @@ class LldpInterfaceDetailTestsMixin(object):
"lldp_show_neighbor_detail.json")
self.show_chassis_data = load_data(self.version_dir,
"lldp_show_chassis.json")
self.neighbours_summary_data = load_data(self.version_dir,
"lldp_show_neighbor_summary.json")
def test_initialize(self):
"""
@ -138,7 +143,7 @@ class LldpInterfaceDetailTestsMixin(object):
agents = self.driver.lldp_agents_list()
# Validate the agents have been parsed
self.assertNotEqual(0, len(agents))
self.assertEqual(self.num_expected_agents, len(agents))
@mock.patch('sysinv.agent.lldp.drivers.lldpd.driver.subprocess.Popen')
def test_lldp_neighbours_list(self, mock_popen):
@ -158,7 +163,9 @@ class LldpInterfaceDetailTestsMixin(object):
neighbors = self.driver.lldp_neighbours_list()
# Validate the neighbors have been parsed correctly
self.assertNotEqual(0, len(neighbors))
self.assertEqual(self.num_expected_neighbors, len(neighbors))
for n in neighbors:
self.assertEqual(self.expected_neighbor_ttl, n.ttl)
@mock.patch('sysinv.agent.lldp.drivers.lldpd.driver.subprocess.Popen')
def test_lldp_update_systemname(self, mock_popen):
@ -187,9 +194,71 @@ class LldpInterfaceDetailTestsMixin(object):
mock_popen.assert_called_with(
["lldpcli", "configure", "system", "hostname", newname], stdout=mock.ANY)
def test_config_controller(self):
"""
See controllerconfig/controllerconfig/controllerconfig/config_management.py
This test isolates the code in the large methods that interact with lldp
This just tests that the parsed results in config controller are valid
"""
lldpcli_show_output = self.neighbours_summary_data
# step 1. call load
lldp_interfaces = json.loads(lldpcli_show_output)['lldp'][0]['interface']
# step 2. walk the list
for interface in lldp_interfaces:
i_name = interface['name']
i_val = interface['port'][0]['id'][0]['value']
self.assertIn(i_name, self.expected_neighbor_interfaces)
self.assertIn(i_val, self.expected_neighbor_port_ids)
# Centos environment is shipped with lldpcli version 0.9.0
class TestCentosLldpInterfaceDetail(LldpInterfaceDetailTestsMixin,
base.TestCase):
version_dir = "0.9.0"
hostname = 'controller-0'
hostname = "controller-0"
# num_expected_agents
# parsed from lldp_show_interface_detail.json
num_expected_agents = 5
# num_expected_neighbors and expected_neighbor_ttl
# parsed from lldp_show_neighbor_detail.json
num_expected_neighbors = 1
expected_neighbor_ttl = "3544"
# expected_neighbor_interfaces and expected_neighbor_port_ids
# parsed from lldp_show_neighbor_summary.json
# centos has the port value as a 'ifname'
expected_neighbor_interfaces = ["eno1", ]
expected_neighbor_port_ids = ["Gi0/39"]
def setUp(self):
super(TestCentosLldpInterfaceDetail, self).setUp()
self.mocked_get_os_type = mock.patch(
'sysinv.common.utils.get_os_type',
return_value=constants.OS_CENTOS)
self.mocked_get_os_type.start()
self.addCleanup(self.mocked_get_os_type.stop)
class TestDebianLldpInterfaceDetail(LldpInterfaceDetailTestsMixin,
base.TestCase):
version_dir = "1.0.11"
hostname = "controller-0"
# num_expected_agents
# parsed from lldp_show_interface_detail.json
num_expected_agents = 5
# num_expected_neighbors and expected_neighbor_ttl
# are parsed from lldp_show_neighbor_detail.json
num_expected_neighbors = 1
expected_neighbor_ttl = "3601"
# expected_neighbor_interfaces and expected_neighbor_port_ids
# parsed from lldp_show_neighbor_summary.json
# debian has the port value as a 'mac'
expected_neighbor_interfaces = ["enp0s3", ]
expected_neighbor_port_ids = ["0a:00:27:00:00:0d"]
def setUp(self):
super(TestDebianLldpInterfaceDetail, self).setUp()
self.mocked_get_os_type = mock.patch(
'sysinv.common.utils.get_os_type',
return_value=constants.OS_DEBIAN)
self.mocked_get_os_type.start()
self.addCleanup(self.mocked_get_os_type.stop)

View File

@ -179,7 +179,10 @@ commands =
pylint {posargs} sysinv --rcfile=./pylint.rc
[testenv:cover]
basepython = python2.7
basepython = python3.9
install_command = pip install -v -v -v \
-c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/starlingx/root/raw/branch/master/build-tools/requirements/debian/upper-constraints.txt} \
{opts} {packages}
passenv = CURL_CA_BUNDLE
deps = {[testenv]deps}
setenv = {[testenv]setenv}