]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - addons/dhcp.py
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
9 from ipaddr
import IPNetwork
11 from ifupdown
.iface
import *
12 import ifupdown
.policymanager
as policymanager
13 from ifupdownaddons
.modulebase
import moduleBase
14 from ifupdownaddons
.dhclient
import dhclient
15 from ifupdownaddons
.iproute2
import iproute2
16 import ifupdown
.ifupdownflags
as ifupdownflags
17 from ifupdown
.utils
import utils
19 from ifupdown
.netlink
import netlink
20 except ImportError, e
:
21 raise ImportError (str(e
) + "- required module not found")
23 class dhcp(moduleBase
):
24 """ ifupdown2 addon module to configure dhcp on interface """
26 def __init__(self
, *args
, **kargs
):
27 moduleBase
.__init
__(self
, *args
, **kargs
)
28 self
.dhclientcmd
= dhclient(**kargs
)
31 def syntax_check(self
, ifaceobj
, ifaceobj_getfunc
):
32 return self
.is_dhcp_allowed_on(ifaceobj
, syntax_check
=True)
34 def is_dhcp_allowed_on(self
, ifaceobj
, syntax_check
):
35 if ifaceobj
.addr_method
and 'dhcp' in ifaceobj
.addr_method
:
36 return utils
.is_addr_ip_allowed_on(ifaceobj
, syntax_check
=True)
39 def _up(self
, ifaceobj
):
40 # if dhclient is already running do not stop and start it
41 dhclient4_running
= self
.dhclientcmd
.is_running(ifaceobj
.name
)
42 dhclient6_running
= self
.dhclientcmd
.is_running6(ifaceobj
.name
)
44 # today if we have an interface with both inet and inet6, if we
45 # remove the inet or inet6 or both then execute ifreload, we need
46 # to release/kill the appropriate dhclient(4/6) if they are running
47 self
._down
_stale
_dhcp
_config
(ifaceobj
, 'inet', dhclient4_running
)
48 self
._down
_stale
_dhcp
_config
(ifaceobj
, 'inet6', dhclient6_running
)
51 dhclient_cmd_prefix
= None
52 dhcp_wait
= policymanager
.policymanager_api
.get_attr_default(
53 module_name
=self
.__class
__.__name
__, attr
='dhcp-wait')
54 wait
= not str(dhcp_wait
).lower() == "no"
55 vrf
= ifaceobj
.get_attr_value_first('vrf')
56 if (vrf
and self
.vrf_exec_cmd_prefix
and
57 self
.ipcmd
.link_exists(vrf
)):
58 dhclient_cmd_prefix
= '%s %s' %(self
.vrf_exec_cmd_prefix
, vrf
)
60 if 'inet' in ifaceobj
.addr_family
:
62 self
.logger
.info('dhclient4 already running on %s. '
63 'Not restarting.' % ifaceobj
.name
)
65 # First release any existing dhclient processes
67 if not ifupdownflags
.flags
.PERFMODE
:
68 self
.dhclientcmd
.stop(ifaceobj
.name
)
71 self
.dhclientcmd
.start(ifaceobj
.name
, wait
=wait
,
72 cmd_prefix
=dhclient_cmd_prefix
)
73 if 'inet6' in ifaceobj
.addr_family
:
75 self
.logger
.info('dhclient6 already running on %s. '
76 'Not restarting.' % ifaceobj
.name
)
78 accept_ra
= ifaceobj
.get_attr_value_first('accept_ra')
81 self
.sysctl_set('net.ipv6.conf.%s' %ifaceobj
.name
+
82 '.accept_ra', accept_ra
)
83 autoconf
= ifaceobj
.get_attr_value_first('autoconf')
86 self
.sysctl_set('net.ipv6.conf.%s' %ifaceobj
.name
+
87 '.autoconf', autoconf
)
89 self
.dhclientcmd
.stop6(ifaceobj
.name
)
92 #add delay before starting IPv6 dhclient to
93 #make sure the configured interface/link is up.
98 addr_output
= utils
.exec_command('ip -6 addr show %s'
100 r
= re
.search('inet6 .* scope link', addr_output
)
102 self
.dhclientcmd
.start6(ifaceobj
.name
,
104 cmd_prefix
=dhclient_cmd_prefix
)
109 self
.log_error(str(e
), ifaceobj
)
111 def _down_stale_dhcp_config(self
, ifaceobj
, family
, dhclientX_running
):
112 addr_family
= ifaceobj
.addr_family
114 if not family
in ifaceobj
.addr_family
and dhclientX_running
:
115 ifaceobj
.addr_family
= [family
]
116 self
._dhcp
_down
(ifaceobj
)
120 ifaceobj
.addr_family
= addr_family
122 def _dhcp_down(self
, ifaceobj
):
123 dhclient_cmd_prefix
= None
124 vrf
= ifaceobj
.get_attr_value_first('vrf')
125 if (vrf
and self
.vrf_exec_cmd_prefix
and
126 self
.ipcmd
.link_exists(vrf
)):
127 dhclient_cmd_prefix
= '%s %s' %(self
.vrf_exec_cmd_prefix
, vrf
)
128 if 'inet6' in ifaceobj
.addr_family
:
129 self
.dhclientcmd
.release6(ifaceobj
.name
, dhclient_cmd_prefix
)
130 if 'inet' in ifaceobj
.addr_family
:
131 self
.dhclientcmd
.release(ifaceobj
.name
, dhclient_cmd_prefix
)
133 def _down(self
, ifaceobj
):
134 self
._dhcp
_down
(ifaceobj
)
135 self
.ipcmd
.link_down(ifaceobj
.name
)
137 def _query_check(self
, ifaceobj
, ifaceobjcurr
):
138 status
= ifaceStatus
.SUCCESS
141 dhcp_v4
= self
.dhclientcmd
.is_running(ifaceobjcurr
.name
)
142 dhcp_v6
= self
.dhclientcmd
.is_running6(ifaceobjcurr
.name
)
146 if 'inet' not in ifaceobj
.addr_family
and not dhcp_v6
:
147 status
= ifaceStatus
.ERROR
148 ifaceobjcurr
.addr_method
= 'dhcp'
151 if 'inet6' not in ifaceobj
.addr_family
and not dhcp_v4
:
152 status
= ifaceStatus
.ERROR
153 ifaceobjcurr
.addr_method
= 'dhcp'
154 ifaceobjcurr
.addr_family
= ifaceobj
.addr_family
156 ifaceobjcurr
.addr_family
= []
157 status
= ifaceStatus
.ERROR
158 ifaceobjcurr
.status
= status
160 def _query_running(self
, ifaceobjrunning
):
161 if not self
.ipcmd
.link_exists(ifaceobjrunning
.name
):
163 if self
.dhclientcmd
.is_running(ifaceobjrunning
.name
):
164 ifaceobjrunning
.addr_family
.append('inet')
165 ifaceobjrunning
.addr_method
= 'dhcp'
166 if self
.dhclientcmd
.is_running6(ifaceobjrunning
.name
):
167 ifaceobjrunning
.addr_family
.append('inet6')
168 ifaceobjrunning
.addr_method
= 'dhcp6'
170 _run_ops
= {'up' : _up
,
173 'query-checkcurr' : _query_check
,
174 'query-running' : _query_running
}
177 """ returns list of ops supported by this module """
178 return self
._run
_ops
.keys()
180 def _init_command_handlers(self
):
182 self
.ipcmd
= iproute2()
184 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None, **extra_args
):
185 """ run dhcp configuration on the interface object passed as argument
188 **ifaceobj** (object): iface object
190 **operation** (str): any of 'up', 'down', 'query-checkcurr',
194 **query_ifaceobj** (object): query check ifaceobject. This is only
195 valid when op is 'query-checkcurr'. It is an object same as
196 ifaceobj, but contains running attribute values and its config
197 status. The modules can use it to return queried running state
198 of interfaces. status is success if the running state is same
199 as user required state in ifaceobj. error otherwise.
201 op_handler
= self
._run
_ops
.get(operation
)
205 if (operation
!= 'query-running' and
206 (ifaceobj
.addr_method
!= 'dhcp' and
207 ifaceobj
.addr_method
!= 'dhcp6')):
211 if not self
.is_dhcp_allowed_on(ifaceobj
, syntax_check
=False):
213 self
._init
_command
_handlers
()
214 if operation
== 'query-checkcurr':
215 op_handler(self
, ifaceobj
, query_ifaceobj
)
217 op_handler(self
, ifaceobj
)