Back to the main page
DHCP reservation for Linux, Solaris, AK
Intro
This is bigger reservation then this page .
The design is almost same, the bigger tool supports Linux and Solaris 10, 11 and AK (basically Solaris for ZFS appliance),
and should support more sites, hence there is site dedicated configuration file to specify
Cobbler and Jumpstart/AI (Automated Installer) server for that specific site.
Design
- There is the module (in ./lib) to create DHCP cfg file for a system (ex. Cobbler client or Solaris).
Class COBBLER_SYSTEM is blueprint for Linux file, its instance has attributes: location, hostname, MAC, IP, router, boot file.
Class S11_SYSTEM is for Solaris 11, its instance has attributes: location, hostname, MAC, IP.
Class S10_SYSTEM_X86 is for Solaris 10 x86, its instance has attributes: location, hostname, MAC, IP.
Class AK_SYSTEM is for AK, its instance has attributes: location, hostname, MAC, IP.
Methods for object (class instance) are: create, read and delete cfg file.
There is some test, after if __name__ == '__main__' , to be used if you run module directly.
- There is ASCII file, list of supported subnets.
- There is configuration file per site
- There is main python script, called by user or another tool. The help reads mandatory and optional arguments.
Implementation
- The module to create cgf file is lib/dhcp_cfg.py, hence lib directory is place for modules.
There is the empty file lib/__init__.py so Python knows to treat this directory as having modules (packages).
- Since will be more locations, let's have symbolic link that doesn't have location in its name. Like:
ls -la /usr/bin/ca-dhcp-reserve.py
lrwxrwxrwx 1 root root 44 Mar 11 10:12 /usr/bin/ca-dhcp-reserve.py -> /etc/dhcp/dhcp-tools/sca/dhcp-sca-reserve.py
Files
List of supported subnets (location: sca)
File sca-subnets.txt reads something like:
20.162.48.0/24
20.162.49.0/24
...shortened ...
20.169.131.0/24
Site config file (location: sca)
File sca.cfg reads something like:
# This is config file for SCA DHCP reservation
COBBLER_SERVER = 'ca-cobbler-sca.domain.com' # next-server for OL/OVS/Linux
CAINSTALL_SERVER = 'ca-install-sca.domain.com' # install server for Sol/AK
Module lib/dhcp_cfg.py
" Module to create DHCP config file for Cobbler and ca-install clients"
# The module name is .py
# When import, use only : ex.
# import
# Use sys.path.append("/path/to/module") if needed
# ------------------------------------------------------
import os
import socket
import sys
import re
global DHCPCFGDIR
DHCPCFGDIR = "/etc/dhcp/clients/"
# --------------------------
# Cobbler system
# --------------------------
class COBBLER_SYSTEM(object):
"""
Blueprint for DHCP Cobbler system's config file
Attributes:
1. loc (string, location is hardcoded in script that imports this module)
2. hostname (string, user input)
3. mac (string, user input)
4. ip (string, calculated)
5. router (string, calculated)
6. bootfile (string, user input): default is None object
"""
def __init__(self, loc, hostname, mac, ip, router, bootfile=None):
"""
Initialize object whos attributes are collection of data
used to create DHCP config file for Cobbler client
"""
self.loc = loc
self.hostname = hostname
self.mac = mac
self.ip = ip
self.router = router
self.bootfile = bootfile
global CFG_COBBLER_SYSTEM
CFG_COBBLER_SYSTEM = DHCPCFGDIR + self.hostname
# Get values from config file, each loc has its own dir/cfg file
# parent directory is os.path.join(sys.path[0], os.pardir)
LOCATION_CFGFILE = (os.path.join(sys.path[0], os.pardir) + "/" + self.loc + "/" + self.loc + ".cfg")
try:
execfile(LOCATION_CFGFILE, globals())
except IOError as err:
sys.exit("IOError: {0}".format(err))
global cobbler_server_ip
cobbler_server_ip=socket.gethostbyname(COBBLER_SERVER) # IP of Cobbler server
# ---------------------------------------------------------------
# this is of you want to manipulate filename attribute of an object
# ---------------------------------------------------------------
@property
def bootfile(self):
""" Get 'bootfile' property/value """
return self._bootfile
@bootfile.setter
def bootfile(self, value):
""" Set value to 'bootfile' """
self._bootfile = value
@bootfile.deleter
def bootfile(self):
""" Delete 'bootfile' """
del self._bootfile
# ---------------------------------------------------------------
def create_cfg_file(self):
""" Creates config file """
print ("DHCP reservation has been created: " + CFG_COBBLER_SYSTEM)
try:
if self.bootfile != None:
f = open(CFG_COBBLER_SYSTEM, "w+")
f.write("host " + self.hostname + " {\n")
f.write("\thardware ethernet " + self.mac + " ;\n")
f.write("\tfixed-address " + self.ip + " ;\n")
f.write("\toption routers " + self.router + " ;\n")
f.write("\tnext-server " + cobbler_server_ip + " ;\n")
f.write("\tfilename " + "\"" + str(self.bootfile) + "\"" + " ;\n")
f.write("\t }\n")
f.close()
else:
f = open(CFG_COBBLER_SYSTEM, "w+")
f.write("host " + self.hostname + " {\n")
f.write("\thardware ethernet " + self.mac + " ;\n")
f.write("\tfixed-address " + self.ip + " ;\n")
f.write("\toption routers " + self.router + " ;\n")
f.write("\tnext-server " + cobbler_server_ip + " ;\n")
f.write("\t }\n")
f.close()
except IOError as err:
print("IOError: {0}".format(err))
def remove_cfg_file(self):
""" Removes config file """
try:
os.remove(CFG_COBBLER_SYSTEM)
print ("File " + CFG_COBBLER_SYSTEM + " is removed!")
except IOError as err:
print("IOError: {0}".format(err))
def read_cfg_file(self):
""" Prints config file """
print ("Reading file " + CFG_COBBLER_SYSTEM)
try:
f = open(CFG_COBBLER_SYSTEM, "r")
print f.read()
f.close()
except IOError as err:
print("IOError: {0}".format(err))
# --------------------------
# Solaris 11 system
# --------------------------
class S11_SYSTEM(object):
"""
Blueprint for Solaris 11 client's DHCP config file
Attributes:
1. loc (string, location is hardcoded in script that imports this module)
2. hostname (string, user input)
3. mac (string, user input)
4. ip (string, calculated)
"""
def __init__(self, loc, hostname, mac, ip):
"""
Initialize object whos attributes are collection of data
used to create DHCP config file for ca-install client
"""
self.loc = loc
self.hostname = hostname
self.mac = mac
self.ip = ip
global CFG_S11_SYSTEM
CFG_S11_SYSTEM = DHCPCFGDIR + self.hostname
# Get values from config file, each loc has its own dir/cfg file
# parent directory is os.path.join(sys.path[0], os.pardir)
LOCATION_CFGFILE = (os.path.join(sys.path[0], os.pardir) + "/" + self.loc + "/" + self.loc + ".cfg")
try:
execfile(LOCATION_CFGFILE, globals())
except IOError as err:
sys.exit("IOError: {0}".format(err))
global cainstall_ip
cainstall_ip=socket.gethostbyname(CAINSTALL_SERVER) # IP of ca-install server
def create_cfg_file(self):
""" Creates config file """
print ("DHCP reservation has been created: " + CFG_S11_SYSTEM)
client_id = "01" + re.sub(":","",self.mac).upper()
try:
f = open(CFG_S11_SYSTEM, "w+")
f.write("host " + self.hostname + " { \n")
f.write("\thardware ethernet " + self.mac + " ;\n")
f.write("\tfixed-address " + self.ip + " ;\n")
f.write("\tnext-server " + cainstall_ip + " ;\n")
f.write("\tif option arch = 00:00 { \n")
f.write("\t\tfilename \"" + client_id + ".bios" + "\";\n")
f.write("\t} else if option arch = 00:07 { \n")
f.write("\t\tfilename \"" + client_id + ".uefi" + "\";\n")
f.write("\t} else { \n")
f.write("\t\tfilename \"http://" + cainstall_ip + ":5555/cgi-bin/wanboot-cgi\" ;\n")
f.write("\t\t }\n")
f.write("\t }\n")
f.close()
except IOError as err:
print("IOError: {0}".format(err))
def remove_cfg_file(self):
""" Removes config file """
try:
os.remove(CFG_S11_SYSTEM)
print ("File " + CFG_S11_SYSTEM + " is removed!")
except IOError as err:
print("IOError: {0}".format(err))
def read_cfg_file(self):
""" Prints config file """
print ("Reading file " + CFG_S11_SYSTEM)
try:
f = open(CFG_S11_SYSTEM, "r")
print f.read()
f.close()
except IOError as err:
print("IOError: {0}".format(err))
# -----------------------------
# Solaris 10 system x84
# -----------------------------
class S10_SYSTEM_X86(object):
"""
Blueprint for Solaris 10 x86 client's DHCP config file
Attributes:
1. loc (string, location is hardcoded in script that imports this module)
2. hostname (string, user input)
3. mac (string, user input)
4. ip (string, calculated)
"""
def __init__(self, loc, hostname, mac, ip):
"""
Initialize object whos attributes are collection of data
used to create DHCP config file for ca-install client
"""
self.loc = loc
self.hostname = hostname
self.mac = mac
self.ip = ip
global CFG_S10_SYSTEM_X86
CFG_S10_SYSTEM_X86 = DHCPCFGDIR + self.hostname
# Get values from config file, each loc has its own dir/cfg file
# parent directory is os.path.join(sys.path[0], os.pardir)
LOCATION_CFGFILE = (os.path.join(sys.path[0], os.pardir) + "/" + self.loc + "/" + self.loc + ".cfg")
try:
execfile(LOCATION_CFGFILE, globals())
except IOError as err:
sys.exit("IOError: {0}".format(err))
global cainstall_ip
cainstall_ip=socket.gethostbyname(CAINSTALL_SERVER) # IP of ca-install server
def create_cfg_file(self):
""" Creates config file """
print ("DHCP reservation has been created: " + CFG_S10_SYSTEM_X86)
client_id = "01" + re.sub(":","",self.mac).upper()
try:
f = open(CFG_S10_SYSTEM_X86, "w+")
f.write("host " + self.hostname + " { \n")
f.write("\thardware ethernet " + self.mac + " ;\n")
f.write("\tfixed-address " + self.ip + " ;\n")
f.write("\tfilename \"" + client_id + "\" ;\n")
f.write("\tnext-server " + cainstall_ip + " ;\n")
f.write("\t }\n")
f.close()
except IOError as err:
print("IOError: {0}".format(err))
def remove_cfg_file(self):
""" Removes config file """
try:
os.remove(CFG_S10_SYSTEM_X86)
print ("File " + CFG_S10_SYSTEM_X86 + " is removed!")
except IOError as err:
print("IOError: {0}".format(err))
def read_cfg_file(self):
""" Prints config file """
print ("Reading file " + CFG_S10_SYSTEM_X86)
try:
f = open(CFG_S10_SYSTEM_X86, "r")
print f.read()
f.close()
except IOError as err:
print("IOError: {0}".format(err))
# ---------------
# AK system
# ---------------
class AK_SYSTEM(object):
"""
Blueprint for AK client's DHCP config file
Attributes:
1. loc (string, location is hardcoded in script that imports this module)
2. hostname (string, user input)
3. mac (string, user input)
4. ip (string, calculated)
"""
def __init__(self, loc, hostname, mac, ip):
"""
Initialize object whos attributes are collection of data
used to create DHCP config file for ca-install client
"""
self.loc = loc
self.hostname = hostname
self.mac = mac
self.ip = ip
global CFG_AK_SYSTEM
CFG_AK_SYSTEM = DHCPCFGDIR + self.hostname
# Get values from config file, each loc has its own dir/cfg file
# parent directory is os.path.join(sys.path[0], os.pardir)
LOCATION_CFGFILE = (os.path.join(sys.path[0], os.pardir) + "/" + self.loc + "/" + self.loc + ".cfg")
try:
execfile(LOCATION_CFGFILE, globals())
except IOError as err:
sys.exit("IOError: {0}".format(err))
global cainstall_ip
cainstall_ip=socket.gethostbyname(CAINSTALL_SERVER) # IP of ca-install server
def create_cfg_file(self):
""" Creates config file """
print ("DHCP reservation has been created: " + CFG_AK_SYSTEM)
client_id = "01" + re.sub(":","",self.mac).upper()
try:
f = open(CFG_AK_SYSTEM, "w+")
f.write("host " + self.hostname + " { \n")
f.write("\thardware ethernet " + self.mac + " ;\n")
f.write("\tfixed-address " + self.ip + " ;\n")
f.write("\tnext-server " + cainstall_ip + " ;\n")
f.write("\tif option arch = 00:00 { \n")
f.write("\t\tfilename \"" + client_id + ".bios" + "\";\n")
f.write("\t} else if option arch = 00:07 { \n")
f.write("\t\tfilename \"" + client_id + ".uefi" + "\";\n")
f.write("\t} else { \n")
f.write("\t\tfilename \"http://" + cainstall_ip + ":5555/cgi-bin/wanboot-cgi\" ;\n")
f.write("\t\t#option SUNW.SsysidCF \"http://" + cainstall_ip + ":5555/solaris/ak\" ;\n")
f.write("\t\t }\n")
f.write("\t }\n")
f.close()
except IOError as err:
print("IOError: {0}".format(err))
def remove_cfg_file(self):
""" Removes config file """
try:
os.remove(CFG_AK_SYSTEM)
print ("File " + CFG_AK_SYSTEM + " is removed!")
except IOError as err:
print("IOError: {0}".format(err))
def read_cfg_file(self):
""" Prints config file """
print ("Reading file " + CFG_AK_SYSTEM)
try:
f = open(CFG_AK_SYSTEM, "r")
print f.read()
f.close()
except IOError as err:
print("IOError: {0}".format(err))
if __name__ == '__main__':
# Cobbler client test, only when module is run directly !
print COBBLER_SYSTEM.__doc__
ca_zdudic = COBBLER_SYSTEM("sca", "ca-zdudic1.domain.com",
"10:2:30:4:5:61", "10.211.22.33", "10.211.0.1", "/path/boot/me/file")
#ca_zdudic = COBBLER_SYSTEM("sca", "ca-zdudic2.domain.com", "1:21:3:41:5:6", "10.211.22.33", "10.211.0.1")
print "hostname is " + ca_zdudic.hostname
print "mac is " + ca_zdudic.mac
print "boot file is " + str(ca_zdudic.bootfile)
ca_zdudic.create_cfg_file()
ca_zdudic.read_cfg_file()
ca_zdudic.remove_cfg_file()
# Sol 11 client test
print S11_SYSTEM.__doc__
ca_zdudic2 = S11_SYSTEM("sca", "ca-zdudic2.domain.com", "00:ab:cd:ef:22:33", "10.211.11.66")
print "hostname is " + ca_zdudic2.hostname
print "mac is " + ca_zdudic2.mac
ca_zdudic2.create_cfg_file()
ca_zdudic2.read_cfg_file()
ca_zdudic2.remove_cfg_file()
# Sol 10 client test
print S10_SYSTEM_X86.__doc__
ca_zdudic1 = S10_SYSTEM_X86("sca", "ca-zdudic1.domain.com", "00:ab:cd:ef:22:33", "10.147.24.49")
ca_zdudic1.create_cfg_file()
ca_zdudic1.read_cfg_file()
ca_zdudic1.remove_cfg_file()
Main script sca/dhcp-sca-reserve.py (location: sca)
Note: see variable "LOC"
#!/usr/bin/env python
# SCA DHCP reservation
# ----------------------
import os
import sys
import getpass
import socket
import netaddr
import argparse
import ldap
import pwd # getting real user
import subprocess
from time import gmtime, strftime
import datetime
import logging, logging.handlers
sys.path.append(os.path.abspath(os.path.join(sys.path[0], os.pardir))) # append parent dir
import lib.dhcp_cfg as dhcp_cfg # import LabOps module for DHCP cfg files creation
# --- LOCATION is uniq ----
LOC = "sca"
# -------------------------
i_am=getpass.getuser()
if i_am != "root":
sys.exit(i_am + ", please run this via sudo (otherwise you won't have permissions to complete reservation)")
# even root must use sudo
try:
realuser = pwd.getpwuid(int(os.getenv('SUDO_UID'))).pw_name
realuserid = os.getenv('SUDO_UID')
except:
#SUDO_UID is missing
sys.exit("Even root is requested to use sudo, please re-run it with sudo.")
# define logging directory structure
PROGRAM = os.path.basename(sys.argv[0]) # name of this script
LOG_PATH = ("/var/log/" + PROGRAM) # put together "/var/log/"
if not os.path.exists(LOG_PATH): # create LOG_PATH if doesn't exists
os.makedirs(LOG_PATH)
os.chown(LOG_PATH,-1,580) # root(-1 means no change):crm for DSEE client
os.chmod(LOG_PATH,0775) # drwxrwxr-x
def verify_mac(hwaddr):
"""
To be used as type for MAC argument
"""
if not netaddr.valid_mac(hwaddr):
sys.exit("ERROR: %s is not valid MAC" % hwaddr)
return hwaddr
def verify_owner(username):
"""
Check if this is valid DSEE username
https://www.python-ldap.org/en/python-ldap-3.2.0/reference/ldap.html
Search filers can be:
email address: searchFilter = "mail=mickey.mouse@oracle.com"
login: searchFilter = "uid=mmouse"
UID: searchFilter = "uidNumber=123456789"
"""
DSEE_SRV="dsee-ldap-server.domain.com" # DSEE server
baseDN = "dc=domain,dc=com"
searchScope = ldap.SCOPE_SUBTREE # subtree search
retrieveAttributes = None
# create ldap object
try:
ldapobject = ldap.initialize('ldap://' + DSEE_SRV)
ldapobject.protocol_version = ldap.VERSION3
except ldap.LDAPError as err:
sys.exit("ldap.LDAPError: {0}".format(err))
try:
searchFilter = "uid=" + username
l_search = ldapobject.search(baseDN, searchScope, searchFilter, retrieveAttributes)
result_status, result_data = ldapobject.result(l_search, 0)
if not result_data:
sys.exit("ERROR: there is no " + username + " in DSEE" )
else:
return username
except ldap.LDAPError as err:
sys.exit("ldap.LDAPError: {0}".format(err))
# -- argument work
parser = argparse.ArgumentParser(
description="Add DHCP cfg file for a system (location: " + LOC + " )",
epilog='Brought to you by LabOps')
os = parser.add_mutually_exclusive_group(required=True)
os.add_argument("-l", "--linux", help="Linux install via Cobbler", action="store_true") # store_true for flag, no value
os.add_argument("-i", "--solaris11", help="Solaris 11 install", action="store_true")
os.add_argument("-j", "--solaris10", help="Solaris 10 x86 install (SPARC is not supported)", action="store_true")
os.add_argument("-z", "--ak", help="AK install", action="store_true")
parser.add_argument("-s", "--system", help="System's FQDN", required=True)
parser.add_argument("-m", "--mac", help="System's MAC ( : as delimiter)", type=verify_mac, required=True)
parser.add_argument("-b", "--bootfile", help="Custom boot file, only linux install (it must be in :/tftpboot)")
parser.add_argument("-o", "--owner", help=argparse.SUPPRESS, type=verify_owner) # hidden option
args = parser.parse_args()
system=args.system
mac=args.mac
linuxinstall=args.linux
s11install=args.solaris11
s10install=args.solaris10
akinstall=args.ak
# --- Define logging
LOG_FILE = (LOG_PATH + "/" + system + "_" + datetime.datetime.now().strftime("%m-%d-%Y_%Hh%Mm%Ss"))
# create logger (interface that script uses for logging)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# create file handler (define log destination)
handler = logging.handlers.TimedRotatingFileHandler(LOG_FILE, when='MIDNIGHT', backupCount=50, utc=False)
# create formatter (define layout of logs)
formatter = logging.Formatter('%(asctime)s:%(levelname)s: %(message)s')
handler.setFormatter(formatter)
# add handler to logger
logger.addHandler(handler)
# start logging
logger.debug("")
logger.debug("START AT : " + strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
logger.debug("Location for a config file: " + LOC)
SUBNETFILE = (sys.path[0] + "/" + LOC + "-subnets.txt") # location subnet file, in same dir as running script
logger.debug("Subnet list is from the file " + SUBNETFILE)
def not_whq_pls():
"""
Check that script is not used on DHCP in WHQ and PLS2.
These two DHCP servers are under LabOps control,
and users should not modify anything there.
"""
if socket.gethostname() == "ca-hq-infra1.domain.com" or socket.gethostname() == "ca-pls-infra1.domain.com":
logger.debug("ERROR: This can't be run on WHQ or PLS DHCP servers.")
sys.exit("ERROR: This can't be run on WHQ or PLS DHCP servers.")
# No running in WHQ/PLS
not_whq_pls()
# Log who runs this and on behalf of whom
# compare with i_am, which is basically root
# also check if hidden argument 'owner' is used
if realuser != i_am: # run by mortal user via sudo
if not args.owner:
logger.debug("Run by " + realuser + " (uid: " + realuserid + ") as root, via sudo.")
else:
logger.debug(realuser + ", you cannot reserve on behalf of someone else.")
sys.exit(realuser + ", you cannot reserve on behalf of someone else.")
if realuser == i_am: # run by root
if not args.owner:
logger.debug("Root cannot do this without providing owner of reservation, use <-o DSEE_account>")
sys.exit("Root cannot do this without providing owner of reservation, use <-o DSEE_account>")
else:
logger.debug("Run by root on behalf of " + args.owner)
def bootfile_check():
"""
Not used,
but can be used to check existence of bootfile in Cobbler server
"""
if args.bootfile:
if os.path.isfile("/tftpboot/" + args.bootfile):
logger.debug("OK: /tftpboot/" + args.bootfile + " exists")
else:
logger.debug("ERROR: Cannot find /tftpboot/" + args.bootfile )
sys.exit("ERROR: Cannot find /tftpboot/" + args.bootfile )
def find_ip():
"""
Determine IP for given system
"""
try:
global ipaddress # define global to be used outside of this function
global systemfqdn
ipaddress = socket.gethostbyname(system)
logger.debug("OK: " + system + "'s IP address is " + ipaddress)
systemfqdn = socket.getfqdn(system)
except:
logger.debug("ERROR: " + system + " is not in DNS")
sys.exit("ERROR: " + system + " is not in DNS")
def subnet_check(ipaddress):
"""
Check if IP is in subnet,
and find router and broadcast address.
Arguments:
1. IP, determined by find_ip()
2. file (list of subnets), it's hard coded here!
"""
global default_router
f = open(SUBNETFILE, 'r')
ip_ok = False
try:
for subnet in f:
if netaddr.IPAddress(ipaddress) in netaddr.IPNetwork(subnet):
logger.debug("OK: " + ipaddress + " is on supported " + LOC + " subnet " + str(netaddr.IPNetwork(subnet)))
default_router = str(netaddr.IPNetwork(subnet).network + 1) # assumption: default router is network IP + 1
broadcast_ip = str(netaddr.IPNetwork(subnet).broadcast)
logger.debug("Default router (assumption: network IP + 1): " + default_router)
logger.debug("Broadcast IP: " + broadcast_ip)
ip_ok = True
f.close()
except:
logger.debug("ERROR: Cannot analyze " + ipaddress + " and determine subnet and default router")
sys.exit("ERROR: Cannot analyze " + ipaddress + " and determine subnet and default router")
if not ip_ok:
logger.debug("WARNING: " + ipaddress + " is on " + LOC + " subnet not supported on this DHCP!")
sys.exit("WARNING: " + ipaddress + " is on " + LOC + " subnet not supported on this DHCP!")
def create_cobbler_cfg_file():
"""
Note: dash (-) & dot (.) can't be used in object name,
hence we create first systemobject
"""
systemobject = system.replace("-", "_").replace(".", "_")
logger.debug("System's object/ID: " + systemobject)
try:
if args.bootfile:
systemobject = dhcp_cfg.COBBLER_SYSTEM(LOC, systemfqdn, mac, ipaddress, default_router, args.bootfile)
logger.debug("Creating DHCP cfg for Cobbler system (location: " + systemobject.loc + ") with: " +
systemobject.hostname + " " + systemobject.mac + " " + systemobject.router +
" " + str(systemobject.bootfile) )
systemobject.create_cfg_file()
orig = sys.stdout # initial stdout
sys.stdout = open(LOG_FILE, "a") # want to read cfg file into log
logger.debug("Checking the cfg file:")
systemobject.read_cfg_file()
sys.stdout.close()
sys.stdout = orig # restore initial stdout
else:
systemobject = dhcp_cfg.COBBLER_SYSTEM(LOC, systemfqdn, mac, ipaddress, default_router)
logger.debug("Creating DHCP cfg for Cobbler system (location: " + systemobject.loc + ") with: " +
systemobject.hostname + " " + systemobject.mac + " " + systemobject.router )
systemobject.create_cfg_file()
orig = sys.stdout # initial stdout
sys.stdout = open(LOG_FILE, "a") # want to read cfg file into log
logger.debug("Checking the cfg file:")
systemobject.read_cfg_file()
sys.stdout.close()
sys.stdout = orig # restore initial stdout
except:
logger.debug("ERROR: Cannot create DHCP cfg for Cobbler system " + system)
sys.exit("ERROR: Cannot create DHCP cfg for Cobbler system " + system)
def create_s11_cfg_file():
"""
Note: dash (-) & dot (.) can't be used in object name,
hence we create first systemobject
"""
systemobject = system.replace("-", "_").replace(".", "_")
logger.debug("System's object/ID: " + systemobject)
try:
systemobject = dhcp_cfg.S11_SYSTEM(LOC, systemfqdn, mac, ipaddress)
logger.debug("Creating DHCP cfg for Solaris11 system (location: " + systemobject.loc + ") with: " +
systemobject.hostname + " " + systemobject.mac )
systemobject.create_cfg_file()
orig = sys.stdout # initial stdout
sys.stdout = open(LOG_FILE, "a") # want to read cfg file into log
logger.debug("Checking the cfg file:")
systemobject.read_cfg_file()
sys.stdout.close()
sys.stdout = orig # restore initial stdout
except:
logger.debug("ERROR: Cannot create DHCP cfg for Solaris 11 system " + system)
sys.exit("ERROR: Cannot create DHCP cfg for Solaris 11 system " + system)
def create_ak_cfg_file():
"""
Note: dash (-) & dot (.) can't be used in object name,
hence we create first systemobject
"""
systemobject = system.replace("-", "_").replace(".", "_")
logger.debug("System's object/ID: " + systemobject)
try:
systemobject = dhcp_cfg.AK_SYSTEM(LOC, systemfqdn, mac, ipaddress)
logger.debug("Creating DHCP cfg for AK system (location: " + systemobject.loc + ") with: " +
systemobject.hostname + " " + systemobject.mac )
systemobject.create_cfg_file()
orig = sys.stdout # initial stdout
sys.stdout = open(LOG_FILE, "a") # want to read cfg file into log
logger.debug("Checking the cfg file:")
systemobject.read_cfg_file()
sys.stdout.close()
sys.stdout = orig # restore initial stdout
except:
logger.debug("ERROR: Cannot create DHCP cfg for AK system " + system)
sys.exit("ERROR: Cannot create DHCP cfg for AK system " + system)
def create_s10_cfg_file():
"""
Note: dash (-) & dot (.) can't be used in object name,
hence we create first systemobject
"""
systemobject = system.replace("-", "_").replace(".", "_")
logger.debug("System's object/ID: " + systemobject)
try:
systemobject = dhcp_cfg.S10_SYSTEM_X86(LOC, systemfqdn, mac, ipaddress)
logger.debug("Creating DHCP cfg for Solaris10 x86 system (location: " + systemobject.loc + ") with: " +
systemobject.hostname + " " + systemobject.mac )
systemobject.create_cfg_file()
orig = sys.stdout # initial stdout
sys.stdout = open(LOG_FILE, "a") # want to read cfg file into log
logger.debug("Checking the cfg file:")
systemobject.read_cfg_file()
sys.stdout.close()
sys.stdout = orig # restore initial stdout
except:
logger.debug("ERROR: Cannot create DHCP cfg for Solaris 10 x86 system " + system)
sys.exit("ERROR: Cannot create DHCP cfg for Solaris 10 x86 system " + system)
def compile_client_list():
"""
Compile list of clients for clients.include file.
Need to import os module again or get error:
AttributeError: '_MutuallyExclusiveGroup' object has no attribute 'path'
Need to troubleshoot more!?
"""
import os
CLIENTSDIR = "/etc/dhcp/clients/"
if not os.path.exists(CLIENTSDIR):
logger.debug("ERROR: " + CLIENTSDIR + " does not exist.")
sys.exit("ERROR: " + CLIENTSDIR + " does not exist.")
f = open("/etc/dhcp/clients.include", "w+")
try:
for root, dirs, files in os.walk(CLIENTSDIR):
for clientname in files:
f.write("include \"" + CLIENTSDIR + clientname + "\" ;\n")
logger.debug("OK: Compiled new /etc/dhcp/clients.include")
except:
logger.debug("ERROR: cannot compile /etc/dhcp/clients.include")
sys.exit("ERROR: cannot compile /etc/dhcp/clients.include")
f.close()
def dhcp_cfg_check():
"""
Check DHCP cfg syntax
"""
return True if subprocess.call(['service', 'dhcpd', 'configtest']) == 0 else False
def dhcp_restart():
"""
Restart DHCP service
"""
return True if subprocess.call(['service', 'dhcpd', 'restart']) == 0 else False
# ---- MAIN -----
if __name__ == '__main__':
if linuxinstall:
print ("Install type: Linux")
logger.debug("Install type: Linux")
find_ip()
subnet_check(ipaddress)
create_cobbler_cfg_file()
compile_client_list()
if not dhcp_cfg_check():
logger.debug("ERROR: DHCP config check fails")
sys.exit("ERROR: DHCP config check fails")
else:
logger.debug("OK: DHCP config looks good")
if not dhcp_restart():
logger.debug("ERROR: DHCP service restart fails")
sys.exit("ERROR: DHCP service restart fails")
else:
logger.debug("OK: DHCP service has been restarted")
elif s11install:
print ("Install type: Solaris 11")
logger.debug("Install type: Solaris 11")
find_ip()
subnet_check(ipaddress)
create_s11_cfg_file()
compile_client_list()
if not dhcp_cfg_check():
logger.debug("ERROR: DHCP config check fails")
sys.exit("ERROR: DHCP config check fails")
else:
logger.debug("OK: DHCP config looks good")
if not dhcp_restart():
logger.debug("ERROR: DHCP service restart fails")
sys.exit("ERROR: DHCP service restart fails")
else:
logger.debug("OK: DHCP service has been restarted")
elif akinstall:
print ("Install type: AK")
logger.debug("Install type: AK")
find_ip()
subnet_check(ipaddress)
create_ak_cfg_file()
compile_client_list()
if not dhcp_cfg_check():
logger.debug("ERROR: DHCP config check fails")
sys.exit("ERROR: DHCP config check fails")
else:
logger.debug("OK: DHCP config looks good")
if not dhcp_restart():
logger.debug("ERROR: DHCP service restart fails")
sys.exit("ERROR: DHCP service restart fails")
else:
logger.debug("OK: DHCP service has been restarted")
elif s10install:
print ("Install type: Solaris 10 x86")
logger.debug("Install type: Solaris 10 x86")
find_ip()
subnet_check(ipaddress)
create_s10_cfg_file() # arch is checked inside function
compile_client_list()
if not dhcp_cfg_check():
logger.debug("ERROR: DHCP config check fails")
sys.exit("ERROR: DHCP config check fails")
else:
logger.debug("OK: DHCP config looks good")
if not dhcp_restart():
logger.debug("ERROR: DHCP service restart fails")
sys.exit("ERROR: DHCP service restart fails")
else:
logger.debug("OK: DHCP service has been restarted")
logger.debug("FINISH AT : " + strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
Usage
[zdudic@dhcp-server ~]which ca-dhcp-reserve.py
/usr/bin/ca-dhcp-reserve.py
[zdudic@dhcp-server ~]sudo !!
sudo ca-dhcp-reserve.py
usage: ca-dhcp-reserve.py [-h] (-l | -i | -j | -z) -s SYSTEM -m MAC
[-b BOOTFILE]
ca-dhcp-reserve.py: error: argument -s/--system is required
[zdudic@ca-dhcp-sca ~]ca-dhcp-reserve.py -h
zdudic, please run this via sudo (otherwise you won't have permissions to complete reservation)
[zdudic@dhcp-server ~]sudo !!
sudo ca-dhcp-reserve.py -h
usage: ca-dhcp-reserve.py [-h] (-l | -i | -j | -z) -s SYSTEM -m MAC
[-b BOOTFILE]
Add DHCP cfg file for a system (location: sca )
optional arguments:
-h, --help show this help message and exit
-l, --linux Linux install via Cobbler
-i, --solaris11 Solaris 11 install
-j, --solaris10 Solaris 10 x86 install (SPARC is not supported)
-z, --ak AK install
-s SYSTEM, --system SYSTEM
System's FQDN
-m MAC, --mac MAC System's MAC ( : as delimiter)
-b BOOTFILE, --bootfile BOOTFILE
Custom boot file, only linux install (it must be in
:/tftpboot)
Brought to you by LabOps
Back to the main page