]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/ifupdown/iface.py
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
10 """ifupdown2 network interface object
12 It is modeled based on the 'iface' section in /etc/network/interfaces
13 file. But can be extended to include any other network interface format
16 from collections
import OrderedDict
25 class ifaceLinkKind():
30 class ifaceLinkType():
37 """Enumerates iface status """
45 def to_str(cls
, state
):
46 if state
== cls
.UNKNOWN
:
48 elif state
== cls
.SUCCESS
:
50 elif state
== cls
.ERROR
:
52 elif state
== cls
.NOTFOUND
:
56 def from_str(cls
, state_str
):
57 if state_str
== 'unknown':
59 elif state_str
== 'success':
61 elif state_str
== 'error':
65 """Enumerates iface state """
81 def to_str(cls
, state
):
82 if state
== cls
.UNKNOWN
:
84 elif state
== cls
.NEW
:
86 elif state
== cls
.PRE_UP
:
90 elif state
== cls
.POST_UP
:
92 elif state
== cls
.PRE_DOWN
:
94 elif state
== cls
.DOWN
:
96 elif state
== cls
.POST_DOWN
:
98 elif state
== cls
.QUERY_CHECKCURR
:
99 return 'query-checkcurr'
100 elif state
== cls
.QUERY_RUNNING
:
101 return 'query-running'
104 def from_str(cls
, state_str
):
105 if state_str
== 'unknown':
107 elif state_str
== 'new':
109 elif state_str
== 'pre-up':
111 elif state_str
== 'up':
113 elif state_str
== 'post-up':
115 elif state_str
== 'pre-down':
117 elif state_str
== 'down':
119 elif state_str
== 'post-down':
121 elif state_str
== 'query-checkcurr':
122 return cls
.QUERY_CHECKCURR
123 elif state_str
== 'query-running':
124 return cls
.QUERY_RUNNING
126 class ifaceJsonEncoder(json
.JSONEncoder
):
127 def default(self
, o
):
130 retconfig
= dict((k
, (v
[0] if len(v
) == 1 else v
))
131 for k
,v
in o
.config
.items())
132 return OrderedDict({'name' : o
.name
,
133 'addr_method' : o
.addr_method
,
134 'addr_family' : o
.addr_family
,
136 'config' : retconfig
})
138 class ifaceJsonDecoder():
140 def json_to_ifaceobj(cls
, ifaceattrdict
):
141 ifaceattrdict
['config'] = OrderedDict([(k
, (v
if isinstance(v
, list)
143 for k
,v
in ifaceattrdict
.get('config',
144 OrderedDict()).items()])
145 return iface(attrsdict
=ifaceattrdict
)
148 """ ifupdown2 iface object class
151 **name** Name of the interface
153 **addr_family** Address family eg, inet, inet6. Can be None to
154 indicate both address families
156 **addr_method** Address method eg, static, manual or None for
157 static address method
159 **config** dictionary of config lines for this interface
161 **state** Configuration state of an interface as defined by
164 **status** Configuration status of an interface as defined by
167 **flags** Internal flags used by iface processing
169 **priv_flags** private flags owned by module using this class
171 **module_flags** module flags owned by module using this class
173 **refcnt** reference count, indicating number of interfaces
174 dependent on this iface
176 **lowerifaces** list of interface names lower to this interface or
177 this interface depends on
179 **upperifaces** list of interface names upper to this interface or
180 the interfaces that depend on this interface
182 **auto** True if interface belongs to the auto class
184 **classes** List of classes the interface belongs to
186 **env** shell environment the interface needs during
189 **raw_config** raw interface config from file
192 # flag to indicate that the object was created from pickled state
193 _PICKLED
= 0x00000001
194 HAS_SIBLINGS
= 0x00000010
195 IFACERANGE_ENTRY
= 0x00000100
196 IFACERANGE_START
= 0x00001000
200 def __init__(self
, attrsdict
={}):
201 self
._set
_attrs
_from
_dict
(attrsdict
)
202 self
._config
_status
= {}
203 """dict with config status of iface attributes"""
204 self
.state
= ifaceState
.NEW
205 """iface state (of type ifaceState) """
206 self
.status
= ifaceStatus
.UNKNOWN
207 """iface status (of type ifaceStatus) """
208 self
.status_str
= None
209 """iface status str (string representing the status) """
212 self
.priv_flags
= 0x0
213 """iface module flags dictionary with module name: flags"""
214 self
.module_flags
= {}
215 """iface priv flags. can be used by the external object manager """
217 """iface refcnt (incremented for each dependent this interface has) """
218 self
.lowerifaces
= None
219 """lower iface list (in other words: slaves of this interface """
220 self
.upperifaces
= None
221 """upper iface list (in other words: master of this interface """
223 """interface classes this iface belongs to """
225 """environment variable dict required for this interface to run"""
227 """interface config/attributes in raw format (eg: as it appeared in the interfaces file)"""
228 self
.linkstate
= None
229 """linkstate of the interface"""
230 self
.type = ifaceType
.UNKNOWN
232 self
.priv_data
= None
234 self
.link_type
= ifaceLinkType
.LINK_UNKNOWN
235 self
.link_kind
= ifaceLinkKind
.UNKNOWN
237 def _set_attrs_from_dict(self
, attrdict
):
238 self
.auto
= attrdict
.get('auto', False)
239 self
.name
= attrdict
.get('name')
240 self
.addr_family
= attrdict
.get('addr_family')
241 self
.addr_method
= attrdict
.get('addr_method')
242 self
.config
= attrdict
.get('config', OrderedDict())
244 def inc_refcnt(self
):
245 """ increment refcnt of the interface. Usually used to indicate that
246 it has dependents """
249 def dec_refcnt(self
):
250 """ decrement refcnt of the interface. Usually used to indicate that
251 it has lost its dependent """
254 def is_config_present(self
):
255 """ returns true if the interface has user provided config,
257 addr_method
= self
.addr_method
258 if addr_method
and addr_method
in ['dhcp', 'dhcp6', 'loopback']:
265 def set_class(self
, classname
):
266 """ appends class to the interfaces class list """
267 self
.classes
.append(classname
)
269 def set_state_n_status(self
, state
, status
):
270 """ sets state and status of an interface """
274 def set_flag(self
, flag
):
277 def clear_flag(self
, flag
):
280 def add_to_upperifaces(self
, upperifacename
):
281 """ add to the list of upperifaces """
283 if upperifacename
not in self
.upperifaces
:
284 self
.upperifaces
.append(upperifacename
)
286 self
.upperifaces
= [upperifacename
]
288 def get_attr_value(self
, attr_name
):
289 """ add to the list of upperifaces """
290 return self
.config
.get(attr_name
)
292 def get_attr_value_first(self
, attr_name
):
293 """ get first value of the specified attr name """
294 attr_value_list
= self
.config
.get(attr_name
)
296 return attr_value_list
[0]
299 def get_attrs_value_first(self
, attrs
):
300 """ get first value of the first attr in the list.
301 Useful when you have multiple attrs representing the
305 attr_value_list
= self
.config
.get(attr
)
307 return attr_value_list
[0]
310 def get_attr_value_n(self
, attr_name
, attr_index
):
311 """ get n'th value of the specified attr name """
312 attr_value_list
= self
.config
.get(attr_name
)
315 return attr_value_list
[attr_index
]
322 """ get shell environment variables the interface must execute in """
327 def generate_env(self
):
328 """ generate shell environment variables dict interface must execute
329 in. This is used to support legacy ifupdown scripts
333 env
['IFACE'] = self
.name
334 for attr
, attr_value
in config
.items():
335 attr_env_name
= 'IF_%s' %attr
.upper()
336 env
[attr_env_name
] = attr_value
[0]
340 def update_config(self
, attr_name
, attr_value
):
341 """ add attribute name and value to the interface config """
342 self
.config
.setdefault(attr_name
, []).append(attr_value
)
344 def replace_config(self
, attr_name
, attr_value
):
345 """ add attribute name and value to the interface config """
346 self
.config
[attr_name
] = [attr_value
]
348 def delete_config(self
, attr_name
):
349 """ add attribute name and value to the interface config """
351 del self
.config
[attr_name
]
355 def update_config_dict(self
, attrdict
):
356 self
.config
.update(attrdict
)
358 def update_config_with_status(self
, attr_name
, attr_value
, attr_status
=0):
359 """ add attribute name and value to the interface config and also
360 update the config_status dict with status of this attribute config """
363 self
.config
.setdefault(attr_name
, []).append(attr_value
)
364 self
._config
_status
.setdefault(attr_name
, []).append(attr_status
)
365 # set global iface state
367 self
.status
= ifaceStatus
.ERROR
368 elif self
.status
!= ifaceStatus
.ERROR
:
369 # Not already error, mark success
370 self
.status
= ifaceStatus
.SUCCESS
372 def check_n_update_config_with_status_many(self
, ifaceobjorig
, attr_names
,
374 # set multiple attribute status to zero
375 # also updates status only if the attribute is present
376 for attr_name
in attr_names
:
377 if not ifaceobjorig
.get_attr_value_first(attr_name
):
379 self
.config
.setdefault(attr_name
, []).append('')
380 self
._config
_status
.setdefault(attr_name
, []).append(attr_status
)
382 def get_config_attr_status(self
, attr_name
, idx
=0):
383 """ get status of a attribute config on this interface.
385 Looks at the iface _config_status dict"""
386 return self
._config
_status
.get(attr_name
, [])[idx
]
388 def compare(self
, dstiface
):
389 """ compares iface object with iface object passed as argument
391 Returns True if object self is same as dstiface and False otherwise """
393 if self
.name
!= dstiface
.name
: return False
394 if self
.type != dstiface
.type: return False
395 if self
.addr_family
!= dstiface
.addr_family
: return False
396 if self
.addr_method
!= dstiface
.addr_method
: return False
397 if self
.auto
!= dstiface
.auto
: return False
398 if self
.classes
!= dstiface
.classes
: return False
399 if len(self
.config
) != len(dstiface
.config
):
401 if any(True for k
in self
.config
if k
not in dstiface
.config
):
403 if any(True for k
,v
in self
.config
.items()
404 if v
!= dstiface
.config
.get(k
)): return False
408 def __getstate__(self
):
409 odict
= self
.__dict
__.copy()
412 del odict
['lowerifaces']
413 del odict
['upperifaces']
415 del odict
['_config_status']
417 del odict
['priv_flags']
418 del odict
['module_flags']
419 del odict
['raw_config']
420 del odict
['linkstate']
422 del odict
['link_type']
423 del odict
['link_kind']
426 def __setstate__(self
, dict):
427 self
.__dict
__.update(dict)
428 self
._config
_status
= {}
429 self
.state
= ifaceState
.NEW
430 self
.status
= ifaceStatus
.UNKNOWN
433 self
.lowerifaces
= None
434 self
.upperifaces
= None
435 self
.linkstate
= None
438 self
.module_flags
= {}
440 self
.flags |
= self
._PICKLED
441 self
.link_type
= ifaceLinkType
.LINK_NA
442 self
.link_kind
= ifaceLinkKind
.UNKNOWN
444 def dump_raw(self
, logger
):
447 print 'auto %s' %self
.name
448 print (self
.raw_config
[0])
449 for i
in range(1, len(self
.raw_config
)):
450 print(indent
+ self
.raw_config
[i
])
452 def dump(self
, logger
):
454 logger
.info(self
.name
+ ' : {')
455 logger
.info(indent
+ 'family: %s' %self
.addr_family
)
456 logger
.info(indent
+ 'method: %s' %self
.addr_method
)
457 logger
.info(indent
+ 'flags: %x' %self
.flags
)
458 logger
.info(indent
+ 'state: %s'
459 %ifaceState
.to_str(self
.state
))
460 logger
.info(indent
+ 'status: %s'
461 %ifaceStatus
.to_str(self
.status
))
462 logger
.info(indent
+ 'refcnt: %d' %self
.refcnt
)
465 logger
.info(indent
+ 'lowerdevs: %s' %str
(d
))
467 logger
.info(indent
+ 'lowerdevs: None')
469 logger
.info(indent
+ 'config: ')
472 logger
.info(indent
+ indent
+ str(config
))
475 def dump_pretty(self
, with_status
=False,
476 successstr
='success', errorstr
='error',
477 unknownstr
='unknown', use_realname
=False):
480 if use_realname
and self
.realname
:
481 name
= '%s' %self
.realname
483 name
= '%s' %self
.name
485 outbuf
+= 'auto %s\n' %name
487 if self
.type == ifaceType
.BRIDGE_VLAN
:
488 ifaceline
+= 'vlan %s' %name
490 ifaceline
+= 'iface %s' %name
492 ifaceline
+= ' %s' %self
.addr_family
494 ifaceline
+= ' %s' %self
.addr_method
497 if (self
.status
== ifaceStatus
.ERROR
or
498 self
.status
== ifaceStatus
.NOTFOUND
):
500 ifaceline
+= ' (%s)' %self
.status_str
501 status_str
= errorstr
502 elif self
.status
== ifaceStatus
.SUCCESS
:
503 status_str
= successstr
505 outbuf
+= '{0:65} {1:>8}'.format(ifaceline
, status_str
) + '\n'
507 outbuf
+= ifaceline
+ '\n'
508 if self
.status
== ifaceStatus
.NOTFOUND
:
509 outbuf
= (outbuf
.encode('utf8')
510 if isinstance(outbuf
, unicode) else outbuf
)
514 outbuf
+= ifaceline
+ '\n'
517 for cname
, cvaluelist
in config
.items():
519 for cv
in cvaluelist
:
521 s
= self
.get_config_attr_status(cname
, idx
)
523 status_str
= unknownstr
525 status_str
= errorstr
527 status_str
= successstr
528 outbuf
+= (indent
+ '{0:55} {1:>10}'.format(
529 '%s %s' %(cname
, cv
), status_str
)) + '\n'
531 outbuf
+= indent
+ '%s %s\n' %(cname
, cv
)
534 outbuf
= (outbuf
.encode('utf8')
535 if isinstance(outbuf
, unicode) else outbuf
)