Ejemplo n.º 1
0
def remove_client_dhcp_config(client_id):
    '''
    If a local DHCP server is running, remove any client configuration for
    this client from its configuration. If not, inform end-user that the
    client-service binding should no longer be referenced in the DHCP
    configuration.
    '''
    server = dhcp.DHCPServer()
    if server.is_configured():
        # A local DHCP server is configured. Check for a host entry and remove
        # it if found.
        mac_address = client_id[2:]
        mac_address = AIdb.formatValue('mac', mac_address)
        if server.host_is_configured(mac_address):
            print cw(
                _("Removing host entry '%s' from local DHCP "
                  "configuration.") % mac_address)
            server.remove_host(mac_address)

            if server.is_online():
                try:
                    server.control('restart')
                except dhcp.DHCPServerError as err:
                    print >> sys.stderr, cw(
                        _("Unable to restart the DHCP "
                          "SMF service: %s" % err))
                    return
    else:
        # No local DHCP configuration, inform user that it needs to be
        # unconfigured elsewhere.
        print cw(
            _("No local DHCP configuration found. Unless it will be "
              "reused, the bootfile '%s' may be removed from the DHCP "
              "configuration\n" % client_id))
Ejemplo n.º 2
0
    def test_permissions(self):
        '''Test correct permissions of dhcpd4.conf'''

        dhcpsrv = dhcp.DHCPServer()
        dhcpsrv.add_arch_class('i386', 'some-test-string')
        # save original umask
        orig_umask = os.umask(0022)
        # set too restrictive and too open umask
        for mask in (0066, 0000):
            os.umask(mask)
            dhcpsrv.update_bootfile_for_arch('i386', 'some-other-test-string')
            mode = os.stat(self.dhcp_dir + '/' + 'dhcpd4.conf').st_mode
            self.assertEqual(mode, 0100644)
Ejemplo n.º 3
0
def remove_dhcp_configuration(service):
    '''
    Determines if a local DHCP server is running and if this service's bootfile
    is set as the architecture's default boot service. If it is, we'll unset it
    as we're deleting the service. If the DHCP configuration isn't local,
    inform the end-user that the DHCP configuration should not reference this
    bootfile any longer.
    '''
    server = dhcp.DHCPServer()
    if server.is_configured():
        # Server is configured. Regardless of it's current state, check for
        # this bootfile in the service's architecture class. If it is set as
        # the default for this architecture, unset it.
        try:
            arch_class = dhcp.DHCPArchClass.get_arch(server, service.arch)
        except dhcp.DHCPServerError as err:
            print >> sys.stderr, cw(_("\nUnable to access DHCP configuration: "
                                      "%s\n" % err))
            return

        # Skip SPARC services, since they share a global bootfile
        if (service.arch != 'sparc' and arch_class is not None and 
            arch_class.bootfile == service.dhcp_bootfile):
            try:
                print cw(_("Removing this service's bootfile from local DHCP "
                           "configuration\n"))
                arch_class.unset_bootfile()
            except dhcp.DHCPServerError as err:
                print >> sys.stderr, cw(_("\nUnable to unset this service's "
                                          "bootfile in the DHCP "
                                          "configuration: %s\n" % err))
                return

            if server.is_online():
                try:
                    server.control('restart')
                except dhcp.DHCPServerError as err:
                    print >> sys.stderr, cw(_("\nUnable to restart the DHCP "
                                              "SMF service: %s\n" % err))
Ejemplo n.º 4
0
def remove_dhcp_configuration(service):
    '''
    Determines if a local DHCP server is running and if this service's bootfile
    is set as the architecture's default boot service. If it is, we'll unset it
    as we're deleting the service. If the DHCP configuration isn't local,
    inform the end-user that the DHCP configuration should not reference this
    bootfile any longer.
    '''
    logging.debug("in remove_dhcp_configuration, service=%s", service.name)

    # Skip SPARC services, since they share a global bootfile
    if service.arch == 'sparc':
        return

    server = dhcp.DHCPServer()
    if server.is_configured():
        # Server is configured. Regardless of its current state, check for
        # this bootfile in the service's architecture class. If it is set as
        # the default for this architecture, unset it.
        try:
            arch_class = dhcp.DHCPArchClass.get_arch(server, service.arch)
        except dhcp.DHCPServerError as err:
            print >> sys.stderr, cw(
                _("\nUnable to access DHCP configuration: "
                  "%s\n" % err))
            return

        if arch_class is None or arch_class.bootfile is None:
            # nothing to do
            return

        logging.debug("arch_class.bootfile is %s", arch_class.bootfile)
        if isinstance(arch_class.bootfile, list):
            # The list consists of tuples: (archval, relpath to bootfile)
            # e.g., [('00:00', '<svcname>/boot/grub/pxegrub2'),..]
            # Using the first tuple, get the service name.
            relpath = arch_class.bootfile[0][1]
        else:
            relpath = arch_class.bootfile
        parts = relpath.partition('/')
        arch_svcname = parts[0]

        if arch_svcname == service.name:
            try:
                print cw(
                    _("Removing this service's bootfile(s) from local "
                      "DHCP configuration\n"))
                arch_class.unset_bootfile()
            except dhcp.DHCPServerError as err:
                print >> sys.stderr, cw(
                    _("\nUnable to unset this service's "
                      "bootfile(s) in the DHCP "
                      "configuration: %s\n" % err))
                return

            if server.is_online():
                try:
                    server.control('restart')
                except dhcp.DHCPServerError as err:
                    print >> sys.stderr, cw(
                        _("\nUnable to restart the DHCP "
                          "SMF service: %s\n" % err))
Ejemplo n.º 5
0
def setup_x86_client(service,
                     mac_address,
                     bootargs='',
                     suppress_dhcp_msgs=False):
    ''' Set up an x86 client

    Creates relative symlink(s) in /etc/netboot::
        <client_id>.<archtype> -> ./<svcname>/<bootfile_path>
        e.g., 01223344223344.bios -> ./mysvc/boot/grub/pxegrub
    Creates /etc/netboot/<cfg_file>.<client_id> boot configuration file
    Adds client info to AI_SERVICE_DIR_PATH/<svcname>/.config file

    Arguments:
              service - the AIService to associate with client
              mac_address - client MAC address (as formed by
                            MACAddress class, i.e., 'ABABABABABAB')
              bootargs = bootargs of client (x86)
              suppress_dhcp_msgs - if True, suppresses output of DHCP
                                   configuration messages
    Returns: Nothing

    '''
    # create a client-identifier (01 + MAC ADDRESS)
    client_id = "01" + mac_address
    clientinfo = dict()

    svcgrub = grubcfg(service.name,
                      path=service.image.path,
                      config_dir=service.config_dir)

    # Call setup_client - it will return netconfig_files, config_files,
    # and tuples, e.g.:
    # netconfig_files:  ['/etc/netboot/menu.lst.01234234234234']
    # config_files:  ['/etc/netboot/menu.conf.01234234234234']
    # boot_tuples:  [('00:00', 'bios', 'mysvc/boot/grub/pxegrub2'),
    #                ('00:07', 'uefi', 'mysvc/boot/grub/grub2netx64.efi')]
    # If the client specifies bootargs, use them. Otherwise, inherit
    # the bootargs specified in the service.
    netconfig_files, config_files, boot_tuples = \
        svcgrub.setup_client(mac_address, bootargs=bootargs,
                             service_bootargs=service.bootargs)

    # update the bootargs in the service .config file
    if bootargs:
        clientinfo[config.BOOTARGS] = bootargs

    # keep track of client files to delete when client is removed
    client_files = list(netconfig_files)
    client_files.extend(config_files)

    # create symlink(s) from the boot directory to the sevice's bootfile(s).
    # note these must be relative from the boot directory.
    for arch, archtype, relpath in boot_tuples:
        # name of symlink is /etc/netboot/<clientid>.<archtype>
        bootfile_symlink = _bootfile_path(client_id, archtype)
        dotpath = './' + relpath
        logging.debug('creating symlink %s->%s', bootfile_symlink, dotpath)
        os.symlink(dotpath, bootfile_symlink)
        client_files.append(bootfile_symlink)

        # if this is archtype bios, create <clientid> symlink to
        # <clientid>.bios for backward compatibility with existing dhcp
        # servers.
        if archtype == 'bios':
            clientid_path = os.path.join(com.BOOT_DIR, client_id)
            dot_client_arch = './' + client_id + '.' + archtype
            logging.debug('creating symlink %s->%s', clientid_path,
                          dot_client_arch)
            os.symlink(dot_client_arch, clientid_path)

    logging.debug('adding client_files to .config: %s', client_files)
    clientinfo[config.FILES] = client_files
    config.add_client_info(service.name, client_id, clientinfo)

    # Configure DHCP for this client if the configuration is local, otherwise
    # suggest the configuration addition. Note we only need to do this for
    # x86-based clients, not SPARC.
    server = dhcp.DHCPServer()
    if server.is_configured():
        # We'll need the actual hardware ethernet address for the DHCP entry,
        # rather than the non-delimited string that 'mac_address' is.
        full_mac = AIdb.formatValue('mac', mac_address)
        try:
            if not suppress_dhcp_msgs:
                print cw(
                    _("Adding host entry for %s to local DHCP "
                      "configuration.") % full_mac)
            server.add_option_arch()
            server.add_host(full_mac, boot_tuples)
        except dhcp.DHCPServerError as err:
            print cw(
                _("Unable to add host (%(mac)s) to DHCP "
                  "configuration: %(error)s") % {
                      'mac': full_mac,
                      'error': err
                  })
            return

        if server.is_online():
            try:
                server.control('restart')
            except dhcp.DHCPServerError as err:
                print >> sys.stderr, cw(
                    _("\nUnable to restart the DHCP SMF "
                      "service: %s\n" % err))
                return
        elif not suppress_dhcp_msgs:
            print cw(
                _("\nLocal DHCP configuration complete, but the DHCP "
                  "server SMF service is offline. To enable the "
                  "changes made, enable: %s.\nPlease see svcadm(1M) "
                  "for further information.\n") % dhcp.DHCP_SERVER_IPV4_SVC)
    else:
        # No local DHCP, tell the user all about their boot configuration
        valid_nets = list(com.get_valid_networks())
        if valid_nets:
            server_ip = valid_nets[0]

        if not suppress_dhcp_msgs:
            boofile_text = '\n'
            for archval, archtype, relpath in boot_tuples:
                bootfilename = client_id + '.' + archtype
                boofile_text = (boofile_text + '\t' + archtype +
                                ' clients (arch ' + archval + '):  ' +
                                bootfilename + '\n')
            print _(_PXE_CLIENT_DHCP_CONFIG % (server_ip, boofile_text))

            if len(valid_nets) > 1:
                print cw(
                    _("\nNote: determined more than one IP address "
                      "configured for use with AI. Please ensure the "
                      "above 'Boot server IP' is correct.\n"))
Ejemplo n.º 6
0
def setup_x86_client(service, mac_address, bootargs=''):
    ''' Set up an x86 client

    Creates a relative symlink from the <svcname>'s bootfile to
        /etc/netboot/<client_id>
    Creates /etc/netboot/menu.lst.<client_id> boot configuration file
    Adds client info to AI_SERVICE_DIR_PATH/<svcname>/.config file

    Arguments:
              image_path - directory path to AI image
              mac_address - client MAC address (as formed by
                            MACAddress class, i.e., 'ABABABABABAB')
              bootargs = bootargs of client (x86)
    Returns: Nothing

    '''
    # create a client-identifier (01 + MAC ADDRESS)
    client_id = "01" + mac_address

    menulst = os.path.join(service.config_dir, grub.MENULST)
    client_menulst = _menulst_path(client_id)

    # copy service's menu.lst file to menu.lst.<client_id>
    try:
        shutil.copy(menulst, client_menulst)
    except IOError as err:
        print >> sys.stderr, cw(
            _("Unable to copy grub menu.lst file: %s") % err.strerror)
        return

    # create a symlink from the boot directory to the sevice's bootfile.
    # note this must be relative from the boot directory.
    bootfile, pxegrub_path = _pxegrub_path(client_id)
    os.symlink("./" + service.dhcp_bootfile, pxegrub_path)

    clientinfo = {config.FILES: [client_menulst, pxegrub_path]}

    # if the client specifies bootargs, use them. Otherwise, inherit
    # the bootargs specified in the service (do nothing)
    if bootargs:
        grub.update_bootargs(client_menulst, service.bootargs, bootargs)
        clientinfo[config.BOOTARGS] = bootargs

    config.add_client_info(service.name, client_id, clientinfo)

    # Configure DHCP for this client if the configuration is local, otherwise
    # suggest the configuration addition. Note we only need to do this for
    # x86-based clients, not SPARC.
    server = dhcp.DHCPServer()
    if server.is_configured():
        # We'll need the actual hardware ethernet address for the DHCP entry,
        # rather than the non-delimited string that 'mac_address' is.
        full_mac = AIdb.formatValue('mac', mac_address)
        try:
            print cw(
                _("Adding host entry for %s to local DHCP configuration.") %
                full_mac)
            server.add_host(full_mac, bootfile)
        except dhcp.DHCPServerError as err:
            print cw(
                _("Unable to add host (%s) to DHCP configuration: %s") %
                (full_mac, err))
            return

        if server.is_online():
            try:
                server.control('restart')
            except dhcp.DHCPServerError as err:
                print >> sys.stderr, cw(
                    _("\nUnable to restart the DHCP SMF "
                      "service: %s\n" % err))
                return
        else:
            print cw(
                _("\nLocal DHCP configuration complete, but the DHCP "
                  "server SMF service is offline. To enable the "
                  "changes made, enable: %s.\nPlease see svcadm(1M) "
                  "for further information.\n") % dhcp.DHCP_SERVER_IPV4_SVC)
    else:
        # No local DHCP, tell the user all about their boot configuration
        valid_nets = list(com.get_valid_networks())
        if valid_nets:
            server_ip = valid_nets[0]

        print _(_PXE_CLIENT_DHCP_CONFIG % (server_ip, bootfile))

        if len(valid_nets) > 1:
            print cw(
                _("\nNote: determined more than one IP address "
                  "configured for use with AI. Please ensure the above "
                  "'Boot server IP' is correct.\n"))