mirror of
https://github.com/CumulusNetworks/ifupdown2.git
synced 2024-05-06 15:54:50 +00:00
Ticket: None
Reviewed By: CCR-4058
Testing Done: ifup'd interface with both dhcp-wait: "no" and dhcp-wait: "yes"
and not specified at all.
A previous patch implemented the nowait option for DHCP. This patch changes the
name of the option to "dhcp-wait" and makes the default, if nothing is specified
in the policy files, to be "yes", which means dhclient will be called without
the "-nw" option, causing it to wait for up to a minute for a response from the
DHCP server before continuing.
The format of the JSON in the policy file for this option was also changed so
that it conforms to the other ifupdown2 policy options. This format is now:
{
"dhcp": {
"defaults": { "dhcp-wait": "no" }
}
}
Also, the documented argument values are "yes" and "no". Any other values, will
be interpreted as "yes".
A subsequent patch in cl-basefiles will be made to include this fragment in
/var/lib/ifupdown2/policy.d/dhcp.json so that Cumulus Linux will default to
not waiting for DHCP to complete.
140 lines
5.5 KiB
Python
140 lines
5.5 KiB
Python
#!/usr/bin/python
|
|
#
|
|
# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
|
|
# Author: Roopa Prabhu, roopa@cumulusnetworks.com
|
|
#
|
|
|
|
try:
|
|
from ipaddr import IPNetwork
|
|
from sets import Set
|
|
from ifupdown.iface import *
|
|
import ifupdown.policymanager as policymanager
|
|
from ifupdownaddons.modulebase import moduleBase
|
|
from ifupdownaddons.dhclient import dhclient
|
|
from ifupdownaddons.iproute2 import iproute2
|
|
except ImportError, e:
|
|
raise ImportError (str(e) + "- required module not found")
|
|
|
|
class dhcp(moduleBase):
|
|
""" ifupdown2 addon module to configure dhcp on interface """
|
|
|
|
def __init__(self, *args, **kargs):
|
|
moduleBase.__init__(self, *args, **kargs)
|
|
self.dhclientcmd = dhclient(**kargs)
|
|
self.ipcmd = None
|
|
|
|
def _up(self, ifaceobj):
|
|
# if dhclient is already running do not stop and start it
|
|
if self.dhclientcmd.is_running(ifaceobj.name) or \
|
|
self.dhclientcmd.is_running6(ifaceobj.name):
|
|
self.logger.info('dhclient already running on %s. Not restarting.' % \
|
|
ifaceobj.name)
|
|
return
|
|
try:
|
|
dhcp_wait = policymanager.policymanager_api.get_attr_default(
|
|
module_name=self.__class__.__name__, attr='dhcp-wait')
|
|
wait = not str(dhcp_wait).lower() == "no"
|
|
if ifaceobj.addr_family == 'inet':
|
|
# First release any existing dhclient processes
|
|
try:
|
|
if not self.PERFMODE:
|
|
self.dhclientcmd.stop(ifaceobj.name)
|
|
except:
|
|
pass
|
|
self.dhclientcmd.start(ifaceobj.name, wait=wait)
|
|
elif ifaceobj.addr_family == 'inet6':
|
|
accept_ra = ifaceobj.get_attr_value_first('accept_ra')
|
|
if accept_ra:
|
|
# XXX: Validate value
|
|
self.sysctl_set('net.ipv6.conf.%s' %ifaceobj.name +
|
|
'.accept_ra', accept_ra)
|
|
autoconf = ifaceobj.get_attr_value_first('autoconf')
|
|
if autoconf:
|
|
# XXX: Validate value
|
|
self.sysctl_set('net.ipv6.conf.%s' %ifaceobj.name +
|
|
'.autoconf', autoconf)
|
|
try:
|
|
self.dhclientcmd.stop6(ifaceobj.name)
|
|
except:
|
|
pass
|
|
self.dhclientcmd.start6(ifaceobj.name, wait=wait)
|
|
except Exception, e:
|
|
self.log_error(str(e))
|
|
|
|
def _down(self, ifaceobj):
|
|
self.dhclientcmd.release(ifaceobj.name)
|
|
self.ipcmd.link_down(ifaceobj.name)
|
|
|
|
def _query_check(self, ifaceobj, ifaceobjcurr):
|
|
if self.dhclientcmd.is_running(ifaceobjcurr.name):
|
|
ifaceobjcurr.addr_family = 'inet'
|
|
if ifaceobj.addr_family != 'inet':
|
|
ifaceobjcurr.status = ifaceStatus.ERROR
|
|
ifaceobjcurr.addr_method = 'dhcp'
|
|
ifaceobjcurr.status = ifaceStatus.SUCCESS
|
|
elif self.dhclientcmd.is_running6(ifaceobjcurr.name):
|
|
ifaceobjcurr.addr_family = 'inet6'
|
|
if ifaceobj.addr_family != 'inet6':
|
|
ifaceobjcurr.status = ifaceStatus.ERROR
|
|
ifaceobjcurr.addr_method = 'dhcp'
|
|
ifaceobjcurr.status = ifaceStatus.SUCCESS
|
|
else:
|
|
ifaceobjcurr.addr_family = None
|
|
ifaceobjcurr.status = ifaceStatus.ERROR
|
|
|
|
def _query_running(self, ifaceobjrunning):
|
|
if not self.ipcmd.link_exists(ifaceobjrunning.name):
|
|
return
|
|
if self.dhclientcmd.is_running(ifaceobjrunning.name):
|
|
ifaceobjrunning.addr_family = 'inet'
|
|
ifaceobjrunning.addr_method = 'dhcp'
|
|
elif self.dhclientcmd.is_running6(ifaceobjrunning.name):
|
|
ifaceobjrunning.addr_family = 'inet6'
|
|
ifaceobjrunning.addr_method = 'dhcp6'
|
|
|
|
_run_ops = {'up' : _up,
|
|
'down' : _down,
|
|
'query-checkcurr' : _query_check,
|
|
'query-running' : _query_running }
|
|
|
|
def get_ops(self):
|
|
""" returns list of ops supported by this module """
|
|
return self._run_ops.keys()
|
|
|
|
def _init_command_handlers(self):
|
|
if not self.ipcmd:
|
|
self.ipcmd = iproute2(**self.get_flags())
|
|
|
|
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
|
""" run dhcp configuration on the interface object passed as argument
|
|
|
|
Args:
|
|
**ifaceobj** (object): iface object
|
|
|
|
**operation** (str): any of 'up', 'down', 'query-checkcurr',
|
|
'query-running'
|
|
|
|
Kwargs:
|
|
**query_ifaceobj** (object): query check ifaceobject. This is only
|
|
valid when op is 'query-checkcurr'. It is an object same as
|
|
ifaceobj, but contains running attribute values and its config
|
|
status. The modules can use it to return queried running state
|
|
of interfaces. status is success if the running state is same
|
|
as user required state in ifaceobj. error otherwise.
|
|
"""
|
|
op_handler = self._run_ops.get(operation)
|
|
if not op_handler:
|
|
return
|
|
try:
|
|
if (operation != 'query-running' and
|
|
(ifaceobj.addr_method != 'dhcp' and
|
|
ifaceobj.addr_method != 'dhcp6')):
|
|
return
|
|
except:
|
|
return
|
|
self._init_command_handlers()
|
|
if operation == 'query-checkcurr':
|
|
op_handler(self, ifaceobj, query_ifaceobj)
|
|
else:
|
|
op_handler(self, ifaceobj)
|