Adds workaround for routing 169.254.x.x addresses

See: https://bugs.launchpad.net/quantum/+bug/1174657
This commit is contained in:
Alessandro Pilotti
2013-05-01 15:25:44 +03:00
parent dcafa75141
commit 4b08f9ef93
3 changed files with 90 additions and 0 deletions

View File

@@ -16,10 +16,12 @@
import posixpath import posixpath
import urllib2 import urllib2
import urlparse
from cloudbaseinit.metadata.services import base from cloudbaseinit.metadata.services import base
from cloudbaseinit.openstack.common import cfg from cloudbaseinit.openstack.common import cfg
from cloudbaseinit.openstack.common import log as logging from cloudbaseinit.openstack.common import log as logging
from cloudbaseinit.osutils import factory as osutils_factory
opts = [ opts = [
cfg.StrOpt('metadata_base_url', default='http://169.254.169.254/', cfg.StrOpt('metadata_base_url', default='http://169.254.169.254/',
@@ -37,8 +39,38 @@ class HttpService(base.BaseMetadataService):
super(HttpService, self).__init__() super(HttpService, self).__init__()
self._enable_retry = True self._enable_retry = True
def _check_metadata_ip_route(self):
'''
Workaround for: https://bugs.launchpad.net/quantum/+bug/1174657
'''
osutils = osutils_factory.OSUtilsFactory().get_os_utils()
os_major_version = int(osutils.get_os_version().split('.')[0])
if os_major_version >= 6:
# 169.254.x.x addresses are not getting routed starting from
# Windows Vista / 2008
metadata_netloc = urlparse.urlparse(CONF.metadata_base_url).netloc
metadata_host = metadata_netloc.split(':')[0]
if metadata_host.startswith("169.254."):
if not osutils.check_static_route_exists(metadata_host):
(interface_index, gateway) = osutils.get_default_gateway()
if gateway:
try:
osutils.add_static_route(metadata_host,
"255.255.255.255",
gateway,
interface_index,
10)
except Exception, ex:
# Ignore it
LOG.exception(ex)
def load(self): def load(self):
super(HttpService, self).load() super(HttpService, self).load()
self._check_metadata_ip_route()
try: try:
self.get_meta_data('openstack') self.get_meta_data('openstack')
return True return True

View File

@@ -69,3 +69,16 @@ class BaseOSUtils(object):
def terminate(self): def terminate(self):
pass pass
def get_default_gateway(self):
pass
def check_static_route_exists(self, destination):
pass
def add_static_route(self, destination, mask, next_hop, interface_index,
metric):
pass
def get_os_version(self):
pass

View File

@@ -327,3 +327,48 @@ class WindowsUtils(base.BaseOSUtils):
# is not enough # is not enough
time.sleep(3) time.sleep(3)
self._stop_service(self._service_name) self._stop_service(self._service_name)
def get_default_gateway(self):
conn = wmi.WMI(moniker='//./root/cimv2')
for net_adapter_config in conn.Win32_NetworkAdapterConfiguration():
if net_adapter_config.DefaultIPGateway:
return (net_adapter_config.InterfaceIndex,
net_adapter_config.DefaultIPGateway[0])
return (None, None)
def check_static_route_exists(self, destination):
conn = wmi.WMI(moniker='//./root/cimv2')
return len(conn.Win32_IP4RouteTable(Destination=destination)) > 0
def add_static_route(self, destination, mask, next_hop, interface_index,
metric):
args = ['ROUTE', 'ADD', destination, 'MASK', mask, next_hop]
(out, err, ret_val) = self.execute_process(args)
# Cannot use the return value to determine the outcome
if err:
raise Exception('Unable to add route: %(err)s' % locals())
# TODO(alexpilotti): The following code creates the route properly and
# "route print" shows the added route, but routing to the destination
# fails. This option would be preferable compared to spawning a
# "ROUTE ADD" process.
'''
ROUTE_PROTOCOL_NETMGMT = 3
ROUTE_TYPE_INDIRECT = 4
conn = wmi.WMI(moniker='//./root/cimv2')
route = conn.Win32_IP4RouteTable.SpawnInstance_()
route.Destination = destination
route.Mask = mask
route.NextHop = next_hop
route.InterfaceIndex = interface_index
route.Metric1 = metric
route.Protocol = self.ROUTE_PROTOCOL_NETMGMT
route.Type = self.ROUTE_TYPE_INDIRECT
route.Put_()
'''
def get_os_version(self):
conn = wmi.WMI(moniker='//./root/cimv2')
return conn.Win32_OperatingSystem()[0].Version