diff options
author | Michael DeHaan <mdehaan@redhat.com> | 2006-10-12 11:26:14 -0400 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2006-10-12 11:26:14 -0400 |
commit | 55ce69eb59d2080aaeea7e4f712583e9967f6167 (patch) | |
tree | ee489735f41da6907022e06c7a6ad516b7b4885f | |
parent | d496b2b75dc3bb80b85deac10125450073e4fee7 (diff) | |
download | third_party-cobbler-55ce69eb59d2080aaeea7e4f712583e9967f6167.tar.gz third_party-cobbler-55ce69eb59d2080aaeea7e4f712583e9967f6167.tar.xz third_party-cobbler-55ce69eb59d2080aaeea7e4f712583e9967f6167.zip |
Added a basic locking system to avoid multiple "sync" operations happening at the same time -- not a huge risk -- but it ought to be guarded against.
-rw-r--r-- | TODO | 29 | ||||
-rwxr-xr-x | cobbler/cobbler.py | 83 | ||||
-rw-r--r-- | cobbler/cobbler_msg.py | 1 | ||||
-rw-r--r-- | cobbler/item.py | 10 | ||||
-rw-r--r-- | cobbler/item_distro.py | 10 | ||||
-rw-r--r-- | cobbler/item_profile.py | 18 | ||||
-rw-r--r-- | cobbler/item_system.py | 12 |
7 files changed, 79 insertions, 84 deletions
@@ -1,17 +1,30 @@ cobbler TODO list - - GTK (or Web) UI for Cobbler ? - - Port over to xeninst python module once available for something other than Rawhide - - Wake on lan integration for PXE - - Integration with stonnith or other up/down devices? - - Locking + +need to fix: + - global locking -- one cobbler command at a time - For "enchant", try to verify that syslinux and mkinitrd are installed on the remote. - - "make test" shouldn't overwrite files in /var/lib/cobbler/ - "enchant" would be better if it didn't need to know the password - "enchant" has issues with ssh key changes locking it out - "enchant" should be written in a more distro-agnostic way. - - "add" should be distinguished from "edit" so as to not overwrite + - "cobbler add" should be distinguished from "edit" so as to not overwrite + - "make test" shouldn't overwrite files in /var/lib/cobbler/ new configs. + +really nice to have: + - GTK (or Web) UI for Cobbler ? + +making things more standardized/flexible: + - Port over to xeninst python module once available for something other than Rawhide + - abstract out the --pxe-arch system, possibly pseudonym it to arch, + and make the multiple-bootloader system more plugin oriented to allow + for alternative bootloaders (not neccessarily kickstart related) + to be added + - look into what it would take to make kickstart *more optional* + +bells and whistles: + - Wake on lan integration for PXE + - Integration with stonnith or other up/down devices? -general cleanup: +internal code cleanup: - an argument parsing overhaul is probably due - remove the cobbler_msg logic since i18n isn't likely diff --git a/cobbler/cobbler.py b/cobbler/cobbler.py index 886a24b..2bfd810 100755 --- a/cobbler/cobbler.py +++ b/cobbler/cobbler.py @@ -16,10 +16,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. import sys import api +import os +import os.path import cobbler_msg import cexceptions +LOCKFILE="/var/lib/cobbler/lock" + class BootCLI: @@ -58,7 +62,6 @@ class BootCLI: 'systems' : self.system, 'system' : self.system, 'sync' : self.sync, - 'enchant' : self.enchant_system, '--help' : self.usage, '/?' : self.usage } @@ -89,6 +92,7 @@ class BootCLI: commands = { '--name' : lambda(a): self.api.systems().remove(a), '--system' : lambda(a): self.api.systems().remove(a), + '--system' : lambda(a): self.api.systems().remove(a) } on_ok = lambda: True return self.apply_args(args,commands,on_ok) @@ -124,63 +128,15 @@ class BootCLI: """ sys = self.api.new_system() commands = { - '--name' : lambda(a) : sys.set_name(a), - '--system' : lambda(a) : sys.set_name(a), - '--profile' : lambda(a) : sys.set_profile(a), - '--kopts' : lambda(a) : sys.set_kernel_options(a), - '--ksmeta' : lambda(a) : sys.set_ksmeta(a), - '--pxe-arch' : lambda(a) : sys.set_pxe_arch(a), - '--pxe-address' : lambda(a) : sys.set_pxe_address(a) - # FIXME: surface a way to pin the IP. + '--name' : lambda(a) : sys.set_name(a), + '--system' : lambda(a) : sys.set_name(a), + '--profile' : lambda(a) : sys.set_profile(a), + '--kopts' : lambda(a) : sys.set_kernel_options(a), + '--ksmeta' : lambda(a) : sys.set_ksmeta(a) } on_ok = lambda: self.api.systems().add(sys) return self.apply_args(args,commands,on_ok) - def apply_cmd_args(self,args,accepted,required,err_msg): - """ - This is a variation of the command parsing done in apply_args but - is not centric to things in the object graph. - """ - for arg in args: - try: - (first, last) = (None, None) - (first, last) = arg.split("=") - except: - if first is None: - continue - raise cexceptions.CobblerException(err_msg) - if first in accepted.keys(): - accepted[first] = last - else: - raise cexceptions.CobblerException("weird_arg",first) - for arg in required: - if accepted[arg] is None: - raise cexceptions.CobblerException(err_msg) - return accepted - - def import_distros(self,args): - stored = { - "--path" : None - } - required = [ "--path" ] - results = self.apply_cmd_args(args,stored,required,"import_args") - return self.api.import_distros(stored["--path"]) - - def enchant_system(self,args): - """ - Replace an existing running password. - """ - stored = { - "--name" : None, - "--profile" : None, - "--password" : None - } - required = [ "--name", "--profile", "--password" ] - results = self.apply_cmd_args(args,stored,required,"enchant_args") - return self.api.enchant(stored["--name"], - stored["--profile"], - stored["--password"] - ) def profile_edit(self,args): """ @@ -199,6 +155,7 @@ class BootCLI: '--ksmeta' : lambda(a) : profile.set_ksmeta(a) # the following options are most likely not useful for profiles (yet) # primarily due to not being implemented in koan. + # '--xen-mac' : lambda(a) : profile.set_xen_mac(a), # '--xen-paravirt' : lambda(a) : profile.set_xen_paravirt(a), } on_ok = lambda: self.api.profiles().add(profile) @@ -221,6 +178,7 @@ class BootCLI: on_ok = lambda: self.api.distros().add(distro) return self.apply_args(args,commands,on_ok) + def apply_args(self,args,input_routines,on_ok): """ Custom CLI handling, instead of getopt/optparse. @@ -269,6 +227,7 @@ class BootCLI: status = self.api.sync(dryrun=False) return status + def check(self,args): """ Check system for network boot decency/prereqs: 'cobbler check' @@ -306,12 +265,24 @@ def main(): """ CLI entry point """ + exitcode = 0 try: + if os.path.exists(LOCKFILE): + raise cexceptions.CobblerException("lock") + try: + lockfile = open(LOCKFILE,"w+") + except: + raise cexceptions.CobblerException("no_create",LOCKFILE) + lockfile.close() BootCLI(sys.argv).run() except cexceptions.CobblerException, exc: print str(exc)[1:-1] # remove framing air quotes - sys.exit(1) - sys.exit(0) + exitcode = 1 + try: + os.remove(LOCKFILE) + except: + pass + return exitcode if __name__ == "__main__": sys.exit(main()) diff --git a/cobbler/cobbler_msg.py b/cobbler/cobbler_msg.py index 48e357b..dbcdfff 100644 --- a/cobbler/cobbler_msg.py +++ b/cobbler/cobbler_msg.py @@ -86,6 +86,7 @@ _msg_table = { "exc_no_template" : "can't read /etc/cobbler/dhcp.template", "exc_dhcp_nomac" : "when cobbler is managing dhcpd.conf, all system names must be MAC addresses. Aborting.", "exc_ia64_noip" : "due to an IA64 bootloader limitation, system (%s) must define a pxe-address value (which is an IP address)", + "lock" : "Locked. If cobbler is currently running, wait for termination, otherwise remove /var/lib/cobbler/lock", "check_ok" : """ No setup problems found. diff --git a/cobbler/item.py b/cobbler/item.py index 6c55225..0bec45f 100644 --- a/cobbler/item.py +++ b/cobbler/item.py @@ -48,6 +48,16 @@ class Item(serializable.Serializable): return False return True + def load_item(self,datastruct,key): + """ + Used in subclass from_datastruct functions to load items from + a hash. Intented to ease backwards compatibility of config + files during upgrades. + """ + if datastruct.has_key(key): + return datastruct[key] + return '' + def to_datastruct(self): """ Returns an easily-marshalable representation of the collection. diff --git a/cobbler/item_distro.py b/cobbler/item_distro.py index 838dc1a..0d0f26d 100644 --- a/cobbler/item_distro.py +++ b/cobbler/item_distro.py @@ -43,11 +43,11 @@ class Distro(item.Item): """ Modify this object to take on values in seed_data """ - self.name = seed_data['name'] - self.kernel = seed_data['kernel'] - self.initrd = seed_data['initrd'] - self.kernel_options = seed_data['kernel_options'] - self.ks_meta = seed_data['ks_meta'] + self.name = self.load_item(seed_data,'name') + self.kernel = self.load_item(seed_data,'kernel') + self.initrd = self.load_item(seed_data,'initrd') + self.kernel_options = self.load_item(seed_data,'kernel_options') + self.ks_meta = self.load_item(seed_data,'ks_meta') return self def set_kernel(self,kernel): diff --git a/cobbler/item_profile.py b/cobbler/item_profile.py index 6a626d3..ad1cf45 100644 --- a/cobbler/item_profile.py +++ b/cobbler/item_profile.py @@ -43,17 +43,17 @@ class Profile(item.Item): """ Load this object's properties based on seed_data """ - self.name = seed_data['name'] - self.distro = seed_data['distro'] - self.kickstart = seed_data['kickstart'] - self.kernel_options = seed_data['kernel_options'] - self.ks_meta = seed_data['ks_meta'] - self.xen_name = seed_data['xen_name'] + self.name = self.load_item(seed_data,'name') + self.distro = self.load_item(seed_data,'distro') + self.kickstart = self.load_item(seed_data,'kickstart') + self.kernel_options = self.load_item(seed_data,'kernel_options') + self.ks_meta = self.load_item(seed_data,'ks_meta') + self.xen_name = self.load_item(seed_data,'xen_name') if not self.xen_name or self.xen_name == '': self.xen_name = self.name - self.xen_ram = seed_data['xen_ram'] - self.xen_file_size = seed_data['xen_file_size'] - self.xen_paravirt = seed_data['xen_paravirt'] + self.xen_ram = self.load_item(seed_data,'xen_ram') + self.xen_file_size = self.load_item(seed_data,'xen_file_size') + self.xen_paravirt = self.load_item(seed_data,'xen_paravirt') return self def set_distro(self,distro_name): diff --git a/cobbler/item_system.py b/cobbler/item_system.py index 217e511..2568959 100644 --- a/cobbler/item_system.py +++ b/cobbler/item_system.py @@ -31,12 +31,12 @@ class System(item.Item): self.pxe_address = "" def from_datastruct(self,seed_data): - self.name = seed_data['name'] - self.profile = seed_data['profile'] - self.kernel_options = seed_data['kernel_options'] - self.ks_meta = seed_data['ks_meta'] - self.pxe_arch = seed_data['pxe_arch'] - self.pxe_address = 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_arch = self.load_item(seed_data,'pxe_arch') + self.pxe_address = self.load_item(seed_data,'pxe_address') return self def set_name(self,name): |