summaryrefslogtreecommitdiffstats
path: root/cobbler
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@mdehaan.rdu.redhat.com>2007-04-03 18:18:58 -0400
committerMichael DeHaan <mdehaan@mdehaan.rdu.redhat.com>2007-04-03 18:18:58 -0400
commit9fe68fb4b0befc4a0692ebe21a4d6492bf0d654b (patch)
treee33fbcd1ee18f18f9d00a8c45f10d2076cb3925a /cobbler
parent97b9c3735f4cd4f421e2226e413a924517b8f968 (diff)
downloadthird_party-cobbler-9fe68fb4b0befc4a0692ebe21a4d6492bf0d654b.tar.gz
third_party-cobbler-9fe68fb4b0befc4a0692ebe21a4d6492bf0d654b.tar.xz
third_party-cobbler-9fe68fb4b0befc4a0692ebe21a4d6492bf0d654b.zip
Add preliminary support for RHEL5 tree management. This is rather
complicated and introduces a new variable source_repos on each 'distro' object and also has some implications for how sync completes. Basically RHEL5 has multiple comps files so createrepo must be run more than once. The main point of this support is to install and configure the "core" mirror for distros, where previously only extras/updates were dealt with. The core repo is derived from the kickstart tree (cobbler import) rather than the "cobbler repo add" commands (manual add).
Diffstat (limited to 'cobbler')
-rw-r--r--cobbler/action_import.py166
-rw-r--r--cobbler/action_sync.py22
-rw-r--r--cobbler/item_distro.py14
3 files changed, 154 insertions, 48 deletions
diff --git a/cobbler/action_import.py b/cobbler/action_import.py
index d1b84d3..669c2f1 100644
--- a/cobbler/action_import.py
+++ b/cobbler/action_import.py
@@ -43,6 +43,7 @@ class Importer:
self.profiles = config.profiles()
self.systems = config.systems()
self.settings = config.settings()
+ self.distros_added = []
# ----------------------------------------------------------------------
@@ -77,10 +78,16 @@ class Importer:
self.processed_repos = {}
- os.path.walk(self.path, self.walker, None)
+ print "---------------- (adding distros)"
+ os.path.walk(self.path, self.distro_adder, {})
- self.guess_kickstarts()
-
+ print "---------------- (associating repos)"
+ self.repo_finder()
+
+ print "---------------- (associating kickstarts)"
+ self.kickstart_finder()
+
+ print "---------------- (syncing)"
self.api.sync()
return True
@@ -91,7 +98,7 @@ class Importer:
try:
os.makedirs(dir)
except:
- print "- didn't create %s" % dir
+ pass
# ----------------------------------------------------------------------
@@ -104,7 +111,7 @@ class Importer:
# ----------------------------------------------------------------------
- def guess_kickstarts(self):
+ def kickstart_finder(self):
"""
For all of the profiles in the config w/o a kickstart, look
@@ -120,10 +127,6 @@ class Importer:
# this isn't a mirrored profile, so we won't touch it
print "- skipping %s since profile isn't mirrored" % profile.name
continue
- if distro.ks_meta.has_key("tree") or profile.ks_meta.has_key("tree"):
- # this distro has already been imported, do not proceed
- print "- skipping %s since existing tree attributes were found" % profile.name
- continue
kdir = os.path.dirname(distro.kernel)
base_dir = "/".join(kdir.split("/")[0:-2])
@@ -159,9 +162,11 @@ class Importer:
if not os.path.exists(dest_link):
os.symlink(base, dest_link)
base = base.replace(self.settings.webdir,"")
- tree = "tree=http://%s/cblr/links/%s" % (self.settings.server, distro.name)
- print "- %s" % tree
- distro.set_ksmeta(tree)
+
+ meta = distro.ks_meta
+ meta["tree"] = "http://%s/cblr/links/%s" % (self.settings.server, distro.name)
+ print "- tree: %s" % meta["tree"]
+ distro.set_ksmeta(meta)
# ---------------------------------------------------------------------
@@ -198,28 +203,32 @@ class Importer:
if rpm.find(x) != -1:
return ("redhat", 2, 0)
- print "- scanning rpm: %s" % rpm
- (first, rest) = rpm.split("-release-")
- flavor = first.lower()
-
- # if there's still a hypen in the filename, get the trailing part.
- rdx = rest.find("-")
- if rdx != -1:
- rest = rest[rdx+1:]
-
- # if there's still a hypen in the filename, get the beginning part
- rdx = rest.rfind("-")
- if rdx != -1:
- rest = rest[:rdx-1]
-
- tokens = rest.split(".")
- major = float(tokens[0])
- minor = float(tokens[1])
+ # now get the flavor:
+ flavor = "redhat"
+ if rpm.lower().find("fedora") != -1:
+ flavor = "fedora"
+ if rpm.lower().find("centos") != -1:
+ flavor = "centos"
+
+ # get all the tokens and try to guess a version
+ accum = []
+ tokens = rpm.split(".")
+ for t in tokens:
+ tokens2 = t.split("-")
+ for t2 in tokens2:
+ try:
+ float(t2)
+ accum.append(t2)
+ except:
+ pass
+
+ major = float(accum[0])
+ minor = float(accum[1])
return (flavor, major, minor)
# ----------------------------------------------------------------------
- def walker(self,foo,dirname,fnames):
+ def distro_adder(self,foo,dirname,fnames):
initrd = None
kernel = None
@@ -231,27 +240,89 @@ class Importer:
initrd = os.path.join(dirname,x)
if x.startswith("vmlinuz"):
kernel = os.path.join(dirname,x)
- if initrd is not None and kernel is not None:
- self.last_distro = self.add_entry(dirname,kernel,initrd)
- path_parts = kernel.split("/")[:-3]
+ if initrd is not None and kernel is not None and dirname.find("isolinux") == -1:
+ self.add_entry(dirname,kernel,initrd)
+ path_parts = kernel.split("/")[:-2]
comps_path = "/".join(path_parts)
- print "- running repo update on %s" % comps_path
- self.process_comps_file(comps_path)
+
+ # ----------------------------------------------------------------------
+
+ def repo_finder(self):
+
+ for distro in self.distros_added:
+ print "- traversing distro %s" % distro.name
+ if distro.kernel.find("ks_mirror") != -1:
+ basepath = os.path.dirname(distro.kernel)
+ top = "/".join(basepath.split("/")[0:-3]) # up one level
+ print "- descent into %s" % top
+ os.path.walk(top, self.repo_scanner, distro)
+ else:
+ print "- this distro isn't mirrored"
+
+ # ----------------------------------------------------------------------
+
+ def repo_scanner(self,distro,dirname,fnames):
+
+ for x in fnames:
+ if x == "repodata":
+ self.process_comps_file(dirname, distro)
+ continue
+
# ----------------------------------------------------------------------
- def process_comps_file(self, comps_path):
+ def process_comps_file(self, comps_path, distro):
+ print "- scanning: %s (distro: %s)" % (comps_path, distro.name)
+
+ repo_file = os.path.join(comps_path, "repodata", "repomd.xml")
+ if not os.path.exists(repo_file):
+ raise RuntimeError, "no repomd found"
+
+ # figure out what our comps file is ...
+ print "- looking for %s/repodata/comps*.xml" % comps_path
+ files = glob.glob("%s/repodata/comps*.xml" % comps_path)
+ if len(files) == 0:
+ raise RuntimeError, "no comps files here: %s" % comps_path
+ # pull the filename from the longer part
+ comps_file = files[0].split("/")[-1]
- comps_file = os.path.join(comps_path, "repodata", "comps.xml")
- if not os.path.exists(comps_file):
- print "- no comps file found: %s" % comps_file
- return
try:
+
+ # store the location of the RPMs in the distro object.
+ # this is so sync can find it later.
+ # FIXME: can't really do that as there right be more than one.
+
+
+ counter = len(distro.source_repos)
+
+ # find path segment for yum_url (changing filesystem path to http:// trailing fragment)
+ seg = comps_path.rfind("ks_mirror")
+ urlseg = comps_path[seg+10:]
+
+ # write a yum config file that shows how to use the repo.
+ if counter == 0:
+ dotrepo = "%s.repo" % distro.name
+ else:
+ dotrepo = "%s-%s.repo" % (distro.name, counter)
+
+ fname = os.path.join(self.settings.webdir, "ks_mirror", "config", "%s-%s.repo" % (distro.name, counter))
+ repo_url = "http://%s/cobbler/ks_mirror/config/%s-%s.repo" % (self.settings.server, distro.name, counter)
+ distro.source_repos.append(repo_url)
+
+ print "- url: %s" % repo_url
+ config_file = open(fname, "w+")
+ config_file.write("[%s]\n" % "core-%s" % counter)
+ config_file.write("name=%s\n" % "core-%s " % counter)
+ config_file.write("baseurl=http://%s/cobbler/ks_mirror/%s\n" % (self.settings.server, urlseg))
+ config_file.write("enabled=1\n")
+ config_file.write("gpgcheck=0\n")
+ config_file.close()
+
# don't run creatrepo twice -- this can happen easily for Xen and PXE, when
# they'll share same repo files.
if not self.processed_repos.has_key(comps_path):
- cmd = "createrepo --basedir / --groupfile %s %s" % (comps_file, comps_path)
+ cmd = "createrepo --basedir / --groupfile %s %s" % (os.path.join(comps_path, "repodata", comps_file), comps_path)
print "- %s" % cmd
sub_process.call(cmd,shell=True)
self.processed_repos[comps_path] = 1
@@ -277,8 +348,10 @@ class Importer:
distro.set_kernel(kernel)
distro.set_initrd(initrd)
distro.set_arch(pxe_arch)
+ distro.source_repos = []
self.distros.add(distro)
-
+ self.distros_added.append(distro)
+
existing_profile = self.profiles.find(name)
if existing_profile is None:
@@ -300,14 +373,13 @@ class Importer:
name = "-".join(dirname.split("/"))
if name.startswith("-"):
name = name[1:]
+ name = name.replace("-os","")
+ name = name.replace("-images","")
+ name = name.replace("-tree","")
name = name.replace("var-www-cobbler-", "")
name = name.replace("ks_mirror-","")
- name = name.replace("os-images-","")
- name = name.replace("tree-images-","")
- name = name.replace("images-","")
- name = name.replace("tree-","")
- name = name.replace("--","-")
name = name.replace("-pxeboot","")
+ name = name.replace("--","-")
return name
def get_pxe_arch(self,dirname):
diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py
index 2f8902a..1559b64 100644
--- a/cobbler/action_sync.py
+++ b/cobbler/action_sync.py
@@ -389,6 +389,15 @@ class BootSync:
continue
http_url = "http://%s/cblr/repo_mirror/%s" % (self.settings.server, repo.name)
buf = buf + "repo --name=%s --baseurl=%s\n" % (repo.name, http_url)
+ distro = self.distros.find(profile.distro)
+
+ # tack on all the install source repos IF there is more than one.
+ # this is basically to support things like RHEL5 split trees
+ # if there is only one, then there is no need to do this.
+ if len(distro.source_repos) > 1:
+ for r in distro.source_repos:
+ buf = buf + "%s\n" % r
+
return buf
def generate_config_stanza(self, profile):
@@ -401,6 +410,19 @@ class BootSync:
continue
if not (repo.local_filename is None) or (repo.local_filename == ""):
buf = buf + "wget http://%s/cblr/repo_mirror/%s/config.repo --output-document=/etc/yum.repos.d/%s.repo\n" % (self.settings.server, repo.name, repo.local_filename)
+
+ # now install the core repos
+ distro = self.distros.find(profile.distro)
+ for r in distro.source_repos:
+ short = r.split("/")[-1]
+ buf = buf + "wget %s --output-document=/etc/yum.repos.d/%s.repo\n" % (r, short)
+
+ # if there were any core repos, install the voodoo to disable the OS public core
+ # location
+ if len(distro.source_repos) > 0:
+ for x in ["fedora-core", "Centos-Base", "rhel-core"] :
+ buf = buf + "mv /etc/yum.repos.d/%s.repo /etc/yum.repos.d/disabled-%s\n" % (x,x)
+
return buf
def validate_kickstarts_per_system(self):
diff --git a/cobbler/item_distro.py b/cobbler/item_distro.py
index 48e28ea..c4c115f 100644
--- a/cobbler/item_distro.py
+++ b/cobbler/item_distro.py
@@ -40,6 +40,7 @@ class Distro(item.Item):
self.ks_meta = {}
self.arch = "x86"
self.breed = "redhat"
+ self.source_repos = []
def from_datastruct(self,seed_data):
"""
@@ -52,6 +53,8 @@ class Distro(item.Item):
self.ks_meta = self.load_item(seed_data,'ks_meta')
self.arch = self.load_item(seed_data,'arch','x86')
self.breed = self.load_item(seed_data,'breed','redhat')
+ self.source_repos = self.load_item(seed_data,'source_repos',[])
+
# backwards compatibility -- convert string entries to dicts for storage
if type(self.kernel_options) != dict:
self.set_kernel_options(self.kernel_options)
@@ -88,6 +91,14 @@ class Distro(item.Item):
return True
raise cexceptions.CobblerException("no_initrd")
+ def set_source_repos(self, repos):
+ """
+ A list of http:// URLs on the cobbler server that point to
+ yum configuration files that can be used to
+ install core packages. Use by cobbler import only.
+ """
+ self.source_repos = repos
+
def set_arch(self,arch):
"""
The field is mainly relevant to PXE provisioning.
@@ -130,7 +141,8 @@ class Distro(item.Item):
'kernel_options' : self.kernel_options,
'ks_meta' : self.ks_meta,
'arch' : self.arch,
- 'breed' : self.breed
+ 'breed' : self.breed,
+ 'source_repos' : self.source_repos
}
def printable(self):