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

Subscribers

People subscribed via source and target branches