def os_mount(self):
     self.mount_path, self.diff_path = self.get_mount_info()
     failsafe_makedirs(self.mount_path)
     failsafe_makedirs(self.diff_path)
     self.docker.local.image_mount(self.fullname, self.diff_path,
                                   self.mount_path)
     self.mounted = True
Example #2
0
def setup(mount_path):
    # ensure FILES var is completely defined
    if FILES['/root/.ssh/authorized_keys'] is None:
        # ensure server has a pub key
        ensure_root_key_exists()
        # we will authorize the server to connect to nodes
        with open(SERVER_KEY_PATH + '.pub') as f:
            FILES['/root/.ssh/authorized_keys'] = f.read()
    # /etc/dropbear is a symlink to /var/run/dropbear on some images.
    # * /var/run/dropbear is an absolute path, thus we should mind not
    #   being directed to server files!
    # * in this conf, the content of this directory is cleared at startup,
    #   which is not what we want.
    # We may have the same issues with /etc/ssh.
    remove_if_link(mount_path + '/etc/ssh')
    remove_if_link(mount_path + '/etc/dropbear')
    # copy files listed in variable FILES on the image
    for path, content in FILES.items():
        failsafe_makedirs(mount_path + os.path.dirname(path))
        with open(mount_path + path, 'w') as f:
            f.write(content)
    # set node DNS servers
    if os.path.exists(mount_path + '/etc/resolv.conf'):
        os.rename(mount_path + '/etc/resolv.conf',
                  mount_path + '/etc/resolv.conf.saved')
    with open(mount_path + '/etc/resolv.conf', 'w') as f:
        for resolver in get_dns_servers():
            f.write("nameserver {}\n".format(resolver))
    if os.path.isfile(mount_path + '/etc/hostname') and \
            not os.path.islink(mount_path + '/etc/hostname'):
        os.remove(mount_path +
                  '/etc/hostname')  # probably a residual of image build
    # fix absolute symlinks in /boot
    fix_absolute_symlinks(mount_path, mount_path + '/boot')
    # fix compatbility with old walt-node packages
    if os.path.exists(mount_path + '/usr/local/bin/walt-echo'):
        os.remove(mount_path + '/usr/local/bin/walt-echo')
    # copy walt scripts in <image>/bin, update template parameters
    image_bindir = mount_path + '/bin/'
    for script_name, template in NODE_SCRIPTS.items():
        script_path = resource_filename(__name__, script_name)
        shutil.copy(script_path, image_bindir)
        if template:
            update_template(image_bindir + script_name, TEMPLATE_ENV)
    # read image spec file if any
    image_spec = spec.read_image_spec(mount_path)
    if image_spec != None:
        # update template files specified there
        spec.update_templates(mount_path, image_spec, TEMPLATE_ENV)
        # update features matching those of the server
        spec.enable_matching_features(mount_path, image_spec)
    # copy server spec file, just in case
    spec.copy_server_spec_file(mount_path)
    # fix PTP conf regarding unicast default mode too verbose on LAN
    fix_ptp(mount_path)
Example #3
0
 def mount(self, image_id, fullname=None):
     if image_id in self.mounts:
         return  # already mounted
     self.mounts.add(image_id)
     desc = fullname if fullname else image_id
     print('Mounting %s...' % desc)
     mount_path = get_mount_path(image_id)
     failsafe_makedirs(mount_path)
     self.docker.local.image_mount(image_id, mount_path)
     setup(mount_path)
     print('Mounting %s... done' % desc)
Example #4
0
def failsafe_mkfifo(path, mode=None):
    if mode == None:
        mode = RW_ALL
    # check if it does not exist already
    if os.path.exists(path):
        return
    # ensure parent dir exists
    failsafe_makedirs(os.path.dirname(path))
    # create the fifo
    os.mkfifo(path)
    os.chmod(path, mode)
def setup(image):
    mount_path = image.mount_path
    # ensure FILES var is completely defined
    if FILES['/root/.ssh/authorized_keys'] is None:
        # ensure server has a pub key
        ensure_root_key_exists()
        # we will authorize the server to connect to nodes
        with open(SERVER_KEY_PATH + '.pub') as f:
            FILES['/root/.ssh/authorized_keys'] = f.read()
    # /etc/dropbear is a symlink to /var/run/dropbear on some images.
    # * /var/run/dropbear is an absolute path, thus we should mind not
    #   being directed to server files!
    # * in this conf, the content of this directory is cleared at startup,
    #   which is not what we want.
    # We may have the same issues with /etc/ssh.
    remove_if_link(mount_path + '/etc/ssh')
    remove_if_link(mount_path + '/etc/dropbear')
    # copy files listed in variable FILES on the image
    for path, content in FILES.items():
        failsafe_makedirs(mount_path + os.path.dirname(path))
        with open(mount_path + path, 'w') as f:
            f.write(content)
    # set node DNS servers
    if os.path.exists(mount_path + '/etc/resolv.conf'):
        os.rename(mount_path + '/etc/resolv.conf', mount_path + '/etc/resolv.conf.saved')
    with open(mount_path + '/etc/resolv.conf', 'w') as f:
        for resolver in get_dns_servers():
            f.write("nameserver {}\n".format(resolver))
    if os.path.isfile(mount_path + '/etc/hostname') and \
            not os.path.islink(mount_path + '/etc/hostname'):
        os.remove(mount_path + '/etc/hostname')     # probably a residual of image build
    # fix absolute symlinks in /boot
    fix_absolute_symlinks(mount_path, mount_path + '/boot')
    # fix compatbility with old walt-node packages
    if os.path.exists(mount_path + '/usr/local/bin/walt-echo'):
        os.remove(mount_path + '/usr/local/bin/walt-echo')
    # copy walt scripts in <image>/bin, update template parameters
    image_bindir = mount_path + '/bin/'
    for script_name, template in NODE_SCRIPTS.items():
        script_path = resource_filename(__name__, script_name)
        shutil.copy(script_path, image_bindir)
        if template:
            update_template(image_bindir + script_name, TEMPLATE_ENV)
    # read image spec file if any
    image_spec = spec.read_image_spec(mount_path)
    if image_spec != None:
        # update template files specified there
        spec.update_templates(mount_path, image_spec, TEMPLATE_ENV)
        # update features matching those of the server
        spec.enable_matching_features(image, image_spec)
    # copy server spec file, just in case
    spec.copy_server_spec_file(mount_path)
    # fix PTP conf regarding unicast default mode too verbose on LAN
    fix_ptp(mount_path)
Example #6
0
def failsafe_mkfifo(path, mode = None):
    if mode == None:
        mode = RW_ALL
    # check if it does not exist already
    if os.path.exists(path):
        return
    # ensure parent dir exists
    failsafe_makedirs(os.path.dirname(path))
    # create the fifo
    os.mkfifo(path)
    os.chmod(path, mode)
 def start_vnode(self, node):
     if not os.path.exists('/etc/qemu/bridge.conf'):
         failsafe_makedirs('/etc/qemu')
         with open('/etc/qemu/bridge.conf', 'w') as f:
             f.write('allow walt-net\n')
     cmd = CMD_START_VNODE % dict(mac=node.mac,
                                  ip=node.ip,
                                  model=node.model,
                                  name=node.name,
                                  server_ip=get_server_ip())
     print(cmd)
     subprocess.Popen(shlex.split(cmd))
 def start_vnode(self, node):
     if not os.path.exists('/etc/qemu/bridge.conf'):
         failsafe_makedirs('/etc/qemu')
         with open('/etc/qemu/bridge.conf', 'w') as f:
             f.write('allow walt-net\n')
     cmd = CMD_START_VNODE % dict(
         mac = node.mac,
         ip = node.ip,
         model = node.model,
         name = node.name,
         server_ip = get_server_ip()
     )
     print(cmd)
     subprocess.Popen(shlex.split(cmd))
 def __init__(self, serial_dev_path):
     self.f = open(serial_dev_path, 'r', 0)
     self.walt_logs = open(SERVER_LOGS_FIFO, 'w')
     # Data does not comes in immediately after we have the
     # device open. Wait a little to make sure we get
     # the data to be flushed.
     time.sleep(0.1)
     self.flush()
     self.logdefs = []
     self.logvars = {}
     log_dir = '/var/log/walt/autolog%s' % serial_dev_path
     failsafe_makedirs(log_dir)
     self.in_dbg_log = open(log_dir + '/in.log', 'w')
     self.out_dbg_log = open(log_dir + '/out.log', 'w')
     self.started = False
 def __init__(self, serial_dev_path):
     self.f = open(serial_dev_path, 'r', 0)
     self.walt_logs = open(SERVER_LOGS_FIFO, 'w')
     # Data does not comes in immediately after we have the
     # device open. Wait a little to make sure we get
     # the data to be flushed.
     time.sleep(0.1)
     self.flush()
     self.logdefs = []
     self.logvars = {}
     log_dir = '/var/log/walt/autolog%s' % serial_dev_path
     failsafe_makedirs(log_dir)
     self.in_dbg_log = open(log_dir + '/in.log', 'w')
     self.out_dbg_log = open(log_dir + '/out.log', 'w')
     self.started = False
Example #11
0
def run():
    if len(sys.argv) < 2:
        sys.exit('Missing 1st argument: "up" or "down".')
    action = sys.argv[1]
    if action not in ('up', 'down'):
        sys.exit('1st argument must be "up" or "down".')
    iface = os.environ.get('IFACE')
    if iface is None:
        sys.exit('IFACE environment variable is missing.')
    failsafe_makedirs(WALT_STATUS_DIR)
    if action == 'up':
        network_conf = conf['network']
        up(iface, network_conf)
    elif action == 'down':
        down(iface)
Example #12
0
def update(db):
    # create dir if it does not exist yet
    failsafe_makedirs(NODES_PATH)
    # list existing entries, in case some of them are obsolete
    invalid_entries = set(f for f in os.listdir(NODES_PATH))
    # each node has a directory entry with:
    # - a link called "fs" to the image filesystem root
    # - a link called "tftp" to a directory of boot files stored per-model in the image
    # The name of this dir is the mac address of the node,
    # written <hh>:<hh>:<hh>:<hh>:<hh>:<hh>.
    # For compatibility with different network bootloaders
    # we also provide 3 links to this directory:
    # - mac address written <hh>-<hh>-<hh>-<hh>-<hh>-<hh>
    # - ipv4 address (dotted quad notation)
    # - walt node name
    for db_node in db.select('nodes'):
        if db_node.image is not None:
            image_path = get_mount_path(db_node.image)
            mac = db_node.mac
            model = db_node.model
            mac_dash = mac.replace(':', '-')
            device = db.select_unique('devices', mac=mac)
            failsafe_makedirs(NODES_PATH + mac)
            failsafe_symlink(image_path,
                             NODES_PATH + mac + '/fs',
                             force_relative=True)
            # link to boot files stored inside the image
            failsafe_symlink(image_path + '/boot/' + model,
                             NODES_PATH + mac + '/tftp',
                             force_relative=True)
            for ln_name in (mac_dash, device.ip, device.name):
                failsafe_symlink(NODES_PATH + mac,
                                 NODES_PATH + ln_name,
                                 force_relative=True)
                # this entry is valid
                invalid_entries.discard(ln_name)
            invalid_entries.discard(mac)
    # if there are still values in variable invalid_entries,
    # we can remove the corresponding entry
    for entry in invalid_entries:
        entry = NODES_PATH + entry
        if os.path.isdir(entry) and not os.path.islink(entry):
            shutil.rmtree(entry)
        else:
            os.remove(entry)
Example #13
0
def generate_exports_file(images, nodes):
    with open('/etc/exports', 'w') as f:
        f.write("# Root filesystem images\n")
        for image in images:
            if image.ready:
                f.write((IMAGE_EXPORT_PATTERN %
                         dict(image_mountpoint=image.mount_path,
                              walt_subnet=get_walt_subnet(),
                              fsid=get_fsid(image))) + "\n")
        f.write("# Persistent node directories\n")
        for node in nodes:
            persist_path = PERSISTENT_PATH % dict(node_mac=node.mac)
            try:
                # ensure persistent directories exists
                failsafe_makedirs(persist_path)
            except OSError:
                # directory already exists
                pass
            f.write((PERSISTENT_EXPORT_PATTERN %
                     dict(persist_mountpoint=persist_path,
                          walt_subnet=get_walt_subnet())) + "\n")
Example #14
0
def update(db):
    # create dir if it does not exist yet
    failsafe_makedirs(NODES_PATH)
    # list existing entries, in case some of them are obsolete
    invalid_entries = set(f for f in os.listdir(NODES_PATH))
    # each node has a directory entry with:
    # - a link called "fs" to the image filesystem root
    # - a link called "tftp" to a directory of boot files stored per-model in the image
    # The name of this dir is the mac address of the node,
    # written <hh>:<hh>:<hh>:<hh>:<hh>:<hh>.
    # For compatibility with different network bootloaders
    # we also provide 3 links to this directory:
    # - mac address written <hh>-<hh>-<hh>-<hh>-<hh>-<hh>
    # - ipv4 address (dotted quad notation)
    # - walt node name
    for db_node in db.select('nodes'):
        if db_node.image is not None:
            image_path = get_mount_path(db_node.image)
            mac = db_node.mac
            model = db_node.model
            mac_dash = mac.replace(':', '-')
            device = db.select_unique('devices', mac=mac)
            failsafe_makedirs(NODES_PATH + mac)
            failsafe_symlink(image_path, NODES_PATH + mac + '/fs', force_relative=True)
            # link to boot files stored inside the image
            failsafe_symlink(image_path + '/boot/' + model,
                            NODES_PATH + mac + '/tftp', force_relative=True)
            for ln_name in (mac_dash, device.ip, device.name):
                failsafe_symlink(NODES_PATH + mac, NODES_PATH + ln_name, force_relative=True)
                # this entry is valid
                invalid_entries.discard(ln_name)
            invalid_entries.discard(mac)
    # if there are still values in variable invalid_entries,
    # we can remove the corresponding entry
    for entry in invalid_entries:
        entry = NODES_PATH + entry
        if os.path.isdir(entry) and not os.path.islink(entry):
            shutil.rmtree(entry)
        else:
            os.remove(entry)
 def start_vnode(self, node):
     if not os.path.exists('/etc/qemu/bridge.conf'):
         failsafe_makedirs('/etc/qemu')
         with open('/etc/qemu/bridge.conf', 'w') as f:
             f.write('allow walt-net\n')
     # in case a screen session already exists for this vnode
     # (e.g. walt server process was killed), kill it
     self.try_kill_vnode(node.mac)
     # start vnode
     VNODE_LOG_DIR.mkdir(parents=True, exist_ok=True)
     hypmac = node.mac.replace(':', '-')
     cmd = CMD_START_VNODE % dict(
         mac = node.mac,
         hypmac = hypmac,
         ip = node.ip,
         model = node.model,
         name = node.name,
         server_ip = get_server_ip(),
         cpu_cores = node.conf.get('cpu.cores', VNODE_DEFAULT_CPU_CORES),
         ram = node.conf.get('ram', VNODE_DEFAULT_RAM),
         ttyrec_file = VNODE_LOG_DIR / (hypmac + str(int(time())) + '.tty')
     )
     print(cmd)
     subprocess.Popen(shlex.split(cmd))
Example #16
0
def copy_server_spec_file(image_path):
    target_path = image_path + SERVER_SPEC_PATH
    failsafe_makedirs(os.path.dirname(target_path))
    shutil.copy(SERVER_SPEC_PATH, target_path)
Example #17
0
 def os_mount(self):
     self.mount_path, self.diff_path = self.get_mount_info()
     failsafe_makedirs(self.mount_path)
     failsafe_makedirs(self.diff_path)
     self.docker.local.image_mount(self.fullname, self.diff_path, self.mount_path)
     self.mounted = True