Gathers information about a network interface. This method relies on the JSON output of the `ip` command. If the interface is available, the JSON structure is an array containing an object, which looks like the following (extra properties omitted for brevity): [{ "op
(interface_name)
| 74 | |
| 75 | |
| 76 | def inspect_interface(interface_name): |
| 77 | """Gathers information about a network interface. |
| 78 | |
| 79 | This method relies on the JSON output of the `ip` command. If the interface |
| 80 | is available, the JSON structure is an array containing an object, which |
| 81 | looks like the following (extra properties omitted for brevity): |
| 82 | [{ |
| 83 | "operstate": "UP", |
| 84 | "address": "e4:5f:01:98:65:05", |
| 85 | "addr_info": [{"family":"inet", "local":"192.168.12.86"}] |
| 86 | }] |
| 87 | Note that `addr_info` might be empty, e.g. if `operstate` is `DOWN`; |
| 88 | it also might contain additional families, such as `inet6` (IPv6). |
| 89 | |
| 90 | In general, we don’t have too much trust in the consistency of the JSON |
| 91 | structure, as there is no reliable documentation for it. We try to handle |
| 92 | and parse the output in a defensive and graceful way, to maximize |
| 93 | robustness and avoid producing erratic failures. |
| 94 | |
| 95 | Args: |
| 96 | interface_name: the technical interface name as string, e.g. `eth0`. |
| 97 | |
| 98 | Returns: |
| 99 | InterfaceStatus object |
| 100 | """ |
| 101 | status = InterfaceStatus(interface_name, False, None, None) |
| 102 | |
| 103 | try: |
| 104 | # The command arguments are trusted because they aren't based on user |
| 105 | # input. |
| 106 | ip_cmd_out_raw = subprocess.check_output( # noqa: S603 |
| 107 | [ |
| 108 | '/usr/bin/ip', |
| 109 | '-json', |
| 110 | 'address', |
| 111 | 'show', |
| 112 | interface_name, |
| 113 | ], |
| 114 | stderr=subprocess.STDOUT, |
| 115 | universal_newlines=True) |
| 116 | except subprocess.CalledProcessError as e: |
| 117 | logger.error('Failed to run `ip` command: %s', str(e)) |
| 118 | return status |
| 119 | |
| 120 | try: |
| 121 | json_output = json.loads(ip_cmd_out_raw) |
| 122 | except json.decoder.JSONDecodeError as e: |
| 123 | logger.error('Failed to parse JSON output of `ip` command: %s', str(e)) |
| 124 | return status |
| 125 | |
| 126 | if len(json_output) == 0: |
| 127 | return status |
| 128 | data = json_output[0] |
| 129 | |
| 130 | if 'operstate' in data: |
| 131 | status.is_connected = data['operstate'] == 'UP' |
| 132 | if 'address' in data: |
| 133 | status.mac_address = data['address'].replace(':', '-') |
no test coverage detected