import logging
import os
import subprocess
import sys

import gen
import gen.build_deploy.bash
import pkgpanda
from dcos_installer.constants import BOOTSTRAP_DIR, CLUSTER_PACKAGES_PATH, SERVE_DIR

log = logging.getLogger(__name__)


def do_configure(config):
    gen_out = gen.generate(config.as_gen_format(), extra_sources=[gen.build_deploy.bash.onprem_source])

    subprocess.check_call(['mkdir', '-p', SERVE_DIR])
    gen.build_deploy.bash.generate(gen_out, SERVE_DIR)

    # Get bootstrap from artifacts
    # TODO(cmaloney): Switch to use a local storage provider like do_aws_configure does.
    fetch_bootstrap(gen_out.arguments['bootstrap_id'])
    # Write some package metadata
    pkgpanda.util.write_json(CLUSTER_PACKAGES_PATH, gen_out.cluster_packages)


def do_move_atomic(src_dir, dest_dir, filenames):
    assert os.path.exists(src_dir)
    assert os.path.exists(dest_dir)

    def rollback():
        for filename in filenames:
            filename = dest_dir + '/' + filename
            try:
                os.remove(filename)
            except OSError as ex:
                log.error("Internal error removing temporary file. Might have corrupted file %s: %s",
                          filename, ex.strerror)
        sys.exit(1)

    try:
        # Copy across
        for filename in filenames:
            subprocess.check_output(['cp', src_dir + '/' + filename, dest_dir + '/' + filename])
    except subprocess.CalledProcessError as ex:
        log.error("Copy failed: %s\nOutput:\n%s", ex.cmd, ex.output)
        log.error("Removing partial artifacts")
        rollback()
    except KeyboardInterrupt:
        log.error("Copy out of installer interrupted. Removing partial files.")
        rollback()


def fetch_bootstrap(bootstrap_id):
    filenames = [
        "{}.bootstrap.tar.xz".format(bootstrap_id),
        "{}.active.json".format(bootstrap_id)]
    container_cache_dir = "artifacts/bootstrap"

    # If all the targets already exist, no-op
    dest_files = [BOOTSTRAP_DIR + '/' + filename for filename in filenames]
    if all(map(os.path.exists, dest_files)):
        return

    # Make sure the internal cache files exist
    src_files = [container_cache_dir + '/' + filename for filename in filenames]
    for filename in src_files:
        if not os.path.exists(filename):
            log.error("Internal Error: %s not found. Should have been in the installer container.", filename)
            raise FileNotFoundError(filename)

    subprocess.check_call(['mkdir', '-p', BOOTSTRAP_DIR])
    do_move_atomic(container_cache_dir, BOOTSTRAP_DIR, filenames)

@@ -768,229 +768,684 @@
 def 
-do_move_atomic(src_dir, dest_dir, filenames):%0A    assert os.path.exists(src_dir)%0A    assert os.path.exists(dest_dir)%0A%0A    def rollback():%0A        for filename in file
+parent_dirs(filename):%0A    assert not (filename.startswith('/') or filename.endswith('/'))%0A    dirs = %5B%5D%0A    for directory in filename.split('/')%5B:-1%5D:%0A        dirs.append(directory)%0A        yield '/'.join(dirs)%0A%0A%0Adef do_move_atomic(src_dir, dest_dir, filenames):%0A    assert os.path.exists(src_dir)%0A    assert os.path.exists(dest_dir)%0A%0A    created_dirs = %5B%5D%0A    created_files = %5B%5D%0A%0A    def mkdir(dirname):%0A        created_dirs.append(dirname)%0A        subprocess.check_output(%5B'mkdir', dir
 name
-s:
+%5D)%0A
 %0A    
-        filename = dest_dir + '/' + filename
+def copy(src, dest):%0A        created_files.append(dest)%0A        subprocess.check_output(%5B'cp', src, dest%5D)%0A%0A    def rollback():%0A        for filename in reversed(created_files):
 %0A   
@@ -1683,138 +1683,559 @@
 or)%0A
-        sys.exit(1)%0A%0A    try:%0A        # Copy across%0A        for filename in filenames:%0A            subprocess.check_output(%5B'cp', 
+%0A        for filename in reversed(created_dirs):%0A            try:%0A                os.rmdir(filename)%0A            except OSError as ex:%0A                log.error(%22Internal error removing temporary dir %25s: %25s%22, filename, ex.strerror)%0A%0A        sys.exit(1)%0A%0A    try:%0A        # Copy across%0A        for filename in filenames:%0A            for parent_dir in parent_dirs(filename):%0A                dest_parent_dir = dest_dir + '/' + parent_dir%0A                if not os.path.exists(dest_parent_dir):%0A                    mkdir(dest_parent_dir)%0A            copy(
 src_
@@ -2281,17 +2281,16 @@
 filename
-%5D
 )%0A    ex

Create and roll back parent dirs for artifacts