root / lib / netutils.py @ 653bc0f1
History | View | Annotate | Download (19.7 kB)
1 | a744b676 | Manuel Franceschini | #
|
---|---|---|---|
2 | a744b676 | Manuel Franceschini | #
|
3 | a744b676 | Manuel Franceschini | |
4 | 8ad0da1e | Iustin Pop | # Copyright (C) 2010, 2011, 2012 Google Inc.
|
5 | a744b676 | Manuel Franceschini | #
|
6 | a744b676 | Manuel Franceschini | # This program is free software; you can redistribute it and/or modify
|
7 | a744b676 | Manuel Franceschini | # it under the terms of the GNU General Public License as published by
|
8 | a744b676 | Manuel Franceschini | # the Free Software Foundation; either version 2 of the License, or
|
9 | a744b676 | Manuel Franceschini | # (at your option) any later version.
|
10 | a744b676 | Manuel Franceschini | #
|
11 | a744b676 | Manuel Franceschini | # This program is distributed in the hope that it will be useful, but
|
12 | a744b676 | Manuel Franceschini | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | a744b676 | Manuel Franceschini | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | a744b676 | Manuel Franceschini | # General Public License for more details.
|
15 | a744b676 | Manuel Franceschini | #
|
16 | a744b676 | Manuel Franceschini | # You should have received a copy of the GNU General Public License
|
17 | a744b676 | Manuel Franceschini | # along with this program; if not, write to the Free Software
|
18 | a744b676 | Manuel Franceschini | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 | a744b676 | Manuel Franceschini | # 02110-1301, USA.
|
20 | a744b676 | Manuel Franceschini | |
21 | a744b676 | Manuel Franceschini | |
22 | a744b676 | Manuel Franceschini | """Ganeti network utility module.
|
23 | a744b676 | Manuel Franceschini |
|
24 | a744b676 | Manuel Franceschini | This module holds functions that can be used in both daemons (all) and
|
25 | a744b676 | Manuel Franceschini | the command line scripts.
|
26 | a744b676 | Manuel Franceschini |
|
27 | a744b676 | Manuel Franceschini | """
|
28 | a744b676 | Manuel Franceschini | |
29 | a744b676 | Manuel Franceschini | |
30 | a744b676 | Manuel Franceschini | import errno |
31 | 37531236 | Andrea Spadaccini | import os |
32 | a744b676 | Manuel Franceschini | import re |
33 | a744b676 | Manuel Franceschini | import socket |
34 | a744b676 | Manuel Franceschini | import struct |
35 | a744b676 | Manuel Franceschini | import IN |
36 | 37531236 | Andrea Spadaccini | import logging |
37 | a744b676 | Manuel Franceschini | |
38 | a744b676 | Manuel Franceschini | from ganeti import constants |
39 | a744b676 | Manuel Franceschini | from ganeti import errors |
40 | 37531236 | Andrea Spadaccini | from ganeti import utils |
41 | e91b297c | Michael Hanselmann | from ganeti import vcluster |
42 | a744b676 | Manuel Franceschini | |
43 | a744b676 | Manuel Franceschini | # Structure definition for getsockopt(SOL_SOCKET, SO_PEERCRED, ...):
|
44 | a744b676 | Manuel Franceschini | # struct ucred { pid_t pid; uid_t uid; gid_t gid; };
|
45 | a744b676 | Manuel Franceschini | #
|
46 | a744b676 | Manuel Franceschini | # The GNU C Library defines gid_t and uid_t to be "unsigned int" and
|
47 | a744b676 | Manuel Franceschini | # pid_t to "int".
|
48 | a744b676 | Manuel Franceschini | #
|
49 | a744b676 | Manuel Franceschini | # IEEE Std 1003.1-2008:
|
50 | a744b676 | Manuel Franceschini | # "nlink_t, uid_t, gid_t, and id_t shall be integer types"
|
51 | a744b676 | Manuel Franceschini | # "blksize_t, pid_t, and ssize_t shall be signed integer types"
|
52 | a744b676 | Manuel Franceschini | _STRUCT_UCRED = "iII"
|
53 | a744b676 | Manuel Franceschini | _STRUCT_UCRED_SIZE = struct.calcsize(_STRUCT_UCRED) |
54 | a744b676 | Manuel Franceschini | |
55 | 069a4bcf | Guido Trotter | # Workaround a bug in some linux distributions that don't define SO_PEERCRED
|
56 | 069a4bcf | Guido Trotter | try:
|
57 | a3e964cf | Klaus Aehlig | # pylint: disable=E1101
|
58 | 069a4bcf | Guido Trotter | _SO_PEERCRED = IN.SO_PEERCRED |
59 | 069a4bcf | Guido Trotter | except AttributeError: |
60 | 069a4bcf | Guido Trotter | _SO_PEERCRED = 17
|
61 | 069a4bcf | Guido Trotter | |
62 | 37531236 | Andrea Spadaccini | # Regexes used to find IP addresses in the output of ip.
|
63 | 37531236 | Andrea Spadaccini | _IP_RE_TEXT = r"[.:a-z0-9]+" # separate for testing purposes |
64 | 37531236 | Andrea Spadaccini | _IP_FAMILY_RE = re.compile(r"(?P<family>inet6?)\s+(?P<ip>%s)/" % _IP_RE_TEXT,
|
65 | 37531236 | Andrea Spadaccini | re.IGNORECASE) |
66 | 37531236 | Andrea Spadaccini | |
67 | 37531236 | Andrea Spadaccini | # Dict used to convert from a string representing an IP family to an IP
|
68 | 37531236 | Andrea Spadaccini | # version
|
69 | e687ec01 | Michael Hanselmann | _NAME_TO_IP_VER = { |
70 | 37531236 | Andrea Spadaccini | "inet": constants.IP4_VERSION,
|
71 | 37531236 | Andrea Spadaccini | "inet6": constants.IP6_VERSION,
|
72 | 37531236 | Andrea Spadaccini | } |
73 | 37531236 | Andrea Spadaccini | |
74 | 37531236 | Andrea Spadaccini | |
75 | 37531236 | Andrea Spadaccini | def _GetIpAddressesFromIpOutput(ip_output): |
76 | 37531236 | Andrea Spadaccini | """Parses the output of the ip command and retrieves the IP addresses and
|
77 | 37531236 | Andrea Spadaccini | version.
|
78 | 37531236 | Andrea Spadaccini |
|
79 | 37531236 | Andrea Spadaccini | @param ip_output: string containing the output of the ip command;
|
80 | 37531236 | Andrea Spadaccini | @rtype: dict; (int, list)
|
81 | 37531236 | Andrea Spadaccini | @return: a dict having as keys the IP versions and as values the
|
82 | 37531236 | Andrea Spadaccini | corresponding list of addresses found in the IP output.
|
83 | 37531236 | Andrea Spadaccini |
|
84 | 37531236 | Andrea Spadaccini | """
|
85 | 37531236 | Andrea Spadaccini | addr = dict((i, []) for i in _NAME_TO_IP_VER.values()) |
86 | 37531236 | Andrea Spadaccini | |
87 | 37531236 | Andrea Spadaccini | for row in ip_output.splitlines(): |
88 | 37531236 | Andrea Spadaccini | match = _IP_FAMILY_RE.search(row) |
89 | 37531236 | Andrea Spadaccini | if match and IPAddress.IsValid(match.group("ip")): |
90 | 37531236 | Andrea Spadaccini | addr[_NAME_TO_IP_VER[match.group("family")]].append(match.group("ip")) |
91 | 37531236 | Andrea Spadaccini | |
92 | 37531236 | Andrea Spadaccini | return addr
|
93 | 37531236 | Andrea Spadaccini | |
94 | a744b676 | Manuel Franceschini | |
95 | a744b676 | Manuel Franceschini | def GetSocketCredentials(sock): |
96 | a744b676 | Manuel Franceschini | """Returns the credentials of the foreign process connected to a socket.
|
97 | a744b676 | Manuel Franceschini |
|
98 | a744b676 | Manuel Franceschini | @param sock: Unix socket
|
99 | a744b676 | Manuel Franceschini | @rtype: tuple; (number, number, number)
|
100 | a744b676 | Manuel Franceschini | @return: The PID, UID and GID of the connected foreign process.
|
101 | a744b676 | Manuel Franceschini |
|
102 | a744b676 | Manuel Franceschini | """
|
103 | 069a4bcf | Guido Trotter | peercred = sock.getsockopt(socket.SOL_SOCKET, _SO_PEERCRED, |
104 | a744b676 | Manuel Franceschini | _STRUCT_UCRED_SIZE) |
105 | a744b676 | Manuel Franceschini | return struct.unpack(_STRUCT_UCRED, peercred)
|
106 | a744b676 | Manuel Franceschini | |
107 | a744b676 | Manuel Franceschini | |
108 | 37531236 | Andrea Spadaccini | def IsValidInterface(ifname): |
109 | 37531236 | Andrea Spadaccini | """Validate an interface name.
|
110 | 37531236 | Andrea Spadaccini |
|
111 | 37531236 | Andrea Spadaccini | @type ifname: string
|
112 | 37531236 | Andrea Spadaccini | @param ifname: Name of the network interface
|
113 | 37531236 | Andrea Spadaccini | @return: boolean indicating whether the interface name is valid or not.
|
114 | 37531236 | Andrea Spadaccini |
|
115 | 37531236 | Andrea Spadaccini | """
|
116 | 37531236 | Andrea Spadaccini | return os.path.exists(utils.PathJoin("/sys/class/net", ifname)) |
117 | 37531236 | Andrea Spadaccini | |
118 | 37531236 | Andrea Spadaccini | |
119 | 37531236 | Andrea Spadaccini | def GetInterfaceIpAddresses(ifname): |
120 | 37531236 | Andrea Spadaccini | """Returns the IP addresses associated to the interface.
|
121 | 37531236 | Andrea Spadaccini |
|
122 | 37531236 | Andrea Spadaccini | @type ifname: string
|
123 | 37531236 | Andrea Spadaccini | @param ifname: Name of the network interface
|
124 | 37531236 | Andrea Spadaccini | @return: A dict having for keys the IP version (either
|
125 | 37531236 | Andrea Spadaccini | L{constants.IP4_VERSION} or L{constants.IP6_VERSION}) and for
|
126 | 37531236 | Andrea Spadaccini | values the lists of IP addresses of the respective version
|
127 | 37531236 | Andrea Spadaccini | associated to the interface
|
128 | 37531236 | Andrea Spadaccini |
|
129 | 37531236 | Andrea Spadaccini | """
|
130 | 37531236 | Andrea Spadaccini | result = utils.RunCmd([constants.IP_COMMAND_PATH, "-o", "addr", "show", |
131 | 37531236 | Andrea Spadaccini | ifname]) |
132 | 37531236 | Andrea Spadaccini | |
133 | 37531236 | Andrea Spadaccini | if result.failed:
|
134 | 37531236 | Andrea Spadaccini | logging.error("Error running the ip command while getting the IP"
|
135 | 37531236 | Andrea Spadaccini | " addresses of %s", ifname)
|
136 | 37531236 | Andrea Spadaccini | return None |
137 | 37531236 | Andrea Spadaccini | |
138 | 37531236 | Andrea Spadaccini | return _GetIpAddressesFromIpOutput(result.output)
|
139 | 37531236 | Andrea Spadaccini | |
140 | 37531236 | Andrea Spadaccini | |
141 | b705c7a6 | Manuel Franceschini | def GetHostname(name=None, family=None): |
142 | b705c7a6 | Manuel Franceschini | """Returns a Hostname object.
|
143 | a744b676 | Manuel Franceschini |
|
144 | b705c7a6 | Manuel Franceschini | @type name: str
|
145 | b705c7a6 | Manuel Franceschini | @param name: hostname or None
|
146 | b705c7a6 | Manuel Franceschini | @type family: int
|
147 | b705c7a6 | Manuel Franceschini | @param family: AF_INET | AF_INET6 | None
|
148 | b705c7a6 | Manuel Franceschini | @rtype: L{Hostname}
|
149 | b705c7a6 | Manuel Franceschini | @return: Hostname object
|
150 | 17f7fd27 | Manuel Franceschini | @raise errors.OpPrereqError: in case of errors in resolving
|
151 | b705c7a6 | Manuel Franceschini |
|
152 | b705c7a6 | Manuel Franceschini | """
|
153 | a744b676 | Manuel Franceschini | try:
|
154 | b705c7a6 | Manuel Franceschini | return Hostname(name=name, family=family)
|
155 | a744b676 | Manuel Franceschini | except errors.ResolverError, err:
|
156 | a744b676 | Manuel Franceschini | raise errors.OpPrereqError("The given name (%s) does not resolve: %s" % |
157 | a744b676 | Manuel Franceschini | (err[0], err[2]), errors.ECODE_RESOLVER) |
158 | a744b676 | Manuel Franceschini | |
159 | a744b676 | Manuel Franceschini | |
160 | b705c7a6 | Manuel Franceschini | class Hostname: |
161 | b705c7a6 | Manuel Franceschini | """Class implementing resolver and hostname functionality.
|
162 | a744b676 | Manuel Franceschini |
|
163 | a744b676 | Manuel Franceschini | """
|
164 | e7b3ad26 | Manuel Franceschini | _VALID_NAME_RE = re.compile("^[a-z0-9._-]{1,255}$")
|
165 | e7b3ad26 | Manuel Franceschini | |
166 | b705c7a6 | Manuel Franceschini | def __init__(self, name=None, family=None): |
167 | a744b676 | Manuel Franceschini | """Initialize the host name object.
|
168 | a744b676 | Manuel Franceschini |
|
169 | b705c7a6 | Manuel Franceschini | If the name argument is None, it will use this system's name.
|
170 | b705c7a6 | Manuel Franceschini |
|
171 | b705c7a6 | Manuel Franceschini | @type family: int
|
172 | b705c7a6 | Manuel Franceschini | @param family: AF_INET | AF_INET6 | None
|
173 | b705c7a6 | Manuel Franceschini | @type name: str
|
174 | b705c7a6 | Manuel Franceschini | @param name: hostname or None
|
175 | a744b676 | Manuel Franceschini |
|
176 | a744b676 | Manuel Franceschini | """
|
177 | 5f30ea3f | Michael Hanselmann | self.name = self.GetFqdn(name) |
178 | b705c7a6 | Manuel Franceschini | self.ip = self.GetIP(self.name, family=family) |
179 | a744b676 | Manuel Franceschini | |
180 | f3044516 | Manuel Franceschini | @classmethod
|
181 | f3044516 | Manuel Franceschini | def GetSysName(cls): |
182 | f3044516 | Manuel Franceschini | """Legacy method the get the current system's name.
|
183 | f3044516 | Manuel Franceschini |
|
184 | f3044516 | Manuel Franceschini | """
|
185 | f3044516 | Manuel Franceschini | return cls.GetFqdn()
|
186 | f3044516 | Manuel Franceschini | |
187 | 5f30ea3f | Michael Hanselmann | @classmethod
|
188 | 5f30ea3f | Michael Hanselmann | def GetFqdn(cls, hostname=None): |
189 | f3044516 | Manuel Franceschini | """Return fqdn.
|
190 | f3044516 | Manuel Franceschini |
|
191 | f3044516 | Manuel Franceschini | If hostname is None the system's fqdn is returned.
|
192 | a744b676 | Manuel Franceschini |
|
193 | f3044516 | Manuel Franceschini | @type hostname: str
|
194 | f3044516 | Manuel Franceschini | @param hostname: name to be fqdn'ed
|
195 | f3044516 | Manuel Franceschini | @rtype: str
|
196 | f3044516 | Manuel Franceschini | @return: fqdn of given name, if it exists, unmodified name otherwise
|
197 | a744b676 | Manuel Franceschini |
|
198 | a744b676 | Manuel Franceschini | """
|
199 | f3044516 | Manuel Franceschini | if hostname is None: |
200 | e91b297c | Michael Hanselmann | virtfqdn = vcluster.GetVirtualHostname() |
201 | e91b297c | Michael Hanselmann | if virtfqdn:
|
202 | 5f30ea3f | Michael Hanselmann | result = virtfqdn |
203 | e91b297c | Michael Hanselmann | else:
|
204 | 5f30ea3f | Michael Hanselmann | result = socket.getfqdn() |
205 | f3044516 | Manuel Franceschini | else:
|
206 | 5f30ea3f | Michael Hanselmann | result = socket.getfqdn(hostname) |
207 | 5f30ea3f | Michael Hanselmann | |
208 | 5f30ea3f | Michael Hanselmann | return cls.GetNormalizedName(result)
|
209 | a744b676 | Manuel Franceschini | |
210 | a744b676 | Manuel Franceschini | @staticmethod
|
211 | b705c7a6 | Manuel Franceschini | def GetIP(hostname, family=None): |
212 | b705c7a6 | Manuel Franceschini | """Return IP address of given hostname.
|
213 | b705c7a6 | Manuel Franceschini |
|
214 | b705c7a6 | Manuel Franceschini | Supports both IPv4 and IPv6.
|
215 | a744b676 | Manuel Franceschini |
|
216 | a744b676 | Manuel Franceschini | @type hostname: str
|
217 | a744b676 | Manuel Franceschini | @param hostname: hostname to look up
|
218 | b705c7a6 | Manuel Franceschini | @type family: int
|
219 | b705c7a6 | Manuel Franceschini | @param family: AF_INET | AF_INET6 | None
|
220 | b705c7a6 | Manuel Franceschini | @rtype: str
|
221 | b705c7a6 | Manuel Franceschini | @return: IP address
|
222 | a744b676 | Manuel Franceschini | @raise errors.ResolverError: in case of errors in resolving
|
223 | a744b676 | Manuel Franceschini |
|
224 | a744b676 | Manuel Franceschini | """
|
225 | a744b676 | Manuel Franceschini | try:
|
226 | b705c7a6 | Manuel Franceschini | if family in (socket.AF_INET, socket.AF_INET6): |
227 | b705c7a6 | Manuel Franceschini | result = socket.getaddrinfo(hostname, None, family)
|
228 | b705c7a6 | Manuel Franceschini | else:
|
229 | b43dcc5a | Manuel Franceschini | result = socket.getaddrinfo(hostname, None)
|
230 | a744b676 | Manuel Franceschini | except (socket.gaierror, socket.herror, socket.error), err:
|
231 | a744b676 | Manuel Franceschini | # hostname not found in DNS, or other socket exception in the
|
232 | a744b676 | Manuel Franceschini | # (code, description format)
|
233 | a744b676 | Manuel Franceschini | raise errors.ResolverError(hostname, err.args[0], err.args[1]) |
234 | a744b676 | Manuel Franceschini | |
235 | b705c7a6 | Manuel Franceschini | # getaddrinfo() returns a list of 5-tupes (family, socktype, proto,
|
236 | b705c7a6 | Manuel Franceschini | # canonname, sockaddr). We return the first tuple's first address in
|
237 | b705c7a6 | Manuel Franceschini | # sockaddr
|
238 | e7b3ad26 | Manuel Franceschini | try:
|
239 | e7b3ad26 | Manuel Franceschini | return result[0][4][0] |
240 | e7b3ad26 | Manuel Franceschini | except IndexError, err: |
241 | 39d1744a | Iustin Pop | # we don't have here an actual error code, it's just that the
|
242 | 39d1744a | Iustin Pop | # data type returned by getaddrinfo is not what we expected;
|
243 | 39d1744a | Iustin Pop | # let's keep the same format in the exception arguments with a
|
244 | 39d1744a | Iustin Pop | # dummy error code
|
245 | 39d1744a | Iustin Pop | raise errors.ResolverError(hostname, 0, |
246 | 39d1744a | Iustin Pop | "Unknown error in getaddrinfo(): %s" % err)
|
247 | a744b676 | Manuel Franceschini | |
248 | e7b3ad26 | Manuel Franceschini | @classmethod
|
249 | e7b3ad26 | Manuel Franceschini | def GetNormalizedName(cls, hostname): |
250 | a744b676 | Manuel Franceschini | """Validate and normalize the given hostname.
|
251 | a744b676 | Manuel Franceschini |
|
252 | a744b676 | Manuel Franceschini | @attention: the validation is a bit more relaxed than the standards
|
253 | a744b676 | Manuel Franceschini | require; most importantly, we allow underscores in names
|
254 | a744b676 | Manuel Franceschini | @raise errors.OpPrereqError: when the name is not valid
|
255 | a744b676 | Manuel Franceschini |
|
256 | a744b676 | Manuel Franceschini | """
|
257 | a744b676 | Manuel Franceschini | hostname = hostname.lower() |
258 | e7b3ad26 | Manuel Franceschini | if (not cls._VALID_NAME_RE.match(hostname) or |
259 | a744b676 | Manuel Franceschini | # double-dots, meaning empty label
|
260 | a744b676 | Manuel Franceschini | ".." in hostname or |
261 | a744b676 | Manuel Franceschini | # empty initial label
|
262 | a744b676 | Manuel Franceschini | hostname.startswith(".")):
|
263 | a744b676 | Manuel Franceschini | raise errors.OpPrereqError("Invalid hostname '%s'" % hostname, |
264 | a744b676 | Manuel Franceschini | errors.ECODE_INVAL) |
265 | a744b676 | Manuel Franceschini | if hostname.endswith("."): |
266 | a744b676 | Manuel Franceschini | hostname = hostname.rstrip(".")
|
267 | a744b676 | Manuel Franceschini | return hostname
|
268 | a744b676 | Manuel Franceschini | |
269 | a744b676 | Manuel Franceschini | |
270 | 05edafd3 | Santi Raffa | def ValidatePortNumber(port): |
271 | 05edafd3 | Santi Raffa | """Returns the validated integer port number if it is valid.
|
272 | 05edafd3 | Santi Raffa |
|
273 | 05edafd3 | Santi Raffa | @param port: the port number to be validated
|
274 | 05edafd3 | Santi Raffa |
|
275 | 05edafd3 | Santi Raffa | @raise ValueError: if the port is not valid
|
276 | 05edafd3 | Santi Raffa | @rtype: int
|
277 | 05edafd3 | Santi Raffa | @return: the validated value.
|
278 | 05edafd3 | Santi Raffa |
|
279 | 05edafd3 | Santi Raffa | """
|
280 | 05edafd3 | Santi Raffa | |
281 | 05edafd3 | Santi Raffa | try:
|
282 | 05edafd3 | Santi Raffa | port = int(port)
|
283 | 05edafd3 | Santi Raffa | except TypeError: |
284 | 05edafd3 | Santi Raffa | raise errors.ProgrammerError("ValidatePortNumber called with non-numeric" |
285 | 05edafd3 | Santi Raffa | " type %s." % port.__class__.__name__)
|
286 | 05edafd3 | Santi Raffa | except ValueError: |
287 | 05edafd3 | Santi Raffa | raise ValueError("Invalid port value: '%s'" % port) |
288 | 05edafd3 | Santi Raffa | |
289 | 05edafd3 | Santi Raffa | if not 0 < port < 2 ** 16: |
290 | 05edafd3 | Santi Raffa | raise ValueError("Invalid port value: '%d'" % port) |
291 | 05edafd3 | Santi Raffa | |
292 | 05edafd3 | Santi Raffa | return port
|
293 | 05edafd3 | Santi Raffa | |
294 | 05edafd3 | Santi Raffa | |
295 | a744b676 | Manuel Franceschini | def TcpPing(target, port, timeout=10, live_port_needed=False, source=None): |
296 | a744b676 | Manuel Franceschini | """Simple ping implementation using TCP connect(2).
|
297 | a744b676 | Manuel Franceschini |
|
298 | a744b676 | Manuel Franceschini | Check if the given IP is reachable by doing attempting a TCP connect
|
299 | a744b676 | Manuel Franceschini | to it.
|
300 | a744b676 | Manuel Franceschini |
|
301 | a744b676 | Manuel Franceschini | @type target: str
|
302 | 77b02a99 | Renรฉ Nussbaumer | @param target: the IP to ping
|
303 | a744b676 | Manuel Franceschini | @type port: int
|
304 | a744b676 | Manuel Franceschini | @param port: the port to connect to
|
305 | a744b676 | Manuel Franceschini | @type timeout: int
|
306 | a744b676 | Manuel Franceschini | @param timeout: the timeout on the connection attempt
|
307 | a744b676 | Manuel Franceschini | @type live_port_needed: boolean
|
308 | a744b676 | Manuel Franceschini | @param live_port_needed: whether a closed port will cause the
|
309 | a744b676 | Manuel Franceschini | function to return failure, as if there was a timeout
|
310 | a744b676 | Manuel Franceschini | @type source: str or None
|
311 | a744b676 | Manuel Franceschini | @param source: if specified, will cause the connect to be made
|
312 | a744b676 | Manuel Franceschini | from this specific source address; failures to bind other
|
313 | a744b676 | Manuel Franceschini | than C{EADDRNOTAVAIL} will be ignored
|
314 | a744b676 | Manuel Franceschini |
|
315 | a744b676 | Manuel Franceschini | """
|
316 | 25ba209e | Michael Hanselmann | logging.debug("Attempting to reach TCP port %s on target %s with a timeout"
|
317 | 25ba209e | Michael Hanselmann | " of %s seconds", port, target, timeout)
|
318 | 25ba209e | Michael Hanselmann | |
319 | a744b676 | Manuel Franceschini | try:
|
320 | 8b312c1d | Manuel Franceschini | family = IPAddress.GetAddressFamily(target) |
321 | 25ba209e | Michael Hanselmann | except errors.IPAddressError, err:
|
322 | 25ba209e | Michael Hanselmann | raise errors.ProgrammerError("Family of IP address given in parameter" |
323 | 25ba209e | Michael Hanselmann | " 'target' can't be determined: %s" % err)
|
324 | a744b676 | Manuel Franceschini | |
325 | a744b676 | Manuel Franceschini | sock = socket.socket(family, socket.SOCK_STREAM) |
326 | a744b676 | Manuel Franceschini | success = False
|
327 | a744b676 | Manuel Franceschini | |
328 | a744b676 | Manuel Franceschini | if source is not None: |
329 | a744b676 | Manuel Franceschini | try:
|
330 | a744b676 | Manuel Franceschini | sock.bind((source, 0))
|
331 | 8ad0da1e | Iustin Pop | except socket.error, err:
|
332 | 8ad0da1e | Iustin Pop | if err[0] == errno.EADDRNOTAVAIL: |
333 | a744b676 | Manuel Franceschini | success = False
|
334 | a744b676 | Manuel Franceschini | |
335 | a744b676 | Manuel Franceschini | sock.settimeout(timeout) |
336 | a744b676 | Manuel Franceschini | |
337 | a744b676 | Manuel Franceschini | try:
|
338 | a744b676 | Manuel Franceschini | sock.connect((target, port)) |
339 | a744b676 | Manuel Franceschini | sock.close() |
340 | a744b676 | Manuel Franceschini | success = True
|
341 | a744b676 | Manuel Franceschini | except socket.timeout:
|
342 | a744b676 | Manuel Franceschini | success = False
|
343 | 8ad0da1e | Iustin Pop | except socket.error, err:
|
344 | 8ad0da1e | Iustin Pop | success = (not live_port_needed) and (err[0] == errno.ECONNREFUSED) |
345 | a744b676 | Manuel Franceschini | |
346 | a744b676 | Manuel Franceschini | return success
|
347 | a744b676 | Manuel Franceschini | |
348 | a744b676 | Manuel Franceschini | |
349 | a744b676 | Manuel Franceschini | def GetDaemonPort(daemon_name): |
350 | a744b676 | Manuel Franceschini | """Get the daemon port for this cluster.
|
351 | a744b676 | Manuel Franceschini |
|
352 | a744b676 | Manuel Franceschini | Note that this routine does not read a ganeti-specific file, but
|
353 | a744b676 | Manuel Franceschini | instead uses C{socket.getservbyname} to allow pre-customization of
|
354 | a744b676 | Manuel Franceschini | this parameter outside of Ganeti.
|
355 | a744b676 | Manuel Franceschini |
|
356 | a744b676 | Manuel Franceschini | @type daemon_name: string
|
357 | a744b676 | Manuel Franceschini | @param daemon_name: daemon name (in constants.DAEMONS_PORTS)
|
358 | a744b676 | Manuel Franceschini | @rtype: int
|
359 | a744b676 | Manuel Franceschini |
|
360 | a744b676 | Manuel Franceschini | """
|
361 | a744b676 | Manuel Franceschini | if daemon_name not in constants.DAEMONS_PORTS: |
362 | a744b676 | Manuel Franceschini | raise errors.ProgrammerError("Unknown daemon: %s" % daemon_name) |
363 | a744b676 | Manuel Franceschini | |
364 | a744b676 | Manuel Franceschini | (proto, default_port) = constants.DAEMONS_PORTS[daemon_name] |
365 | a744b676 | Manuel Franceschini | try:
|
366 | a744b676 | Manuel Franceschini | port = socket.getservbyname(daemon_name, proto) |
367 | a744b676 | Manuel Franceschini | except socket.error:
|
368 | a744b676 | Manuel Franceschini | port = default_port |
369 | a744b676 | Manuel Franceschini | |
370 | a744b676 | Manuel Franceschini | return port
|
371 | 8b312c1d | Manuel Franceschini | |
372 | 8b312c1d | Manuel Franceschini | |
373 | 8b312c1d | Manuel Franceschini | class IPAddress(object): |
374 | 8b312c1d | Manuel Franceschini | """Class that represents an IP address.
|
375 | 8b312c1d | Manuel Franceschini |
|
376 | 8b312c1d | Manuel Franceschini | """
|
377 | 8b312c1d | Manuel Franceschini | iplen = 0
|
378 | 8b312c1d | Manuel Franceschini | family = None
|
379 | 8b312c1d | Manuel Franceschini | loopback_cidr = None
|
380 | 8b312c1d | Manuel Franceschini | |
381 | 8b312c1d | Manuel Franceschini | @staticmethod
|
382 | 8b312c1d | Manuel Franceschini | def _GetIPIntFromString(address): |
383 | 8b312c1d | Manuel Franceschini | """Abstract method to please pylint.
|
384 | 8b312c1d | Manuel Franceschini |
|
385 | 8b312c1d | Manuel Franceschini | """
|
386 | 8b312c1d | Manuel Franceschini | raise NotImplementedError |
387 | 8b312c1d | Manuel Franceschini | |
388 | 8b312c1d | Manuel Franceschini | @classmethod
|
389 | 8b312c1d | Manuel Franceschini | def IsValid(cls, address): |
390 | 8b312c1d | Manuel Franceschini | """Validate a IP address.
|
391 | 8b312c1d | Manuel Franceschini |
|
392 | 8b312c1d | Manuel Franceschini | @type address: str
|
393 | 8b312c1d | Manuel Franceschini | @param address: IP address to be checked
|
394 | 8b312c1d | Manuel Franceschini | @rtype: bool
|
395 | 8b312c1d | Manuel Franceschini | @return: True if valid, False otherwise
|
396 | 8b312c1d | Manuel Franceschini |
|
397 | 8b312c1d | Manuel Franceschini | """
|
398 | 8b312c1d | Manuel Franceschini | if cls.family is None: |
399 | 8b312c1d | Manuel Franceschini | try:
|
400 | 8b312c1d | Manuel Franceschini | family = cls.GetAddressFamily(address) |
401 | 8b312c1d | Manuel Franceschini | except errors.IPAddressError:
|
402 | 8b312c1d | Manuel Franceschini | return False |
403 | 8b312c1d | Manuel Franceschini | else:
|
404 | 8b312c1d | Manuel Franceschini | family = cls.family |
405 | 8b312c1d | Manuel Franceschini | |
406 | 8b312c1d | Manuel Franceschini | try:
|
407 | 8b312c1d | Manuel Franceschini | socket.inet_pton(family, address) |
408 | 8b312c1d | Manuel Franceschini | return True |
409 | 8b312c1d | Manuel Franceschini | except socket.error:
|
410 | 8b312c1d | Manuel Franceschini | return False |
411 | 8b312c1d | Manuel Franceschini | |
412 | 8b312c1d | Manuel Franceschini | @classmethod
|
413 | 7df2c4f0 | Andrea Spadaccini | def ValidateNetmask(cls, netmask): |
414 | 7df2c4f0 | Andrea Spadaccini | """Validate a netmask suffix in CIDR notation.
|
415 | 7df2c4f0 | Andrea Spadaccini |
|
416 | 7df2c4f0 | Andrea Spadaccini | @type netmask: int
|
417 | 7df2c4f0 | Andrea Spadaccini | @param netmask: netmask suffix to validate
|
418 | 7df2c4f0 | Andrea Spadaccini | @rtype: bool
|
419 | 7df2c4f0 | Andrea Spadaccini | @return: True if valid, False otherwise
|
420 | 7df2c4f0 | Andrea Spadaccini |
|
421 | 7df2c4f0 | Andrea Spadaccini | """
|
422 | 7df2c4f0 | Andrea Spadaccini | assert (isinstance(netmask, (int, long))) |
423 | 7df2c4f0 | Andrea Spadaccini | |
424 | 7df2c4f0 | Andrea Spadaccini | return 0 < netmask <= cls.iplen |
425 | 7df2c4f0 | Andrea Spadaccini | |
426 | 7df2c4f0 | Andrea Spadaccini | @classmethod
|
427 | 8b312c1d | Manuel Franceschini | def Own(cls, address): |
428 | 8b312c1d | Manuel Franceschini | """Check if the current host has the the given IP address.
|
429 | 8b312c1d | Manuel Franceschini |
|
430 | 8b312c1d | Manuel Franceschini | This is done by trying to bind the given address. We return True if we
|
431 | 8b312c1d | Manuel Franceschini | succeed or false if a socket.error is raised.
|
432 | 8b312c1d | Manuel Franceschini |
|
433 | 8b312c1d | Manuel Franceschini | @type address: str
|
434 | 8b312c1d | Manuel Franceschini | @param address: IP address to be checked
|
435 | 8b312c1d | Manuel Franceschini | @rtype: bool
|
436 | 8b312c1d | Manuel Franceschini | @return: True if we own the address, False otherwise
|
437 | 8b312c1d | Manuel Franceschini |
|
438 | 8b312c1d | Manuel Franceschini | """
|
439 | 8b312c1d | Manuel Franceschini | if cls.family is None: |
440 | 8b312c1d | Manuel Franceschini | try:
|
441 | 8b312c1d | Manuel Franceschini | family = cls.GetAddressFamily(address) |
442 | 8b312c1d | Manuel Franceschini | except errors.IPAddressError:
|
443 | 8b312c1d | Manuel Franceschini | return False |
444 | 8b312c1d | Manuel Franceschini | else:
|
445 | 8b312c1d | Manuel Franceschini | family = cls.family |
446 | 8b312c1d | Manuel Franceschini | |
447 | 8b312c1d | Manuel Franceschini | s = socket.socket(family, socket.SOCK_DGRAM) |
448 | 8b312c1d | Manuel Franceschini | success = False
|
449 | 8b312c1d | Manuel Franceschini | try:
|
450 | 8b312c1d | Manuel Franceschini | try:
|
451 | 8b312c1d | Manuel Franceschini | s.bind((address, 0))
|
452 | 8b312c1d | Manuel Franceschini | success = True
|
453 | 8b312c1d | Manuel Franceschini | except socket.error:
|
454 | 8b312c1d | Manuel Franceschini | success = False
|
455 | 8b312c1d | Manuel Franceschini | finally:
|
456 | 8b312c1d | Manuel Franceschini | s.close() |
457 | 8b312c1d | Manuel Franceschini | return success
|
458 | 8b312c1d | Manuel Franceschini | |
459 | 8b312c1d | Manuel Franceschini | @classmethod
|
460 | 8b312c1d | Manuel Franceschini | def InNetwork(cls, cidr, address): |
461 | 8b312c1d | Manuel Franceschini | """Determine whether an address is within a network.
|
462 | 8b312c1d | Manuel Franceschini |
|
463 | 8b312c1d | Manuel Franceschini | @type cidr: string
|
464 | 8b312c1d | Manuel Franceschini | @param cidr: Network in CIDR notation, e.g. '192.0.2.0/24', '2001:db8::/64'
|
465 | 8b312c1d | Manuel Franceschini | @type address: str
|
466 | 8b312c1d | Manuel Franceschini | @param address: IP address
|
467 | 8b312c1d | Manuel Franceschini | @rtype: bool
|
468 | 8b312c1d | Manuel Franceschini | @return: True if address is in cidr, False otherwise
|
469 | 8b312c1d | Manuel Franceschini |
|
470 | 8b312c1d | Manuel Franceschini | """
|
471 | 8b312c1d | Manuel Franceschini | address_int = cls._GetIPIntFromString(address) |
472 | 8b312c1d | Manuel Franceschini | subnet = cidr.split("/")
|
473 | 8b312c1d | Manuel Franceschini | assert len(subnet) == 2 |
474 | 8b312c1d | Manuel Franceschini | try:
|
475 | 8b312c1d | Manuel Franceschini | prefix = int(subnet[1]) |
476 | 8b312c1d | Manuel Franceschini | except ValueError: |
477 | 8b312c1d | Manuel Franceschini | return False |
478 | 8b312c1d | Manuel Franceschini | |
479 | 8b312c1d | Manuel Franceschini | assert 0 <= prefix <= cls.iplen |
480 | 8b312c1d | Manuel Franceschini | target_int = cls._GetIPIntFromString(subnet[0])
|
481 | 8b312c1d | Manuel Franceschini | # Convert prefix netmask to integer value of netmask
|
482 | e687ec01 | Michael Hanselmann | netmask_int = (2 ** cls.iplen) - 1 ^ ((2 ** cls.iplen) - 1 >> prefix) |
483 | 8b312c1d | Manuel Franceschini | # Calculate hostmask
|
484 | e687ec01 | Michael Hanselmann | hostmask_int = netmask_int ^ (2 ** cls.iplen) - 1 |
485 | 8b312c1d | Manuel Franceschini | # Calculate network address by and'ing netmask
|
486 | 8b312c1d | Manuel Franceschini | network_int = target_int & netmask_int |
487 | 8b312c1d | Manuel Franceschini | # Calculate broadcast address by or'ing hostmask
|
488 | 8b312c1d | Manuel Franceschini | broadcast_int = target_int | hostmask_int |
489 | 8b312c1d | Manuel Franceschini | |
490 | 8b312c1d | Manuel Franceschini | return network_int <= address_int <= broadcast_int
|
491 | 8b312c1d | Manuel Franceschini | |
492 | 8b312c1d | Manuel Franceschini | @staticmethod
|
493 | 8b312c1d | Manuel Franceschini | def GetAddressFamily(address): |
494 | 8b312c1d | Manuel Franceschini | """Get the address family of the given address.
|
495 | 8b312c1d | Manuel Franceschini |
|
496 | 8b312c1d | Manuel Franceschini | @type address: str
|
497 | 8b312c1d | Manuel Franceschini | @param address: ip address whose family will be returned
|
498 | 8b312c1d | Manuel Franceschini | @rtype: int
|
499 | 37531236 | Andrea Spadaccini | @return: C{socket.AF_INET} or C{socket.AF_INET6}
|
500 | 8b312c1d | Manuel Franceschini | @raise errors.GenericError: for invalid addresses
|
501 | 8b312c1d | Manuel Franceschini |
|
502 | 8b312c1d | Manuel Franceschini | """
|
503 | 8b312c1d | Manuel Franceschini | try:
|
504 | 8b312c1d | Manuel Franceschini | return IP4Address(address).family
|
505 | 8b312c1d | Manuel Franceschini | except errors.IPAddressError:
|
506 | 8b312c1d | Manuel Franceschini | pass
|
507 | 8b312c1d | Manuel Franceschini | |
508 | 8b312c1d | Manuel Franceschini | try:
|
509 | 8b312c1d | Manuel Franceschini | return IP6Address(address).family
|
510 | 8b312c1d | Manuel Franceschini | except errors.IPAddressError:
|
511 | 8b312c1d | Manuel Franceschini | pass
|
512 | 8b312c1d | Manuel Franceschini | |
513 | 8b312c1d | Manuel Franceschini | raise errors.IPAddressError("Invalid address '%s'" % address) |
514 | 8b312c1d | Manuel Franceschini | |
515 | 37531236 | Andrea Spadaccini | @staticmethod
|
516 | 37531236 | Andrea Spadaccini | def GetVersionFromAddressFamily(family): |
517 | 37531236 | Andrea Spadaccini | """Convert an IP address family to the corresponding IP version.
|
518 | 37531236 | Andrea Spadaccini |
|
519 | 37531236 | Andrea Spadaccini | @type family: int
|
520 | 37531236 | Andrea Spadaccini | @param family: IP address family, one of socket.AF_INET or socket.AF_INET6
|
521 | 37531236 | Andrea Spadaccini | @return: an int containing the IP version, one of L{constants.IP4_VERSION}
|
522 | 37531236 | Andrea Spadaccini | or L{constants.IP6_VERSION}
|
523 | 37531236 | Andrea Spadaccini | @raise errors.ProgrammerError: for unknown families
|
524 | 37531236 | Andrea Spadaccini |
|
525 | 37531236 | Andrea Spadaccini | """
|
526 | 37531236 | Andrea Spadaccini | if family == socket.AF_INET:
|
527 | 37531236 | Andrea Spadaccini | return constants.IP4_VERSION
|
528 | 37531236 | Andrea Spadaccini | elif family == socket.AF_INET6:
|
529 | 37531236 | Andrea Spadaccini | return constants.IP6_VERSION
|
530 | 37531236 | Andrea Spadaccini | |
531 | 37531236 | Andrea Spadaccini | raise errors.ProgrammerError("%s is not a valid IP address family" % family) |
532 | 37531236 | Andrea Spadaccini | |
533 | 37531236 | Andrea Spadaccini | @staticmethod
|
534 | 37531236 | Andrea Spadaccini | def GetAddressFamilyFromVersion(version): |
535 | 37531236 | Andrea Spadaccini | """Convert an IP version to the corresponding IP address family.
|
536 | 37531236 | Andrea Spadaccini |
|
537 | 37531236 | Andrea Spadaccini | @type version: int
|
538 | 37531236 | Andrea Spadaccini | @param version: IP version, one of L{constants.IP4_VERSION} or
|
539 | 37531236 | Andrea Spadaccini | L{constants.IP6_VERSION}
|
540 | 37531236 | Andrea Spadaccini | @return: an int containing the IP address family, one of C{socket.AF_INET}
|
541 | 37531236 | Andrea Spadaccini | or C{socket.AF_INET6}
|
542 | 37531236 | Andrea Spadaccini | @raise errors.ProgrammerError: for unknown IP versions
|
543 | 37531236 | Andrea Spadaccini |
|
544 | 37531236 | Andrea Spadaccini | """
|
545 | 37531236 | Andrea Spadaccini | if version == constants.IP4_VERSION:
|
546 | 37531236 | Andrea Spadaccini | return socket.AF_INET
|
547 | 37531236 | Andrea Spadaccini | elif version == constants.IP6_VERSION:
|
548 | 37531236 | Andrea Spadaccini | return socket.AF_INET6
|
549 | 37531236 | Andrea Spadaccini | |
550 | 37531236 | Andrea Spadaccini | raise errors.ProgrammerError("%s is not a valid IP version" % version) |
551 | 37531236 | Andrea Spadaccini | |
552 | 7df2c4f0 | Andrea Spadaccini | @staticmethod
|
553 | 7df2c4f0 | Andrea Spadaccini | def GetClassFromIpVersion(version): |
554 | 7df2c4f0 | Andrea Spadaccini | """Return the IPAddress subclass for the given IP version.
|
555 | 7df2c4f0 | Andrea Spadaccini |
|
556 | 7df2c4f0 | Andrea Spadaccini | @type version: int
|
557 | 7df2c4f0 | Andrea Spadaccini | @param version: IP version, one of L{constants.IP4_VERSION} or
|
558 | 7df2c4f0 | Andrea Spadaccini | L{constants.IP6_VERSION}
|
559 | 7df2c4f0 | Andrea Spadaccini | @return: a subclass of L{netutils.IPAddress}
|
560 | 7df2c4f0 | Andrea Spadaccini | @raise errors.ProgrammerError: for unknowo IP versions
|
561 | 7df2c4f0 | Andrea Spadaccini |
|
562 | 7df2c4f0 | Andrea Spadaccini | """
|
563 | 7df2c4f0 | Andrea Spadaccini | if version == constants.IP4_VERSION:
|
564 | 7df2c4f0 | Andrea Spadaccini | return IP4Address
|
565 | 7df2c4f0 | Andrea Spadaccini | elif version == constants.IP6_VERSION:
|
566 | 7df2c4f0 | Andrea Spadaccini | return IP6Address
|
567 | 7df2c4f0 | Andrea Spadaccini | |
568 | 7df2c4f0 | Andrea Spadaccini | raise errors.ProgrammerError("%s is not a valid IP version" % version) |
569 | 7df2c4f0 | Andrea Spadaccini | |
570 | 7df2c4f0 | Andrea Spadaccini | @staticmethod
|
571 | 7df2c4f0 | Andrea Spadaccini | def GetClassFromIpFamily(family): |
572 | 7df2c4f0 | Andrea Spadaccini | """Return the IPAddress subclass for the given IP family.
|
573 | 7df2c4f0 | Andrea Spadaccini |
|
574 | 7df2c4f0 | Andrea Spadaccini | @param family: IP family (one of C{socket.AF_INET} or C{socket.AF_INET6}
|
575 | 7df2c4f0 | Andrea Spadaccini | @return: a subclass of L{netutils.IPAddress}
|
576 | 7df2c4f0 | Andrea Spadaccini | @raise errors.ProgrammerError: for unknowo IP versions
|
577 | 7df2c4f0 | Andrea Spadaccini |
|
578 | 7df2c4f0 | Andrea Spadaccini | """
|
579 | 7df2c4f0 | Andrea Spadaccini | return IPAddress.GetClassFromIpVersion(
|
580 | 7df2c4f0 | Andrea Spadaccini | IPAddress.GetVersionFromAddressFamily(family)) |
581 | 7df2c4f0 | Andrea Spadaccini | |
582 | 8b312c1d | Manuel Franceschini | @classmethod
|
583 | 8b312c1d | Manuel Franceschini | def IsLoopback(cls, address): |
584 | 8b312c1d | Manuel Franceschini | """Determine whether it is a loopback address.
|
585 | 8b312c1d | Manuel Franceschini |
|
586 | 8b312c1d | Manuel Franceschini | @type address: str
|
587 | 8b312c1d | Manuel Franceschini | @param address: IP address to be checked
|
588 | 8b312c1d | Manuel Franceschini | @rtype: bool
|
589 | 8b312c1d | Manuel Franceschini | @return: True if loopback, False otherwise
|
590 | 8b312c1d | Manuel Franceschini |
|
591 | 8b312c1d | Manuel Franceschini | """
|
592 | 8b312c1d | Manuel Franceschini | try:
|
593 | 8b312c1d | Manuel Franceschini | return cls.InNetwork(cls.loopback_cidr, address)
|
594 | 8b312c1d | Manuel Franceschini | except errors.IPAddressError:
|
595 | 8b312c1d | Manuel Franceschini | return False |
596 | 8b312c1d | Manuel Franceschini | |
597 | 8b312c1d | Manuel Franceschini | |
598 | 8b312c1d | Manuel Franceschini | class IP4Address(IPAddress): |
599 | 8b312c1d | Manuel Franceschini | """IPv4 address class.
|
600 | 8b312c1d | Manuel Franceschini |
|
601 | 8b312c1d | Manuel Franceschini | """
|
602 | 8b312c1d | Manuel Franceschini | iplen = 32
|
603 | 8b312c1d | Manuel Franceschini | family = socket.AF_INET |
604 | 8b312c1d | Manuel Franceschini | loopback_cidr = "127.0.0.0/8"
|
605 | 8b312c1d | Manuel Franceschini | |
606 | 8b312c1d | Manuel Franceschini | def __init__(self, address): |
607 | 8b312c1d | Manuel Franceschini | """Constructor for IPv4 address.
|
608 | 8b312c1d | Manuel Franceschini |
|
609 | 8b312c1d | Manuel Franceschini | @type address: str
|
610 | 8b312c1d | Manuel Franceschini | @param address: IP address
|
611 | 8b312c1d | Manuel Franceschini | @raises errors.IPAddressError: if address invalid
|
612 | 8b312c1d | Manuel Franceschini |
|
613 | 8b312c1d | Manuel Franceschini | """
|
614 | 8b312c1d | Manuel Franceschini | IPAddress.__init__(self)
|
615 | 8b312c1d | Manuel Franceschini | if not self.IsValid(address): |
616 | 8b312c1d | Manuel Franceschini | raise errors.IPAddressError("IPv4 Address %s invalid" % address) |
617 | 8b312c1d | Manuel Franceschini | |
618 | 8b312c1d | Manuel Franceschini | self.address = address
|
619 | 8b312c1d | Manuel Franceschini | |
620 | 8b312c1d | Manuel Franceschini | @staticmethod
|
621 | 8b312c1d | Manuel Franceschini | def _GetIPIntFromString(address): |
622 | 8b312c1d | Manuel Franceschini | """Get integer value of IPv4 address.
|
623 | 8b312c1d | Manuel Franceschini |
|
624 | 8b312c1d | Manuel Franceschini | @type address: str
|
625 | 17f7fd27 | Manuel Franceschini | @param address: IPv6 address
|
626 | 8b312c1d | Manuel Franceschini | @rtype: int
|
627 | 8b312c1d | Manuel Franceschini | @return: integer value of given IP address
|
628 | 8b312c1d | Manuel Franceschini |
|
629 | 8b312c1d | Manuel Franceschini | """
|
630 | 8b312c1d | Manuel Franceschini | address_int = 0
|
631 | 8b312c1d | Manuel Franceschini | parts = address.split(".")
|
632 | 8b312c1d | Manuel Franceschini | assert len(parts) == 4 |
633 | 8b312c1d | Manuel Franceschini | for part in parts: |
634 | 8b312c1d | Manuel Franceschini | address_int = (address_int << 8) | int(part) |
635 | 8b312c1d | Manuel Franceschini | |
636 | 8b312c1d | Manuel Franceschini | return address_int
|
637 | 8b312c1d | Manuel Franceschini | |
638 | 8b312c1d | Manuel Franceschini | |
639 | 8b312c1d | Manuel Franceschini | class IP6Address(IPAddress): |
640 | 8b312c1d | Manuel Franceschini | """IPv6 address class.
|
641 | 8b312c1d | Manuel Franceschini |
|
642 | 8b312c1d | Manuel Franceschini | """
|
643 | 8b312c1d | Manuel Franceschini | iplen = 128
|
644 | 8b312c1d | Manuel Franceschini | family = socket.AF_INET6 |
645 | 8b312c1d | Manuel Franceschini | loopback_cidr = "::1/128"
|
646 | 8b312c1d | Manuel Franceschini | |
647 | 8b312c1d | Manuel Franceschini | def __init__(self, address): |
648 | 8b312c1d | Manuel Franceschini | """Constructor for IPv6 address.
|
649 | 8b312c1d | Manuel Franceschini |
|
650 | 8b312c1d | Manuel Franceschini | @type address: str
|
651 | 8b312c1d | Manuel Franceschini | @param address: IP address
|
652 | 8b312c1d | Manuel Franceschini | @raises errors.IPAddressError: if address invalid
|
653 | 8b312c1d | Manuel Franceschini |
|
654 | 8b312c1d | Manuel Franceschini | """
|
655 | 8b312c1d | Manuel Franceschini | IPAddress.__init__(self)
|
656 | 8b312c1d | Manuel Franceschini | if not self.IsValid(address): |
657 | 8b312c1d | Manuel Franceschini | raise errors.IPAddressError("IPv6 Address [%s] invalid" % address) |
658 | 8b312c1d | Manuel Franceschini | self.address = address
|
659 | 8b312c1d | Manuel Franceschini | |
660 | 8b312c1d | Manuel Franceschini | @staticmethod
|
661 | 8b312c1d | Manuel Franceschini | def _GetIPIntFromString(address): |
662 | 8b312c1d | Manuel Franceschini | """Get integer value of IPv6 address.
|
663 | 8b312c1d | Manuel Franceschini |
|
664 | 8b312c1d | Manuel Franceschini | @type address: str
|
665 | 17f7fd27 | Manuel Franceschini | @param address: IPv6 address
|
666 | 8b312c1d | Manuel Franceschini | @rtype: int
|
667 | 8b312c1d | Manuel Franceschini | @return: integer value of given IP address
|
668 | 8b312c1d | Manuel Franceschini |
|
669 | 8b312c1d | Manuel Franceschini | """
|
670 | 8b312c1d | Manuel Franceschini | doublecolons = address.count("::")
|
671 | 8b312c1d | Manuel Franceschini | assert not doublecolons > 1 |
672 | 8b312c1d | Manuel Franceschini | if doublecolons == 1: |
673 | 8b312c1d | Manuel Franceschini | # We have a shorthand address, expand it
|
674 | 8b312c1d | Manuel Franceschini | parts = [] |
675 | 8b312c1d | Manuel Franceschini | twoparts = address.split("::")
|
676 | d0c8c01d | Iustin Pop | sep = len(twoparts[0].split(":")) + len(twoparts[1].split(":")) |
677 | d0c8c01d | Iustin Pop | parts = twoparts[0].split(":") |
678 | 17385bd2 | Andrea Spadaccini | parts.extend(["0"] * (8 - sep)) |
679 | d0c8c01d | Iustin Pop | parts += twoparts[1].split(":") |
680 | 8b312c1d | Manuel Franceschini | else:
|
681 | 8b312c1d | Manuel Franceschini | parts = address.split(":")
|
682 | 8b312c1d | Manuel Franceschini | |
683 | 8b312c1d | Manuel Franceschini | address_int = 0
|
684 | 8b312c1d | Manuel Franceschini | for part in parts: |
685 | d0c8c01d | Iustin Pop | address_int = (address_int << 16) + int(part or "0", 16) |
686 | 8b312c1d | Manuel Franceschini | |
687 | 8b312c1d | Manuel Franceschini | return address_int
|
688 | 1a8337f2 | Manuel Franceschini | |
689 | 7845b8c8 | Manuel Franceschini | |
690 | 981732fb | Manuel Franceschini | def FormatAddress(address, family=None): |
691 | 1a8337f2 | Manuel Franceschini | """Format a socket address
|
692 | 1a8337f2 | Manuel Franceschini |
|
693 | 1a8337f2 | Manuel Franceschini | @type address: family specific (usually tuple)
|
694 | 1a8337f2 | Manuel Franceschini | @param address: address, as reported by this class
|
695 | 981732fb | Manuel Franceschini | @type family: integer
|
696 | 981732fb | Manuel Franceschini | @param family: socket family (one of socket.AF_*) or None
|
697 | 1a8337f2 | Manuel Franceschini |
|
698 | 1a8337f2 | Manuel Franceschini | """
|
699 | 981732fb | Manuel Franceschini | if family is None: |
700 | 981732fb | Manuel Franceschini | try:
|
701 | 981732fb | Manuel Franceschini | family = IPAddress.GetAddressFamily(address[0])
|
702 | 981732fb | Manuel Franceschini | except errors.IPAddressError:
|
703 | 981732fb | Manuel Franceschini | raise errors.ParameterError(address)
|
704 | 981732fb | Manuel Franceschini | |
705 | 1a8337f2 | Manuel Franceschini | if family == socket.AF_UNIX and len(address) == 3: |
706 | 1a8337f2 | Manuel Franceschini | return "pid=%s, uid=%s, gid=%s" % address |
707 | 1a8337f2 | Manuel Franceschini | |
708 | 1a8337f2 | Manuel Franceschini | if family in (socket.AF_INET, socket.AF_INET6) and len(address) == 2: |
709 | 1a8337f2 | Manuel Franceschini | host, port = address |
710 | 1a8337f2 | Manuel Franceschini | if family == socket.AF_INET6:
|
711 | 1a8337f2 | Manuel Franceschini | res = "[%s]" % host
|
712 | 1a8337f2 | Manuel Franceschini | else:
|
713 | 1a8337f2 | Manuel Franceschini | res = host |
714 | 1a8337f2 | Manuel Franceschini | |
715 | 1a8337f2 | Manuel Franceschini | if port is not None: |
716 | 1a8337f2 | Manuel Franceschini | res += ":%s" % port
|
717 | 1a8337f2 | Manuel Franceschini | |
718 | 1a8337f2 | Manuel Franceschini | return res
|
719 | 1a8337f2 | Manuel Franceschini | |
720 | 1a8337f2 | Manuel Franceschini | raise errors.ParameterError(family, address) |