]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/addons/dhcp.py
3 # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
11 import ifupdown2
.ifupdown
.policymanager
as policymanager
12 import ifupdown2
.ifupdown
.ifupdownflags
as ifupdownflags
14 from ifupdown2
.ifupdown
.iface
import *
15 from ifupdown2
.ifupdown
.utils
import utils
17 from ifupdown2
.ifupdownaddons
.dhclient
import dhclient
18 from ifupdown2
.ifupdownaddons
.LinkUtils
import LinkUtils
19 from ifupdown2
.ifupdownaddons
.modulebase
import moduleBase
21 import ifupdown
.policymanager
as policymanager
22 import ifupdown
.ifupdownflags
as ifupdownflags
24 from ifupdown
.iface
import *
25 from ifupdown
.utils
import utils
27 from ifupdownaddons
.dhclient
import dhclient
28 from ifupdownaddons
.LinkUtils
import LinkUtils
29 from ifupdownaddons
.modulebase
import moduleBase
32 class dhcp(moduleBase
):
33 """ ifupdown2 addon module to configure dhcp on interface """
35 def __init__(self
, *args
, **kargs
):
36 moduleBase
.__init
__(self
, *args
, **kargs
)
37 self
.dhclientcmd
= dhclient(**kargs
)
40 def syntax_check(self
, ifaceobj
, ifaceobj_getfunc
):
41 return self
.is_dhcp_allowed_on(ifaceobj
, syntax_check
=True)
43 def is_dhcp_allowed_on(self
, ifaceobj
, syntax_check
):
44 if ifaceobj
.addr_method
and 'dhcp' in ifaceobj
.addr_method
:
45 return utils
.is_addr_ip_allowed_on(ifaceobj
, syntax_check
=True)
48 def _up(self
, ifaceobj
):
49 # if dhclient is already running do not stop and start it
50 dhclient4_running
= self
.dhclientcmd
.is_running(ifaceobj
.name
)
51 dhclient6_running
= self
.dhclientcmd
.is_running6(ifaceobj
.name
)
53 # today if we have an interface with both inet and inet6, if we
54 # remove the inet or inet6 or both then execute ifreload, we need
55 # to release/kill the appropriate dhclient(4/6) if they are running
56 self
._down
_stale
_dhcp
_config
(ifaceobj
, 'inet', dhclient4_running
)
57 self
._down
_stale
_dhcp
_config
(ifaceobj
, 'inet6', dhclient6_running
)
60 dhclient_cmd_prefix
= None
61 dhcp_wait
= policymanager
.policymanager_api
.get_attr_default(
62 module_name
=self
.__class
__.__name
__, attr
='dhcp-wait')
63 wait
= not str(dhcp_wait
).lower() == "no"
64 inet6_ll_wait
= policymanager
.policymanager_api
.get_iface_default(module_name
=self
.__class
__.__name
__, \
65 ifname
=ifaceobj
.name
, attr
='inet6-ll-wait')
67 ll_wait_time
= int(inet6_ll_wait
)
72 vrf
= ifaceobj
.get_attr_value_first('vrf')
73 if (vrf
and self
.vrf_exec_cmd_prefix
and
74 self
.ipcmd
.link_exists(vrf
)):
75 dhclient_cmd_prefix
= '%s %s' %(self
.vrf_exec_cmd_prefix
, vrf
)
77 if 'inet' in ifaceobj
.addr_family
:
79 self
.logger
.info('dhclient4 already running on %s. '
80 'Not restarting.' % ifaceobj
.name
)
82 # First release any existing dhclient processes
84 if not ifupdownflags
.flags
.PERFMODE
:
85 self
.dhclientcmd
.stop(ifaceobj
.name
)
88 self
.dhclientcmd
.start(ifaceobj
.name
, wait
=wait
,
89 cmd_prefix
=dhclient_cmd_prefix
)
90 if 'inet6' in ifaceobj
.addr_family
:
92 self
.logger
.info('dhclient6 already running on %s. '
93 'Not restarting.' % ifaceobj
.name
)
95 accept_ra
= ifaceobj
.get_attr_value_first('accept_ra')
98 self
.sysctl_set('net.ipv6.conf.%s' %ifaceobj
.name
+
99 '.accept_ra', accept_ra
)
100 autoconf
= ifaceobj
.get_attr_value_first('autoconf')
102 # XXX: Validate value
103 self
.sysctl_set('net.ipv6.conf.%s' %ifaceobj
.name
+
104 '.autoconf', autoconf
)
106 self
.dhclientcmd
.stop6(ifaceobj
.name
)
109 #add delay before starting IPv6 dhclient to
110 #make sure the configured interface/link is up.
112 timeout
= ll_wait_time
115 timeout
= ll_wait_time
+1
118 addr_output
= utils
.exec_command('%s -6 addr show %s'
119 %(utils
.ip_cmd
, ifaceobj
.name
))
120 r
= re
.search('inet6 .* scope link', addr_output
)
122 self
.dhclientcmd
.start6(ifaceobj
.name
,
124 cmd_prefix
=dhclient_cmd_prefix
)
131 self
.log_error(str(e
), ifaceobj
)
133 def _down_stale_dhcp_config(self
, ifaceobj
, family
, dhclientX_running
):
134 addr_family
= ifaceobj
.addr_family
136 if not family
in ifaceobj
.addr_family
and dhclientX_running
:
137 ifaceobj
.addr_family
= [family
]
138 self
._dhcp
_down
(ifaceobj
)
142 ifaceobj
.addr_family
= addr_family
144 def _dhcp_down(self
, ifaceobj
):
145 dhclient_cmd_prefix
= None
146 vrf
= ifaceobj
.get_attr_value_first('vrf')
147 if (vrf
and self
.vrf_exec_cmd_prefix
and
148 self
.ipcmd
.link_exists(vrf
)):
149 dhclient_cmd_prefix
= '%s %s' %(self
.vrf_exec_cmd_prefix
, vrf
)
150 if 'inet6' in ifaceobj
.addr_family
:
151 self
.dhclientcmd
.release6(ifaceobj
.name
, dhclient_cmd_prefix
)
152 if 'inet' in ifaceobj
.addr_family
:
153 self
.dhclientcmd
.release(ifaceobj
.name
, dhclient_cmd_prefix
)
155 def _down(self
, ifaceobj
):
156 self
._dhcp
_down
(ifaceobj
)
157 self
.ipcmd
.link_down(ifaceobj
.name
)
159 def _query_check(self
, ifaceobj
, ifaceobjcurr
):
160 status
= ifaceStatus
.SUCCESS
163 dhcp_v4
= self
.dhclientcmd
.is_running(ifaceobjcurr
.name
)
164 dhcp_v6
= self
.dhclientcmd
.is_running6(ifaceobjcurr
.name
)
168 if 'inet' not in ifaceobj
.addr_family
and not dhcp_v6
:
169 status
= ifaceStatus
.ERROR
170 ifaceobjcurr
.addr_method
= 'dhcp'
173 if 'inet6' not in ifaceobj
.addr_family
and not dhcp_v4
:
174 status
= ifaceStatus
.ERROR
175 ifaceobjcurr
.addr_method
= 'dhcp'
176 ifaceobjcurr
.addr_family
= ifaceobj
.addr_family
178 ifaceobjcurr
.addr_family
= []
179 status
= ifaceStatus
.ERROR
180 ifaceobjcurr
.status
= status
182 def _query_running(self
, ifaceobjrunning
):
183 if not self
.ipcmd
.link_exists(ifaceobjrunning
.name
):
185 if self
.dhclientcmd
.is_running(ifaceobjrunning
.name
):
186 ifaceobjrunning
.addr_family
.append('inet')
187 ifaceobjrunning
.addr_method
= 'dhcp'
188 if self
.dhclientcmd
.is_running6(ifaceobjrunning
.name
):
189 ifaceobjrunning
.addr_family
.append('inet6')
190 ifaceobjrunning
.addr_method
= 'dhcp6'
192 _run_ops
= {'up' : _up
,
195 'query-checkcurr' : _query_check
,
196 'query-running' : _query_running
}
199 """ returns list of ops supported by this module """
200 return self
._run
_ops
.keys()
202 def _init_command_handlers(self
):
204 self
.ipcmd
= LinkUtils()
206 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None, **extra_args
):
207 """ run dhcp configuration on the interface object passed as argument
210 **ifaceobj** (object): iface object
212 **operation** (str): any of 'up', 'down', 'query-checkcurr',
216 **query_ifaceobj** (object): query check ifaceobject. This is only
217 valid when op is 'query-checkcurr'. It is an object same as
218 ifaceobj, but contains running attribute values and its config
219 status. The modules can use it to return queried running state
220 of interfaces. status is success if the running state is same
221 as user required state in ifaceobj. error otherwise.
223 op_handler
= self
._run
_ops
.get(operation
)
227 if (operation
!= 'query-running' and
228 (ifaceobj
.addr_method
!= 'dhcp' and
229 ifaceobj
.addr_method
!= 'dhcp6')):
233 if not self
.is_dhcp_allowed_on(ifaceobj
, syntax_check
=False):
235 self
._init
_command
_handlers
()
236 if operation
== 'query-checkcurr':
237 op_handler(self
, ifaceobj
, query_ifaceobj
)
239 op_handler(self
, ifaceobj
)