~racb/ubuntu/precise/cobbler/upstream_location

« back to all changes in this revision

Viewing changes to .pc/47_ubuntu_add_codenames.patch/cobbler/modules/manage_import_debian_ubuntu.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Chuck Short, Clint Byrum, Robie Basak
  • Date: 2011-11-15 12:35:40 UTC
  • mfrom: (1.1.8)
  • Revision ID: package-import@ubuntu.com-20111115123540-5g139uuhg7z0hv5d
Tags: 2.2.2-0ubuntu1
[Chuck Short]
* New upstream release:
  + Use dh_python2 everywhere.
  + Folded debian/patches/49_ubuntu_add_arm_arch_support.patch
    and debian/patches/56_ubuntu_arm_generate_pxe_files.patch
    into one patch for easier upstreaming.
  + Dropped debian/patches/50_fix_cobbler_timezone.patch:
    Fix upstream.
  + Dropped debian/patches/47_ubuntu_add_oneiric_codename.patch
    in favor of debian/patches/47_ubuntu_add_codenames.patch:
    It adds "precise" and drops unsupported releases as well.
  + Dropped debian/patches/41_update_tree_path_with_arch.patch:
    No longer needed.
  + Dropped debian/patches/55_ubuntu_branding.patch: Will be moved
    to orchestra

 [Clint Byrum]
 * debian/cobbler.postinst: create users.digest mode 0600 so it
   is not world readable. (LP: #858860)
 * debian/control: cobbler needs to depend on python-cobbler
   (LP: #863738)
 * debian/patches/58_fix_egg_cache.patch: Do not point dangerous
   PYTHON_EGG_CACHE at world writable directory. (LP: #858875)
 * debian/cobbler-common.install: remove users.digest as it is
   not required and contains a known password that would leave
   cobblerd vulnerable if started before configuration is done
 * debian/cobbler-web.postinst: fix perms on webui_sessions to
   be more secure (LP: #863755)

 [Robie Basak]
 * Backport safe YAML load from upstream. (LP: #858883)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
This is some of the code behind 'cobbler sync'.
 
3
 
 
4
Copyright 2006-2009, Red Hat, Inc
 
5
Michael DeHaan <mdehaan@redhat.com>
 
6
John Eckersberg <jeckersb@redhat.com>
 
7
 
 
8
This program is free software; you can redistribute it and/or modify
 
9
it under the terms of the GNU General Public License as published by
 
10
the Free Software Foundation; either version 2 of the License, or
 
11
(at your option) any later version.
 
12
 
 
13
This program is distributed in the hope that it will be useful,
 
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
GNU General Public License for more details.
 
17
 
 
18
You should have received a copy of the GNU General Public License
 
19
along with this program; if not, write to the Free Software
 
20
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
21
02110-1301  USA
 
22
"""
 
23
 
 
24
import os
 
25
import os.path
 
26
import shutil
 
27
import time
 
28
import sys
 
29
import glob
 
30
import traceback
 
31
import errno
 
32
import re
 
33
from utils import popen2
 
34
from shlex import shlex
 
35
 
 
36
import codes
 
37
import utils
 
38
from cexceptions import *
 
39
import templar
 
40
 
 
41
import item_distro
 
42
import item_profile
 
43
import item_repo
 
44
import item_system
 
45
 
 
46
from utils import _
 
47
 
 
48
# Import aptsources module if available to obtain repo mirror.
 
49
try:
 
50
    from aptsources import distro
 
51
    from aptsources import sourceslist
 
52
    apt_available = True
 
53
except:
 
54
    apt_available = False
 
55
 
 
56
def register():
 
57
   """
 
58
   The mandatory cobbler module registration hook.
 
59
   """
 
60
   return "manage/import"
 
61
 
 
62
 
 
63
class ImportDebianUbuntuManager:
 
64
 
 
65
    def __init__(self,config,logger):
 
66
        """
 
67
        Constructor
 
68
        """
 
69
        self.logger        = logger
 
70
        self.config        = config
 
71
        self.api           = config.api
 
72
        self.distros       = config.distros()
 
73
        self.profiles      = config.profiles()
 
74
        self.systems       = config.systems()
 
75
        self.settings      = config.settings()
 
76
        self.repos         = config.repos()
 
77
        self.templar       = templar.Templar(config)
 
78
 
 
79
    # required function for import modules
 
80
    def what(self):
 
81
        return "import/debian_ubuntu"
 
82
 
 
83
    # required function for import modules
 
84
    def check_for_signature(self,path,cli_breed):
 
85
       signatures = [
 
86
           'pool',
 
87
           '.disk/mini-info',
 
88
       ]
 
89
 
 
90
       #self.logger.info("scanning %s for a debian/ubuntu distro signature" % path)
 
91
       for signature in signatures:
 
92
           d = os.path.join(path,signature)
 
93
           if os.path.exists(d):
 
94
               self.logger.info("Found a debian/ubuntu compatible signature: %s" % signature)
 
95
               return (True,signature)
 
96
 
 
97
       if cli_breed and cli_breed in self.get_valid_breeds():
 
98
           self.logger.info("Warning: No distro signature for kernel at %s, using value from command line" % path)
 
99
           return (True,None)
 
100
 
 
101
       return (False,None)
 
102
 
 
103
    # required function for import modules
 
104
    def run(self,pkgdir,name,path,network_root=None,kickstart_file=None,rsync_flags=None,arch=None,breed=None,os_version=None):
 
105
        self.pkgdir = pkgdir
 
106
        self.name = name
 
107
        self.network_root = network_root
 
108
        self.kickstart_file = kickstart_file
 
109
        self.rsync_flags = rsync_flags
 
110
        self.arch = arch
 
111
        self.breed = breed
 
112
        self.os_version = os_version
 
113
        self.path = path
 
114
 
 
115
        # some fixups for the XMLRPC interface, which does not use "None"
 
116
        if self.arch == "":           self.arch           = None
 
117
        if self.kickstart_file == "": self.kickstart_file = None
 
118
        if self.os_version == "":     self.os_version     = None
 
119
        if self.rsync_flags == "":    self.rsync_flags    = None
 
120
        if self.network_root == "":   self.network_root   = None
 
121
 
 
122
        # If no breed was specified on the command line, figure it out
 
123
        if self.breed == None:
 
124
            self.breed = self.get_breed_from_directory()
 
125
            if not self.breed:
 
126
                utils.die(self.logger,"import failed - could not determine breed of debian-based distro")
 
127
               
 
128
        # if we're going to do any copying, set where to put things
 
129
        # and then make sure nothing is already there.
 
130
 
 
131
        # import takes a --kickstart for forcing selection that can't be used in all circumstances
 
132
 
 
133
        if self.kickstart_file and not self.breed:
 
134
            utils.die(self.logger,"Kickstart file can only be specified when a specific breed is selected")
 
135
 
 
136
        if self.os_version and not self.breed:
 
137
            utils.die(self.logger,"OS version can only be specified when a specific breed is selected")
 
138
 
 
139
        if self.breed and self.breed.lower() not in self.get_valid_breeds():
 
140
            utils.die(self.logger,"Supplied import breed is not supported by this module")
 
141
 
 
142
        # try to detect arch and os_version when importing an Ubuntu mini ISO. This is,
 
143
        # if the signature is the file '.disk/mini-info' which will only be found in mini iso.
 
144
        # This is determined when when detecting the signature, and if this is a readable file.
 
145
        # This file contains info in the way:
 
146
        #   'Ubuntu-Server 11.04 "Natty Narwhal" - Beta i386 (20110407)'
 
147
        #   'Ubuntu 11.10 "oneiric" - i386 (20101020ubuntu35)'
 
148
        info_file_path = "%s/%s" % (self.path, self.pkgdir)
 
149
        if os.path.isfile(info_file_path):
 
150
            info_file = open(info_file_path, "r")
 
151
            # traverse through the split info_line looking for a supportted os_version/arch.
 
152
            for str in info_file.readline().split():
 
153
                info = str.strip('"').lower()
 
154
                # Only set os_version/arch if not already done so.
 
155
                if info in self.get_valid_os_versions() and not self.os_version:
 
156
                    self.os_version = info
 
157
                # if info is arch amd64 replace it with x86_64 because cobbler does not suppor
 
158
                # amd64 for imports.
 
159
                if info == "amd64":
 
160
                    info = "x86_64"
 
161
                if info in self.get_valid_arches() and not self.arch:
 
162
                    self.arch = info
 
163
 
 
164
        # now walk the filesystem looking for distributions that match certain patterns
 
165
 
 
166
        self.logger.info("adding distros")
 
167
        distros_added = []
 
168
        # FIXME : search below self.path for isolinux configurations or known directories from TRY_LIST
 
169
        os.path.walk(self.path, self.distro_adder, distros_added)
 
170
 
 
171
        # find out if we can auto-create any repository records from the install tree
 
172
 
 
173
        if self.network_root is None:
 
174
            self.logger.info("associating repos")
 
175
            # FIXME: this automagic is not possible (yet) without mirroring
 
176
            self.repo_finder(distros_added)
 
177
 
 
178
        # find the most appropriate answer files for each profile object
 
179
 
 
180
        self.logger.info("associating kickstarts")
 
181
        self.kickstart_finder(distros_added)
 
182
 
 
183
        # ensure bootloaders are present
 
184
        self.api.pxegen.copy_bootloaders()
 
185
 
 
186
        return True
 
187
 
 
188
    # required function for import modules
 
189
    def get_valid_arches(self):
 
190
        return ["i386", "ppc", "x86_64", "x86", "arm",]
 
191
 
 
192
    # required function for import modules
 
193
    def get_valid_breeds(self):
 
194
        return ["debian","ubuntu"]
 
195
 
 
196
    # required function for import modules
 
197
    def get_valid_os_versions(self):
 
198
        if self.breed == "debian":
 
199
            return codes.VALID_OS_VERSIONS["debian"]
 
200
        elif self.breed == "ubuntu":
 
201
            return codes.VALID_OS_VERSIONS["ubuntu"]
 
202
        else:
 
203
            return []
 
204
 
 
205
    def get_valid_repo_breeds(self):
 
206
        return ["apt",]
 
207
 
 
208
    def get_release_files(self):
 
209
        """
 
210
        Find distro release packages.
 
211
        """
 
212
        return glob.glob(os.path.join(self.get_rootdir(), "dists/*"))
 
213
 
 
214
    def get_breed_from_directory(self):
 
215
        for breed in self.get_valid_breeds():
 
216
            # NOTE : Although we break the loop after the first match,
 
217
            # multiple debian derived distros can actually live at the same pool -- JP
 
218
            d = os.path.join(self.path, breed)
 
219
            if (os.path.islink(d) and os.path.isdir(d) and os.path.realpath(d) == os.path.realpath(self.path)) or os.path.basename(self.path) == breed:
 
220
                return breed
 
221
        else:
 
222
            return None
 
223
 
 
224
    def get_tree_location(self, distro):
 
225
        """
 
226
        Once a distribution is identified, find the part of the distribution
 
227
        that has the URL in it that we want to use for kickstarting the
 
228
        distribution, and create a ksmeta variable $tree that contains this.
 
229
        """
 
230
 
 
231
        base = self.get_rootdir()
 
232
 
 
233
        if self.network_root is None:
 
234
            dists_path = os.path.join(self.path, "dists")
 
235
            if os.path.isdir(dists_path):
 
236
                tree = "http://@@http_server@@/cblr/ks_mirror/%s" % (self.name)
 
237
            else:
 
238
                tree = "http://@@http_server@@/cblr/repo_mirror/%s" % (distro.name)
 
239
            self.set_install_tree(distro, tree)
 
240
        else:
 
241
            # where we assign the kickstart source is relative to our current directory
 
242
            # and the input start directory in the crawl.  We find the path segments
 
243
            # between and tack them on the network source path to find the explicit
 
244
            # network path to the distro that Anaconda can digest.
 
245
            tail = utils.path_tail(self.path, base)
 
246
            tree = self.network_root[:-1] + tail
 
247
            self.set_install_tree(distro, tree)
 
248
 
 
249
        return
 
250
 
 
251
    def repo_finder(self, distros_added):
 
252
        for distro in distros_added:
 
253
            self.logger.info("traversing distro %s" % distro.name)
 
254
            # FIXME : Shouldn't decide this the value of self.network_root ?
 
255
            if distro.kernel.find("ks_mirror") != -1:
 
256
                basepath = os.path.dirname(distro.kernel)
 
257
                top = self.get_rootdir()
 
258
                self.logger.info("descent into %s" % top)
 
259
                dists_path = os.path.join(self.path, "dists")
 
260
                if not os.path.isdir(dists_path):
 
261
                    self.process_repos(self, distro)
 
262
            else:
 
263
                self.logger.info("this distro isn't mirrored")
 
264
 
 
265
    def get_repo_mirror_from_apt(self):
 
266
        """
 
267
        This tries to determine the apt mirror/archive to use (when processing repos)
 
268
        if the host machine is Debian or Ubuntu.
 
269
        """
 
270
        try:
 
271
            sources = sourceslist.SourcesList()
 
272
            release = distro.get_distro()
 
273
            release.get_sources(sources)
 
274
            mirrors = release.get_server_list()
 
275
            for mirror in mirrors:
 
276
                if mirror[2] == True:
 
277
                    mirror = mirror[1]
 
278
                    break
 
279
        except:
 
280
            return False
 
281
 
 
282
        return mirror
 
283
 
 
284
    def distro_adder(self,distros_added,dirname,fnames):
 
285
        """
 
286
        This is an os.path.walk routine that finds distributions in the directory
 
287
        to be scanned and then creates them.
 
288
        """
 
289
 
 
290
        # FIXME: If there are more than one kernel or initrd image on the same directory,
 
291
        # results are unpredictable
 
292
 
 
293
        initrd = None
 
294
        kernel = None
 
295
 
 
296
        for x in fnames:
 
297
            adtls = []
 
298
 
 
299
            fullname = os.path.join(dirname,x)
 
300
            if os.path.islink(fullname) and os.path.isdir(fullname):
 
301
                if fullname.startswith(self.path):
 
302
                    self.logger.warning("avoiding symlink loop")
 
303
                    continue
 
304
                self.logger.info("following symlink: %s" % fullname)
 
305
                os.path.walk(fullname, self.distro_adder, distros_added)
 
306
 
 
307
            if ( x.startswith("initrd.gz") or x.startswith("uInitrd") ) and x != "initrd.size":
 
308
                initrd = os.path.join(dirname,x)
 
309
            if ( x.startswith("linux") or x.startswith("uImage") ) and x.find("initrd") == -1:
 
310
                kernel = os.path.join(dirname,x)
 
311
 
 
312
            # if we've collected a matching kernel and initrd pair, turn the in and add them to the list
 
313
            if initrd is not None and kernel is not None:
 
314
                adtls.append(self.add_entry(dirname,kernel,initrd))
 
315
                kernel = None
 
316
                initrd = None
 
317
 
 
318
            for adtl in adtls:
 
319
                distros_added.extend(adtl)
 
320
 
 
321
    def add_entry(self,dirname,kernel,initrd):
 
322
        """
 
323
        When we find a directory with a valid kernel/initrd in it, create the distribution objects
 
324
        as appropriate and save them.  This includes creating xen and rescue distros/profiles
 
325
        if possible.
 
326
        """
 
327
 
 
328
        proposed_name = self.get_proposed_name(dirname,kernel)
 
329
        proposed_arch = self.get_proposed_arch(dirname)
 
330
 
 
331
        if self.arch and proposed_arch and self.arch != proposed_arch:
 
332
            self.logger.error("Arch from pathname (%s) does not match with supplied one (%s)"%(proposed_arch,self.arch))
 
333
            return
 
334
 
 
335
        archs = self.learn_arch_from_tree()
 
336
        if not archs:
 
337
            if self.arch:
 
338
                archs.append( self.arch )
 
339
        else:
 
340
            if self.arch and self.arch not in archs:
 
341
                utils.die(self.logger, "Given arch (%s) not found on imported tree %s"%(self.arch,self.get_pkgdir()))
 
342
        if proposed_arch:
 
343
            if archs and proposed_arch not in archs:
 
344
                self.logger.warning("arch from pathname (%s) not found on imported tree %s" % (proposed_arch,self.get_pkgdir()))
 
345
                return
 
346
 
 
347
            archs = [ proposed_arch ]
 
348
 
 
349
        if len(archs)>1:
 
350
            self.logger.warning("- Warning : Multiple archs found : %s" % (archs))
 
351
 
 
352
        distros_added = []
 
353
 
 
354
        for pxe_arch in archs:
 
355
            name = proposed_name + "-" + pxe_arch
 
356
            existing_distro = self.distros.find(name=name)
 
357
 
 
358
            if existing_distro is not None:
 
359
                self.logger.warning("skipping import, as distro name already exists: %s" % name)
 
360
                continue
 
361
 
 
362
            else:
 
363
                self.logger.info("creating new distro: %s" % name)
 
364
                distro = self.config.new_distro()
 
365
 
 
366
            if name.find("-autoboot") != -1:
 
367
                # this is an artifact of some EL-3 imports
 
368
                continue
 
369
 
 
370
            distro.set_name(name)
 
371
            distro.set_kernel(kernel)
 
372
            distro.set_initrd(initrd)
 
373
            distro.set_arch(pxe_arch)
 
374
            distro.set_breed(self.breed)
 
375
            # If a version was supplied on command line, we set it now
 
376
            if self.os_version:
 
377
                distro.set_os_version(self.os_version)
 
378
 
 
379
            self.distros.add(distro,save=True)
 
380
            distros_added.append(distro)
 
381
 
 
382
            existing_profile = self.profiles.find(name=name)
 
383
 
 
384
            # see if the profile name is already used, if so, skip it and
 
385
            # do not modify the existing profile
 
386
 
 
387
            if existing_profile is None:
 
388
                self.logger.info("creating new profile: %s" % name)
 
389
                #FIXME: The created profile holds a default kickstart, and should be breed specific
 
390
                profile = self.config.new_profile()
 
391
            else:
 
392
                self.logger.info("skipping existing profile, name already exists: %s" % name)
 
393
                continue
 
394
 
 
395
            # save our minimal profile which just points to the distribution and a good
 
396
            # default answer file
 
397
 
 
398
            profile.set_name(name)
 
399
            profile.set_distro(name)
 
400
            profile.set_kickstart(self.kickstart_file)
 
401
 
 
402
            # depending on the name of the profile we can define a good virt-type
 
403
            # for usage with koan
 
404
 
 
405
            if name.find("-xen") != -1:
 
406
                profile.set_virt_type("xenpv")
 
407
            elif name.find("vmware") != -1:
 
408
                profile.set_virt_type("vmware")
 
409
            else:
 
410
                profile.set_virt_type("qemu")
 
411
 
 
412
            # save our new profile to the collection
 
413
 
 
414
            self.profiles.add(profile,save=True)
 
415
 
 
416
        return distros_added
 
417
 
 
418
    def get_proposed_name(self,dirname,kernel=None):
 
419
        """
 
420
        Given a directory name where we have a kernel/initrd pair, try to autoname
 
421
        the distribution (and profile) object based on the contents of that path
 
422
        """
 
423
 
 
424
        if self.network_root is not None:
 
425
            name = self.name #+ "-".join(utils.path_tail(os.path.dirname(self.path),dirname).split("/"))
 
426
        else:
 
427
            # remove the part that says /var/www/cobbler/ks_mirror/name
 
428
            name = "-".join(dirname.split("/")[5:])
 
429
 
 
430
        if kernel is not None and kernel.find("PAE") != -1:
 
431
            name = name + "-PAE"
 
432
 
 
433
        # These are all Ubuntu's doing, the netboot images are buried pretty
 
434
        # deep. ;-) -JC
 
435
        name = name.replace("-netboot","")
 
436
        name = name.replace("-ubuntu-installer","")
 
437
        name = name.replace("-amd64","")
 
438
        name = name.replace("-i386","")
 
439
 
 
440
        # we know that some kernel paths should not be in the name
 
441
 
 
442
        name = name.replace("-images","")
 
443
        name = name.replace("-pxeboot","")
 
444
        name = name.replace("-install","")
 
445
        name = name.replace("-isolinux","")
 
446
 
 
447
        # some paths above the media root may have extra path segments we want
 
448
        # to clean up
 
449
 
 
450
        name = name.replace("-os","")
 
451
        name = name.replace("-tree","")
 
452
        name = name.replace("var-www-cobbler-", "")
 
453
        name = name.replace("ks_mirror-","")
 
454
        name = name.replace("--","-")
 
455
 
 
456
        # remove any architecture name related string, as real arch will be appended later
 
457
 
 
458
        name = name.replace("chrp","ppc64")
 
459
 
 
460
        for separator in [ '-' , '_'  , '.' ] :
 
461
            for arch in [ "i386" , "x86_64" , "ia64" , "ppc64", "ppc32", "ppc", "x86" , "s390x", "s390" , "386" , "amd", "arm" ]:
 
462
                name = name.replace("%s%s" % ( separator , arch ),"")
 
463
 
 
464
        return name
 
465
 
 
466
    def get_proposed_arch(self,dirname):
 
467
        """
 
468
        Given an directory name, can we infer an architecture from a path segment?
 
469
        """
 
470
        if dirname.find("x86_64") != -1 or dirname.find("amd") != -1:
 
471
            return "x86_64"
 
472
        if dirname.find("ia64") != -1:
 
473
            return "ia64"
 
474
        if dirname.find("i386") != -1 or dirname.find("386") != -1 or dirname.find("x86") != -1:
 
475
            return "i386"
 
476
        if dirname.find("s390x") != -1:
 
477
            return "s390x"
 
478
        if dirname.find("s390") != -1:
 
479
            return "s390"
 
480
        if dirname.find("ppc64") != -1 or dirname.find("chrp") != -1:
 
481
            return "ppc64"
 
482
        if dirname.find("ppc32") != -1:
 
483
            return "ppc"
 
484
        if dirname.find("ppc") != -1:
 
485
            return "ppc"
 
486
        return None
 
487
 
 
488
    def arch_walker(self,foo,dirname,fnames):
 
489
        """
 
490
        See docs on learn_arch_from_tree.
 
491
 
 
492
        The TRY_LIST is used to speed up search, and should be dropped for default importer
 
493
        Searched kernel names are kernel-header, linux-headers-, kernel-largesmp, kernel-hugemem
 
494
 
 
495
        This method is useful to get the archs, but also to package type and a raw guess of the breed
 
496
        """
 
497
 
 
498
        # try to find a kernel header RPM and then look at it's arch.
 
499
        for x in fnames:
 
500
            if self.match_kernelarch_file(x):
 
501
                for arch in self.get_valid_arches():
 
502
                    if x.find(arch) != -1:
 
503
                        foo[arch] = 1
 
504
                for arch in [ "i686" , "amd64" ]:
 
505
                    if x.find(arch) != -1:
 
506
                        foo[arch] = 1
 
507
 
 
508
    def kickstart_finder(self,distros_added):
 
509
        """
 
510
        For all of the profiles in the config w/o a kickstart, use the
 
511
        given kickstart file, or look at the kernel path, from that,
 
512
        see if we can guess the distro, and if we can, assign a kickstart
 
513
        if one is available for it.
 
514
        """
 
515
        for profile in self.profiles:
 
516
            distro = self.distros.find(name=profile.get_conceptual_parent().name)
 
517
            if distro is None or not (distro in distros_added):
 
518
                continue
 
519
 
 
520
            kdir = os.path.dirname(distro.kernel)
 
521
            if self.kickstart_file == None:
 
522
                for file in self.get_release_files():
 
523
                    results = self.scan_pkg_filename(file)
 
524
                    # FIXME : If os is not found on tree but set with CLI, no kickstart is searched
 
525
                    if results is None:
 
526
                        self.logger.warning("skipping %s" % file)
 
527
                        continue
 
528
                    (flavor, major, minor, release) = results
 
529
                    # Why use set_variance()? scan_pkg_filename() does everything we need now - jcammarata
 
530
                    #version , ks = self.set_variance(flavor, major, minor, distro.arch)
 
531
                    if self.os_version:
 
532
                        if self.os_version != flavor:
 
533
                            utils.die(self.logger,"CLI version differs from tree : %s vs. %s" % (self.os_version,flavor))
 
534
                    distro.set_comment("%s %s (%s.%s.%s) %s" % (self.breed,flavor,major,minor,release,self.arch))
 
535
                    distro.set_os_version(flavor)
 
536
                    # is this even valid for debian/ubuntu? - jcammarata
 
537
                    #ds = self.get_datestamp()
 
538
                    #if ds is not None:
 
539
                    #    distro.set_tree_build_time(ds)
 
540
                    profile.set_kickstart("/var/lib/cobbler/kickstarts/sample.seed")
 
541
                    self.profiles.add(profile,save=True)
 
542
 
 
543
            self.configure_tree_location(distro)
 
544
            self.distros.add(distro,save=True) # re-save
 
545
            self.api.serialize()
 
546
 
 
547
    def configure_tree_location(self, distro):
 
548
        """
 
549
        Once a distribution is identified, find the part of the distribution
 
550
        that has the URL in it that we want to use for kickstarting the
 
551
        distribution, and create a ksmeta variable $tree that contains this.
 
552
        """
 
553
 
 
554
        base = self.get_rootdir()
 
555
 
 
556
        if self.network_root is None:
 
557
            dists_path = os.path.join( self.path , "dists" )
 
558
            if os.path.isdir( dists_path ):
 
559
                tree = "http://@@http_server@@/cblr/ks_mirror/%s" % (self.name)
 
560
            else:
 
561
                tree = "http://@@http_server@@/cblr/repo_mirror/%s" % (distro.name)
 
562
            self.set_install_tree(distro, tree)
 
563
        else:
 
564
            # where we assign the kickstart source is relative to our current directory
 
565
            # and the input start directory in the crawl.  We find the path segments
 
566
            # between and tack them on the network source path to find the explicit
 
567
            # network path to the distro that Anaconda can digest.
 
568
            tail = utils.path_tail(self.path, base)
 
569
            tree = self.network_root[:-1] + tail
 
570
            self.set_install_tree(distro, tree)
 
571
 
 
572
    def get_rootdir(self):
 
573
        return self.path
 
574
 
 
575
    def get_pkgdir(self):
 
576
        if not self.pkgdir:
 
577
            return None
 
578
        return os.path.join(self.get_rootdir(),self.pkgdir)
 
579
 
 
580
    def set_install_tree(self, distro, url):
 
581
        distro.ks_meta["tree"] = url
 
582
 
 
583
    def learn_arch_from_tree(self):
 
584
        """
 
585
        If a distribution is imported from DVD, there is a good chance the path doesn't
 
586
        contain the arch and we should add it back in so that it's part of the
 
587
        meaningful name ... so this code helps figure out the arch name.  This is important
 
588
        for producing predictable distro names (and profile names) from differing import sources
 
589
        """
 
590
        result = {}
 
591
        # FIXME : this is called only once, should not be a walk
 
592
        if self.get_pkgdir():
 
593
            os.path.walk(self.get_pkgdir(), self.arch_walker, result)
 
594
        if result.pop("amd64",False):
 
595
            result["x86_64"] = 1
 
596
        if result.pop("i686",False):
 
597
            result["i386"] = 1
 
598
        if result.pop("x86",False):
 
599
            result["i386"] = 1
 
600
        return result.keys()
 
601
 
 
602
    def match_kernelarch_file(self, filename):
 
603
        """
 
604
        Is the given filename a kernel filename?
 
605
        """
 
606
        if not filename.endswith("deb"):
 
607
            return False
 
608
        if filename.startswith("linux-headers-"):
 
609
            return True
 
610
        return False
 
611
 
 
612
    def scan_pkg_filename(self, file):
 
613
        """
 
614
        Determine what the distro is based on the release package filename.
 
615
        """
 
616
        # FIXME: all of these dist_names should probably be put in a function
 
617
        # which would be called in place of looking in codes.py.  Right now
 
618
        # you have to update both codes.py and this to add a new release
 
619
        if self.breed == "debian":
 
620
            dist_names = ['etch','lenny',]
 
621
        elif self.breed == "ubuntu":
 
622
            dist_names = ['dapper','hardy','intrepid','jaunty','karmic','lynx','maverick','natty',]
 
623
        else:
 
624
            return None
 
625
 
 
626
        if os.path.basename(file) in dist_names:
 
627
            release_file = os.path.join(file,'Release')
 
628
            self.logger.info("Found %s release file: %s" % (self.breed,release_file))
 
629
 
 
630
            f = open(release_file,'r')
 
631
            lines = f.readlines()
 
632
            f.close()
 
633
 
 
634
            for line in lines:
 
635
                if line.lower().startswith('version: '):
 
636
                    version = line.split(':')[1].strip()
 
637
                    values = version.split('.')
 
638
                    if len(values) == 1:
 
639
                        # I don't think you'd ever hit this currently with debian or ubuntu,
 
640
                        # just including it for safety reasons
 
641
                        return (os.path.basename(file), values[0], "0", "0")
 
642
                    elif len(values) == 2:
 
643
                        return (os.path.basename(file), values[0], values[1], "0")
 
644
                    elif len(values) > 2:
 
645
                        return (os.path.basename(file), values[0], values[1], values[2])
 
646
        return None
 
647
 
 
648
    def get_datestamp(self):
 
649
        """
 
650
        Not used for debian/ubuntu... should probably be removed? - jcammarata
 
651
        """
 
652
        pass
 
653
 
 
654
    def set_variance(self, flavor, major, minor, arch):
 
655
        """
 
656
        Set distro specific versioning.
 
657
        """
 
658
        # I don't think this is required anymore, as the scan_pkg_filename() function
 
659
        # above does everything we need it to - jcammarata
 
660
        #
 
661
        #if self.breed == "debian":
 
662
        #    dist_names = { '4.0' : "etch" , '5.0' : "lenny" }
 
663
        #    dist_vers = "%s.%s" % ( major , minor )
 
664
        #    os_version = dist_names[dist_vers]
 
665
        #
 
666
        #    return os_version , "/var/lib/cobbler/kickstarts/sample.seed"
 
667
        #elif self.breed == "ubuntu":
 
668
        #    # Release names taken from wikipedia
 
669
        #    dist_names = { '6.4'  :"dapper", 
 
670
        #                   '8.4'  :"hardy", 
 
671
        #                   '8.10' :"intrepid", 
 
672
        #                   '9.4'  :"jaunty",
 
673
        #                   '9.10' :"karmic",
 
674
        #                   '10.4' :"lynx",
 
675
        #                   '10.10':"maverick",
 
676
        #                   '11.4' :"natty",
 
677
        #                 }
 
678
        #    dist_vers = "%s.%s" % ( major , minor )
 
679
        #    if not dist_names.has_key( dist_vers ):
 
680
        #        dist_names['4ubuntu2.0'] = "IntrepidIbex"
 
681
        #    os_version = dist_names[dist_vers]
 
682
        # 
 
683
        #    return os_version , "/var/lib/cobbler/kickstarts/sample.seed"
 
684
        #else:
 
685
        #    return None
 
686
        pass
 
687
 
 
688
    def process_repos(self, main_importer, distro):
 
689
        # Create a disabled repository for the new distro, and the security updates
 
690
        #
 
691
        # NOTE : We cannot use ks_meta nor os_version because they get fixed at a later stage
 
692
 
 
693
        # Obtain repo mirror from APT if available
 
694
        mirror = False
 
695
        if apt_available:
 
696
            # Example returned URL: http://us.archive.ubuntu.com/ubuntu
 
697
            mirror = self.get_repo_mirror_from_apt()
 
698
            if mirror:
 
699
                mirror = mirror + "/dists"
 
700
        if not mirror:
 
701
            mirror = "http://archive.ubuntu.com/ubuntu/dists/"
 
702
 
 
703
        repo = item_repo.Repo(main_importer.config)
 
704
        repo.set_breed( "apt" )
 
705
        repo.set_arch( distro.arch )
 
706
        repo.set_keep_updated( False )
 
707
        repo.yumopts["--ignore-release-gpg"] = None
 
708
        repo.yumopts["--verbose"] = None
 
709
        repo.set_name( distro.name )
 
710
        repo.set_os_version( distro.os_version )
 
711
 
 
712
        if distro.breed == "ubuntu":
 
713
            repo.set_mirror( "%s/%s" % (mirror, distro.os_version) )
 
714
        else:
 
715
            # NOTE : The location of the mirror should come from timezone
 
716
            repo.set_mirror( "http://ftp.%s.debian.org/debian/dists/%s" % ( 'us' , distro.os_version ) )
 
717
 
 
718
        security_repo = item_repo.Repo(main_importer.config)
 
719
        security_repo.set_breed( "apt" )
 
720
        security_repo.set_arch( distro.arch )
 
721
        security_repo.set_keep_updated( False )
 
722
        security_repo.yumopts["--ignore-release-gpg"] = None
 
723
        security_repo.yumopts["--verbose"] = None
 
724
        security_repo.set_name( distro.name + "-security" )
 
725
        security_repo.set_os_version( distro.os_version )
 
726
        # There are no official mirrors for security updates
 
727
        if distro.breed == "ubuntu":
 
728
            security_repo.set_mirror( "%s/%s-security" % (mirror, distro.os_version) )
 
729
        else:
 
730
            security_repo.set_mirror( "http://security.debian.org/debian-security/dists/%s/updates" % distro.os_version )
 
731
 
 
732
        self.logger.info("Added repos for %s" % distro.name)
 
733
        repos  = main_importer.config.repos()
 
734
        repos.add(repo,save=True)
 
735
        repos.add(security_repo,save=True)
 
736
 
 
737
# ==========================================================================
 
738
 
 
739
def get_import_manager(config,logger):
 
740
    return ImportDebianUbuntuManager(config,logger)