2
This is some of the code behind 'cobbler sync'.
4
Copyright 2006-2009, Red Hat, Inc
5
Michael DeHaan <mdehaan@redhat.com>
6
John Eckersberg <jeckersb@redhat.com>
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.
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.
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
33
from utils import popen2
34
from shlex import shlex
38
from cexceptions import *
48
# Import aptsources module if available to obtain repo mirror.
50
from aptsources import distro
51
from aptsources import sourceslist
58
The mandatory cobbler module registration hook.
60
return "manage/import"
63
class ImportDebianUbuntuManager:
65
def __init__(self,config,logger):
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)
79
# required function for import modules
81
return "import/debian_ubuntu"
83
# required function for import modules
84
def check_for_signature(self,path,cli_breed):
89
#self.logger.info("scanning %s for a debian/ubuntu distro signature" % path)
90
for signature in signatures:
91
d = os.path.join(path,signature)
93
self.logger.info("Found a debian/ubuntu compatible signature: %s" % signature)
94
return (True,signature)
96
if cli_breed and cli_breed in self.get_valid_breeds():
97
self.logger.info("Warning: No distro signature for kernel at %s, using value from command line" % path)
102
# required function for import modules
103
def run(self,pkgdir,mirror,mirror_name,network_root=None,kickstart_file=None,rsync_flags=None,arch=None,breed=None,os_version=None):
106
self.mirror_name = mirror_name
107
self.network_root = network_root
108
self.kickstart_file = kickstart_file
109
self.rsync_flags = rsync_flags
112
self.os_version = os_version
114
# some fixups for the XMLRPC interface, which does not use "None"
115
if self.arch == "": self.arch = None
116
if self.mirror == "": self.mirror = None
117
if self.mirror_name == "": self.mirror_name = None
118
if self.kickstart_file == "": self.kickstart_file = None
119
if self.os_version == "": self.os_version = None
120
if self.rsync_flags == "": self.rsync_flags = None
121
if self.network_root == "": self.network_root = None
123
# If no breed was specified on the command line, figure it out
124
if self.breed == None:
125
self.breed = self.get_breed_from_directory()
127
utils.die(self.logger,"import failed - could not determine breed of debian-based distro")
129
# debug log stuff for testing
130
#self.logger.info("DEBUG: self.pkgdir = %s" % str(self.pkgdir))
131
#self.logger.info("DEBUG: self.mirror = %s" % str(self.mirror))
132
#self.logger.info("DEBUG: self.mirror_name = %s" % str(self.mirror_name))
133
#self.logger.info("DEBUG: self.network_root = %s" % str(self.network_root))
134
#self.logger.info("DEBUG: self.kickstart_file = %s" % str(self.kickstart_file))
135
#self.logger.info("DEBUG: self.rsync_flags = %s" % str(self.rsync_flags))
136
#self.logger.info("DEBUG: self.arch = %s" % str(self.arch))
137
#self.logger.info("DEBUG: self.breed = %s" % str(self.breed))
138
#self.logger.info("DEBUG: self.os_version = %s" % str(self.os_version))
140
# both --import and --name are required arguments
142
if self.mirror is None:
143
utils.die(self.logger,"import failed. no --path specified")
144
if self.mirror_name is None:
145
utils.die(self.logger,"import failed. no --name specified")
147
# if --arch is supplied, validate it to ensure it's valid
149
if self.arch is not None and self.arch != "":
150
self.arch = self.arch.lower()
151
if self.arch == "x86":
154
if self.arch not in self.get_valid_arches():
155
utils.die(self.logger,"arch must be one of: %s" % string.join(self.get_valid_arches(),", "))
157
# if we're going to do any copying, set where to put things
158
# and then make sure nothing is already there.
160
self.path = os.path.normpath( "%s/ks_mirror/%s" % (self.settings.webdir, self.mirror_name) )
161
if os.path.exists(self.path) and self.arch is None:
162
# FIXME : Raise exception even when network_root is given ?
163
utils.die(self.logger,"Something already exists at this import location (%s). You must specify --arch to avoid potentially overwriting existing files." % self.path)
165
# import takes a --kickstart for forcing selection that can't be used in all circumstances
167
if self.kickstart_file and not self.breed:
168
utils.die(self.logger,"Kickstart file can only be specified when a specific breed is selected")
170
if self.os_version and not self.breed:
171
utils.die(self.logger,"OS version can only be specified when a specific breed is selected")
173
if self.breed and self.breed.lower() not in self.get_valid_breeds():
174
utils.die(self.logger,"Supplied import breed is not supported by this module")
176
# if --arch is supplied, make sure the user is not importing a path with a different
177
# arch, which would just be silly.
180
# append the arch path to the name if the arch is not already
182
for x in self.get_valid_arches():
183
if self.path.lower().find(x) != -1:
185
utils.die(self.logger,"Architecture found on pathname (%s) does not fit the one given in command line (%s)"%(x,self.arch))
188
# FIXME : This is very likely removed later at get_proposed_name, and the guessed arch appended again
189
self.path += ("-%s" % self.arch)
190
# If arch is specified we also need to update the mirror name.
191
self.mirror_name = self.mirror_name + "-" + self.arch
193
# make the output path and mirror content but only if not specifying that a network
194
# accessible support location already exists (this is --available-as on the command line)
196
if self.network_root is None:
197
# we need to mirror (copy) the files
199
utils.mkdir(self.path)
201
if self.mirror.startswith("http://") or self.mirror.startswith("ftp://") or self.mirror.startswith("nfs://"):
203
# http mirrors are kind of primative. rsync is better.
204
# that's why this isn't documented in the manpage and we don't support them.
205
# TODO: how about adding recursive FTP as an option?
207
utils.die(self.logger,"unsupported protocol")
211
# good, we're going to use rsync..
212
# we don't use SSH for public mirrors and local files.
213
# presence of user@host syntax means use SSH
215
# kick off the rsync now
217
if not utils.rsync_files(self.mirror, self.path, self.rsync_flags, self.logger):
218
utils.die(self.logger, "failed to rsync the files")
222
# rather than mirroring, we're going to assume the path is available
223
# over http, ftp, and nfs, perhaps on an external filer. scanning still requires
224
# --mirror is a filesystem path, but --available-as marks the network path
226
if not os.path.exists(self.mirror):
227
utils.die(self.logger, "path does not exist: %s" % self.mirror)
229
# find the filesystem part of the path, after the server bits, as each distro
230
# URL needs to be calculated relative to this.
232
if not self.network_root.endswith("/"):
233
self.network_root = self.network_root + "/"
234
self.path = os.path.normpath( self.mirror )
235
valid_roots = [ "nfs://", "ftp://", "http://" ]
236
for valid_root in valid_roots:
237
if self.network_root.startswith(valid_root):
240
utils.die(self.logger, "Network root given to --available-as must be nfs://, ftp://, or http://")
241
if self.network_root.startswith("nfs://"):
243
(a,b,rest) = self.network_root.split(":",3)
245
utils.die(self.logger, "Network root given to --available-as is missing a colon, please see the manpage example.")
247
# now walk the filesystem looking for distributions that match certain patterns
249
self.logger.info("adding distros")
251
# FIXME : search below self.path for isolinux configurations or known directories from TRY_LIST
252
os.path.walk(self.path, self.distro_adder, distros_added)
254
# find out if we can auto-create any repository records from the install tree
256
if self.network_root is None:
257
self.logger.info("associating repos")
258
# FIXME: this automagic is not possible (yet) without mirroring
259
self.repo_finder(distros_added)
261
# find the most appropriate answer files for each profile object
263
self.logger.info("associating kickstarts")
264
self.kickstart_finder(distros_added)
266
# ensure bootloaders are present
267
self.api.pxegen.copy_bootloaders()
271
# required function for import modules
272
def get_valid_arches(self):
273
return ["i386", "ppc", "x86_64", "x86",]
275
# required function for import modules
276
def get_valid_breeds(self):
277
return ["debian","ubuntu"]
279
# required function for import modules
280
def get_valid_os_versions(self):
281
if self.breed == "debian":
282
return ["etch", "lenny", "squeeze", "sid", "stable", "testing", "unstable", "experimental",]
283
elif self.breed == "ubuntu":
284
return ["dapper", "hardy", "karmic", "lucid", "maverick", "natty",]
288
def get_valid_repo_breeds(self):
291
def get_release_files(self):
293
Find distro release packages.
295
return glob.glob(os.path.join(self.get_rootdir(), "dists/*"))
297
def get_breed_from_directory(self):
298
for breed in self.get_valid_breeds():
299
# NOTE : Although we break the loop after the first match,
300
# multiple debian derived distros can actually live at the same pool -- JP
301
d = os.path.join(self.mirror, breed)
302
if (os.path.islink(d) and os.path.isdir(d) and os.path.realpath(d) == os.path.realpath(self.mirror)) or os.path.basename(self.mirror) == breed:
307
def get_tree_location(self, distro):
309
Once a distribution is identified, find the part of the distribution
310
that has the URL in it that we want to use for kickstarting the
311
distribution, and create a ksmeta variable $tree that contains this.
314
base = self.get_rootdir()
316
if self.network_root is None:
317
dists_path = os.path.join(self.path, "dists")
318
if os.path.isdir(dists_path):
319
tree = "http://@@http_server@@/cblr/ks_mirror/%s" % (self.mirror_name)
321
tree = "http://@@http_server@@/cblr/repo_mirror/%s" % (distro.name)
322
self.set_install_tree(distro, tree)
324
# where we assign the kickstart source is relative to our current directory
325
# and the input start directory in the crawl. We find the path segments
326
# between and tack them on the network source path to find the explicit
327
# network path to the distro that Anaconda can digest.
328
tail = self.path_tail(self.path, base)
329
tree = self.network_root[:-1] + tail
330
self.set_install_tree(distro, tree)
334
def repo_finder(self, distros_added):
335
for distro in distros_added:
336
self.logger.info("traversing distro %s" % distro.name)
337
# FIXME : Shouldn't decide this the value of self.network_root ?
338
if distro.kernel.find("ks_mirror") != -1:
339
basepath = os.path.dirname(distro.kernel)
340
top = self.get_rootdir()
341
self.logger.info("descent into %s" % top)
342
dists_path = os.path.join(self.path, "dists")
343
if not os.path.isdir(dists_path):
344
self.process_repos(self, distro)
346
self.logger.info("this distro isn't mirrored")
348
def get_repo_mirror_from_apt(self):
350
This tries to determine the apt mirror/archive to use (when processing repos)
351
if the host machine is Debian or Ubuntu.
354
sources = sourceslist.SourcesList()
355
release = distro.get_distro()
356
release.get_sources(sources)
357
mirrors = release.get_server_list()
358
for mirror in mirrors:
359
if mirror[2] == True:
367
def distro_adder(self,distros_added,dirname,fnames):
369
This is an os.path.walk routine that finds distributions in the directory
370
to be scanned and then creates them.
373
# FIXME: If there are more than one kernel or initrd image on the same directory,
374
# results are unpredictable
382
fullname = os.path.join(dirname,x)
383
if os.path.islink(fullname) and os.path.isdir(fullname):
384
if fullname.startswith(self.path):
385
self.logger.warning("avoiding symlink loop")
387
self.logger.info("following symlink: %s" % fullname)
388
os.path.walk(fullname, self.distro_adder, distros_added)
390
if ( x.startswith("initrd.gz") ) and x != "initrd.size":
391
initrd = os.path.join(dirname,x)
392
if ( x.startswith("linux") ) and x.find("initrd") == -1:
393
kernel = os.path.join(dirname,x)
395
# if we've collected a matching kernel and initrd pair, turn the in and add them to the list
396
if initrd is not None and kernel is not None:
397
adtls.append(self.add_entry(dirname,kernel,initrd))
402
distros_added.extend(adtl)
404
def add_entry(self,dirname,kernel,initrd):
406
When we find a directory with a valid kernel/initrd in it, create the distribution objects
407
as appropriate and save them. This includes creating xen and rescue distros/profiles
411
proposed_name = self.get_proposed_name(dirname,kernel)
412
proposed_arch = self.get_proposed_arch(dirname)
414
if self.arch and proposed_arch and self.arch != proposed_arch:
415
utils.die(self.logger,"Arch from pathname (%s) does not match with supplied one %s"%(proposed_arch,self.arch))
417
archs = self.learn_arch_from_tree()
420
archs.append( self.arch )
422
if self.arch and self.arch not in archs:
423
utils.die(self.logger, "Given arch (%s) not found on imported tree %s"%(self.arch,self.get_pkgdir()))
425
if archs and proposed_arch not in archs:
426
self.logger.warning("arch from pathname (%s) not found on imported tree %s" % (proposed_arch,self.get_pkgdir()))
429
archs = [ proposed_arch ]
432
self.logger.warning("- Warning : Multiple archs found : %s" % (archs))
436
for pxe_arch in archs:
437
name = proposed_name + "-" + pxe_arch
438
existing_distro = self.distros.find(name=name)
440
if existing_distro is not None:
441
self.logger.warning("skipping import, as distro name already exists: %s" % name)
445
self.logger.info("creating new distro: %s" % name)
446
distro = self.config.new_distro()
448
if name.find("-autoboot") != -1:
449
# this is an artifact of some EL-3 imports
452
distro.set_name(name)
453
distro.set_kernel(kernel)
454
distro.set_initrd(initrd)
455
distro.set_arch(pxe_arch)
456
distro.set_breed(self.breed)
457
# If a version was supplied on command line, we set it now
459
distro.set_os_version(self.os_version)
461
self.distros.add(distro,save=True)
462
distros_added.append(distro)
464
existing_profile = self.profiles.find(name=name)
466
# see if the profile name is already used, if so, skip it and
467
# do not modify the existing profile
469
if existing_profile is None:
470
self.logger.info("creating new profile: %s" % name)
471
#FIXME: The created profile holds a default kickstart, and should be breed specific
472
profile = self.config.new_profile()
474
self.logger.info("skipping existing profile, name already exists: %s" % name)
477
# save our minimal profile which just points to the distribution and a good
478
# default answer file
480
profile.set_name(name)
481
profile.set_distro(name)
482
profile.set_kickstart(self.kickstart_file)
484
# depending on the name of the profile we can define a good virt-type
485
# for usage with koan
487
if name.find("-xen") != -1:
488
profile.set_virt_type("xenpv")
489
elif name.find("vmware") != -1:
490
profile.set_virt_type("vmware")
492
profile.set_virt_type("qemu")
494
# save our new profile to the collection
496
self.profiles.add(profile,save=True)
500
def get_proposed_name(self,dirname,kernel=None):
502
Given a directory name where we have a kernel/initrd pair, try to autoname
503
the distribution (and profile) object based on the contents of that path
506
if self.network_root is not None:
507
name = self.mirror_name + "-".join(self.path_tail(os.path.dirname(self.path),dirname).split("/"))
509
# remove the part that says /var/www/cobbler/ks_mirror/name
510
name = "-".join(dirname.split("/")[5:])
512
if kernel is not None and kernel.find("PAE") != -1:
515
# These are all Ubuntu's doing, the netboot images are buried pretty
517
name = name.replace("-netboot","")
518
name = name.replace("-ubuntu-installer","")
519
name = name.replace("-amd64","")
520
name = name.replace("-i386","")
522
# we know that some kernel paths should not be in the name
524
name = name.replace("-images","")
525
name = name.replace("-pxeboot","")
526
name = name.replace("-install","")
527
name = name.replace("-isolinux","")
529
# some paths above the media root may have extra path segments we want
532
name = name.replace("-os","")
533
name = name.replace("-tree","")
534
name = name.replace("var-www-cobbler-", "")
535
name = name.replace("ks_mirror-","")
536
name = name.replace("--","-")
538
# remove any architecture name related string, as real arch will be appended later
540
name = name.replace("chrp","ppc64")
542
for separator in [ '-' , '_' , '.' ] :
543
for arch in [ "i386" , "x86_64" , "ia64" , "ppc64", "ppc32", "ppc", "x86" , "s390x", "s390" , "386" , "amd" ]:
544
name = name.replace("%s%s" % ( separator , arch ),"")
548
def get_proposed_arch(self,dirname):
550
Given an directory name, can we infer an architecture from a path segment?
552
if dirname.find("x86_64") != -1 or dirname.find("amd") != -1:
554
if dirname.find("ia64") != -1:
556
if dirname.find("i386") != -1 or dirname.find("386") != -1 or dirname.find("x86") != -1:
558
if dirname.find("s390x") != -1:
560
if dirname.find("s390") != -1:
562
if dirname.find("ppc64") != -1 or dirname.find("chrp") != -1:
564
if dirname.find("ppc32") != -1:
566
if dirname.find("ppc") != -1:
570
def arch_walker(self,foo,dirname,fnames):
572
See docs on learn_arch_from_tree.
574
The TRY_LIST is used to speed up search, and should be dropped for default importer
575
Searched kernel names are kernel-header, linux-headers-, kernel-largesmp, kernel-hugemem
577
This method is useful to get the archs, but also to package type and a raw guess of the breed
580
# try to find a kernel header RPM and then look at it's arch.
582
if self.match_kernelarch_file(x):
583
for arch in self.get_valid_arches():
584
if x.find(arch) != -1:
586
for arch in [ "i686" , "amd64" ]:
587
if x.find(arch) != -1:
590
def kickstart_finder(self,distros_added):
592
For all of the profiles in the config w/o a kickstart, use the
593
given kickstart file, or look at the kernel path, from that,
594
see if we can guess the distro, and if we can, assign a kickstart
595
if one is available for it.
597
for profile in self.profiles:
598
distro = self.distros.find(name=profile.get_conceptual_parent().name)
599
if distro is None or not (distro in distros_added):
602
kdir = os.path.dirname(distro.kernel)
603
if self.kickstart_file == None:
604
for file in self.get_release_files():
605
results = self.scan_pkg_filename(file)
606
# FIXME : If os is not found on tree but set with CLI, no kickstart is searched
608
self.logger.warning("skipping %s" % file)
610
(flavor, major, minor, release) = results
611
# Why use set_variance()? scan_pkg_filename() does everything we need now - jcammarata
612
#version , ks = self.set_variance(flavor, major, minor, distro.arch)
614
if self.os_version != flavor:
615
utils.die(self.logger,"CLI version differs from tree : %s vs. %s" % (self.os_version,flavor))
616
distro.set_comment("%s %s (%s.%s.%s) %s" % (self.breed,flavor,major,minor,release,self.arch))
617
distro.set_os_version(flavor)
618
# is this even valid for debian/ubuntu? - jcammarata
619
#ds = self.get_datestamp()
621
# distro.set_tree_build_time(ds)
622
profile.set_kickstart("/var/lib/cobbler/kickstarts/sample.seed")
623
self.profiles.add(profile,save=True)
625
self.configure_tree_location(distro)
626
self.distros.add(distro,save=True) # re-save
629
def configure_tree_location(self, distro):
631
Once a distribution is identified, find the part of the distribution
632
that has the URL in it that we want to use for kickstarting the
633
distribution, and create a ksmeta variable $tree that contains this.
636
base = self.get_rootdir()
638
if self.network_root is None:
639
dists_path = os.path.join( self.path , "dists" )
640
if os.path.isdir( dists_path ):
641
tree = "http://@@http_server@@/cblr/ks_mirror/%s" % (self.mirror_name)
643
tree = "http://@@http_server@@/cblr/repo_mirror/%s" % (distro.name)
644
self.set_install_tree(distro, tree)
646
# where we assign the kickstart source is relative to our current directory
647
# and the input start directory in the crawl. We find the path segments
648
# between and tack them on the network source path to find the explicit
649
# network path to the distro that Anaconda can digest.
650
tail = utils.path_tail(self.path, base)
651
tree = self.network_root[:-1] + tail
652
self.set_install_tree(distro, tree)
654
def get_rootdir(self):
657
def get_pkgdir(self):
660
return os.path.join(self.get_rootdir(),self.pkgdir)
662
def set_install_tree(self, distro, url):
663
distro.ks_meta["tree"] = url
665
def learn_arch_from_tree(self):
667
If a distribution is imported from DVD, there is a good chance the path doesn't
668
contain the arch and we should add it back in so that it's part of the
669
meaningful name ... so this code helps figure out the arch name. This is important
670
for producing predictable distro names (and profile names) from differing import sources
673
# FIXME : this is called only once, should not be a walk
674
if self.get_pkgdir():
675
os.path.walk(self.get_pkgdir(), self.arch_walker, result)
676
if result.pop("amd64",False):
678
if result.pop("i686",False):
682
def match_kernelarch_file(self, filename):
684
Is the given filename a kernel filename?
686
if not filename.endswith("deb"):
688
if filename.startswith("linux-headers-"):
692
def scan_pkg_filename(self, file):
694
Determine what the distro is based on the release package filename.
696
# FIXME: all of these dist_names should probably be put in a function
697
# which would be called in place of looking in codes.py. Right now
698
# you have to update both codes.py and this to add a new release
699
if self.breed == "debian":
700
dist_names = ['etch','lenny',]
701
elif self.breed == "ubuntu":
702
dist_names = ['dapper','hardy','intrepid','jaunty','karmic','lynx','maverick','natty',]
706
if os.path.basename(file) in dist_names:
707
release_file = os.path.join(file,'Release')
708
self.logger.info("Found %s release file: %s" % (self.breed,release_file))
710
f = open(release_file,'r')
711
lines = f.readlines()
715
if line.lower().startswith('version: '):
716
version = line.split(':')[1].strip()
717
values = version.split('.')
719
# I don't think you'd ever hit this currently with debian or ubuntu,
720
# just including it for safety reasons
721
return (os.path.basename(file), values[0], "0", "0")
722
elif len(values) == 2:
723
return (os.path.basename(file), values[0], values[1], "0")
724
elif len(values) > 2:
725
return (os.path.basename(file), values[0], values[1], values[2])
728
def get_datestamp(self):
730
Not used for debian/ubuntu... should probably be removed? - jcammarata
734
def set_variance(self, flavor, major, minor, arch):
736
Set distro specific versioning.
738
# I don't think this is required anymore, as the scan_pkg_filename() function
739
# above does everything we need it to - jcammarata
741
#if self.breed == "debian":
742
# dist_names = { '4.0' : "etch" , '5.0' : "lenny" }
743
# dist_vers = "%s.%s" % ( major , minor )
744
# os_version = dist_names[dist_vers]
746
# return os_version , "/var/lib/cobbler/kickstarts/sample.seed"
747
#elif self.breed == "ubuntu":
748
# # Release names taken from wikipedia
749
# dist_names = { '6.4' :"dapper",
751
# '8.10' :"intrepid",
755
# '10.10':"maverick",
758
# dist_vers = "%s.%s" % ( major , minor )
759
# if not dist_names.has_key( dist_vers ):
760
# dist_names['4ubuntu2.0'] = "IntrepidIbex"
761
# os_version = dist_names[dist_vers]
763
# return os_version , "/var/lib/cobbler/kickstarts/sample.seed"
768
def process_repos(self, main_importer, distro):
769
# Create a disabled repository for the new distro, and the security updates
771
# NOTE : We cannot use ks_meta nor os_version because they get fixed at a later stage
773
# Obtain repo mirror from APT if available
776
# Example returned URL: http://us.archive.ubuntu.com/ubuntu
777
mirror = self.get_repo_mirror_from_apt()
779
mirror = mirror + "/dists"
781
mirror = "http://archive.ubuntu.com/ubuntu/dists/"
783
repo = item_repo.Repo(main_importer.config)
784
repo.set_breed( "apt" )
785
repo.set_arch( distro.arch )
786
repo.set_keep_updated( False )
787
repo.yumopts["--ignore-release-gpg"] = None
788
repo.yumopts["--verbose"] = None
789
repo.set_name( distro.name )
790
repo.set_os_version( distro.os_version )
792
if distro.breed == "ubuntu":
793
repo.set_mirror( "%s/%s" % (mirror, distro.os_version) )
795
# NOTE : The location of the mirror should come from timezone
796
repo.set_mirror( "http://ftp.%s.debian.org/debian/dists/%s" % ( 'us' , distro.os_version ) )
798
security_repo = item_repo.Repo(main_importer.config)
799
security_repo.set_breed( "apt" )
800
security_repo.set_arch( distro.arch )
801
security_repo.set_keep_updated( False )
802
security_repo.yumopts["--ignore-release-gpg"] = None
803
security_repo.yumopts["--verbose"] = None
804
security_repo.set_name( distro.name + "-security" )
805
security_repo.set_os_version( distro.os_version )
806
# There are no official mirrors for security updates
807
if distro.breed == "ubuntu":
808
security_repo.set_mirror( "%s/%s-security" % (mirror, distro.os_version) )
810
security_repo.set_mirror( "http://security.debian.org/debian-security/dists/%s/updates" % distro.os_version )
812
self.logger.info("Added repos for %s" % distro.name)
813
repos = main_importer.config.repos()
814
repos.add(repo,save=True)
815
repos.add(security_repo,save=True)
817
# ==========================================================================
819
def get_import_manager(config,logger):
820
return ImportDebianUbuntuManager(config,logger)