Merge lp:~andreserl/ubuntu/natty/cobbler/lp731620 into lp:ubuntu/natty/cobbler

Proposed by Andres Rodriguez
Status: Superseded
Proposed branch: lp:~andreserl/ubuntu/natty/cobbler/lp731620
Merge into: lp:ubuntu/natty/cobbler
Diff against target: 55544 lines (+53908/-0) (has conflicts)
301 files modified
.bzrignore (+1/-0)
AUTHORS (+95/-0)
CHANGELOG (+912/-0)
COPYING (+340/-0)
MANIFEST.in (+13/-0)
README (+9/-0)
aux/anamon (+280/-0)
aux/anamon.init (+101/-0)
cobbler.spec (+266/-0)
cobbler/action_acl.py (+120/-0)
cobbler/action_buildiso.py (+447/-0)
cobbler/action_check.py (+482/-0)
cobbler/action_dlcontent.py (+96/-0)
cobbler/action_hardlink.py (+60/-0)
cobbler/action_import.py (+1332/-0)
cobbler/action_litesync.py (+167/-0)
cobbler/action_log.py (+71/-0)
cobbler/action_power.py (+150/-0)
cobbler/action_replicate.py (+357/-0)
cobbler/action_report.py (+365/-0)
cobbler/action_reposync.py (+568/-0)
cobbler/action_status.py (+172/-0)
cobbler/action_sync.py (+259/-0)
cobbler/action_validate.py (+119/-0)
cobbler/api.py (+947/-0)
cobbler/cexceptions.py (+44/-0)
cobbler/cli.py (+553/-0)
cobbler/clogger.py (+89/-0)
cobbler/cobblerd.py (+145/-0)
cobbler/codes.py (+98/-0)
cobbler/collection.py (+444/-0)
cobbler/collection_distros.py (+103/-0)
cobbler/collection_files.py (+63/-0)
cobbler/collection_images.py (+78/-0)
cobbler/collection_mgmtclasses.py (+64/-0)
cobbler/collection_packages.py (+63/-0)
cobbler/collection_profiles.py (+82/-0)
cobbler/collection_repos.py (+77/-0)
cobbler/collection_systems.py (+69/-0)
cobbler/config.py (+298/-0)
cobbler/configgen.py (+156/-0)
cobbler/couch.py (+101/-0)
cobbler/field_info.py (+170/-0)
cobbler/func_utils.py (+34/-0)
cobbler/item.py (+407/-0)
cobbler/item_distro.py (+246/-0)
cobbler/item_file.py (+82/-0)
cobbler/item_image.py (+197/-0)
cobbler/item_mgmtclass.py (+64/-0)
cobbler/item_package.py (+64/-0)
cobbler/item_profile.py (+240/-0)
cobbler/item_repo.py (+198/-0)
cobbler/item_system.py (+676/-0)
cobbler/kickgen.py (+200/-0)
cobbler/module_loader.py (+106/-0)
cobbler/modules/add_post_distro_tftp_copy_fetchable_files.py (+53/-0)
cobbler/modules/authn_configfile.py (+84/-0)
cobbler/modules/authn_denyall.py (+51/-0)
cobbler/modules/authn_ldap.py (+136/-0)
cobbler/modules/authn_passthru.py (+47/-0)
cobbler/modules/authn_spacewalk.py (+154/-0)
cobbler/modules/authn_testing.py (+50/-0)
cobbler/modules/authz_allowall.py (+50/-0)
cobbler/modules/authz_configfile.py (+65/-0)
cobbler/modules/authz_ownership.py (+205/-0)
cobbler/modules/install_post_log.py (+51/-0)
cobbler/modules/install_post_power.py (+53/-0)
cobbler/modules/install_post_report.py (+101/-0)
cobbler/modules/install_pre_clear_anamon_logs.py (+74/-0)
cobbler/modules/install_pre_log.py (+31/-0)
cobbler/modules/manage_bind.py (+332/-0)
cobbler/modules/manage_dnsmasq.py (+205/-0)
cobbler/modules/manage_import_debian.old (+727/-0)
cobbler/modules/manage_import_debian_ubuntu.py (+777/-0)
cobbler/modules/manage_import_redhat.py (+972/-0)
cobbler/modules/manage_import_ubuntu.old (+727/-0)
cobbler/modules/manage_import_vmware.py (+862/-0)
cobbler/modules/manage_in_tftpd.py (+144/-0)
cobbler/modules/manage_isc.py (+201/-0)
cobbler/modules/manage_tftpd_py.py (+109/-0)
cobbler/modules/scm_track.py (+109/-0)
cobbler/modules/serializer_catalog.py (+241/-0)
cobbler/modules/serializer_couch.py (+136/-0)
cobbler/modules/sync_post_restart_services.py (+66/-0)
cobbler/modules/sync_post_tftp_copy_fetchable_files.py (+48/-0)
cobbler/pxegen.py (+836/-0)
cobbler/remote.py (+2547/-0)
cobbler/resource.py (+75/-0)
cobbler/serializer.py (+168/-0)
cobbler/services.py (+462/-0)
cobbler/settings.py (+170/-0)
cobbler/sub_process.py (+1149/-0)
cobbler/templar.py (+171/-0)
cobbler/template_api.py (+212/-0)
cobbler/test_basic.py (+894/-0)
cobbler/utils.py (+2071/-0)
cobbler/yumgen.py (+120/-0)
cobbler4j/.classpath (+9/-0)
cobbler4j/.externalToolBuilders/Ant Builder.launch (+18/-0)
cobbler4j/.project (+23/-0)
cobbler4j/README (+24/-0)
cobbler4j/build.py (+143/-0)
cobbler4j/build.xml (+61/-0)
cobbler4j/notes.txt (+458/-0)
cobbler4j/object_base.tmpl (+145/-0)
cobbler4j/pom.xml (+130/-0)
cobbler4j/src/main/java/org/fedorahosted/cobbler/CobblerConnection.java (+106/-0)
cobbler4j/src/main/java/org/fedorahosted/cobbler/CobblerObject.java (+238/-0)
cobbler4j/src/main/java/org/fedorahosted/cobbler/Finder.java (+118/-0)
cobbler4j/src/main/java/org/fedorahosted/cobbler/ObjectType.java (+46/-0)
cobbler4j/src/main/java/org/fedorahosted/cobbler/PropertyLoader.java (+56/-0)
cobbler4j/src/main/java/org/fedorahosted/cobbler/XmlRpcException.java (+51/-0)
cobbler4j/src/test/java/org/fedorahosted/cobbler/test/Config.java (+44/-0)
cobbler4j/src/test/java/org/fedorahosted/cobbler/test/DistroTests.java (+107/-0)
cobbler4j/src/test/java/org/fedorahosted/cobbler/test/FinderTests.java (+25/-0)
cobbler4j/src/test/java/org/fedorahosted/cobbler/test/Fixture.java (+34/-0)
cobbler4j/src/test/java/org/fedorahosted/cobbler/test/ProfileTests.java (+119/-0)
cobbler4j/src/test/java/org/fedorahosted/cobbler/test/RepoTests.java (+106/-0)
cobbler4j/user.properties.sample (+6/-0)
config/auth.conf (+2/-0)
config/cheetah_macros (+2/-0)
config/cobbler.conf (+32/-0)
config/cobbler_bash (+87/-0)
config/cobbler_web.conf (+27/-0)
config/cobblerd (+141/-0)
config/cobblerd_rotate (+28/-0)
config/completions (+508/-0)
config/modules.conf (+86/-0)
config/rsync.exclude (+12/-0)
config/settings (+342/-0)
config/users.conf (+28/-0)
config/users.digest (+1/-0)
contrib/cobbler_sync_master (+193/-0)
debian/README.source (+8/-0)
debian/changelog (+92/-0)
debian/cobbler-common.dirs (+12/-0)
debian/cobbler-common.install (+50/-0)
debian/cobbler-web.install (+2/-0)
debian/cobbler-web.postinst (+22/-0)
debian/cobbler-web.postrm (+20/-0)
debian/cobbler.dirs (+2/-0)
debian/cobbler.docs (+1/-0)
debian/cobbler.install (+4/-0)
debian/cobbler.postinst (+8/-0)
debian/cobbler.postrm (+8/-0)
debian/cobbler.upstart (+14/-0)
debian/compat (+1/-0)
debian/control (+132/-0)
debian/copyright (+452/-0)
debian/koan.dirs (+3/-0)
debian/koan.install (+4/-0)
debian/libcobbler4j-java.jlibs (+1/-0)
debian/patches/05_cobbler_fix_reposync_permissions.patch (+12/-0)
debian/patches/12_fix_dhcp_restart.patch (+12/-0)
debian/patches/21_cobbler_use_netboot.patch (+17/-0)
debian/patches/30_cobbler4j_redstone.patch (+21/-0)
debian/patches/31_add_ubuntu_koan_utils_support.patch (+35/-0)
debian/patches/32_fix_koan_import_yum.patch (+60/-0)
debian/patches/series (+6/-0)
debian/pycompat (+1/-0)
debian/python-cobbler.install (+1/-0)
debian/python-cobbler.postinst (+12/-0)
debian/rules (+47/-0)
debian/source/format (+1/-0)
docs/cobbler-register.pod (+39/-0)
docs/cobbler.pod (+993/-0)
docs/koan.pod (+112/-0)
kickstarts/default.ks (+2/-0)
kickstarts/legacy.ks (+62/-0)
kickstarts/pxerescue.ks (+15/-0)
kickstarts/sample.ks (+69/-0)
kickstarts/sample.seed (+96/-0)
kickstarts/sample_end.ks (+75/-0)
koan/app.py (+1656/-0)
koan/configurator.py (+307/-0)
koan/imagecreate.py (+192/-0)
koan/opt_parse.py (+1682/-0)
koan/qcreate.py (+212/-0)
koan/register.py (+196/-0)
koan/sub_process.py (+1149/-0)
koan/text_wrap.py (+354/-0)
koan/utils.py (+548/-0)
koan/vmwcreate.py (+175/-0)
koan/xencreate.py (+193/-0)
scripts/cobbler (+36/-0)
scripts/cobbler-ext-nodes (+21/-0)
scripts/cobbler-register (+19/-0)
scripts/cobblerd (+97/-0)
scripts/debuginator.py (+50/-0)
scripts/demo_connect.py (+44/-0)
scripts/index.py (+199/-0)
scripts/koan (+19/-0)
scripts/services.py (+99/-0)
scripts/tftpd.py (+1064/-0)
scripts/zpxe.rexx (+298/-0)
setup.cfg (+19/-0)
setup.py (+276/-0)
snippets/cobbler_register (+13/-0)
snippets/download_config_files (+18/-0)
snippets/func_install_if_enabled (+4/-0)
snippets/func_register_if_enabled (+26/-0)
snippets/keep_cfengine_keys (+97/-0)
snippets/keep_files (+156/-0)
snippets/keep_rhn_keys (+88/-0)
snippets/keep_ssh_host_keys (+107/-0)
snippets/kickstart_done (+76/-0)
snippets/kickstart_start (+32/-0)
snippets/koan_environment (+4/-0)
snippets/log_ks_post (+2/-0)
snippets/log_ks_pre (+12/-0)
snippets/main_partition_select (+3/-0)
snippets/network_config (+85/-0)
snippets/partition_select (+34/-0)
snippets/post_anamon (+23/-0)
snippets/post_install_kernel_options (+7/-0)
snippets/post_install_network_config (+372/-0)
snippets/post_koan_add_reinstall_entry (+6/-0)
snippets/post_s390_reboot (+67/-0)
snippets/pre_anamon (+4/-0)
snippets/pre_install_network_config (+92/-0)
snippets/pre_partition_select (+33/-0)
snippets/redhat_register (+18/-0)
templates/etc/dhcp.template (+62/-0)
templates/etc/dnsmasq.template (+20/-0)
templates/etc/named.template (+31/-0)
templates/etc/rsync.template (+43/-0)
templates/etc/tftpd.template (+19/-0)
templates/etc/zone.template (+13/-0)
templates/ldap/ldap_authconfig.template (+1/-0)
templates/power/power_apc_snmp.template (+1/-0)
templates/power/power_bladecenter.template (+1/-0)
templates/power/power_bullpap.template (+1/-0)
templates/power/power_drac.template (+4/-0)
templates/power/power_ether_wake.template (+9/-0)
templates/power/power_ilo.template (+2/-0)
templates/power/power_integrity.template (+1/-0)
templates/power/power_ipmilan.template (+2/-0)
templates/power/power_ipmitool.template (+1/-0)
templates/power/power_lpar.template (+3/-0)
templates/power/power_rsa.template (+1/-0)
templates/power/power_virsh.template (+32/-0)
templates/power/power_wti.template (+1/-0)
templates/pxe/efidefault.template (+4/-0)
templates/pxe/grubprofile.template (+4/-0)
templates/pxe/grubsystem.template (+4/-0)
templates/pxe/pxedefault.template (+15/-0)
templates/pxe/pxelocal.template (+9/-0)
templates/pxe/pxelocal_ia64.template (+4/-0)
templates/pxe/pxelocal_s390x.template (+1/-0)
templates/pxe/pxeprofile.template (+5/-0)
templates/pxe/pxeprofile_esxi.template (+6/-0)
templates/pxe/pxeprofile_s390x.template (+11/-0)
templates/pxe/pxesystem.template (+8/-0)
templates/pxe/pxesystem_esxi.template (+8/-0)
templates/pxe/pxesystem_ia64.template (+6/-0)
templates/pxe/pxesystem_ppc.template (+11/-0)
templates/pxe/pxesystem_s390x.template (+11/-0)
templates/pxe/s390x_conf.template (+77/-0)
templates/pxe/s390x_parm.template (+21/-0)
templates/reporting/build_report_email.template (+46/-0)
tests/multi.py (+29/-0)
tests/performance.py (+70/-0)
tests/pycallgraph_mod.py (+228/-0)
web/cobbler_web/templates/blank.tmpl (+12/-0)
web/cobbler_web/templates/check.tmpl (+14/-0)
web/cobbler_web/templates/empty.tmpl (+9/-0)
web/cobbler_web/templates/enoaccess.tmpl (+12/-0)
web/cobbler_web/templates/error_page.tmpl (+14/-0)
web/cobbler_web/templates/eventlog.tmpl (+14/-0)
web/cobbler_web/templates/events.tmpl (+33/-0)
web/cobbler_web/templates/generic_delete.tmpl (+27/-0)
web/cobbler_web/templates/generic_edit.tmpl (+536/-0)
web/cobbler_web/templates/generic_list.tmpl (+188/-0)
web/cobbler_web/templates/generic_rename.tmpl (+35/-0)
web/cobbler_web/templates/header.tmpl (+3/-0)
web/cobbler_web/templates/import.tmpl (+50/-0)
web/cobbler_web/templates/index.tmpl (+11/-0)
web/cobbler_web/templates/item.tmpl (+38/-0)
web/cobbler_web/templates/ksfile_edit.tmpl (+62/-0)
web/cobbler_web/templates/ksfile_list.tmpl (+32/-0)
web/cobbler_web/templates/master.tmpl (+84/-0)
web/cobbler_web/templates/message.tmpl (+13/-0)
web/cobbler_web/templates/paginate.tmpl (+186/-0)
web/cobbler_web/templates/settings.tmpl (+30/-0)
web/cobbler_web/templates/snippet_edit.tmpl (+72/-0)
web/cobbler_web/templates/snippet_list.tmpl (+31/-0)
web/cobbler_web/templates/task_created.tmpl (+10/-0)
web/cobbler_web/templatetags/site.py (+361/-0)
web/cobbler_web/urls.py (+47/-0)
web/cobbler_web/views.py (+1120/-0)
web/content/cobbler.js (+49/-0)
web/content/index.html (+10/-0)
web/content/jquery-1.3.2.js (+4376/-0)
web/content/jquery-1.3.2.min.js (+19/-0)
web/content/jsGrowl.css (+101/-0)
web/content/jsGrowl.js (+269/-0)
web/content/jsGrowl_jquery.js (+29/-0)
web/content/style.css (+47/-0)
web/manage.py (+11/-0)
web/settings.py (+69/-0)
web/urls.py (+18/-0)
Conflict adding file .bzrignore.  Moved existing file to .bzrignore.moved.
Conflict adding file AUTHORS.  Moved existing file to AUTHORS.moved.
Conflict adding file CHANGELOG.  Moved existing file to CHANGELOG.moved.
Conflict adding file COPYING.  Moved existing file to COPYING.moved.
Conflict adding file MANIFEST.in.  Moved existing file to MANIFEST.in.moved.
Conflict adding file README.  Moved existing file to README.moved.
Conflict adding file aux.  Moved existing file to aux.moved.
Conflict adding file cobbler.  Moved existing file to cobbler.moved.
Conflict adding file cobbler.spec.  Moved existing file to cobbler.spec.moved.
Conflict adding file cobbler4j.  Moved existing file to cobbler4j.moved.
Conflict adding file config.  Moved existing file to config.moved.
Conflict adding file contrib.  Moved existing file to contrib.moved.
Conflict adding file debian.  Moved existing file to debian.moved.
Conflict adding file diagrams.  Moved existing file to diagrams.moved.
Conflict adding file docs.  Moved existing file to docs.moved.
Conflict adding file kickstarts.  Moved existing file to kickstarts.moved.
Conflict adding file koan.  Moved existing file to koan.moved.
Conflict adding file scripts.  Moved existing file to scripts.moved.
Conflict adding file setup.cfg.  Moved existing file to setup.cfg.moved.
Conflict adding file setup.py.  Moved existing file to setup.py.moved.
Conflict adding file snippets.  Moved existing file to snippets.moved.
Conflict adding file templates.  Moved existing file to templates.moved.
Conflict adding file tests.  Moved existing file to tests.moved.
Conflict adding file web.  Moved existing file to web.moved.
To merge this branch: bzr merge lp:~andreserl/ubuntu/natty/cobbler/lp731620
Reviewer Review Type Date Requested Status
Chuck Short Pending
Review via email: mp+53091@code.launchpad.net

This proposal has been superseded by a proposal from 2011-03-11.

To post a comment you must log in.

Unmerged revisions

2009. By Andres Rodriguez

Update patch Descriptions

2008. By Andres Rodriguez

* debian/patches/32_fix_koan_import_yum.patch: Fix import error of yum
  python module; adds flexibility for other package managers. (LP: #731620)

2007. By Andres Rodriguez

debian/patches/31_add_ubuntu_koan_utils_support.patch: Add support for ubuntu
distro in koan utils.py.

2006. By Chuck Short

New release

2005. By Chuck Short

New upstream version

2004. By Chuck Short

* New upstream release
* Add python-koan package (LP: #731616):
  - debian/control: Add python-koan binary package; fix typo
  - debian/python-cobbler.install: Do not install koan python modules.
  - debian/python-koan.install: Add. Install koan python modules.

2003. By Chuck Short

Fake changelog

2002. By Chuck Short

Update changelog

2001. By Chuck Short

New upstream release

2000. By Chuck Short

Fix up get-orig-source a bit better

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.bzrignore'
2--- .bzrignore 1970-01-01 00:00:00 +0000
3+++ .bzrignore 2011-03-11 21:10:49 +0000
4@@ -0,0 +1,1 @@
5+.pc
6
7=== renamed file '.bzrignore' => '.bzrignore.moved'
8=== added file 'AUTHORS'
9--- AUTHORS 1970-01-01 00:00:00 +0000
10+++ AUTHORS 2011-03-11 21:10:49 +0000
11@@ -0,0 +1,95 @@
12+Cobbler, Koan, and Cobbler-Web are written & maintained by:
13+
14+ Michael DeHaan <mdehaan@redhat.com>
15+
16+Patches and other contributions from:
17+
18+ Partha Aji <paji@redhat.com>
19+ Anton Arapov <aarapov@redhat.com>
20+ Niels Basjes <cobbler@basjes.nl>
21+ Tim Bielawa <timbielawa@gmail.com>
22+ Joseph Boyer Jr. <jboyer@liquidnet.com>
23+ Andrew Brown <ambrown@ncsu.edu>
24+ David Brown <dmlb2000@gmail.com>
25+ James Bowes <jbowes@redhat.com>
26+ James Cammarata <jimi@sgnx.net>
27+ Jasper Capel <jcapel@redhat.com>
28+ C. Daniel Chase <dan@cdchase.com>
29+ Gordon Child <gordon@cpanel.net>
30+ Cristian Ciupitu <cristian.ciupitu@yahoo.com>
31+ Carsten Clasohm <cclasohm@redhat.com>
32+ Ian Ward Comfort <icomfort@rescomp.stanford.edu>
33+ Rob Crittenden <rcritten@redhat.com>
34+ Scott Dodson <sdodson@redhat.com>
35+ Charles Duffy <Charles_Duffy@messageone.com>
36+ Máirín Duffy <duffy@redhat.com>
37+ John Eckersberg <jeckersb@redhat.com>
38+ Lee Faus <lfaus@redhat.com>
39+ Leonid Flaks <flaks@bnl.gov>
40+ Eoghan Gaffney <eoghan@noroutetohost.org>
41+ Dan Guernsey <danpg102@gmail.com>
42+ Marcel Haerry <haerry+et@puzzle.ch>
43+ Peter Halliday <phalliday@excelsiorsystems.net>
44+ Niels Hasse <haase.niels@googlemail.com>
45+ Dave Hatton <dave@davehatton.it>
46+ Scott Henson <shenson@redhat.com>
47+ Garrett Holmstrom <garett.holmstrom@gmail.com>
48+ Stephan Hauiser <stephan@huiser.nl>
49+ Tru Huynh <tru@pasteur.fr>
50+ Matt Hyclak <hyclak@math.ohiou.edu>
51+ Mihai Ibanescu <mihai.ibanescu@gmail.com>
52+ Shuichi Ihara <ihara@sun.com>
53+ Pablo Iranzo Gómez <pablo.iranzo@redhat.com>
54+ Brian Kearney <bkearney@redhat.com>
55+ Henry Kemp <henrykemp@gmail.com>
56+ Ruben Kerkhof <ruben@rubenkerkhof.com>
57+ Don Khan <khan_don@emc.com>
58+ Dominic LoBue <git.20.dlobue@neverbox.com>
59+ Gavin Romig-Koch <gavin@redhat.com>
60+ James Laska <jlaska@redhat.com>
61+ Vito Laurenza <vitolaurenza@gmail.com>
62+ Adrian Likins <alikins@redhat.com>
63+ David Lutterkort <dlutter@redhat.com>
64+ Lester M. <needwork@gmail.com>
65+ Bryan Mason <bjmason@redhat.com>
66+ Mike McCune <mmccune@redhat.com>
67+ Mark McLoughlin <markmc@redhat.com>
68+ Jim Meyering <jim@meyering.net>
69+ Jeroen van Meeuwen <kanarip@kanarip.com>
70+ Sean Millichamp <sean@bruenor.org>
71+ Perry Myers <pmyers@redhat.com>
72+ Jack Neely <jjneely@ncsu.edu>
73+ Javier Palacious <javiplx@gmail.com>
74+ Bill Peck <bpeck@redhat.com>
75+ Lassi Pölönen <lassi.polonen@helsinki.fi>
76+ Jasper Poppe <jpoppe@ebay.com>
77+ Dan Radez <dradez@redhat.com>
78+ Ben Riggs <rigg0022@umn.edu>
79+ Jeremy Rosengren <jeremy@rosengren.org>
80+ Adam Rosenwald <thestrider@gmail.com>
81+ Christophe Sahut <csahut@nogoa.org>
82+ Satoru Satoh <ssato@redhat.com>
83+ Jeff Schroeder <jeffschroeder@computer.org>
84+ Scott Seago <sseago@redhat.com>
85+ Justin Sherill <jsherril@redhat.com>
86+ Anderson Silva <ansilva@redhat.com>
87+ Joe Smith <yasumoto7@gmail.com>
88+ Michael Stahnke <mastahnke@gmail.com>
89+ Dylan Swift <dylan.swift@gmail.com>
90+ Al Tobey <tobert@gmail.com>
91+ Thomas Uhde <thomas.uhde@KabelDeutschland.de>
92+ Ronald van den Blink <ronald@a61.nl>
93+ Tim Verhoeven <tim.verhoeven.be@gmail.com>
94+ John L. Villalovos <john@sodarock.com>
95+ Peter Vreman <peter.vreman@acision.com>
96+ Adam Wolf <adamwolf@feelslikeburning.com>
97+ Simon Woolsgrove <simon@woolsgrove.com>
98+ Todd Zullinger <tmz@pobox.com>
99+ Kelsey Hightower <kelsey.hightower@gmail.com>
100+ Chuck Short <chuck.short@canonical.com>
101+ Jonathan Sabo <jonathan.sabo@gmail.com>
102+ Douglas Kilpatrick <dkilpatrick@verisign.com>
103+
104+ [...send patches to get your name here...]
105+
106+
107
108=== renamed file 'AUTHORS' => 'AUTHORS.moved'
109=== added file 'CHANGELOG'
110--- CHANGELOG 1970-01-01 00:00:00 +0000
111+++ CHANGELOG 2011-03-11 21:10:49 +0000
112@@ -0,0 +1,912 @@
113+Cobbler CHANGELOG
114+- Nov 29 2010
115+- (FEAT) --force-path to overwrite virt-path file location
116+
117+- Apr 27 2010 - 2.0.4
118+- (BUGF) fetch extra metadata from upstream repositories more safely
119+- (BUGF) allow the creation of subprofiles again
120+- (BUGF) don't warn needlessly when repo rpm_list is empty
121+- (BUGF) run createrepo on partial yum mirrors
122+- (BUGF) change default mode for new directories from 0777 to 0755
123+- (BUGF) fix replication pruning to not prune systems when inappropriate
124+- (BUGF) always authorize the CLI
125+- (BUGF) fix passthru auth Trac#549
126+- (BUGF) fix for spacewalk bug 529277
127+- (BUGF) fix umask so files are not world writable
128+- (BUGF) fix default pxe template to support default system record
129+- (BUGF) redo the PXE menuif a profile is removed
130+- (BUGF) properly escape snippets
131+- (FEAT) Support Mercurial (hg) for scm tracking
132+
133+- Feb 15 2010 - 2.0.3.1
134+- (BUGF) Fix kernel command line parsing
135+
136+- Feb 12 2010 - 2.0.3
137+- (FEAT) API Test Framework
138+- (FEAT) Cobbler4j Eclipse bindings
139+- (BUGF) Trac544 Create noarch and src repos
140+- (BUGF) Snippet Cleanups
141+- (FEAT) Cleanup Kickstart Generation
142+- (FEAT) Ability to include remote kickstart content
143+- (FEAT) Koan ability for remote kickstart content
144+- (BUGF) Trac547 Profile Creation in WebUI
145+- (BUGF) Trac520 Sort HTML Dropdown Lists
146+- (BUGF) Allow koan to use http urls for kernel/initrd
147+- (FEAT) Cobbler4j now uses maven to build
148+- (FEAT) Allow multiple kernel options with the same name
149+- (BUGF) Various logging cleanups
150+- (BUGF) Exit with proper error codes
151+- (BUGF) Fix multiselect fields in the WUI
152+- (BUGF) Trac550 stop leaking FDs in subprocess_call
153+- (BUGF) Trac566 link distros on replicate
154+- (BUGF) Trac563 Replace dos line endings with unix line endings when saving ksdata
155+- (FEAT) Support RHEL6 kernel sizes
156+- (BUGF) Preserve hardlinks on replicate
157+- Full List 2b3a4f960b564691ca9a0470f677bd902f60b021..b99401d4dc6cf7f6c010eecf6c5d235316b59f73
158+
159+- Nov 23 2009 - 2.0.2
160+- (FEAT) Added support for Cobbler4j
161+- (FEAT) Added method for enabling autostart on qemu domains
162+- (BUGF) web ui: move sessions directory to /var
163+- (BUGF) Update the vlanpattern regex to cover more common virtual interface formats
164+- (BUGF) cobbler check: fix BIND detection
165+- (BUGF) Fix error message creating profile without a distro
166+- (BUGF) use proper HTTP error codes
167+- (BUGF) Create more intuitive system for displaying actions under configuration items.
168+- (BUGF) Fixed hardlinking
169+- (BUGF) Creating subprofile in WebUI no longer fails on default_ownership
170+- (BUGF) No longer delete excluded files in reposync rsync
171+- (BUGF) Add fedora12 and fedora13 as valid 'redhat' versions
172+- (BUGF) Correct improper distro creation while importing i386 Fedora/RHEL.
173+- (BUGF) Better messaging for invalid object errors
174+- (BUGF) Added a legacy sync mechanism
175+- (BUGF) No longer bundle libraries on distros where they are already available
176+
177+- Sep 18 2009 - 2.0.1
178+- (BUGF) Fixes for image based CLI usage and object validation
179+- (BUGF) Fix koan check for images ... they don't need a kickstart
180+- (BUGF) Get NFS image mounting working again
181+- (BUGF) Show object name on cobbler-web edit pages
182+- (BUGF) Make memtest integration look in the right file locations
183+- (BUGF) Fix check for dhcpd installation
184+- (BUGF) Fix code to detect dhcpd config file installation
185+- (BUGF) Cleaned up generated comments in settings files
186+- (BUGF) Unhide per-system post-install kernel options
187+- (BUGF) Unhide owners fields
188+- (BUGF) Fix "cobbler profile/system dumpvars" command
189+- (BUGF) Remove acl_engine reference from authz_configfile
190+- (BUGF) Add "View Kickstart" link back on profile list page
191+- (FEAT) Very Experimental CouchDB serializer, off by default. Touch /etc/cobbler/use.couch
192+- (BUGF) Fix pagination for webapp
193+- (BUGF) Widen left column for webapp to better show controls
194+- (BUGF) Workaround older mod_python scoping bug with utils.uniquify
195+- (BUGF) Fix interface additions from web system edit page for new systems
196+- (BUGF) Make cobbler reposync --only=N sync only that repo
197+- (BUGF) Mark cobbler_web.conf config(noreplace) in the RPM specfile
198+- (BUGF) Have cobbler check look for more SELinux things to do
199+- (BUGF) Fix saving of "static" network field in webapp
200+- (BUGF) Deepcopy interfaces to prevent copying of interface data
201+
202+- Sep 17 2009 - for 2.0 release
203+- Development release start
204+- (FEAT) add two new default flags to yum reposync (-m and -d) for grabbing comps automatically and also deleting duplicate RPMs
205+- (BUGF) validate gateway input against python-netaddr
206+- (FEAT) --kopts="~foo" --in-place can be used to delete a hash entry without affecting the others, not to be confused with "!foo" to supress it.
207+- (FEAT) web app moves to Django
208+- (FEAT) koan: Support for virt-autoboot feature (Xen only at this point, needs fixing)
209+- (FEAT) koan: use private address range for random MACs
210+- (FEAT) yum createrepo flags are now tweakable in settings
211+- (FEAT) new snippet for RHN Hosted: keep RHN keys between reinstalls
212+- (FEAT) allow per_distro snippets in addition to per_profile/per_system
213+- (BUGF) don't add port number to http_server if it's 80.
214+- (FEAT) support F11 fence-agent paths
215+- (BUGF) koan autodetection now can gather MACs/IPs for bridged interfaces better
216+- (FEAT) F11 and RAID support for keep_ssh_host_keys
217+- (FEAT) keep_ssh_host_keys gets F11+RAID support
218+- (FEAT) per-task logging
219+- (BUGF) validateks checkes /every/ kickstart, as different variables may be present
220+- (FEAT) CLI now speaks XMLRPC (faster)
221+- (FEAT) task engine for webapp
222+- (FEAT) background APIs for all actions
223+- (FEAT) look at ksdevice when building buildiso CDs to add the proper network lines
224+- (BUGF) don't use RPM to check os_version, so RPM won't be called in rpm %post
225+- (BUGF) deprecated omapi/omshell features for manage_isc now removed
226+- (FEAT) removed configuration files for binary paths, will look for in PATH
227+- (FEAT) removed configuration settings indicating where some config files are
228+- (FEAT) yum priorities plugin setting for distro repos now tweakable in settings
229+- (BUGF) unfinished contrib. debian import/repo support disabled until it can be finished
230+- (FEAT) replicate is now greatly improved and smarter
231+- (BUGF) aclengine (unfinished feature) removed, (not the same as aclsetup)
232+
233+- - 1.6.9
234+- (FEAT/cobbler) cobbler can now pass the virtio26 os version to virtinst, so virtio drivers can be used for RHEL5
235+.3 for instance
236+- (BUGF/cobbler) The URL to the WebUI documentation in the manpage was corrected
237+- (BUGF/cobbler) add the --nameserver option for static interfaces when defined (snippet fix)
238+
239+- 1.6.7
240+- (BUGF/koan) Workaround for a bug in ybin, use --verbose for happy return codes
241+- (BUGF/cobbler) patch to redhat_register for Satellite
242+
243+1.6.6 (for more accurate listing, see release16 branch)
244+- (BUGF) don't use -m option for drac unless power_id is set
245+- (BUGF) don't run createrepo on reposync'd repos, it is redundant
246+- (BUGF) fix error message when wrong virt ram value is applied
247+- (FEAT) koan now partially works in source code form on EL 2
248+- (FEAT) discover repomd filenames (for F11 and later)
249+- (BUGF) Satellite also has a python module named "server" so we have to remove ours for Python imports. This code was not used anyway.
250+- (BUGF) fix typo in network config snippet
251+
252+- ... - 1.6.5
253+- (BUGF) don't use json on python x<=2.3 since we know it's simplejson x<2.0, which has unicode issues
254+- (FEAT) support F-11 imports
255+- (BUGF) don't add koan virtual interfaces for vlan tagged interfaces
256+- (BUGF) pair PAE and non-PAE content in imports better
257+- (BUGF) don't try to scp /etc/cobbler/*.ks on replicate, this is an old path
258+- (BUGF) set proper umask on .mtime files
259+- (BUGF) fix koan error with unspecified arch using --kexec
260+- (BUGF) don't use --onboot=on in network config for kickstart for RHEL 3.
261+- (FEAT) koan can be built on EL-2
262+
263+- Fri May 8 2009 - 1.6.4
264+- (BUGF) empty nameserver search paths now don't screw up resolv.conf
265+- (BUGF) unicode fix for --template-files feature
266+- (BUGF) mod python input fix for repo/profile associations in webapp
267+- (BUGF) change "hostname" to "option hostname" in dhcp.template
268+- (BUGF) fixes for unicode problem with Cheetah, repos, and json
269+- (BUGF) unicode fix for --template-files feature
270+- (BUGF) another unicode fix
271+- (BUGF) bonding interface setup for RHEL4 now works
272+- (BUGF) generate DHCP info even if netboot is disabled
273+- (BUGF) Change to network_config snippet to ignore bond masters to prevent anaconda failures when MAC addresses are not specified
274+- (BUGF) fix to CLI rename deleting subobjects via cobblerd (important!)
275+- (BUGF) fix blender cache problem with using dnsnames instead of record names (ISC DHCP management)
276+- (BUGF) quote host name in stock ISC template
277+
278+- XXX - 1.6.3
279+- (BUGF) import with datestamp 0 when .discinfo is not found, do not crash
280+- (BUGF) various fixes to "cobbler report" when using non-standard formats
281+- (BUGF) rename with same name does not delete
282+- (BUGF) Fix for traceback when generating DHCP config and the bonding_master interface does not exist.
283+- (BUGF) remove trailing newline from tokens
284+- (BUGF) fix unicode handling of some fields under EL4
285+- (BUGF) fix webui search error (fixed better on devel)
286+- (BUGF) fix duplicate power reference
287+- (BUGF) fix error message that makes it appear dnsmasq had a problem restarting, when it did not
288+- (BUGF) spec requires python-urlgrabber
289+- (BUGF) change settings default from 'ksdevice=eth0' to 'bootif'
290+- (BUGF) keep DHCP restart quiet
291+- (BUGF) better hostname setting with DHCP management on
292+- (BUGF) fix bug in repo breed auto-detection code
293+- (BUGF) close file descriptors by using subprocess, not os.system
294+- (BUGF) make cobbler package Arch for now, require syslinux where it makes sense only. To be changed in later release to download it from intertubes.
295+
296+- Mon Mar 30 2009 - 1.6.2
297+- (BUGF) Fix for cache cleanup problem in cobblerd
298+
299+- Fri Mar 27 2009 - 1.6.1
300+- (FEAT) Improved anaconda monitoring code
301+- (FEAT) download comps.xml always (even if yum does not have the option)
302+- (FEAT) performance upgrades for cobblerd service to avoid reloads
303+- (FEAT) more code for s390 imports (WIP)
304+- (BUGF) import works better with rawhide
305+- (FEAT) snippet to preserve SSH host keys across reinstalls
306+- (FEAT) email trigger to notify when builds finish
307+- (FEAT) triggers now are written in Python, old system still exists.
308+- (FEAT) s390x zpxe support
309+- (BUGF) retry power 5 times before giving up
310+- (BUGF) fix for RHEL3 ppc imports
311+- (FEAT) use nameserver variable in network config in Anaconda when set
312+- (BUGF) sleep 5 seconds between power cycling systems
313+- (FEAT) support for /usr/bin/cobbler-register
314+- (FEAT) web UI search feature
315+- (FEAT) very simple "cobbler hardlink" command to optimize space in /var/www/cobbler
316+- (FEAT) new "change" trigger that runs on all adds/edits/removes/syncs
317+- (FEAT) an SCM trigger that knows about /var/lib/cobbler kickstarts, snippets, and config directories, and audits them for changes
318+- (BUGF) update ctime on object copies
319+- (BUGF) fix cobbler check code that makes sure default password is not in use
320+- (BUGF) remove duplicate text box for management classes from server edit page
321+- (BUGF) fix stderr output on Ctrl+C
322+- (BUGF) potential performance savings WRT duplicate python objects
323+- (BUGF) don't deserialize during sync, it makes it take twice as long
324+- (FEAT) Ubuntu support for import (added/improved)
325+- (BUGF) make DHCP managemnet work with bonding
326+- (BUGF) teach serializer_catalog to fly with JSON
327+- (BUGF) don't use yumdownloader when rpm_list is []
328+- (BUGF) fix default kickstart location
329+- (BUGF) properly "flatten" environment values for webapp
330+- (BUGF) fix for MSIE rendering in web app
331+- (BUGF) stop yumdownloader including system yum repos
332+- (DOCS) update webui project page link
333+- (BUGF) remove caching logic from remote.py
334+- (FEAT) added --exclude-dns option to buildiso
335+- (BUGF) fix string comparisons to tolerate unicode
336+- (BUGF) fix dealing with name servers and name servers search, esp in web app
337+
338+- Tue Mar 3 2009 - 1.4.3
339+- (BUGF) fix OMAPI support's (note: deprecated) usage of subprocess
340+- (BUGF) don't traceback on invalid cmd ("cobbler distro list --name=foo")
341+- (BUGF) fix import usage with --kickstart option (no more traceback)
342+- (BUGF) fix removal of images with child system objects
343+- (BUGF) make --rpmlist on repo use same parsing routes as the rest of cobbler
344+- (BUGF) default value for server override should be <<inherit>> not <inherit>
345+- (BUGF) ensure if virt bridge is set to "" it will apply the value from settings
346+- (BUGF) cobbler check should say path to config file is /etc/cobbler, not /var/lib
347+- (FEAT) enable cobblerweb username/pass logins when authing with spacewalk
348+- (BUGF) allow --kopts to take parameters that are shell quoted.
349+- (BUGF) allow kernel options to start with '-'
350+- (BUGF) Use shlex for parsing --kopts to allow a wider variety of kernel options
351+- (BUGF) prevent potential traceback when --template-file data isn't a hash
352+- (BUGF) anaconda doesn't honor nameserver always, set manually
353+- (BUGF) various post install network snippet fixes
354+- (BUGF) fix OMAPI support's (note: deprecated) usage of subprocess
355+- (SPEC) fix build for rawhide now that yaboot is included
356+- (BUGF) allow src and noarch arches for repo objects
357+- (BUGF) move to PyYAML for YAML implementation since it is better maintained
358+- (BUGF) fixed web-interface editing of ownership
359+- (BUGF) fixed web-interface editing of management classes
360+- (BUGF) don't run full sync in import, sync makes the install system unavailable for very short periods of time
361+- (FEAT) XMLRPC functions for searching objects, just like the Python API has
362+- (BUGF) make "find repo" CLI command search repos, not systems
363+
364+- XXX - 1.4.2
365+- (BUGF) fix WTI power templates
366+- (FEAT) add WTI power type
367+- (BUGF) remove Python 2.6/3000 warnings
368+- (BUGF) fix typo in network template (DNS enumeration)
369+- (BUGF) make buildiso work for systems that are using bonding
370+- (BUGF) blending fix for --template-files
371+- (BUGF) cobbler check ignores comments in TFTP config
372+- (BUGF) fix image type field editing in the webapp
373+- (BUGF) allow deletion of eth0 if other interfaces are present
374+- (BUGF) fix server-override setting in CLI for profile objects
375+- (BUGF) systems and profiles are now sorted for "cobbler buildiso"
376+- (BUGF) ensure that directories exist when installing a template file
377+- (BUGF) fix for typo in network config snippet
378+- (BUGF) fix for func integration script (should overwrite config, not append)
379+- (BUGF) append nameservers and gateway, if set, for buildiso
380+
381+- Fri Jan 09 2009 - 1.4.1
382+- (BUGF) Cobbler check looks for right httpd on SUSE
383+- (BUGF) post_install_network_config snippet had bash errors
384+- (BUGF) don't run restorecon programatically
385+- (FEAT) have cobbler check mention when semanage rules should be applied
386+- (BUGF) fix an obscure xmlrpclib corner case where a string that looks like an int can't be served because xmlrpclib thinks it's an int. Applies to XMLRPC consumers only, not CobblerWeb or the cobbler CLI.
387+- (BUGF) fix external kickstart URLs (not templated) and per-system overrides.
388+- (BUGF) fix 'cobbler check' code for SuSE services
389+- (FEAT) batch editing on the system page.
390+
391+- Fri Dec 19 2008 - 1.4
392+- (----) Stable release of 1.3 development branch
393+
394+- Fri Dec 19 2008 - 1.3
395+- (FEAT) ACLs to extend authz (see Wiki)
396+- (FEAT) puppet integration with --mgmt-classes and external nodes URL
397+- (FEAT) added puppet external nodes script, cobbler-ext-nodes
398+ see https://fedorahosted.org/cobbler/wiki/UsingCobblerWithConfigManagementSystem
399+- (FEAT) ability to use --enable-menu=0/1 to hide profiles from the PXE menu, and config setting to change default value for --enable-menu
400+- (FEAT) added livecd based physical machine cloner script to "contrib"
401+- (FEAT) enable import for debian ISOs and mirrors (1 distro at a time for now)
402+- (FEAT) auto-create rescue profile objects
403+- (FEAT) included network_config snippet and added --static=0/1 to system objects
404+- (FEAT) cobbler report gains additional options for Wiki formatting, csv, and showing only certain fields
405+- (FEAT) changed default kernel options to include ksdevice=bootif (not ksdevice=eth0) and added ipappend 2 to PXE
406+- (FEAT) distro edits now no longer require a sync to rebuild the PXE menu
407+- (BUGF) minor tweak to the blender function to remove a certain class of typing errors where a string is being blended with a list, should not have any noticable effect on existing installs
408+- (BUGF) add missing import of "_" in remote.py
409+- (FEAT) upgraded webui editing for multiple NICs
410+- (FEAT) "template_universe" variable created for snake's usage, variable contains all template variables and is also passed to the template.
411+- (FEAT) refactored import with better Debian/Ubuntu support
412+- (FEAT) Func integration snippets and new settings
413+- (FEAT) settings file and modules.conf now generated by setup.py using templates
414+- (FEAT) --template-files makes cobbler more of a full config management system!
415+- (FEAT) cobbler reposync now supports --tries=N and --no-fail
416+- (FEAT) duplicate hostname prevention, on by default
417+- (FEAT) make import work for Scientific Linux
418+- (FEAT) distro remove will remove mirrored content when it's safe to do so
419+- (FEAT) repo remove will remove mirrored repo content
420+- (FEAT) added snippet for better post-install network configuration
421+- (BUGF) duplicate repo supression to prevent errors in certain Andaconda's
422+- (FEAT) post_network_snippet/interfaces can set up VLANs
423+- (FEAT) call unittests with nose, which offers cleaner output, see tests/README
424+- (FEAT) update included elilo to 3.8
425+- (BUGF) quote append line for elilo
426+- (BUGF) added ExcludeArch: ppc64
427+- (FEAT) --environment parameter added to reposync
428+- (BUGF) have triggers ignore dotfiles so directories can be version controlled (and so on)
429+- (FEAT) init scripts and specfiles now install on SuSE
430+- (TEST) added remote tests, moved existing unit tests to api.py methods
431+- (FEAT) import can auto assign kickstarts based on distro (feature for beaker)
432+- (FEAT) import now saves the dot version of the OS in the comment field
433+- (FEAT) import now adds tree build time
434+- (FEAT) --comment field added to all objects
435+- (FEAT) keep creation and modification times with each object
436+- (FEAT) added ppc imports and arches to supplement s390x (and assoc koan chage)
437+- (FEAT) added number of interfaces required to each image
438+- ~~~ 1.3.2
439+- (BUGF) fix for possible import of insecure modules by Cheetah in Cobbler web.
440+- (FEAT) new version function
441+- (FEAT) misc WUI organization
442+- (FEAT) allow auth against multiple LDAP servers
443+- (FEAT) replicate now copies image objects
444+- (BUGF) replicate now uses higher level API methods to avoid some profile sync errors when distros fail
445+- (FEAT) /etc/cobbler/pxe and /etc/cobbler/power are new config file paths
446+- (FEAT) /var/lib/cobbler/kickstarts is the new home for kicktart files
447+- (FEAT) webui sidebar reorg
448+- (FEAT) manage_dhcpd feature (ISC) now checks service status before restarting
449+- (BUGF) omapi for manage_dhcp feature (ISC) now defaults to off
450+- (FEAT) added module whitelist to settings file
451+- (BUGF) don't let the service handler connect to itself over mod_python/proxy, RH 5.3 does not like
452+- (FEAT) mtimes and ctimes and uids in the API
453+- (FEAT) new functions to get objects based on last modified time, for sync with other apps
454+- ~~~ 1.3.3 Test release
455+- (FEAT) Python 2.6 specfile changes
456+- ~~~ 1.3.X
457+- (FEAT) cobbler check output is always logged to /var/log/cobbler/check.log
458+- (FEAT) new redhat_register snippet and --redhat-management-key options!
459+- (BUGF) SELinux optimizations to symlink/hardlink/chcon/restorecon behavior
460+- (----) no SELinux support on EL 4
461+- (FEAT) yum_post_install_mirror now on by default
462+
463+- ??? - 1.2.9
464+- (BUGF) do not allow unsafe Cheetah imports
465+
466+- Wed Oct 15 2008 - 1.2.8
467+- (BUGF) make cobbler read /etc/cobbler/settings.py (introduced in 1.2.6)
468+
469+- Tue Oct 14 2008 - 1.2.7
470+- (BUGF) go easier on restrictings when importing subprofiles to prevent load errors
471+- (FEAT) added debuginator script to scripts/ (not shipped with RPM)
472+
473+- Fri Oct 10 2008 - 1.2.6
474+- (BUGF) fix image vs system parentage problem affecting cobbler replicate
475+- (BUGF) fix restart-services trigger to not restart dns unneccessarily
476+- (BUGF) add missing variable newname to signature for remote copy_ functions
477+- (BUGF) fix for ownership ownership module when editing kickstarts
478+
479+- Fri Sep 26 2008 - 1.2.5
480+- (BUGF) expose --arch for "cobbler image add"
481+- (BUGF) unbreak dnsmasq DHCP management, similar to ISC bug
482+- (BUGF) fix --arch for cobbler distro add/edit
483+- (BUGF) fix merge error with remote.py's remove_profile function (fix webapp)
484+- (BUGF) make keep_updated and mirror_locally checkboxes in WebUI display correctly
485+
486+- Mon Sep 08 2008 - 1.2.4
487+- (BUGF) simple rebuild to remove cli_report.py, which is not in git
488+
489+- Sun Sep 07 2008 - 1.2.3
490+- (BUGF) fix to manage_isc.py code
491+
492+- Fri Sep 05 2008 - 1.2.2
493+- (BUGF) fix to where elilo location is loaded in manage_isc.py
494+- (BUGF) populate netboot_enabled in WebUI correctly
495+- (BUGF) make RPM own some unowned directories in "triggers"
496+- (BUGF) add named_conf setting to settings
497+
498+- Tue Sep 02 2008 - 1.2.1
499+- (BUGF) fix merge problem with 1.2
500+
501+- Fri Aug 29 2008 - 1.2.0
502+- (FEAT) All development work from 1.X merged in
503+- (FEAT) when --netboot-enabled is toggled, rather than deleting the PXE config, create a local boot PXE config
504+- (BUGF) disable some s390 aspects of cobbler check until it is supported
505+- (FEAT) new --os-version, better validation for --breed, --breed/--os-version also for images
506+
507+- ??? - 1.1.1
508+- (FEAT) make template replacement use regex module
509+- (BUGF) remove bootloader check in settings as that code doesn't need it
510+- (BUGF) refinements to image handling
511+- (FEAT) getks command added to command line
512+- (BUGF) don't print traceback during certain SystemExits
513+- (BUGF) --help now works more intuitively on odd command line usage
514+- (BUGF) use pxesystem for systems, not pxeprofile
515+- (FEAT) make Cheetah formatting errors contain help text for users
516+- (FEAT) --kopts-post can configure post-install kernel options
517+- (BUGF) subtemplates are now errorCatcher Echo compatible
518+
519+- ??? - 1.1.0
520+- devel branch
521+- added cobbler aclsetup command for running cobbler as non-root
522+- added cobbler find command to do searches from the command line
523+- fix mkdir invocation
524+- improved cobbler replicate, it now can rsync needed files
525+- further templatize ISC dhcp config file (pay attention to /etc/cobbler/dhcp.template.rpmnew !)
526+- fix for NFS imported URLs during kickstart generation
527+- added yumreposync_flags to settings, default "-l" for use plugins
528+- added an extra mkdir for rhn's reposync, though I believe the -l cures it already
529+- allow mod python bits to work via non-80 http ports
530+- when mirroring repos, act as 686 not 386 to get all the kernel updates
531+- upgrades to cobbler buildiso
532+- added patch to allow --in-place editing of ksmeta/kopts
533+- added patch to allow multiple duplicate kernel options
534+- fix kickstart serving when the tree is on NFS
535+- s390x import, added support for s390x "pseudo-PXE" trees
536+- added support for tracking image objects and virtual ISO images
537+- support for multiple copies of the same kernel option in kopts
538+- add cobbler bash completion script
539+- fix bug with 255 kernel options line warning not firing soon enough
540+- add findks.cgi support back as http://server/cblr/svc/op/findks
541+- merge patch to surface status over API
542+- make yum repos served up for /etc/yum.repos.d fully dynamic (mod_python)
543+- cobbler find API calls and command line usage can now use fnmatch (wildcards)
544+- return code cleanup (0/1 now more predictable)
545+- added comments to /etc/cobbler/modules.conf
546+- during import non-xen kernels will default --virt-type to qemu
547+- when editing/adding profiles, auto-rebuild the PXE menu
548+- added http://cobbler.example.org/cblr/svc/op/list/what/systems (or profiles, etc)
549+- in the webui, only show compatible repos when editing a profile
550+- refresh cobblerd cache before adding objects
551+- system object IP's ok in CIDR notation (AAA.BBB.CCC.DDD/EE) for defining PXE behavior.
552+- split partition select template into two parts (old one still ships)
553+- cleanup some stock kickstarts so we always use $kickstart_start
554+- hook ctrl+c during serializer writes to prevent possible corruption of data in /var/lib/cobbler
555+- added 'serializer_catalog' as the new default serializer. It is backward compatible and much faster.
556+- removed serializer_shelve
557+- webui page lookups don't load the full object collection
558+- systems can also inherit from images
559+- changes to PXE images directly
560+- bootloaders is no longer a config file setting
561+- we can now look for syslinux in one of two places (/usr/lib, /usr/share)
562+- cobbler hardlinks a bit more when it can for /var/www image copies
563+- add Xen FV and VMware virt types to WebUI
564+
565+- Thu Jul 17 2008 - 1.0.4 (tentative)
566+- Backported findks.cgi to mod_python, minor mod_python svc handler changes
567+
568+- Wed Jun 03 2008 - 1.0.3
569+- Fix typo in replicate code
570+- remove rhpl reference
571+- scrub references to manage_*_mode and rewrite the restart-services trigger
572+- add new settings to control whether the restart-trigger restarts things
573+- yum reposync should also pull i686 kernels, not just i386
574+- make cobblerd close file handles
575+- fix kickstart serving when the tree is on NFS
576+- fix missing reposync createdir (also now in stable branch)
577+- add back missing remove_profile/remove_repo
578+- remove profile_change support
579+
580+- Mon Jun 09 2008 - 1.0.2
581+- Fix mkdir invocation
582+- Fix error message output from failed kickstart rendering
583+- manpage edits
584+- make buildiso work for SuSE
585+
586+- Tue Jun 03 2008 - 1.0.1
587+- Fix misformatted warning in "check"
588+- Do not have RPM own tftpboot, just generate files in TFTP dir as detected
589+- Default arches to 'i386' not 'x86' for consistency, esp. in import
590+- When querying kickstart templates, do not return directories
591+- Make triggers for add/delete work for renames and copies (same triggers)
592+- Do not cache snippets so they can be tweaked w/o starting the service
593+- Make manpage reference /etc/cobbler/settings, not /var/lib
594+- Added manage_forward_zones/manage_reverse_zones to included config file
595+- Fix python double-use-of-parameter error
596+
597+- Mon May 12 2008 - 0.9.2
598+- run createrepo with less preconditions during cobbler reposync
599+- doc upgrades and error handling for "cobbler replicate"
600+- improved error message that occurs when copying from nfs w/ rootsquash
601+- mac duplication checking improvements for CLI
602+- add warning to cobbler check if selinux is on and Apache boolean not set
603+- added warning to cobbler check if templates use the default password
604+- setting per-system kickstart template to "" or "delete" restores inheritance
605+- if repos in profiles no longer exist, remove noisy warning, move to "check"
606+- move warning about reposync to check also (check is more useful at runtime now)
607+- build pxe trees for systems even if interface0 is undefined
608+- add sync() back into XMLRPC API, missing in 0.9.1
609+- added 'distro_name', 'profile_name', and 'system_name' to generated template vars
610+- it's now possible to undefine a --ksmeta or kopts symbol defined in a parent with "!foo"
611+- log errors while rendering kickstarts
612+- comments added to the config file, neat!
613+- settings file is now /etc/cobbler/settings
614+
615+- Fri May 09 2008 - 0.9.1
616+- patch to allow yumopts to override gpgcheck
617+- applied patch to send hostname from ISC
618+- added patch to allow --kopts/--ksmeta items to be cleared with --kopts=delete
619+- tftpboot location is now inferred from xinetd config (added for F9 compat)
620+- added authn_ldap and stub for authz_configfile
621+- authz_configfile allows filtering ldap/other users by config file
622+- WebUI now has checkbox on distro/profile for deleting child objects
623+- cli has different semantics between "add" and "edit" now for safety reasons
624+- cobbler wants to keep IPs/MACs unique now in configuration (can be disabled)
625+- added --clobber option to allow add to overwrite existing objects (for scripts)
626+- updated/tested kerberos support for those needing to auth against it
627+- update menu.c32 to 3.62 to allow for timeouts during menu (and future submenu)
628+- update PXE defaults to invoke menu.c32 automatically w/ timeout
629+- removed dependency on rhpl
630+- import can now take an --arch (and is recommended usage)
631+- now possible to override snippets on a profile/system specific basis
632+- provide a different default sample kickstart for imports of F8 and later
633+- support for kerberos authentication
634+- revamped pre/post install triggers system (triggered via cgi from kickstart wget)
635+- logrotate should not send emails to root when restarting services
636+- default core (but not repo add) repos to priority 1 (lowest) if using priorities plugin
637+- change default authentication to deny_all, xmlrpc_rw_enabled now on by default
638+- additional fix for mod_python select box submissions
639+- set repo arch if found in the URL and no --arch is specified
640+- CGI scripts have been moved under mod_python for speed/consolidation
641+- kickstart templates are now evaluated dynamically
642+- optional MAC registration is now built-in to requesting kickstarts
643+- legacy static file generation from /var/www/cobbler removed
644+- implement "cobbler ___ dumpvars --name=X" feature to show template vars
645+- validateks now works against all URLs as opposed to rendered local files
646+- now possible to create new kickstarts in webui, and delete unused ones
647+- support for OMAPI for avoid dhcp restarts
648+- support for managing BIND
649+- xen kernel (PV) distros do not get added to PXE menus as they won't boot there
650+- cobbler buildiso command to build non live ISOs
651+- cobbler replicate command
652+- added cobbler repo option --mirror-locally to reference external repos without mirroring
653+- all virt parameters on profiles can now be overriden on cobbler profile objects
654+- added some additional links for kickstart viewing/editing to the web page
655+
656+- ??? - 0.8.3
657+- Make createrepo get run for local cobbler reposync invocations as needed
658+- fix WebUI documentation URL
659+- fix bug in /etc/cobbler/modules.conf regarding pluggable authn/z
660+- fix default flags for yumdownloader
661+- fix for RHEL 4u6 DVD/tree import x86_64 arch detection
662+- fix for dnsmasq template file host config path
663+- fix dnsmasq template to point at the correct hosts file
664+- force all names to be alphanumeric
665+- all mod python pieces now happy with Unicode output
666+
667+* Fri Feb 22 2008 - 0.8.2
668+- fix to webui to allow repos to be edited there on profile page
669+- disable local socket XMLRPC as nothing is using it.
670+- fixed findks.cgi so it supports multiple NICs
671+- import now supports both --path and --mirror as aliases, as before
672+- added change_profile.cgi for changing profiles from CGI
673+- added register_mac.cgi
674+
675+* Wed Feb 20 2008 - 0.8.1
676+- bugfix in reposync code
677+- don't print tracebacks on SystemExit from optparse
678+- manpage tweaks
679+
680+* Fri Feb 15 2008 - 0.8.0 (TBD)
681+- stable release of 0.7.* branch plus ...
682+- fixed potential user problem with source_repos in upgrade scenario
683+- additional higher level API functions for find, fixes for other higher level API functions
684+- better messaging when insufficient permissions on needed files
685+- update permissions on reposync fixes
686+
687+* Thu Jan 31 2008 - 0.7.2 (0.8 rc)
688+- default_virt_file_size and default_virt_ram added to settings
689+- enforce permissions/selinux context after reposync
690+- better API for copying/renames, API consistancy cleanup
691+- support for renames that resolve dependencies, inclusion in CLI+webapp
692+- remove leading newline in rendered template files, which apparently breaks AutoYAST?
693+- recursive syncs automatically sync all subobjects when editing parent objects (default behavior)
694+- deletes can now be done recursively (optional --recursive on distro/profile remove)
695+- 'cobbler list' is now (re)sorted
696+
697+* Wed Jan 09 2008 - 0.7.1
698+- allow imports to force usage of a specific kickstart template with --kickstart
699+- added --yumopts parameter to repos (works just like --kopts/--ksmeta)
700+- minor doc fixes
701+- fix for name of F8 comps.xml file
702+- added option --rsync-flags to import command
703+- added http_port to settings to run Apache on non-80
704+- rsync during createrepo now keeps filesystem permissions/groups
705+- ...
706+
707+* Mon Dec 10 2007 - 0.7.0
708+- Testing branch
709+- Fix bug related to <<inherit>> and kickstart args
710+- Make CLI functions modular and use optparse
711+- Quote wget args to avoid creating stray files on target system
712+- Support Xen FV as virt type (requires F8+)
713+- Implemented fully pluggable authn/authz system
714+- WebUI is now mod_python based
715+- Greatly enhanced logging (goes to /var/log/cobbler/cobbler.log)
716+- ...
717+
718+* Wed Nov 14 2007 - 0.6.4
719+- Changed permissions of auth.conf
720+- Fixes for working with rhn_yum_plugin
721+- still allow repo configuration for distro repos that have just 1 repo (like C5.1)
722+- disable CGI weblogging by default (backend logging TBA)
723+- fix WebUI handling of keep_updated (repo field) and netboot_enabled (system field)
724+- disable the blender_cache as it's running afoul of the sync code
725+- update htaccess file to only authenticate the webui, not nopxe.cgi and findks.cgi
726+
727+* Wed Nov 07 2007 - 0.6.3
728+- Be able to define and use Multiple NICs per system
729+- Add --virt-cpus to profile editing
730+- Fix bug where WUI (XMLRPC) auth wasn't supported on EL4
731+- Add --virt-bridge to profile editing and NICs
732+- Added serializer_shelve (as option) for added performance/persistance over YAML, experimental in /etc/cobbler/modules.conf, see Wiki
733+- Backup state files and migrate state structures upon RPM upgrade
734+- Added some more redundant files (for unsupported distros) to the rsync.exclude file
735+- added pre-sync and post-sync triggers, service restarts are now handled by /var/lib/cobbler/triggers
736+- webui now uses htaccess (see manpage and Wiki for setup instructions)
737+- added pagination to the WUI to keep pages from growing overly long
738+- added --server-override parameter for help with multi-subnet configurations (also see Wiki)
739+- removed yum-utils as a hard requirement, cobbler check now looks for yum-utils
740+- fixed bug where cobbler would try to copy hardlinks to themselves during sync
741+- misc random bugfixing
742+
743+* Fri Sep 28 2007 - 0.6.2
744+- cobbler repo auto-add to discover yum repos automatically
745+- fix bug that allows empty mac addresses (None) in dhcpd.conf
746+- kickstarts automatically save kickstart file used to /root/cobbler.ks
747+- allow multiple (comma-seperated) values for --virt-size
748+- removed deprecated 'enchant' function (use SSH and koan instead)
749+- cleanup of a few unused settings
750+- allow for serialization modules to be selected in /etc/cobbler/modules.conf
751+- patch to allow for reposync of specific repos, even if not set to update
752+- added --dhcp-tag section for better DHCP customization (esp with multiple subnets)
753+- added Apache proxying around XMLRPC port for wider network access
754+- refactor XMLRPC API and establish a read-write API
755+- allow for configuring of read-write XMLRPC users in /etc/cobbler/auth.conf
756+- WebUI
757+- packaged /var/lib/cobbler/settings as a config file
758+- added BuildRequires to help build on other platforms
759+- relocate cgi-bin files to cgi-bin/cobbler for namespacing
760+- fix syslog logging for systems not in the cobbler DB.
761+- fix bug in which non-lowercase intermediate objects could be deleted
762+
763+* Thu Aug 30 2007 - 0.6.1
764+- re enable --resolve in yumdownloader (cobbler repo mgmt feature)
765+- fix get_distros_for_koan API function in cobblerd (not used by koan)
766+- allow find API to search by arbitrary fields
767+- status and logging now shows system names
768+- upgraded init scripts
769+- zeroconf/avahi publishing for cobblerd service
770+- logRequests = 0 for XMLRPC. Make it be quiet.
771+- ignore subdirectories of /var/lib/cobbler/snippets
772+- fixed bug in graph rendering that allowed for upward property propogation in some cases
773+- fixed bug that did not correctly evaluate repository settings of inherited sub-profiles/objects
774+- tweaked domU sample kickstart to include wget
775+- added some more unit tests
776+- fix typo down one error path in cobbler sync.
777+- fix reposync handling when using rsync protocol and directory paths do not contain arch
778+- allow basic usage of Cheetah variables in config files @@server@@, etc.
779+- fix auto-repo attachment for distros with split trees (i.e. RHEL5)
780+
781+* Thu Aug 09 2007 - 0.6.0
782+- bugfix in error path in "cobbler check"
783+- stable release for 0.5.x
784+
785+* Thu Jul 26 2007 - 0.5.2 (RC)
786+- Have cobbler check ensure services are started
787+- Add cobbler validateks command to look for broken rendered kickstarts
788+- Added -v/--version
789+- Added SNIPPET::foo capability to pull /var/lib/cobbler/snippets/foo into templates (anywhere)
790+- Import can now take an --available-as=nfs://server:/mount/point to do cobbler import without mirroring
791+- Feature to enable "pxe_just_once" for boot loop prevention
792+
793+* Fri Jul 20 2007 - 0.5.1
794+- Added logging for cobblerd -- /var/log/cobbler/cobblerd.log
795+- Cobblerd now ignores XMLRPC IOError
796+- Added findks.cgi
797+- Misc bugfixing
798+- Added --virt-path, --virt-type
799+
800+* Wed Jun 24 2007 - 0.5.0
801+- Remove hardcode of /var/www/cobbler in cobblerd
802+- Improve various warning warning messages
803+- cobbler (objecttype) (objectname) now gives info about the object instead of just all objects
804+- Added --hostname to "cobbler system add", --ip-address (or --ip) is also a better alias for the misnamed --pxe-address
805+- Optionally use dnsmasq for DHCP (and DNS!) instead of ISC dhcpd.
806+- Add --mac and remove requirement for --name to be an ip, mac, or hostname.
807+- Manpage cleanup
808+- Patch to allow pre and post triggers
809+- Patch to allow --createrepo-flags and to cache on import, fix multiple calls to createrepo
810+- Various modifications to allow for profile inheritance
811+- All variables in object tree now available for use in templating, nicer blending algorithms
812+- Optional override of --kickstart in system object
813+
814+* Thu Apr 26 2007 - 0.4.8
815+- Make import friendlier for older distros
816+- Make import friendlier for newer createrepos that don't have --basedir
817+
818+* Fri Apr 20 2007 - 0.4.7
819+- Disable mod_python tracker piece for RHEL5 (replacement eventual).
820+- Kickstart tracking now understands Apache logs
821+- Added support for --rpm-list parameter to "repo add" for download of partial content from repositories
822+ (ex: cobbler and koan from FC6extras, w/o games).
823+- More consistant naming on imports, regardless of data source.
824+- Teach cobbler to remove .olddata dirs, which can happen if createrepo crashes or is killed mid-process
825+- Default yum_core_repos_from_server to 0
826+- Implemented triggers for add/delete commands
827+- BootAPI and Config object classes are now Borg patterned to prevent duplication of config info from the API.
828+- cobbler_syslogd -> cobblerd, now has XMLRPC component for koan >= 0.2.9 clients. Old clients still work.
829+- Make cobbler_import work for Centos 5
830+- Removed requirements on what files that are parameters to --kernel and --initrd must be named.
831+- Added support for "rename", "copy", and "edit" commands -- before there just was "add" and "remove"
832+
833+* Thu Apr 05 2007 - 0.4.6
834+- Bind cobbler_syslogd to all addresses
835+- Store repos as list, not string
836+- Fix traceback in cobbler_sync with older configurations (pre-kickstart tracking)
837+- Make cobbler import feature better understand older RHEL and in-between builds of Fedora.
838+- Make cobbler repo add/reposync understand http://, ftp://, and some limited support for RHN.
839+- Add settings parameter to toggle core repo mirror behavior on/off.
840+- Manpage cleanup.
841+
842+* Fri Mar 23 2007 - 0.4.5
843+- Removed legacy --virt-name parameter, requires koan upgrade to 0.2.8
844+
845+* Fri Mar 23 2007 - 0.4.4
846+- Generate PXE configuration files from templates in /etc/cobbler to be more customizable
847+- Fix bug with wrong kickstart metadata being used for import
848+- Fix bug with argument parsing for --repos
849+- Much cleaner distro/profile names with --import
850+- For import, the "tree" parameter is now attached to the distro, not the profile
851+- Add "links" directory in webdir for symlinking to full kickstart tree paths.
852+- Misc tweaks to shorten kernel parameter length
853+- Giving invalid arguments to "report" will show an error message
854+- Distros, Profiles, and System names are now case insensitive.
855+
856+* Wed Feb 28 2007 - 0.4.3
857+- Added netboot_enabled option for systems to control install loops in programmatic context.
858+- Disabling anchors in YAML serialization (which make files harder to edit)
859+- Fix bug in ksmeta argument processing, takes whitespace again, not commas
860+- Fix bug in old-style deserialization with str and int concatenation
861+
862+* Mon Feb 19 2007 - 0.4.2
863+- Fix bug in "cobbler system remove"
864+
865+* Mon Feb 19 2007 - 0.4.1
866+- Bundle menu.c32 for older distros
867+- Unbundle Cheetah as it's available at http://www.python.org/pyvault/centos-4-i386/
868+
869+* Mon Feb 19 2007 - 0.4.0
870+- Added feature to minimize the need to run "cobbler sync" for add commands
871+ Now only need to run sync when files change behind the scenes or when
872+ manually editing YAML
873+- Moving back to Cheetah for templating (old kickstarts should escape $ with \$)
874+- PXE menus for the default profile. Type "menu" at the prompt to get a menu, or wait for local boot.
875+- Manpage cleanup and clarification
876+- Bugfix: cobbler will no longer create repo files on remotes when --local-filename is not used for "repo add"
877+
878+* Mon Jan 28 2007 - 0.3.9
879+- Make init scripts correspond with FC-E guidelines
880+
881+* Thu Jan 24 2007 - 0.3.8
882+- Fixed minor bug in logfile processing related to 0.3.7
883+
884+* Thu Jan 24 2007 - 0.3.7
885+- Default/examples kickstarts are now fully automatic (added hd type/size detection).
886+- Kickstart tracking now includes remote syslog support, just run "cobbler sync" to enable.
887+- "cobbler status" command improved to include syslog info/times.
888+- Added fc6 kickstart file that was left out of the RPM earlier
889+- Added mini domU kickstart
890+- bugfix: don't install mod_python watcher on older Apache installs (like RHEL4) as it
891+ somehow corrupts downloads on older copies. kickstart tracking by syslog still works
892+ on those platforms. (This only applies to the cobbler server, not clients).
893+
894+* Thu Dec 21 2006 - 0.3.6
895+- locking feature now enabled
896+- "enchant" now supports provisioning virtual images remotely when using --is-virt=yes
897+- cobbler no longer restarts httpd if the config file already exists.
898+- "cobbler repo sync" is now an alias for "cobbler reposync"
899+- "cobbler list --something" can now be invoked as "cobbler something list"
900+- "cobbler list" just shows names of items now
901+- "cobbler report" is now used for showing full information output
902+- "list" (as well as report) are now sorted alphabetically
903+- basic kickstart tracking feature. requests on /var/www/cobbler get logged to /var/log/cobbler.
904+
905+* Wed Dec 20 2006 - 0.3.5
906+- Fixed bug in cobbler import related to orphan detection
907+- Made default rsync.exclude more strict (OO langpacks and KDE translation)
908+- Now runs createrepo during "cobbler import" to build more correct repodata
909+- Added additional repo mirroring commands: "cobbler repo add", etc
910+- Documentation on repo mirroring features.
911+- fix bug in rsync:// import code that saved distributions in the wrong path
912+- The --dryrun option on "cobbler sync" is now unsupported.
913+- Fixed bug in virt specific profile information not being used with koan
914+- import now takes --name in addition to --mirror-name to be more consistant
915+- rsync repo import shouldn't assume SSH unless no rsync:// in mirror URL
916+- strict host key checking disabled for "cobbler enchant" feature
917+
918+* Mon Dec 05 2006 - 0.3.4
919+- Don't rsync PPC content or ISO's on cobbler import
920+- Manpage cleanup
921+
922+* Tue Nov 14 2006 - 0.3.3
923+- During "cobbler sync" only PXE-related directories in /tftpboot
924+ are deleted. This allows /tftpboot to be used for other
925+ purposes.
926+
927+* Thr Oct 25 2006 - 0.3.2
928+- By default, boot and install in text mode
929+
930+* Wed Oct 25 2006 - 0.3.1
931+- The app now refers to "virt" in many places instead of "xen".
932+ It's been coded such that files will migrate forward without
933+ any major issues, and the newer version of koan can still hit
934+ older releases (for now). The CLI still takes the --xen options
935+ as well as the new --virt options, as they are aliased. The API
936+ now exclusively just uses methods with "virt" in them, however.
937+- ...
938+
939+* Tue Oct 24 2006 - 0.3.0
940+- Reload httpd during sync
941+- New profiles without set kickstarts default to /etc/cobbler/default.ks
942+ though this can be changed in /var/lib/cobbler/settings
943+- Better forward upgrades for /var/lib/cobbler/settings. New entries
944+ get added when they are referenced.
945+
946+* Tue Oct 24 2006 - 0.2.9
947+- Bug fix, enchant now detects if koan_path is not set
948+- import now can do ssh rsync as well as just rsyncd
949+- Misc bug fixes related to not choking on bad info
950+- Fixed bug where --pxe-address wasn't surfaced
951+- Sync is a little less verbose
952+
953+* Wed Oct 18 2006 - 0.2.8
954+- Performance speedups to "import" command
955+- Bug fix, imported paths (again) convert slashes to underscores
956+
957+* Tue Oct 17 2006 - 0.2.7
958+- Removed pexpect to enhance support for other distros
959+- enchant syntax changed (see NEWS)
960+- now builds on RHEL4
961+
962+* Tue Oct 17 2006 - 0.2.6
963+- Removing Cheetah and replacing w/ simpler templating system
964+- Don't delete localmirror on sync
965+
966+* Mon Oct 16 2006 - 0.2.5
967+- New "import" feature for rsync:// mirrors and filesystem directories
968+- Manpage clarification
969+- "enchant" is now a subcommand of "cobbler system" and takes less arguments.
970+- Several random bugfixes (mainly along error paths)
971+
972+* Wed Oct 11 2006 - 0.2.4
973+- Changes to make things work with python 2.3 (RHEL4, etc)
974+- Updated YAML code to ensure better backward compatibility
975+
976+* Mon Oct 9 2006 - 0.2.3
977+- Cobbler now creates a profile and system listing (YAML) in /var needed
978+ by the next version of koan (which will be 0.2.1)
979+- bugfix: enchant should reboot the target box
980+- bugfix: enchant should fail if path to koan isn't configured
981+
982+* Fri Oct 6 2006 - 0.2.2
983+- bugfix: "--pxe-hostname" made available in CLI and renamed as "--pxe-address"
984+- workaround: elilo doesn't do MAC address pxe config files, use IP for ia64
985+- bugfix: added next-server line for per-MAC dhcp configs
986+- bugfix: fixed manpage errors
987+
988+* Thu Sep 28 2006 - 0.2.1
989+- New ability to "enchant" remote systems (see NEWS)
990+- Misc. bugfixes
991+
992+* Fri Sep 22 2006 - 0.2.0
993+- New dhcp.d conf management features (see NEWS)
994+- IA64 support (see NEWS)
995+- dhcpd.conf MAC & hostname association features
996+
997+* Thu Sep 21 2006 - 0.1.1-8
998+- (RPM) Added doc files to doc section, removed INSTALLED_FILES
999+
1000+* Wed Sep 20 2006 - 0.1.1-7
1001+- Split HTTP and TFTP content to seperate directories
1002+ to enable running in SELinux targetted/enforcing mode.
1003+- Make the Virt MAC address a property of a system, not a profile
1004+- Misc. fixes, mainly along the error path
1005+
1006+* Fri Sep 15 2006 - 0.1.1-6
1007+- Make koan own it's directory, add GPL "COPYING" file.
1008+
1009+* Wed Aug 16 2006 - 0.1.1-5
1010+- Spec file tweaks only for FC-Extras
1011+
1012+* Thu Jul 20 2006 - 0.1.1-4
1013+- Fixed python import paths in yaml code, which errantly assumed yaml was installed as a module.
1014+
1015+* Wed Jul 12 2006 - 0.1.1-3
1016+- Added templating support using Cheetah
1017+
1018+* Thu Jul 9 2006 - 0.1.0-2
1019+- Fedora-Extras rpm spec tweaks
1020+
1021+* Tue Jun 28 2006 - 0.1.0-1
1022+- rpm genesis
1023+
1024+
1025
1026=== renamed file 'CHANGELOG' => 'CHANGELOG.moved'
1027=== added file 'COPYING'
1028--- COPYING 1970-01-01 00:00:00 +0000
1029+++ COPYING 2011-03-11 21:10:49 +0000
1030@@ -0,0 +1,340 @@
1031+ GNU GENERAL PUBLIC LICENSE
1032+ Version 2, June 1991
1033+
1034+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
1035+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1036+ Everyone is permitted to copy and distribute verbatim copies
1037+ of this license document, but changing it is not allowed.
1038+
1039+ Preamble
1040+
1041+ The licenses for most software are designed to take away your
1042+freedom to share and change it. By contrast, the GNU General Public
1043+License is intended to guarantee your freedom to share and change free
1044+software--to make sure the software is free for all its users. This
1045+General Public License applies to most of the Free Software
1046+Foundation's software and to any other program whose authors commit to
1047+using it. (Some other Free Software Foundation software is covered by
1048+the GNU Lesser General Public License instead.) You can apply it to
1049+your programs, too.
1050+
1051+ When we speak of free software, we are referring to freedom, not
1052+price. Our General Public Licenses are designed to make sure that you
1053+have the freedom to distribute copies of free software (and charge for
1054+this service if you wish), that you receive source code or can get it
1055+if you want it, that you can change the software or use pieces of it
1056+in new free programs; and that you know you can do these things.
1057+
1058+ To protect your rights, we need to make restrictions that forbid
1059+anyone to deny you these rights or to ask you to surrender the rights.
1060+These restrictions translate to certain responsibilities for you if you
1061+distribute copies of the software, or if you modify it.
1062+
1063+ For example, if you distribute copies of such a program, whether
1064+gratis or for a fee, you must give the recipients all the rights that
1065+you have. You must make sure that they, too, receive or can get the
1066+source code. And you must show them these terms so they know their
1067+rights.
1068+
1069+ We protect your rights with two steps: (1) copyright the software, and
1070+(2) offer you this license which gives you legal permission to copy,
1071+distribute and/or modify the software.
1072+
1073+ Also, for each author's protection and ours, we want to make certain
1074+that everyone understands that there is no warranty for this free
1075+software. If the software is modified by someone else and passed on, we
1076+want its recipients to know that what they have is not the original, so
1077+that any problems introduced by others will not reflect on the original
1078+authors' reputations.
1079+
1080+ Finally, any free program is threatened constantly by software
1081+patents. We wish to avoid the danger that redistributors of a free
1082+program will individually obtain patent licenses, in effect making the
1083+program proprietary. To prevent this, we have made it clear that any
1084+patent must be licensed for everyone's free use or not licensed at all.
1085+
1086+ The precise terms and conditions for copying, distribution and
1087+modification follow.
1088+
1089+ GNU GENERAL PUBLIC LICENSE
1090+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
1091+
1092+ 0. This License applies to any program or other work which contains
1093+a notice placed by the copyright holder saying it may be distributed
1094+under the terms of this General Public License. The "Program", below,
1095+refers to any such program or work, and a "work based on the Program"
1096+means either the Program or any derivative work under copyright law:
1097+that is to say, a work containing the Program or a portion of it,
1098+either verbatim or with modifications and/or translated into another
1099+language. (Hereinafter, translation is included without limitation in
1100+the term "modification".) Each licensee is addressed as "you".
1101+
1102+Activities other than copying, distribution and modification are not
1103+covered by this License; they are outside its scope. The act of
1104+running the Program is not restricted, and the output from the Program
1105+is covered only if its contents constitute a work based on the
1106+Program (independent of having been made by running the Program).
1107+Whether that is true depends on what the Program does.
1108+
1109+ 1. You may copy and distribute verbatim copies of the Program's
1110+source code as you receive it, in any medium, provided that you
1111+conspicuously and appropriately publish on each copy an appropriate
1112+copyright notice and disclaimer of warranty; keep intact all the
1113+notices that refer to this License and to the absence of any warranty;
1114+and give any other recipients of the Program a copy of this License
1115+along with the Program.
1116+
1117+You may charge a fee for the physical act of transferring a copy, and
1118+you may at your option offer warranty protection in exchange for a fee.
1119+
1120+ 2. You may modify your copy or copies of the Program or any portion
1121+of it, thus forming a work based on the Program, and copy and
1122+distribute such modifications or work under the terms of Section 1
1123+above, provided that you also meet all of these conditions:
1124+
1125+ a) You must cause the modified files to carry prominent notices
1126+ stating that you changed the files and the date of any change.
1127+
1128+ b) You must cause any work that you distribute or publish, that in
1129+ whole or in part contains or is derived from the Program or any
1130+ part thereof, to be licensed as a whole at no charge to all third
1131+ parties under the terms of this License.
1132+
1133+ c) If the modified program normally reads commands interactively
1134+ when run, you must cause it, when started running for such
1135+ interactive use in the most ordinary way, to print or display an
1136+ announcement including an appropriate copyright notice and a
1137+ notice that there is no warranty (or else, saying that you provide
1138+ a warranty) and that users may redistribute the program under
1139+ these conditions, and telling the user how to view a copy of this
1140+ License. (Exception: if the Program itself is interactive but
1141+ does not normally print such an announcement, your work based on
1142+ the Program is not required to print an announcement.)
1143+
1144+These requirements apply to the modified work as a whole. If
1145+identifiable sections of that work are not derived from the Program,
1146+and can be reasonably considered independent and separate works in
1147+themselves, then this License, and its terms, do not apply to those
1148+sections when you distribute them as separate works. But when you
1149+distribute the same sections as part of a whole which is a work based
1150+on the Program, the distribution of the whole must be on the terms of
1151+this License, whose permissions for other licensees extend to the
1152+entire whole, and thus to each and every part regardless of who wrote it.
1153+
1154+Thus, it is not the intent of this section to claim rights or contest
1155+your rights to work written entirely by you; rather, the intent is to
1156+exercise the right to control the distribution of derivative or
1157+collective works based on the Program.
1158+
1159+In addition, mere aggregation of another work not based on the Program
1160+with the Program (or with a work based on the Program) on a volume of
1161+a storage or distribution medium does not bring the other work under
1162+the scope of this License.
1163+
1164+ 3. You may copy and distribute the Program (or a work based on it,
1165+under Section 2) in object code or executable form under the terms of
1166+Sections 1 and 2 above provided that you also do one of the following:
1167+
1168+ a) Accompany it with the complete corresponding machine-readable
1169+ source code, which must be distributed under the terms of Sections
1170+ 1 and 2 above on a medium customarily used for software interchange; or,
1171+
1172+ b) Accompany it with a written offer, valid for at least three
1173+ years, to give any third party, for a charge no more than your
1174+ cost of physically performing source distribution, a complete
1175+ machine-readable copy of the corresponding source code, to be
1176+ distributed under the terms of Sections 1 and 2 above on a medium
1177+ customarily used for software interchange; or,
1178+
1179+ c) Accompany it with the information you received as to the offer
1180+ to distribute corresponding source code. (This alternative is
1181+ allowed only for noncommercial distribution and only if you
1182+ received the program in object code or executable form with such
1183+ an offer, in accord with Subsection b above.)
1184+
1185+The source code for a work means the preferred form of the work for
1186+making modifications to it. For an executable work, complete source
1187+code means all the source code for all modules it contains, plus any
1188+associated interface definition files, plus the scripts used to
1189+control compilation and installation of the executable. However, as a
1190+special exception, the source code distributed need not include
1191+anything that is normally distributed (in either source or binary
1192+form) with the major components (compiler, kernel, and so on) of the
1193+operating system on which the executable runs, unless that component
1194+itself accompanies the executable.
1195+
1196+If distribution of executable or object code is made by offering
1197+access to copy from a designated place, then offering equivalent
1198+access to copy the source code from the same place counts as
1199+distribution of the source code, even though third parties are not
1200+compelled to copy the source along with the object code.
1201+
1202+ 4. You may not copy, modify, sublicense, or distribute the Program
1203+except as expressly provided under this License. Any attempt
1204+otherwise to copy, modify, sublicense or distribute the Program is
1205+void, and will automatically terminate your rights under this License.
1206+However, parties who have received copies, or rights, from you under
1207+this License will not have their licenses terminated so long as such
1208+parties remain in full compliance.
1209+
1210+ 5. You are not required to accept this License, since you have not
1211+signed it. However, nothing else grants you permission to modify or
1212+distribute the Program or its derivative works. These actions are
1213+prohibited by law if you do not accept this License. Therefore, by
1214+modifying or distributing the Program (or any work based on the
1215+Program), you indicate your acceptance of this License to do so, and
1216+all its terms and conditions for copying, distributing or modifying
1217+the Program or works based on it.
1218+
1219+ 6. Each time you redistribute the Program (or any work based on the
1220+Program), the recipient automatically receives a license from the
1221+original licensor to copy, distribute or modify the Program subject to
1222+these terms and conditions. You may not impose any further
1223+restrictions on the recipients' exercise of the rights granted herein.
1224+You are not responsible for enforcing compliance by third parties to
1225+this License.
1226+
1227+ 7. If, as a consequence of a court judgment or allegation of patent
1228+infringement or for any other reason (not limited to patent issues),
1229+conditions are imposed on you (whether by court order, agreement or
1230+otherwise) that contradict the conditions of this License, they do not
1231+excuse you from the conditions of this License. If you cannot
1232+distribute so as to satisfy simultaneously your obligations under this
1233+License and any other pertinent obligations, then as a consequence you
1234+may not distribute the Program at all. For example, if a patent
1235+license would not permit royalty-free redistribution of the Program by
1236+all those who receive copies directly or indirectly through you, then
1237+the only way you could satisfy both it and this License would be to
1238+refrain entirely from distribution of the Program.
1239+
1240+If any portion of this section is held invalid or unenforceable under
1241+any particular circumstance, the balance of the section is intended to
1242+apply and the section as a whole is intended to apply in other
1243+circumstances.
1244+
1245+It is not the purpose of this section to induce you to infringe any
1246+patents or other property right claims or to contest validity of any
1247+such claims; this section has the sole purpose of protecting the
1248+integrity of the free software distribution system, which is
1249+implemented by public license practices. Many people have made
1250+generous contributions to the wide range of software distributed
1251+through that system in reliance on consistent application of that
1252+system; it is up to the author/donor to decide if he or she is willing
1253+to distribute software through any other system and a licensee cannot
1254+impose that choice.
1255+
1256+This section is intended to make thoroughly clear what is believed to
1257+be a consequence of the rest of this License.
1258+
1259+ 8. If the distribution and/or use of the Program is restricted in
1260+certain countries either by patents or by copyrighted interfaces, the
1261+original copyright holder who places the Program under this License
1262+may add an explicit geographical distribution limitation excluding
1263+those countries, so that distribution is permitted only in or among
1264+countries not thus excluded. In such case, this License incorporates
1265+the limitation as if written in the body of this License.
1266+
1267+ 9. The Free Software Foundation may publish revised and/or new versions
1268+of the General Public License from time to time. Such new versions will
1269+be similar in spirit to the present version, but may differ in detail to
1270+address new problems or concerns.
1271+
1272+Each version is given a distinguishing version number. If the Program
1273+specifies a version number of this License which applies to it and "any
1274+later version", you have the option of following the terms and conditions
1275+either of that version or of any later version published by the Free
1276+Software Foundation. If the Program does not specify a version number of
1277+this License, you may choose any version ever published by the Free Software
1278+Foundation.
1279+
1280+ 10. If you wish to incorporate parts of the Program into other free
1281+programs whose distribution conditions are different, write to the author
1282+to ask for permission. For software which is copyrighted by the Free
1283+Software Foundation, write to the Free Software Foundation; we sometimes
1284+make exceptions for this. Our decision will be guided by the two goals
1285+of preserving the free status of all derivatives of our free software and
1286+of promoting the sharing and reuse of software generally.
1287+
1288+ NO WARRANTY
1289+
1290+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
1291+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
1292+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
1293+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
1294+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1295+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
1296+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
1297+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
1298+REPAIR OR CORRECTION.
1299+
1300+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
1301+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
1302+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
1303+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
1304+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
1305+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
1306+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
1307+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
1308+POSSIBILITY OF SUCH DAMAGES.
1309+
1310+ END OF TERMS AND CONDITIONS
1311+
1312+ How to Apply These Terms to Your New Programs
1313+
1314+ If you develop a new program, and you want it to be of the greatest
1315+possible use to the public, the best way to achieve this is to make it
1316+free software which everyone can redistribute and change under these terms.
1317+
1318+ To do so, attach the following notices to the program. It is safest
1319+to attach them to the start of each source file to most effectively
1320+convey the exclusion of warranty; and each file should have at least
1321+the "copyright" line and a pointer to where the full notice is found.
1322+
1323+ <one line to give the program's name and a brief idea of what it does.>
1324+ Copyright (C) <year> <name of author>
1325+
1326+ This program is free software; you can redistribute it and/or modify
1327+ it under the terms of the GNU General Public License as published by
1328+ the Free Software Foundation; either version 2 of the License, or
1329+ (at your option) any later version.
1330+
1331+ This program is distributed in the hope that it will be useful,
1332+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1333+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1334+ GNU General Public License for more details.
1335+
1336+ You should have received a copy of the GNU General Public License along
1337+ with this program; if not, write to the Free Software Foundation, Inc.,
1338+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1339+
1340+Also add information on how to contact you by electronic and paper mail.
1341+
1342+If the program is interactive, make it output a short notice like this
1343+when it starts in an interactive mode:
1344+
1345+ Gnomovision version 69, Copyright (C) year name of author
1346+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
1347+ This is free software, and you are welcome to redistribute it
1348+ under certain conditions; type `show c' for details.
1349+
1350+The hypothetical commands `show w' and `show c' should show the appropriate
1351+parts of the General Public License. Of course, the commands you use may
1352+be called something other than `show w' and `show c'; they could even be
1353+mouse-clicks or menu items--whatever suits your program.
1354+
1355+You should also get your employer (if you work as a programmer) or your
1356+school, if any, to sign a "copyright disclaimer" for the program, if
1357+necessary. Here is a sample; alter the names:
1358+
1359+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
1360+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
1361+
1362+ <signature of Ty Coon>, 1 April 1989
1363+ Ty Coon, President of Vice
1364+
1365+This General Public License does not permit incorporating your program into
1366+proprietary programs. If your program is a subroutine library, you may
1367+consider it more useful to permit linking proprietary applications with the
1368+library. If this is what you want to do, use the GNU Lesser General
1369+Public License instead of this License.
1370+
1371
1372=== renamed file 'COPYING' => 'COPYING.moved'
1373=== added file 'MANIFEST.in'
1374--- MANIFEST.in 1970-01-01 00:00:00 +0000
1375+++ MANIFEST.in 2011-03-11 21:10:49 +0000
1376@@ -0,0 +1,13 @@
1377+include COPYING AUTHORS README CHANGELOG
1378+include cobbler.spec
1379+
1380+recursive-include aux *
1381+recursive-include config *
1382+recursive-include docs *
1383+recursive-include installer_templates *
1384+recursive-include kickstarts *
1385+recursive-include snippets *
1386+recursive-include scripts *
1387+recursive-include templates *
1388+recursive-include web *
1389+
1390
1391=== renamed file 'MANIFEST.in' => 'MANIFEST.in.moved'
1392=== added file 'README'
1393--- README 1970-01-01 00:00:00 +0000
1394+++ README 2011-03-11 21:10:49 +0000
1395@@ -0,0 +1,9 @@
1396+Cobbler README
1397+
1398+Docs are currently available two ways:
1399+- Install the RPM and run "man cobbler"
1400+- Run "perldoc cobbler.pod" from a source checkout
1401+
1402+To build the RPM:
1403+- Run "make"
1404+
1405
1406=== renamed file 'README' => 'README.moved'
1407=== added directory 'aux'
1408=== renamed directory 'aux' => 'aux.moved'
1409=== added file 'aux/anamon'
1410--- aux/anamon 1970-01-01 00:00:00 +0000
1411+++ aux/anamon 2011-03-11 21:10:49 +0000
1412@@ -0,0 +1,280 @@
1413+#!/usr/bin/python
1414+
1415+"""
1416+This is a script used to automatically log details from an Anaconda
1417+install back to a cobbler server.
1418+
1419+Copyright 2008, Red Hat, Inc
1420+various@redhat.com
1421+
1422+This program is free software; you can redistribute it and/or modify
1423+it under the terms of the GNU General Public License as published by
1424+the Free Software Foundation; either version 2 of the License, or
1425+(at your option) any later version.
1426+
1427+This program is distributed in the hope that it will be useful,
1428+but WITHOUT ANY WARRANTY; without even the implied warranty of
1429+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1430+GNU General Public License for more details.
1431+
1432+You should have received a copy of the GNU General Public License
1433+along with this program; if not, write to the Free Software
1434+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
1435+02110-1301 USA
1436+"""
1437+
1438+import os
1439+import sys
1440+import string
1441+import time
1442+import re
1443+import base64
1444+import shlex
1445+
1446+# on older installers (EL 2) we might not have xmlrpclib
1447+# and can't do logging, however this is more widely
1448+# supported than remote syslog and also provides more
1449+# detail.
1450+try:
1451+ import xmlrpclib
1452+except ImportError, e:
1453+ print "xmlrpclib not available, exiting"
1454+ sys.exit(0)
1455+
1456+# shlex.split support arrived in python-2.3, the following will provide some
1457+# accomodation for older distros (e.g. RHEL3)
1458+if not hasattr(shlex, "split"):
1459+ shlex.split = lambda s: s.split(" ")
1460+
1461+class WatchedFile:
1462+ def __init__(self, fn, alias):
1463+ self.fn = fn
1464+ self.alias = alias
1465+ self.reset()
1466+
1467+ def reset(self):
1468+ self.where = 0
1469+ self.last_size = 0
1470+ self.lfrag=''
1471+ self.re_list={}
1472+ self.seen_line={}
1473+
1474+ def exists(self):
1475+ return os.access(self.fn, os.F_OK)
1476+
1477+ def lookfor(self,pattern):
1478+ self.re_list[pattern] = re.compile(pattern,re.MULTILINE)
1479+ self.seen_line[pattern] = 0
1480+
1481+ def seen(self,pattern):
1482+ if self.seen_line.has_key(pattern):
1483+ return self.seen_line[pattern]
1484+ else:
1485+ return 0
1486+
1487+ def changed(self):
1488+ if not self.exists():
1489+ return 0
1490+ size = os.stat(self.fn)[6]
1491+ if size > self.last_size:
1492+ self.last_size = size
1493+ return 1
1494+ else:
1495+ return 0
1496+
1497+ def uploadWrapper(self, blocksize = 262144):
1498+ """upload a file in chunks using the uploadFile call"""
1499+ retries = 3
1500+ fo = file(self.fn, "r")
1501+ totalsize = os.path.getsize(self.fn)
1502+ ofs = 0
1503+ while True:
1504+ lap = time.time()
1505+ contents = fo.read(blocksize)
1506+ size = len(contents)
1507+ data = base64.encodestring(contents)
1508+ if size == 0:
1509+ offset = -1
1510+ sz = ofs
1511+ else:
1512+ offset = ofs
1513+ sz = size
1514+ del contents
1515+ tries = 0
1516+ while tries <= retries:
1517+ debug("upload_log_data('%s', '%s', %s, %s, ...)\n" % (name, self.alias, sz, offset))
1518+ if session.upload_log_data(name, self.alias, sz, offset, data):
1519+ break
1520+ else:
1521+ tries = tries + 1
1522+ if size == 0:
1523+ break
1524+ ofs += size
1525+ fo.close()
1526+
1527+ def update(self):
1528+ if not self.exists():
1529+ return
1530+ if not self.changed():
1531+ return
1532+ try:
1533+ self.uploadWrapper()
1534+ except:
1535+ raise
1536+
1537+class MountWatcher:
1538+
1539+ def __init__(self,mp):
1540+ self.mountpoint = mp
1541+ self.zero()
1542+
1543+ def zero(self):
1544+ self.line=''
1545+ self.time = time.time()
1546+
1547+ def update(self):
1548+ found = 0
1549+ if os.path.exists('/proc/mounts'):
1550+ fd = open('/proc/mounts')
1551+ while 1:
1552+ line = fd.readline()
1553+ if not line:
1554+ break
1555+ parts = string.split(line)
1556+ mp = parts[1]
1557+ if mp == self.mountpoint:
1558+ found = 1
1559+ if line != self.line:
1560+ self.line = line
1561+ self.time = time.time()
1562+ fd.close()
1563+ if not found:
1564+ self.zero()
1565+
1566+ def stable(self):
1567+ self.update()
1568+ if self.line and (time.time() - self.time > 60):
1569+ return 1
1570+ else:
1571+ return 0
1572+
1573+def anamon_loop():
1574+ alog = WatchedFile("/tmp/anaconda.log", "anaconda.log")
1575+ alog.lookfor("step installpackages$")
1576+
1577+ slog = WatchedFile("/tmp/syslog", "sys.log")
1578+ xlog = WatchedFile("/tmp/X.log", "X.log")
1579+ llog = WatchedFile("/tmp/lvmout", "lvmout.log")
1580+ storage_log = WatchedFile("/tmp/storage.log", "storage.log")
1581+ prgm_log = WatchedFile("/tmp/program.log", "program.log")
1582+ vnc_log = WatchedFile("/tmp/vncserver.log", "vncserver.log")
1583+ kcfg = WatchedFile("/tmp/ks.cfg", "ks.cfg")
1584+ scrlog = WatchedFile("/tmp/ks-script.log", "ks-script.log")
1585+ dump = WatchedFile("/tmp/anacdump.txt", "anacdump.txt")
1586+ mod = WatchedFile("/tmp/modprobe.conf", "modprobe.conf")
1587+
1588+ # Setup '/mnt/sysimage' watcher
1589+ sysimage = MountWatcher("/mnt/sysimage")
1590+
1591+ # Monitor for {install,upgrade}.log changes
1592+ package_logs = list()
1593+ package_logs.append(WatchedFile("/mnt/sysimage/root/install.log", "install.log"))
1594+ package_logs.append(WatchedFile("/mnt/sysimage/tmp/install.log", "tmp+install.log"))
1595+ package_logs.append(WatchedFile("/mnt/sysimage/root/upgrade.log", "upgrade.log"))
1596+ package_logs.append(WatchedFile("/mnt/sysimage/tmp/upgrade.log", "tmp+upgrade.log"))
1597+
1598+ # Monitor for bootloader configuration changes
1599+ bootloader_cfgs = list()
1600+ bootloader_cfgs.append(WatchedFile("/mnt/sysimage/boot/grub/grub.conf", "grub.conf"))
1601+ bootloader_cfgs.append(WatchedFile("/mnt/sysimage/boot/etc/yaboot.conf", "yaboot.conf"))
1602+ bootloader_cfgs.append(WatchedFile("/mnt/sysimage/boot/efi/efi/redhat/elilo.conf", "elilo.conf"))
1603+ bootloader_cfgs.append(WatchedFile("/mnt/sysimage/etc/zipl.conf", "zipl.conf"))
1604+
1605+ # Were we asked to watch specific files?
1606+ watchlist = list()
1607+ waitlist = list()
1608+ if watchfiles:
1609+ # Create WatchedFile objects for each requested file
1610+ for watchfile in watchfiles:
1611+ if os.path.exists(watchfile):
1612+ watchfilebase = os.path.basename(watchfile)
1613+ watchlog = WatchedFile(watchfile, watchfilebase)
1614+ watchlist.append(watchlog)
1615+
1616+ # Use the default watchlist and waitlist
1617+ else:
1618+ watchlist = [alog, slog, dump, scrlog, mod, llog, kcfg, storage_log, prgm_log, vnc_log, xlog]
1619+ waitlist.extend(package_logs)
1620+ waitlist.extend(bootloader_cfgs)
1621+
1622+ # Monitor loop
1623+ while 1:
1624+ time.sleep(5)
1625+
1626+ # Not all log files are available at the start, we'll loop through the
1627+ # waitlist to determine when each file can be added to the watchlist
1628+ for watch in waitlist:
1629+ if alog.seen("step installpackages$") or (sysimage.stable() and watch.exists()):
1630+ debug("Adding %s to watch list\n" % watch.alias)
1631+ watchlist.append(watch)
1632+ waitlist.remove(watch)
1633+
1634+ # Send any updates
1635+ for wf in watchlist:
1636+ wf.update()
1637+
1638+ # If asked to run_once, exit now
1639+ if exit:
1640+ break
1641+
1642+# Establish some defaults
1643+name = ""
1644+server = ""
1645+port = "80"
1646+daemon = 1
1647+debug = lambda x,**y: None
1648+watchfiles = []
1649+exit = False
1650+
1651+# Process command-line args
1652+n = 0
1653+while n < len(sys.argv):
1654+ arg = sys.argv[n]
1655+ if arg == '--name':
1656+ n = n+1
1657+ name = sys.argv[n]
1658+ elif arg == '--watchfile':
1659+ n = n+1
1660+ watchfiles.extend(shlex.split(sys.argv[n]))
1661+ elif arg == '--exit':
1662+ exit = True
1663+ elif arg == '--server':
1664+ n = n+1
1665+ server = sys.argv[n]
1666+ elif arg == '--port':
1667+ n = n+1
1668+ port = sys.argv[n]
1669+ elif arg == '--debug':
1670+ debug = lambda x,**y: sys.stderr.write(x % y)
1671+ elif arg == '--fg':
1672+ daemon = 0
1673+ n = n+1
1674+
1675+# Create an xmlrpc session handle
1676+session = xmlrpclib.Server("http://%s:%s/cobbler_api" % (server, port))
1677+
1678+# Fork and loop
1679+if daemon:
1680+ if not os.fork():
1681+ # Redirect the standard I/O file descriptors to the specified file.
1682+ DEVNULL = getattr(os, "devnull", "/dev/null")
1683+ os.open(DEVNULL, os.O_RDWR) # standard input (0)
1684+ os.dup2(0, 1) # Duplicate standard input to standard output (1)
1685+ os.dup2(0, 2) # Duplicate standard input to standard error (2)
1686+
1687+ anamon_loop()
1688+ sys.exit(1)
1689+ sys.exit(0)
1690+else:
1691+ anamon_loop()
1692+
1693
1694=== added file 'aux/anamon.init'
1695--- aux/anamon.init 1970-01-01 00:00:00 +0000
1696+++ aux/anamon.init 2011-03-11 21:10:49 +0000
1697@@ -0,0 +1,101 @@
1698+#!/bin/bash
1699+## BEGIN INIT INFO
1700+# Provides: anamon
1701+# Default-Start: 3 5
1702+# Default-Stop: 0 1 2 4 6
1703+# Required-Start:
1704+# Should-Start: $network
1705+# Short-Description: Starts the cobbler anamon boot notification program
1706+# Description: anamon runs the first time a machine is booted after
1707+# installation.
1708+## END INIT INFO
1709+
1710+#
1711+# anamon: Starts the cobbler post-install boot notification program
1712+#
1713+# chkconfig: 35 99 95
1714+#
1715+# description: anamon runs the first time a machine is booted after
1716+# installation.
1717+#
1718+
1719+LOCKFILE="/var/lock/subsys/anamon"
1720+CFGFILE="/etc/sysconfig/anamon"
1721+
1722+# Source function library.
1723+. /etc/init.d/functions
1724+
1725+# Source anamon config
1726+. $CFGFILE
1727+
1728+LOGFILES=${LOGFILES:-/var/log/boot.log}
1729+
1730+# FIXME - can we rely on the koan snippet to update /etc/profile.d/cobbler.sh?
1731+if [ -z "$COBBLER_SERVER" ]; then
1732+ echo "No COBBLER_SERVER defined in $CFGFILE"
1733+ exit 1
1734+fi
1735+
1736+if [ -z "$COBBLER_NAME" ]; then
1737+ echo "No COBBLER_NAME defined in $CFGFILE"
1738+ exit 1
1739+fi
1740+
1741+if [ -z "$LOGFILES" ]; then
1742+ echo "No LOGFILES defined in $CFGFILE"
1743+ exit 1
1744+fi
1745+
1746+start() {
1747+ echo -n $"Starting anamon: "
1748+ daemon /usr/local/sbin/anamon --watchfile \"$LOGFILES\" --name $COBBLER_NAME --server $COBBLER_SERVER --port ${COBBLER_PORT:-80} --exit
1749+ RETVAL=$?
1750+ [ $RETVAL -eq 0 ] && touch $LOCKFILE
1751+ echo
1752+
1753+ # Disable service start
1754+ chkconfig anamon off
1755+
1756+ return $RETVAL
1757+}
1758+
1759+stop () {
1760+ echo -n $"Shutting down anamon: "
1761+ killproc /usr/local/sbin/anamon
1762+ RETVAL=$?
1763+ [ $RETVAL -eq 0 ] && rm -f $LOCKFILE
1764+ echo
1765+ return $RETVAL
1766+}
1767+
1768+restart() {
1769+ stop
1770+ start
1771+}
1772+
1773+case "$1" in
1774+ start)
1775+ start
1776+ ;;
1777+ stop)
1778+ stop
1779+ ;;
1780+ restart)
1781+ restart
1782+ ;;
1783+ condrestart)
1784+ if [ -f $LOCKFILE ]; then
1785+ restart
1786+ fi
1787+ ;;
1788+ status)
1789+ status anamon
1790+ RETVAL=$?
1791+ ;;
1792+ *)
1793+ echo $"Usage: $0 {start|stop|status|restart|condrestart}"
1794+ RETVAL=2
1795+ ;;
1796+esac
1797+
1798+exit $RETVAL
1799
1800=== added directory 'cobbler'
1801=== renamed directory 'cobbler' => 'cobbler.moved'
1802=== added file 'cobbler.spec'
1803--- cobbler.spec 1970-01-01 00:00:00 +0000
1804+++ cobbler.spec 2011-03-11 21:10:49 +0000
1805@@ -0,0 +1,266 @@
1806+%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
1807+%{!?pyver: %define pyver %(%{__python} -c "import sys ; print sys.version[:3]" || echo 0)}
1808+
1809+%define _binaries_in_noarch_packages_terminate_build 0
1810+%global debug_package %{nil}
1811+Summary: Boot server configurator
1812+Name: cobbler
1813+License: GPLv2+
1814+AutoReq: no
1815+Version: 2.1.0
1816+Release: 2%{?dist}
1817+Source0: http://shenson.fedorapeople.org/cobbler/cobbler-%{version}.tar.gz
1818+Group: Applications/System
1819+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
1820+BuildArch: noarch
1821+Url: http://fedorahosted.org/cobbler
1822+
1823+BuildRequires: redhat-rpm-config
1824+BuildRequires: PyYAML
1825+BuildRequires: python-cheetah
1826+
1827+Requires: python >= 2.3
1828+Requires: httpd
1829+Requires: tftp-server
1830+Requires: mod_wsgi
1831+Requires: createrepo
1832+Requires: python-cheetah
1833+Requires: python-netaddr
1834+Requires: python-simplejson
1835+Requires: python-urlgrabber
1836+Requires: PyYAML
1837+Requires: rsync
1838+
1839+%if 0%{?fedora} >= 11 || 0%{?rhel} >= 6
1840+Requires: python(abi) >= %{pyver}
1841+Requires: genisoimage
1842+%else
1843+Requires: mkisofs
1844+%endif
1845+%if 0%{?fedora} >= 8
1846+BuildRequires: python-setuptools-devel
1847+%else
1848+BuildRequires: python-setuptools
1849+%endif
1850+%if 0%{?fedora} >= 6 || 0%{?rhel} >= 5
1851+Requires: yum-utils
1852+%endif
1853+
1854+Requires(post): /sbin/chkconfig
1855+Requires(preun): /sbin/chkconfig
1856+Requires(preun): /sbin/service
1857+
1858+%description
1859+
1860+Cobbler is a network install server. Cobbler supports PXE,
1861+virtualized installs, and re-installing existing Linux machines. The
1862+last two modes use a helper tool, 'koan', that integrates with
1863+cobbler. There is also a web interface 'cobbler-web'. Cobbler's
1864+advanced features include importing distributions from DVDs and rsync
1865+mirrors, kickstart templating, integrated yum mirroring, and built-in
1866+DHCP/DNS Management. Cobbler has a XMLRPC API for integration with
1867+other applications.
1868+
1869+%prep
1870+%setup -q
1871+
1872+%build
1873+%{__python} setup.py build
1874+
1875+%install
1876+test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT
1877+%{__python} setup.py install --optimize=1 --root=$RPM_BUILD_ROOT $PREFIX
1878+mkdir -p $RPM_BUILD_ROOT/etc/httpd/conf.d
1879+install -p -m 644 config/cobbler.conf $RPM_BUILD_ROOT/etc/httpd/conf.d/
1880+install -p -m 644 config/cobbler_web.conf $RPM_BUILD_ROOT/etc/httpd/conf.d/
1881+
1882+mkdir -p $RPM_BUILD_ROOT/var/spool/koan
1883+
1884+%if 0%{?fedora} >= 9 || 0%{?rhel} > 5
1885+mkdir -p $RPM_BUILD_ROOT/var/lib/tftpboot/images
1886+%else
1887+mkdir -p $RPM_BUILD_ROOT/tftpboot/images
1888+%endif
1889+
1890+rm -f $RPM_BUILD_ROOT/etc/cobbler/cobblerd
1891+
1892+%clean
1893+test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT
1894+
1895+%post
1896+if [ "$1" = "1" ];
1897+then
1898+ # This happens upon initial install. Upgrades will follow the next else
1899+ /sbin/chkconfig --add cobblerd
1900+elif [ "$1" -ge "2" ];
1901+then
1902+ # backup config
1903+ if [ -e /var/lib/cobbler/distros ]; then
1904+ cp /var/lib/cobbler/distros* /var/lib/cobbler/backup 2>/dev/null
1905+ cp /var/lib/cobbler/profiles* /var/lib/cobbler/backup 2>/dev/null
1906+ cp /var/lib/cobbler/systems* /var/lib/cobbler/backup 2>/dev/null
1907+ cp /var/lib/cobbler/repos* /var/lib/cobbler/backup 2>/dev/null
1908+ cp /var/lib/cobbler/networks* /var/lib/cobbler/backup 2>/dev/null
1909+ cp /var/lib/cobbler/mgmtclasses* /var/lib/cobbler/backup 2>/dev/null
1910+ cp /var/lib/cobbler/packages* /var/lib/cobbler/backup 2>/dev/null
1911+ cp /var/lib/cobbler/files* /var/lib/cobbler/backup 2>/dev/null
1912+ fi
1913+ if [ -e /var/lib/cobbler/config ]; then
1914+ cp -a /var/lib/cobbler/config /var/lib/cobbler/backup 2>/dev/null
1915+ fi
1916+ # upgrade older installs
1917+ # move power and pxe-templates from /etc/cobbler, backup new templates to *.rpmnew
1918+ for n in power pxe; do
1919+ rm -f /etc/cobbler/$n*.rpmnew
1920+ find /etc/cobbler -maxdepth 1 -name "$n*" -type f | while read f; do
1921+ newf=/etc/cobbler/$n/`basename $f`
1922+ [ -e $newf ] && mv $newf $newf.rpmnew
1923+ mv $f $newf
1924+ done
1925+ done
1926+ # upgrade older installs
1927+ # copy kickstarts from /etc/cobbler to /var/lib/cobbler/kickstarts
1928+ rm -f /etc/cobbler/*.ks.rpmnew
1929+ find /etc/cobbler -maxdepth 1 -name "*.ks" -type f | while read f; do
1930+ newf=/var/lib/cobbler/kickstarts/`basename $f`
1931+ [ -e $newf ] && mv $newf $newf.rpmnew
1932+ cp $f $newf
1933+ done
1934+ /sbin/service cobblerd condrestart
1935+fi
1936+
1937+%preun
1938+if [ $1 = 0 ]; then
1939+ /sbin/service cobblerd stop >/dev/null 2>&1 || :
1940+ chkconfig --del cobblerd || :
1941+fi
1942+
1943+%postun
1944+if [ "$1" -ge "1" ]; then
1945+ /sbin/service cobblerd condrestart >/dev/null 2>&1 || :
1946+ /sbin/service httpd condrestart >/dev/null 2>&1 || :
1947+fi
1948+
1949+
1950+%files
1951+
1952+%defattr(-,root,root,-)
1953+
1954+%{_bindir}/cobbler
1955+%{_bindir}/cobbler-ext-nodes
1956+%{_bindir}/cobblerd
1957+%{_sbindir}/tftpd.py*
1958+
1959+%config(noreplace) %{_sysconfdir}/cobbler
1960+/etc/init.d/cobblerd
1961+
1962+%{python_sitelib}/cobbler
1963+
1964+%config(noreplace) /var/lib/cobbler
1965+
1966+/var/log/cobbler
1967+/var/www/cobbler
1968+
1969+%{_mandir}/man1/cobbler.1.gz
1970+
1971+%config(noreplace) /etc/httpd/conf.d/cobbler.conf
1972+
1973+%if 0%{?fedora} >= 9 || 0%{?rhel} >= 5
1974+%exclude %{python_sitelib}/cobbler/sub_process.py*
1975+%endif
1976+%if 0%{?fedora} >= 9 || 0%{?rhel} > 5
1977+%{python_sitelib}/cobbler*.egg-info
1978+/var/lib/tftpboot/images
1979+%else
1980+/tftpboot/images
1981+%endif
1982+
1983+%doc AUTHORS CHANGELOG README COPYING
1984+
1985+%package -n koan
1986+
1987+Summary: Helper tool that performs cobbler orders on remote machines
1988+Group: Applications/System
1989+Requires: python >= 2.0
1990+%if 0%{?fedora} >= 11 || 0%{?rhel} >= 6
1991+Requires: python(abi) >= %{pyver}
1992+%endif
1993+
1994+
1995+%description -n koan
1996+
1997+Koan stands for kickstart-over-a-network and allows for both
1998+network installation of new virtualized guests and reinstallation
1999+of an existing system. For use with a boot-server configured with Cobbler
2000+
2001+%files -n koan
2002+%defattr(-,root,root,-)
2003+%dir /var/spool/koan
2004+%dir /var/lib/koan/config
2005+%{_bindir}/koan
2006+%{_bindir}/cobbler-register
2007+%{python_sitelib}/koan
2008+
2009+%if 0%{?fedora} >= 9 || 0%{?rhel} >= 5
2010+%exclude %{python_sitelib}/koan/sub_process.py*
2011+%exclude %{python_sitelib}/koan/opt_parse.py*
2012+%exclude %{python_sitelib}/koan/text_wrap.py*
2013+%endif
2014+
2015+%{_mandir}/man1/koan.1.gz
2016+%{_mandir}/man1/cobbler-register.1.gz
2017+%dir /var/log/koan
2018+%doc AUTHORS COPYING CHANGELOG README
2019+
2020+
2021+%package -n cobbler-web
2022+
2023+Summary: Web interface for Cobbler
2024+Group: Applications/System
2025+Requires: cobbler
2026+Requires: Django
2027+%if 0%{?fedora} >= 11 || 0%{?rhel} >= 6
2028+Requires: python(abi) >= %{pyver}
2029+%endif
2030+
2031+%description -n cobbler-web
2032+
2033+Web interface for Cobbler that allows visiting
2034+http://server/cobbler_web to configure the install server.
2035+
2036+%files -n cobbler-web
2037+%defattr(-,root,root,-)
2038+%doc AUTHORS COPYING CHANGELOG README
2039+%config(noreplace) /etc/httpd/conf.d/cobbler_web.conf
2040+%defattr(-,apache,apache,-)
2041+/usr/share/cobbler/web
2042+%dir /var/lib/cobbler/webui_sessions
2043+/var/www/cobbler_webui_content/
2044+
2045+%changelog
2046+* Thu Jun 17 2010 Scott Henson <shenson@redhat.com> - 2.1.0-1
2047+- Bump upstream release
2048+
2049+* Tue Apr 27 2010 Scott Henson <shenson@redhat.com> - 2.0.4-1
2050+- Bug fix release, see Changelog for details
2051+
2052+* Thu Apr 15 2010 Devan Goodwin <dgoodwin@rm-rf.ca> 2.0.3.2-1
2053+- Tagging for new build tools.
2054+
2055+* Mon Mar 1 2010 Scott Henson <shenson@redhat.com> - 2.0.3.1-3
2056+- Bump release because I forgot cobbler-web
2057+
2058+* Mon Mar 1 2010 Scott Henson <shenson@redhat.com> - 2.0.3.1-2
2059+- Remove requires on mkinitrd as it is not used
2060+
2061+* Mon Feb 15 2010 Scott Henson <shenson@redhat.com> - 2.0.3.1-1
2062+- Upstream Brown Paper Bag Release (see CHANGELOG)
2063+
2064+* Thu Feb 11 2010 Scott Henson <shenson@redhat.com> - 2.0.3-1
2065+- Upstream changes (see CHANGELOG)
2066+
2067+* Mon Nov 23 2009 John Eckersberg <jeckersb@redhat.com> - 2.0.2-1
2068+- Upstream changes (see CHANGELOG)
2069+
2070+* Tue Sep 15 2009 Michael DeHaan <mdehaan@redhat.com> - 2.0.0-1
2071+- First release with unified spec files
2072
2073=== renamed file 'cobbler.spec' => 'cobbler.spec.moved'
2074=== added file 'cobbler/__init__.py'
2075=== added file 'cobbler/action_acl.py'
2076--- cobbler/action_acl.py 1970-01-01 00:00:00 +0000
2077+++ cobbler/action_acl.py 2011-03-11 21:10:49 +0000
2078@@ -0,0 +1,120 @@
2079+"""
2080+Configures acls for various users/groups so they can access the cobbler command
2081+line as non-root. Now that CLI is largely remoted (XMLRPC) this is largely just
2082+useful for not having to log in (access to shared-secret) file but also grants
2083+access to hand-edit various config files and other useful things.
2084+
2085+Copyright 2006-2009, Red Hat, Inc
2086+Michael DeHaan <mdehaan@redhat.com>
2087+
2088+This program is free software; you can redistribute it and/or modify
2089+it under the terms of the GNU General Public License as published by
2090+the Free Software Foundation; either version 2 of the License, or
2091+(at your option) any later version.
2092+
2093+This program is distributed in the hope that it will be useful,
2094+but WITHOUT ANY WARRANTY; without even the implied warranty of
2095+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2096+GNU General Public License for more details.
2097+
2098+You should have received a copy of the GNU General Public License
2099+along with this program; if not, write to the Free Software
2100+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2101+02110-1301 USA
2102+"""
2103+
2104+import os
2105+import os.path
2106+import shutil
2107+import sys
2108+import glob
2109+import traceback
2110+import errno
2111+import utils
2112+from cexceptions import *
2113+from utils import _
2114+import clogger
2115+
2116+class AclConfig:
2117+
2118+ def __init__(self,config,logger=None):
2119+ """
2120+ Constructor
2121+ """
2122+ self.config = config
2123+ self.api = config.api
2124+ self.settings = config.settings()
2125+ if logger is None:
2126+ logger = clogger.Logger()
2127+ self.logger = logger
2128+
2129+ def run(self,adduser=None,addgroup=None,removeuser=None,removegroup=None):
2130+ """
2131+ Automate setfacl commands
2132+ """
2133+
2134+ ok = False
2135+ if adduser:
2136+ ok = True
2137+ self.modacl(True,True,adduser)
2138+ if addgroup:
2139+ ok = True
2140+ self.modacl(True,False,addgroup)
2141+ if removeuser:
2142+ ok = True
2143+ self.modacl(False,True,removeuser)
2144+ if removegroup:
2145+ ok = True
2146+ self.modacl(False,False,removegroup)
2147+ if not ok:
2148+ raise CX("no arguments specified, nothing to do")
2149+
2150+ def modacl(self,isadd,isuser,who):
2151+
2152+ webdir = self.settings.webdir
2153+ snipdir = self.settings.snippetsdir
2154+ tftpboot = utils.tftpboot_location()
2155+
2156+ PROCESS_DIRS = {
2157+ "/var/log/cobbler" : "rwx",
2158+ "/var/log/cobbler/tasks" : "rwx",
2159+ "/var/lib/cobbler" : "rwx",
2160+ "/etc/cobbler" : "rwx",
2161+ tftpboot : "rwx",
2162+ "/var/lib/cobbler/triggers" : "rwx"
2163+ }
2164+ if not snipdir.startswith("/var/lib/cobbler/"):
2165+ PROCESS_DIRS[snipdir] = "r"
2166+
2167+ cmd = "-R"
2168+
2169+ if isadd:
2170+ cmd = "%s -m" % cmd
2171+ else:
2172+ cmd = "%s -x" % cmd
2173+
2174+ if isuser:
2175+ cmd = "%s u:%s" % (cmd,who)
2176+ else:
2177+ cmd = "%s g:%s" % (cmd,who)
2178+
2179+ for d in PROCESS_DIRS:
2180+ how = PROCESS_DIRS[d]
2181+ if isadd:
2182+ cmd2 = "%s:%s" % (cmd,how)
2183+ else:
2184+ cmd2 = cmd
2185+
2186+ cmd2 = "%s %s" % (cmd2,d)
2187+ rc = utils.subprocess_call(self.logger,"setfacl -d %s" % cmd2,shell=True)
2188+ if not rc == 0:
2189+ utils.die(self.logger,"command failed")
2190+ rc = utils.subprocess_call(self.logger,"setfacl %s" % cmd2,shell=True)
2191+ if not rc == 0:
2192+ utils.die(self.logger,"command failed")
2193+
2194+
2195+
2196+
2197+
2198+
2199
2200=== added file 'cobbler/action_buildiso.py'
2201--- cobbler/action_buildiso.py 1970-01-01 00:00:00 +0000
2202+++ cobbler/action_buildiso.py 2011-03-11 21:10:49 +0000
2203@@ -0,0 +1,447 @@
2204+"""
2205+Builds non-live bootable CD's that have PXE-equivalent behavior
2206+for all cobbler profiles currently in memory.
2207+
2208+Copyright 2006-2009, Red Hat, Inc
2209+Michael DeHaan <mdehaan@redhat.com>
2210+
2211+This program is free software; you can redistribute it and/or modify
2212+it under the terms of the GNU General Public License as published by
2213+the Free Software Foundation; either version 2 of the License, or
2214+(at your option) any later version.
2215+
2216+This program is distributed in the hope that it will be useful,
2217+but WITHOUT ANY WARRANTY; without even the implied warranty of
2218+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2219+GNU General Public License for more details.
2220+
2221+You should have received a copy of the GNU General Public License
2222+along with this program; if not, write to the Free Software
2223+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2224+02110-1301 USA
2225+"""
2226+
2227+import os
2228+import os.path
2229+import shutil
2230+import sys
2231+import traceback
2232+import shutil
2233+import re
2234+
2235+import utils
2236+from cexceptions import *
2237+from utils import _
2238+import clogger
2239+
2240+# FIXME: lots of overlap with pxegen.py, should consolidate
2241+# FIXME: disable timeouts and remove local boot for this?
2242+HEADER = """
2243+
2244+DEFAULT menu
2245+PROMPT 0
2246+MENU TITLE Cobbler | http://cobbler.et.redhat.com
2247+TIMEOUT 200
2248+TOTALTIMEOUT 6000
2249+ONTIMEOUT local
2250+
2251+LABEL local
2252+ MENU LABEL (local)
2253+ MENU DEFAULT
2254+ KERNEL chain.c32
2255+ APPEND hd0 0
2256+
2257+"""
2258+
2259+class BuildIso:
2260+ """
2261+ Handles conversion of internal state to the tftpboot tree layout
2262+ """
2263+
2264+ def __init__(self,config,verbose=False,logger=None):
2265+ """
2266+ Constructor
2267+ """
2268+ self.verbose = verbose
2269+ self.config = config
2270+ self.api = config.api
2271+ self.distros = config.distros()
2272+ self.profiles = config.profiles()
2273+ self.systems = config.systems()
2274+ self.distros = config.distros()
2275+ self.distmap = {}
2276+ self.distctr = 0
2277+ self.source = ""
2278+ if logger is None:
2279+ logger = clogger.Logger()
2280+ self.logger = logger
2281+
2282+
2283+ def make_shorter(self,distname):
2284+ if self.distmap.has_key(distname):
2285+ return self.distmap[distname]
2286+ else:
2287+ self.distctr = self.distctr + 1
2288+ self.distmap[distname] = str(self.distctr)
2289+ return str(self.distctr)
2290+
2291+
2292+ def generate_netboot_iso(self,imagesdir,isolinuxdir,profiles=None,systems=None,exclude_dns=None):
2293+ self.logger.info("copying kernels and initrds for profiles")
2294+ # copy all images in included profiles to images dir
2295+ for profile in self.api.profiles():
2296+ use_this = True
2297+ if profiles is not None:
2298+ which_profiles = profiles.split(",")
2299+ if not profile.name in which_profiles:
2300+ use_this = False
2301+
2302+ if use_this:
2303+ dist = profile.get_conceptual_parent()
2304+ if dist.name.lower().find("-xen") != -1:
2305+ self.logger.info("skipping Xen distro: %s" % dist.name)
2306+ continue
2307+ distname = self.make_shorter(dist.name)
2308+ # buildisodir/isolinux/$distro/vmlinuz, initrd.img
2309+ # FIXME: this will likely crash on non-Linux breeds
2310+ f1 = os.path.join(isolinuxdir, "%s.krn" % distname)
2311+ f2 = os.path.join(isolinuxdir, "%s.img" % distname)
2312+ if not os.path.exists(dist.kernel):
2313+ utils.die(self.logger,"path does not exist: %s" % dist.kernel)
2314+ if not os.path.exists(dist.initrd):
2315+ utils.die(self.logger,"path does not exist: %s" % dist.initrd)
2316+ shutil.copyfile(dist.kernel, f1)
2317+ shutil.copyfile(dist.initrd, f2)
2318+
2319+ if systems is not None:
2320+ self.logger.info("copying kernels and initrds for systems")
2321+ # copy all images in included profiles to images dir
2322+ for system in self.api.systems():
2323+ if system.name in systems:
2324+ profile = system.get_conceptual_parent()
2325+ dist = profile.get_conceptual_parent()
2326+ if dist.name.find("-xen") != -1:
2327+ continue
2328+ distname = self.make_shorter(dist.name)
2329+ # buildisodir/isolinux/$distro/vmlinuz, initrd.img
2330+ # FIXME: this will likely crash on non-Linux breeds
2331+ shutil.copyfile(dist.kernel, os.path.join(isolinuxdir, "%s.krn" % distname))
2332+ shutil.copyfile(dist.initrd, os.path.join(isolinuxdir, "%s.img" % distname))
2333+
2334+ self.logger.info("generating a isolinux.cfg")
2335+ isolinuxcfg = os.path.join(isolinuxdir, "isolinux.cfg")
2336+ cfg = open(isolinuxcfg, "w+")
2337+ cfg.write(HEADER) # fixme, use template
2338+
2339+ self.logger.info("generating profile list")
2340+ #sort the profiles
2341+ profile_list = [profile for profile in self.profiles]
2342+ def sort_name(a,b):
2343+ return cmp(a.name,b.name)
2344+ profile_list.sort(sort_name)
2345+
2346+ for profile in profile_list:
2347+ use_this = True
2348+ if profiles is not None:
2349+ which_profiles = profiles.split(",")
2350+ if not profile.name in which_profiles:
2351+ use_this = False
2352+
2353+ if use_this:
2354+ dist = profile.get_conceptual_parent()
2355+ if dist.name.find("-xen") != -1:
2356+ continue
2357+ data = utils.blender(self.api, True, profile)
2358+ distname = self.make_shorter(dist.name)
2359+
2360+ cfg.write("\n")
2361+ cfg.write("LABEL %s\n" % profile.name)
2362+ cfg.write(" MENU LABEL %s\n" % profile.name)
2363+ cfg.write(" kernel %s.krn\n" % distname)
2364+
2365+ if data["kickstart"].startswith("/"):
2366+ data["kickstart"] = "http://%s:%s/cblr/svc/op/ks/profile/%s" % (
2367+ data["server"],
2368+ self.api.settings().http_port,
2369+ profile.name
2370+ )
2371+
2372+ append_line = " append initrd=%s.img" % distname
2373+ append_line = append_line + " ks=%s " % data["kickstart"]
2374+ append_line = append_line + " %s\n" % data["kernel_options"]
2375+
2376+ length=len(append_line)
2377+ if length>254:
2378+ self.logger.warning("append line length is greater than 254 chars: (%s chars)" % length)
2379+
2380+ cfg.write(append_line)
2381+
2382+ if systems is not None:
2383+ self.logger.info("generating system list")
2384+
2385+ cfg.write("\nMENU SEPARATOR\n")
2386+
2387+ #sort the systems
2388+ system_list = [system for system in self.systems]
2389+ def sort_name(a,b):
2390+ return cmp(a.name,b.name)
2391+ system_list.sort(sort_name)
2392+
2393+ for system in system_list:
2394+ use_this = False
2395+ if systems is not None:
2396+ which_systems = systems.split(",")
2397+ if system.name in which_systems:
2398+ use_this = True
2399+
2400+ if use_this:
2401+ profile = system.get_conceptual_parent()
2402+ dist = profile.get_conceptual_parent()
2403+ if dist.name.find("-xen") != -1:
2404+ continue
2405+ data = utils.blender(self.api, True, system)
2406+ distname = self.make_shorter(dist.name)
2407+
2408+ cfg.write("\n")
2409+ cfg.write("LABEL %s\n" % system.name)
2410+ cfg.write(" MENU LABEL %s\n" % system.name)
2411+ cfg.write(" kernel %s.krn\n" % distname)
2412+
2413+ if data["kickstart"].startswith("/"):
2414+ data["kickstart"] = "http://%s:%s/cblr/svc/op/ks/system/%s" % (
2415+ data["server"],
2416+ self.api.settings().http_port,
2417+ system.name
2418+ )
2419+
2420+ append_line = " append initrd=%s.img" % distname
2421+ append_line = append_line + " ks=%s" % data["kickstart"]
2422+ append_line = append_line + " %s" % data["kernel_options"]
2423+
2424+ # add network info to avoid DHCP only if it is available
2425+
2426+ if data.has_key("bonding_master_eth0") and data["bonding_master_eth0"] != "":
2427+ primary_interface = data["bonding_master_eth0"]
2428+ else:
2429+ primary_interface = "eth0"
2430+
2431+ # check if ksdevice entry exists and use that for network info
2432+
2433+ blended = utils.blender(self.api, False, system) # don't collapse
2434+
2435+ if blended["kernel_options"].has_key("ksdevice") and blended["kernel_options"]["ksdevice"] != "":
2436+ ksdevice = blended["kernel_options"]["ksdevice"]
2437+ self.logger.info(" - ksdevice %s set for system %s" % (ksdevice,system.name))
2438+
2439+ if data.has_key("ip_address_" + ksdevice ) and data["ip_address_" + ksdevice] != "":
2440+ primary_interface = ksdevice
2441+ else:
2442+
2443+ for (obj_iname, obj_interface) in data['interfaces'].iteritems():
2444+ mac = obj_interface["mac_address"].upper()
2445+ ksdevice_mac = ksdevice.upper()
2446+
2447+ if mac == ksdevice_mac:
2448+ primary_interface = obj_iname
2449+
2450+
2451+ if data.has_key("ip_address_" + primary_interface) and data["ip_address_" + primary_interface] != "":
2452+ append_line = append_line + " ip=%s" % data["ip_address_" + primary_interface]
2453+
2454+ if data.has_key("subnet_" + primary_interface) and data["subnet_" + primary_interface] != "":
2455+ append_line = append_line + " netmask=%s" % data["subnet_" + primary_interface]
2456+
2457+ if data.has_key("gateway") and data["gateway"] != "":
2458+ append_line = append_line + " gateway=%s" % data["gateway"]
2459+
2460+ if not exclude_dns and data.has_key("name_servers") and data["name_servers"]:
2461+ append_line = append_line + " dns=%s\n" % ",".join(data["name_servers"])
2462+
2463+ length=len(append_line)
2464+ if length > 254:
2465+ self.logger.warning("append line length is greater than 254 chars: (%s chars)" % length)
2466+
2467+ cfg.write(append_line)
2468+
2469+ self.logger.info("done writing config")
2470+ cfg.write("\n")
2471+ cfg.write("MENU END\n")
2472+ cfg.close()
2473+
2474+
2475+ def generate_standalone_iso(self,imagesdir,isolinuxdir,distname,filesource):
2476+
2477+ # Get the distro object for the requested distro
2478+ # and then get all of its descendants (profiles/sub-profiles/systems)
2479+ distro = self.api.find_distro(distname)
2480+ if distro is None:
2481+ utils.die(self.logger,"distro %s was not found, aborting" % distname)
2482+ descendants = distro.get_descendants()
2483+
2484+ if filesource is None:
2485+ # Try to determine the source from the distro kernel path
2486+ self.logger.debug("trying to locate source for distro")
2487+ found_source = False
2488+ (source_head, source_tail) = os.path.split(distro.kernel)
2489+ while source_tail != '':
2490+ if source_head == os.path.join(self.api.settings().webdir, "ks_mirror"):
2491+ filesource = os.path.join(source_head, source_tail)
2492+ found_source = True
2493+ self.logger.debug("found source in %s" % filesource)
2494+ break
2495+ (source_head, source_tail) = os.path.split(source_head)
2496+ # Can't find the source, raise an error
2497+ if not found_source:
2498+ utils.die(self.logger," Error, no installation source found. When building a standalone ISO, you must specify a --source if the distro install tree is not hosted locally")
2499+
2500+ self.logger.info("copying kernels and initrds for standalone distro")
2501+ # buildisodir/isolinux/$distro/vmlinuz, initrd.img
2502+ # FIXME: this will likely crash on non-Linux breeds
2503+ f1 = os.path.join(isolinuxdir, "vmlinuz")
2504+ f2 = os.path.join(isolinuxdir, "initrd.img")
2505+ if not os.path.exists(distro.kernel):
2506+ utils.die(self.logger,"path does not exist: %s" % distro.kernel)
2507+ if not os.path.exists(distro.initrd):
2508+ utils.die(self.logger,"path does not exist: %s" % distro.initrd)
2509+ shutil.copyfile(distro.kernel, f1)
2510+ shutil.copyfile(distro.initrd, f2)
2511+
2512+ cmd = "rsync -rlptgu --exclude=boot.cat --exclude=TRANS.TBL --exclude=isolinux/ %s/ %s/../" % (filesource, isolinuxdir)
2513+ self.logger.info("- copying distro %s files (%s)" % (distname,cmd))
2514+ rc = utils.subprocess_call(self.logger, cmd, shell=True)
2515+ if rc:
2516+ utils.die(self.logger,"rsync of files failed")
2517+
2518+ self.logger.info("generating a isolinux.cfg")
2519+ isolinuxcfg = os.path.join(isolinuxdir, "isolinux.cfg")
2520+ cfg = open(isolinuxcfg, "w+")
2521+ cfg.write(HEADER) # fixme, use template
2522+
2523+ for descendant in descendants:
2524+ data = utils.blender(self.api, True, descendant)
2525+
2526+ cfg.write("\n")
2527+ cfg.write("LABEL %s\n" % descendant.name)
2528+ cfg.write(" MENU LABEL %s\n" % descendant.name)
2529+ cfg.write(" kernel vmlinuz\n")
2530+
2531+ data["kickstart"] = "cdrom:/isolinux/ks-%s.cfg" % descendant.name
2532+
2533+ append_line = " append initrd=initrd.img"
2534+ append_line = append_line + " ks=%s " % data["kickstart"]
2535+ append_line = append_line + " %s\n" % data["kernel_options"]
2536+
2537+ cfg.write(append_line)
2538+
2539+ if descendant.COLLECTION_TYPE == 'profile':
2540+ kickstart_data = self.api.kickgen.generate_kickstart_for_profile(descendant.name)
2541+ elif descendant.COLLECTION_TYPE == 'system':
2542+ kickstart_data = self.api.kickgen.generate_kickstart_for_system(descendant.name)
2543+
2544+ cdregex = re.compile("url .*\n", re.IGNORECASE)
2545+ kickstart_data = cdregex.sub("cdrom\n", kickstart_data)
2546+
2547+ ks_name = os.path.join(isolinuxdir, "ks-%s.cfg" % descendant.name)
2548+ ks_file = open(ks_name, "w+")
2549+ ks_file.write(kickstart_data)
2550+ ks_file.close()
2551+
2552+ self.logger.info("done writing config")
2553+ cfg.write("\n")
2554+ cfg.write("MENU END\n")
2555+ cfg.close()
2556+
2557+ return
2558+
2559+
2560+ def run(self,iso=None,buildisodir=None,profiles=None,systems=None,distro=None,standalone=None,source=None,exclude_dns=None):
2561+
2562+ self.settings = self.config.settings()
2563+
2564+ # the distro option is for stand-alone builds only
2565+ if not standalone and distro is not None:
2566+ utils.die(self.logger,"The --distro option should only be used when creating a standalone ISO")
2567+ # if building standalone, we only want --distro,
2568+ # profiles/systems are disallowed
2569+ if standalone:
2570+ if profiles is not None or systems is not None:
2571+ utils.die(self.logger,"When building a standalone ISO, use --distro only instead of --profiles/--systems")
2572+ elif distro is None:
2573+ utils.die(self.logger,"When building a standalone ISO, you must specify a --distro")
2574+ if source != None and not os.path.exists(source):
2575+ utils.die(self.logger,"The source specified (%s) does not exist" % source)
2576+
2577+ # if iso is none, create it in . as "kickstart.iso"
2578+ if iso is None:
2579+ iso = "kickstart.iso"
2580+
2581+ if buildisodir is None:
2582+ buildisodir = self.settings.buildisodir
2583+ else:
2584+ if not os.path.isdir(buildisodir):
2585+ utils.die(self.logger,"The --tempdir specified is not a directory")
2586+
2587+ (buildisodir_head,buildisodir_tail) = os.path.split(os.path.normpath(buildisodir))
2588+ if buildisodir_tail != "buildiso":
2589+ buildisodir = os.path.join(buildisodir, "buildiso")
2590+
2591+ self.logger.info("using/creating buildisodir: %s" % buildisodir)
2592+ if not os.path.exists(buildisodir):
2593+ os.makedirs(buildisodir)
2594+ else:
2595+ shutil.rmtree(buildisodir)
2596+ os.makedirs(buildisodir)
2597+
2598+ # if base of buildisodir does not exist, fail
2599+ # create all profiles unless filtered by "profiles"
2600+
2601+ imagesdir = os.path.join(buildisodir, "images")
2602+ isolinuxdir = os.path.join(buildisodir, "isolinux")
2603+
2604+ self.logger.info("building tree for isolinux")
2605+ if not os.path.exists(imagesdir):
2606+ os.makedirs(imagesdir)
2607+ if not os.path.exists(isolinuxdir):
2608+ os.makedirs(isolinuxdir)
2609+
2610+ self.logger.info("copying miscellaneous files")
2611+
2612+ isolinuxbin = "/usr/share/syslinux/isolinux.bin"
2613+ if not os.path.exists(isolinuxbin):
2614+ isolinuxbin = "/usr/lib/syslinux/isolinux.bin"
2615+
2616+ menu = "/usr/share/syslinux/menu.c32"
2617+ if not os.path.exists(menu):
2618+ menu = "/var/lib/cobbler/loaders/menu.c32"
2619+
2620+ chain = "/usr/share/syslinux/chain.c32"
2621+ if not os.path.exists(chain):
2622+ chain = "/usr/lib/syslinux/chain.c32"
2623+
2624+ files = [ isolinuxbin, menu, chain ]
2625+ for f in files:
2626+ if not os.path.exists(f):
2627+ utils.die(self.logger,"Required file not found: %s" % f)
2628+ else:
2629+ utils.copyfile(f, os.path.join(isolinuxdir, os.path.basename(f)), self.api)
2630+
2631+ if standalone:
2632+ self.generate_standalone_iso(imagesdir,isolinuxdir,distro,source)
2633+ else:
2634+ self.generate_netboot_iso(imagesdir,isolinuxdir,profiles,systems,exclude_dns)
2635+
2636+ # removed --quiet
2637+ cmd = "mkisofs -o %s -r -b isolinux/isolinux.bin -c isolinux/boot.cat" % iso
2638+ cmd = cmd + " -no-emul-boot -boot-load-size 4"
2639+ cmd = cmd + " -boot-info-table -V Cobbler\ Install -R -J -T %s" % buildisodir
2640+
2641+ rc = utils.subprocess_call(self.logger, cmd, shell=True)
2642+ if rc != 0:
2643+ utils.die(self.logger,"mkisofs failed")
2644+
2645+ self.logger.info("ISO build complete")
2646+ self.logger.info("You may wish to delete: %s" % buildisodir)
2647+ self.logger.info("The output file is: %s" % iso)
2648+
2649+ return True
2650+
2651
2652=== added file 'cobbler/action_check.py'
2653--- cobbler/action_check.py 1970-01-01 00:00:00 +0000
2654+++ cobbler/action_check.py 2011-03-11 21:10:49 +0000
2655@@ -0,0 +1,482 @@
2656+"""
2657+Validates whether the system is reasonably well configured for
2658+serving up content. This is the code behind 'cobbler check'.
2659+
2660+Copyright 2006-2009, Red Hat, Inc
2661+Michael DeHaan <mdehaan@redhat.com>
2662+
2663+This program is free software; you can redistribute it and/or modify
2664+it under the terms of the GNU General Public License as published by
2665+the Free Software Foundation; either version 2 of the License, or
2666+(at your option) any later version.
2667+
2668+This program is distributed in the hope that it will be useful,
2669+but WITHOUT ANY WARRANTY; without even the implied warranty of
2670+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2671+GNU General Public License for more details.
2672+
2673+You should have received a copy of the GNU General Public License
2674+along with this program; if not, write to the Free Software
2675+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2676+02110-1301 USA
2677+"""
2678+
2679+import os
2680+import re
2681+import action_sync
2682+import utils
2683+import glob
2684+from utils import _
2685+import clogger
2686+
2687+class BootCheck:
2688+
2689+ def __init__(self,config,logger=None):
2690+ """
2691+ Constructor
2692+ """
2693+ self.config = config
2694+ self.settings = config.settings()
2695+ if logger is None:
2696+ logger = clogger.Logger()
2697+ self.logger = logger
2698+
2699+
2700+ def run(self):
2701+ """
2702+ Returns None if there are no errors, otherwise returns a list
2703+ of things to correct prior to running application 'for real'.
2704+ (The CLI usage is "cobbler check" before "cobbler sync")
2705+ """
2706+ status = []
2707+ self.checked_dist = utils.check_dist()
2708+ self.check_name(status)
2709+ self.check_selinux(status)
2710+ if self.settings.manage_dhcp:
2711+ mode = self.config.api.get_sync().dhcp.what()
2712+ if mode == "isc":
2713+ self.check_dhcpd_bin(status)
2714+ self.check_dhcpd_conf(status)
2715+ self.check_service(status,"dhcpd")
2716+ elif mode == "dnsmasq":
2717+ self.check_dnsmasq_bin(status)
2718+ self.check_service(status,"dnsmasq")
2719+
2720+ if self.settings.manage_dns:
2721+ mode = self.config.api.get_sync().dns.what()
2722+ if mode == "bind":
2723+ self.check_bind_bin(status)
2724+ self.check_service(status,"named")
2725+ elif mode == "dnsmasq" and not self.settings.manage_dhcp:
2726+ self.check_dnsmasq_bin(status)
2727+ self.check_service(status,"dnsmasq")
2728+
2729+ mode = self.config.api.get_sync().tftpd.what()
2730+ if mode == "in_tftpd":
2731+ self.check_tftpd_bin(status)
2732+ self.check_tftpd_dir(status)
2733+ self.check_tftpd_conf(status)
2734+ elif mode == "tftpd_py":
2735+ self.check_ctftpd_bin(status)
2736+ self.check_ctftpd_dir(status)
2737+ self.check_ctftpd_conf(status)
2738+
2739+ self.check_service(status, "cobblerd")
2740+
2741+ self.check_bootloaders(status)
2742+ self.check_rsync_conf(status)
2743+ self.check_httpd(status)
2744+ self.check_iptables(status)
2745+ self.check_yum(status)
2746+ self.check_debmirror(status)
2747+ self.check_for_ksvalidator(status)
2748+ self.check_for_default_password(status)
2749+ self.check_for_unreferenced_repos(status)
2750+ self.check_for_unsynced_repos(status)
2751+ self.check_for_cman(status)
2752+
2753+ return status
2754+
2755+ def check_for_ksvalidator(self, status):
2756+ if self.checked_dist in ["debian", "ubuntu"]:
2757+ return
2758+
2759+ if not os.path.exists("/usr/bin/ksvalidator"):
2760+ status.append("ksvalidator was not found, install pykickstart")
2761+
2762+ return True
2763+
2764+ def check_for_cman(self, status):
2765+ # not doing rpm -q here to be cross-distro friendly
2766+ if not os.path.exists("/sbin/fence_ilo") and not os.path.exists("/usr/sbin/fence_ilo"):
2767+ status.append("fencing tools were not found, and are required to use the (optional) power management features. install cman or fence-agents to use them")
2768+ return True
2769+
2770+ def check_service(self, status, which, notes=""):
2771+ if notes != "":
2772+ notes = " (NOTE: %s)" % notes
2773+ rc = 0
2774+ if self.checked_dist == "redhat" or self.checked_dist == "suse":
2775+ if os.path.exists("/etc/rc.d/init.d/%s" % which):
2776+ rc = utils.subprocess_call(self.logger,"/sbin/service %s status > /dev/null 2>/dev/null" % which, shell=True)
2777+ if rc != 0:
2778+ status.append(_("service %s is not running%s") % (which,notes))
2779+ return False
2780+ elif self.checked_dist in ["debian", "ubuntu"]:
2781+ # we still use /etc/init.d
2782+ if os.path.exists("/etc/init.d/%s" % which):
2783+ rc = utils.subprocess_call(self.logger,"/etc/init.d/%s status /dev/null 2>/dev/null" % which, shell=True)
2784+ if rc != 0:
2785+ status.append(_("service %s is not running%s") % which,notes)
2786+ return False
2787+ elif self.checked_dist == "ubuntu":
2788+ if os.path.exists("/etc/init/%s.conf" % which):
2789+ rc = utils.subprocess_call(self.logger,"status %s > /dev/null 2>&1" % which, shell=True)
2790+ if rc != 0:
2791+ status.append(_("service %s is not running%s") % (which,notes))
2792+ else:
2793+ status.append(_("Unknown distribution type, cannot check for running service %s" % which))
2794+ return False
2795+ return True
2796+
2797+ def check_iptables(self, status):
2798+ if os.path.exists("/etc/rc.d/init.d/iptables"):
2799+ rc = utils.subprocess_call(self.logger,"/sbin/service iptables status >/dev/null 2>/dev/null", shell=True)
2800+ if rc == 0:
2801+ status.append(_("since iptables may be running, ensure 69, 80, and %(xmlrpc)s are unblocked") % { "xmlrpc" : self.settings.xmlrpc_port })
2802+
2803+ def check_yum(self,status):
2804+ if self.checked_dist in ["debian", "ubuntu"]:
2805+ return
2806+
2807+ if not os.path.exists("/usr/bin/createrepo"):
2808+ status.append(_("createrepo package is not installed, needed for cobbler import and cobbler reposync, install createrepo?"))
2809+ if not os.path.exists("/usr/bin/reposync"):
2810+ status.append(_("reposync is not installed, need for cobbler reposync, install/upgrade yum-utils?"))
2811+ if not os.path.exists("/usr/bin/yumdownloader"):
2812+ status.append(_("yumdownloader is not installed, needed for cobbler repo add with --rpm-list parameter, install/upgrade yum-utils?"))
2813+ if self.settings.reposync_flags.find("-l"):
2814+ if self.checked_dist == "redhat" or self.checked_dist == "suse":
2815+ yum_utils_ver = utils.subprocess_get(self.logger,"/usr/bin/rpmquery --queryformat=%{VERSION} yum-utils", shell=True)
2816+ if yum_utils_ver < "1.1.17":
2817+ status.append(_("yum-utils need to be at least version 1.1.17 for reposync -l, current version is %s") % yum_utils_ver )
2818+
2819+ def check_debmirror(self,status):
2820+ if not os.path.exists("/usr/bin/debmirror"):
2821+ status.append(_("debmirror package is not installed, it will be required to manage debian deployments and repositories"))
2822+ if os.path.exists("/etc/debmirror.conf"):
2823+ f = open("/etc/debmirror.conf")
2824+ re_dists = re.compile(r'@dists=')
2825+ re_arches = re.compile(r'@arches=')
2826+ for line in f.readlines():
2827+ if re_dists.search(line) and not line.strip().startswith("#"):
2828+ status.append(_("comment 'dists' on /etc/debmirror.conf for proper debian support"))
2829+ if re_arches.search(line) and not line.strip().startswith("#"):
2830+ status.append(_("comment 'arches' on /etc/debmirror.conf for proper debian support"))
2831+
2832+
2833+ def check_name(self,status):
2834+ """
2835+ If the server name in the config file is still set to localhost
2836+ kickstarts run from koan will not have proper kernel line
2837+ parameters.
2838+ """
2839+ if self.settings.server == "127.0.0.1":
2840+ status.append(_("The 'server' field in /etc/cobbler/settings must be set to something other than localhost, or kickstarting features will not work. This should be a resolvable hostname or IP for the boot server as reachable by all machines that will use it."))
2841+ if self.settings.next_server == "127.0.0.1":
2842+ status.append(_("For PXE to be functional, the 'next_server' field in /etc/cobbler/settings must be set to something other than 127.0.0.1, and should match the IP of the boot server on the PXE network."))
2843+
2844+ def check_selinux(self,status):
2845+ """
2846+ Suggests various SELinux rules changes to run Cobbler happily with
2847+ SELinux in enforcing mode. FIXME: this method could use some
2848+ refactoring in the future.
2849+ """
2850+ if self.checked_dist in ["debian", "ubuntu"]:
2851+ return
2852+
2853+ enabled = self.config.api.is_selinux_enabled()
2854+ if enabled:
2855+ data2 = utils.subprocess_get(self.logger,"/usr/sbin/getsebool -a",shell=True)
2856+ for line in data2.split("\n"):
2857+ if line.find("httpd_can_network_connect ") != -1:
2858+ if line.find("off") != -1:
2859+ status.append(_("Must enable a selinux boolean to enable vital web services components, run: setsebool -P httpd_can_network_connect true"))
2860+ if line.find("rsync_disable_trans ") != -1:
2861+ if line.find("on") != -1:
2862+ status.append(_("Must enable the cobbler import and replicate commands, run: setsebool -P rsync_disable_trans=1"))
2863+
2864+ data3 = utils.subprocess_get(self.logger,"/usr/sbin/semanage fcontext -l | grep public_content_t",shell=True)
2865+
2866+ rule1 = False
2867+ rule2 = False
2868+ rule3 = False
2869+ selinux_msg = "/usr/sbin/semanage fcontext -a -t public_content_t \"%s\""
2870+ for line in data3.split("\n"):
2871+ if line.startswith("/tftpboot/.*"):
2872+ rule1 = True
2873+ if line.startswith("/var/lib/tftpboot/.*"):
2874+ rule2 = True
2875+ if line.startswith("/var/www/cobbler/images/.*"):
2876+ rule3 = True
2877+
2878+ rules = []
2879+ if os.path.exists("/tftpboot") and not rule1:
2880+ rules.append(selinux_msg % "/tftpboot/.*")
2881+ else:
2882+ if not rule2:
2883+ rules.append(selinux_msg % "/var/lib/tftpboot/.*")
2884+ if not rule3:
2885+ rules.append(selinux_msg % "/var/www/cobbler/images/.*")
2886+ if len(rules) > 0:
2887+ status.append("you need to set some SELinux content rules to ensure cobbler serves content correctly in your SELinux environment, run the following: %s" % " && ".join(rules))
2888+
2889+ # now check to see that the Django sessions path is accessible
2890+ # by Apache
2891+
2892+ data4 = utils.subprocess_get(self.logger,"/usr/sbin/semanage fcontext -l | grep httpd_sys_content_rw_t",shell=True)
2893+ selinux_msg = "you need to set some SELinux rules if you want to use cobbler-web (an optional package), run the following: /usr/sbin/semanage fcontext -a -t httpd_sys_content_rw_t \"%s\""
2894+ rule4 = False
2895+ for line in data4.split("\n"):
2896+ if line.startswith("/var/lib/cobbler/webui_sessions/.*"):
2897+ rule4 = True
2898+ if not rule4:
2899+ status.append(selinux_msg % "/var/lib/cobbler/webui_sessions/.*")
2900+
2901+
2902+ def check_for_default_password(self,status):
2903+ default_pass = self.settings.default_password_crypted
2904+ if default_pass == "$1$mF86/UHC$WvcIcX2t6crBz2onWxyac.":
2905+ status.append(_("The default password used by the sample templates for newly installed machines (default_password_crypted in /etc/cobbler/settings) is still set to 'cobbler' and should be changed, try: \"openssl passwd -1 -salt 'random-phrase-here' 'your-password-here'\" to generate new one"))
2906+
2907+
2908+ def check_for_unreferenced_repos(self,status):
2909+ repos = []
2910+ referenced = []
2911+ not_found = []
2912+ for r in self.config.api.repos():
2913+ repos.append(r.name)
2914+ for p in self.config.api.profiles():
2915+ my_repos = p.repos
2916+ if my_repos != "<<inherit>>":
2917+ referenced.extend(my_repos)
2918+ for r in referenced:
2919+ if r not in repos and r != "<<inherit>>":
2920+ not_found.append(r)
2921+ if len(not_found) > 0:
2922+ status.append(_("One or more repos referenced by profile objects is no longer defined in cobbler: %s") % ", ".join(not_found))
2923+
2924+ def check_for_unsynced_repos(self,status):
2925+ need_sync = []
2926+ for r in self.config.repos():
2927+ if r.mirror_locally == 1:
2928+ lookfor = os.path.join(self.settings.webdir, "repo_mirror", r.name)
2929+ if not os.path.exists(lookfor):
2930+ need_sync.append(r.name)
2931+ if len(need_sync) > 0:
2932+ status.append(_("One or more repos need to be processed by cobbler reposync for the first time before kickstarting against them: %s") % ", ".join(need_sync))
2933+
2934+
2935+ def check_httpd(self,status):
2936+ """
2937+ Check if Apache is installed.
2938+ """
2939+ if self.checked_dist in [ "suse", "redhat" ]:
2940+ rc = utils.subprocess_get(self.logger,"httpd -v")
2941+ else:
2942+ rc = utils.subprocess_get(self.logger,"apache2 -v")
2943+ if rc.find("Server") == -1:
2944+ status.append("Apache (httpd) is not installed and/or in path")
2945+
2946+
2947+ def check_dhcpd_bin(self,status):
2948+ """
2949+ Check if dhcpd is installed
2950+ """
2951+ if not os.path.exists("/usr/sbin/dhcpd"):
2952+ status.append("dhcpd is not installed")
2953+
2954+ def check_dnsmasq_bin(self,status):
2955+ """
2956+ Check if dnsmasq is installed
2957+ """
2958+ rc = utils.subprocess_get(self.logger,"dnsmasq --help")
2959+ if rc.find("Valid options") == -1:
2960+ status.append("dnsmasq is not installed and/or in path")
2961+
2962+ def check_bind_bin(self,status):
2963+ """
2964+ Check if bind is installed.
2965+ """
2966+ rc = utils.subprocess_get(self.logger,"named -v")
2967+ # it should return something like "BIND 9.6.1-P1-RedHat-9.6.1-6.P1.fc11"
2968+ if rc.find("BIND") == -1:
2969+ status.append("named is not installed and/or in path")
2970+
2971+ def check_bootloaders(self,status):
2972+ """
2973+ Check if network bootloaders are installed
2974+ """
2975+ # FIXME: move zpxe.rexx to loaders
2976+
2977+ bootloaders = {
2978+ "elilo" : [ "/var/lib/cobbler/loaders/elilo*.efi" ],
2979+ "menu.c32" : [ "/usr/share/syslinux/menu.c32",
2980+ "/usr/lib/syslinux/menu.c32",
2981+ "/var/lib/cobbler/loaders/menu.c32" ],
2982+ "yaboot" : [ "/var/lib/cobbler/loaders/yaboot*" ],
2983+ "pxelinux.0" : [ "/usr/share/syslinux/pxelinux.0",
2984+ "/usr/lib/syslinux/pxelinux.0",
2985+ "/var/lib/cobbler/loaders/pxelinux.0" ],
2986+ "efi" : [ "/var/lib/cobbler/loaders/grub-x86.efi",
2987+ "/var/lib/cobbler/loaders/grub-x86_64.efi" ],
2988+ }
2989+
2990+ # look for bootloaders at the glob locations above
2991+ found_bootloaders = []
2992+ items = bootloaders.keys()
2993+ for loader_name in items:
2994+ patterns = bootloaders[loader_name]
2995+ for pattern in patterns:
2996+ matches = glob.glob(pattern)
2997+ if len(matches) > 0:
2998+ found_bootloaders.append(loader_name)
2999+ not_found = []
3000+
3001+ # invert the list of what we've found so we can report on what we haven't found
3002+ for loader_name in items:
3003+ if loader_name not in found_bootloaders:
3004+ not_found.append(loader_name)
3005+
3006+ if len(not_found) > 0:
3007+ status.append("some network boot-loaders are missing from /var/lib/cobbler/loaders, you may run 'cobbler get-loaders' to download them, or, if you only want to handle x86/x86_64 netbooting, you may ensure that you have installed a *recent* version of the syslinux package installed and can ignore this message entirely. Files in this directory, should you want to support all architectures, should include pxelinux.0, menu.c32, elilo.efi, and yaboot. The 'cobbler get-loaders' command is the easiest way to resolve these requirements.")
3008+
3009+ def check_tftpd_bin(self,status):
3010+ """
3011+ Check if tftpd is installed
3012+ """
3013+ if self.checked_dist in ["debian", "ubuntu"]:
3014+ return
3015+
3016+ if not os.path.exists("/etc/xinetd.d/tftp"):
3017+ status.append("missing /etc/xinetd.d/tftp, install tftp-server?")
3018+
3019+ def check_tftpd_dir(self,status):
3020+ """
3021+ Check if cobbler.conf's tftpboot directory exists
3022+ """
3023+ if self.checked_dist in ["debian", "ubuntu"]:
3024+ return
3025+
3026+ bootloc = utils.tftpboot_location()
3027+ if not os.path.exists(bootloc):
3028+ status.append(_("please create directory: %(dirname)s") % { "dirname" : bootloc })
3029+
3030+
3031+ def check_tftpd_conf(self,status):
3032+ """
3033+ Check that configured tftpd boot directory matches with actual
3034+ Check that tftpd is enabled to autostart
3035+ """
3036+ if self.checked_dist in ["debian", "ubuntu"]:
3037+ return
3038+
3039+ if os.path.exists("/etc/xinetd.d/tftp"):
3040+ f = open("/etc/xinetd.d/tftp")
3041+ re_disable = re.compile(r'disable.*=.*yes')
3042+ for line in f.readlines():
3043+ if re_disable.search(line) and not line.strip().startswith("#"):
3044+ status.append(_("change 'disable' to 'no' in %(file)s") % { "file" : "/etc/xinetd.d/tftp" })
3045+ else:
3046+ status.append("missing configuration file: /etc/xinetd.d/tftp")
3047+
3048+ def check_ctftpd_bin(self,status):
3049+ """
3050+ Check if the Cobbler tftp server is installed
3051+ """
3052+ if self.checked_dist in ["debian", "ubuntu"]:
3053+ return
3054+
3055+ if not os.path.exists("/etc/xinetd.d/ctftp"):
3056+ status.append("missing /etc/xinetd.d/ctftp")
3057+
3058+ def check_ctftpd_dir(self,status):
3059+ """
3060+ Check if cobbler.conf's tftpboot directory exists
3061+ """
3062+ if self.checked_dist in ["debian", "ubuntu"]:
3063+ return
3064+
3065+ bootloc = utils.tftpboot_location()
3066+ if not os.path.exists(bootloc):
3067+ status.append(_("please create directory: %(dirname)s") % { "dirname" : bootloc })
3068+
3069+ def check_ctftpd_conf(self,status):
3070+ """
3071+ Check that configured tftpd boot directory matches with actual
3072+ Check that tftpd is enabled to autostart
3073+ """
3074+ if self.checked_dist in ["debian", "ubuntu"]:
3075+ return
3076+
3077+ if os.path.exists("/etc/xinetd.d/tftp"):
3078+ f = open("/etc/xinetd.d/tftp")
3079+ re_disable = re.compile(r'disable.*=.*no')
3080+ for line in f.readlines():
3081+ if re_disable.search(line) and not line.strip().startswith("#"):
3082+ status.append(_("change 'disable' to 'yes' in %(file)s") % { "file" : "/etc/xinetd.d/tftp" })
3083+ if os.path.exists("/etc/xinetd.d/ctftp"):
3084+ f = open("/etc/xinetd.d/ctftp")
3085+ re_disable = re.compile(r'disable.*=.*yes')
3086+ for line in f.readlines():
3087+ if re_disable.search(line) and not line.strip().startswith("#"):
3088+ status.append(_("change 'disable' to 'no' in %(file)s") % { "file" : "/etc/xinetd.d/ctftp" })
3089+ else:
3090+ status.append("missing configuration file: /etc/xinetd.d/ctftp")
3091+
3092+ def check_rsync_conf(self,status):
3093+ """
3094+ Check that rsync is enabled to autostart
3095+ """
3096+ if self.checked_dist in ["debian", "ubuntu"]:
3097+ return
3098+
3099+ if os.path.exists("/etc/xinetd.d/rsync"):
3100+ f = open("/etc/xinetd.d/rsync")
3101+ re_disable = re.compile(r'disable.*=.*yes')
3102+ for line in f.readlines():
3103+ if re_disable.search(line) and not line.strip().startswith("#"):
3104+ status.append(_("change 'disable' to 'no' in %(file)s") % { "file" : "/etc/xinetd.d/rsync" })
3105+ else:
3106+ status.append(_("file %(file)s does not exist") % { "file" : "/etc/xinetd.d/rsync" })
3107+
3108+
3109+ def check_dhcpd_conf(self,status):
3110+ """
3111+ NOTE: this code only applies if cobbler is *NOT* set to generate
3112+ a dhcp.conf file
3113+
3114+ Check that dhcpd *appears* to be configured for pxe booting.
3115+ We can't assure file correctness. Since a cobbler user might
3116+ have dhcp on another server, it's okay if it's not there and/or
3117+ not configured correctly according to automated scans.
3118+ """
3119+ if not (self.settings.manage_dhcp == 0):
3120+ return
3121+
3122+ if os.path.exists(self.settings.dhcpd_conf):
3123+ match_next = False
3124+ match_file = False
3125+ f = open(self.settings.dhcpd_conf)
3126+ for line in f.readlines():
3127+ if line.find("next-server") != -1:
3128+ match_next = True
3129+ if line.find("filename") != -1:
3130+ match_file = True
3131+ if not match_next:
3132+ status.append(_("expecting next-server entry in %(file)s") % { "file" : self.settings.dhcpd_conf })
3133+ if not match_file:
3134+ status.append(_("missing file: %(file)s") % { "file" : self.settings.dhcpd_conf })
3135+ else:
3136+ status.append(_("missing file: %(file)s") % { "file" : self.settings.dhcpd_conf })
3137+
3138
3139=== added file 'cobbler/action_dlcontent.py'
3140--- cobbler/action_dlcontent.py 1970-01-01 00:00:00 +0000
3141+++ cobbler/action_dlcontent.py 2011-03-11 21:10:49 +0000
3142@@ -0,0 +1,96 @@
3143+"""
3144+Downloads bootloader content for all arches for when the user doesn't want to supply their own.
3145+
3146+Copyright 2009, Red Hat, Inc
3147+Michael DeHaan <mdehaan@redhat.com>
3148+
3149+This program is free software; you can redistribute it and/or modify
3150+it under the terms of the GNU General Public License as published by
3151+the Free Software Foundation; either version 2 of the License, or
3152+(at your option) any later version.
3153+
3154+This program is distributed in the hope that it will be useful,
3155+but WITHOUT ANY WARRANTY; without even the implied warranty of
3156+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3157+GNU General Public License for more details.
3158+
3159+You should have received a copy of the GNU General Public License
3160+along with this program; if not, write to the Free Software
3161+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
3162+02110-1301 USA
3163+"""
3164+
3165+import os
3166+import urlgrabber
3167+import clogger
3168+
3169+class ContentDownloader:
3170+
3171+ def __init__(self,config,logger=None):
3172+ """
3173+ Constructor
3174+ """
3175+ self.config = config
3176+ self.settings = config.settings()
3177+ if logger is None:
3178+ logger = clogger.Logger()
3179+ self.logger = logger
3180+
3181+
3182+ def run(self,force=False):
3183+ """
3184+ Download bootloader content for all of the latest bootloaders, since the user
3185+ has chosen to not supply their own. You may ask "why not get this from yum", though
3186+ Fedora has no IA64 repo, for instance, and we also want this to be able to work on Debian and
3187+ further do not want folks to have to install a cross compiler. For those that don't like this approach
3188+ they can still source their cross-arch bootloader content manually.
3189+ """
3190+
3191+ content_server = "http://dgoodwin.fedorapeople.org/loaders"
3192+ dest = "/var/lib/cobbler/loaders"
3193+
3194+ files = (
3195+ ( "%s/README" % content_server, "%s/README" % dest ),
3196+ ( "%s/COPYING.elilo" % content_server, "%s/COPYING.elilo" % dest ),
3197+ ( "%s/COPYING.yaboot" % content_server, "%s/COPYING.yaboot" % dest),
3198+ ( "%s/COPYING.syslinux" % content_server, "%s/COPYING.syslinux" % dest),
3199+ ( "%s/elilo-3.8-ia64.efi" % content_server, "%s/elilo-ia64.efi" % dest ),
3200+ ( "%s/yaboot-1.3.14-12" % content_server, "%s/yaboot" % dest),
3201+ ( "%s/pxelinux.0-3.61" % content_server, "%s/pxelinux.0" % dest),
3202+ ( "%s/menu.c32-3.61" % content_server, "%s/menu.c32" % dest),
3203+ ( "%s/grub-0.97-x86.efi" % content_server, "%s/grub-x86.efi" % dest),
3204+ ( "%s/grub-0.97-x86_64.efi" % content_server, "%s/grub-x86_64.efi" % dest),
3205+ )
3206+
3207+ proxies = {}
3208+ for var in os.environ.keys():
3209+ if (var.lower() == "http_proxy"):
3210+ proxies['http'] = os.environ[var]
3211+
3212+ if (var.lower() == "ftp_proxy"):
3213+ proxies['ftp'] = os.environ[var]
3214+
3215+ if (len(proxies) > 0):
3216+ for f in files:
3217+ src = f[0]
3218+ dst = f[1]
3219+ if os.path.exists(dst) and not force:
3220+ self.logger.info("path %s already exists, not overwriting existing content, use --force if you wish to update" % dst)
3221+ continue
3222+ os.chdir(dest)
3223+ self.logger.info("downloading %s to %s" % (src,dst))
3224+ urlgrabber.grabber.urlgrab(src, proxies=proxies)
3225+
3226+ else:
3227+ self.logger.info("downloading content required to netboot all arches")
3228+ for f in files:
3229+ src = f[0]
3230+ dst = f[1]
3231+ if os.path.exists(dst) and not force:
3232+ self.logger.info("path %s already exists, not overwriting existing content, use --force if you wish to update" % dst)
3233+ continue
3234+ self.logger.info("downloading %s to %s" % (src,dst))
3235+ urlgrabber.urlgrab(src,dst)
3236+
3237+ return True
3238+
3239
3240=== added file 'cobbler/action_hardlink.py'
3241--- cobbler/action_hardlink.py 1970-01-01 00:00:00 +0000
3242+++ cobbler/action_hardlink.py 2011-03-11 21:10:49 +0000
3243@@ -0,0 +1,60 @@
3244+"""
3245+Hard links cobbler content together to save space.
3246+
3247+Copyright 2009, Red Hat, Inc
3248+Michael DeHaan <mdehaan@redhat.com>
3249+
3250+This program is free software; you can redistribute it and/or modify
3251+it under the terms of the GNU General Public License as published by
3252+the Free Software Foundation; either version 2 of the License, or
3253+(at your option) any later version.
3254+
3255+This program is distributed in the hope that it will be useful,
3256+but WITHOUT ANY WARRANTY; without even the implied warranty of
3257+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3258+GNU General Public License for more details.
3259+
3260+You should have received a copy of the GNU General Public License
3261+along with this program; if not, write to the Free Software
3262+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
3263+02110-1301 USA
3264+"""
3265+
3266+import os
3267+import utils
3268+from cexceptions import *
3269+import clogger
3270+
3271+class HardLinker:
3272+
3273+ def __init__(self,config,logger=None):
3274+ """
3275+ Constructor
3276+ """
3277+ #self.config = config
3278+ #self.api = config.api
3279+ #self.settings = config.settings()
3280+ if logger is None:
3281+ logger = clogger.Logger()
3282+ self.logger = logger
3283+
3284+
3285+ def run(self):
3286+ """
3287+ Simply hardlinks directories that are cobbler managed.
3288+ This is a /very/ simple command but may grow more complex
3289+ and intelligent over time.
3290+ """
3291+
3292+ # FIXME: if these directories become configurable some
3293+ # changes will be required here.
3294+
3295+ if not os.path.exists("/usr/sbin/hardlink"):
3296+ utils.die(self.logger,"please install 'hardlink' (/usr/sbin/hardlink) to use this feature")
3297+
3298+ self.logger.info("now hardlinking to save space, this may take some time.")
3299+
3300+ rc = utils.subprocess_call(self.logger,"/usr/sbin/hardlink -c -v /var/www/cobbler/ks_mirror /var/www/cobbler/repo_mirror",shell=True)
3301+
3302+ return rc
3303+
3304
3305=== added file 'cobbler/action_import.py'
3306--- cobbler/action_import.py 1970-01-01 00:00:00 +0000
3307+++ cobbler/action_import.py 2011-03-11 21:10:49 +0000
3308@@ -0,0 +1,1332 @@
3309+"""
3310+Enables the "cobbler import" command to seed cobbler
3311+information with available distribution from rsync mirrors
3312+and mounted DVDs.
3313+
3314+Copyright 2006-2009, Red Hat, Inc
3315+Michael DeHaan <mdehaan@redhat.com>
3316+
3317+This program is free software; you can redistribute it and/or modify
3318+it under the terms of the GNU General Public License as published by
3319+the Free Software Foundation; either version 2 of the License, or
3320+(at your option) any later version.
3321+
3322+This program is distributed in the hope that it will be useful,
3323+but WITHOUT ANY WARRANTY; without even the implied warranty of
3324+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3325+GNU General Public License for more details.
3326+
3327+You should have received a copy of the GNU General Public License
3328+along with this program; if not, write to the Free Software
3329+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
3330+02110-1301 USA
3331+"""
3332+
3333+from cexceptions import *
3334+import os
3335+import os.path
3336+import re
3337+import traceback
3338+import glob
3339+import api
3340+import utils
3341+import shutil
3342+from utils import _
3343+import item_repo
3344+import clogger
3345+
3346+# FIXME: add --quiet depending on if not --verbose?
3347+RSYNC_CMD = "rsync -a %s '%s' %s/ks_mirror/%s --exclude-from=/etc/cobbler/rsync.exclude --progress"
3348+
3349+class Importer:
3350+
3351+ def __init__(self,api,config,mirror,mirror_name,network_root=None,kickstart_file=None,rsync_flags=None,arch=None,breed=None,os_version=None,logger=None):
3352+ """
3353+ Performs an import of a install tree (or trees) from the given
3354+ mirror address. The prefix of the distro is to be specified
3355+ by mirror name. For instance, if FC-6 is given, FC-6-xen-i386
3356+ would be a potential distro that could be created. For content
3357+ available on external servers via a known nfs:// or ftp:// or
3358+ http:// path, we can import without doing rsync mirorring to
3359+ cobbler's http directory. This is explained in more detail
3360+ in the manpage. Leave network_root to None if want mirroring.
3361+ """
3362+ self.api = api
3363+ self.config = config
3364+ self.mirror = mirror
3365+ self.mirror_name = mirror_name
3366+ self.network_root = network_root
3367+ self.distros = config.distros()
3368+ self.profiles = config.profiles()
3369+ self.systems = config.systems()
3370+ self.settings = config.settings()
3371+ self.kickstart_file = kickstart_file
3372+ self.rsync_flags = rsync_flags
3373+ self.arch = arch
3374+ self.breed = breed
3375+ self.os_version = os_version
3376+ if logger is None:
3377+ logger = clogger.Logger()
3378+ self.logger = logger
3379+
3380+
3381+ # ========================================================================
3382+
3383+ def run(self):
3384+
3385+ """
3386+ This contains the guts of the import command.
3387+ """
3388+
3389+ # some fixups for the XMLRPC interface, which does not use "None"
3390+ if self.arch == "": self.arch = None
3391+ if self.mirror == "": self.mirror = None
3392+ if self.mirror_name == "": self.mirror_name = None
3393+ if self.breed == "": self.breed = None
3394+ if self.kickstart_file == "": self.kickstart_file = None
3395+ if self.os_version == "": self.os_version = None
3396+ if self.rsync_flags == "": self.rsync_flags = None
3397+ if self.network_root == "": self.network_root = None
3398+
3399+ # both --import and --name are required arguments
3400+
3401+ if self.mirror is None:
3402+ utils.die(self.logger,"import failed. no --path specified")
3403+ if self.mirror_name is None:
3404+ utils.die(self.logger,"import failed. no --name specified")
3405+
3406+ # if --arch is supplied, validate it to ensure it's valid
3407+
3408+ if self.arch is not None and self.arch != "":
3409+ self.arch = self.arch.lower()
3410+ if self.arch == "x86":
3411+ # be consistent
3412+ self.arch = "i386"
3413+ if self.arch not in [ "i386", "ia64", "ppc", "ppc64", "s390", "s390x", "x86_64", ]:
3414+ utils.die(self.logger,"arch must be i386, ia64, ppc, ppc64, s390, s390x or x86_64")
3415+
3416+ # if we're going to do any copying, set where to put things
3417+ # and then make sure nothing is already there.
3418+
3419+ mpath = os.path.join(self.settings.webdir, "ks_mirror", self.mirror_name)
3420+ if os.path.exists(mpath) and self.arch is None:
3421+ # FIXME : Raise exception even when network_root is given ?
3422+ utils.die(self.logger,"Something already exists at this import location (%s). You must specify --arch to avoid potentially overwriting existing files." % mpath)
3423+
3424+ # import takes a --kickstart for forcing selection that can't be used in all circumstances
3425+
3426+ if self.kickstart_file and not self.breed:
3427+ utils.die(self.logger,"Kickstart file can only be specified when a specific breed is selected")
3428+
3429+ if self.os_version and not self.breed:
3430+ utils.die(self.logger,"OS version can only be specified when a specific breed is selected")
3431+
3432+ #if self.breed and self.breed.lower() not in [ "redhat", "debian", "ubuntu", "windows" ]:
3433+ #if self.breed and self.breed.lower() not in [ "redhat" ]:
3434+ if self.breed and self.breed.lower() not in [ "redhat", "vmware" ]:
3435+ utils.die(self.logger,"Supplied import breed is not supported")
3436+
3437+ # if --arch is supplied, make sure the user is not importing a path with a different
3438+ # arch, which would just be silly.
3439+
3440+ if self.arch:
3441+ # append the arch path to the name if the arch is not already
3442+ # found in the name.
3443+ for x in [ "i386", "ia64", "ppc", "ppc64", "s390", "s390x", "x86_64", "x86", ]:
3444+ if self.mirror_name.lower().find(x) != -1:
3445+ if self.arch != x :
3446+ utils.die(self.logger,"Architecture found on pathname (%s) does not fit the one given in command line (%s)"%(x,self.arch))
3447+ break
3448+ else:
3449+ # FIXME : This is very likely removed later at get_proposed_name, and the guessed arch appended again
3450+ self.mirror_name = self.mirror_name + "-" + self.arch
3451+
3452+ # make the output path and mirror content but only if not specifying that a network
3453+ # accessible support location already exists (this is --available-as on the command line)
3454+
3455+ if self.network_root is None:
3456+
3457+ # we need to mirror (copy) the files
3458+
3459+ self.path = os.path.normpath( "%s/ks_mirror/%s" % (self.settings.webdir, self.mirror_name) )
3460+ self.mkdir(self.path)
3461+
3462+ # prevent rsync from creating the directory name twice
3463+ # if we are copying via rsync
3464+
3465+ if not self.mirror.endswith("/"):
3466+ self.mirror = "%s/" % self.mirror
3467+
3468+ if self.mirror.startswith("http://") or self.mirror.startswith("ftp://") or self.mirror.startswith("nfs://"):
3469+
3470+ # http mirrors are kind of primative. rsync is better.
3471+ # that's why this isn't documented in the manpage and we don't support them.
3472+ # TODO: how about adding recursive FTP as an option?
3473+
3474+ utils.die(self.logger,"unsupported protocol")
3475+
3476+ else:
3477+
3478+ # good, we're going to use rsync..
3479+ # we don't use SSH for public mirrors and local files.
3480+ # presence of user@host syntax means use SSH
3481+
3482+ spacer = ""
3483+ if not self.mirror.startswith("rsync://") and not self.mirror.startswith("/"):
3484+ spacer = ' -e "ssh" '
3485+ rsync_cmd = RSYNC_CMD
3486+ if self.rsync_flags:
3487+ rsync_cmd = rsync_cmd + " " + self.rsync_flags
3488+
3489+ # kick off the rsync now
3490+
3491+ self.run_this(rsync_cmd, (spacer, self.mirror, self.settings.webdir, self.mirror_name))
3492+
3493+ else:
3494+
3495+ # rather than mirroring, we're going to assume the path is available
3496+ # over http, ftp, and nfs, perhaps on an external filer. scanning still requires
3497+ # --mirror is a filesystem path, but --available-as marks the network path
3498+
3499+ if not os.path.exists(self.mirror):
3500+ utils.die(self.logger, "path does not exist: %s" % self.mirror)
3501+
3502+ # find the filesystem part of the path, after the server bits, as each distro
3503+ # URL needs to be calculated relative to this.
3504+
3505+ if not self.network_root.endswith("/"):
3506+ self.network_root = self.network_root + "/"
3507+ self.path = os.path.normpath( self.mirror )
3508+ valid_roots = [ "nfs://", "ftp://", "http://" ]
3509+ for valid_root in valid_roots:
3510+ if self.network_root.startswith(valid_root):
3511+ break
3512+ else:
3513+ utils.die(self.logger, "Network root given to --available-as must be nfs://, ftp://, or http://")
3514+ if self.network_root.startswith("nfs://"):
3515+ try:
3516+ (a,b,rest) = self.network_root.split(":",3)
3517+ except:
3518+ utils.die(self.logger, "Network root given to --available-as is missing a colon, please see the manpage example.")
3519+
3520+ # now walk the filesystem looking for distributions that match certain patterns
3521+
3522+ self.logger.info("adding distros")
3523+ distros_added = []
3524+ # FIXME : search below self.path for isolinux configurations or known directories from TRY_LIST
3525+ os.path.walk(self.path, self.distro_adder, distros_added)
3526+
3527+ # find out if we can auto-create any repository records from the install tree
3528+
3529+ if self.network_root is None:
3530+ self.logger.info("associating repos")
3531+ # FIXME: this automagic is not possible (yet) without mirroring
3532+ self.repo_finder(distros_added)
3533+
3534+ # find the most appropriate answer files for each profile object
3535+
3536+ self.logger.info("associating kickstarts")
3537+ self.kickstart_finder(distros_added)
3538+
3539+ # ensure bootloaders are present
3540+ self.api.pxegen.copy_bootloaders()
3541+
3542+ return True
3543+
3544+ # ----------------------------------------------------------------------
3545+
3546+ def mkdir(self, dir):
3547+
3548+ """
3549+ A more tolerant mkdir.
3550+ FIXME: use the one in utils.py (?)
3551+ """
3552+
3553+ try:
3554+ os.makedirs(dir)
3555+ except OSError , ex:
3556+ if ex.strerror == "Permission denied":
3557+ utils.die(self.logger, "Permission denied at %s" % dir)
3558+ except:
3559+ pass
3560+
3561+ # ----------------------------------------------------------------------
3562+
3563+ def run_this(self, cmd, args):
3564+
3565+ """
3566+ A simple wrapper around subprocess calls.
3567+ """
3568+
3569+ my_cmd = cmd % args
3570+ rc = utils.subprocess_call(self.logger,my_cmd,shell=True)
3571+ if rc != 0:
3572+ utils.die(self.logger,"Command failed")
3573+
3574+ # =======================================================================
3575+
3576+ def kickstart_finder(self,distros_added):
3577+
3578+ """
3579+ For all of the profiles in the config w/o a kickstart, use the
3580+ given kickstart file, or look at the kernel path, from that,
3581+ see if we can guess the distro, and if we can, assign a kickstart
3582+ if one is available for it.
3583+ """
3584+ for profile in self.profiles:
3585+ distro = self.distros.find(name=profile.get_conceptual_parent().name)
3586+ if distro is None or not (distro in distros_added):
3587+ continue
3588+
3589+ kdir = os.path.dirname(distro.kernel)
3590+ importer = import_factory(kdir,self.path,self.breed,self.logger)
3591+ if self.kickstart_file == None:
3592+ for rpm in importer.get_release_files():
3593+ # FIXME : This redhat specific check should go into the importer.find_release_files method
3594+ if rpm.find("notes") != -1:
3595+ continue
3596+ results = importer.scan_pkg_filename(rpm)
3597+ # FIXME : If os is not found on tree but set with CLI, no kickstart is searched
3598+ if results is None:
3599+ self.logger.warning("No version found on imported tree")
3600+ continue
3601+ (flavor, major, minor) = results
3602+ version , ks = importer.set_variance(flavor, major, minor, distro.arch)
3603+ if self.os_version:
3604+ if self.os_version != version:
3605+ utils.die(self.logger,"CLI version differs from tree : %s vs. %s" % (self.os_version,version))
3606+ ds = importer.get_datestamp()
3607+ distro.set_comment("%s.%s" % (version, int(minor)))
3608+ distro.set_os_version(version)
3609+ if ds is not None:
3610+ distro.set_tree_build_time(ds)
3611+ profile.set_kickstart(ks)
3612+ self.profiles.add(profile,save=True)
3613+
3614+ self.configure_tree_location(distro,importer)
3615+ self.distros.add(distro,save=True) # re-save
3616+ self.api.serialize()
3617+
3618+ # ==========================================================================
3619+
3620+
3621+ def configure_tree_location(self, distro, importer):
3622+
3623+ """
3624+ Once a distribution is identified, find the part of the distribution
3625+ that has the URL in it that we want to use for kickstarting the
3626+ distribution, and create a ksmeta variable $tree that contains this.
3627+ """
3628+
3629+ base = importer.get_rootdir()
3630+
3631+ if self.network_root is None:
3632+ if distro.breed == "debian" or distro.breed == "ubuntu":
3633+ dists_path = os.path.join( self.path , "dists" )
3634+ if os.path.isdir( dists_path ):
3635+ tree = "http://@@http_server@@/cblr/ks_mirror/%s" % (self.mirror_name)
3636+ else:
3637+ tree = "http://@@http_server@@/cblr/repo_mirror/%s" % (distro.name)
3638+ else:
3639+ dest_link = os.path.join(self.settings.webdir, "links", distro.name)
3640+ # create the links directory only if we are mirroring because with
3641+ # SELinux Apache can't symlink to NFS (without some doing)
3642+ if not os.path.exists(dest_link):
3643+ try:
3644+ os.symlink(base, dest_link)
3645+ except:
3646+ # this shouldn't happen but I've seen it ... debug ...
3647+ self.logger.warning("symlink creation failed: %(base)s, %(dest)s") % { "base" : base, "dest" : dest_link }
3648+ # how we set the tree depends on whether an explicit network_root was specified
3649+ tree = "http://@@http_server@@/cblr/links/%s" % (distro.name)
3650+ importer.set_install_tree( distro, tree)
3651+ else:
3652+ # where we assign the kickstart source is relative to our current directory
3653+ # and the input start directory in the crawl. We find the path segments
3654+ # between and tack them on the network source path to find the explicit
3655+ # network path to the distro that Anaconda can digest.
3656+ tail = self.path_tail(self.path, base)
3657+ tree = self.network_root[:-1] + tail
3658+ importer.set_install_tree( distro, tree)
3659+
3660+ # ============================================================================
3661+
3662+ def path_tail(self, apath, bpath):
3663+ """
3664+ Given two paths (B is longer than A), find the part in B not in A
3665+ """
3666+ position = bpath.find(apath)
3667+ if position != 0:
3668+ utils.die(self.logger, "- warning: possible symlink traversal?: %s")
3669+ rposition = position + len(self.mirror)
3670+ result = bpath[rposition:]
3671+ if not result.startswith("/"):
3672+ result = "/" + result
3673+ return result
3674+
3675+ # ======================================================================
3676+
3677+ def repo_finder(self,distros_added):
3678+
3679+ """
3680+ This routine looks through all distributions and tries to find
3681+ any applicable repositories in those distributions for post-install
3682+ usage.
3683+ """
3684+
3685+ for distro in distros_added:
3686+ self.logger.info("traversing distro %s" % distro.name)
3687+ # FIXME : Shouldn't decide this the value of self.network_root ?
3688+ if distro.kernel.find("ks_mirror") != -1:
3689+ basepath = os.path.dirname(distro.kernel)
3690+ importer = import_factory(basepath,self.path,self.breed,self.logger)
3691+ top = importer.get_rootdir()
3692+ self.logger.info("descent into %s" % top)
3693+ if distro.breed in [ "debian" , "ubuntu" ]:
3694+ dists_path = os.path.join( self.path , "dists" )
3695+ if not os.path.isdir( dists_path ):
3696+ importer.process_repos( self , distro )
3697+ else:
3698+ # FIXME : The location of repo definition is known from breed
3699+ os.path.walk(top, self.repo_scanner, distro)
3700+ else:
3701+ self.logger.info("this distro isn't mirrored")
3702+
3703+ # ========================================================================
3704+
3705+
3706+ def repo_scanner(self,distro,dirname,fnames):
3707+
3708+ """
3709+ This is an os.path.walk routine that looks for potential yum repositories
3710+ to be added to the configuration for post-install usage.
3711+ """
3712+
3713+ matches = {}
3714+ for x in fnames:
3715+ if x == "base" or x == "repodata":
3716+ self.logger.info("processing repo at : %s" % dirname)
3717+ # only run the repo scanner on directories that contain a comps.xml
3718+ gloob1 = glob.glob("%s/%s/*comps*.xml" % (dirname,x))
3719+ if len(gloob1) >= 1:
3720+ if matches.has_key(dirname):
3721+ self.logger.info("looks like we've already scanned here: %s" % dirname)
3722+ continue
3723+ self.logger.info("need to process repo/comps: %s" % dirname)
3724+ self.process_comps_file(dirname, distro)
3725+ matches[dirname] = 1
3726+ else:
3727+ self.logger.info("directory %s is missing xml comps file, skipping" % dirname)
3728+ continue
3729+
3730+ # =======================================================================================
3731+
3732+
3733+
3734+ def process_comps_file(self, comps_path, distro):
3735+ """
3736+ When importing Fedora/EL certain parts of the install tree can also be used
3737+ as yum repos containing packages that might not yet be available via updates
3738+ in yum. This code identifies those areas.
3739+ """
3740+
3741+ processed_repos = {}
3742+
3743+ masterdir = "repodata"
3744+ if not os.path.exists(os.path.join(comps_path, "repodata")):
3745+ # older distros...
3746+ masterdir = "base"
3747+
3748+ # figure out what our comps file is ...
3749+ self.logger.info("looking for %(p1)s/%(p2)s/*comps*.xml" % { "p1" : comps_path, "p2" : masterdir })
3750+ files = glob.glob("%s/%s/*comps*.xml" % (comps_path, masterdir))
3751+ if len(files) == 0:
3752+ self.logger.info("no comps found here: %s" % os.path.join(comps_path, masterdir))
3753+ return # no comps xml file found
3754+
3755+ # pull the filename from the longer part
3756+ comps_file = files[0].split("/")[-1]
3757+
3758+ try:
3759+
3760+ # store the yum configs on the filesystem so we can use them later.
3761+ # and configure them in the kickstart post, etc
3762+
3763+ counter = len(distro.source_repos)
3764+
3765+ # find path segment for yum_url (changing filesystem path to http:// trailing fragment)
3766+ seg = comps_path.rfind("ks_mirror")
3767+ urlseg = comps_path[seg+10:]
3768+
3769+ # write a yum config file that shows how to use the repo.
3770+ if counter == 0:
3771+ dotrepo = "%s.repo" % distro.name
3772+ else:
3773+ dotrepo = "%s-%s.repo" % (distro.name, counter)
3774+
3775+ fname = os.path.join(self.settings.webdir, "ks_mirror", "config", "%s-%s.repo" % (distro.name, counter))
3776+
3777+ repo_url = "http://@@http_server@@/cobbler/ks_mirror/config/%s-%s.repo" % (distro.name, counter)
3778+
3779+ repo_url2 = "http://@@http_server@@/cobbler/ks_mirror/%s" % (urlseg)
3780+
3781+ distro.source_repos.append([repo_url,repo_url2])
3782+
3783+ # NOTE: the following file is now a Cheetah template, so it can be remapped
3784+ # during sync, that's why we have the @@http_server@@ left as templating magic.
3785+ # repo_url2 is actually no longer used. (?)
3786+
3787+ config_file = open(fname, "w+")
3788+ config_file.write("[core-%s]\n" % counter)
3789+ config_file.write("name=core-%s\n" % counter)
3790+ config_file.write("baseurl=http://@@http_server@@/cobbler/ks_mirror/%s\n" % (urlseg))
3791+ config_file.write("enabled=1\n")
3792+ config_file.write("gpgcheck=0\n")
3793+ config_file.write("priority=$yum_distro_priority\n")
3794+ config_file.close()
3795+
3796+ # don't run creatrepo twice -- this can happen easily for Xen and PXE, when
3797+ # they'll share same repo files.
3798+
3799+ if not processed_repos.has_key(comps_path):
3800+ utils.remove_yum_olddata(comps_path)
3801+ #cmd = "createrepo --basedir / --groupfile %s %s" % (os.path.join(comps_path, masterdir, comps_file), comps_path)
3802+ cmd = "createrepo %s --groupfile %s %s" % (self.settings.createrepo_flags,os.path.join(comps_path, masterdir, comps_file), comps_path)
3803+ utils.subprocess_call(self.logger, cmd, shell=True)
3804+ processed_repos[comps_path] = 1
3805+ # for older distros, if we have a "base" dir parallel with "repodata", we need to copy comps.xml up one...
3806+ p1 = os.path.join(comps_path, "repodata", "comps.xml")
3807+ p2 = os.path.join(comps_path, "base", "comps.xml")
3808+ if os.path.exists(p1) and os.path.exists(p2):
3809+ shutil.copyfile(p1,p2)
3810+
3811+ except:
3812+ self.logger.error("error launching createrepo (not installed?), ignoring")
3813+ utils.log_exc(self.logger)
3814+
3815+
3816+ # ========================================================================
3817+
3818+ def distro_adder(self,distros_added,dirname,fnames):
3819+
3820+ """
3821+ This is an os.path.walk routine that finds distributions in the directory
3822+ to be scanned and then creates them.
3823+ """
3824+
3825+ # FIXME: If there are more than one kernel or initrd image on the same directory,
3826+ # results are unpredictable
3827+
3828+ initrd = None
3829+ kernel = None
3830+
3831+ # make sure we don't mismatch PAE and non-PAE types
3832+ pae_initrd = None
3833+ pae_kernel = None
3834+
3835+ for x in fnames:
3836+ adtls = []
3837+
3838+ fullname = os.path.join(dirname,x)
3839+ if os.path.islink(fullname) and os.path.isdir(fullname):
3840+ if fullname.startswith(self.path):
3841+ # Prevent infinite loop with Sci Linux 5
3842+ self.logger.warning("avoiding symlink loop")
3843+ continue
3844+ self.logger.info("following symlink: %s" % fullname)
3845+ os.path.walk(fullname, self.distro_adder, distros_added)
3846+
3847+ if ( x.startswith("initrd") or x.startswith("ramdisk.image.gz") or x.startswith("vmkboot.gz") ) and x != "initrd.size" and x != "initrd.addrsize":
3848+ if x.find("PAE") == -1:
3849+ initrd = os.path.join(dirname,x)
3850+ else:
3851+ pae_initrd = os.path.join(dirname, x)
3852+
3853+ if ( x.startswith("vmlinu") or x.startswith("kernel.img") or x.startswith("linux") or x.startswith("mboot.c32") ) and x.find("initrd") == -1:
3854+ if x.find("PAE") == -1:
3855+ kernel = os.path.join(dirname,x)
3856+ else:
3857+ pae_kernel = os.path.join(dirname, x)
3858+
3859+ # if we've collected a matching kernel and initrd pair, turn the in and add them to the list
3860+ if initrd is not None and kernel is not None and dirname.find("isolinux") == -1:
3861+ adtls.append(self.add_entry(dirname,kernel,initrd))
3862+ kernel = None
3863+ initrd = None
3864+ elif pae_initrd is not None and pae_kernel is not None and dirname.find("isolinux") == -1:
3865+ adtls.append(self.add_entry(dirname,pae_kernel,pae_initrd))
3866+ pae_kernel = None
3867+ pae_initrd = None
3868+ elif initrd is not None and kernel is not None and dirname.find("VMware") == -1:
3869+ adtls.append(self.add_entry(dirname,kernel,initrd))
3870+ kernel = None
3871+ initrd = None
3872+ for adtl in adtls:
3873+ distros_added.extend(adtl)
3874+
3875+
3876+
3877+
3878+ # ========================================================================
3879+
3880+ def add_entry(self,dirname,kernel,initrd):
3881+
3882+ """
3883+ When we find a directory with a valid kernel/initrd in it, create the distribution objects
3884+ as appropriate and save them. This includes creating xen and rescue distros/profiles
3885+ if possible.
3886+ """
3887+
3888+ proposed_name = self.get_proposed_name(dirname,kernel)
3889+ proposed_arch = self.get_proposed_arch(dirname)
3890+
3891+ if self.arch and proposed_arch and self.arch != proposed_arch:
3892+ utils.die(self.logger,"Arch from pathname (%s) does not match with supplied one %s"%(proposed_arch,self.arch))
3893+
3894+ importer = import_factory(dirname,self.path,self.breed,self.logger)
3895+
3896+ archs = importer.learn_arch_from_tree()
3897+ if not archs:
3898+ if self.arch:
3899+ archs.append( self.arch )
3900+ else:
3901+ if self.arch and self.arch not in archs:
3902+ utils.die(self.logger, "Given arch (%s) not found on imported tree %s"%(self.arch,importer.get_pkgdir()))
3903+ if proposed_arch:
3904+ if archs and proposed_arch not in archs:
3905+ self.logger.warning("arch from pathname (%s) not found on imported tree %s" % (proposed_arch,importer.get_pkgdir()))
3906+ return
3907+
3908+ archs = [ proposed_arch ]
3909+
3910+ if importer.breed == "ubuntu" and dirname.find("ubuntu-installer") == -1:
3911+ self.logger.info("skipping entry, there are no netboot images")
3912+ return
3913+
3914+
3915+ if len(archs)>1:
3916+ if importer.breed in [ "redhat" ]:
3917+ self.logger.warning("directory %s holds multiple arches : %s" % (dirname, archs))
3918+ return
3919+ self.logger.warning("- Warning : Multiple archs found : %s" % (archs))
3920+
3921+ distros_added = []
3922+
3923+ for pxe_arch in archs:
3924+
3925+ name = proposed_name + "-" + pxe_arch
3926+ existing_distro = self.distros.find(name=name)
3927+
3928+ if existing_distro is not None:
3929+ self.logger.warning("skipping import, as distro name already exists: %s" % name)
3930+ continue
3931+
3932+ else:
3933+ self.logger.info("creating new distro: %s" % name)
3934+ distro = self.config.new_distro()
3935+
3936+ if name.find("-autoboot") != -1:
3937+ # this is an artifact of some EL-3 imports
3938+ continue
3939+
3940+ distro.set_name(name)
3941+ distro.set_kernel(kernel)
3942+ distro.set_initrd(initrd)
3943+ distro.set_arch(pxe_arch)
3944+ distro.set_breed(importer.breed)
3945+ # If a version was supplied on command line, we set it now
3946+ if self.os_version:
3947+ distro.set_os_version(self.os_version)
3948+
3949+ self.distros.add(distro,save=True)
3950+ distros_added.append(distro)
3951+
3952+ existing_profile = self.profiles.find(name=name)
3953+
3954+ # see if the profile name is already used, if so, skip it and
3955+ # do not modify the existing profile
3956+
3957+ if existing_profile is None:
3958+ self.logger.info("creating new profile: %s" % name)
3959+ #FIXME: The created profile holds a default kickstart, and should be breed specific
3960+ profile = self.config.new_profile()
3961+ else:
3962+ self.logger.info("skipping existing profile, name already exists: %s" % name)
3963+ continue
3964+
3965+ # save our minimal profile which just points to the distribution and a good
3966+ # default answer file
3967+
3968+ profile.set_name(name)
3969+ profile.set_distro(name)
3970+ if self.kickstart_file:
3971+ profile.set_kickstart(self.kickstart_file)
3972+ else:
3973+ profile.set_kickstart(importer.ks)
3974+
3975+ # depending on the name of the profile we can define a good virt-type
3976+ # for usage with koan
3977+
3978+ if name.find("-xen") != -1:
3979+ profile.set_virt_type("xenpv")
3980+ elif name.find("vmware") != -1:
3981+ profile.set_virt_type("vmware")
3982+ else:
3983+ profile.set_virt_type("qemu")
3984+
3985+ # save our new profile to the collection
3986+
3987+ self.profiles.add(profile,save=True)
3988+
3989+ # Create a rescue image as well, if this is not a xen distro
3990+ # but only for red hat profiles
3991+
3992+ # this code disabled as it seems to be adding "-rescue" to
3993+ # distros that are /not/ rescue related, which is wrong.
3994+ # left as a FIXME for those who find this feature interesting.
3995+
3996+ #if name.find("-xen") == -1 and importer.breed == "redhat":
3997+ # rescue_name = 'rescue-' + name
3998+ # existing_profile = self.profiles.find(name=rescue_name)
3999+ #
4000+ # if existing_profile is None:
4001+ # self.logger.info("creating new profile: %s" % rescue_name)
4002+ # profile = self.config.new_profile()
4003+ # else:
4004+ # continue
4005+ #
4006+ # profile.set_name(rescue_name)
4007+ # profile.set_distro(name)
4008+ # profile.set_virt_type("qemu")
4009+ # profile.kernel_options['rescue'] = None
4010+ # profile.kickstart = '/var/lib/cobbler/kickstarts/pxerescue.ks'
4011+ #
4012+ # self.profiles.add(profile,save=True)
4013+
4014+ # self.api.serialize() # not required, is implicit
4015+
4016+ return distros_added
4017+
4018+ # ========================================================================
4019+
4020+ def get_proposed_name(self,dirname,kernel=None):
4021+
4022+ """
4023+ Given a directory name where we have a kernel/initrd pair, try to autoname
4024+ the distribution (and profile) object based on the contents of that path
4025+ """
4026+
4027+ if self.network_root is not None:
4028+ name = self.mirror_name + "-".join(self.path_tail(os.path.dirname(self.path),dirname).split("/"))
4029+ else:
4030+ # remove the part that says /var/www/cobbler/ks_mirror/name
4031+ name = "-".join(dirname.split("/")[5:])
4032+
4033+ if kernel is not None and kernel.find("PAE") != -1:
4034+ name = name + "-PAE"
4035+
4036+ # These are all Ubuntu's doing, the netboot images are buried pretty
4037+ # deep. ;-) -JC
4038+ name = name.replace("-netboot","")
4039+ name = name.replace("-ubuntu-installer","")
4040+ name = name.replace("-amd64","")
4041+ name = name.replace("-i386","")
4042+
4043+ # we know that some kernel paths should not be in the name
4044+
4045+ name = name.replace("-images","")
4046+ name = name.replace("-pxeboot","")
4047+ name = name.replace("-install","")
4048+ name = name.replace("-isolinux","")
4049+
4050+ # some paths above the media root may have extra path segments we want
4051+ # to clean up
4052+
4053+ name = name.replace("-os","")
4054+ name = name.replace("-tree","")
4055+ name = name.replace("var-www-cobbler-", "")
4056+ name = name.replace("ks_mirror-","")
4057+ name = name.replace("--","-")
4058+
4059+ # remove any architecture name related string, as real arch will be appended later
4060+
4061+ name = name.replace("chrp","ppc64")
4062+
4063+ for separator in [ '-' , '_' , '.' ] :
4064+ for arch in [ "i386" , "x86_64" , "ia64" , "ppc64", "ppc32", "ppc", "x86" , "s390x", "s390" , "386" , "amd" ]:
4065+ name = name.replace("%s%s" % ( separator , arch ),"")
4066+
4067+ return name
4068+
4069+ # ========================================================================
4070+
4071+ def get_proposed_arch(self,dirname):
4072+ """
4073+ Given an directory name, can we infer an architecture from a path segment?
4074+ """
4075+ if dirname.find("x86_64") != -1 or dirname.find("amd") != -1:
4076+ return "x86_64"
4077+ if dirname.find("ia64") != -1:
4078+ return "ia64"
4079+ if dirname.find("i386") != -1 or dirname.find("386") != -1 or dirname.find("x86") != -1:
4080+ return "i386"
4081+ if dirname.find("s390x") != -1:
4082+ return "s390x"
4083+ if dirname.find("s390") != -1:
4084+ return "s390"
4085+ if dirname.find("ppc64") != -1 or dirname.find("chrp") != -1:
4086+ return "ppc64"
4087+ if dirname.find("ppc32") != -1:
4088+ return "ppc"
4089+ if dirname.find("ppc") != -1:
4090+ return "ppc"
4091+ return None
4092+
4093+# ==============================================
4094+
4095+
4096+def guess_breed(kerneldir,path,cli_breed,logger):
4097+
4098+ """
4099+ This tries to guess the distro. Traverses from kernel dir to imported root checking
4100+ for distro signatures, which are the locations in media where the search for release
4101+ packages should start. When a debian/ubuntu pool is found, the upper directory should
4102+ be checked to get the real breed. If we are on a real media, the upper directory will
4103+ be at the same level, as a local '.' symlink
4104+ The lowercase names are required for fat32/vfat filesystems
4105+ """
4106+ signatures = [
4107+ [ 'pool' , "debian" ],
4108+ [ 'VMware/RPMS' , "vmware" ],
4109+ [ 'imagedd.bz2' , "vmware" ],
4110+ [ 'RedHat/RPMS' , "redhat" ],
4111+ [ 'RedHat/rpms' , "redhat" ],
4112+ [ 'RedHat/Base' , "redhat" ],
4113+ [ 'Fedora/RPMS' , "redhat" ],
4114+ [ 'Fedora/rpms' , "redhat" ],
4115+ [ 'CentOS/RPMS' , "redhat" ],
4116+ [ 'CentOS/rpms' , "redhat" ],
4117+ [ 'CentOS' , "redhat" ],
4118+ [ 'Packages' , "redhat" ],
4119+ [ 'Fedora' , "redhat" ],
4120+ [ 'Server' , "redhat" ],
4121+ [ 'Client' , "redhat" ],
4122+ [ 'SL' , "redhat" ],
4123+ [ 'isolinux.bin', None ],
4124+ ]
4125+ guess = None
4126+
4127+ while kerneldir != os.path.dirname(path) :
4128+ logger.info("scanning %s for distro signature" % kerneldir)
4129+ for (x, breedguess) in signatures:
4130+ d = os.path.join( kerneldir , x )
4131+ if os.path.exists( d ):
4132+ guess = breedguess
4133+ break
4134+ if guess:
4135+ break
4136+
4137+ kerneldir = os.path.dirname(kerneldir)
4138+ else:
4139+ if cli_breed:
4140+ logger.info("Warning: No distro signature for kernel at %s, using value from command line" % kerneldir)
4141+ return (cli_breed , kerneldir , None)
4142+ utils.die(logger, "No distro signature for kernel at %s" % kerneldir )
4143+
4144+ if guess == "debian" :
4145+ for suite in [ "debian" , "ubuntu" ] :
4146+ # NOTE : Although we break the loop after the first match,
4147+ # multiple debian derived distros can actually live at the same pool -- JP
4148+ d = os.path.join( kerneldir , suite )
4149+ if os.path.islink(d) and os.path.isdir(d):
4150+ if os.path.realpath(d) == os.path.realpath(kerneldir):
4151+ return (suite, kerneldir ,x)
4152+ if os.path.basename( kerneldir ) == suite :
4153+ return (suite , kerneldir , x)
4154+
4155+ return (guess, kerneldir , x)
4156+
4157+# ============================================================
4158+
4159+
4160+def import_factory(kerneldir,path,cli_breed,logger):
4161+ """
4162+ Given a directory containing a kernel, return an instance of an Importer
4163+ that can be used to complete the import.
4164+ """
4165+
4166+ breed , rootdir, pkgdir = guess_breed(kerneldir,path,cli_breed,logger)
4167+ # NOTE : The guess_breed code should be included in the factory, in order to make
4168+ # the real root directory available, so allowing kernels at different levels within
4169+ # the same tree (removing the isolinux rejection from distro_adder) -- JP
4170+
4171+ if isinstance(rootdir, list):
4172+ if rootdir[1]:
4173+ logger.info("found content (breed=%s) at %s" % (breed,os.path.join( rootdir[0] , rootdir[1])))
4174+ else:
4175+ logger.info("found content (breed=%s) at %s" % (breed,rootdir[0]))
4176+ else:
4177+ logger.info("found content (breed=%s) at %s" % (breed,rootdir))
4178+
4179+ if cli_breed:
4180+ if cli_breed != breed:
4181+ utils.die(logger, "Requested breed (%s); breed found is %s" % ( cli_breed , breed ) )
4182+ breed = cli_breed
4183+
4184+ if breed == "redhat":
4185+ return RedHatImporter(logger,rootdir,pkgdir)
4186+ if breed == "vmware":
4187+ return VMwareImporter(logger,rootdir,pkgdir)
4188+ # disabled for 2.0
4189+ #elif breed == "debian":
4190+ # return DebianImporter(logger,rootdir,pkgdir)
4191+ #elif breed == "ubuntu":
4192+ # return UbuntuImporter(logger,rootdir,pkgdir)
4193+ elif breed:
4194+ utils.die(logger, "Unsupported OS breed %s" % breed)
4195+
4196+
4197+class BaseImporter:
4198+ """
4199+ Base class for distribution specific importer code.
4200+ """
4201+
4202+ # FIXME : Rename learn_arch_from_tree into guess_arch and simplify.
4203+ # FIXME : Drop package extension check and make a single search for all names.
4204+ # FIXME: Next methods to be moved here: kickstart_finder TRY_LIST loop
4205+
4206+ # ===================================================================
4207+
4208+ def arch_walker(self,foo,dirname,fnames):
4209+ """
4210+ See docs on learn_arch_from_tree.
4211+
4212+ The TRY_LIST is used to speed up search, and should be dropped for default importer
4213+ Searched kernel names are kernel-header, linux-headers-, kernel-largesmp, kernel-hugemem
4214+
4215+ This method is useful to get the archs, but also to package type and a raw guess of the breed
4216+ """
4217+
4218+ # try to find a kernel header RPM and then look at it's arch.
4219+ for x in fnames:
4220+ if self.match_kernelarch_file(x):
4221+ for arch in [ "i386" , "x86_64" , "ia64" , "ppc64", "ppc", "s390", "s390x" ]:
4222+ if x.find(arch) != -1:
4223+ foo[arch] = 1
4224+ for arch in [ "i686" , "amd64" ]:
4225+ if x.find(arch) != -1:
4226+ foo[arch] = 1
4227+
4228+ # ===================================================================
4229+
4230+ def get_rootdir(self):
4231+ return self.rootdir
4232+
4233+ # ===================================================================
4234+
4235+ def get_pkgdir(self):
4236+ if not self.pkgdir:
4237+ return None
4238+ return os.path.join(self.get_rootdir(),self.pkgdir)
4239+
4240+ # ===================================================================
4241+
4242+ def set_install_tree(self, distro, url):
4243+ distro.ks_meta["tree"] = url
4244+
4245+ # ===================================================================
4246+
4247+ def learn_arch_from_tree(self):
4248+ """
4249+ If a distribution is imported from DVD, there is a good chance the path doesn't
4250+ contain the arch and we should add it back in so that it's part of the
4251+ meaningful name ... so this code helps figure out the arch name. This is important
4252+ for producing predictable distro names (and profile names) from differing import sources
4253+ """
4254+ result = {}
4255+ # FIXME : this is called only once, should not be a walk
4256+ if self.get_pkgdir():
4257+ os.path.walk(self.get_pkgdir(), self.arch_walker, result)
4258+ if result.pop("amd64",False):
4259+ result["x86_64"] = 1
4260+ if result.pop("i686",False):
4261+ result["i386"] = 1
4262+ return result.keys()
4263+
4264+ def get_datestamp(self):
4265+ """
4266+ Allows each breed to return its datetime stamp
4267+ """
4268+ return None
4269+ # ===================================================================
4270+
4271+ def __init__(self,logger,rootdir,pkgdir):
4272+ raise exceptions.NotImplementedError
4273+
4274+ # ===================================================================
4275+
4276+ def process_repos(self, main_importer, distro):
4277+ raise exceptions.NotImplementedError
4278+
4279+# ===================================================================
4280+# ===================================================================
4281+
4282+class RedHatImporter ( BaseImporter ) :
4283+
4284+ def __init__(self,logger,rootdir,pkgdir):
4285+ self.breed = "redhat"
4286+ self.ks = "/var/lib/cobbler/kickstarts/default.ks"
4287+ self.rootdir = rootdir
4288+ self.pkgdir = pkgdir
4289+ self.logger = logger
4290+
4291+ # ================================================================
4292+
4293+ def get_release_files(self):
4294+ data = glob.glob(os.path.join(self.get_pkgdir(), "*release-*"))
4295+ data2 = []
4296+ for x in data:
4297+ b = os.path.basename(x)
4298+ if b.find("fedora") != -1 or \
4299+ b.find("redhat") != -1 or \
4300+ b.find("centos") != -1:
4301+ data2.append(x)
4302+ return data2
4303+
4304+ # ================================================================
4305+
4306+ def match_kernelarch_file(self, filename):
4307+ """
4308+ Is the given filename a kernel filename?
4309+ """
4310+
4311+ if not filename.endswith("rpm") and not filename.endswith("deb"):
4312+ return False
4313+ for match in ["kernel-header", "kernel-source", "kernel-smp", "kernel-largesmp", "kernel-hugemem", "linux-headers-", "kernel-devel", "kernel-"]:
4314+ if filename.find(match) != -1:
4315+ return True
4316+ return False
4317+
4318+ # ================================================================
4319+
4320+ def scan_pkg_filename(self, rpm):
4321+ """
4322+ Determine what the distro is based on the release package filename.
4323+ """
4324+
4325+ rpm = os.path.basename(rpm)
4326+
4327+ # if it looks like a RHEL RPM we'll cheat.
4328+ # it may be slightly wrong, but it will be close enough
4329+ # for RHEL5 we can get it exactly.
4330+
4331+ for x in [ "4AS", "4ES", "4WS", "4common", "4Desktop" ]:
4332+ if rpm.find(x) != -1:
4333+ return ("redhat", 4, 0)
4334+ for x in [ "3AS", "3ES", "3WS", "3Desktop" ]:
4335+ if rpm.find(x) != -1:
4336+ return ("redhat", 3, 0)
4337+ for x in [ "2AS", "2ES", "2WS", "2Desktop" ]:
4338+ if rpm.find(x) != -1:
4339+ return ("redhat", 2, 0)
4340+
4341+ # now get the flavor:
4342+ flavor = "redhat"
4343+ if rpm.lower().find("fedora") != -1:
4344+ flavor = "fedora"
4345+ if rpm.lower().find("centos") != -1:
4346+ flavor = "centos"
4347+
4348+ # get all the tokens and try to guess a version
4349+ accum = []
4350+ tokens = rpm.split(".")
4351+ for t in tokens:
4352+ tokens2 = t.split("-")
4353+ for t2 in tokens2:
4354+ try:
4355+ float(t2)
4356+ accum.append(t2)
4357+ except:
4358+ pass
4359+
4360+ major = float(accum[0])
4361+ minor = float(accum[1])
4362+ return (flavor, major, minor)
4363+
4364+ def get_datestamp(self):
4365+ """
4366+ Based on a RedHat tree find the creation timestamp
4367+ """
4368+ base = self.get_rootdir()
4369+ if os.path.exists("%s/.discinfo" % base):
4370+ discinfo = open("%s/.discinfo" % base, "r")
4371+ datestamp = discinfo.read().split("\n")[0]
4372+ discinfo.close()
4373+ else:
4374+ return 0
4375+ return float(datestamp)
4376+
4377+ def set_variance(self, flavor, major, minor, arch):
4378+
4379+ """
4380+ find the profile kickstart and set the distro breed/os-version based on what
4381+ we can find out from the rpm filenames and then return the kickstart
4382+ path to use.
4383+ """
4384+
4385+ if flavor == "fedora":
4386+
4387+ # this may actually fail because the libvirt/virtinst database
4388+ # is not always up to date. We keep a simplified copy of this
4389+ # in codes.py. If it fails we set it to something generic
4390+ # and don't worry about it.
4391+
4392+ try:
4393+ os_version = "fedora%s" % int(major)
4394+ except:
4395+ os_version = "other"
4396+
4397+ if flavor == "redhat" or flavor == "centos":
4398+
4399+ if major <= 2:
4400+ # rhel2.1 is the only rhel2
4401+ os_version = "rhel2.1"
4402+ else:
4403+ try:
4404+ # must use libvirt version
4405+ os_version = "rhel%s" % (int(major))
4406+ except:
4407+ os_version = "other"
4408+
4409+ kickbase = "/var/lib/cobbler/kickstarts"
4410+ # Look for ARCH/OS_VERSION.MINOR kickstart first
4411+ # ARCH/OS_VERSION next
4412+ # OS_VERSION next
4413+ # OS_VERSION.MINOR next
4414+ # ARCH/default.ks next
4415+ # FLAVOR.ks next
4416+ kickstarts = [
4417+ "%s/%s/%s.%i.ks" % (kickbase,arch,os_version,int(minor)),
4418+ "%s/%s/%s.ks" % (kickbase,arch,os_version),
4419+ "%s/%s.%i.ks" % (kickbase,os_version,int(minor)),
4420+ "%s/%s.ks" % (kickbase,os_version),
4421+ "%s/%s/default.ks" % (kickbase,arch),
4422+ "%s/%s.ks" % (kickbase,flavor),
4423+ ]
4424+ for kickstart in kickstarts:
4425+ if os.path.exists(kickstart):
4426+ return os_version, kickstart
4427+
4428+ major = int(major)
4429+
4430+ if flavor == "fedora":
4431+ if major >= 8:
4432+ return os_version , "/var/lib/cobbler/kickstarts/sample_end.ks"
4433+ if major >= 6:
4434+ return os_version , "/var/lib/cobbler/kickstarts/sample.ks"
4435+
4436+ if flavor == "redhat" or flavor == "centos":
4437+ if major >= 5:
4438+ return os_version , "/var/lib/cobbler/kickstarts/sample.ks"
4439+
4440+ return os_version , "/var/lib/cobbler/kickstarts/legacy.ks"
4441+
4442+ self.logger.warning("could not use distro specifics, using rhel 4 compatible kickstart")
4443+ return None , "/var/lib/cobbler/kickstarts/legacy.ks"
4444+
4445+
4446+class VMwareImporter (BaseImporter):
4447+ """
4448+ VMware specific importer code.
4449+ """
4450+
4451+ def __init__(self,logger,rootdir,pkgdir):
4452+ self.breed = "vmware"
4453+ self.ks = "/var/lib/cobbler/kickstarts/default.ks"
4454+ self.rootdir = rootdir
4455+ self.pkgdir = pkgdir
4456+ self.logger = logger
4457+
4458+ def learn_arch_from_tree(self):
4459+ """
4460+ Attempt to figure out the arch from packages in the install tree.
4461+ ESX 4 and up is 64bit.
4462+ """
4463+ result = ["x86_64"]
4464+ return result
4465+
4466+ def get_release_files(self):
4467+ """
4468+ Find distro release packages.
4469+ """
4470+ data = glob.glob(os.path.join(self.get_pkgdir(), "*release-*"))
4471+ data2 = []
4472+ for x in data:
4473+ b = os.path.basename(x)
4474+ if b.find("vmware") != -1:
4475+ data2.append(x)
4476+ if len(data2) == 0:
4477+ # ESXi maybe?
4478+ return glob.glob(os.path.join(self.get_rootdir(), "imagedd.bz2*"))
4479+ return data2
4480+
4481+ def scan_pkg_filename(self, rpm):
4482+ """
4483+ Determine what the distro is based on the release package filename.
4484+ """
4485+ rpm = os.path.basename(rpm)
4486+
4487+ if rpm.lower().find("-esx-") != -1:
4488+ flavor = "esx"
4489+ elif rpm.lower() == "imagedd.bz2":
4490+ flavor = "esxi"
4491+
4492+ match = re.search(r'^([\-a-zA-Z0-9]+)-([\.0-9]+)-([\.0-9]+)\.', rpm)
4493+ if match:
4494+ (name, version, release) = [match.group(1), match.group(2), match.group(3)]
4495+ major = version.split('.')[0]
4496+ minor = release.split('.')[0]
4497+ else:
4498+ # FIXME: better major/minor detection for esxi
4499+ # or if the match falls through for some reason
4500+ major = 4
4501+ minor = 0
4502+
4503+ return (flavor, major, minor)
4504+
4505+ def set_variance(self, flavor, major, minor, arch):
4506+ """
4507+ Set distro specific versioning.
4508+ """
4509+ os_version = "%s%s" % (flavor, major)
4510+ return os_version , "/var/lib/cobbler/kickstarts/default.ks"
4511+
4512+
4513+ def get_datestamp(self):
4514+ """
4515+ Based on a VMWare tree find the creation timestamp
4516+ """
4517+ pass
4518+
4519+#class DebianImporter ( BaseImporter ) :
4520+#
4521+# def __init__(self,logger,rootdir,pkgdir):
4522+# self.breed = "debian"
4523+# self.ks = "/var/lib/cobbler/kickstarts/sample.seed"
4524+# self.rootdir = rootdir
4525+# self.pkgdir = pkgdir
4526+# self.logger = logger
4527+#
4528+# def get_release_files(self):
4529+# if not self.get_pkgdir():
4530+# return []
4531+# # search for base-files or base-installer ?
4532+# return glob.glob(os.path.join(self.get_pkgdir(), "main/b/base-files" , "base-files_*"))
4533+#
4534+# def match_kernelarch_file(self, filename):
4535+# if not filename.endswith("deb"):
4536+# return False
4537+# if filename.startswith("linux-headers-"):
4538+# return True
4539+# return False
4540+#
4541+# def scan_pkg_filename(self, deb):
4542+#
4543+# deb = os.path.basename(deb)
4544+# self.logger.info("processing deb : %s" % deb)
4545+#
4546+# # get all the tokens and try to guess a version
4547+# accum = []
4548+# tokens = deb.split("_")
4549+# tokens2 = tokens[1].split(".")
4550+# for t2 in tokens2:
4551+# try:
4552+# val = int(t2)
4553+# accum.append(val)
4554+# except:
4555+# pass
4556+# # Safeguard for non-guessable versions
4557+# if not accum:
4558+# return None
4559+# accum.append(0)
4560+#
4561+# return (None, accum[0], accum[1])
4562+#
4563+# def set_variance(self, flavor, major, minor, arch):
4564+#
4565+# dist_names = { '4.0' : "etch" , '5.0' : "lenny" }
4566+# dist_vers = "%s.%s" % ( major , minor )
4567+# os_version = dist_names[dist_vers]
4568+#
4569+# return os_version , "/var/lib/cobbler/kickstarts/sample.seed"
4570+#
4571+# def set_install_tree(self, distro, url):
4572+# idx = url.find("://")
4573+# url = url[idx+3:]
4574+#
4575+# idx = url.find("/")
4576+# distro.ks_meta["hostname"] = url[:idx]
4577+# distro.ks_meta["directory"] = url[idx:]
4578+# if not distro.os_version :
4579+# utils.die(self.logger, "OS version is required for debian distros")
4580+# distro.ks_meta["suite"] = distro.os_version
4581+#
4582+# def process_repos(self, main_importer, distro):
4583+#
4584+# # Create a disabled repository for the new distro, and the security updates
4585+# #
4586+# # NOTE : We cannot use ks_meta nor os_version because they get fixed at a later stage
4587+#
4588+# repo = item_repo.Repo(main_importer.config)
4589+# repo.set_breed( "apt" )
4590+# repo.set_arch( distro.arch )
4591+# repo.set_keep_updated( False )
4592+# repo.yumopts["--ignore-release-gpg"] = None
4593+# repo.yumopts["--verbose"] = None
4594+# repo.set_name( distro.name )
4595+# repo.set_os_version( distro.os_version )
4596+# # NOTE : The location of the mirror should come from timezone
4597+# repo.set_mirror( "http://ftp.%s.debian.org/debian/dists/%s" % ( 'us' , '@@suite@@' ) )
4598+#
4599+# security_repo = item_repo.Repo(main_importer.config)
4600+# security_repo.set_breed( "apt" )
4601+# security_repo.set_arch( distro.arch )
4602+# security_repo.set_keep_updated( False )
4603+# security_repo.yumopts["--ignore-release-gpg"] = None
4604+# security_repo.yumopts["--verbose"] = None
4605+# security_repo.set_name( distro.name + "-security" )
4606+# security_repo.set_os_version( distro.os_version )
4607+# # There are no official mirrors for security updates
4608+# security_repo.set_mirror( "http://security.debian.org/debian-security/dists/%s/updates" % '@@suite@@' )
4609+#
4610+# self.logger.info("Added repos for %s" % distro.name)
4611+# repos = main_importer.config.repos()
4612+# repos.add(repo,save=True)
4613+# repos.add(security_repo,save=True)
4614+
4615+
4616+#class UbuntuImporter ( DebianImporter ) :
4617+#
4618+# def __init__(self,rootdir,pkgdir):
4619+# DebianImporter.__init__(self,rootdir,pkgdir)
4620+# self.breed = "ubuntu"
4621+#
4622+# def get_release_files(self):
4623+# if not self.get_pkgdir():
4624+# return []
4625+# return glob.glob(os.path.join(self.get_pkgdir(), "main/u/ubuntu-docs" , "ubuntu-docs_*"))
4626+#
4627+# def set_variance(self, flavor, major, minor, arch):
4628+#
4629+# # Release names taken from wikipedia
4630+# dist_names = { '6.4':"dapper", '8.4':"hardy", '8.10':"intrepid", '9.4':"jaunty" }
4631+# dist_vers = "%s.%s" % ( major , minor )
4632+# if not dist_names.has_key( dist_vers ):
4633+# dist_names['4ubuntu2.0'] = "IntrepidIbex"
4634+# os_version = dist_names[dist_vers]
4635+#
4636+# return os_version , "/var/lib/cobbler/kickstarts/sample.seed"
4637+#
4638+# def process_repos(self, main_importer, distro):
4639+#
4640+# pass
4641
4642=== added file 'cobbler/action_litesync.py'
4643--- cobbler/action_litesync.py 1970-01-01 00:00:00 +0000
4644+++ cobbler/action_litesync.py 2011-03-11 21:10:49 +0000
4645@@ -0,0 +1,167 @@
4646+"""
4647+Running small pieces of cobbler sync when certain actions are taken,
4648+such that we don't need a time consuming sync when adding new
4649+systems if nothing has changed for systems that have already
4650+been created.
4651+
4652+Copyright 2006-2009, Red Hat, Inc
4653+Michael DeHaan <mdehaan@redhat.com>
4654+
4655+This program is free software; you can redistribute it and/or modify
4656+it under the terms of the GNU General Public License as published by
4657+the Free Software Foundation; either version 2 of the License, or
4658+(at your option) any later version.
4659+
4660+This program is distributed in the hope that it will be useful,
4661+but WITHOUT ANY WARRANTY; without even the implied warranty of
4662+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4663+GNU General Public License for more details.
4664+
4665+You should have received a copy of the GNU General Public License
4666+along with this program; if not, write to the Free Software
4667+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
4668+02110-1301 USA
4669+"""
4670+
4671+import os
4672+import os.path
4673+
4674+import utils
4675+import traceback
4676+import clogger
4677+import module_loader
4678+
4679+class BootLiteSync:
4680+ """
4681+ Handles conversion of internal state to the tftpboot tree layout
4682+ """
4683+
4684+ def __init__(self,config,verbose=False,logger=None):
4685+ """
4686+ Constructor
4687+ """
4688+ self.verbose = verbose
4689+ self.config = config
4690+ self.distros = config.distros()
4691+ self.profiles = config.profiles()
4692+ self.systems = config.systems()
4693+ self.images = config.images()
4694+ self.settings = config.settings()
4695+ self.repos = config.repos()
4696+ if logger is None:
4697+ logger = clogger.Logger()
4698+ self.logger = logger
4699+ self.tftpd = module_loader.get_module_from_file(
4700+ "tftpd","module","in_tftpd"
4701+ ).get_manager(config,logger)
4702+ self.sync = config.api.get_sync(verbose,logger=self.logger)
4703+ self.sync.make_tftpboot()
4704+
4705+ def add_single_distro(self, name):
4706+ # get the distro record
4707+ distro = self.distros.find(name=name)
4708+ if distro is None:
4709+ return
4710+ # copy image files to images/$name in webdir & tftpboot:
4711+ self.sync.pxegen.copy_single_distro_files(distro,
4712+ self.settings.webdir,True)
4713+ self.tftpd.add_single_distro(distro)
4714+
4715+ # generate any templates listed in the distro
4716+ self.sync.pxegen.write_templates(distro)
4717+ # cascade sync
4718+ kids = distro.get_children()
4719+ for k in kids:
4720+ self.add_single_profile(k.name, rebuild_menu=False)
4721+ self.sync.pxegen.make_pxe_menu()
4722+
4723+
4724+ def add_single_image(self, name):
4725+ image = self.images.find(name=name)
4726+ self.sync.pxegen.copy_single_image_files(image)
4727+ kids = image.get_children()
4728+ for k in kids:
4729+ self.add_single_system(k.name)
4730+ self.sync.pxegen.make_pxe_menu()
4731+
4732+ def remove_single_distro(self, name):
4733+ bootloc = utils.tftpboot_location()
4734+ # delete contents of images/$name directory in webdir
4735+ utils.rmtree(os.path.join(self.settings.webdir, "images", name))
4736+ # delete contents of images/$name in tftpboot
4737+ utils.rmtree(os.path.join(bootloc, "images", name))
4738+ # delete potential symlink to tree in webdir/links
4739+ utils.rmfile(os.path.join(self.settings.webdir, "links", name))
4740+
4741+ def remove_single_image(self, name):
4742+ bootloc = utils.tftpboot_location()
4743+ utils.rmfile(os.path.join(bootloc, "images2", name))
4744+
4745+ def add_single_profile(self, name, rebuild_menu=True):
4746+ # get the profile object:
4747+ profile = self.profiles.find(name=name)
4748+ if profile is None:
4749+ # most likely a subprofile's kid has been
4750+ # removed already, though the object tree has
4751+ # not been reloaded ... and this is just noise.
4752+ return
4753+ # rebuild the yum configuration files for any attached repos
4754+ # generate any templates listed in the distro
4755+ self.sync.pxegen.write_templates(profile)
4756+ # cascade sync
4757+ kids = profile.get_children()
4758+ for k in kids:
4759+ if k.COLLECTION_TYPE == "profile":
4760+ self.add_single_profile(k.name, rebuild_menu=False)
4761+ else:
4762+ self.add_single_system(k.name)
4763+ if rebuild_menu:
4764+ self.sync.pxegen.make_pxe_menu()
4765+ return True
4766+
4767+ def remove_single_profile(self, name, rebuild_menu=True):
4768+ # delete profiles/$name file in webdir
4769+ utils.rmfile(os.path.join(self.settings.webdir, "profiles", name))
4770+ # delete contents on kickstarts/$name directory in webdir
4771+ utils.rmtree(os.path.join(self.settings.webdir, "kickstarts", name))
4772+ if rebuild_menu:
4773+ self.sync.pxegen.make_pxe_menu()
4774+
4775+ def update_system_netboot_status(self,name):
4776+ self.tftpd.update_netboot(name)
4777+
4778+ def add_single_system(self, name):
4779+ # get the system object:
4780+ system = self.systems.find(name=name)
4781+ if system is None:
4782+ return
4783+ # rebuild system_list file in webdir
4784+ if self.settings.manage_dhcp:
4785+ self.sync.dhcp.regen_ethers()
4786+ if self.settings.manage_dns:
4787+ self.sync.dns.regen_hosts()
4788+ # write the PXE files for the system
4789+ self.tftpd.add_single_system(system)
4790+
4791+ def remove_single_system(self, name):
4792+ bootloc = utils.tftpboot_location()
4793+ system_record = self.systems.find(name=name)
4794+ # delete contents of kickstarts_sys/$name in webdir
4795+ system_record = self.systems.find(name=name)
4796+
4797+ itanic = False
4798+ profile = self.profiles.find(name=system_record.profile)
4799+ if profile is not None:
4800+ distro = self.distros.find(name=profile.get_conceptual_parent().name)
4801+ if distro is not None and distro in [ "ia64", "IA64"]:
4802+ itanic = True
4803+
4804+ for (name,interface) in system_record.interfaces.iteritems():
4805+ filename = utils.get_config_filename(system_record,interface=name)
4806+
4807+ if not itanic:
4808+ utils.rmfile(os.path.join(bootloc, "pxelinux.cfg", filename))
4809+ utils.rmfile(os.path.join(bootloc, "grub", filename.upper()))
4810+ else:
4811+ utils.rmfile(os.path.join(bootloc, filename))
4812+
4813
4814=== added file 'cobbler/action_log.py'
4815--- cobbler/action_log.py 1970-01-01 00:00:00 +0000
4816+++ cobbler/action_log.py 2011-03-11 21:10:49 +0000
4817@@ -0,0 +1,71 @@
4818+"""
4819+
4820+Copyright 2009, Red Hat, Inc
4821+Bill Peck <bpeck@redhat.com>
4822+
4823+This program is free software; you can redistribute it and/or modify
4824+it under the terms of the GNU General Public License as published by
4825+the Free Software Foundation; either version 2 of the License, or
4826+(at your option) any later version.
4827+
4828+This program is distributed in the hope that it will be useful,
4829+but WITHOUT ANY WARRANTY; without even the implied warranty of
4830+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4831+GNU General Public License for more details.
4832+
4833+You should have received a copy of the GNU General Public License
4834+along with this program; if not, write to the Free Software
4835+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
4836+02110-1301 USA
4837+"""
4838+
4839+
4840+import os
4841+import os.path
4842+import sys
4843+import traceback
4844+import clogger
4845+
4846+import utils
4847+from cexceptions import *
4848+import glob
4849+
4850+class LogTool:
4851+ """
4852+ Helpers for dealing with System logs, consoles, anamon, etc..
4853+ """
4854+
4855+ def __init__(self,config,system,api,logger=None):
4856+ """
4857+ Log library constructor requires a cobbler system object.
4858+ """
4859+ self.system = system
4860+ self.config = config
4861+ self.settings = config.settings()
4862+ self.api = api
4863+ if logger is None:
4864+ logger = clogger.Logger()
4865+ self.logger = logger
4866+
4867+
4868+ def clear(self):
4869+ """
4870+ Clears the system logs
4871+ """
4872+
4873+ #FIXME /var/consoles should come from config.settings()
4874+ logs = ['/var/consoles/%s' % self.system.name]
4875+ anamon_dir = '/var/log/cobbler/anamon/%s' % self.system.name
4876+ if os.path.isdir(anamon_dir):
4877+ logs.extend(filter(os.path.isfile, glob.glob('%s/*' % anamon_dir)))
4878+ for log in logs:
4879+ try:
4880+ f = open(log, 'w')
4881+ f.truncate()
4882+ f.close()
4883+ except IOError, e:
4884+ self.logger.info("Failed to Truncate '%s':%s " % (log, e))
4885+ except OSError, e:
4886+ self.logger.info("Failed to Truncate '%s':%s " % (log, e))
4887+ return 0
4888+
4889
4890=== added file 'cobbler/action_power.py'
4891--- cobbler/action_power.py 1970-01-01 00:00:00 +0000
4892+++ cobbler/action_power.py 2011-03-11 21:10:49 +0000
4893@@ -0,0 +1,150 @@
4894+"""
4895+Power management library. For cobbler objects with power management configured
4896+encapsulate the logic to run power management commands so that the admin does not
4897+have to use seperate tools and remember how each of the power management tools are
4898+set up. This makes power cycling a system for reinstallation much easier.
4899+
4900+See https://fedorahosted.org/cobbler/wiki/PowerManagement
4901+
4902+Copyright 2008-2009, Red Hat, Inc
4903+Michael DeHaan <mdehaan@redhat.com>
4904+
4905+This program is free software; you can redistribute it and/or modify
4906+it under the terms of the GNU General Public License as published by
4907+the Free Software Foundation; either version 2 of the License, or
4908+(at your option) any later version.
4909+
4910+This program is distributed in the hope that it will be useful,
4911+but WITHOUT ANY WARRANTY; without even the implied warranty of
4912+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4913+GNU General Public License for more details.
4914+
4915+You should have received a copy of the GNU General Public License
4916+along with this program; if not, write to the Free Software
4917+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
4918+02110-1301 USA
4919+"""
4920+
4921+
4922+import os
4923+import os.path
4924+import traceback
4925+import time
4926+import re
4927+
4928+import utils
4929+import func_utils
4930+from cexceptions import *
4931+import templar
4932+import clogger
4933+
4934+class PowerTool:
4935+ """
4936+ Handles conversion of internal state to the tftpboot tree layout
4937+ """
4938+
4939+ def __init__(self,config,system,api,force_user=None,force_pass=None,logger=None):
4940+ """
4941+ Power library constructor requires a cobbler system object.
4942+ """
4943+ self.system = system
4944+ self.config = config
4945+ self.settings = config.settings()
4946+ self.api = api
4947+ self.logger = self.api.logger
4948+ self.force_user = force_user
4949+ self.force_pass = force_pass
4950+ if logger is None:
4951+ logger = clogger.Logger()
4952+ self.logger = logger
4953+
4954+ def power(self, desired_state):
4955+ """
4956+ state is either "on" or "off". Rebooting is implemented at the api.py
4957+ level.
4958+
4959+ The user and password need not be supplied. If not supplied they
4960+ will be taken from the environment, COBBLER_POWER_USER and COBBLER_POWER_PASS.
4961+ If provided, these will override any other data and be used instead. Users
4962+ interested in maximum security should take that route.
4963+ """
4964+
4965+ template = self.get_command_template()
4966+ template_file = open(template, "r")
4967+
4968+ meta = utils.blender(self.api, False, self.system)
4969+ meta["power_mode"] = desired_state
4970+
4971+ # allow command line overrides of the username/password
4972+ if self.force_user is not None:
4973+ meta["power_user"] = self.force_user
4974+ if self.force_pass is not None:
4975+ meta["power_pass"] = self.force_pass
4976+
4977+ tmp = templar.Templar(self.api._config)
4978+ cmd = tmp.render(template_file, meta, None, self.system)
4979+ template_file.close()
4980+
4981+ cmd = cmd.strip()
4982+
4983+ self.logger.info("cobbler power configuration is:")
4984+
4985+ self.logger.info(" type : %s" % self.system.power_type)
4986+ self.logger.info(" address: %s" % self.system.power_address)
4987+ self.logger.info(" user : %s" % self.system.power_user)
4988+ self.logger.info(" id : %s" % self.system.power_id)
4989+
4990+ # if no username/password data, check the environment
4991+
4992+ if meta.get("power_user","") == "":
4993+ meta["power_user"] = os.environ.get("COBBLER_POWER_USER","")
4994+ if meta.get("power_pass","") == "":
4995+ meta["power_pass"] = os.environ.get("COBBLER_POWER_PASS","")
4996+
4997+ self.logger.info("- %s" % cmd)
4998+
4999+ # use shell so we can have mutliple power commands chained together
5000+ cmd = ['/bin/sh','-c', cmd]
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches