|
15 | 15 |
|
16 | 16 |
|
17 | 17 | class Interface(Module):
|
18 |
| - """Test network interfaces""" |
| 18 | + """Test network interfaces |
19 | 19 |
|
20 |
| - def __init__(self, name): |
| 20 | + >>> host.interface("eth0").exists |
| 21 | + True |
| 22 | +
|
| 23 | + Optionally, the protocol family to use can be enforced. |
| 24 | +
|
| 25 | + >>> host.interface("eth0", "inet6").adresses |
| 26 | + ['fe80::e291:f5ff:fe98:6b8c'] |
| 27 | + """ |
| 28 | + |
| 29 | + def __init__(self, name, family=None): |
21 | 30 | self.name = name
|
| 31 | + self.family = family |
22 | 32 | super().__init__()
|
23 | 33 |
|
24 | 34 | @property
|
@@ -49,30 +59,74 @@ def get_module_class(cls, host):
|
49 | 59 | return BSDInterface
|
50 | 60 | raise NotImplementedError
|
51 | 61 |
|
| 62 | + @classmethod |
| 63 | + def names(cls): |
| 64 | + """Return the names of all the interfaces. |
| 65 | +
|
| 66 | + >>> host.interface.names() |
| 67 | + ['lo', 'tunl0', 'ip6tnl0', 'eth0'] |
| 68 | + """ |
| 69 | + raise NotImplementedError |
| 70 | + |
| 71 | + @classmethod |
| 72 | + def default(cls, family=None): |
| 73 | + """Return the interface used for the default route. |
| 74 | +
|
| 75 | + >>> host.interface.default() |
| 76 | + <interface eth0> |
| 77 | +
|
| 78 | + Optionally, the protocol family to use can be enforced. |
| 79 | +
|
| 80 | + >>> host.interface.default("inet6") |
| 81 | + None |
| 82 | + """ |
| 83 | + raise NotImplementedError |
| 84 | + |
52 | 85 |
|
53 | 86 | class LinuxInterface(Interface):
|
54 | 87 | @cached_property
|
55 | 88 | def _ip(self):
|
56 |
| - return self.find_command("ip") |
| 89 | + ip_cmd = self.find_command("ip") |
| 90 | + if self.family is not None: |
| 91 | + ip_cmd = f"{ip_cmd} -f {self.family}" |
| 92 | + return ip_cmd |
57 | 93 |
|
58 | 94 | @property
|
59 | 95 | def exists(self):
|
60 |
| - return self.run_test("%s link show %s", self._ip, self.name).rc == 0 |
| 96 | + return self.run_test("{} link show %s".format(self._ip), self.name).rc == 0 |
61 | 97 |
|
62 | 98 | @property
|
63 | 99 | def speed(self):
|
64 | 100 | return int(self.check_output("cat /sys/class/net/%s/speed", self.name))
|
65 | 101 |
|
66 | 102 | @property
|
67 | 103 | def addresses(self):
|
68 |
| - stdout = self.check_output("%s addr show %s", self._ip, self.name) |
| 104 | + stdout = self.check_output("{} addr show %s".format(self._ip), self.name) |
69 | 105 | addrs = []
|
70 | 106 | for line in stdout.splitlines():
|
71 | 107 | splitted = [e.strip() for e in line.split(" ") if e]
|
72 | 108 | if splitted and splitted[0] in ("inet", "inet6"):
|
73 | 109 | addrs.append(splitted[1].split("/", 1)[0])
|
74 | 110 | return addrs
|
75 | 111 |
|
| 112 | + @classmethod |
| 113 | + def default(cls, family=None): |
| 114 | + _default = cls(None, family=family) |
| 115 | + out = cls.check_output("{} route ls".format(_default._ip)) |
| 116 | + for line in out.splitlines(): |
| 117 | + if "default" in line: |
| 118 | + _default.name = line.strip().rsplit(" ", 1)[-1] |
| 119 | + return _default |
| 120 | + |
| 121 | + @classmethod |
| 122 | + def names(cls): |
| 123 | + # -o is to tell the ip command to return 1 line per interface |
| 124 | + out = cls.check_output("{} -o link show".format(cls(None)._ip)) |
| 125 | + interfaces = [] |
| 126 | + for line in out.splitlines(): |
| 127 | + interfaces.append(line.strip().split(": ", 2)[1].split("@", 1)[0]) |
| 128 | + return interfaces |
| 129 | + |
76 | 130 |
|
77 | 131 | class BSDInterface(Interface):
|
78 | 132 | @property
|
|
0 commit comments