summaryrefslogtreecommitdiff
path: root/cloudinit/net/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/net/__init__.py')
-rw-r--r--cloudinit/net/__init__.py42
1 files changed, 38 insertions, 4 deletions
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
index f83d3681..3642fb1f 100644
--- a/cloudinit/net/__init__.py
+++ b/cloudinit/net/__init__.py
@@ -12,6 +12,7 @@ import re
from cloudinit.net.network_state import mask_to_net_prefix
from cloudinit import util
+from cloudinit.url_helper import UrlError, readurl
LOG = logging.getLogger(__name__)
SYS_CLASS_NET = "/sys/class/net/"
@@ -612,7 +613,8 @@ def get_interfaces():
Bridges and any devices that have a 'stolen' mac are excluded."""
ret = []
devs = get_devicelist()
- empty_mac = '00:00:00:00:00:00'
+ # 16 somewhat arbitrarily chosen. Normally a mac is 6 '00:' tokens.
+ zero_mac = ':'.join(('00',) * 16)
for name in devs:
if not interface_has_own_mac(name):
continue
@@ -624,7 +626,8 @@ def get_interfaces():
# some devices may not have a mac (tun0)
if not mac:
continue
- if mac == empty_mac and name != 'lo':
+ # skip nics that have no mac (00:00....)
+ if name != 'lo' and mac == zero_mac[:len(mac)]:
continue
ret.append((name, mac, device_driver(name), device_devid(name)))
return ret
@@ -645,16 +648,36 @@ def get_ib_hwaddrs_by_interface():
return ret
+def has_url_connectivity(url):
+ """Return true when the instance has access to the provided URL
+
+ Logs a warning if url is not the expected format.
+ """
+ if not any([url.startswith('http://'), url.startswith('https://')]):
+ LOG.warning(
+ "Ignoring connectivity check. Expected URL beginning with http*://"
+ " received '%s'", url)
+ return False
+ try:
+ readurl(url, timeout=5)
+ except UrlError:
+ return False
+ return True
+
+
class EphemeralIPv4Network(object):
"""Context manager which sets up temporary static network configuration.
- No operations are performed if the provided interface is already connected.
+ No operations are performed if the provided interface already has the
+ specified configuration.
+ This can be verified with the connectivity_url.
If unconnected, bring up the interface with valid ip, prefix and broadcast.
If router is provided setup a default route for that interface. Upon
context exit, clean up the interface leaving no configuration behind.
"""
- def __init__(self, interface, ip, prefix_or_mask, broadcast, router=None):
+ def __init__(self, interface, ip, prefix_or_mask, broadcast, router=None,
+ connectivity_url=None):
"""Setup context manager and validate call signature.
@param interface: Name of the network interface to bring up.
@@ -663,6 +686,8 @@ class EphemeralIPv4Network(object):
prefix.
@param broadcast: Broadcast address for the IPv4 network.
@param router: Optionally the default gateway IP.
+ @param connectivity_url: Optionally, a URL to verify if a usable
+ connection already exists.
"""
if not all([interface, ip, prefix_or_mask, broadcast]):
raise ValueError(
@@ -673,6 +698,8 @@ class EphemeralIPv4Network(object):
except ValueError as e:
raise ValueError(
'Cannot setup network: {0}'.format(e))
+
+ self.connectivity_url = connectivity_url
self.interface = interface
self.ip = ip
self.broadcast = broadcast
@@ -681,6 +708,13 @@ class EphemeralIPv4Network(object):
def __enter__(self):
"""Perform ephemeral network setup if interface is not connected."""
+ if self.connectivity_url:
+ if has_url_connectivity(self.connectivity_url):
+ LOG.debug(
+ 'Skip ephemeral network setup, instance has connectivity'
+ ' to %s', self.connectivity_url)
+ return
+
self._bringup_device()
if self.router:
self._bringup_router()