]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown/utils.py
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
19 from functools
import partial
20 from ipaddr
import IPNetwork
, IPAddress
22 from ifupdown
.iface
import *
24 def signal_handler_f(ps
, sig
, frame
):
27 if sig
== signal
.SIGINT
:
28 raise KeyboardInterrupt
31 logger
= logging
.getLogger('ifupdown')
32 DEVNULL
= open(os
.devnull
, 'w')
59 def get_onoff_bool(value
):
60 if value
in utils
._onoff
_bool
:
61 return utils
._onoff
_bool
[value
]
65 def get_boolean_from_string(value
):
66 if value
in utils
._string
_values
:
67 return utils
._string
_values
[value
]
71 def get_yesno_boolean(bool):
72 return utils
._yesno
_bool
[bool]
75 def boolean_support_binary(value
):
76 return utils
._binary
_bool
[utils
.get_boolean_from_string(value
)]
79 def is_binary_bool(value
):
80 return value
== '0' or value
== '1'
83 def support_yesno_attrs(attrsdict
, attrslist
, ifaceobj
=None):
85 for attr
in attrslist
:
86 value
= ifaceobj
.get_attr_value_first(attr
)
87 if value
and not utils
.is_binary_bool(value
):
89 bool = utils
.get_boolean_from_string(attrsdict
[attr
])
90 attrsdict
[attr
] = utils
.get_yesno_boolean(bool)
92 for attr
in attrslist
:
94 attrsdict
[attr
] = utils
.boolean_support_binary(attrsdict
[attr
])
97 def importName(cls
, modulename
, name
):
98 """ Import a named object """
100 module
= __import__(modulename
, globals(), locals(), [name
])
103 return getattr(module
, name
)
106 def lockFile(cls
, lockfile
):
108 fp
= os
.open(lockfile
, os
.O_CREAT | os
.O_TRUNC | os
.O_WRONLY
)
109 fcntl
.flock(fp
, fcntl
.LOCK_EX | fcntl
.LOCK_NB
)
110 fcntl
.fcntl(fp
, fcntl
.F_SETFD
, fcntl
.FD_CLOEXEC
)
116 def parse_iface_range(cls
, name
):
118 # return (prefix, range-start, range-end)
119 # eg return ("swp1.", 1, 20, ".100")
120 range_match
= re
.match("^([\w]+)\[([\d]+)-([\d]+)\]([\.\w]+)", name
)
122 range_groups
= range_match
.groups()
123 if range_groups
[1] and range_groups
[2]:
124 return (range_groups
[0], int(range_groups
[1], 10),
125 int(range_groups
[2], 10), range_groups
[3])
128 # return (prefix, range-start, range-end, suffix)
129 # eg return ("swp", 1, 20, ".100")
130 range_match
= re
.match("^([\w\.]+)\[([\d]+)-([\d]+)\]", name
)
132 range_groups
= range_match
.groups()
133 if range_groups
[1] and range_groups
[2]:
134 return (range_groups
[0], int(range_groups
[1], 10),
135 int(range_groups
[2], 10))
139 def expand_iface_range(cls
, name
):
141 irange
= cls
.parse_iface_range(name
)
144 # eg swp1.[2-4], r = "swp1.", 2, 4)
145 for i
in range(irange
[1], irange
[2]):
146 ifacenames
.append('%s%d' %(irange
[0], i
))
147 elif len(irange
) == 4:
148 for i
in range(irange
[1], irange
[2]):
149 # eg swp[2-4].100, r = ("swp", 2, 4, ".100")
150 ifacenames
.append('%s%d%s' %(irange
[0], i
, irange
[3]))
154 def is_ifname_range(cls
, name
):
155 if '[' in name
or ']' in name
:
160 def check_ifname_size_invalid(cls
, name
=''):
161 """ IFNAMSIZ in include/linux/if.h is 16 so we check this """
163 if len(name
) > IFNAMSIZ
- 1:
169 def enable_subprocess_signal_forwarding(cls
, ps
, sig
):
170 signal
.signal(sig
, partial(signal_handler_f
, ps
))
173 def disable_subprocess_signal_forwarding(cls
, sig
):
174 signal
.signal(sig
, signal
.SIG_DFL
)
177 def _log_command_exec(cls
, cmd
, stdin
):
179 cls
.logger
.info('executing %s [%s]' % (cmd
, stdin
))
181 cls
.logger
.info('executing %s' % cmd
)
184 def _format_error(cls
, cmd
, cmd_returncode
, cmd_output
, stdin
):
185 if type(cmd
) is list:
188 cmd
= '%s [%s]' % (cmd
, stdin
)
190 return 'cmd \'%s\' failed: returned %d (%s)' % \
191 (cmd
, cmd_returncode
, cmd_output
)
193 return 'cmd \'%s\' failed: returned %d' % (cmd
, cmd_returncode
)
196 def get_normalized_ip_addr(cls
, ifacename
, ipaddrs
):
197 if not ipaddrs
: return None
198 if isinstance(ipaddrs
, list):
204 addrs
.append(str(IPNetwork(ip
)) if '/' in ip
else str(IPAddress(ip
)))
205 except Exception as e
:
206 cls
.logger
.warning('%s: %s' % (ifacename
, e
))
210 return str(IPNetwork(ipaddrs
)) if '/' in ipaddrs
else str(IPAddress(ipaddrs
))
211 except Exception as e
:
212 cls
.logger
.warning('%s: %s' % (ifacename
, e
))
216 def is_addr_ip_allowed_on(cls
, ifaceobj
, syntax_check
=False):
217 msg
= ('%s: ignoring ip address. Assigning an IP '
218 'address is not allowed on' % ifaceobj
.name
)
219 if (ifaceobj
.role
& ifaceRole
.SLAVE
220 and not (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
)):
222 if ifaceobj
.upperifaces
:
223 up
= ifaceobj
.upperifaces
[0]
224 msg
= ('%s enslaved interfaces. %s'
225 % (msg
, ('%s is enslaved to %s'
226 % (ifaceobj
.name
, up
)) if up
else '')).strip()
228 cls
.logger
.warning(msg
)
232 elif (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
233 and ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_VLAN_AWARE
):
234 msg
= '%s bridge vlan aware interfaces'
236 cls
.logger
.warning(msg
)
243 def _execute_subprocess(cls
, cmd
,
249 stderr
=subprocess
.STDOUT
):
251 exec's commands using subprocess Popen
253 cmd, should be shlex.split if not shell
256 Note: close_fds=True is affecting performance (2~3 times slower)
258 if ifupdownflags
.flags
.DRYRUN
:
263 ch
= subprocess
.Popen(cmd
,
267 stdin
=subprocess
.PIPE
if stdin
else None,
268 stdout
=subprocess
.PIPE
if stdout
else cls
.DEVNULL
,
270 utils
.enable_subprocess_signal_forwarding(ch
, signal
.SIGINT
)
272 cmd_output
= ch
.communicate(input=stdin
)[0]
273 cmd_returncode
= ch
.wait()
274 except Exception as e
:
275 raise Exception('cmd \'%s\' failed (%s)' % (' '.join(cmd
), str(e
)))
277 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
278 if cmd_returncode
!= 0:
279 raise Exception(cls
._format
_error
(cmd
,
286 def exec_user_command(cls
, cmd
, close_fds
=False, stdout
=True,
287 stdin
=None, stderr
=subprocess
.STDOUT
):
288 cls
._log
_command
_exec
(cmd
, stdin
)
289 return cls
._execute
_subprocess
(cmd
,
297 def exec_command(cls
, cmd
, env
=None, close_fds
=False, stdout
=True,
298 stdin
=None, stderr
=subprocess
.STDOUT
):
299 cls
._log
_command
_exec
(cmd
, stdin
)
300 return cls
._execute
_subprocess
(shlex
.split(cmd
),
308 def exec_commandl(cls
, cmdl
, env
=None, close_fds
=False, stdout
=True,
309 stdin
=None, stderr
=subprocess
.STDOUT
):
310 cls
._log
_command
_exec
(' '.join(cmdl
), stdin
)
311 return cls
._execute
_subprocess
(cmdl
,
318 fcntl
.fcntl(utils
.DEVNULL
, fcntl
.F_SETFD
, fcntl
.FD_CLOEXEC
)