7FA2A64613ACBFB33C2065E
     'ˆÄÐ„Œ‰ÏÁÎ ?Æ    '# Copyright (C) 2012 Canonical Ltd.
# Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
# Copyright (C) 2012 Yahoo! Inc.
#
# Author: Scott Moser <scott.moser@canonical.com>
# Author: Juerg Haefliger <juerg.haefliger@hp.com>
# Author: Joshua Harlow <harlowja@yahoo-inc.com>
#
# This file is part of cloud-init. See LICENSE file for license information.

from copy import copy, deepcopy
import re

from cloudinit import log as logging
from cloudinit.net.network_state import net_prefix_to_ipv4_mask
from cloudinit import util

from cloudinit.simpletable import SimpleTable

LOG = logging.getLogger()


DEFAULT_NETDEV_INFO = {
    "ipv4": [],
    "ipv6": [],
    "hwaddr": "",
    "up": False
}


def _netdev_info_iproute(ipaddr_out):
    """
    Get network device dicts from ip route and ip link info.

    @param ipaddr_out: Output string from 'ip addr show' command.

    @returns: A dict of device info keyed by network device name containing
              device configuration values.
    @raise: TypeError if ipaddr_out isn't a string.
    """
    devs = {}
    dev_name = None
    for num, line in enumerate(ipaddr_out.splitlines()):
        m = re.match(r'^\d+:\s(?P<dev>[^:]+):\s+<(?P<flags>\S+)>\s+.*', line)
        if m:
            dev_name = m.group('dev').lower().split('@')[0]
            flags = m.group('flags').split(',')
            devs[dev_name] = {
                'ipv4': [], 'ipv6': [], 'hwaddr': '',
                'up': bool('UP' in flags and 'LOWER_UP' in flags),
            }
        elif 'inet6' in line:
            m = re.match(
                r'\s+inet6\s(?P<ip>\S+)\sscope\s(?P<scope6>\S+).*', line)
            if not m:
                LOG.warning(
                    'Could not parse ip addr show: (line:%d) %s', num, line)
                continue
            devs[dev_name]['ipv6'].append(m.groupdict())
        elif 'inet' in line:
            m = re.match(
                r'\s+inet\s(?P<cidr4>\S+)(\sbrd\s(?P<bcast>\S+))?\sscope\s'
                r'(?P<scope>\S+).*', line)
            if not m:
                LOG.warning(
                    'Could not parse ip addr show: (line:%d) %s', num, line)
                continue
            match = m.groupdict()
            cidr4 = match.pop('cidr4')
            addr, _, prefix = cidr4.partition('/')
            if not prefix:
                prefix = '32'
            devs[dev_name]['ipv4'].append({
                'ip': addr,
                'bcast': match['bcast'] if match['bcast'] else '',
                'mask': net_prefix_to_ipv4_mask(prefix),
                'scope': match['scope']})
        elif 'link' in line:
            m = re.match(
                r'\s+link/(?P<link_type>\S+)\s(?P<hwaddr>\S+).*', line)
            if not m:
                LOG.warning(
                    'Could not parse ip addr show: (line:%d) %s', num, line)
                continue
            if m.group('link_type') == 'ether':
                devs[dev_name]['hwaddr'] = m.group('hwaddr')
            else:
                devs[dev_name]['hwaddr'] = ''
        else:
            continue
    return devs


def _netdev_info_ifconfig(ifconfig_data):
    # fields that need to be returned in devs for each dev
    devs = {}
    for line in ifconfig_data.splitlines():
        if len(line) == 0:
            continue
        if line[0] not in ("\t", " "):
            curdev = line.split()[0]
            # current ifconfig pops a ':' on the end of the device
            if curdev.endswith(':'):
                curdev = curdev[:-1]
            if curdev not in devs:
                devs[curdev] = deepcopy(DEFAULT_NETDEV_INFO)
        toks = line.lower().strip().split()
        if toks[0] == "up":
            devs[curdev]['up'] = True
        # If the output of ifconfig doesn't contain the required info in the
        # obvious place, use a regex filter to be sure.
        elif len(toks) > 1:
            if re.search(r"flags=\d+<up,", toks[1]):
                devs[curdev]['up'] = True

        for i in range(len(toks)):
            