~alai/charms/trusty/contrail-configuration-inc-timeout/trunk

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/contrib/openstack/context.py

  • Committer: Robert Ayres
  • Date: 2015-08-28 10:58:17 UTC
  • Revision ID: robert.ayres@canonical.com-20150828105817-c8ar12o1x0o35uxc
Sync charm helpers

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
from charmhelpers.core.strutils import bool_from_string
51
51
 
52
52
from charmhelpers.core.host import (
 
53
    get_bond_master,
 
54
    is_phy_iface,
53
55
    list_nics,
54
56
    get_nic_hwaddr,
55
57
    mkdir,
122
124
         of specifying multiple key value pairs within the same string. For
123
125
         example, a string in the format of 'key1=value1, key2=value2' will
124
126
         return a dict of:
125
 
         {'key1': 'value1',
126
 
          'key2': 'value2'}.
 
127
 
 
128
             {'key1': 'value1',
 
129
              'key2': 'value2'}.
127
130
 
128
131
      2. A string in the above format, but supporting a comma-delimited list
129
132
         of values for the same key. For example, a string in the format of
130
133
         'key1=value1, key2=value3,value4,value5' will return a dict of:
131
 
         {'key1', 'value1',
132
 
          'key2', 'value2,value3,value4'}
 
134
 
 
135
             {'key1', 'value1',
 
136
              'key2', 'value2,value3,value4'}
133
137
 
134
138
      3. A string containing a colon character (:) prior to an equal
135
139
         character (=) will be treated as yaml and parsed as such. This can be
136
140
         used to specify more complex key value pairs. For example,
137
141
         a string in the format of 'key1: subkey1=value1, subkey2=value2' will
138
142
         return a dict of:
139
 
         {'key1', 'subkey1=value1, subkey2=value2'}
 
143
 
 
144
             {'key1', 'subkey1=value1, subkey2=value2'}
140
145
 
141
146
    The provided config_flags string may be a list of comma-separated values
142
147
    which themselves may be comma-separated list of values.
891
896
        return ctxt
892
897
 
893
898
    def __call__(self):
894
 
        self._ensure_packages()
895
 
 
896
899
        if self.network_manager not in ['quantum', 'neutron']:
897
900
            return {}
898
901
 
922
925
 
923
926
 
924
927
class NeutronPortContext(OSContextGenerator):
925
 
    NIC_PREFIXES = ['eth', 'bond']
926
928
 
927
929
    def resolve_ports(self, ports):
928
930
        """Resolve NICs not yet bound to bridge(s)
934
936
 
935
937
        hwaddr_to_nic = {}
936
938
        hwaddr_to_ip = {}
937
 
        for nic in list_nics(self.NIC_PREFIXES):
 
939
        for nic in list_nics():
 
940
            # Ignore virtual interfaces (bond masters will be identified from
 
941
            # their slaves)
 
942
            if not is_phy_iface(nic):
 
943
                continue
 
944
 
 
945
            _nic = get_bond_master(nic)
 
946
            if _nic:
 
947
                log("Replacing iface '%s' with bond master '%s'" % (nic, _nic),
 
948
                    level=DEBUG)
 
949
                nic = _nic
 
950
 
938
951
            hwaddr = get_nic_hwaddr(nic)
939
952
            hwaddr_to_nic[hwaddr] = nic
940
953
            addresses = get_ipv4_addr(nic, fatal=False)
960
973
                # trust it to be the real external network).
961
974
                resolved.append(entry)
962
975
 
963
 
        return resolved
 
976
        # Ensure no duplicates
 
977
        return list(set(resolved))
964
978
 
965
979
 
966
980
class OSConfigFlagContext(OSContextGenerator):
1050
1064
        :param config_file : Service's config file to query sections
1051
1065
        :param interface   : Subordinate interface to inspect
1052
1066
        """
1053
 
        self.service = service
1054
1067
        self.config_file = config_file
1055
 
        self.interface = interface
 
1068
        if isinstance(service, list):
 
1069
            self.services = service
 
1070
        else:
 
1071
            self.services = [service]
 
1072
        if isinstance(interface, list):
 
1073
            self.interfaces = interface
 
1074
        else:
 
1075
            self.interfaces = [interface]
1056
1076
 
1057
1077
    def __call__(self):
1058
1078
        ctxt = {'sections': {}}
1059
 
        for rid in relation_ids(self.interface):
 
1079
        rids = []
 
1080
        for interface in self.interfaces:
 
1081
            rids.extend(relation_ids(interface))
 
1082
        for rid in rids:
1060
1083
            for unit in related_units(rid):
1061
1084
                sub_config = relation_get('subordinate_configuration',
1062
1085
                                          rid=rid, unit=unit)
1068
1091
                            'setting from %s' % rid, level=ERROR)
1069
1092
                        continue
1070
1093
 
1071
 
                    if self.service not in sub_config:
1072
 
                        log('Found subordinate_config on %s but it contained'
1073
 
                            'nothing for %s service' % (rid, self.service),
1074
 
                            level=INFO)
1075
 
                        continue
1076
 
 
1077
 
                    sub_config = sub_config[self.service]
1078
 
                    if self.config_file not in sub_config:
1079
 
                        log('Found subordinate_config on %s but it contained'
1080
 
                            'nothing for %s' % (rid, self.config_file),
1081
 
                            level=INFO)
1082
 
                        continue
1083
 
 
1084
 
                    sub_config = sub_config[self.config_file]
1085
 
                    for k, v in six.iteritems(sub_config):
1086
 
                        if k == 'sections':
1087
 
                            for section, config_dict in six.iteritems(v):
1088
 
                                log("adding section '%s'" % (section),
1089
 
                                    level=DEBUG)
1090
 
                                ctxt[k][section] = config_dict
1091
 
                        else:
1092
 
                            ctxt[k] = v
1093
 
 
 
1094
                    for service in self.services:
 
1095
                        if service not in sub_config:
 
1096
                            log('Found subordinate_config on %s but it contained'
 
1097
                                'nothing for %s service' % (rid, service),
 
1098
                                level=INFO)
 
1099
                            continue
 
1100
 
 
1101
                        sub_config = sub_config[service]
 
1102
                        if self.config_file not in sub_config:
 
1103
                            log('Found subordinate_config on %s but it contained'
 
1104
                                'nothing for %s' % (rid, self.config_file),
 
1105
                                level=INFO)
 
1106
                            continue
 
1107
 
 
1108
                        sub_config = sub_config[self.config_file]
 
1109
                        for k, v in six.iteritems(sub_config):
 
1110
                            if k == 'sections':
 
1111
                                for section, config_list in six.iteritems(v):
 
1112
                                    log("adding section '%s'" % (section),
 
1113
                                        level=DEBUG)
 
1114
                                    if ctxt[k].get(section):
 
1115
                                        ctxt[k][section].extend(config_list)
 
1116
                                    else:
 
1117
                                        ctxt[k][section] = config_list
 
1118
                            else:
 
1119
                                ctxt[k] = v
1094
1120
        log("%d section(s) found" % (len(ctxt['sections'])), level=DEBUG)
1095
1121
        return ctxt
1096
1122
 
1267
1293
    def __call__(self):
1268
1294
        ports = config('data-port')
1269
1295
        if ports:
 
1296
            # Map of {port/mac:bridge}
1270
1297
            portmap = parse_data_port_mappings(ports)
1271
 
            ports = portmap.values()
 
1298
            ports = portmap.keys()
 
1299
            # Resolve provided ports or mac addresses and filter out those
 
1300
            # already attached to a bridge.
1272
1301
            resolved = self.resolve_ports(ports)
 
1302
            # FIXME: is this necessary?
1273
1303
            normalized = {get_nic_hwaddr(port): port for port in resolved
1274
1304
                          if port not in ports}
1275
1305
            normalized.update({port: port for port in resolved
1276
1306
                               if port in ports})
1277
1307
            if resolved:
1278
 
                return {bridge: normalized[port] for bridge, port in
 
1308
                return {bridge: normalized[port] for port, bridge in
1279
1309
                        six.iteritems(portmap) if port in normalized.keys()}
1280
1310
 
1281
1311
        return None