diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index d0d86ce..8f5e9b2 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -689,43 +689,45 @@ class NetworkStateInterpreter(object):
def _normalize_subnet(subnet):
- subnet = copy.deepcopy(subnet)
- for k in ('address', 'gateway', 'netmask'):
- if k in subnet and not subnet[k]:
- del subnet[k]
+ # Prune all keys with None values.
+ normalized_subnet = dict((k, v) for k, v in subnet.iteritems() if v)
- if 'address' in subnet:
- addr = subnet['address']
+ addr = subnet.get('address')
+ prefix = subnet.get('prefix')
+ netmask = subnet.get('netmask')
+ if addr:
if "/" in addr:
- toks = subnet['address'].split("/", 2)
+ toks = addr.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'))
+ # XXX If prefix is defined by the user but address is also CIDR, we
+ # silently overwrite the user's original prefix here. We should
+ # log a warning about ignoring user-defined prefix and netmask if
+ # present.
+ subnet['prefix'] = toks[1]
+ elif netmask:
+ subnet['prefix'] = mask_to_net_prefix(netmask)
else:
- if is_ipv6_addr(subnet['address']):
+ if is_ipv6_addr(addr):
subnet['prefix'] = 64
else:
subnet['prefix'] = 24
+ # XXX this 'try' here so we don't have to handle non-ints in 2 places
+ # above int(toks[1]) and int(subnet['prefix'])
+ if prefix:
+ try:
+ prefix = int(prefix)
+ except ValueError:
+ raise TypeError('prefix {} is not an integer'.format(prefix))
+
#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']
-
- if 'addr' in subnet and not subnet['addr']:
- del subnet['addr']
-
- routes = subnet.get('routes')
- if not routes:
- subnet['routes'] = []
- else:
- subnet['routes'] = [_normalize_route(r) for r in subnet['routes']]
+ # Remove netmask and
+ subnet.pop('netmask', None)
+ subnet['routes'] = [_normalize_route(r) for r in subnet.get('routes', [])]
return subnet