Home | History | Annotate | Download | only in cros
      1 # Copyright 2015 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """
      6 Encapsulate functionality of the dhcpd Daemon. Support writing out a
      7 configuration file as well as starting and stopping the service.
      8 """
      9 
     10 import os
     11 import signal
     12 
     13 from autotest_lib.client.common_lib import error
     14 from autotest_lib.client.common_lib import utils
     15 
     16 # Filenames used for execution.
     17 DHCPV6_SERVER_EXECUTABLE = '/usr/local/sbin/dhcpd'
     18 DHCPV6_SERVER_CONFIG_FILE = '/tmp/dhcpv6_test.conf'
     19 DHCPV6_SERVER_PID_FILE = '/tmp/dhcpv6_test.pid'
     20 
     21 DHCPV6_SERVER_ADDRESS = '2001:db8:0:1::1'
     22 DHCPV6_SERVER_SUBNET_PREFIX = '2001:db8:0:1::'
     23 DHCPV6_SERVER_SUBNET_PREFIX_LENGTH = 64
     24 DHCPV6_ADDRESS_RANGE_LOW = 0x100
     25 DHCPV6_ADDRESS_RANGE_HIGH = 0x1ff
     26 DHCPV6_PREFIX_DELEGATION_INDEX_LOW = 0x1
     27 DHCPV6_PREFIX_DELEGATION_INDEX_HIGH = 0xf
     28 DHCPV6_PREFIX_DELEGATION_RANGE_FORMAT = '2001:db8:0:%x00::'
     29 DHCPV6_PREFIX_DELEGATION_RANGE_LOW = (DHCPV6_PREFIX_DELEGATION_RANGE_FORMAT %
     30                                       (DHCPV6_PREFIX_DELEGATION_INDEX_LOW))
     31 DHCPV6_PREFIX_DELEGATION_RANGE_HIGH = (DHCPV6_PREFIX_DELEGATION_RANGE_FORMAT %
     32                                        (DHCPV6_PREFIX_DELEGATION_INDEX_HIGH))
     33 DHCPV6_PREFIX_DELEGATION_PREFIX_LENGTH = 56
     34 DHCPV6_DEFAULT_LEASE_TIME = 600
     35 DHCPV6_MAX_LEASE_TIME = 7200
     36 DHCPV6_NAME_SERVERS = 'fec0:0:0:1::1'
     37 DHCPV6_DOMAIN_SEARCH = 'domain.example'
     38 
     39 CONFIG_DEFAULT_LEASE_TIME = 'default_lease_time'
     40 CONFIG_MAX_LEASE_TIME = 'max_lease_time'
     41 CONFIG_SUBNET = 'subnet'
     42 CONFIG_RANGE = 'range'
     43 CONFIG_NAME_SERVERS = 'name_servers'
     44 CONFIG_DOMAIN_SEARCH = 'domain_search'
     45 CONFIG_PREFIX_RANGE = 'prefix_range'
     46 
     47 class Dhcpv6TestServer(object):
     48     """
     49     This is an embodiment of the DHCPv6 server (dhcpd) process.  It converts an
     50     config dict into parameters for the dhcpd configuration file and
     51     manages startup and cleanup of the process.
     52     """
     53 
     54     def __init__(self, interface = None):
     55         if not os.path.exists(DHCPV6_SERVER_EXECUTABLE):
     56             raise error.TestNAError('Could not find executable %s; '
     57                                     'this is likely an old version of '
     58                                     'ChromiumOS' %
     59                                     DHCPV6_SERVER_EXECUTABLE)
     60         self._interface = interface
     61         # "2001:db8:0:1::/64"
     62         subnet = '%s/%d' % (DHCPV6_SERVER_SUBNET_PREFIX,
     63                             DHCPV6_SERVER_SUBNET_PREFIX_LENGTH)
     64         # "2001:db8:0:1::100 2001:db8:1::1ff"
     65         range = '%s%x %s%x' % (DHCPV6_SERVER_SUBNET_PREFIX,
     66                                DHCPV6_ADDRESS_RANGE_LOW,
     67                                DHCPV6_SERVER_SUBNET_PREFIX,
     68                                DHCPV6_ADDRESS_RANGE_HIGH)
     69         # "2001:db8:0:100:: 2001:db8:1:f00:: /56"
     70         prefix_range = '%s %s /%d' % (DHCPV6_PREFIX_DELEGATION_RANGE_LOW,
     71                                       DHCPV6_PREFIX_DELEGATION_RANGE_HIGH,
     72                                       DHCPV6_PREFIX_DELEGATION_PREFIX_LENGTH)
     73         self._config = {
     74             CONFIG_DEFAULT_LEASE_TIME: DHCPV6_DEFAULT_LEASE_TIME,
     75             CONFIG_MAX_LEASE_TIME: DHCPV6_MAX_LEASE_TIME,
     76             CONFIG_SUBNET: subnet,
     77             CONFIG_RANGE: range,
     78             CONFIG_NAME_SERVERS: DHCPV6_NAME_SERVERS,
     79             CONFIG_DOMAIN_SEARCH: DHCPV6_DOMAIN_SEARCH,
     80             CONFIG_PREFIX_RANGE: prefix_range
     81         }
     82 
     83 
     84     def _write_config_file(self):
     85         """
     86         Write out a configuration file for DHCPv6 server to use.
     87         """
     88         config = '\n'.join([
     89                      'default-lease-time %(default_lease_time)d;',
     90                      'max-lease-time %(max_lease_time)d;',
     91                      'subnet6 %(subnet)s {',
     92                      '  range6 %(range)s;',
     93                      '  option dhcp6.name-servers %(name_servers)s;',
     94                      '  option dhcp6.domain-search \"%(domain_search)s\";',
     95                      '  prefix6 %(prefix_range)s;',
     96                      '}'
     97                      '']) % self._config
     98         with open(DHCPV6_SERVER_CONFIG_FILE, 'w') as f:
     99             f.write(config)
    100 
    101 
    102     def _cleanup(self):
    103         """
    104         Cleanup temporary files.  If PID file exists, also kill the
    105         associated process.
    106         """
    107         if os.path.exists(DHCPV6_SERVER_PID_FILE):
    108             pid = int(file(DHCPV6_SERVER_PID_FILE).read())
    109             os.remove(DHCPV6_SERVER_PID_FILE)
    110             try:
    111                 os.kill(pid, signal.SIGTERM)
    112             except OSError:
    113                 pass
    114         if os.path.exists(DHCPV6_SERVER_CONFIG_FILE):
    115             os.remove(DHCPV6_SERVER_CONFIG_FILE)
    116 
    117 
    118     def start(self):
    119         """
    120         Start the DHCPv6 server.  The server will daemonize itself and
    121         run in the background.
    122         """
    123         self._cleanup()
    124         self._write_config_file()
    125         utils.system('%s -6 -pf %s -cf %s %s' %
    126                      (DHCPV6_SERVER_EXECUTABLE,
    127                       DHCPV6_SERVER_PID_FILE,
    128                       DHCPV6_SERVER_CONFIG_FILE,
    129                       self._interface))
    130 
    131 
    132     def stop(self):
    133         """
    134         Halt the DHCPv6 server.
    135         """
    136         self._cleanup()
    137