]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - addons/vrf.py
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
9 from ifupdown
.iface
import *
10 import ifupdown
.policymanager
as policymanager
12 import ifupdown
.rtnetlink_api
as rtnetlink_api
13 from ifupdownaddons
.modulebase
import moduleBase
14 from ifupdownaddons
.bondutil
import bondutil
15 from ifupdownaddons
.iproute2
import iproute2
20 class vrf(moduleBase
):
21 """ ifupdown2 addon module to configure vrfs """
22 _modinfo
= { 'mhelp' : 'vrf configuration module',
25 {'help' : 'vrf device table id. key to ' +
26 'creating a vrf device',
27 'example': ['vrf-table-id 1']},
29 {'help' : 'vrf device default route ' +
30 'to avoid communication outside the vrf device',
31 'example': ['vrf-default-route yes/no']},
33 {'help' : 'vrf the interface is part of.',
34 'example': ['vrf blue']}}}
36 iproute2_vrf_filename
= '/etc/iproute2/rt_tables.d/ifupdown2_vrf_map.conf'
37 iproute2_vrf_filehdr
= '# This file is autogenerated by ifupdown2.\n' + \
38 '# It contains the vrf name to table mapping.\n' + \
39 '# Reserved table range %s %s\n'
40 VRF_TABLE_START
= 1001
43 def __init__(self
, *args
, **kargs
):
44 ifupdownaddons
.modulebase
.moduleBase
.__init
__(self
, *args
, **kargs
)
47 self
.name
= self
.__class
__.__name
__
49 ip_rules
= self
.exec_command('/sbin/ip rule show').splitlines()
50 self
.ip_rule_cache
= [' '.join(r
.split()) for r
in ip_rules
]
52 self
.ip_rule_cache
= []
53 self
.logger
.warn('%s' %str
(e
))
56 ip_rules
= self
.exec_command('/sbin/ip -6 rule show').splitlines()
57 self
.ip6_rule_cache
= [' '.join(r
.split()) for r
in ip_rules
]
59 self
.ip6_rule_cache
= []
60 self
.logger
.warn('%s' %str
(e
))
62 #self.logger.debug("vrf: ip rule cache")
63 #self.logger.info(self.ip_rule_cache)
65 #self.logger.info("vrf: ip -6 rule cache")
66 #self.logger.info(self.ip6_rule_cache)
68 # XXX: check for vrf reserved overlap in /etc/iproute2/rt_tables
69 self
.iproute2_vrf_map
= {}
70 # read or create /etc/iproute2/rt_tables.d/ifupdown2.vrf_map
71 if os
.path
.exists(self
.iproute2_vrf_filename
):
72 self
.vrf_map_fd
= open(self
.iproute2_vrf_filename
, 'a+')
73 lines
= self
.vrf_map_fd
.readlines()
79 (table
, vrf_name
) = l
.strip().split()
80 self
.iproute2_vrf_map
[table
] = vrf_name
82 self
.logger
.info('vrf: iproute2_vrf_map: unable to parse %s'
85 #self.logger.info("vrf: dumping iproute2_vrf_map")
86 #self.logger.info(self.iproute2_vrf_map)
88 # purge vrf table entries that are not around
89 iproute2_vrf_map_pruned
= {}
90 for t
, v
in self
.iproute2_vrf_map
.iteritems():
91 if os
.path
.exists('/sys/class/net/%s' %v
):
92 iproute2_vrf_map_pruned
[t
] = v
96 self
._del
_vrf
_rules
(v
, t
)
99 self
.iproute2_vrf_map
= iproute2_vrf_map_pruned
101 self
.vrf_table_id_start
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-table-id-start')
102 if not self
.vrf_table_id_start
:
103 self
.vrf_table_id_start
= self
.VRF_TABLE_START
104 self
.vrf_table_id_end
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-table-id-end')
105 if not self
.vrf_table_id_end
:
106 self
.vrf_table_id_end
= self
.VRF_TABLE_END
107 self
.vrf_max_count
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-max-count')
109 last_used_vrf_table
= None
110 for t
in range(self
.vrf_table_id_start
,
111 self
.vrf_table_id_end
):
112 if not self
.iproute2_vrf_map
.get(t
):
114 last_used_vrf_table
= t
115 self
.last_used_vrf_table
= last_used_vrf_table
116 self
.iproute2_write_vrf_map
= False
117 atexit
.register(self
.iproute2_vrf_map_write
)
118 self
.vrf_fix_local_table
= True
120 self
.vrf_cgroup_create
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='vrf-cgroup-create')
121 if not self
.vrf_cgroup_create
:
122 self
.vrf_cgroup_create
= False
123 elif self
.vrf_cgroup_create
== 'yes':
124 self
.vrf_cgroup_create
= True
126 self
.vrf_cgroup_create
= False
128 def iproute2_vrf_map_write(self
):
129 if not self
.iproute2_write_vrf_map
:
131 self
.logger
.info('vrf: writing table map to %s'
132 %self
.iproute2_vrf_filename
)
133 with
open(self
.iproute2_vrf_filename
, 'w') as f
:
134 f
.write(self
.iproute2_vrf_filehdr
%(self
.vrf_table_id_start
,
135 self
.vrf_table_id_end
))
136 for t
, v
in self
.iproute2_vrf_map
.iteritems():
137 f
.write('%s %s\n' %(t
, v
))
139 def _is_vrf(self
, ifaceobj
):
140 if ifaceobj
.get_attr_value_first('vrf-table'):
144 def get_upper_ifacenames(self
, ifaceobj
, ifacenames_all
=None):
145 """ Returns list of interfaces dependent on ifaceobj """
147 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
149 ifaceobj
.link_type
= ifaceLinkType
.LINK_MASTER
150 ifaceobj
.link_kind |
= ifaceLinkKind
.VRF
151 vrf_iface_name
= ifaceobj
.get_attr_value_first('vrf')
152 if not vrf_iface_name
:
154 ifaceobj
.link_type
= ifaceLinkType
.LINK_SLAVE
155 ifaceobj
.link_kind |
= ifaceLinkKind
.VRF_SLAVE
157 return [vrf_iface_name
]
159 def get_upper_ifacenames_running(self
, ifaceobj
):
162 def _get_iproute2_vrf_table(self
, vrf_dev_name
):
163 for t
, v
in self
.iproute2_vrf_map
.iteritems():
164 if v
== vrf_dev_name
:
168 def _get_avail_vrf_table_id(self
):
169 if self
.last_used_vrf_table
== None:
170 table_id_start
= self
.vrf_table_id_start
172 table_id_start
= self
.last_used_vrf_table
+ 1
173 for t
in range(table_id_start
,
174 self
.vrf_table_id_end
):
175 if not self
.iproute2_vrf_map
.get(t
):
176 self
.last_used_vrf_table
= t
180 def _iproute2_vrf_table_entry_add(self
, vrf_dev_name
, table_id
):
181 self
.iproute2_vrf_map
[table_id
] = vrf_dev_name
182 self
.iproute2_write_vrf_map
= True
184 def _iproute2_vrf_table_entry_del(self
, table_id
):
186 del self
.iproute2_vrf_map
[table_id
]
187 self
.iproute2_write_vrf_map
= True
189 self
.logger
.info('vrf: iproute2 vrf map del failed for %d (%s)'
193 def _handle_dhcp_slaves(self
, ifacename
, vrfname
, ifaceobj
,
195 """ If we have a vrf slave that has dhcp configured, bring up the
196 vrf master now. This is needed because vrf has special handling
197 in dhclient hook which requires the vrf master to be present """
199 if (not ifaceobj
.addr_method
or
200 (ifaceobj
.addr_method
!= 'dhcp' and
201 ifaceobj
.addr_method
!= 'dhcp6')):
203 vrf_master
= ifaceobj
.upperifaces
[0]
205 self
.logger
.warn('%s: vrf master not found' %ifacename
)
207 if os
.path
.exists('/sys/class/net/%s' %vrf_master
):
208 self
.logger
.info('%s: vrf master %s exists returning'
209 %(ifacename
, vrf_master
))
211 vrf_master_objs
= ifaceobj_getfunc(vrf_master
)
212 if not vrf_master_objs
:
213 self
.logger
.warn('%s: vrf master ifaceobj not found' %ifacename
)
215 self
.logger
.info('%s: bringing up vrf master %s'
216 %(ifacename
, vrf_master
))
217 for mobj
in vrf_master_objs
:
218 vrf_table
= mobj
.get_attr_value_first('vrf-table')
220 if vrf_table
== 'auto':
221 vrf_table
= self
._get
_avail
_vrf
_table
_id
()
223 self
.log_error('%s: unable to get an auto table id'
225 self
.logger
.info('%s: table id auto: selected table id %s\n'
226 %(mobj
.name
, vrf_table
))
227 self
._up
_vrf
_dev
(mobj
, vrf_table
, False)
229 self
.ipcmd
.link_set(ifacename
, 'master', vrfname
)
232 def _up_vrf_slave(self
, ifacename
, vrfname
, ifaceobj
=None,
233 ifaceobj_getfunc
=None):
235 if self
.ipcmd
.link_exists(vrfname
):
236 self
.ipcmd
.link_set(ifacename
, 'master', vrfname
)
238 self
._handle
_dhcp
_slaves
(ifacename
, vrfname
, ifaceobj
,
241 self
.logger
.warn('%s: %s' %(ifacename
, str(e
)))
243 def _del_vrf_rules(self
, vrf_dev_name
, vrf_table
):
245 ip_rule_out_format
= '%s: from all %s %s lookup %s'
246 ip_rule_cmd
= 'ip %s rule del pref %s %s %s table %s'
248 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
249 if rule
in self
.ip_rule_cache
:
250 rule_cmd
= ip_rule_cmd
%('', pref
, 'oif', vrf_dev_name
, vrf_table
)
251 self
.exec_command(rule_cmd
)
253 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
254 if rule
in self
.ip_rule_cache
:
255 rule_cmd
= ip_rule_cmd
%('', pref
, 'iif', vrf_dev_name
, vrf_table
)
256 self
.exec_command(rule_cmd
)
258 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
259 if rule
in self
.ip_rule_cache
:
260 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'oif', vrf_dev_name
,
262 self
.exec_command(rule_cmd
)
264 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
265 if rule
in self
.ip_rule_cache
:
266 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'iif', vrf_dev_name
,
268 self
.exec_command(rule_cmd
)
270 def _add_vrf_rules(self
, vrf_dev_name
, vrf_table
):
272 ip_rule_out_format
= '%s: from all %s %s lookup %s'
273 ip_rule_cmd
= 'ip %s rule add pref %s %s %s table %s'
274 if self
.vrf_fix_local_table
:
275 self
.vrf_fix_local_table
= False
276 rule
= '0: from all lookup local'
277 if rule
in self
.ip_rule_cache
:
279 self
.exec_command('ip rule del pref 0')
280 self
.exec_command('ip rule add pref 32765 table local')
282 self
.logger
.info('%s' %str
(e
))
286 #200: from all oif blue lookup blue
287 #200: from all iif blue lookup blue
289 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
290 if rule
not in self
.ip_rule_cache
:
291 rule_cmd
= ip_rule_cmd
%('', pref
, 'oif', vrf_dev_name
, vrf_table
)
292 self
.exec_command(rule_cmd
)
294 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
295 if rule
not in self
.ip_rule_cache
:
296 rule_cmd
= ip_rule_cmd
%('', pref
, 'iif', vrf_dev_name
, vrf_table
)
297 self
.exec_command(rule_cmd
)
299 rule
= ip_rule_out_format
%(pref
, 'oif', vrf_dev_name
, vrf_dev_name
)
300 if rule
not in self
.ip_rule_cache
:
301 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'oif', vrf_dev_name
, vrf_table
)
302 self
.exec_command(rule_cmd
)
304 rule
= ip_rule_out_format
%(pref
, 'iif', vrf_dev_name
, vrf_dev_name
)
305 if rule
not in self
.ip_rule_cache
:
306 rule_cmd
= ip_rule_cmd
%('-6', pref
, 'iif', vrf_dev_name
,
308 self
.exec_command(rule_cmd
)
310 def _add_vrf_slaves(self
, ifaceobj
):
311 running_slaves
= self
.ipcmd
.link_get_lowers(ifaceobj
.name
)
312 config_slaves
= ifaceobj
.lowerifaces
313 if not config_slaves
and not running_slaves
:
315 add_slaves
= set(config_slaves
).difference(set(running_slaves
))
316 del_slaves
= set(running_slaves
).difference(set(config_slaves
))
320 self
._up
_vrf
_slave
(s
, ifaceobj
.name
)
322 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
327 self
._down
_vrf
_slave
(s
, ifaceobj
.name
)
329 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
331 if ifaceobj
.link_type
== ifaceLinkType
.LINK_MASTER
:
332 for s
in config_slaves
:
334 rtnetlink_api
.rtnl_api
.link_set(s
, "up")
336 self
.logger
.debug('%s: %s: link set up (%s)'
337 %(ifaceobj
.name
, s
, str(e
)))
340 def _create_cgroup(self
, ifaceobj
):
341 if not self
.vrf_cgroup_create
:
344 if not os
.path
.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj
.name
):
345 self
.exec_command('/usr/bin/cgcreate -g l3mdev:%s' %ifaceobj
.name
)
347 self
.log_error('%s: cgroup create failed (%s)\n'
348 %(ifaceobj
.name
, str(e
)), ifaceobj
)
350 self
.exec_command('/usr/bin/cgset -r l3mdev.master-device=%s %s'
351 %(ifaceobj
.name
, ifaceobj
.name
))
353 self
.log_warn('%s: cgset failed (%s)\n'
354 %(ifaceobj
.name
, str(e
)), ifaceobj
)
356 def _set_vrf_dev_processed_flag(self
, ifaceobj
):
357 ifaceobj
.module_flags
[self
.name
] = \
358 ifaceobj
.module_flags
.setdefault(self
.name
, 0) | \
359 vrfPrivFlags
.PROCESSED
361 def _check_vrf_dev_processed_flag(self
, ifaceobj
):
362 if (ifaceobj
.module_flags
.get(self
.name
, 0x0) & vrfPrivFlags
.PROCESSED
):
366 def _create_vrf_dev(self
, ifaceobj
, vrf_table
):
367 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
368 if vrf_table
== 'auto':
369 vrf_table
= self
._get
_avail
_vrf
_table
_id
()
371 self
.log_error('%s: unable to get an auto table id'
373 self
.logger
.info('%s: table id auto: selected table id %s\n'
374 %(ifaceobj
.name
, vrf_table
))
375 # XXX: If we decide to not allow vrf id usages out of
376 # the reserved ifupdown range, then uncomment this code.
378 # if (int(vrf_table) < self.vrf_table_id_start or
379 # int(vrf_table) > self.vrf_table_id_end):
380 # self.log_error('%s: vrf table id %s out of reserved range [%d,%d]'
381 # %(ifaceobj.name, vrf_table,
382 # self.vrf_table_id_start,
383 # self.vrf_table_id_end))
385 self
.ipcmd
.link_create(ifaceobj
.name
, 'vrf',
386 {'table' : '%s' %vrf_table
})
388 self
.log_error('%s: create failed (%s)\n'
389 %(ifaceobj
.name
, str(e
)))
391 vrf_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
393 self
.log_error('%s: unable to get vrf table id'
396 # if the device exists, check if table id is same
397 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobj
.name
)
399 running_table
= vrfdev_attrs
.get('table', None)
400 if vrf_table
!= running_table
:
401 self
.log_error('%s: cannot change vrf table id,running table id %s is different from config id %s' %(ifaceobj
.name
,
402 running_table
, vrf_table
))
404 def _add_vrf_default_route(self
, ifaceobj
, vrf_table
):
405 vrf_default_route
= ifaceobj
.get_attr_value_first('vrf-default-route')
406 if not vrf_default_route
:
407 vrf_default_route
= policymanager
.policymanager_api
.get_attr_default(
408 module_name
=self
.__class
__.__name
__,
409 attr
='vrf-default-route')
410 if not vrf_default_route
:
412 if str(vrf_default_route
).lower() == "yes":
414 self
.exec_command('ip route add table %s unreachable default'
415 ' metric %d' %(vrf_table
, 240))
422 self
.exec_command('ip -6 route add table %s unreachable '
423 'default metric %d' %(vrf_table
, 240))
429 def _up_vrf_dev(self
, ifaceobj
, vrf_table
, add_slaves
=True):
431 # if vrf dev is already processed return. This can happen
432 # if we had a dhcp slave. See self._handle_dhcp_slaves
433 if self
._check
_vrf
_dev
_processed
_flag
(ifaceobj
):
436 self
._create
_vrf
_dev
(ifaceobj
, vrf_table
)
438 self
._iproute
2_vrf
_table
_entry
_add
(ifaceobj
.name
, vrf_table
)
439 self
._add
_vrf
_rules
(ifaceobj
.name
, vrf_table
)
440 self
._create
_cgroup
(ifaceobj
)
442 self
._add
_vrf
_slaves
(ifaceobj
)
443 self
._add
_vrf
_default
_route
(ifaceobj
, vrf_table
)
444 self
._set
_vrf
_dev
_processed
_flag
(ifaceobj
)
446 self
.log_error('%s: %s' %(ifaceobj
.name
, str(e
)))
448 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
450 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
452 if self
.vrf_count
== self
.vrf_max_count
:
453 self
.log_error('%s: max vrf count %d hit...not '
454 'creating vrf' %(ifaceobj
.name
,
456 self
._up
_vrf
_dev
(ifaceobj
, vrf_table
)
458 vrf
= ifaceobj
.get_attr_value_first('vrf')
460 self
._up
_vrf
_slave
(ifaceobj
.name
, vrf
, ifaceobj
,
463 self
.log_error(str(e
))
465 def _delete_cgroup(self
, ifaceobj
):
467 if os
.path
.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj
.name
):
468 self
.exec_command('cgdelete -g l3mdev:%s' %ifaceobj
.name
)
470 self
.log_warn('%s: cgroup delete failed (%s)\n'
471 %(ifaceobj
.name
, str(e
)), ifaceobj
)
473 def _down_vrf_dev(self
, ifaceobj
, vrf_table
):
474 if vrf_table
== 'auto':
475 vrf_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
477 self
.ipcmd
.link_delete(ifaceobj
.name
)
479 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
483 self
._iproute
2_vrf
_table
_entry
_del
(vrf_table
)
484 self
._delete
_cgroup
(ifaceobj
)
486 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
490 self
._del
_vrf
_rules
(ifaceobj
.name
, vrf_table
)
492 self
.logger
.info('%s: %s' %(ifaceobj
.name
, str(e
)))
495 def _down_vrf_slave(self
, ifacename
, vrf
):
497 self
.ipcmd
.link_set(ifacename
, 'nomaster')
499 self
.logger
.warn('%s: %s' %(ifacename
, str(e
)))
501 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
503 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
505 self
._down
_vrf
_dev
(ifaceobj
, vrf_table
)
507 vrf
= ifaceobj
.get_attr_value_first('vrf')
509 self
._down
_vrf
_slave
(ifaceobj
.name
, vrf
)
511 self
.log_warn(str(e
))
513 def _query_check_vrf_slave(self
, ifaceobj
, ifaceobjcurr
, vrf
):
515 master
= self
.ipcmd
.link_get_master(ifaceobj
.name
)
516 if not master
or master
!= vrf
:
517 ifaceobjcurr
.update_config_with_status('vrf', master
, 1)
519 ifaceobjcurr
.update_config_with_status('vrf', master
, 0)
521 self
.log_warn(str(e
))
523 def _query_check_vrf_dev(self
, ifaceobj
, ifaceobjcurr
, vrf_table
):
525 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
526 self
.logger
.info('%s: vrf: does not exist' %(ifaceobj
.name
))
528 if vrf_table
== 'auto':
529 config_table
= self
._get
_iproute
2_vrf
_table
(ifaceobj
.name
)
531 config_table
= vrf_table
532 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobj
.name
)
534 ifaceobjcurr
.update_config_with_status('vrf-table', 'None', 1)
536 running_table
= vrfdev_attrs
.get('table')
537 if not running_table
:
538 ifaceobjcurr
.update_config_with_status('vrf-table', 'None', 1)
540 if config_table
!= running_table
:
541 ifaceobjcurr
.update_config_with_status('vrf-table',
544 ifaceobjcurr
.update_config_with_status('vrf-table',
547 self
.log_warn(str(e
))
549 def _query_check(self
, ifaceobj
, ifaceobjcurr
):
551 vrf_table
= ifaceobj
.get_attr_value_first('vrf-table')
553 self
._query
_check
_vrf
_dev
(ifaceobj
, ifaceobjcurr
, vrf_table
)
555 vrf
= ifaceobj
.get_attr_value_first('vrf')
557 self
._query
_check
_vrf
_slave
(ifaceobj
, ifaceobjcurr
, vrf
)
559 self
.log_warn(str(e
))
561 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
563 kind
= self
.ipcmd
.link_get_kind(ifaceobjrunning
.name
)
565 vrfdev_attrs
= self
.ipcmd
.link_get_linkinfo_attrs(ifaceobjrunning
.name
)
567 running_table
= vrfdev_attrs
.get('table')
569 ifaceobjrunning
.update_config('vrf-table',
571 elif kind
== 'vrf_slave':
572 vrf
= self
.ipcmd
.link_get_master(ifaceobjrunning
.name
)
574 ifaceobjrunning
.update_config('vrf', vrf
)
576 self
.log_warn(str(e
))
578 _run_ops
= {'pre-up' : _up
,
580 'query-running' : _query_running
,
581 'query-checkcurr' : _query_check
}
584 """ returns list of ops supported by this module """
585 return self
._run
_ops
.keys()
587 def _init_command_handlers(self
):
588 flags
= self
.get_flags()
590 self
.ipcmd
= iproute2(**flags
)
592 self
.bondcmd
= bondutil(**flags
)
594 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None,
595 ifaceobj_getfunc
=None, **extra_args
):
596 """ run bond configuration on the interface object passed as argument
599 **ifaceobj** (object): iface object
601 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
605 **query_ifaceobj** (object): query check ifaceobject. This is only
606 valid when op is 'query-checkcurr'. It is an object same as
607 ifaceobj, but contains running attribute values and its config
608 status. The modules can use it to return queried running state
609 of interfaces. status is success if the running state is same
610 as user required state in ifaceobj. error otherwise.
612 op_handler
= self
._run
_ops
.get(operation
)
615 self
._init
_command
_handlers
()
616 if operation
== 'query-checkcurr':
617 op_handler(self
, ifaceobj
, query_ifaceobj
)
619 op_handler(self
, ifaceobj
, ifaceobj_getfunc
=ifaceobj_getfunc
)