]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdownaddons/ifenslaveutil.py
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
9 from ifupdown
.iface
import *
10 from utilsbase
import *
11 from iproute2
import *
14 class ifenslaveutil(utilsBase
):
15 """ This class contains methods to interact with linux kernel bond
16 related interfaces """
18 _cache_fill_done
= False
20 def __init__(self
, *args
, **kargs
):
21 utilsBase
.__init
__(self
, *args
, **kargs
)
22 if self
.CACHE
and not self
._cache
_fill
_done
:
23 self
._bond
_linkinfo
_fill
_all
()
24 self
._cache
_fill
_done
= True
26 def _bond_linkinfo_fill_attrs(self
, bondname
):
28 linkCache
.links
[bondname
]['linkinfo'] = {}
30 linkCache
.links
[bondname
] = {'linkinfo': {}}
33 linkCache
.set_attr([bondname
, 'linkinfo', 'slaves'],
34 self
.read_file_oneline('/sys/class/net/%s/bonding/slaves'
36 linkCache
.set_attr([bondname
, 'linkinfo', 'mode'],
37 self
.read_file_oneline('/sys/class/net/%s/bonding/mode'
38 %bondname
).split()[0])
39 linkCache
.set_attr([bondname
, 'linkinfo', 'xmit_hash_policy'],
40 self
.read_file_oneline(
41 '/sys/class/net/%s/bonding/xmit_hash_policy'
42 %bondname
).split()[0])
43 linkCache
.set_attr([bondname
, 'linkinfo', 'lacp_rate'],
44 self
.read_file_oneline('/sys/class/net/%s/bonding/lacp_rate'
45 %bondname
).split()[1])
46 linkCache
.set_attr([bondname
, 'linkinfo', 'ad_sys_priority'],
47 self
.read_file_oneline('/sys/class/net/%s/bonding/ad_sys_priority'
49 linkCache
.set_attr([bondname
, 'linkinfo', 'ad_sys_mac_addr'],
50 self
.read_file_oneline('/sys/class/net/%s/bonding/ad_sys_mac_addr'
52 map(lambda x
: linkCache
.set_attr([bondname
, 'linkinfo', x
],
53 self
.read_file_oneline('/sys/class/net/%s/bonding/%s'
55 ['use_carrier', 'miimon', 'min_links', 'num_unsol_na',
56 'num_grat_arp', 'lacp_bypass_allow', 'lacp_bypass_period',
57 'lacp_bypass_all_active', 'clag_enable'])
61 def _bond_linkinfo_fill_all(self
):
62 bondstr
= self
.read_file_oneline('/sys/class/net/bonding_masters')
65 [self
._bond
_linkinfo
_fill
_attrs
(b
) for b
in bondstr
.split()]
67 def _bond_linkinfo_fill(self
, bondname
, refresh
=False):
69 linkCache
.get_attr([bondname
, 'linkinfo', 'slaves'])
73 bondstr
= self
.read_file_oneline('/sys/class/net/bonding_masters')
74 if (not bondstr
or bondname
not in bondstr
.split()):
75 raise Exception('bond %s not found' %bondname
)
76 self
._bond
_linkinfo
_fill
_attrs
(bondname
)
78 def _cache_get(self
, attrlist
, refresh
=False):
83 if not ifenslaveutil
._cache
_fill
_done
:
84 self
._bond
_linkinfo
_fill
_all
()
85 ifenslaveutil
._cache
_fill
_done
= True
86 return linkCache
.get_attr(attrlist
)
88 return linkCache
.get_attr(attrlist
)
89 self
._bond
_linkinfo
_fill
(attrlist
[0], refresh
)
90 return linkCache
.get_attr(attrlist
)
92 self
.logger
.debug('_cache_get(%s) : [%s]'
93 %(str(attrlist
), str(e
)))
97 def _cache_check(self
, attrlist
, value
, refresh
=False):
99 attrvalue
= self
._cache
_get
(attrlist
, refresh
)
100 if attrvalue
and attrvalue
== value
:
103 self
.logger
.debug('_cache_check(%s) : [%s]'
104 %(str(attrlist
), str(e
)))
108 def _cache_update(self
, attrlist
, value
):
109 if self
.DRYRUN
: return
111 if attrlist
[-1] == 'slaves':
112 linkCache
.add_to_attrlist(attrlist
, value
)
114 linkCache
.add_attr(attrlist
, value
)
118 def _cache_delete(self
, attrlist
, value
=None):
119 if self
.DRYRUN
: return
121 if attrlist
[-1] == 'slaves':
122 linkCache
.remove_from_attrlist(attrlist
, value
)
124 linkCache
.del_attr(attrlist
)
128 def _cache_invalidate(self
):
129 if self
.DRYRUN
: return
130 linkCache
.invalidate()
132 def set_attrs(self
, bondname
, attrdict
, prehook
):
133 for attrname
, attrval
in attrdict
.items():
134 if (self
._cache
_check
([bondname
, 'linkinfo',
135 attrname
], attrval
)):
137 if (attrname
== 'mode' or attrname
== 'xmit_hash_policy' or
138 attrname
== 'lacp_rate' or attrname
== 'min_links'):
142 self
.write_file('/sys/class/net/%s/bonding/%s'
143 %(bondname
, attrname
), attrval
)
146 self
.logger
.warn(str(e
))
151 def set_use_carrier(self
, bondname
, use_carrier
):
152 if not use_carrier
or (use_carrier
!= '0' and use_carrier
!= '1'):
154 if (self
._cache
_check
([bondname
, 'linkinfo', 'use_carrier'],
157 self
.write_file('/sys/class/net/%s' %bondname
+
158 '/bonding/use_carrier', use_carrier
)
159 self
._cache
_update
([bondname
, 'linkinfo',
160 'use_carrier'], use_carrier
)
162 def get_use_carrier(self
, bondname
):
163 return self
._cache
_get
([bondname
, 'linkinfo', 'use_carrier'])
165 def set_xmit_hash_policy(self
, bondname
, hash_policy
, prehook
=None):
166 valid_values
= ['layer2', 'layer3+4', 'layer2+3']
169 if hash_policy
not in valid_values
:
170 raise Exception('invalid hash policy value %s' %hash_policy
)
171 if (self
._cache
_check
([bondname
, 'linkinfo', 'xmit_hash_policy'],
176 self
.write_file('/sys/class/net/%s' %bondname
+
177 '/bonding/xmit_hash_policy', hash_policy
)
178 self
._cache
_update
([bondname
, 'linkinfo', 'xmit_hash_policy'],
181 def get_xmit_hash_policy(self
, bondname
):
182 return self
._cache
_get
([bondname
, 'linkinfo', 'xmit_hash_policy'])
184 def set_miimon(self
, bondname
, miimon
):
185 if (self
._cache
_check
([bondname
, 'linkinfo', 'miimon'],
188 self
.write_file('/sys/class/net/%s' %bondname
+
189 '/bonding/miimon', miimon
)
190 self
._cache
_update
([bondname
, 'linkinfo', 'miimon'], miimon
)
192 def get_miimon(self
, bondname
):
193 return self
._cache
_get
([bondname
, 'linkinfo', 'miimon'])
195 def set_clag_enable(self
, bondname
, clag_id
):
196 clag_enable
= '0' if clag_id
== '0' else '1'
197 if self
._cache
_check
([bondname
, 'linkinfo', 'clag_enable'],
198 clag_enable
) == False:
199 self
.write_file('/sys/class/net/%s' %bondname
+
200 '/bonding/clag_enable', clag_enable
)
201 self
._cache
_update
([bondname
, 'linkinfo', 'clag_enable'],
204 def get_clag_enable(self
, bondname
):
205 return self
._cache
_get
([bondname
, 'linkinfo', 'clag_enable'])
207 def set_mode(self
, bondname
, mode
, prehook
=None):
208 valid_modes
= ['balance-rr', 'active-backup', 'balance-xor',
209 'broadcast', '802.3ad', 'balance-tlb', 'balance-alb']
212 if mode
not in valid_modes
:
213 raise Exception('invalid mode %s' %mode
)
214 if (self
._cache
_check
([bondname
, 'linkinfo', 'mode'],
219 self
.write_file('/sys/class/net/%s' %bondname
+ '/bonding/mode', mode
)
220 self
._cache
_update
([bondname
, 'linkinfo', 'mode'], mode
)
222 def get_mode(self
, bondname
):
223 return self
._cache
_get
([bondname
, 'linkinfo', 'mode'])
225 def set_lacp_rate(self
, bondname
, lacp_rate
, prehook
=None, posthook
=None):
226 if not lacp_rate
or (lacp_rate
!= '0' and lacp_rate
!= '1'):
228 if (self
._cache
_check
([bondname
, 'linkinfo', 'lacp_rate'],
234 self
.write_file('/sys/class/net/%s' %bondname
+
235 '/bonding/lacp_rate', lacp_rate
)
241 self
._cache
_update
([bondname
, 'linkinfo',
242 'lacp_rate'], lacp_rate
)
244 def get_lacp_rate(self
, bondname
):
245 return self
._cache
_get
([bondname
, 'linkinfo', 'lacp_rate'])
247 def set_lacp_fallback_allow(self
, bondname
, allow
, prehook
=None, posthook
=None):
248 if (self
._cache
_check
([bondname
, 'linkinfo', 'lacp_bypass_allow'],
254 self
.write_file('/sys/class/net/%s' %bondname
+
255 '/bonding/lacp_bypass_allow', allow
)
261 self
._cache
_update
([bondname
, 'linkinfo',
262 'lacp_bypass_allow'], allow
)
264 def get_lacp_fallback_allow(self
, bondname
):
265 return self
._cache
_get
([bondname
, 'linkinfo', 'lacp_bypass_allow'])
267 def set_lacp_fallback_period(self
, bondname
, period
, prehook
=None, posthook
=None):
268 if (self
._cache
_check
([bondname
, 'linkinfo', 'lacp_bypass_period'],
269 lacp_bypass_period
)):
274 self
.write_file('/sys/class/net/%s' %bondname
+
275 '/bonding/lacp_bypass_period', period
)
281 self
._cache
_update
([bondname
, 'linkinfo',
282 'lacp_bypass_period'], period
)
284 def get_lacp_fallback_period(self
, bondname
):
285 return self
._cache
_get
([bondname
, 'linkinfo', 'lacp_bypass_period'])
287 def set_min_links(self
, bondname
, min_links
, prehook
=None):
288 if (self
._cache
_check
([bondname
, 'linkinfo', 'min_links'],
293 self
.write_file('/sys/class/net/%s/bonding/min_links' %bondname
,
295 self
._cache
_update
([bondname
, 'linkinfo', 'min_links'], min_links
)
297 def get_min_links(self
, bondname
):
298 return self
._cache
_get
([bondname
, 'linkinfo', 'min_links'])
300 def set_lacp_fallback_priority(self
, bondname
, port
, val
):
301 slavefile
= '/sys/class/net/%s/bonding_slave/lacp_bypass_priority' %port
302 if os
.path
.exists(slavefile
):
303 self
.write_file(slavefile
, val
)
305 def get_lacp_fallback_priority(self
, bondname
):
306 slaves
= self
.get_slaves(bondname
)
311 priofile
= '/sys/class/net/%s/bonding_slave/lacp_bypass_priority' %slave
312 if os
.path
.exists(priofile
):
313 val
= self
.read_file_oneline(priofile
)
314 if val
and val
!= '0':
315 prio
= slave
+ '=' + val
318 prio_str
= ' '.join(prios
)
321 def set_lacp_fallback_all_active(self
, bondname
, useprio
, prehook
=None, posthook
=None):
322 if (self
._cache
_check
([bondname
, 'linkinfo', 'lacp_bypass_all_active'],
323 lacp_bypass_all_active
)):
328 self
.write_file('/sys/class/net/%s' %bondname
+
329 '/bonding/lacp_bypass_all_active', useprio
)
335 self
._cache
_update
([bondname
, 'linkinfo',
336 'lacp_bypass_all_active'], useprio
)
338 def get_lacp_fallback_all_active(self
, bondname
):
339 return self
._cache
_get
([bondname
, 'linkinfo', 'lacp_bypass_all_active'])
341 def get_ad_sys_mac_addr(self
, bondname
):
342 return self
._cache
_get
([bondname
, 'linkinfo', 'ad_sys_mac_addr'])
344 def get_ad_sys_priority(self
, bondname
):
345 return self
._cache
_get
([bondname
, 'linkinfo', 'ad_sys_priority'])
347 def enslave_slave(self
, bondname
, slave
, prehook
=None, posthook
=None):
348 slaves
= self
._cache
_get
([bondname
, 'linkinfo', 'slaves'])
349 if slaves
and slave
in slaves
: return
352 self
.write_file('/sys/class/net/%s' %bondname
+
353 '/bonding/slaves', '+' + slave
)
356 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slave
)
358 def remove_slave(self
, bondname
, slave
):
359 slaves
= self
._cache
_get
([bondname
, 'linkinfo', 'slaves'])
360 if slave
not in slaves
:
362 sysfs_bond_path
= ('/sys/class/net/%s' %bondname
+
364 if not os
.path
.exists(sysfs_bond_path
):
366 self
.write_file(sysfs_bond_path
, '-' + slave
)
367 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'], slave
)
369 def remove_slaves_all(self
, bondname
):
370 if not _self
._cache
_get
([bondname
, 'linkinfo', 'slaves']):
373 sysfs_bond_path
= ('/sys/class/net/%s' %bondname
+
377 f
= open(sysfs_bond_path
, 'r')
378 slaves
= f
.readline().strip().split()
381 raise Exception('error reading slaves of bond %s' %bondname
382 + '(' + str(e
) + ')')
384 ipcmd
.ip_link_down(slave
)
386 self
.remove_slave(bondname
, slave
)
389 raise Exception('error removing slave %s'
390 %slave
+ ' from bond %s' %bondname
+
394 self
._cache
_del
([bondname
, 'linkinfo', 'slaves'])
396 def load_bonding_module(self
):
397 return self
.exec_command('modprobe -q bonding')
399 def create_bond(self
, bondname
):
400 if self
.bond_exists(bondname
):
402 sysfs_net
= '/sys/class/net/'
403 sysfs_bonding_masters
= sysfs_net
+ 'bonding_masters'
404 if not os
.path
.exists(sysfs_bonding_masters
):
405 self
.logger
.debug('loading bonding driver')
406 self
.load_bonding_module()
408 self
.write_file(sysfs_bonding_masters
, '+' + bondname
)
409 self
._cache
_update
([bondname
], {})
411 def delete_bond(self
, bondname
):
412 if not os
.path
.exists('/sys/class/net/%s' %bondname
):
414 self
.write_file('/sys/class/net/bonding_masters', '-' + bondname
)
415 self
._cache
_delete
([bondname
])
417 def unset_master(self
, bondname
):
418 print 'Do nothing yet'
421 def get_slaves(self
, bondname
):
422 slaves
= self
._cache
_get
([bondname
, 'linkinfo', 'slaves'])
425 slavefile
= '/sys/class/net/%s/bonding/slaves' %bondname
426 if os
.path
.exists(slavefile
):
427 buf
= self
.read_file_oneline(slavefile
)
432 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slaves
)
435 def bond_slave_exists(self
, bond
, slave
):
436 slaves
= self
.get_slaves(bond
)
437 if not slaves
: return False
438 return slave
in slaves
440 def bond_exists(self
, bondname
):
441 return os
.path
.exists('/sys/class/net/%s/bonding' %bondname
)