Merge ~jocave/plainbox-provider-resource:add-network-management-resource into plainbox-provider-resource:master

Proposed by Jonathan Cave
Status: Merged
Approved by: Jonathan Cave
Approved revision: e4fa437b004ba75f7f2d30ab0af63d46e3b5b4b2
Merged at revision: 170104f43398b70e04ddb111bc85cef6d0b29775
Proposed branch: ~jocave/plainbox-provider-resource:add-network-management-resource
Merge into: plainbox-provider-resource:master
Diff against target: 153 lines (+139/-0)
2 files modified
bin/net_if_management.py (+125/-0)
jobs/resource.pxu (+14/-0)
Reviewer Review Type Date Requested Status
Maciej Kisielewski Approve
Sylvain Pineau (community) Approve
Review via email: mp+369051@code.launchpad.net

Description of the change

Resource job that, for all network interfaces identified by udev (categories NETWORK and WIRELESS), applies a simple set of rules to work out what utility is responsible for managing it.

This includes parsing the netplan configuration files and testing to see if network-manager is available.

It is intended that this resource can than be used to filter network related jobs in test plans and hence eliminate the need to keep separate plans and launchers for specific utilities.

To post a comment you must log in.
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

very useful and well written, +1

review: Approve
Revision history for this message
Maciej Kisielewski (kissiel) wrote :

Two comments below.

Revision history for this message
Jonathan Cave (jocave) wrote :

Addressed comments from kissiel

Revision history for this message
Maciej Kisielewski (kissiel) wrote :

Thanks for that syntactic sugar! +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/bin/net_if_management.py b/bin/net_if_management.py
2new file mode 100755
3index 0000000..1b08274
4--- /dev/null
5+++ b/bin/net_if_management.py
6@@ -0,0 +1,125 @@
7+#!/usr/bin/env python3
8+# This file is part of Checkbox.
9+#
10+# Copyright 2019 Canonical Ltd.
11+# Written by:
12+# Jonathan Cave <jonathan.cave@canonical.com>
13+#
14+# Checkbox is free software: you can redistribute it and/or modify
15+# it under the terms of the GNU General Public License version 3,
16+# as published by the Free Software Foundation.
17+#
18+# Checkbox is distributed in the hope that it will be useful,
19+# but WITHOUT ANY WARRANTY; without even the implied warranty of
20+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21+# GNU General Public License for more details.
22+#
23+# You should have received a copy of the GNU General Public License
24+# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
25+
26+from enum import Enum
27+import subprocess as sp
28+import sys
29+
30+from checkbox_support.parsers.netplan import Netplan
31+from checkbox_support.parsers.udevadm import UdevadmParser, UdevResult
32+
33+
34+class UdevInterfaceLister(UdevResult):
35+
36+ def __init__(self, categories):
37+ self.categories = categories
38+ self.names = []
39+ cmd = 'udevadm info --export-db'
40+ output = sp.check_output(cmd, shell=True).decode(sys.stdout.encoding)
41+ udev = UdevadmParser(output)
42+ udev.run(self)
43+
44+ def addDevice(self, device):
45+ c = getattr(device, "category", None)
46+ if c in self.categories:
47+ p = getattr(device, "interface", None)
48+ if p is not None:
49+ self.names.append(p)
50+
51+
52+class NmInterfaceState():
53+
54+ def __init__(self):
55+ self.devices = {}
56+ cmd = 'nmcli -v'
57+ rc = sp.call(cmd, shell=True, stdout=sp.DEVNULL, stderr=sp.DEVNULL)
58+ if rc != 0:
59+ self.available = False
60+ return
61+ self.available = True
62+ cmd = 'nmcli -t -f DEVICE,STATE d'
63+ output = sp.check_output(cmd, shell=True).decode(sys.stdout.encoding)
64+ for line in output.splitlines():
65+ dev, state = line.strip().split(':')
66+ self.devices[dev] = state
67+
68+
69+class States(Enum):
70+ unspecified = 'unspecified'
71+ error = 'error'
72+ networkd = 'networkd'
73+ nm = 'NetworkManager'
74+
75+
76+def main():
77+ # Use udev as definitive source of network interfaces
78+ all_interfaces = UdevInterfaceLister(['NETWORK', 'WIRELESS'])
79+
80+ # Get the neplan config
81+ netplan_conf = Netplan()
82+ netplan_conf.parse()
83+
84+ # Get the NetworkManager config
85+ nm_conf = NmInterfaceState()
86+
87+ # fallback state
88+ global_scope_manager = States.unspecified.value
89+
90+ # if netplan has a top-level renderer use that as default:
91+ if netplan_conf.network.get('renderer'):
92+ global_scope_manager = netplan_conf.network['renderer']
93+
94+ for n in all_interfaces.names:
95+ print('device: {}'.format(n))
96+ print('nmcli_available: {}'.format(nm_conf.available))
97+
98+ if n in netplan_conf.wifis:
99+ category_scope_manager = netplan_conf.wifis.get('renderer')
100+ elif n in netplan_conf.ethernets:
101+ category_scope_manager = netplan_conf.ethernets.get('renderer')
102+
103+ # Netplan config indcates NM
104+ if (global_scope_manager == States.nm.value or
105+ category_scope_manager == States.nm.value):
106+ # if NM isnt actually available this is a bad config
107+ if not nm_conf.available:
108+ print('managed_by: {}'.format(States.error.value))
109+ print()
110+ continue
111+ # NM does not know the interface
112+ if nm_conf.devices.get(n) is None:
113+ print('managed_by: {}'.format(States.error.value))
114+ print()
115+ continue
116+ # NM thinks it doesnt managed the device despite netplan config
117+ if nm_conf.devices.get(n) == 'unmanaged':
118+ print('managed_by: {}'.format(States.error.value))
119+ print()
120+ continue
121+ print('managed_by: {}'.format(States.nm.value))
122+ print()
123+ continue
124+
125+ # No renderer specified
126+ print('managed_by: {}'.format(States.networkd.value))
127+ print()
128+
129+
130+if __name__ == "__main__":
131+ main()
132diff --git a/jobs/resource.pxu b/jobs/resource.pxu
133index 3dc7f9e..9c142e4 100644
134--- a/jobs/resource.pxu
135+++ b/jobs/resource.pxu
136@@ -429,3 +429,17 @@ plugin: resource
137 estimated_duration: 1.0
138 command:
139 snapd_resource features
140+
141+id: net_if_management
142+_summary: Identify what service is managing each physical network interface
143+_description:
144+ Network interfaces on Ubuntu systems are generally configured by either
145+ systemd-networkd or NetworkManager. This configuration can be maintained using
146+ the Netplan utility. This resource attempts to identify which "renderer" is
147+ responsible for cofiguring an individual interface allowing appropriate tests
148+ to be run.
149+plugin: resource
150+estimated_duration: 2.0
151+user: root
152+command:
153+ net_if_management.py

Subscribers

People subscribed via source and target branches