def main()

in legacy/autodmg_cache_builder/autodmg_cache_build.py [0:0]


def main():
    """Main function."""
    wait_for_network()
    if not os.path.exists('/Applications/AutoDMG.app/Contents/MacOS/AutoDMG'):
        print("AutoDMG not at expected path in /Applications, quitting!")
        sys.exit(1)
    parser = argparse.ArgumentParser(
        description='Built a precached AutoDMG image.')
    parser.add_argument(
        '-m', '--manifest', help='Manifest name. Defaults to "prod".',
        default='prod')
    parser.add_argument(
        '-o', '--output', help='Path to DMG to create.',
        default='AutoDMG_full.hfs.dmg')
    parser.add_argument(
        '--cache', help=(
            'Path to local cache to store files. '
            'Defaults to "/Library/AutoDMG"'),
        default='/Library/AutoDMG')
    parser.add_argument(
        '-d', '--download', help='Force a redownload of all files.',
        action='store_true', default=False)
    parser.add_argument(
        '-l', '--logpath', help='Path to log files for AutoDMG.',
        default='/Library/AutoDMG/logs/')
    parser.add_argument(
        '-s', '--source', help='Path to base OS installer.',
        default='/Applications/Install OS X El Capitan.app')
    parser.add_argument(
        '-n', '--volumename', help=(
            'Name of volume after imaging. '
            'Defaults to "Macintosh HD."'),
        default='Macintosh HD')
    parser.add_argument(
        '-S', '--volumesize', help=(
            'Size of volume after imaging. '
            'Defaults to 120'),
        default=120)
    parser.add_argument(
        '--loglevel', help='Set loglevel between 1 and 7. Defaults to 6.',
        choices=range(1, 8), type=int, default=6)
    parser.add_argument(
        '--dsrepo', help='Path to DeployStudio repo. ')
    parser.add_argument(
        '--noicons', help="Don't cache icons.",
        action='store_true', default=False)
    parser.add_argument(
        '-u', '--update', help='Update the profiles plist.',
        action='store_true', default=False)
    parser.add_argument(
        '--extras', help=(
            'Path to JSON file containing additions '
            ' and exceptions lists.')
    )
    args = parser.parse_args()

    print("Using Munki repo: %s" % MUNKI_URL)
    global CACHE
    CACHE = args.cache

    print(time.strftime("%c"))
    print("Starting run...")
    # Create the local cache directories
    dir_struct = {
        'additions': os.path.join(CACHE, 'additions'),
        'catalogs': os.path.join(CACHE, 'catalogs'),
        'downloads': os.path.join(CACHE, 'downloads'),
        'exceptions': os.path.join(CACHE, 'exceptions'),
        'exceptions_pkgs': os.path.join(CACHE, 'exceptions_pkgs'),
        'manifests': os.path.join(CACHE, 'manifests'),
        'icons': os.path.join(CACHE, 'icons'),
        'logs': os.path.join(CACHE, 'logs'),
        'client_resources': os.path.join(CACHE, 'client_resources'),
    }
    path_creation = prepare_local_paths(dir_struct.values())
    if path_creation > 0:
        print("Error setting up local cache directories.")
        sys.exit(-1)

    # Populate the list of installs based on the manifest
    install_list = gather_install_list(args.manifest)

    # Prior to downloading anything, populate the other lists
    additions_list = list()
    item_list = list()
    except_list = list()
    exceptions = list()
    # exceptions[] is a list of exceptions specified by the extras file
    # except_list[] is a list of files downloaded into the exceptions dir
    if args.extras:
        # Additions are downloaded & added to the additions_list
        # Exceptions are added to the exceptions list,
        # Downloaded exceptions are added to the except_list list.
        handle_extras(
            args.extras,
            dir_struct['exceptions'],
            dir_struct['additions'],
            args.download,
            exceptions,
            except_list,
            additions_list
        )

    # Check for managed_install items and download them
    process_managed_installs(
        install_list,
        exceptions,
        except_list,
        item_list,
        dir_struct['exceptions'],
        dir_struct['downloads'],
        args.download
    )

    # Clean up cache of items we don't recognize
    print("Cleaning up downloads folder...")
    cleanup_local_cache(item_list, dir_struct['downloads'])
    print("Cleaning up exceptions folder...")
    cleanup_local_cache(except_list, dir_struct['exceptions'])

    # Icon handling
    if not args.noicons:
        # Download all icons from the catalogs used by the manifest
        catalog_item_list = []
        for catalog in os.listdir(dir_struct['catalogs']):
            catalog_item_list += plistlib.readPlist(
                os.path.join(dir_struct['catalogs'], catalog)
            )
        icon_pkg_file = handle_icons(catalog_item_list)
    if icon_pkg_file:
        additions_list.extend([icon_pkg_file])

    # Munki custom resources handling
    custom_pkg_file = handle_custom()
    if custom_pkg_file:
        additions_list.extend([custom_pkg_file])

    # Build each exception into its own package
    sys.stdout.flush()
    exceptions_pkg_list = build_exceptions(CACHE)
    additions_list.extend(exceptions_pkg_list)

    loglevel = str(args.loglevel)

    # Run any extra code or package builds
    sys.stdout.flush()
    pkg_list = autodmg_org.run_unique_code(args)
    additions_list.extend(pkg_list)

    # Now that cache is downloaded, let's add it to the AutoDMG template.
    print("Creating AutoDMG-full.adtmpl.")
    templatepath = os.path.join(CACHE, 'AutoDMG-full.adtmpl')

    plist = dict()
    plist["ApplyUpdates"] = True
    plist["SourcePath"] = args.source
    plist["TemplateFormat"] = "1.0"
    plist["VolumeName"] = args.volumename
    plist["VolumeSize"] = args.volumesize
    plist["AdditionalPackages"] = [
        os.path.join(
            dir_struct['downloads'], f
        ) for f in os.listdir(
            dir_struct['downloads']
        ) if (not f == '.DS_Store') and (f not in additions_list)
    ]

    if additions_list:
        plist["AdditionalPackages"].extend(additions_list)

    # Complete the AutoDMG-full.adtmpl template
    plistlib.writePlist(plist, templatepath)
    autodmg_cmd = [
        '/Applications/AutoDMG.app/Contents/MacOS/AutoDMG'
    ]
    if os.getuid() == 0:
        # We are running as root
        print("Running as root.")
        autodmg_cmd.append('--root')
    if args.update:
        # Update the profiles plist too
        print("Updating UpdateProfiles.plist...")
        cmd = autodmg_cmd + ['update']
        run(cmd)

    # Clean up cache of items we don't recognize
    print("Cleaning up downloads folder...")
    cleanup_local_cache(item_list, dir_struct['downloads'])
    print("Cleaning up exceptions folder...")
    cleanup_local_cache(except_list, dir_struct['exceptions'])

    logfile = os.path.join(args.logpath, 'build.log')
    # Now kick off the AutoDMG build
    dmg_output_path = os.path.join(CACHE, args.output)
    sys.stdout.flush()
    print("Building disk image...")
    if os.path.isfile(dmg_output_path):
        os.remove(dmg_output_path)
    cmd = autodmg_cmd + [
        '-L', loglevel,
        '-l', logfile,
        'build', templatepath,
        '--download-updates',
        '-o', dmg_output_path]
    print("Full command: %s" % cmd)
    run(cmd)
    if not os.path.isfile(dmg_output_path):
        print("Failed to create disk image!", file=sys.stderr)
        sys.exit(1)

    sys.stdout.flush()
    if args.dsrepo:
        # Check the Deploystudio masters to see if this image already exists
        populate_ds_repo(dmg_output_path, args.dsrepo)

    print("Ending run.")
    print(time.strftime("%c"))