154
160
get_iface_for_address = partial(_get_for_address, key='iface')
156
162
get_netmask_for_address = partial(_get_for_address, key='netmask')
165
def format_ipv6_addr(address):
167
IPv6 needs to be wrapped with [] in url link to parse correctly.
170
address = "[%s]" % address
172
log("Not a valid ipv6 address: %s" % address, level=WARNING)
178
def get_iface_addr(iface='eth0', inet_type='AF_INET', inc_aliases=False,
179
fatal=True, exc_list=None):
181
Return the assigned IP address for a given interface, if any, or [].
183
# Extract nic if passed /dev/ethX
185
iface = iface.split('/')[-1]
189
inet_num = getattr(netifaces, inet_type)
190
except AttributeError:
191
raise Exception('Unknown inet type ' + str(inet_type))
193
interfaces = netifaces.interfaces()
196
for _iface in interfaces:
197
if iface == _iface or _iface.split(':')[0] == iface:
198
ifaces.append(_iface)
199
if fatal and not ifaces:
200
raise Exception("Invalid interface '%s'" % iface)
203
if iface not in interfaces:
205
raise Exception("%s not found " % (iface))
212
for netiface in ifaces:
213
net_info = netifaces.ifaddresses(netiface)
214
if inet_num in net_info:
215
for entry in net_info[inet_num]:
216
if 'addr' in entry and entry['addr'] not in exc_list:
217
addresses.append(entry['addr'])
218
if fatal and not addresses:
219
raise Exception("Interface '%s' doesn't have any %s addresses." %
223
get_ipv4_addr = partial(get_iface_addr, inet_type='AF_INET')
226
def get_iface_from_addr(addr):
227
"""Work out on which interface the provided address is configured."""
228
for iface in netifaces.interfaces():
229
addresses = netifaces.ifaddresses(iface)
230
for inet_type in addresses:
231
for _addr in addresses[inet_type]:
232
_addr = _addr['addr']
234
ll_key = re.compile("(.+)%.*")
235
raw = re.match(ll_key, _addr)
239
log("Address '%s' is configured on iface '%s'" %
243
msg = "Unable to infer net iface on which '%s' is configured" % (addr)
248
"""If no iface provided, inject net iface inferred from unit private
251
def iface_sniffer(*args, **kwargs):
252
if not kwargs.get('iface', None):
253
kwargs['iface'] = get_iface_from_addr(unit_get('private-address'))
255
return f(*args, **kwargs)
261
def get_ipv6_addr(iface=None, inc_aliases=False, fatal=True, exc_list=None,
263
"""Get assigned IPv6 address for a given interface.
265
Returns list of addresses found. If no address found, returns empty list.
267
If iface is None, we infer the current primary interface by doing a reverse
268
lookup on the unit private-address.
270
We currently only support scope global IPv6 addresses i.e. non-temporary
271
addresses. If no global IPv6 address is found, return the first one found
272
in the ipv6 address list.
274
addresses = get_iface_addr(iface=iface, inet_type='AF_INET6',
275
inc_aliases=inc_aliases, fatal=fatal,
280
for addr in addresses:
281
key_scope_link_local = re.compile("^fe80::..(.+)%(.+)")
282
m = re.match(key_scope_link_local, addr)
284
eui_64_mac = m.group(1)
287
global_addrs.append(addr)
290
# Make sure any found global addresses are not temporary
291
cmd = ['ip', 'addr', 'show', iface]
292
out = subprocess.check_output(cmd)
294
key = re.compile("inet6 (.+)/[0-9]+ scope global dynamic.*")
296
key = re.compile("inet6 (.+)/[0-9]+ scope global.*")
299
for line in out.split('\n'):
301
m = re.match(key, line)
302
if m and 'temporary' not in line:
303
# Return the first valid address we find
304
for addr in global_addrs:
305
if m.group(1) == addr:
306
if not dynamic_only or \
307
m.group(1).endswith(eui_64_mac):
314
raise Exception("Interface '%s' doesn't have a scope global "
315
"non-temporary ipv6 address." % iface)
320
def get_bridges(vnic_dir='/sys/devices/virtual/net'):
322
Return a list of bridges on the system or []
324
b_rgex = vnic_dir + '/*/bridge'
325
return [x.replace(vnic_dir, '').split('/')[1] for x in glob.glob(b_rgex)]
328
def get_bridge_nics(bridge, vnic_dir='/sys/devices/virtual/net'):
330
Return a list of nics comprising a given bridge on the system or []
332
brif_rgex = "%s/%s/brif/*" % (vnic_dir, bridge)
333
return [x.split('/')[-1] for x in glob.glob(brif_rgex)]
336
def is_bridge_member(nic):
338
Check if a given nic is a member of a bridge
340
for bridge in get_bridges():
341
if nic in get_bridge_nics(bridge):