示例#1
0
def main(argv):
    parser = optparse.OptionParser(__doc__)
    parser.add_option("--tear-down", dest="tear_down_dir")
    parser.add_option("--show-config", dest="do_show_config",
                      action="store_const", const=True, default=False)
    parser.add_option("--show-ssh-cmd", dest="do_show_ssh_cmd",
                      action="store_const", const=True, default=False)
    parser.allow_interspersed_args = False
    options, args = parser.parse_args(argv)
    if len(args) == 0:
        args = ["bash"]
    if options.tear_down_dir is not None:
        force_rm(options.tear_down_dir)
        return
    config_path = find_config_path(on_not_found=parser.error)
    config = json.loads(read_file(config_path))
    config.setdefault("project_path", os.path.dirname(config_path))
    config.setdefault("cwd", os.path.abspath("."))
    config.setdefault("home", os.path.abspath(os.path.expanduser("~")))
    expand_config(config)
    if options.do_show_config:
        print json.dumps(config, indent=2, sort_keys=True)
        return
    if options.do_show_ssh_cmd:
        ssh_argv = get_ssh_argv(config)
        print "~~~", " ".join(shell_escape(a) for a in ssh_argv)
        return
    basebox(config, args)
示例#2
0
def get_ssh_argv(config, argv=()):
    return ["ssh", "-i", config["ssh_key_path"],
            "-o", "HostKeyAlias=basebox", 
            "-o", "HashKnownHosts=no",
            "-o", "BatchMode=yes",
            # "-t",
            "-o", "ServerAliveInterval=20",
            "-q",
            "-o", "UserKnownHostsFile=" + config["host_key_path"] + ".known",
            "[email protected]"] + [
        " ".join(shell_escape(a) for a in argv)]
示例#3
0
def prepare(config):

    def flush_cache():
        if config["do_write_project_cache"]:
            call_no_print(
                ["mkdir", "-p", os.path.dirname(config["project_cache_path"])])
            with open(config["project_cache_path"], "wb") as fh:
                fh.write(json.dumps(config["project_cache"]))

    flush_cache()
    root_path = os.path.join(config["project_dir"], "root")
    flush_cache()
    if not os.path.exists(root_path):
        force_rm(root_path)
        mnt_path = config["mnt_path"]
        force_rm(mnt_path)
        call(["mkdir", "-p", root_path])
        call(["mkdir", "-p", mnt_path])
        call(["sudo", "mount", "--bind", root_path, mnt_path])
        call(["sudo", "debootstrap", config["ubuntu-codename"], mnt_path], 
             stdout=None, stderr=None, stdin=None)
        for relpath in ["proc", "dev", "dev/pts", "sys"]:
            src = os.path.join("/", relpath)
            dst = os.path.join(mnt_path, relpath)
            call(["sudo", "mkdir", "-p", dst])
            call(["sudo", "mount", "--bind", src, dst])
        resolvconf = os.path.join(mnt_path, "run/resolvconf/resolv.conf")
        force_rm(resolvconf)
        call(["sudo", "cp", "/etc/resolv.conf", resolvconf])
        call(["sudo", "bash", "-c", 'echo "$1" > "$2"', "-", 
              aptconfig.BLANK_SOURCES, 
              os.path.join(mnt_path, "etc/apt/sources.list")])
        base_sources_config = copy.deepcopy(aptconfig.DEFAULT_CONFIG)
        base_sources_config["distribution"] = config["ubuntu-codename"]
        base_sources = aptconfig.render_to_sources_list(base_sources_config)
        call(["sudo", "bash", "-c", 'echo "$1" > "$2"', "-", 
              base_sources, 
              os.path.join(mnt_path, "etc/apt/sources.list.d/base.list")])
        call(["sudo", "chroot", mnt_path, "apt-get", "update"], stdout=None)
        call(["sudo", "chroot", mnt_path, "apt-get", "remove", "--yes",
              "cloud-init"], stdout=None)
        call(["sudo", "chroot", mnt_path, "apt-get", "install", "--yes",
              "language-pack-en"], stdout=None)
        call(["sudo", "chroot", mnt_path, "apt-get", "install", "--yes",
              "openssh-server"], stdout=None)
        call(["sudo", "chroot", mnt_path, "adduser", "--gecos", "", 
              "--disabled-password", "--uid", "1000", "sysadmin"], stdout=None)
        call(["sudo", "mv", os.path.join(mnt_path, "home", "sysadmin"), 
              os.path.join(config["project_dir"], "home")])
        call(["sudo", "chroot", mnt_path, "adduser", "sysadmin", 
              "adm"], stdout=None)
        call(["sudo", "chroot", mnt_path, "adduser", "sysadmin", 
              "sudo"], stdout=None)
        call(["sudo", "chroot", mnt_path, "bash", "-c", 
              "rm -rf /etc/ssh/ssh_host_*"])
        call(["sudo", "chroot", mnt_path, "dpkg-reconfigure", 
              "openssh-server"], stdout=None)
        call(["cp", os.path.join(mnt_path, "etc", "ssh", 
                                 "ssh_host_ecdsa_key.pub"), 
              config["host_key_path"]])
        call(["bash", "-c", 'echo basebox $(cat "$1") > "$2"', "-",
              config["host_key_path"], config["host_key_path"] + ".known"])
        force_rm(config["ssh_key_path"])
        call(["ssh-keygen", "-P", "", "-f", config["ssh_key_path"]])
        for home_path in [os.path.join(mnt_path, "root"),
                          os.path.join(config["project_dir"], "home")]:
            
            ak_path = os.path.join(home_path, ".ssh", "authorized_keys")
            call(["sudo", "mkdir", "-p", os.path.dirname(ak_path)])
            force_rm(ak_path)
            call(["sudo", "cp", config["ssh_key_path"] + ".pub", ak_path])
            if os.path.basename(home_path) != "root":
                call(["sudo", "chown", "-R", "1000:1000", 
                      os.path.dirname(ak_path)])
        call(["sudo", "bash", "-c", 'echo "$1" > "$2"', "-",
              """\
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
  address 192.168.122.200
  netmask 255.255.255.0
  network 192.168.122.0
  gateway 192.168.122.1
  dns-nameservers 192.168.122.1
""", os.path.join(mnt_path, "etc", "network", "interfaces")])
        nopasswd_path = os.path.join(
            mnt_path, "etc", "sudoers.d", "sudo-nopasswd")
        call(["sudo", "bash", "-c", 'echo "$1" > "$2"', "-",
              """\
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
""", nopasswd_path])
        call(["sudo", "chmod", "0440", nopasswd_path])
        #### Run chef here?
        force_rm(mnt_path)
    if get_vm_state(config["vm_name"], on_no_state=lambda m: None) != "running":
        mnt_path = config["mnt_path"]
        force_rm(mnt_path)
        call(["mkdir", "-p", mnt_path])
        call(["sudo", "mount", "--bind", root_path, mnt_path])
        home_rw = os.path.join(config["project_dir"], "home")
        call(["mkdir", "-p", home_rw])
        home_mnt = os.path.join(mnt_path, "home", "sysadmin")
        force_rm(home_mnt)
        call(["sudo", "mkdir", "-p", home_mnt])
        call(["sudo", "mount", "--bind", home_rw, home_mnt])
        call(["virsh", "--connect", "lxc://", "destroy", config["vm_name"]],
             do_check=False)
        while True:
            if get_vm_state(config["vm_name"], 
                            on_no_state=lambda m: "shut off") == "shut off":
                break
            time.sleep(0.1)
        call(["virsh", "--connect", "lxc://", "undefine", config["vm_name"]],
             do_check=False)
        definition = """\
<domain type="lxc">
  <name>TEMPLATE: name</name>
  <memory>524288</memory>
  <os>
    <type arch="x86_64">exe</type>
    <init>/sbin/init</init>
  </os>
  <vcpu>2</vcpu>
  <clock offset="utc"/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <devices>
    <emulator>/usr/lib/libvirt/libvirt_lxc</emulator>
    <filesystem type="mount">
      <source dir="TEMPLATE: root_dir"/>
      <target dir="/"/>
    </filesystem>
    <interface type="bridge">
      <source bridge="virbr0"/>
    </interface>
    <console type="pty">
      <target port="0"/>
    </console>
  </devices>
</domain>
"""
        xml = lxml.etree.fromstring(definition)
        for match in xml.xpath(".//name"):
            match.text = config["vm_name"]
        for match in xml.xpath(".//filesystem//source"):
            match.attrib["dir"] = mnt_path
        xml_path = os.path.join(config["project_dir"], "libvirt.xml")
        call(["bash", "-c", 'echo "$1" > "$2"', "-",
              lxml.etree.tostring(xml), xml_path])
        call(["virsh", "--connect", "lxc://", "define", xml_path])
        call(["virsh", "--connect", "lxc://", "start", config["vm_name"]])
        print "~~~", " ".join(shell_escape(a) for a in get_ssh_argv(config))
    while True:
        rc = []
        call_no_print(get_ssh_argv(config, ["true"]), 
                      do_check=False, handle_rc=rc.append)
        rc = rc[0]
        if rc == 0:
            break
        time.sleep(0.1)