summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@redhat.com>2009-01-05 14:44:16 -0500
committerMichael DeHaan <mdehaan@redhat.com>2009-01-05 14:44:16 -0500
commit352bc629bd1f7790e895aceb380dbe315356e835 (patch)
tree7ca7a2f908abd5fbbdf4e98b6547936e656639bf
parent6e73337ad583f7dc52fad37aa8fcfe45abbf0842 (diff)
downloadcobbler-352bc629bd1f7790e895aceb380dbe315356e835.tar.gz
cobbler-352bc629bd1f7790e895aceb380dbe315356e835.tar.xz
cobbler-352bc629bd1f7790e895aceb380dbe315356e835.zip
(A) It is unneccessary to run restorecon when the contexts on the directories is already correct.
(B) Modify cobbler check code to suggest directories to set semanage rules on/for.
-rw-r--r--cobbler/action_check.py26
-rw-r--r--cobbler/action_litesync.py6
-rw-r--r--cobbler/action_sync.py90
-rw-r--r--cobbler/api.py8
-rw-r--r--cobbler/modules/cli_misc.py7
-rw-r--r--cobbler/pxegen.py30
-rw-r--r--cobbler/utils.py97
-rw-r--r--triggers/restart-services.trigger2
8 files changed, 175 insertions, 91 deletions
diff --git a/cobbler/action_check.py b/cobbler/action_check.py
index 8eeeb41b..1f59da06 100644
--- a/cobbler/action_check.py
+++ b/cobbler/action_check.py
@@ -147,7 +147,31 @@ class BootCheck:
if line.find("httpd_can_network_connect ") != -1:
if line.find("off") != -1:
status.append(_("Must enable selinux boolean to enable Apache and web services components, run: setsebool -P httpd_can_network_connect true"))
-
+ data3 = sub_process.Popen("/usr/sbin/semanage fcontext -l | grep public_content_t",shell=True,stdout=sub_process.PIPE).communicate()[0]
+ #print "DEBUG: data3=\n%s\n" % data3
+
+ rule1 = False
+ rule2 = False
+ rule3 = False
+ selinux_msg = "/usr/sbin/semanage fcontext -a -t public_content_t \"%s\""
+ for line in data3.split("\n"):
+ if line.startswith("/tftpboot/.*") and line.find("public_content_t") != -1:
+ rule1 = True
+ if line.startswith("/var/lib/tftpboot/.*") and line.find("public_content_t") != -1:
+ rule2 = True
+ if line.startswith("/var/www/cobbler/images/.*") and line.find("public_content_t") != -1:
+ rule3 = True
+
+ rules = []
+ if not os.path.exists("/tftpboot") and not rule1:
+ rules.append(selinux_msg % "/tftpboot/.*")
+ else:
+ if not rule2:
+ rules.append(selinux_msg % "/var/lib/tftpboot/.*")
+ if not rule3:
+ rules.append(selinux_msg % "/var/www/cobbler/images/.*")
+ if len(rules) > 0:
+ status.append("you need to set some SELinux content rules to ensure cobbler works correctly in your SELinux environment, run the following: %s" % " && ".join(rules))
def check_for_default_password(self,status):
default_pass = self.settings.default_password_crypted
diff --git a/cobbler/action_litesync.py b/cobbler/action_litesync.py
index b040db0a..6f239578 100644
--- a/cobbler/action_litesync.py
+++ b/cobbler/action_litesync.py
@@ -46,11 +46,11 @@ class BootLiteSync:
Handles conversion of internal state to the tftpboot tree layout
"""
- def __init__(self,config):
+ def __init__(self,config,verbose=True):
"""
Constructor
"""
- self.verbose = True
+ self.verbose = verbose
self.config = config
self.distros = config.distros()
self.profiles = config.profiles()
@@ -58,7 +58,7 @@ class BootLiteSync:
self.images = config.images()
self.settings = config.settings()
self.repos = config.repos()
- self.sync = config.api.get_sync()
+ self.sync = config.api.get_sync(verbose)
def add_single_distro(self, name):
# get the distro record
diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py
index 40e5c443..4b334044 100644
--- a/cobbler/action_sync.py
+++ b/cobbler/action_sync.py
@@ -56,19 +56,22 @@ class BootSync:
"""
Constructor
"""
- self.verbose = verbose
- self.config = config
- self.api = config.api
- self.distros = config.distros()
- self.profiles = config.profiles()
- self.systems = config.systems()
- self.settings = config.settings()
- self.repos = config.repos()
- self.templar = templar.Templar(config)
- self.pxegen = pxegen.PXEGen(config)
- self.dns = dns
- self.dhcp = dhcp
- self.bootloc = utils.tftpboot_location()
+ self.verbose = verbose
+ self.config = config
+ self.api = config.api
+ self.distros = config.distros()
+ self.profiles = config.profiles()
+ self.systems = config.systems()
+ self.settings = config.settings()
+ self.repos = config.repos()
+ self.templar = templar.Templar(config)
+ self.pxegen = pxegen.PXEGen(config)
+ self.dns = dns
+ self.dhcp = dhcp
+ self.bootloc = utils.tftpboot_location()
+ self.pxegen.verbose = verbose
+ self.dns.verbose = verbose
+ self.dhcp.verbose = verbose
def run(self):
"""
@@ -78,34 +81,65 @@ class BootSync:
if not os.path.exists(self.bootloc):
raise CX(_("cannot find directory: %s") % self.bootloc)
+ if self.verbose:
+ print "- running pre-sync triggers"
+
# run pre-triggers...
utils.run_triggers(None, "/var/lib/cobbler/triggers/sync/pre/*")
# (paranoid) in case the pre-trigger modified any objects...
+
+ if self.verbose:
+ print "- loading configuration"
self.api.deserialize()
+
self.distros = self.config.distros()
self.profiles = self.config.profiles()
self.systems = self.config.systems()
self.settings = self.config.settings()
self.repos = self.config.repos()
- self.pxegen = pxegen.PXEGen(self.config)
# execute the core of the sync operation
+
+ if self.verbose:
+ print "- cleaning trees"
self.clean_trees()
+
+ if self.verbose:
+ print "- copying bootloaders"
self.pxegen.copy_bootloaders()
+
+ if self.verbose:
+ print "- copying distros"
self.pxegen.copy_distros()
+
+ if self.verbose:
+ print "- copying images"
self.pxegen.copy_images()
+
for x in self.systems:
+ if self.verbose:
+ print "- copying files for system: %s" % x.name
self.pxegen.write_all_system_files(x)
+
if self.settings.manage_dhcp:
+ if self.verbose:
+ print "- rendering DHCP files"
self.dhcp.write_dhcp_file()
self.dhcp.regen_ethers()
if self.settings.manage_dns:
+ if self.verbose:
+ print "- rendering DNS files"
self.dns.regen_hosts()
self.dns.write_dns_files()
+
+ if self.verbose:
+ print "- generating PXE menu structure"
self.pxegen.make_pxe_menu()
# run post-triggers
+ if self.verbose:
+ print "- running post-sync triggers"
utils.run_triggers(None, "/var/lib/cobbler/triggers/sync/post/*")
return True
@@ -126,14 +160,14 @@ class BootSync:
path = os.path.join(self.settings.webdir,x)
if os.path.isfile(path):
if not x.endswith(".py"):
- utils.rmfile(path)
+ utils.rmfile(path,verbose=self.verbose)
if os.path.isdir(path):
if not x in ["web", "webui", "localmirror","repo_mirror","ks_mirror","images","links","repo_profile","repo_system","svc","rendered"] :
# delete directories that shouldn't exist
- utils.rmtree(path)
+ utils.rmtree(path,verbose=self.verbose)
if x in ["kickstarts","kickstarts_sys","images","systems","distros","profiles","repo_profile","repo_system","rendered"]:
# clean out directory contents
- utils.rmtree_contents(path)
+ utils.rmtree_contents(path,verbose=self.verbose)
pxelinux_dir = os.path.join(self.bootloc, "pxelinux.cfg")
images_dir = os.path.join(self.bootloc, "images")
yaboot_bin_dir = os.path.join(self.bootloc, "ppc")
@@ -141,21 +175,21 @@ class BootSync:
s390_dir = os.path.join(self.bootloc, "s390x")
rendered_dir = os.path.join(self.settings.webdir, "rendered")
if not os.path.exists(pxelinux_dir):
- utils.mkdir(pxelinux_dir)
+ utils.mkdir(pxelinux_dir,verbose=self.verbose)
if not os.path.exists(images_dir):
- utils.mkdir(images_dir)
+ utils.mkdir(images_dir,verbose=self.verbose)
if not os.path.exists(rendered_dir):
- utils.mkdir(rendered_dir)
+ utils.mkdir(rendered_dir,verbose=self.verbose)
if not os.path.exists(yaboot_bin_dir):
- utils.mkdir(yaboot_bin_dir)
+ utils.mkdir(yaboot_bin_dir,verbose=self.verbose)
if not os.path.exists(yaboot_cfg_dir):
- utils.mkdir(yaboot_cfg_dir)
- utils.rmtree_contents(os.path.join(self.bootloc, "pxelinux.cfg"))
- utils.rmtree_contents(os.path.join(self.bootloc, "images"))
- utils.rmtree_contents(os.path.join(self.bootloc, "s390x"))
- utils.rmtree_contents(os.path.join(self.bootloc, "ppc"))
- utils.rmtree_contents(os.path.join(self.bootloc, "etc"))
- utils.rmtree_contents(rendered_dir)
+ utils.mkdir(yaboot_cfg_dir,verbose=self.verbose)
+ utils.rmtree_contents(os.path.join(self.bootloc, "pxelinux.cfg"),verbose=self.verbose)
+ utils.rmtree_contents(os.path.join(self.bootloc, "images"),verbose=self.verbose)
+ utils.rmtree_contents(os.path.join(self.bootloc, "s390x"),verbose=self.verbose)
+ utils.rmtree_contents(os.path.join(self.bootloc, "ppc"),verbose=self.verbose)
+ utils.rmtree_contents(os.path.join(self.bootloc, "etc"),verbose=self.verbose)
+ utils.rmtree_contents(rendered_dir,verbose=self.verbose)
diff --git a/cobbler/api.py b/cobbler/api.py
index 84c2c638..f4178239 100644
--- a/cobbler/api.py
+++ b/cobbler/api.py
@@ -511,7 +511,7 @@ class BootAPI:
validator = action_validate.Validate(self._config)
return validator.run()
- def sync(self):
+ def sync(self,verbose=False):
"""
Take the values currently written to the configuration files in
/etc, and /var, and build out the information tree found in
@@ -519,10 +519,10 @@ class BootAPI:
saved with serialize() will NOT be synchronized with this command.
"""
self.log("sync")
- sync = self.get_sync()
+ sync = self.get_sync(verbose=verbose)
return sync.run()
- def get_sync(self):
+ def get_sync(self,verbose=False):
self.dhcp = self.get_module_from_file(
"dhcp",
"module",
@@ -533,7 +533,7 @@ class BootAPI:
"module",
"manage_bind"
).get_manager(self._config)
- return action_sync.BootSync(self._config,dhcp=self.dhcp,dns=self.dns)
+ return action_sync.BootSync(self._config,dhcp=self.dhcp,dns=self.dns,verbose=verbose)
def reposync(self, name=None, tries=1, nofail=False):
"""
diff --git a/cobbler/modules/cli_misc.py b/cobbler/modules/cli_misc.py
index 94ccc0d1..14e61ff5 100644
--- a/cobbler/modules/cli_misc.py
+++ b/cobbler/modules/cli_misc.py
@@ -172,7 +172,10 @@ class StatusFunction(commands.CobblerFunction):
########################################################
class SyncFunction(commands.CobblerFunction):
-
+
+ def add_options(self, p, args):
+ p.add_option("--verbose", dest="verbose", action="store_true", help="run sync with more output")
+
def help_me(self):
return HELP_FORMAT % ("cobbler sync","")
@@ -180,7 +183,7 @@ class SyncFunction(commands.CobblerFunction):
return "sync"
def run(self):
- return self.api.sync()
+ return self.api.sync(verbose=self.options.verbose)
########################################################
diff --git a/cobbler/pxegen.py b/cobbler/pxegen.py
index 73d56933..e0172549 100644
--- a/cobbler/pxegen.py
+++ b/cobbler/pxegen.py
@@ -62,6 +62,7 @@ class PXEGen:
self.images = config.images()
self.templar = templar.Templar(config)
self.bootloc = utils.tftpboot_location()
+ self.verbose = False
def copy_bootloaders(self):
"""
@@ -73,27 +74,27 @@ class PXEGen:
# copy syslinux from one of two locations
try:
- utils.copyfile_pattern('/usr/lib/syslinux/pxelinux.0', dst, api=self.api)
+ utils.copyfile_pattern('/usr/lib/syslinux/pxelinux.0', dst, api=self.api, verbose=self.verbose)
except:
- utils.copyfile_pattern('/usr/share/syslinux/pxelinux.0', dst, api=self.api)
+ utils.copyfile_pattern('/usr/share/syslinux/pxelinux.0', dst, api=self.api, verbose=self.verbose)
# copy memtest only if we find it
- utils.copyfile_pattern('/boot/memtest*', dst, require_match=False, api=self.api)
+ utils.copyfile_pattern('/boot/memtest*', dst, require_match=False, api=self.api, verbose=self.verbose)
# copy elilo which we include for IA64 targets
- utils.copyfile_pattern('/var/lib/cobbler/elilo-3.8-ia64.efi', dst, api=self.api)
+ utils.copyfile_pattern('/var/lib/cobbler/elilo-3.8-ia64.efi', dst, api=self.api, verbose=self.verbose)
# copy menu.c32 as the older one has some bugs on certain RHEL
- utils.copyfile_pattern('/var/lib/cobbler/menu.c32', dst, api=self.api)
+ utils.copyfile_pattern('/var/lib/cobbler/menu.c32', dst, api=self.api, verbose=self.verbose)
# copy yaboot which we include for PowerPC targets
- utils.copyfile_pattern('/var/lib/cobbler/yaboot-1.3.14', dst, api=self.api)
+ utils.copyfile_pattern('/var/lib/cobbler/yaboot-1.3.14', dst, api=self.api, verbose=self.verbose)
# copy memdisk as we need it to boot ISOs
try:
- utils.copyfile_pattern('/usr/lib/syslinux/memdisk', dst, api=self.api)
+ utils.copyfile_pattern('/usr/lib/syslinux/memdisk', dst, api=self.api, verbose=self.verbose)
except:
- utils.copyfile_pattern('/usr/share/syslinux/memdisk', dst, api=self.api)
+ utils.copyfile_pattern('/usr/share/syslinux/memdisk', dst, api=self.api, verbose=self.verbose)
def copy_distros(self):
@@ -109,6 +110,8 @@ class PXEGen:
errors = list()
for d in self.distros:
try:
+ if self.verbose:
+ print "- copying files for distro: %s" % d.name
self.copy_single_distro_files(d)
except CX, e:
errors.append(e)
@@ -125,6 +128,8 @@ class PXEGen:
errors = list()
for i in self.images:
try:
+ if self.verbose:
+ print "- copying files for image: %s" % i.name
self.copy_single_image_files(i)
except CX, e:
errors.append(e)
@@ -152,9 +157,9 @@ class PXEGen:
allow_symlink=True
dst1 = os.path.join(distro_dir, b_kernel)
dst2 = os.path.join(distro_dir, b_initrd)
- utils.linkfile(kernel, dst1, symlink_ok=allow_symlink, api=self.api)
+ utils.linkfile(kernel, dst1, symlink_ok=allow_symlink, api=self.api, verbose=self.verbose)
- utils.linkfile(initrd, dst2, symlink_ok=allow_symlink, api=self.api)
+ utils.linkfile(initrd, dst2, symlink_ok=allow_symlink, api=self.api, verbose=self.verbose)
def copy_single_image_files(self, img):
images_dir = os.path.join(self.bootloc, "images2")
@@ -166,7 +171,7 @@ class PXEGen:
os.makedirs(images_dir)
basename = os.path.basename(img.file)
newfile = os.path.join(images_dir, img.name)
- utils.linkfile(filename, newfile, api=self.api)
+ utils.linkfile(filename, newfile, api=self.api, verbose=self.verbose)
return True
def write_all_system_files(self,system):
@@ -240,7 +245,8 @@ class PXEGen:
utils.rmfile(f2)
def make_pxe_menu(self):
- self.make_s390_pseudo_pxe_menu()
+ # FIXME: not used for now, future feature?
+ # self.make_s390_pseudo_pxe_menu()
self.make_actual_pxe_menu()
def make_s390_pseudo_pxe_menu(self):
diff --git a/cobbler/utils.py b/cobbler/utils.py
index fece9476..e5b3db6a 100644
--- a/cobbler/utils.py
+++ b/cobbler/utils.py
@@ -822,7 +822,7 @@ def is_safe_to_hardlink(src,dst,api):
# we're dealing with SELinux and files that are not safe to chcon
return False
-def linkfile(src, dst, symlink_ok=False, api=None):
+def linkfile(src, dst, symlink_ok=False, api=None, verbose=False):
"""
Attempt to create a link dst that points to src. Because file
systems suck we attempt several different methods or bail to
@@ -843,25 +843,30 @@ def linkfile(src, dst, symlink_ok=False, api=None):
if not is_safe_to_hardlink(src,dst,api):
# may have to remove old hardlinks for SELinux reasons
# as previous implementations were not complete
- os.remove(dst)
+ if verbose:
+ print "- removing: %s" % dst
+ os.remove(dst)
else:
- restorecon(dst,api=api)
+ # restorecon(dst,api=api,verbose=verbose)
return True
elif os.path.islink(dst):
# existing path exists and is a symlink, update the symlink
+ if verbose:
+ print "- removing: %s" % dst
os.remove(dst)
if is_safe_to_hardlink(src,dst,api):
# we can try a hardlink if the destination isn't to NFS or Samba
# this will help save space and sync time.
try:
+ if verbose:
+ print "- trying hardlink %s -> %s" % (src,dst)
rc = os.link(src, dst)
- restorecon(dst,api=api)
+ # restorecon(dst,api=api,verbose=verbose)
return rc
except (IOError, OSError):
# hardlink across devices, or link already exists
- # can result in extra call to restorecon but no
- # major harm, we'll just symlink it if we can
+ # we'll just symlink it if we can
# or otherwise copy it
pass
@@ -869,20 +874,24 @@ def linkfile(src, dst, symlink_ok=False, api=None):
# we can symlink anywhere except for /tftpboot because
# that is run chroot, so if we can symlink now, try it.
try:
+ if verbose:
+ print "- trying symlink %s -> %s" % (src,dst)
rc = os.symlink(src, dst)
- restorecon(dst,api=api)
+ # restorecon(dst,api=api,verbose=verbose)
return rc
except (IOError, OSError):
pass
# we couldn't hardlink and we couldn't symlink so we must copy
- return copyfile(src, dst, api=api)
+ return copyfile(src, dst, api=api, verbose=verbose)
-def copyfile(src,dst,api=None):
+def copyfile(src,dst,api=None,verbose=False):
try:
+ if verbose:
+ print "- copying: %s -> %s" % (src,dst)
rc = shutil.copyfile(src,dst)
- restorecon(dst,api)
+ # restorecon(dst,api,verbose=verbose)
return rc
except:
if not os.access(src,os.R_OK):
@@ -894,40 +903,44 @@ def copyfile(src,dst,api=None):
# traceback.print_exc()
# raise CX(_("Error copying %(src)s to %(dst)s") % { "src" : src, "dst" : dst})
-def copyfile_pattern(pattern,dst,require_match=True,symlink_ok=False,api=None):
+def copyfile_pattern(pattern,dst,require_match=True,symlink_ok=False,api=None, verbose=False):
files = glob.glob(pattern)
if require_match and not len(files) > 0:
raise CX(_("Could not find files matching %s") % pattern)
for file in files:
base = os.path.basename(file)
dst1 = os.path.join(dst,os.path.basename(file))
- linkfile(file,dst1,symlink_ok=symlink_ok,api=api)
- restorecon(dst1,api=api)
+ linkfile(file,dst1,symlink_ok=symlink_ok,api=api,verbose=verbose)
+ # restorecon(dst1,api=api,verbose=verbose)
-def restorecon(dest, api):
-
- """
- Wrapper around functions to manage SELinux contexts.
- Use chcon public_content_t where we can to allow
- hardlinking between /var/www and tftpboot but use
- restorecon everywhere else.
- """
-
- if not api.is_selinux_enabled():
- return True
-
- tdest = os.path.realpath(dest)
- # remoted = is_remote_file(tdest)
-
- cmd = [ "/sbin/restorecon",dest ]
- rc = sub_process.call(cmd,shell=False,close_fds=True)
- if rc != 0:
- raise CX("restorecon operation failed: %s" % cmd)
-
- return 0
+#def restorecon(dest, api, verbose=False):
+#
+# """
+# Wrapper around functions to manage SELinux contexts.
+# Use chcon public_content_t where we can to allow
+# hardlinking between /var/www and tftpboot but use
+# restorecon everywhere else.
+# """
+#
+# if not api.is_selinux_enabled():
+# return True
+#
+# tdest = os.path.realpath(dest)
+# # remoted = is_remote_file(tdest)
+#
+# cmd = [ "/sbin/restorecon",dest ]
+# if verbose:
+# print "- %s" % " ".join(cmd)
+# rc = sub_process.call(cmd,shell=False,close_fds=True)
+# if rc != 0:
+# raise CX("restorecon operation failed: %s" % cmd)
+#
+# return 0
-def rmfile(path):
+def rmfile(path,verbose=False):
try:
+ if verbose:
+ print "- removing: %s" % path
os.unlink(path)
return True
except OSError, ioe:
@@ -936,16 +949,18 @@ def rmfile(path):
raise CX(_("Error deleting %s") % path)
return True
-def rmtree_contents(path):
+def rmtree_contents(path,verbose=False):
what_to_delete = glob.glob("%s/*" % path)
for x in what_to_delete:
- rmtree(x)
+ rmtree(x,verbose=verbose)
-def rmtree(path):
+def rmtree(path,verbose=False):
try:
if os.path.isfile(path):
- return rmfile(path)
+ return rmfile(path,verbose=verbose)
else:
+ if verbose:
+ print "- removing: %s" % path
return shutil.rmtree(path,ignore_errors=True)
except OSError, ioe:
traceback.print_exc()
@@ -953,8 +968,10 @@ def rmtree(path):
raise CX(_("Error deleting %s") % path)
return True
-def mkdir(path,mode=0777):
+def mkdir(path,mode=0777,verbose=False):
try:
+ if verbose:
+ "- mkdir: %s" % path
return os.makedirs(path,mode)
except OSError, oe:
if not oe.errno == 17: # already exists (no constant for 17?)
diff --git a/triggers/restart-services.trigger b/triggers/restart-services.trigger
index 5f77b4d8..82dc0427 100644
--- a/triggers/restart-services.trigger
+++ b/triggers/restart-services.trigger
@@ -14,7 +14,7 @@ omapi_enabled = settings.omapi_enabled
omapi_port = settings.omapi_port
# load up our DHCP and DNS modules
-bootapi.get_sync()
+bootapi.get_sync(verbose=False)
# bootapi.dhcp and bootapi.dns are now module references
# special handling as we don't want to restart it twice