summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Danjou <julien@danjou.info>2014-08-07 16:15:52 +0200
committerJulien Danjou <julien@danjou.info>2014-08-07 18:09:28 +0200
commit30588b877a813d1ced820313855dfb9826e2c083 (patch)
tree0306c10509fd2616a0113b9aed94cc08bb936840
parentf3e11e40f9871f8328e107bf1390c532fbe3a54b (diff)
downloadtooz-30588b877a813d1ced820313855dfb9826e2c083.tar.gz
Import network_utils from Oslo
This to avoid the URL parsing bug in old Python 2.7. Change-Id: Ic3bc51a6dc3c7ce04405d1f5c1a67a491fcfaa77
-rw-r--r--openstack-common.conf1
-rw-r--r--tooz/openstack/common/network_utils.py163
2 files changed, 164 insertions, 0 deletions
diff --git a/openstack-common.conf b/openstack-common.conf
index e4a804d..6393b3e 100644
--- a/openstack-common.conf
+++ b/openstack-common.conf
@@ -1,3 +1,4 @@
[DEFAULT]
module=lockutils
+module=network_utils
base=tooz
diff --git a/tooz/openstack/common/network_utils.py b/tooz/openstack/common/network_utils.py
new file mode 100644
index 0000000..ea0c825
--- /dev/null
+++ b/tooz/openstack/common/network_utils.py
@@ -0,0 +1,163 @@
+# Copyright 2012 OpenStack Foundation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""
+Network-related utilities and helper functions.
+"""
+
+import logging
+import socket
+
+from six.moves.urllib import parse
+
+from tooz.openstack.common.gettextutils import _LW
+
+LOG = logging.getLogger(__name__)
+
+
+def parse_host_port(address, default_port=None):
+ """Interpret a string as a host:port pair.
+
+ An IPv6 address MUST be escaped if accompanied by a port,
+ because otherwise ambiguity ensues: 2001:db8:85a3::8a2e:370:7334
+ means both [2001:db8:85a3::8a2e:370:7334] and
+ [2001:db8:85a3::8a2e:370]:7334.
+
+ >>> parse_host_port('server01:80')
+ ('server01', 80)
+ >>> parse_host_port('server01')
+ ('server01', None)
+ >>> parse_host_port('server01', default_port=1234)
+ ('server01', 1234)
+ >>> parse_host_port('[::1]:80')
+ ('::1', 80)
+ >>> parse_host_port('[::1]')
+ ('::1', None)
+ >>> parse_host_port('[::1]', default_port=1234)
+ ('::1', 1234)
+ >>> parse_host_port('2001:db8:85a3::8a2e:370:7334', default_port=1234)
+ ('2001:db8:85a3::8a2e:370:7334', 1234)
+ >>> parse_host_port(None)
+ (None, None)
+ """
+ if not address:
+ return (None, None)
+
+ if address[0] == '[':
+ # Escaped ipv6
+ _host, _port = address[1:].split(']')
+ host = _host
+ if ':' in _port:
+ port = _port.split(':')[1]
+ else:
+ port = default_port
+ else:
+ if address.count(':') == 1:
+ host, port = address.split(':')
+ else:
+ # 0 means ipv4, >1 means ipv6.
+ # We prohibit unescaped ipv6 addresses with port.
+ host = address
+ port = default_port
+
+ return (host, None if port is None else int(port))
+
+
+class ModifiedSplitResult(parse.SplitResult):
+ """Split results class for urlsplit."""
+
+ # NOTE(dims): The functions below are needed for Python 2.6.x.
+ # We can remove these when we drop support for 2.6.x.
+ @property
+ def hostname(self):
+ netloc = self.netloc.split('@', 1)[-1]
+ host, port = parse_host_port(netloc)
+ return host
+
+ @property
+ def port(self):
+ netloc = self.netloc.split('@', 1)[-1]
+ host, port = parse_host_port(netloc)
+ return port
+
+
+def urlsplit(url, scheme='', allow_fragments=True):
+ """Parse a URL using urlparse.urlsplit(), splitting query and fragments.
+ This function papers over Python issue9374 when needed.
+
+ The parameters are the same as urlparse.urlsplit.
+ """
+ scheme, netloc, path, query, fragment = parse.urlsplit(
+ url, scheme, allow_fragments)
+ if allow_fragments and '#' in path:
+ path, fragment = path.split('#', 1)
+ if '?' in path:
+ path, query = path.split('?', 1)
+ return ModifiedSplitResult(scheme, netloc,
+ path, query, fragment)
+
+
+def set_tcp_keepalive(sock, tcp_keepalive=True,
+ tcp_keepidle=None,
+ tcp_keepalive_interval=None,
+ tcp_keepalive_count=None):
+ """Set values for tcp keepalive parameters
+
+ This function configures tcp keepalive parameters if users wish to do
+ so.
+
+ :param tcp_keepalive: Boolean, turn on or off tcp_keepalive. If users are
+ not sure, this should be True, and default values will be used.
+
+ :param tcp_keepidle: time to wait before starting to send keepalive probes
+ :param tcp_keepalive_interval: time between successive probes, once the
+ initial wait time is over
+ :param tcp_keepalive_count: number of probes to send before the connection
+ is killed
+ """
+
+ # NOTE(praneshp): Despite keepalive being a tcp concept, the level is
+ # still SOL_SOCKET. This is a quirk.
+ if isinstance(tcp_keepalive, bool):
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, tcp_keepalive)
+ else:
+ raise TypeError("tcp_keepalive must be a boolean")
+
+ if not tcp_keepalive:
+ return
+
+ # These options aren't available in the OS X version of eventlet,
+ # Idle + Count * Interval effectively gives you the total timeout.
+ if tcp_keepidle is not None:
+ if hasattr(socket, 'TCP_KEEPIDLE'):
+ sock.setsockopt(socket.IPPROTO_TCP,
+ socket.TCP_KEEPIDLE,
+ tcp_keepidle)
+ else:
+ LOG.warning(_LW('tcp_keepidle not available on your system'))
+ if tcp_keepalive_interval is not None:
+ if hasattr(socket, 'TCP_KEEPINTVL'):
+ sock.setsockopt(socket.IPPROTO_TCP,
+ socket.TCP_KEEPINTVL,
+ tcp_keepalive_interval)
+ else:
+ LOG.warning(_LW('tcp_keepintvl not available on your system'))
+ if tcp_keepalive_count is not None:
+ if hasattr(socket, 'TCP_KEEPCNT'):
+ sock.setsockopt(socket.IPPROTO_TCP,
+ socket.TCP_KEEPCNT,
+ tcp_keepalive_count)
+ else:
+ LOG.warning(_LW('tcp_keepknt not available on your system'))