'Create bootable CD image to be used for handsoff CD installtions'

def generate_standalone_iso(self, imagesdir, isolinuxdir, distname, filesource, airgapped, profiles):

    distro = self.api.find_distro(distname)
    if (distro is None):
        utils.die(self.logger, ('distro    %s    was    not    found,    aborting' % distname))
    descendants = distro.get_descendants(sort=True)
    profiles = utils.input_string_or_list(profiles)
    if (filesource is None):
        self.logger.debug('trying    to    locate    source    for    distro')
        found_source = False
        (source_head, source_tail) = os.path.split(distro.kernel)
        while (source_tail != ''):
            if (source_head == os.path.join(self.api.settings().webdir, 'distro_mirror')):
                filesource = os.path.join(source_head, source_tail)
                found_source = True
                self.logger.debug(('found    source    in    %s' % filesource))
                break
            (source_head, source_tail) = os.path.split(source_head)
        if (not found_source):
            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')
    self.logger.info('copying    kernels    and    initrds    for    standalone    distro')
    self.copy_boot_files(distro, isolinuxdir, None)
    self.logger.info('generating    an    isolinux.cfg')
    isolinuxcfg = os.path.join(isolinuxdir, 'isolinux.cfg')
    cfg = open(isolinuxcfg, 'w+')
    cfg.write(self.iso_template)
    if airgapped:
        repo_names_to_copy = {}
    for descendant in descendants:
        if (profiles and (((descendant.COLLECTION_TYPE == 'profile') and (descendant.name not in profiles)) or ((descendant.COLLECTION_TYPE == 'system') and (descendant.profile not in profiles)))):
            continue
        menu_indent = 0
        if (descendant.COLLECTION_TYPE == 'system'):
            menu_indent = 4
        data = utils.blender(self.api, False, descendant)
        cfg.write('\n')
        cfg.write(('LABEL    %s\n' % descendant.name))
        if menu_indent:
            cfg.write(('        MENU    INDENT    %d\n' % menu_indent))
        cfg.write(('        MENU    LABEL    %s\n' % descendant.name))
        cfg.write(('        kernel    %s\n' % os.path.basename(distro.kernel)))
        append_line = ('        append    initrd=%s' % os.path.basename(distro.initrd))
        if (distro.breed == 'redhat'):
            append_line += ('    ks=cdrom:/isolinux/%s.cfg' % descendant.name)
        if (distro.breed == 'suse'):
            append_line += ('    autoyast=file:///isolinux/%s.cfg    install=cdrom:///' % descendant.name)
            if ('install' in data['kernel_options']):
                del data['kernel_options']['install']
        if (distro.breed in ['ubuntu', 'debian']):
            append_line += ('    auto-install/enable=true    preseed/file=/cdrom/isolinux/%s.cfg' % descendant.name)
        append_line += self.add_remaining_kopts(data['kernel_options'])
        cfg.write(append_line)
        if (descendant.COLLECTION_TYPE == 'profile'):
            autoinstall_data = self.api.autoinstallgen.generate_autoinstall_for_profile(descendant.name)
        elif (descendant.COLLECTION_TYPE == 'system'):
            autoinstall_data = self.api.autoinstallgen.generate_autoinstall_for_system(descendant.name)
        if (distro.breed == 'redhat'):
            cdregex = re.compile('^\\s*url    .*\n', (re.IGNORECASE | re.MULTILINE))
            autoinstall_data = cdregex.sub('cdrom\n', autoinstall_data, count=1)
        if airgapped:
            descendant_repos = data['repos']
            for repo_name in descendant_repos:
                repo_obj = self.api.find_repo(repo_name)
                error_fmt = (((((descendant.COLLECTION_TYPE + '    ') + descendant.name) + '    refers    to    repo    ') + repo_name) + ',    which    %%s;    cannot    build    airgapped    ISO')
                if (repo_obj is None):
                    utils.die(self.logger, (error_fmt % 'does    not    exist'))
                if (not repo_obj.mirror_locally):
                    utils.die(self.logger, (error_fmt % 'is    not    configured    for    local    mirroring'))
                mirrordir = os.path.join(self.settings.webdir, 'repo_mirror', repo_obj.name)
                if (not os.path.exists(mirrordir)):
                    utils.die(self.logger, (error_fmt % 'has    a    missing    local    mirror    directory'))
                repo_names_to_copy[repo_obj.name] = mirrordir
                reporegex = re.compile((('^(\\s*repo    --name=' + repo_obj.name) + '    --baseurl=).*'), re.MULTILINE)
                autoinstall_data = reporegex.sub((('\\1' + 'file:///mnt/source/repo_mirror/') + repo_obj.name), autoinstall_data)
            srcreporegex = re.compile((('^(\\s*repo    --name=\\S+    --baseurl=).*/cobbler/ks_mirror/' + distro.name) + '/?(.*)'), re.MULTILINE)
            autoinstall_data = srcreporegex.sub((('\\1' + 'file:///mnt/source') + '\\2'), autoinstall_data)
        autoinstall_name = os.path.join(isolinuxdir, ('%s.cfg' % descendant.name))
        autoinstall_file = open(autoinstall_name, 'w+')
        autoinstall_file.write(autoinstall_data)
        autoinstall_file.close()
    self.logger.info('done    writing    config')
    cfg.write('\n')
    cfg.write('MENU    END\n')
    cfg.close()
    if airgapped:
        repodir = os.path.abspath(os.path.join(isolinuxdir, '..', 'repo_mirror'))
        if (not os.path.exists(repodir)):
            os.makedirs(repodir)
        for repo_name in repo_names_to_copy:
            src = repo_names_to_copy[repo_name]
            dst = os.path.join(repodir, repo_name)
            self.logger.info((("    -    copying    repo    '" + repo_name) + "'    for    airgapped    ISO"))
            ok = utils.rsync_files(src, dst, '--exclude=TRANS.TBL    --exclude=cache/    --no-g', logger=self.logger, quiet=True)
            if (not ok):
                utils.die(self.logger, (("rsync    of    repo    '" + repo_name) + "'    failed"))
    cmd = ('rsync    -rlptgu    --exclude=boot.cat    --exclude=TRANS.TBL    --exclude=isolinux/    %s/    %s/../' % (filesource, isolinuxdir))
    self.logger.info(('-    copying    distro    %s    files    (%s)' % (distname, cmd)))
    rc = utils.subprocess_call(self.logger, cmd, shell=True)
    if rc:
        utils.die(self.logger, 'rsync    of    distro    files    failed')
