summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@redhat.com>2007-02-20 13:16:58 -0500
committerJim Meyering <jim@meyering.net>2007-02-20 13:16:58 -0500
commit817962be5ff44c685eae4d7fe9e9247c2ca49fe0 (patch)
tree980e5611e002d99ce00521d79e1c66db6b874e06
parentee62b5bb0fb0c3f184a8dc79720ea379951eb8c6 (diff)
downloadcobbler-817962be5ff44c685eae4d7fe9e9247c2ca49fe0.tar.gz
cobbler-817962be5ff44c685eae4d7fe9e9247c2ca49fe0.tar.xz
cobbler-817962be5ff44c685eae4d7fe9e9247c2ca49fe0.zip
Adding disable_netboot option for cobbler, which can be programatically exercised by API users to prevent install-loop scenarios
by taking action as a result of some event in post. Also making syncless code modifications work with IA64 tftp locations.
-rw-r--r--cobbler/action_litesync.py17
-rw-r--r--cobbler/action_sync.py44
-rw-r--r--cobbler/collection_systems.py2
-rw-r--r--cobbler/item_system.py48
4 files changed, 72 insertions, 39 deletions
diff --git a/cobbler/action_litesync.py b/cobbler/action_litesync.py
index 4f9195c6..fddea9d6 100644
--- a/cobbler/action_litesync.py
+++ b/cobbler/action_litesync.py
@@ -109,7 +109,18 @@ class BootLiteSync:
# delete contents of kickstarts_sys/$name in webdir
filename = self.sync.get_pxe_filename(name)
self.sync.rmtree(os.path.join(self.settings.webdir, "kickstarts_sys", filename))
- # delete pxelinux.cfg/$foo where $foo is either the *encoded* IP
- # or the MAC or default
- self.sync.rmfile(os.path.join(self.settings.tftpboot, "pxelinux.cfg", filename))
+
+ # delete PXE Linux configuration file (which might be in one of two places)
+ itanic = False
+ system_record = self.systems.find(name)
+ profile = self.profiles.find(system_record.profile)
+ # allow cobbler deletes to still work in the cobbler config is discombobulated
+ if profile is not None:
+ distro = self.distros.find(profile.distro)
+ if distro is not None and distro in [ "ia64", "IA64"]:
+ itanic = True
+ if not itanic:
+ self.sync.rmfile(os.path.join(self.settings.tftpboot, "pxelinux.cfg", filename))
+ else:
+ self.sync.rmfile(os.path.join(self.settings.tftpboot, filename))
diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py
index e243afa4..be6d02c9 100644
--- a/cobbler/action_sync.py
+++ b/cobbler/action_sync.py
@@ -264,7 +264,7 @@ class BootSync:
a solution. *Otherwise* duplication is minimal.
"""
- # clean out all of /tftpboot
+ # clean out parts of webdir and all of /tftpboot/images and /tftpboot/pxelinux.cfg
for x in os.listdir(self.settings.webdir):
path = os.path.join(self.settings.webdir,x)
if os.path.isfile(path):
@@ -279,9 +279,6 @@ class BootSync:
self.rmtree_contents(path)
self.rmtree_contents(os.path.join(self.settings.tftpboot, "pxelinux.cfg"))
self.rmtree_contents(os.path.join(self.settings.tftpboot, "images"))
- # no real reason to delete these
- # self.rmfile(os.path.join(self.settings.tftpboot, "pxelinux.0"))
- # self.rmfile(os.path.join(self.settings.tftpboot, "elilo-3.6-ia64.efi"))
def copy_distros(self):
"""
@@ -492,23 +489,8 @@ class BootSync:
self.write_distro_file(d)
for p in self.profiles:
- # TODO: add check to ensure all profiles have distros (=error)
- # TODO: add check to ensure all profiles have systems (=warning)
self.write_profile_file(p)
- # Copy default PXE file if it exists; if there's none, ignore
- # FIXME: Log something inobtrusive ifthe default file is missing
- # src = "/etc/cobbler/default.pxe"
- # if os.path.exists(src):
- # nocopy = False
- # for system in self.systems:
- # if system.name == "default":
- # nocopy = True
- # break
- # if not nocopy:
- # dst = os.path.join(self.settings.tftpboot, "pxelinux.cfg", "default")
- # self.copyfile(src, dst)
-
for system in self.systems:
self.write_all_system_files(system)
@@ -540,10 +522,16 @@ class BootSync:
f3 = os.path.join(self.settings.webdir, "systems", f1)
- if distro.arch in [ "x86", "x86_64", "standard"]:
- self.write_pxe_file(f2,system,profile,distro,False)
- if distro.arch == "ia64":
- self.write_pxe_file(f2,system,profile,distro,True)
+
+ if system.netboot_enabled:
+ if distro.arch in [ "x86", "x86_64", "standard"]:
+ self.write_pxe_file(f2,system,profile,distro,False)
+ if distro.arch == "ia64":
+ self.write_pxe_file(f2,system,profile,distro,True)
+ else:
+ # ensure the file doesn't exist
+ self.rmfile(f2)
+
self.write_system_file(f3,system)
@@ -600,8 +588,9 @@ class BootSync:
# bits and pieces relevant to the profile.
distro = self.distros.find(profile.distro)
contents = self.write_pxe_file(None,None,profile,distro,False,include_header=False)
- defaults.write(contents + "\n")
- defaults.write("\n")
+ if contents is not None:
+ defaults.write(contents + "\n")
+ defaults.write("\n")
defaults.close()
@@ -614,6 +603,11 @@ class BootSync:
NOTE: relevant to tftp only
"""
+ # system might have netboot_enabled set to False (see item_system.py), if so,
+ # don't do anything else and flag the error condition.
+ if system is not None and not system.netboot_enabled:
+ return None
+
buffer = ""
kernel_path = os.path.join("/images",distro.name,os.path.basename(distro.kernel))
diff --git a/cobbler/collection_systems.py b/cobbler/collection_systems.py
index 8d90eb56..7b6191be 100644
--- a/cobbler/collection_systems.py
+++ b/cobbler/collection_systems.py
@@ -48,10 +48,10 @@ class Systems(collection.Collection):
Remove element named 'name' from the collection
"""
if self.find(name):
- del self.listing[name]
if with_delete:
lite_sync = action_litesync.BootLiteSync(self.config)
lite_sync.remove_single_system(name)
+ del self.listing[name]
return True
raise cexceptions.CobblerException("delete_nothing")
diff --git a/cobbler/item_system.py b/cobbler/item_system.py
index 7409f117..5f23be63 100644
--- a/cobbler/item_system.py
+++ b/cobbler/item_system.py
@@ -28,13 +28,15 @@ class System(item.Item):
self.kernel_options = {}
self.ks_meta = {}
self.pxe_address = ""
+ self.netboot_enabled = 1
def from_datastruct(self,seed_data):
- self.name = self.load_item(seed_data,'name')
- self.profile = self.load_item(seed_data,'profile')
- self.kernel_options = self.load_item(seed_data,'kernel_options')
- self.ks_meta = self.load_item(seed_data,'ks_meta')
- self.pxe_address = self.load_item(seed_data,'pxe_address')
+ self.name = self.load_item(seed_data, 'name')
+ self.profile = self.load_item(seed_data, 'profile')
+ self.kernel_options = self.load_item(seed_data, 'kernel_options')
+ self.ks_meta = self.load_item(seed_data, 'ks_meta')
+ self.pxe_address = self.load_item(seed_data, 'pxe_address')
+ self.netboot_enabled = self.load_item(seed_data, 'netboot_enabled', 1)
# backwards compatibility -- convert string entries to dicts for storage
if type(self.kernel_options) != dict:
@@ -60,6 +62,10 @@ class System(item.Item):
return True
def set_pxe_address(self,address):
+ """
+ Assign a IP or hostname in DHCP when this MAC boots.
+ Only works if manage_dhcp is set in /var/lib/cobbler/settings
+ """
# restricting to address as IP only in dhcpd.conf is probably
# incorrect ... some people may want to pin the hostname instead.
# doing so, however, doesn't allow dhcpd.conf to be managed
@@ -78,6 +84,27 @@ class System(item.Item):
return True
raise cexceptions.CobblerException("exc_profile")
+ def set_netboot_enabled(self,netboot_enabled):
+ """
+ If true, allows per-system PXE files to be generated on sync (or add). If false,
+ these files are not generated, thus eliminating the potential for an infinite install
+ loop when systems are set to PXE boot first in the boot order. In general, users
+ who are PXE booting first in the boot order won't create system definitions, so this
+ feature primarily comes into play for programmatic users of the API, who want to
+ initially create a system with netboot enabled and then disable it after the system installs,
+ as triggered by some action in kickstart %post. For this reason, this option is not
+ surfaced in the CLI, output, or documentation (yet).
+
+ Use of this option does not affect the ability to use PXE menus. If an admin has machines
+ set up to PXE only after local boot fails, this option isn't even relevant.
+ """
+ if netboot_enabled in [ True, "True", "true", 1, "on", "yes", "y", "ON", "YES", "Y" ]:
+ # this is a bit lame, though we don't know what the user will enter YAML wise...
+ self.netboot_enabled = 1
+ else:
+ self.netboot_enabled = 0
+ return True
+
def is_valid(self):
"""
A system is valid when it contains a valid name and a profile.
@@ -90,11 +117,12 @@ class System(item.Item):
def to_datastruct(self):
return {
- 'name' : self.name,
- 'profile' : self.profile,
- 'kernel_options' : self.kernel_options,
- 'ks_meta' : self.ks_meta,
- 'pxe_address' : self.pxe_address
+ 'name' : self.name,
+ 'profile' : self.profile,
+ 'kernel_options' : self.kernel_options,
+ 'ks_meta' : self.ks_meta,
+ 'pxe_address' : self.pxe_address,
+ 'netboot_enabled' : self.netboot_enabled
}
def printable(self):