1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 | diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index d0d86ce..5dc3179 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -689,44 +689,70 @@ class NetworkStateInterpreter(object):
def _normalize_subnet(subnet):
+ # Prune all keys with None values.
subnet = copy.deepcopy(subnet)
- for k in ('address', 'gateway', 'netmask'):
- if k in subnet and not subnet[k]:
- del subnet[k]
-
- if 'address' in subnet:
- addr = subnet['address']
- if "/" in addr:
- toks = subnet['address'].split("/", 2)
- subnet['address'] = toks[0]
- subnet['prefix'] = int(toks[1])
- elif subnet.get('prefix'):
- subnet['prefix'] = int(subnet['prefix'])
- elif subnet.get('netmask'):
- subnet['prefix'] = mask_to_net_prefix(subnet.get('netmask'))
- else:
- if is_ipv6_addr(subnet['address']):
- subnet['prefix'] = 64
- else:
- subnet['prefix'] = 24
+ normal_subnet = dict((k, v) for k, v in subnet.iteritems() if v)
+
+ normal_subnet.update(
+ _normalize_net_keys(normal_subnet, address_keys=('address')))
+ normal_subnet.pop('netmask', None)
+ subnet['routes'] = [_normalize_route(r) for r in subnet.get('routes', [])]
+ return subnet
+
- #if is_ipv6_addr(addr):
- # subnet['netmask'] = net_prefix_to_ipv6_mask(subnet['prefix'])
- #else:
- # subnet['netmask'] = net_prefix_to_ipv4_mask(subnet['prefix'])
- if 'netmask' in subnet:
- del subnet['netmask']
+def _normalize_net_keys(network, address_keys=()):
- if 'addr' in subnet and not subnet['addr']:
- del subnet['addr']
+ """Normalize dictionary network keys returning prefix and address keys.
- routes = subnet.get('routes')
- if not routes:
- subnet['routes'] = []
+ @param network: A dict of network-related definition containing prefix,
+ netmask and address_keys.
+ @param address_keys: A tuple of keys to search for representing the address
+ or cidr. The first address_key discovered will be used for
+ normalization.
+
+ @returns: A dict containing normalized prefix and matching addr_key.
+ """
+ network = copy.deepcopy(network)
+ net = dict((k, v) for k, v in network.iteritems() if v)
+ addr_key = None
+ for key in address_keys:
+ if net.get(key):
+ addr_key = key
+ break
+ if not addr_key:
+ message = (
+ 'No config network address keys found: %s', ','.join(address_keys))
+ LOG.error(message)
+ raise ValueError(message)
+
+ addr = net.get(addr_key)
+ netmask = net.get('netmask')
+ if "/" in addr:
+ toks = addr.split("/", 2)
+ net[addr_key] = toks[0]
+ # XXX If prefix is defined by the user but addr_key is a CIDR, we
+ # silently overwrite the user's original prefix here. We should
+ # log a warning about ignoring user-defined prefix and netmask if
+ # present.
+ net['prefix'] = toks[1]
+ elif netmask:
+ net['prefix'] = mask_to_net_prefix(netmask)
else:
- subnet['routes'] = [_normalize_route(r) for r in subnet['routes']]
+ if is_ipv6_addr(addr):
+ subnet['prefix'] = 64
+ else:
+ subnet['prefix'] = 24
- return subnet
+ # XXX this 'try' here so we don't have to handle ValueErrors in 2 places
+ # above int(toks[1]) and int(net['prefix'])
+ prefix = net['prefix']
+ if prefix:
+ try:
+ net['prefix'] = int(prefix)
+ except ValueError:
+ raise TypeError(
+ 'Network config prefix {} is not an integer'.format(prefix))
+ return net
def _normalize_route(route):
@@ -738,36 +764,23 @@ def _normalize_route(route):
'metric': integer metric (only if present in input).
'netmask': netmask (string) equivalent to prefix.
"""
-
- route = route.copy()
+ route = copy.deepcopy(route)
print("route=%s" % route)
- if 'network' in route:
- addr = route['network']
- else:
- addr = route['destination']
-
- if "/" in addr:
- toks = route['destination'].split("/", 2)
- route['destination'] = toks[0]
- route['prefix'] = int(toks[1])
- elif route.get('prefix'):
- route['prefix'] = int(route['prefix'])
- elif route.get('netmask'):
- route['prefix'] = mask_to_net_prefix(route.get('netmask'))
-
- if 'netmask' in route:
- del route['netmask']
- #if is_ipv6_addr(addr):
- # route['netmask'] = net_prefix_to_ipv6_mask(route['prefix'])
- #else:
- # route['netmask'] = net_prefix_to_ipv4_mask(route['prefix'])
-
- if 'metric' in route:
- if route['metric'] in ('', None):
- del route['metric']
- else:
- route['metric'] = int(route['metric'])
- return route
+ # Prune None-value keys
+ normal_route = dict((k, v) for k, v in route.iteritems() if v)
+ normal_route.update(
+ _normalize_net_keys(
+ normal_route, address_keys=('network', 'destination')))
+ normal_route.pop('netmask', None)
+
+ metric = normal_route.get('metric')
+ if metric:
+ try:
+ normal_route['metric'] = int(metric)
+ except ValueError:
+ raise TypeError(
+ 'Route config metric {} is not an integer'.format(metric))
+ return normal_route
def _normalize_subnets(subnets):
|