__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

www-data@216.73.216.10: ~ $
#!/usr/bin/python3
#
# Copyright (C) 2022 Canonical, Ltd.
# Author: Lukas Märdian <slyon@ubuntu.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

'''netplan status command line'''

import json
import logging
import re
from netplan.netdef import NetplanRoute

import yaml

from .. import utils
from ..state import NetplanConfigState, SystemConfigState, JSON
from ..state_diff import DiffJSONEncoder, NetplanDiffState


MATCH_TAGS = re.compile(r'\[([a-z0-9]+)\].*\[\/\1\]')
RICH_OUTPUT = False
try:
    from rich.console import Console
    from rich.highlighter import RegexHighlighter
    from rich.theme import Theme

    class NetplanHighlighter(RegexHighlighter):
        base_style = 'netplan.'
        highlights = [
            r'(^|[\s\/])(?P<int>\d+)([\s:]?\s|$)',
            r'(?P<str>(\"|\').+(\"|\'))',
            ]
    RICH_OUTPUT = True
except ImportError:  # pragma: nocover (we mock RICH_OUTPUT, ignore the logging)
    logging.debug("python3-rich not found, falling back to plain output")


class NetplanStatus(utils.NetplanCommand):
    def __init__(self):
        super().__init__(command_id='status',
                         description='Query networking state of the running system',
                         leaf=True)
        self.all = False
        self.state_diff = None
        self.route_lookup_table_names = {}

    def run(self):
        self.parser.add_argument('ifname', nargs='?', type=str, default=None,
                                 help='Show only this interface')
        self.parser.add_argument('-a', '--all', action='store_true',
                                 help='Show all interface data (incl. inactive)')
        self.parser.add_argument('-v', '--verbose', action='store_true',
                                 help='Show extra information')
        self.parser.add_argument('-f', '--format', default='tabular',
                                 help='Output in machine readable `json` or `yaml` format')
        self.parser.add_argument('--diff', action='store_true',
                                 help='Show the differences between the system\'s and netplan\'s states')
        self.parser.add_argument('--diff-only', action='store_true',
                                 help='Only show the differences between the system\'s and netplan\'s states')
        self.parser.add_argument('--root-dir',
                                 help='Search for configuration files in this root directory instead of /')

        self.func = self.command
        self.parse_args()
        self.run_command()

    def _create_pretty_print(self, _console_width):
        if RICH_OUTPUT:
            # TODO: Use a proper (subiquity?) color palette
            theme = Theme({
                'netplan.int': 'bold cyan',
                'netplan.str': 'yellow',
                'muted': 'grey62',
                'online': 'green bold',
                'offline': 'red bold',
                'unknown': 'yellow bold',
                'highlight': 'bold'
                })
            if self.diff:
                theme = Theme({
                    'netplan.int': 'grey62',
                    'netplan.str': 'grey62',
                    'muted': 'grey62',
                    'online': 'green bold',
                    'offline': 'red bold',
                    'unknown': 'yellow bold',
                    'highlight': 'bold'
                    })

            console = Console(highlighter=NetplanHighlighter(), theme=theme,
                              width=_console_width, emoji=False)
            pprint = console.print
        else:
            pprint = self.plain_print

        return pprint

    def _get_interface_diff(self, ifname) -> dict:
        if self.state_diff:
            if diff := self.state_diff['interfaces'].get(ifname):
                if diff.get('system_state') or diff.get('netplan_state'):
                    return diff
        return {}

    def _is_interface_missing_in_netplan(self, ifname) -> bool:
        if self.state_diff:
            if missing := self.state_diff.get('missing_interfaces_netplan'):
                if ifname in missing:
                    return True
        return False

    def _get_missing_property_list(self, ifname: str, state: str, property: str) -> list[str]:
        if self.state_diff:
            if diff := self.state_diff['interfaces'].get(ifname):
                return diff.get(state, {}).get(property, [])
        return []

    def _get_missing_property_str(self, ifname: str, state: str, property: str) -> str:
        if self.state_diff:
            if diff := self.state_diff['interfaces'].get(ifname):
                return diff.get(state, {}).get(property, '')
        return ''

    def _get_missing_property_set(self, ifname: str, state: str, property: str) -> set:
        if self.state_diff:
            if diff := self.state_diff['interfaces'].get(ifname):
                return diff.get(state, {}).get(property, set())
        return set()

    def _get_missing_property_bool(self, ifname: str, state: str, property: str) -> bool:
        if self.state_diff:
            if diff := self.state_diff['interfaces'].get(ifname):
                return diff.get(state, {}).get(property, False)
        return False

    def _get_missing_netplan_addresses(self, ifname) -> list[str]:
        return self._get_missing_property_list(ifname, 'netplan_state', 'missing_addresses')

    def _get_missing_system_nameservers(self, ifname) -> list[str]:
        return self._get_missing_property_list(ifname, 'system_state', 'missing_nameservers_addresses')

    def _get_missing_netplan_nameservers(self, ifname) -> list[str]:
        return self._get_missing_property_list(ifname, 'netplan_state', 'missing_nameservers_addresses')

    def _get_missing_netplan_search(self, ifname) -> list[str]:
        return self._get_missing_property_list(ifname, 'netplan_state', 'missing_nameservers_search')

    def _get_missing_system_search(self, ifname) -> list[str]:
        return self._get_missing_property_list(ifname, 'system_state', 'missing_nameservers_search')

    def _get_missing_system_macaddress(self, ifname) -> str:
        return self._get_missing_property_str(ifname, 'system_state', 'missing_macaddress')

    def _get_missing_netplan_routes(self, ifname) -> set[NetplanRoute]:
        return self._get_missing_property_set(ifname, 'netplan_state', 'missing_routes')

    def _get_missing_system_routes(self, ifname) -> set[NetplanRoute]:
        return self._get_missing_property_set(ifname, 'system_state', 'missing_routes')

    def _is_missing_dhcp4_address(self, ifname) -> bool:
        return self._get_missing_property_bool(ifname, 'system_state', 'missing_dhcp4_address')

    def _is_missing_dhcp6_address(self, ifname) -> bool:
        return self._get_missing_property_bool(ifname, 'system_state', 'missing_dhcp6_address')

    def _get_missing_system_bond_link(self, ifname) -> str:
        return self._get_missing_property_str(ifname, 'system_state', 'missing_bond_link')

    def _get_missing_netplan_bond_link(self, ifname) -> str:
        return self._get_missing_property_str(ifname, 'netplan_state', 'missing_bond_link')

    def _get_missing_system_bridge_link(self, ifname) -> str:
        return self._get_missing_property_str(ifname, 'system_state', 'missing_bridge_link')

    def _get_missing_netplan_bridge_link(self, ifname) -> str:
        return self._get_missing_property_str(ifname, 'netplan_state', 'missing_bridge_link')

    def _get_missing_system_vrf_link(self, ifname) -> str:
        return self._get_missing_property_str(ifname, 'system_state', 'missing_vrf_link')

    def _get_missing_netplan_vrf_link(self, ifname) -> str:
        return self._get_missing_property_str(ifname, 'netplan_state', 'missing_vrf_link')

    def _get_missing_netplan_members(self, ifname) -> list[str]:
        return self._get_missing_property_list(ifname, 'netplan_state', 'missing_interfaces')

    def _get_missing_system_members(self, ifname) -> list[str]:
        return self._get_missing_property_list(ifname, 'system_state', 'missing_interfaces')

    def _get_missing_system_interfaces(self) -> dict:
        if self.state_diff:
            return self.state_diff.get('missing_interfaces_system', {})
        return {}

    def _has_diff(self, ifname) -> bool:
        if self._is_interface_missing_in_netplan(ifname):
            return True
        if self.state_diff:
            if diff := self.state_diff['interfaces'].get(ifname):
                if diff.get('system_state') or diff.get('netplan_state'):
                    return True
        return False

    def _display_global_state(self, data):
        global_state = data.get('netplan-global-state', {})
        self.pprint(('{title:>'+self.PAD+'} {value}').format(
            title='Online state:',
            value='[online]online[/online]' if global_state.get('online', False) else '[offline]offline[/offline]',
            ))
        ns = global_state.get('nameservers', {})
        dns_addr: list = ns.get('addresses', [])
        dns_mode: str = ns.get('mode')
        dns_search: list = ns.get('search', [])
        if dns_addr:
            for i, val in enumerate(dns_addr):
                self.pprint(('{title:>'+self.PAD+'} {value}[muted]{mode}[/muted]').format(
                    title='DNS Addresses:' if i == 0 else '',
                    value=val,
                    mode=' ({})'.format(dns_mode) if dns_mode else '',
                    ))
        if dns_search:
            for i, val in enumerate(dns_search):
                self.pprint(('{title:>'+self.PAD+'} {value}').format(
                    title='DNS Search:' if i == 0 else '',
                    value=val,
                    ))
        self.pprint()

    def _display_interface_header(self, ifname: str, data):
        state = data.get('operstate', 'UNKNOWN') + '/' + data.get('adminstate', 'UNKNOWN')
        scolor = 'unknown'
        if state == 'UP/UP':
            state = 'UP'
            scolor = 'online'
        elif state == 'DOWN/DOWN':
            state = 'DOWN'
            scolor = 'offline'
        full_type = data.get('type', 'other')
        ssid = data.get('ssid')
        tunnel_mode = data.get('tunnel_mode')
        if full_type == 'wifi' and ssid:
            full_type += ('/"' + ssid + '"')
        elif full_type == 'tunnel' and tunnel_mode:
            full_type += ('/' + tunnel_mode)

        format = '[{col}]●[/{col}] {idx:>2}: {name} {type} [{col}]{state}[/{col}] ({backend}{netdef})'
        netdef = ': [highlight]{}[/highlight]'.format(data.get('id')) if data.get('id') else ''
        extra = ''
        sign = ''
        if self.diff:
            if self._is_interface_missing_in_netplan(ifname):
                sign = self.PLUS
                format = '{sign} [{col}]●[/{col}] {idx:>2}: [green][highlight]{name} {type}'
                format += ' [{col}]{state}[/{col}] ({backend}{netdef})[/highlight][/green]'
            else:
                format = '  [muted]● {idx:>2}: {name} {type} {state} ({backend}{netdef})[/muted]'
                netdef = ': {}'.format(data.get('id')) if data.get('id') else ''

        if not self.diff_only or self._has_diff(ifname):
            self.pprint(format.format(
                sign=sign,
                col=scolor,
                idx=data.get('index', '?'),
                name=ifname,
                type=full_type,
                state=state,
                backend=data.get('backend', 'unmanaged'),
                netdef=netdef,
                extra=extra,
                ))

    def _display_mac_address(self, ifname: str, data):
        if macaddress := data.get('macaddress'):
            hide_macaddress = False
            missing_system_macaddress = self._get_missing_system_macaddress(ifname)
            format = '{title:>'+self.PAD+'} {mac}[muted]{vendor}[/muted]'
            sign = ''
            if self.diff and not missing_system_macaddress:
                format = '  [muted]{title:>'+self.PAD+'} {mac}{vendor}[/muted]'
                if self.diff_only:
                    hide_macaddress = True
            elif self.diff and missing_system_macaddress:
                sign = self.PLUS
                format = '{sign} {title:>'+self.PAD+'} [green][highlight]{mac}{vendor}[/highlight][/green]'

            if not hide_macaddress:
                self.pprint((format).format(
                    sign=sign,
                    title='MAC Address:',
                    mac=macaddress,
                    vendor=' ({})'.format(data.get('vendor', '')) if data.get('vendor') else '',
                    ))

                if self.diff and missing_system_macaddress:
                    sign = self.MINUS
                    format = '{sign} {title:>'+self.PAD+'} [red][highlight]{mac}{vendor}[/highlight][/red]'
                    self.pprint((format).format(
                        sign=sign,
                        title='',
                        mac=missing_system_macaddress,
                        vendor=' ({})'.format(data.get('vendor', '')) if data.get('vendor') else '',
                        ))

    def _display_ip_addresses(self, ifname: str, data):
        lst: list = data.get('addresses', [])
        addresses_displayed = 0
        if lst:
            missing_netplan_addresses = self._get_missing_netplan_addresses(ifname)
            for obj in lst:
                sign = ''
                hide_address = False
                ip, extra = list(obj.items())[0]  # get first (and only) address
                prefix = extra.get('prefix', '')
                flags = []
                if extra.get('flags'):  # flags
                    flags = extra.get('flags', [])
                highlight_start = ''
                highlight_end = ''
                if not flags or 'dhcp' in flags:
                    highlight_start = '[highlight]'
                    highlight_end = '[/highlight]'

                address = f'{ip}/{prefix}'
                if self.diff and address not in missing_netplan_addresses:
                    format = '  [muted]{title:>'+self.PAD+'} {start}{ip}/{prefix}{end}{extra}[/muted]'
                    highlight_start = ''
                    highlight_end = ''
                    if self.diff_only:
                        hide_address = True
                elif self.diff and address in missing_netplan_addresses:
                    sign = self.PLUS
                    format = '{sign} {title:>'+self.PAD+'} [green]{start}{ip}/{prefix}{extra}{end}[/green]'
                    highlight_start = '[highlight]'
                    highlight_end = '[/highlight]'
                else:
                    format = '{title:>'+self.PAD+'} {start}{ip}/{prefix}{end}[muted]{extra}[/muted]'

                if not hide_address:
                    self.pprint((format).format(
                        sign=sign,
                        title='Addresses:' if addresses_displayed == 0 else '',
                        ip=ip,
                        prefix=prefix,
                        extra=' ('+', '.join(flags)+')' if flags else '',
                        start=highlight_start,
                        end=highlight_end,
                        ))
                    addresses_displayed += 1

        if diff := self._get_interface_diff(ifname):
            sign = self.MINUS
            if missing_addresses := diff.get('system_state', {}).get('missing_addresses'):
                for ip in missing_addresses:
                    self.pprint(('{sign} {title:>'+self.PAD+'} [highlight][red]{ip}[/red][/highlight]').format(
                        sign=sign,
                        title='Addresses:' if addresses_displayed == 0 else '',
                        ip=ip,
                        ))
                    addresses_displayed += 1
            if self._is_missing_dhcp4_address(ifname):
                self.pprint(('{sign} {title:>'+self.PAD+'} [highlight][red]0.0.0.0/0 (dhcp)[/red][/highlight]').format(
                    sign=sign,
                    title='Addresses:' if addresses_displayed == 0 else '',
                    ))
                addresses_displayed += 1
            if self._is_missing_dhcp6_address(ifname):
                self.pprint(('{sign} {title:>'+self.PAD+'} [highlight][red]::/0 (dhcp)[/red][/highlight]').format(
                    sign=sign,
                    title='Addresses:' if addresses_displayed == 0 else '',
                    ))

    def _display_dns_addresses(self, ifname: str, data):
        lst = data.get('dns_addresses', [])
        nameservers_displayed = 0
        if lst:
            missing_netplan_nameservers = self._get_missing_netplan_nameservers(ifname)
            for val in lst:
                sign = ''
                hide_nameserver = False
                if self.diff and val not in missing_netplan_nameservers:
                    format = '  [muted]{title:>'+self.PAD+'} {value}[/muted]'
                    highlight_start = ''
                    highlight_end = ''
                    if self.diff_only:
                        hide_nameserver = True
                elif self.diff and val in missing_netplan_nameservers:
                    sign = self.PLUS
                    format = '{sign} {title:>'+self.PAD+'} [green]{start}{value}{end}[/green]'
                    highlight_start = '[highlight]'
                    highlight_end = '[/highlight]'
                else:
                    format = '{title:>'+self.PAD+'} {value}'
                    highlight_start = ''
                    highlight_end = ''

                if not hide_nameserver:
                    self.pprint((format).format(
                        sign=sign,
                        title='DNS Addresses:' if nameservers_displayed == 0 else '',
                        value=val,
                        start=highlight_start,
                        end=highlight_end
                        ))
                    nameservers_displayed += 1

        if self._has_diff(ifname):
            if missing_nameservers_addresses := self._get_missing_system_nameservers(ifname):
                sign = self.MINUS
                for ip in missing_nameservers_addresses:
                    self.pprint(('{sign} {title:>'+self.PAD+'} [red][highlight]{ip}[/highlight][/red]').format(
                        sign=sign,
                        title='DNS Addresses:' if nameservers_displayed == 0 else '',
                        ip=ip,
                        ))
                    nameservers_displayed += 1

    def _display_dns_search(self, ifname, data):
        lst = data.get('dns_search', [])
        searches_displayed = 0
        if lst:
            missing_netplan_search = self._get_missing_netplan_search(ifname)
            for i, val in enumerate(lst):
                sign = ''
                hide_search = False
                if self.diff and val not in missing_netplan_search:
                    format = '  [muted]{title:>'+self.PAD+'} {value}[/muted]'
                    highlight_start = ''
                    highlight_end = ''
                    if self.diff_only:
                        hide_search = True
                elif self.diff and val in missing_netplan_search:
                    sign = self.PLUS
                    format = '{sign} {title:>'+self.PAD+'} [green]{start}{value}{end}[/green]'
                    highlight_start = '[highlight]'
                    highlight_end = '[/highlight]'
                else:
                    format = '{title:>'+self.PAD+'} {value}'
                    highlight_start = ''
                    highlight_end = ''

                if not hide_search:
                    self.pprint((format).format(
                        sign=sign,
                        title='DNS Search:' if searches_displayed == 0 else '',
                        value=val,
                        start=highlight_start,
                        end=highlight_end
                        ))
                    searches_displayed += 1

        if self._has_diff(ifname):
            if missing_nameservers_search := self._get_missing_system_search(ifname):
                sign = self.MINUS
                for domain in missing_nameservers_search:
                    self.pprint(('{sign} {title:>'+self.PAD+'} [red][highlight]{domain}[/highlight][/red]').format(
                        sign=sign,
                        title='DNS Search:' if searches_displayed == 0 else '',
                        domain=domain,
                        ))
                    searches_displayed += 1

    def _display_routes(self, ifname, data):
        lst = data.get('routes', [])
        missing_netplan_routes = self._get_missing_netplan_routes(ifname)
        missing_system_routes = self._get_missing_system_routes(ifname)
        routes_displayed = 0
        if lst:
            if not self.route_lookup_table_names:
                self.route_lookup_table_names = utils.route_table_lookup()

            diff_state = NetplanDiffState(None, None)
            routes = [diff_state._system_route_to_netplan(route) for route in lst]
            if not self.verbose:
                # filter out routes that are not in the main route table
                routes = filter(lambda r: r.table == 254, routes)
            for route in routes:
                hide_route = False
                default_start = ''
                default_end = ''
                if route.to == 'default':
                    default_start = '[highlight]'
                    default_end = '[/highlight]'
                via = ''
                if route.via:
                    via = ' via ' + route.via
                src = ''
                if route.from_addr:
                    src = ' from ' + route.from_addr
                metric = ''
                if route.metric < NetplanRoute._METRIC_UNSPEC_:
                    metric = ' metric ' + str(route.metric)
                table = ''
                if self.verbose and route.table > 0:
                    table = ' table {}'.format(self.route_lookup_table_names.get(route.table, route.table))

                extra = []
                if route.protocol and route.protocol != 'kernel':
                    proto = route.protocol
                    extra.append(proto)
                if route.scope and route.scope != 'global':
                    scope = route.scope
                    extra.append(scope)
                if route.type and route.type != 'unicast':
                    type = route.type
                    extra.append(type)

                sign = ''
                if self.diff and route not in missing_netplan_routes:
                    format = '  [muted]{title:>'+self.PAD+'} {start}{to}{via}{src}{metric}{table}{end}{extra}[/muted]'
                    default_start = ''
                    default_end = ''
                    if self.diff_only:
                        hide_route = True
                elif self.diff and route in missing_netplan_routes:
                    sign = self.PLUS
                    format = '{sign} {title:>'+self.PAD+'} [green][highlight]{start}{to}{via}{src}{metric}'
                    format += '{table}{end}{extra}[/highlight][/green]'
                else:
                    format = '{title:>'+self.PAD+'} {start}{to}{via}{src}{metric}{table}{end}[muted]{extra}[/muted]'

                if not hide_route:
                    self.pprint(format.format(
                        sign=sign,
                        title='Routes:' if routes_displayed == 0 else '',
                        to=route.to,
                        via=via,
                        src=src,
                        metric=metric,
                        table=table,
                        extra=' ('+', '.join(extra)+')' if extra else '',
                        start=default_start,
                        end=default_end))
                    routes_displayed += 1

        if self.diff:
            for route in missing_system_routes:
                via = ''
                if route.via:
                    via = ' via ' + route.via
                src = ''
                if route.from_addr:
                    src = ' from ' + route.from_addr
                metric = ''
                if route.metric < NetplanRoute._METRIC_UNSPEC_:
                    metric = ' metric ' + str(route.metric)
                table = ''
                if self.verbose and route.table > 0:
                    table = ' table {}'.format(self.route_lookup_table_names.get(route.table, route.table))

                extra = []
                if route.scope and route.scope != 'global':
                    scope = route.scope
                    extra.append(scope)
                if route.type and route.type != 'unicast':
                    type = route.type
                    extra.append(type)

                sign = self.MINUS
                format = '{sign} {title:>'+self.PAD+'} {start}[red]{to}{via}{src}{metric}{table}{extra}[/red]{end}'
                self.pprint(format.format(
                    sign=sign,
                    title='Routes:' if routes_displayed == 0 else '',
                    to=route.to,
                    via=via,
                    src=src,
                    metric=metric,
                    table=table,
                    extra=' ('+', '.join(extra)+')' if extra else '',
                    start='[highlight]',
                    end='[/highlight]'))
                routes_displayed += 1

    def _display_bridge(self, ifname, data):
        val = data.get('bridge')
        if val:
            missing_netplan_bridge_link = self._get_missing_netplan_bridge_link(ifname)
            format = '{title:>'+self.PAD+'} {value}'
            sign = ''
            hide_bridge = False
            if self.diff and not missing_netplan_bridge_link:
                format = '  [muted]{title:>'+self.PAD+'} {value}[/muted]'
                if self.diff_only:
                    hide_bridge = True
            elif self.diff and missing_netplan_bridge_link:
                sign = self.PLUS
                format = '{sign} {title:>'+self.PAD+'} [highlight][green]{value}[/green][/highlight]'
                val = missing_netplan_bridge_link

            if not hide_bridge:
                self.pprint((format).format(
                    sign=sign,
                    title='Bridge:',
                    value=val,
                    ))
        if missing_system_bridge_link := self._get_missing_system_bridge_link(ifname):
            sign = self.MINUS
            format = '{sign} {title:>'+self.PAD+'} [highlight][red]{value}[/red][/highlight]'
            self.pprint((format).format(
                sign=sign,
                title='Bridge:',
                value=missing_system_bridge_link,
            ))

    def _display_bond(self, ifname, data):
        val = data.get('bond')
        if val:
            missing_netplan_bond_link = self._get_missing_netplan_bond_link(ifname)
            format = '{title:>'+self.PAD+'} {value}'
            sign = ''
            hide_bond = False
            if self.diff and not missing_netplan_bond_link:
                format = '  [muted]{title:>'+self.PAD+'} {value}[/muted]'
                if self.diff_only:
                    hide_bond = True
            elif self.diff and missing_netplan_bond_link:
                sign = self.PLUS
                format = '{sign} {title:>'+self.PAD+'} [highlight][green]{value}[/green][/highlight]'
                val = missing_netplan_bond_link

            if not hide_bond:
                self.pprint((format).format(
                    sign=sign,
                    title='Bond:',
                    value=val,
                    ))
        if missing_system_bond_link := self._get_missing_system_bond_link(ifname):
            sign = self.MINUS
            format = '{sign} {title:>'+self.PAD+'} [highlight][red]{value}[/red][/highlight]'
            self.pprint((format).format(
                sign=sign,
                title='Bond:',
                value=missing_system_bond_link,
            ))

    def _display_vrf(self, ifname, data):
        val = data.get('vrf')
        if val:
            missing_netplan_vrf_link = self._get_missing_netplan_vrf_link(ifname)
            format = '{title:>'+self.PAD+'} {value}'
            sign = ''
            hide_vrf = False
            if self.diff and not missing_netplan_vrf_link:
                format = '  [muted]{title:>'+self.PAD+'} {value}[/muted]'
                if self.diff_only:
                    hide_vrf = True
            elif self.diff and missing_netplan_vrf_link:
                sign = self.PLUS
                format = '{sign} {title:>'+self.PAD+'} [highlight][green]{value}[/green][/highlight]'
                val = missing_netplan_vrf_link

            if not hide_vrf:
                self.pprint((format).format(
                    sign=sign,
                    title='VRF:',
                    value=val,
                    ))
        if missing_system_vrf_link := self._get_missing_system_vrf_link(ifname):
            sign = self.MINUS
            format = '{sign} {title:>'+self.PAD+'} [highlight][red]{value}[/red][/highlight]'
            self.pprint((format).format(
                sign=sign,
                title='VRF:',
                value=missing_system_vrf_link,
            ))

    def _display_members(self, ifname: str, data):
        lst = data.get('interfaces', [])
        members_displayed = 0
        if lst:
            missing_netplan_interfaces = self._get_missing_netplan_members(ifname)
            for val in lst:
                sign = ''
                hide_member = False
                if self.diff and val not in missing_netplan_interfaces:
                    format = '  [muted]{title:>'+self.PAD+'} {value}[/muted]'
                    highlight_start = ''
                    highlight_end = ''
                    if self.diff_only:
                        hide_member = True
                elif self.diff and val in missing_netplan_interfaces:
                    sign = self.PLUS
                    format = '{sign} {title:>'+self.PAD+'} [green]{start}{value}{end}[/green]'
                    highlight_start = '[highlight]'
                    highlight_end = '[/highlight]'
                else:
                    format = '{title:>'+self.PAD+'} {value}'
                    highlight_start = ''
                    highlight_end = ''

                if not hide_member:
                    self.pprint((format).format(
                        sign=sign,
                        title='Interfaces:' if members_displayed == 0 else '',
                        value=val,
                        start=highlight_start,
                        end=highlight_end,
                        ))
                    members_displayed += 1

        if self._has_diff(ifname):
            if missing_members := self._get_missing_system_members(ifname):
                sign = self.MINUS
                for member in missing_members:
                    self.pprint(('{sign} {title:>'+self.PAD+'} [red][highlight]{member}[/highlight][/red]').format(
                        sign=sign,
                        title='Interfaces:' if members_displayed == 0 else '',
                        member=member,
                        ))
                    members_displayed += 1

    def _display_activation_mode(self, data):
        val = data.get('activation_mode')
        if val:
            self.pprint(('{title:>'+self.PAD+'} {value}').format(
                title='Activation Mode:',
                value=val,
                ))

    def _display_missing_interfaces(self):
        missing_interfaces = self._get_missing_system_interfaces()
        sign = self.MINUS
        for index, (interface, properties) in enumerate(missing_interfaces.items(), 1):
            # If we called netplan status for a single interface, ignore the rest
            if self.ifname and self.ifname != interface:
                continue

            self.pprint('{sign} [{col}]● {idx:>2}  {name} {type}[/{col}]'.format(
                sign=sign,
                col='red',
                idx='',
                name=interface,
                type=properties.get('type'),
                ))

            if index != len(missing_interfaces) and not self.ifname:
                # linebreak only if it's not the last interfaces or the only one
                self.pprint()

    def plain_print(self, *args, **kwargs):
        if len(args):
            lst = list(args)
            while True:
                tags = MATCH_TAGS.findall(lst[0])
                if not tags:
                    break
                for tag in tags:
                    # remove matching opening and closing tag
                    lst[0] = lst[0].replace('[{}]'.format(tag), '')\
                                   .replace('[/{}]'.format(tag), '')
            return print(*lst, **kwargs)
        return print(*args, **kwargs)

    def pretty_print(self, data: JSON, total: int, _console_width=None) -> None:
        self.pprint = self._create_pretty_print(_console_width)
        self.PLUS = '[green]+[/green]'
        self.MINUS = '[red]-[/red]'
        self.PAD = '18'
        if self.diff:
            # In diff mode we shift the text 2 columns to the right so we can display
            # + and - and maintain the alignment consistency
            self.PAD = '20'

        # Global state
        if not self.diff:
            self._display_global_state(data)

        # Per interface
        interfaces = [(key, data[key]) for key in data if key != 'netplan-global-state']
        if self.diff_only:
            # in diff-only mode we filter out interfaces that don't have any diff
            interfaces = list(filter(lambda i: self._has_diff(i[0]), interfaces))

        missing_interfaces = self._get_missing_system_interfaces()
        for index, (ifname, ifconfig) in enumerate(interfaces, 1):
            # If we called netplan status for a single interface, ignore the rest
            if self.ifname and self.ifname != ifname:
                continue

            self._display_interface_header(ifname, ifconfig)
            self._display_mac_address(ifname, ifconfig)
            self._display_ip_addresses(ifname, ifconfig)
            self._display_dns_addresses(ifname, ifconfig)
            self._display_dns_search(ifname, ifconfig)
            self._display_routes(ifname, ifconfig)
            self._display_bridge(ifname, ifconfig)
            self._display_bond(ifname, ifconfig)
            self._display_vrf(ifname, ifconfig)
            self._display_members(ifname, ifconfig)
            self._display_activation_mode(ifconfig)

            if not self.diff_only or self._has_diff(ifname):
                # we only break to a new line if we still have data to display
                if (index != len(interfaces) or len(missing_interfaces) > 0) and not self.ifname:
                    self.pprint()

        if self.diff:
            self._display_missing_interfaces()

        hidden = total - len(interfaces)
        if hidden > 0 and not self.diff:
            self.pprint('\n{} inactive interfaces hidden. Use "--all" to show all.'.format(hidden))

        if self.diff and not self.diff_only:
            self.pprint(
                '\nUse [yellow]"--diff-only"[/yellow] to omit the information that is consistent between the system and Netplan.'
            )

    def command(self):
        # --diff-only implies --diff
        if self.diff_only:
            self.diff = True

        # --diff needs data from all interfaces to work
        if self.diff:
            self.all = True

        system_state = SystemConfigState(self.ifname, self.all)

        output_format = self.format.lower()

        if self.diff:
            netplan_state = NetplanConfigState(rootdir=self.root_dir)
            diff_state = NetplanDiffState(system_state, netplan_state)

            self.state_diff = diff_state.get_diff(self.ifname)

            if output_format == 'json':
                print(json.dumps(self.state_diff, cls=DiffJSONEncoder))
                return
            elif output_format == 'yaml':
                serialized = json.dumps(self.state_diff, cls=DiffJSONEncoder)
                print(yaml.dump(json.loads(serialized)))
                return

        if output_format == 'json':  # structural JSON output
            print(json.dumps(system_state.get_data()))
        elif output_format == 'yaml':  # stuctural YAML output
            print(yaml.dump(system_state.get_data()))
        else:  # pretty print, human readable output
            self.pretty_print(system_state.get_data(), system_state.number_of_interfaces)

Filemanager

Name Type Size Permission Actions
__pycache__ Folder 0755
__init__.py File 1.23 KB 0644
apply.py File 20.05 KB 0644
generate.py File 4.11 KB 0644
get.py File 1.52 KB 0644
info.py File 2.4 KB 0644
ip.py File 6.08 KB 0644
migrate.py File 20.11 KB 0644
set.py File 5.57 KB 0644
sriov_rebind.py File 7.74 KB 0644
status.py File 36.5 KB 0644
try_command.py File 7.83 KB 0644
Filemanager