Giter Site home page Giter Site logo

dwight's Introduction

What is Dwight?

dwight is a utility for managing and deploying chrooted environments with external dependencies. dwight reads a configuration file that specifies how to establish the environment, and then allows you to run commands and interact with the environment.

Chrooted environments are constructed from a base image (currently only squashfs images are supported). External dependencies can then be added on to specified paths at construction time (these paths must exist in the base image as empty directories, as this is done via mount).

Installation

dwight can be installed via pip:

  pip install dwight-chroot

Usage

To run dwight you'll need a configuration file. A configuration file should at least contain the location of the base image. Here is a minimal configuration file:

  ROOT_IMAGE = "/path/to/image.squashfs"

Now just run:

  dwight -c /path/to/config_file.py shell

This will drop you into a shell in your chrooted environment.

Configuration

Dwight receives its configuration from files specified with the -c flag. Multiple files can be specified for this option.

Dwight configuration files are simple Python files that contain settings in the form of underscore-separated uppercase strings (like THIS_ONE). variables not matching that criterion will be silently ignored (enabling you to use them for temporary variables etc.).

When Dwight loads configuration, it first looks for ~/.dwightrc and loads it. If it doesn't exist an empty one will be created. Afterwards each configuration file from command line is loaded in turn, and the end result is the aggregation of all the config files.

PLEASE NOTE that when a configuration file is processed it has access to the parameters set by previous configuration files, so it can choose whether to override them or extend them. This is important, for instance, when using the INCLUDES option -- assigning to it will drop previous entries, so prefer using the += operator instead.

ROOT_IMAGE

The path to the root image for the chroot. This can also be a URL to an image file over http.

INCLUDES

To bind paths or resources to your chroot environment, use the INCLUDES varaible in your configuration file:

  INCLUDES += [
    Include("/path/in/chroot", "/local/path"),
  ]

INCLUDES is a list of Include declarations. Each has a first argument which is the destination inside the chroot, and a second argument which is the resource to be Includeed.

Severl types of resources can be included, as describe below.

Local Paths

Local paths get included as bind-mounts. If the path specified is a relative path, it is taken relative to the current working directory (useful for home dir mounting, for example)

Git/Mercurial Repositories

Git and Mercurial repositories can be included. They are designated by using resource paths starting with git://, ssh+git://, http+hg:// or https+hg://. They also take additional optional parameters, for example:

    Include("/path", "git://server/git/repository", branch="development") # cloning a specific branch
    Include("/path", "git://server/git/repository", tag="rc1") # clone a specific tag
    Include("/path", "git://server/git/repository", commit="4ff7a0565964eb428e5b45479922f164a5ee941b") # specific commit

Squashfs Images

You can include whole images saved as squashfs files. This can be done from a local path:

    Include("/mount", "/path/to/image.squashfs")

Or from http/https:

    Include("/mount", "http://server/files/image.squashfs")

ENVIRON

You can control the environment variables set up by dwight using the ENVIRON variable in your configuration file:

  ENVIRON = {
       "PATH" : "$PATH:another/extra/path/here"
  }

PWD

The working directory for the command to run. By default this is the working directory in which dwight was run.

UID/GIDS

You can control the uid/gids of the chrooted command.

If the uid value is an integer, it will be used as the user to execute commands.

If the uid is None, Dwight will attempt to fetch the uid from the SUDO_UID environment variable. If the variable does not exist, the command will run as root

The variable GIDS holds a list of group ids used when executing commands

If the value is None, Dwight will fetch the list of group id's belonging to the user invoking dwight, using SUDO_UID to determine the current user or using uid 0 if SUDO_UID does not exist

NUM_LOOP_DEVICES

This optional variable controls the amount of loop devices to ensure before chrooting. If it is set, and no hard limit is configured for number of loop devices, dwight will ensure this number of loop devices exists in /dev.

MAX_CACHE_SIZE

The maximum size, in bytes, that the cache directory can occupy. Note that the total size of the cache directory may still exceed this value some times, like in cases where all the space is needed for current includes.

Known Issues

  • Currently including a single git/hg repository multiple times with different commits/branches/tags will cause separate copies of the repository in the cache

Extending, Modifying and Testing the Code

The tests included in dwight are intended to be run in a dedicated environment set up by vagrant. To get started, install vagrant, and then run vagrant up from the project directory to start the environment.

To run the tests, ssh into the client vm and run via nosetests like so:

  $ vagrant ssh client
  vagrant@client:~$ sudo nosetests -w src/tests

Acknowledgements

Special credit and thanks go to Yotam Rubin, who came up with the idea and drove this project forward.

LICENSE

Dwight is distributed under the BSD 3-clause license. (See LICENSE)

dwight's People

Contributors

vmalloc avatar yotam-wizery avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dwight's Issues

Support relative includes

Consider the following include:

INCLUDES = {'my_traces' : Include('git://github.com/yotamr/traces.git')}

It would be convenient to have dwight translate relative my_traces so it appears under the current working directory on the chrooted filesystem. Specifically, the above line should translate to:

INCLUDES = {os.path.join(os.getcwd(), 'my_traces') : Include('git://github.com/yotamr/traces.git')}

default/builtin configuration

Most dwight chroot environments will have some common bind-mounts. I can think of the following:
/proc, /home, /sys/ /dev/, /run

It makes sense to have these mount points embodied in some sort of default/builtin configuration mechanism (which can be disabled with a flag)

uid in chroot context

When running dwight through sudo, the uid in the chroot environment is 0 as well. It's desirable to have dwight command run in the same context of the calling user. I don't have a clean solution, here are some ideas:

  1. Since most dwight invocations are through sudo, dwight can use the SUDO_UID environment variable to setuid() to the original user and setuid(getuid()) in case $SUDO_UID doesn't exist
  2. setuid the Python interpreter - probably a bad idea.

cache should have a maximal size

When the cache exceeds a certain configurable/default size, the oldest entries should be removed when downloading new cache items

working directory of the chrooted command

It would be nice to control the working directory of the user supplied command. In most cases, the working directory will be the host's $PWD. We can add a WORKING_DIRECTORY directive to the configuration file and have dwight generate a default working directory set to $PWD in .dwightrc.

loop device handling

On most distributions, there are by default 8 loop devices in /dev, although more can be created. Dwight may quickly expend 8 loop devices. How about adding a directive to the configuration file that instructs dwight to create the specified amount of loop devices?
I think the logic should be like this:

  1. If LOOP_DEVICES isn't defined, do nothing, else:
  2. If there's a hard limit on the number of loop devices (max_loop exists in /proc/cmdline), do nothing (since the kernel creates all the nodes in /dev according to the limit), else:
  3. Ensure that count LOOP_DEVICES are available in /dev and create any missing nodes.

What do you think?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.