├── vzmaster ├── images │ └── fake.txz ├── vzmaster-push.yaml ├── forever.sh ├── vzmaster-kill.yaml ├── kill.sh ├── vzexec.sh ├── vzmaster-start.yaml └── vzmaster.sh ├── future ├── vzslave │ ├── include │ │ └── vox.hrl │ ├── vox │ ├── src │ │ ├── vox_stop.erl │ │ ├── vox_create.erl │ │ ├── vox_start.erl │ │ └── vox.erl │ ├── Makefile │ └── rebar.config └── vzbuild │ ├── archlinux │ ├── erlang-nano │ │ ├── escript │ │ └── PKGBUILD │ ├── strace-chroot.sh │ ├── bootstrap.sh │ └── openssl-nano │ │ └── PKGBUILD │ ├── strace-parse.sh │ ├── from-bundle.sh │ ├── from-spec.sh │ ├── strace │ ├── tap-snapshots │ │ ├── tap-bug.js-TAP.test.js │ │ └── t-grammar-TAP.test.js │ ├── main.js │ ├── grammar.js │ ├── parse.js │ └── t │ │ └── grammar.js │ ├── strace-spec.sh │ ├── strace-trace.sh │ ├── vzbuild.sh │ ├── shebang.js │ ├── ldd-chroot.sh │ └── dir-links.js ├── bootstrap ├── roles │ └── mivok0.sudo │ │ ├── meta │ │ ├── .galaxy_install_info │ │ └── main.yml │ │ ├── templates │ │ └── sudoers.j2 │ │ ├── tasks │ │ └── main.yml │ │ ├── defaults │ │ └── main.yml │ │ ├── README.md │ │ └── LICENSE ├── bootstrap.sh └── bootstrap.yaml ├── .gitmodules ├── oci_bundles ├── minimal │ └── config.json ├── busybox.spec ├── beanstalkd.spec ├── gearmand.spec ├── gearmand │ └── config.json ├── beanstalkd │ └── config.json └── busybox-static │ └── config.json ├── .gitignore ├── runch └── runch.sh ├── Roadmap.md └── README.md /vzmaster/images/fake.txz: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /future/vzslave/include/vox.hrl: -------------------------------------------------------------------------------- 1 | -define(VERSION,"b9c40e"). 2 | -------------------------------------------------------------------------------- /future/vzslave/vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nponeccop/vz/HEAD/future/vzslave/vox -------------------------------------------------------------------------------- /bootstrap/roles/mivok0.sudo/meta/.galaxy_install_info: -------------------------------------------------------------------------------- 1 | {install_date: 'Sat Mar 12 01:22:13 2016', version: master} 2 | -------------------------------------------------------------------------------- /vzmaster/vzmaster-push.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | tasks: 4 | - copy: src="images/{{ vzexec.image }}.txz" dest="{{ vzexec.path }}/images/" 5 | -------------------------------------------------------------------------------- /bootstrap/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | [ -z $1 ] && echo "Usage: bootstrap 1.2.3.4 [-k]" >&2 && exit 4 | ansible-playbook -i $1, bootstrap.yaml $2 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "archlinux-microcontainers"] 2 | path = archlinux-microcontainers 3 | url = https://github.com/nponeccop/archlinux-microcontainers.git 4 | -------------------------------------------------------------------------------- /future/vzslave/src/vox_stop.erl: -------------------------------------------------------------------------------- 1 | -module(vox_stop). 2 | -compile(export_all). 3 | 4 | command(Args) -> vox:info("~p Args: ~p~n",[?MODULE,Args]), {ok,?MODULE}. 5 | 6 | -------------------------------------------------------------------------------- /future/vzslave/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | echo "-define(VERSION,\"`git rev-parse HEAD | head -c 6`\")." > include/vox.hrl 3 | mad cle dep com bun vox 4 | clean: 5 | rm -rf deps ebin 6 | -------------------------------------------------------------------------------- /bootstrap/roles/mivok0.sudo/templates/sudoers.j2: -------------------------------------------------------------------------------- 1 | # {{ansible_managed}} 2 | {% for i in sudo_users %} 3 | {{i}} ALL=(ALL) {{"NOPASSWD: " if sudo_nopasswd else ""}}ALL 4 | {% endfor %} 5 | -------------------------------------------------------------------------------- /vzmaster/forever.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -x 3 | while true 4 | do 5 | $* || true 6 | sleep 5 7 | done 2> >(logger -t forever) 1> >(logger -t forever -p info) 8 | 9 | 10 | -------------------------------------------------------------------------------- /bootstrap/roles/mivok0.sudo/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # Set up a simple sudoers file 2 | --- 3 | - name: Sudoers file 4 | template: src=sudoers.j2 dest=/etc/sudoers validate='/usr/sbin/visudo -cf %s' 5 | -------------------------------------------------------------------------------- /future/vzbuild/archlinux/erlang-nano/escript: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | R=/usr/lib/erlang-nano 3 | export BINDIR=$R/bin 4 | exec $BINDIR/beam.smp -pc unicode -- -root $R -noshell -noinput -run escript -extra $* 5 | -------------------------------------------------------------------------------- /oci_bundles/minimal/config.json: -------------------------------------------------------------------------------- 1 | 2 | {"process" : 3 | { "args" : [ "foo" ] 4 | ,"user": 5 | { "uid" : 98 6 | , "gid" : 101 7 | } 8 | } 9 | , "cwd" : "/" 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | deps/ 2 | ebin/ 3 | .applist 4 | *.swp 5 | bootstrap/bootstrap.retry 6 | bootstrap/ssh.pub 7 | vzmaster/images/ 8 | vzmaster/*.retry 9 | vzmaster/tmp-*.json 10 | oci_bundles/*/rootfs/ 11 | -------------------------------------------------------------------------------- /bootstrap/roles/mivok0.sudo/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Who has sudo access - use %foo for groups 3 | sudo_users: 4 | - root 5 | - "%wheel" 6 | 7 | # Do users need to enter a password? 8 | sudo_nopasswd: true 9 | -------------------------------------------------------------------------------- /future/vzslave/rebar.config: -------------------------------------------------------------------------------- 1 | {deps_dir,"deps"}. 2 | {deps, [{jsone,".*", {git, "git://github.com/sile/jsone.git", {tag,"v0.3.3"}}}, 3 | {sh, ".*", {git, "git://github.com/synrc/sh", {tag, "master"}}}]}. 4 | -------------------------------------------------------------------------------- /future/vzbuild/archlinux/strace-chroot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | DIR=$1 4 | shift 5 | ../strace-trace.sh $DIR.spec $* 6 | mkdir $DIR 7 | sudo rsync -l / $DIR --files-from=$DIR.spec 8 | sudo arch-chroot $DIR $* 9 | -------------------------------------------------------------------------------- /oci_bundles/busybox.spec: -------------------------------------------------------------------------------- 1 | /bin 2 | /dev 3 | /etc/resolv.conf 4 | /lib 5 | /mnt 6 | /opt 7 | /proc 8 | /run 9 | /sbin 10 | /srv 11 | /sys 12 | /tmp 13 | /usr/bin/busybox 14 | /usr/lib/ld-2.23.so 15 | /usr/lib/ld-linux.so.2 16 | /usr/sbin 17 | -------------------------------------------------------------------------------- /oci_bundles/beanstalkd.spec: -------------------------------------------------------------------------------- 1 | /dev 2 | /etc/gai.conf 3 | /etc/resolv.conf 4 | /lib 5 | /proc 6 | /run 7 | /sys 8 | /tmp 9 | /usr/bin/beanstalkd 10 | /usr/lib/ld-2.23.so 11 | /usr/lib/ld-linux.so.2 12 | /usr/lib/libc-2.23.so 13 | /usr/lib/libc.so.6 14 | -------------------------------------------------------------------------------- /vzmaster/vzmaster-kill.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | tasks: 4 | - file: state=directory path={{ vzexec.path }}bin 5 | - copy: src=kill.sh dest={{ vzexec.path }}/bin/kill mode=755 6 | - command: "{{ vzexec.path }}/bin/kill {{ vzexec.container_id }}" 7 | -------------------------------------------------------------------------------- /future/vzbuild/strace-parse.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex -o pipefail 3 | cat $1 \ 4 | | grep -Ev '^[+\-]|= -1 E[A-Z]+ \([A-Z][A-Za-z ]+\)$' | sed -e 's|^open("\(.*\)", O_.* = [0-9]*$|\1|;s|^execve("\(.*\)", \[.*], 0x.* .*) = [0-9]*|\1|;s|^openat(AT_FDCWD, "\(.*\)", O_.*|\1|' | sort -u 5 | -------------------------------------------------------------------------------- /future/vzbuild/from-bundle.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ -f "$1/config.json" ] 4 | then 5 | txz=$(basename $1).txz 6 | sudo tar --numeric-owner -cJvf $txz -C $1 . 7 | mv $txz $(basename $1)-$(sha256sum $txz | cut -c 1-4).txz 8 | else 9 | echo >&2 Usage: foo {bundle-path} 10 | fi 11 | -------------------------------------------------------------------------------- /future/vzbuild/from-spec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | DIR=$1 4 | ROOT=$2 5 | if [ -z "$DIR" ] 6 | then 7 | echo >&2 DIR cannot be empty 8 | exit -1 9 | fi 10 | 11 | if ! [ -d "$ROOT" ] 12 | then 13 | echo >&2 ROOT must be a directory 14 | exit -2 15 | fi 16 | 17 | 18 | mkdir -p $1/rootfs 19 | sudo rsync -al $ROOT $DIR/rootfs --files-from=$DIR.spec 20 | 21 | -------------------------------------------------------------------------------- /vzmaster/kill.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ex -o pipefail 4 | container_id=$1 5 | pid=$(cat /run/opencontainer/chroots/$container_id/state.json | jshon -e init_process_pid -u) 6 | pgid=$(ps -o pgid="" $pid | awk '{print $1}') 7 | sudo kill -- -$pgid 8 | 9 | echo waiting for $pid to exit 10 | while [ -d /proc/$pid ] ; do sleep 1; done 11 | echo process $pid exited 12 | $(dirname $0)/runch delete $container_id 13 | -------------------------------------------------------------------------------- /future/vzbuild/strace/tap-snapshots/tap-bug.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`tap-bug.js TAP > bar 1`] = ` 9 | foo 10 | ` 11 | -------------------------------------------------------------------------------- /future/vzslave/src/vox_create.erl: -------------------------------------------------------------------------------- 1 | -module(vox_create). 2 | -compile(export_all). 3 | 4 | command(Args) -> 5 | lists:foldl(fun create/2,[],Args), 6 | {ok,?MODULE}. 7 | 8 | create(App,Acc) -> 9 | Name = filename:basename(App,".tgz"), 10 | vox:info("Unpack Container: ~p~n",[Name]), 11 | {ok,Bin} = file:read_file(App), 12 | erl_tar:extract({binary,zlib:gunzip(Bin)},[{cwd,lists:concat(["apps/",Name])}]). 13 | -------------------------------------------------------------------------------- /bootstrap/roles/mivok0.sudo/README.md: -------------------------------------------------------------------------------- 1 | # Simple sudo role 2 | 3 | This role sets up a simple sudoers file. Each user has full sudo access, and a 4 | global setting determines whether NOPASSWD is set or not. 5 | 6 | ## Variables 7 | 8 | * sudo_users - A list of users who have sudo access. Use '%foo' to specify 9 | that users in a given group have sudo access. 10 | * default: root, users in group wheel 11 | * sudo_nopasswd - if set, NOPASSWD is added to all sudoers entries. Use this 12 | when users don't have passwords set. 13 | * default: true 14 | -------------------------------------------------------------------------------- /future/vzbuild/strace/main.js: -------------------------------------------------------------------------------- 1 | const p = require('./parse') 2 | 3 | p 4 | .parseFileSync(process.argv[2]) 5 | .forEach(x => { 6 | const [pid, o] = x 7 | const [k] = Object.keys(o) 8 | 9 | const cb = 10 | { 'openat': x => 11 | { 12 | if ('ret' in x[5].complete) 13 | { 14 | console.log(x[1]) 15 | } 16 | } 17 | , 'execve': x => 18 | { 19 | if ('ret' in x[1].complete) 20 | { 21 | console.log(x[0]) 22 | } 23 | } 24 | } 25 | 26 | if (k in cb) 27 | { 28 | cb[k](o[k]) 29 | } 30 | }) 31 | -------------------------------------------------------------------------------- /bootstrap/bootstrap.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | user: root 4 | vars: 5 | vzexec: 6 | user: "{{ local_user.stdout }}" 7 | roles: 8 | - mivok0.sudo 9 | - geerlingguy.repo-epel 10 | pre_tasks: 11 | - package: state=present name=libselinux-python 12 | - name: get the username running the deploy 13 | local_action: command whoami 14 | register: local_user 15 | - ping: "" 16 | - user: name={{ vzexec.user }} state=present groups=wheel append=yes 17 | - authorized_key: user={{ vzexec.user }} key="{{ item }}" 18 | with_file: ./ssh.pub 19 | - authorized_key: user=root key="{{ item }}" 20 | with_file: ./ssh.pub 21 | 22 | -------------------------------------------------------------------------------- /bootstrap/roles/mivok0.sudo/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Mark Harrison 4 | description: Simple /etc/sudoers management role 5 | license: MIT 6 | min_ansible_version: 1.3 7 | platforms: 8 | - name: EL 9 | versions: 10 | - all 11 | - name: GenericUNIX 12 | versions: 13 | - all 14 | - any 15 | - name: Fedora 16 | versions: 17 | - all 18 | - name: opensuse 19 | versions: 20 | - all 21 | - name: Ubuntu 22 | versions: 23 | - all 24 | - name: SLES 25 | versions: 26 | - all 27 | - name: GenericLinux 28 | versions: 29 | - all 30 | - any 31 | - name: Debian 32 | versions: 33 | - all 34 | categories: 35 | - system 36 | dependencies: [] 37 | -------------------------------------------------------------------------------- /vzmaster/vzexec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | function cmd_ps 3 | { 4 | ps ax -o pgid,cmd | grep /home/$(whoami)/.vzexec | sed "s|/home/$(whoami)/.vzexec//bin/||g;s|/bin/bash ||;s|/home/$(whoami)/.vzexec/||;s|forever runch start bundles/||" | grep -vE "grep|sed" | sort -n -u 5 | } 6 | 7 | function cmd_mounts 8 | { 9 | grep -F /home/$(whoami) /proc/mounts | cut -f 2 -d ' ' | sed "s|/home/$(whoami)/.vzexec/bundles/\(.*\)/rootfs\(/.*\)\$|\1\t\2|" | column -t 10 | } 11 | 12 | function cmd_kill 13 | { 14 | echo Not implemented 15 | } 16 | 17 | 18 | set -e -o pipefail 19 | case $1 in 20 | ps|mounts) 21 | cmd_$1 $2 22 | ;; 23 | *) 24 | echo "Invalid command: $1" >&2 25 | echo "Available commands: ps mounts" >&2 26 | exit 27 | ;; 28 | esac 29 | -------------------------------------------------------------------------------- /future/vzbuild/strace-spec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e -o pipefail 3 | 4 | DIR=$(dirname $0) 5 | IN=$1 6 | ROOT=$2 7 | 8 | [ -d $2 ] || (echo "Argument $2 is not a dir" ; exit -1) 9 | 10 | function grep_nosys { 11 | grep -vE '^/(dev|sys|run|tmp|proc)/|^(/etc/ld.so.cache|/|/var/cache/ldconfig/aux-cache)$'; 12 | } 13 | 14 | ( 15 | node $DIR/dir-links.js <( 16 | ( 17 | cat $IN 18 | find -L /lib -maxdepth 1 -name 'libnss_files.so*' -or -name 'libnss_dns.so*' -or -name 'ld-linux.so*' -or -name 'libresolv.so*' 19 | find -L /etc -maxdepth 1 -name 'hosts' 20 | ) | grep_nosys 21 | ) $ROOT | grep_nosys 22 | 23 | cat <$1.parsed 8 | sudo ./strace-spec.sh $1.parsed $root >$1.spec 9 | sudo rm -r $1 || true 10 | ./from-spec.sh $1 $root 11 | sudo rm -rf ../../oci_bundles/$1/rootfs 12 | mv $1/rootfs ../../oci_bundles/$1 13 | rmdir $1 14 | ./from-bundle.sh ../../oci_bundles/$1 15 | local image=$1-*.txz 16 | if [ -f ../../vzbuild/images/$image ] 17 | then 18 | echo $image already exists 19 | rm $image 20 | return 21 | fi 22 | echo $image 23 | mv $image ../../vzmaster/images 24 | } 25 | 26 | set -e -o pipefail 27 | case $1 in 28 | update|foo) 29 | cmd_$1 $2 $3 30 | ;; 31 | *) 32 | echo "Invalid command: $1" >&2 33 | exit 34 | ;; 35 | esac 36 | -------------------------------------------------------------------------------- /future/vzbuild/shebang.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | 3 | var she = '#'.codePointAt(0) 4 | var bang = '!'.codePointAt(0) 5 | var slash = '/'.codePointAt(0) 6 | var lf = '\n'.codePointAt(0) 7 | var space = ' '.codePointAt(0) 8 | 9 | exports.check = function (fname) 10 | { 11 | if (!fs.lstatSync(fname).isFile()) 12 | { 13 | return null 14 | } 15 | var h = fs.openSync(fname, 0) 16 | if (!h) 17 | { 18 | return null 19 | } 20 | var b = Buffer.alloc(1024) 21 | b[0] = 0 22 | fs.readSync(h, b, 0, b.length) 23 | fs.closeSync(h) 24 | if (b[0] == she && b[1] == bang && b[2] == slash) 25 | { 26 | for (var i = 0; i < b.length; i++) 27 | { 28 | if (b[i] == space || b[i] == lf) break 29 | } 30 | 31 | return i < b.length ? b.slice(2, i).toString() : null 32 | } 33 | else 34 | { 35 | return null 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /future/vzbuild/archlinux/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | mkdir -p build/tmp-minstrap 5 | 6 | # minstrap.spec - a minimal pacstrap capable to install a normal pacstrap :) 7 | sudo ../strace-trace.sh build/tmp-minstrap.spec pacstrap -dc build/tmp-minstrap arch-install-scripts 8 | sudo chown $UID build/tmp-minstrap.spec 9 | echo /usr/bin/pacstrap >>build/tmp-minstrap.spec 10 | echo /usr/bin/busybox >>build/tmp-minstrap.spec 11 | echo /usr/bin/cat >>build/tmp-minstrap.spec 12 | grep -vE "build/tmp-1|^/var/cache/pacman/pkg/|^/var/lib/pacman/sync/|^/home/" build/tmp-minstrap.spec | sort -u -o build/minstrap.spec 13 | sudo rsync -al / build/minstrap --files-from=build/minstrap.spec 14 | # docker run --rm -v $(readlink -m ../newroot):/root -v /var/lib/pacman/sync:/root/var/lib/pacman/sync -v /var/cache/pacman/pkg:/var/cache/pacman/pkg minstrap bash /root/run.sh 15 | -------------------------------------------------------------------------------- /future/vzslave/src/vox_start.erl: -------------------------------------------------------------------------------- 1 | -module(vox_start). 2 | -compile(export_all). 3 | 4 | command(Args) -> {ok,lists:map(fun start/1,Args)}. 5 | 6 | start(App) -> 7 | vox:info("App: ~p~n",[App]), 8 | Dir = filename:join(["apps", App]), 9 | {ok,Bin} = file:read_file(filename:join([Dir, "config.json"])), 10 | {Json } = jsone:decode(Bin), 11 | {Process} = proplists:get_value(<<"process">>,Json), 12 | Args = proplists:get_value(<<"args">>,Process), 13 | {User} = proplists:get_value(<<"user">>,Process), 14 | Uid = proplists:get_value(<<"uid">>,User,0), 15 | Gid = proplists:get_value(<<"gid">>,User,0), 16 | UserSpec = lists:flatten(io_lib:format("--userspec=~p:~p", [Uid,Gid])), 17 | Concat = ["chroot",UserSpec,"rootfs"] ++ lists:map(fun(X) -> binary_to_list(X) end,Args), 18 | vox:info("Oneliner: ~p~n",[Concat]), 19 | {_,R,S} = sh:run(Concat,<<"log">>,Dir), 20 | {ret(R),S}. 21 | 22 | ret(0) -> ok; 23 | ret(_) -> error. 24 | -------------------------------------------------------------------------------- /future/vzbuild/archlinux/openssl-nano/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: andy.melnikov@gmail.com 2 | pkgname=openssl-nano 3 | pkgver=0.1 4 | pkgrel=1 5 | epoch= 6 | pkgdesc="" 7 | arch=(i686) 8 | url="" 9 | license=('GPL') 10 | groups=() 11 | depends=('zlib') 12 | makedepends=('openssl') 13 | checkdepends=() 14 | optdepends=() 15 | provides=(openssl) 16 | conflicts=(openssl) 17 | replaces=() 18 | backup=() 19 | options=() 20 | install= 21 | changelog= 22 | source=() 23 | 24 | noextract=() 25 | md5sums=() 26 | validpgpkeys=() 27 | 28 | prepare() { 29 | cd 30 | #cd "$pkgname-$pkgver" 31 | #patch -p1 -i "$srcdir/$pkgname-$pkgver.patch" 32 | } 33 | 34 | build() { 35 | cd 36 | #cd "$pkgname-$pkgver" 37 | #./configure --prefix=/usr 38 | #make 39 | } 40 | 41 | check() { 42 | cd 43 | #cd "$pkgname-$pkgver" 44 | #make -k check 45 | } 46 | 47 | package() { 48 | cd 49 | tar --numeric-owner --xattrs --acls -cJvf openssl.txz -C / $(pacman -Qlq openssl | grep -Ev '/$|man|include|pkgconfig|misc|bin' | xargs) 50 | tar -xJvf openssl.txz -C $pkgdir 51 | 52 | } 53 | 54 | 55 | -------------------------------------------------------------------------------- /bootstrap/roles/mivok0.sudo/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 Mark Harrison 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /future/vzbuild/archlinux/erlang-nano/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: andy.melnikov@gmail.com 2 | pkgname=erlang-nano 3 | pkgver=0.1 4 | pkgrel=1 5 | epoch= 6 | pkgdesc="" 7 | arch=(i686) 8 | url="" 9 | license=('GPL') 10 | groups=() 11 | depends=('zlib' 'ncurses' 'coreutils') 12 | makedepends=('erlang-nox') 13 | checkdepends=() 14 | optdepends=() 15 | provides=() 16 | conflicts=() 17 | replaces=() 18 | backup=() 19 | options=() 20 | install= 21 | changelog= 22 | source=(escript) 23 | 24 | noextract=() 25 | md5sums=(SKIP) 26 | validpgpkeys=() 27 | 28 | prepare() { 29 | cd 30 | #cd "$pkgname-$pkgver" 31 | #patch -p1 -i "$srcdir/$pkgname-$pkgver.patch" 32 | } 33 | 34 | build() { 35 | cd 36 | #cd "$pkgname-$pkgver" 37 | #./configure --prefix=/usr 38 | #make 39 | } 40 | 41 | check() { 42 | cd 43 | #cd "$pkgname-$pkgver" 44 | #make -k check 45 | } 46 | 47 | package() { 48 | pkgdir2=$pkgdir/usr/lib/$pkgname 49 | mkdir -p $pkgdir2/{bin,lib/{kernel-4.1,stdlib-2.6}} 50 | cp /usr/lib/erlang/erts-7.1/bin/beam.smp $pkgdir2/bin 51 | cp /usr/lib/erlang/bin/start_clean.boot $pkgdir2/bin/start.boot 52 | cp -r /usr/lib/erlang/lib/kernel-4.1/ebin $pkgdir2/lib/kernel-4.1 53 | cp -r /usr/lib/erlang/lib/stdlib-2.6/ebin $pkgdir2/lib/stdlib-2.6 54 | mkdir -p $pkgdir/usr/bin 55 | cp escript $pkgdir/usr/bin 56 | } 57 | -------------------------------------------------------------------------------- /future/vzbuild/ldd-chroot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Author: https://tetsumaki.net/blog/article/2013-06-11-creation-dun-environnement-chroot-arch-linux.html 3 | 4 | # Utilisation: $0 5 | rep="$1" 6 | shift 7 | 8 | # Copie $1 vers $2 en créant les répertoires parents. 9 | copie_dir () 10 | { 11 | [ -e "${2}" ] && return 12 | rep_base=$(dirname "${2}") 13 | [ -d "${rep_base}" ] || { 14 | echo "++ mkdir -p ${rep_base}" 15 | mkdir -p "${rep_base}" 16 | } 17 | echo "+ cp -a $1 $2" 18 | cp -a "$1" "$2" 19 | } 20 | 21 | # Copie $1 vers $2 + copie des bibliothèques utilisées. 22 | copie_ldd () 23 | { 24 | local src dest file f f_link 25 | src="$1" 26 | dest="$2" 27 | [ -e "${dest}" ] && return 28 | file=( $(ldd "$src" | awk '{print $3}' | grep '^/') ) 29 | file=( "${file[@]}" $(ldd "$src" | grep '/' | grep -v '=>' | awk '{print $1}') ) 30 | for f in "${file[@]}" 31 | do 32 | f_link=$(readlink -f "$f") 33 | copie_dir "$f_link" "${rep}${f}" 34 | done 35 | copie_dir "$src" "${dest}" 36 | } 37 | 38 | for prog in "$@" 39 | do 40 | prog=$(which "$prog") || $prog 41 | prog_real=$(readlink -f "$prog") 42 | copie_ldd "$prog_real" "${rep}${prog}" 43 | done 44 | 45 | mkdir $rep/{tmp,dev,sys,proc,run,etc,var/{tmp,cache,db,run,log}} 46 | touch $rep/etc/resolv.conf 47 | -------------------------------------------------------------------------------- /vzmaster/vzmaster.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | function cmd_push 3 | { 4 | local image=$1 5 | if [ -z "$image" ] 6 | then 7 | echo "push: image cannot be empty" >&2 8 | exit 9 | fi 10 | 11 | if [ -f images/$image.txz ] 12 | then 13 | true 14 | else 15 | echo "push: images/$image.txz doesn't exist" >&2 16 | exit 17 | fi 18 | echo '{ "vzexec" : {} }' | jshon -e vzexec -s "/home/$USER/.vzexec/" -i path -s "$image" -i image -p >tmp-push.json 19 | ansible-playbook -e @tmp-push.json vzmaster-push.yaml 20 | } 21 | 22 | function cmd_start 23 | { 24 | local image=$1 25 | if [ -z "$image" ] 26 | then 27 | echo "start: image cannot be empty" >&2 28 | exit -2 29 | fi 30 | 31 | if [ -f images/$image.txz ] 32 | then 33 | true 34 | else 35 | echo "start: images/$image.txz doesn't exist" >&2 36 | exit -1 37 | fi 38 | echo '{ "vzexec" : {} }' | jshon -e vzexec -s "/home/$USER/.vzexec/" -i path -s "$image" -i image -p >tmp-start.json 39 | ansible-playbook -e @tmp-start.json vzmaster-start.yaml 40 | } 41 | 42 | function cmd_kill 43 | { 44 | local container_id=$1 45 | echo '{ "vzexec" : {} }' | jshon -e vzexec -s "/home/$USER/.vzexec" -i path -s "$container_id" -i container_id -p >tmp-kill.json 46 | ansible-playbook -e @tmp-kill.json vzmaster-kill.yaml 47 | } 48 | 49 | set -ex 50 | case $1 in 51 | push|start|kill) 52 | cmd_$1 $2 53 | ;; 54 | *) 55 | echo "Invalid command: $1" >&2 56 | exit 57 | ;; 58 | esac 59 | -------------------------------------------------------------------------------- /oci_bundles/gearmand.spec: -------------------------------------------------------------------------------- 1 | /bin 2 | /dev 3 | /etc/gai.conf 4 | /etc/gearmand.conf 5 | /etc/resolv.conf 6 | /lib 7 | /mnt 8 | /opt 9 | /proc 10 | /run 11 | /sbin 12 | /srv 13 | /sys 14 | /tmp 15 | /usr/bin/gearmand 16 | /usr/lib/ld-2.23.so 17 | /usr/lib/ld-linux.so.2 18 | /usr/lib/libboost_program_options.so.1.60.0 19 | /usr/lib/libc-2.23.so 20 | /usr/lib/libc.so.6 21 | /usr/lib/libcom_err.so.2 22 | /usr/lib/libcom_err.so.2.1 23 | /usr/lib/libcrypto.so.1.0.0 24 | /usr/lib/libdl-2.23.so 25 | /usr/lib/libdl.so.2 26 | /usr/lib/libevent-2.0.so.5 27 | /usr/lib/libevent-2.0.so.5.1.10 28 | /usr/lib/libgcc_s.so.1 29 | /usr/lib/libgssapi_krb5.so.2 30 | /usr/lib/libgssapi_krb5.so.2.2 31 | /usr/lib/libhiredis.so.0.13 32 | /usr/lib/libk5crypto.so.3 33 | /usr/lib/libk5crypto.so.3.1 34 | /usr/lib/libkeyutils.so.1 35 | /usr/lib/libkeyutils.so.1.5 36 | /usr/lib/libkrb5.so.3 37 | /usr/lib/libkrb5.so.3.3 38 | /usr/lib/libkrb5support.so.0 39 | /usr/lib/libkrb5support.so.0.1 40 | /usr/lib/libm-2.23.so 41 | /usr/lib/libm.so.6 42 | /usr/lib/libmysqlclient.so.18 43 | /usr/lib/libmysqlclient.so.18.0.0 44 | /usr/lib/libpq.so.5 45 | /usr/lib/libpq.so.5.8 46 | /usr/lib/libpthread-2.23.so 47 | /usr/lib/libpthread.so.0 48 | /usr/lib/libresolv-2.23.so 49 | /usr/lib/libresolv.so.2 50 | /usr/lib/librt-2.23.so 51 | /usr/lib/librt.so.1 52 | /usr/lib/libsqlite3.so.0 53 | /usr/lib/libsqlite3.so.0.8.6 54 | /usr/lib/libssl.so.1.0.0 55 | /usr/lib/libstdc++.so.6 56 | /usr/lib/libstdc++.so.6.0.21 57 | /usr/lib/libz.so.1 58 | /usr/lib/libz.so.1.2.8 59 | /usr/sbin 60 | -------------------------------------------------------------------------------- /future/vzbuild/strace/grammar.js: -------------------------------------------------------------------------------- 1 | const p = require('panda-grammar') 2 | 3 | const re = (x) => p.re(x) 4 | const nat = re(/^\d+/) 5 | const neg = re(/^-\d+/) 6 | const name = re(/^\d+/) 7 | const cstring = p.re(/^".*?"/) 8 | const proj = (nums, matcher) => p.rule(matcher, x => nums.length == 1 9 | ? x.value[nums[0]] 10 | : nums.map(idx => x.value[idx])) 11 | const ignore = x => p.rule(x, _ => null) 12 | const mode = p.re(/^, (0\d{3}|000)/) 13 | 14 | const retVal = p.any 15 | ( p.tag("ret", nat) 16 | , p.tag("err", proj([0,2,4], p.all(neg, p.ws, p.word, p.ws, p.re(/\(.*?\)/)))) 17 | ) 18 | const completion = p.any 19 | ( p.tag("complete", proj([4], p.all(p.string(')'), p.ws, p.string('='), p.ws, retVal))) 20 | , p.tag("unfinished", ignore(p.string(' '))) 21 | ) 22 | const openat = proj([2, 5, 8, 9, 10, 11], p.all(p.string('openat'), p.string('('), p.word, p.string(','), p.ws, cstring, p.string(','), p.ws, p.word,p.optional(p.many(p.all(p.string('|'),p.word))), p.optional(mode), completion)) 23 | 24 | const execve = proj([1, 3], p.all(p.string("execve("), cstring, re(/.*? vars \*\//), completion)) 25 | 26 | exports.parse2 = proj([0, 2], p.all( 27 | nat, 28 | p.ws, 29 | p.any 30 | ( p.tag('openat', openat) 31 | , p.tag('execve', execve) 32 | , p.tag('signal', ignore(re(/^--- SIG\w+ {.*} ---$/))) 33 | , p.tag('exit', ignore(p.string('+++ exited with 0 +++'))) 34 | , p.tag('resumed', proj([1, 3], p.all 35 | ( p.string('<... ') 36 | , p.word 37 | , p.string(' resumed> ) = ') 38 | , retVal))) 39 | ) 40 | )) 41 | 42 | exports.parse = p.grammar(exports.parse2) 43 | 44 | -------------------------------------------------------------------------------- /future/vzbuild/dir-links.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var assert = require('assert') 4 | 5 | var shebang = require('./shebang') 6 | 7 | assert.equal(process.argv.length, 4, "2 arguments are required") 8 | 9 | var f = fs.readFileSync(process.argv[2], {encoding:'utf-8'}).split('\n') 10 | f.pop() 11 | 12 | var l = {} 13 | 14 | 15 | 16 | var SRC = process.argv[3] 17 | 18 | console.error({SRC}) 19 | 20 | function die(varargs) 21 | { 22 | console.error.apply(null, arguments) 23 | process.exit(-1) 24 | } 25 | 26 | 27 | function resolve(src) 28 | { 29 | if (!fs.existsSync(path.join(SRC, src))) 30 | { 31 | die("ERR3: Broken file list: %s doesn't exist", src) 32 | } 33 | 34 | var d = path.relative(SRC, path.join(SRC, src)) 35 | var p = d.split('/').reduce(function (p, comp) 36 | { 37 | assert.notEqual(comp, '') 38 | var np = path.join(p, comp) 39 | var fullP = path.join(SRC, np) 40 | 41 | if (!fs.existsSync(fullP)) 42 | { 43 | die("ERR1: Broken file list: %s doesn't exist", fullP) 44 | } 45 | 46 | if (fs.lstatSync(fullP).isSymbolicLink()) 47 | { 48 | console.log(path.join('/', np)) 49 | const ld = fs.readlinkSync(fullP) 50 | const rr = path.join('/', path.relative(SRC, path.resolve(SRC, p, ld))) 51 | resolve(rr) 52 | return rr 53 | } 54 | else 55 | { 56 | return np 57 | } 58 | }, '') 59 | 60 | 61 | const pp = path.join(SRC, p) 62 | if (!fs.existsSync(pp)) 63 | { 64 | die("ERR2: Broken file list: %s doesn't exist", pp) 65 | } 66 | 67 | console.log(path.join('/', p)) 68 | var sb = shebang.check(pp) 69 | if (sb != null) 70 | { 71 | resolve(sb) 72 | } 73 | } 74 | 75 | // resolve('/lib/libutil.so') 76 | 77 | f.forEach(resolve) 78 | // 79 | 80 | -------------------------------------------------------------------------------- /future/vzbuild/strace/parse.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const grammar = require('./grammar') 3 | 4 | exports.parseFileSync = fileName => exports.parseArray( 5 | fs 6 | .readFileSync(fileName, 'utf8') 7 | .split('\n') 8 | .filter(x => x != '') 9 | ) 10 | 11 | exports.parseArray = lineArray => { 12 | 13 | const unfinished = {} 14 | 15 | const mapFn = (x) => { 16 | const [pid, o] = grammar.parse(x) 17 | const suspend = (co) => 18 | { 19 | const [kk] = Object.keys(co) 20 | if (kk == 'unfinished') 21 | { 22 | if (pid in unfinished) 23 | { 24 | throw new Error("double unfinished!") 25 | } 26 | unfinished[pid] = o 27 | return true 28 | } 29 | else 30 | { 31 | return false 32 | } 33 | } 34 | 35 | const [k] = Object.keys(o) 36 | const v = o[k] 37 | 38 | switch (k) 39 | { 40 | case 'execve': 41 | const [path, co] = v 42 | suspend(co) 43 | break; 44 | case 'openat': 45 | { 46 | const co = v[5] 47 | if (suspend(co)) 48 | { 49 | return null 50 | } 51 | } 52 | case 'exit': 53 | case 'signal': 54 | break; 55 | case 'resumed': 56 | const [call, ret] = v 57 | 58 | if (('unfinished' in ret)) { 59 | throw new Error('unfinished resume!') 60 | } 61 | const oo = unfinished[pid] 62 | // console.log(oo) 63 | const [kkk] = Object.keys(oo) 64 | switch (kkk) { 65 | case 'execve': 66 | oo.execve[1] = { 'complete' : ret } 67 | return [pid, oo] 68 | case 'openat': 69 | oo.openat[5] = { 'complete' : ret } 70 | return [pid, oo] 71 | } 72 | 73 | break; 74 | default: 75 | console.log(o) 76 | process.exit() 77 | } 78 | return [pid, o] 79 | } 80 | 81 | return lineArray 82 | .map(mapFn) 83 | .filter(x => x != null) 84 | } 85 | -------------------------------------------------------------------------------- /oci_bundles/gearmand/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ociVersion": "0.3.0", 3 | "platform": { 4 | "os": "linux", 5 | "arch": "386" 6 | }, 7 | "process": { 8 | "user": { 9 | "uid": 1002, 10 | "gid": 1002 11 | }, 12 | "args": [ 13 | "/usr/bin/gearmand", "-L", "127.0.0.1" 14 | ] 15 | , "cwd" : "/" 16 | }, 17 | "root": { 18 | "path": "rootfs" 19 | }, 20 | "mounts": [ 21 | { 22 | "destination": "/proc", 23 | "type": "proc", 24 | "source": "proc" 25 | }, 26 | { 27 | "destination": "/dev", 28 | "type": "tmpfs", 29 | "source": "tmpfs", 30 | "options": [ 31 | "nosuid", 32 | "strictatime", 33 | "mode=755", 34 | "size=65536k" 35 | ] 36 | }, 37 | { 38 | "destination": "/dev/pts", 39 | "type": "devpts", 40 | "source": "devpts", 41 | "options": [ 42 | "nosuid", 43 | "noexec", 44 | "newinstance", 45 | "ptmxmode=0666", 46 | "mode=0620", 47 | "gid=5" 48 | ] 49 | }, 50 | { 51 | "destination": "/dev/shm", 52 | "type": "tmpfs", 53 | "source": "shm", 54 | "options": [ 55 | "nosuid", 56 | "noexec", 57 | "nodev", 58 | "mode=1777", 59 | "size=65536k" 60 | ] 61 | }, 62 | { 63 | "destination": "/dev/mqueue", 64 | "type": "mqueue", 65 | "source": "mqueue", 66 | "options": [ 67 | "nosuid", 68 | "noexec", 69 | "nodev" 70 | ] 71 | }, 72 | { 73 | "destination": "/sys", 74 | "type": "sysfs", 75 | "source": "sysfs", 76 | "options": [ 77 | "nosuid", 78 | "noexec", 79 | "nodev" 80 | ] 81 | }, 82 | { 83 | "destination": "/sys/fs/cgroup", 84 | "type": "cgroup", 85 | "source": "cgroup", 86 | "options": [ 87 | "nosuid", 88 | "noexec", 89 | "nodev", 90 | "relatime", 91 | "ro" 92 | ] 93 | } 94 | ] 95 | } 96 | -------------------------------------------------------------------------------- /oci_bundles/beanstalkd/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ociVersion": "0.3.0", 3 | "platform": { 4 | "os": "linux", 5 | "arch": "386" 6 | }, 7 | "process": { 8 | "user": { 9 | "uid": 1000, 10 | "gid": 1000 11 | }, 12 | "args": [ 13 | "/usr/bin/beanstalkd", "-l", "127.0.0.1", "-V" 14 | ] 15 | , "cwd" : "/" 16 | }, 17 | "root": { 18 | "path": "rootfs" 19 | }, 20 | "mounts": [ 21 | { 22 | "destination": "/proc", 23 | "type": "proc", 24 | "source": "proc" 25 | }, 26 | { 27 | "destination": "/dev", 28 | "type": "tmpfs", 29 | "source": "tmpfs", 30 | "options": [ 31 | "nosuid", 32 | "strictatime", 33 | "mode=755", 34 | "size=65536k" 35 | ] 36 | }, 37 | { 38 | "destination": "/dev/pts", 39 | "type": "devpts", 40 | "source": "devpts", 41 | "options": [ 42 | "nosuid", 43 | "noexec", 44 | "newinstance", 45 | "ptmxmode=0666", 46 | "mode=0620", 47 | "gid=5" 48 | ] 49 | }, 50 | { 51 | "destination": "/dev/shm", 52 | "type": "tmpfs", 53 | "source": "shm", 54 | "options": [ 55 | "nosuid", 56 | "noexec", 57 | "nodev", 58 | "mode=1777", 59 | "size=65536k" 60 | ] 61 | }, 62 | { 63 | "destination": "/dev/mqueue", 64 | "type": "mqueue", 65 | "source": "mqueue", 66 | "options": [ 67 | "nosuid", 68 | "noexec", 69 | "nodev" 70 | ] 71 | }, 72 | { 73 | "destination": "/sys", 74 | "type": "sysfs", 75 | "source": "sysfs", 76 | "options": [ 77 | "nosuid", 78 | "noexec", 79 | "nodev" 80 | ] 81 | }, 82 | { 83 | "destination": "/sys/fs/cgroup", 84 | "type": "cgroup", 85 | "source": "cgroup", 86 | "options": [ 87 | "nosuid", 88 | "noexec", 89 | "nodev", 90 | "relatime", 91 | "ro" 92 | ] 93 | } 94 | ] 95 | } 96 | -------------------------------------------------------------------------------- /future/vzslave/src/vox.erl: -------------------------------------------------------------------------------- 1 | -module(vox). 2 | -author('Andy Melnikov'). 3 | -include("vox.hrl"). 4 | -compile(export_all). 5 | -export([main/1]). 6 | 7 | main([]) -> help(); 8 | main(Params) -> 9 | {Other,FP} = fold_params(Params), 10 | unknown(Other), 11 | return(errors(lists:flatten(lists:foldl(fun (_,Errors) when length(Errors) > 0 -> Errors; 12 | ({Name,Par},Errors) -> [return(Name:command(Par))|Errors] end, [], FP)))). 13 | 14 | unknown([]) -> skip; 15 | unknown(Other) -> info("Unknown Command or Parameter ~p~n",[Other]), help(). 16 | 17 | errors(L) when length(L) == 0 -> false; 18 | errors(L) -> info("Errors: ~p~n",[L]), true. 19 | 20 | return(true) -> 1; 21 | return(false) -> 0; 22 | return({ok,L}) -> info("Command: ~p~n",[L]), []; 23 | return(X) -> X. 24 | 25 | help(Reason, Data) -> help(io_lib:format("~s ~p", [Reason, Data])). 26 | help(Msg) -> info("Error: ~s~n~n", [Msg]), help(). 27 | help() -> info("VOX Container Tool version ~s~n",[?VERSION]), 28 | info("BNF: ~n"), 29 | info(" invoke := vox params~n"), 30 | info(" params := [] | run params ~n"), 31 | info(" run := command [ options ]~n"), 32 | info(" command := create [container.tgz] | start | stop~n"), 33 | return(false). 34 | 35 | info(Format) -> io:format(lists:concat([Format,"\r"])). 36 | info(Format,Args) -> io:format(lists:concat([Format,"\r"]),Args). 37 | 38 | plugin(X) -> plugin(X,lists:member(list_to_atom(X),plugins())). 39 | plugin(X,true) -> list_to_atom(lists:concat(['vox_',X])); 40 | plugin(X,false) -> X. 41 | 42 | plugins() -> application:get_env(vox,plugins,[create,start,stop]). 43 | plugins([],N) -> N; 44 | plugins([H|T],N) -> plugins(T,[plugin(H)|N]). 45 | 46 | fold_params(Params) -> 47 | Atomized = plugins(Params,[]), 48 | lists:foldl(fun(X,{Current,Result}) -> 49 | case X of 50 | X when is_atom(X) -> {[],[{X,Current}|Result]}; 51 | E -> {[E|Current],Result} end 52 | end, {[],[]}, Atomized). 53 | -------------------------------------------------------------------------------- /future/vzbuild/strace/t/grammar.js: -------------------------------------------------------------------------------- 1 | const tap = require('tap') 2 | const grammar = require('../grammar') 3 | 4 | const parse = grammar.parse 5 | 6 | tap.plan(13) 7 | tap.matchSnapshot 8 | ( parse('13954 openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3') 9 | , '001 - 2 flags' 10 | ) 11 | 12 | tap.matchSnapshot 13 | ( parse('14802 openat(AT_FDCWD, "/proc/self/mountinfo", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3') 14 | , '002 - 3 flags' 15 | ) 16 | 17 | tap.matchSnapshot 18 | ( parse('13954 openat(AT_FDCWD, "/usr/lib/tls/libtinfo.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)') 19 | , '003 - ENOENT' 20 | ) 21 | 22 | tap.matchSnapshot 23 | ( parse('13955 +++ exited with 0 +++') 24 | , '004 - exit' 25 | ) 26 | 27 | tap.matchSnapshot 28 | ( parse('13954 openat(AT_FDCWD, "/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = -1 ENOENT (No such file or directory)') 29 | , '005 - 1 flag' 30 | ) 31 | 32 | tap.matchSnapshot 33 | ( parse('13954 openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3') 34 | , '006 - mode' 35 | ) 36 | 37 | tap.matchSnapshot 38 | ( parse('13966 openat(AT_FDCWD, "/home/andy/dev/nano-pacstrap32/newroot/var/lib/pacman/db.lck", O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE|O_CLOEXEC, 000) = 4') 39 | , '007 - 000 mode' 40 | ) 41 | 42 | tap.matchSnapshot 43 | ( parse('14005 openat(AT_FDCWD, "/proc/self/fd", O_RDONLY|O_LARGEFILE|O_DIRECTORY ') 44 | , '008 - unfinished' 45 | ) 46 | 47 | tap.matchSnapshot 48 | ( parse('14005 <... openat resumed> ) = 11') 49 | , '009 - resumed' 50 | ) 51 | 52 | tap.matchSnapshot 53 | ( parse('13954 execve("/usr/bin/setarch", ["setarch", "i686", "pacstrap", "-dc", "newroot", "pacman", "archlinux32-keyring"], 0xbf9e18bc /* 14 vars */) = 0') 54 | , '010 - execve' 55 | ) 56 | 57 | tap.matchSnapshot 58 | ( parse('13977 execve("/usr/bin/gpgsm", ["/usr/bin/gpgsm", "--version"], 0x1083be0 /* 18 vars */ ') 59 | , '011 - execve unfinished' 60 | ) 61 | 62 | tap.matchSnapshot 63 | ( parse('13966 --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=13966, si_uid=0} ---') 64 | , '012 - signal' 65 | ) 66 | 67 | tap.pass("should reach end of file") 68 | 69 | -------------------------------------------------------------------------------- /oci_bundles/busybox-static/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ociVersion": "0.5.0-dev", 3 | "platform": { 4 | "os": "linux", 5 | "arch": "386" 6 | }, 7 | "process": { 8 | "terminal": true, 9 | "user": {}, 10 | "args": [ 11 | "sh" 12 | ], 13 | "env": [ 14 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 15 | "TERM=xterm" 16 | ], 17 | "cwd": "/", 18 | "capabilities": [ 19 | "CAP_AUDIT_WRITE", 20 | "CAP_KILL", 21 | "CAP_NET_BIND_SERVICE" 22 | ], 23 | "rlimits": [ 24 | { 25 | "type": "RLIMIT_NOFILE", 26 | "hard": 1024, 27 | "soft": 1024 28 | } 29 | ], 30 | "noNewPrivileges": true 31 | }, 32 | "root": { 33 | "path": "rootfs", 34 | "readonly": true 35 | }, 36 | "hostname": "runc", 37 | "mounts": [ 38 | { 39 | "destination": "/proc", 40 | "type": "proc", 41 | "source": "proc" 42 | }, 43 | { 44 | "destination": "/dev", 45 | "type": "tmpfs", 46 | "source": "tmpfs", 47 | "options": [ 48 | "nosuid", 49 | "strictatime", 50 | "mode=755", 51 | "size=65536k" 52 | ] 53 | }, 54 | { 55 | "destination": "/dev/pts", 56 | "type": "devpts", 57 | "source": "devpts", 58 | "options": [ 59 | "nosuid", 60 | "noexec", 61 | "newinstance", 62 | "ptmxmode=0666", 63 | "mode=0620", 64 | "gid=5" 65 | ] 66 | }, 67 | { 68 | "destination": "/dev/shm", 69 | "type": "tmpfs", 70 | "source": "shm", 71 | "options": [ 72 | "nosuid", 73 | "noexec", 74 | "nodev", 75 | "mode=1777", 76 | "size=65536k" 77 | ] 78 | }, 79 | { 80 | "destination": "/dev/mqueue", 81 | "type": "mqueue", 82 | "source": "mqueue", 83 | "options": [ 84 | "nosuid", 85 | "noexec", 86 | "nodev" 87 | ] 88 | }, 89 | { 90 | "destination": "/sys", 91 | "type": "sysfs", 92 | "source": "sysfs", 93 | "options": [ 94 | "nosuid", 95 | "noexec", 96 | "nodev", 97 | "ro" 98 | ] 99 | }, 100 | { 101 | "destination": "/sys/fs/cgroup", 102 | "type": "cgroup", 103 | "source": "cgroup", 104 | "options": [ 105 | "nosuid", 106 | "noexec", 107 | "nodev", 108 | "relatime", 109 | "ro" 110 | ] 111 | } 112 | ], 113 | "hooks": {}, 114 | "linux": { 115 | "resources": { 116 | "devices": [ 117 | { 118 | "allow": false, 119 | "access": "rwm" 120 | } 121 | ] 122 | }, 123 | "namespaces": [ 124 | { 125 | "type": "pid" 126 | }, 127 | { 128 | "type": "network" 129 | }, 130 | { 131 | "type": "ipc" 132 | }, 133 | { 134 | "type": "uts" 135 | }, 136 | { 137 | "type": "mount" 138 | } 139 | ], 140 | "maskedPaths": [ 141 | "/proc/kcore", 142 | "/proc/latency_stats", 143 | "/proc/timer_stats", 144 | "/proc/sched_debug" 145 | ], 146 | "readonlyPaths": [ 147 | "/proc/asound", 148 | "/proc/bus", 149 | "/proc/fs", 150 | "/proc/irq", 151 | "/proc/sys", 152 | "/proc/sysrq-trigger" 153 | ] 154 | } 155 | } -------------------------------------------------------------------------------- /future/vzbuild/strace/tap-snapshots/t-grammar-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`t/grammar TAP > 001 - 2 flags 1`] = ` 9 | [ '13954', 10 | { openat: 11 | [ 'AT_FDCWD', 12 | '"/etc/ld.so.cache"', 13 | 'O_RDONLY', 14 | [ [ '|', 'O_CLOEXEC' ] ], 15 | undefined, 16 | { complete: { ret: '3' } } ] } ] 17 | ` 18 | 19 | exports[`t/grammar TAP > 002 - 3 flags 1`] = ` 20 | [ '14802', 21 | { openat: 22 | [ 'AT_FDCWD', 23 | '"/proc/self/mountinfo"', 24 | 'O_RDONLY', 25 | [ [ '|', 'O_LARGEFILE' ], [ '|', 'O_CLOEXEC' ] ], 26 | undefined, 27 | { complete: { ret: '3' } } ] } ] 28 | ` 29 | 30 | exports[`t/grammar TAP > 003 - ENOENT 1`] = ` 31 | [ '13954', 32 | { openat: 33 | [ 'AT_FDCWD', 34 | '"/usr/lib/tls/libtinfo.so.6"', 35 | 'O_RDONLY', 36 | [ [ '|', 'O_CLOEXEC' ] ], 37 | undefined, 38 | { complete: { err: [ '-1', 'ENOENT', '(No such file or directory)' ] } } ] } ] 39 | ` 40 | 41 | exports[`t/grammar TAP > 004 - exit 1`] = ` 42 | [ '13955', { exit: null } ] 43 | ` 44 | 45 | exports[`t/grammar TAP > 005 - 1 flag 1`] = ` 46 | [ '13954', 47 | { openat: 48 | [ 'AT_FDCWD', 49 | '"/usr/lib/gconv/gconv-modules.cache"', 50 | 'O_RDONLY', 51 | undefined, 52 | undefined, 53 | { complete: { err: [ '-1', 'ENOENT', '(No such file or directory)' ] } } ] } ] 54 | ` 55 | 56 | exports[`t/grammar TAP > 006 - mode 1`] = ` 57 | [ '13954', 58 | { openat: 59 | [ 'AT_FDCWD', 60 | '"/dev/null"', 61 | 'O_WRONLY', 62 | [ [ '|', 'O_CREAT' ], 63 | [ '|', 'O_TRUNC' ], 64 | [ '|', 'O_LARGEFILE' ] ], 65 | ', 0666', 66 | { complete: { ret: '3' } } ] } ] 67 | ` 68 | 69 | exports[`t/grammar TAP > 007 - 000 mode 1`] = ` 70 | [ '13966', 71 | { openat: 72 | [ 'AT_FDCWD', 73 | '"/home/andy/dev/nano-pacstrap32/newroot/var/lib/pacman/db.lck"', 74 | 'O_WRONLY', 75 | [ [ '|', 'O_CREAT' ], 76 | [ '|', 'O_EXCL' ], 77 | [ '|', 'O_LARGEFILE' ], 78 | [ '|', 'O_CLOEXEC' ] ], 79 | ', 000', 80 | { complete: { ret: '4' } } ] } ] 81 | ` 82 | 83 | exports[`t/grammar TAP > 008 - unfinished 1`] = ` 84 | [ '14005', 85 | { openat: 86 | [ 'AT_FDCWD', 87 | '"/proc/self/fd"', 88 | 'O_RDONLY', 89 | [ [ '|', 'O_LARGEFILE' ], [ '|', 'O_DIRECTORY' ] ], 90 | undefined, 91 | { unfinished: null } ] } ] 92 | ` 93 | 94 | exports[`t/grammar TAP > 009 - resumed 1`] = ` 95 | [ '14005', { resumed: [ 'openat', { ret: '11' } ] } ] 96 | ` 97 | 98 | exports[`t/grammar TAP > 010 - execve 1`] = ` 99 | [ '13954', 100 | { execve: [ '"/usr/bin/setarch"', { complete: { ret: '0' } } ] } ] 101 | ` 102 | 103 | exports[`t/grammar TAP > 011 - execve unfinished 1`] = ` 104 | [ '13977', 105 | { execve: [ '"/usr/bin/gpgsm"', { unfinished: null } ] } ] 106 | ` 107 | 108 | exports[`t/grammar TAP > 012 - signal 1`] = ` 109 | [ '13966', { signal: null } ] 110 | ` 111 | -------------------------------------------------------------------------------- /runch/runch.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | chroot_add_mount() { 4 | sudo mount "$@" && CHROOT_ACTIVE_MOUNTS=("$2" "${CHROOT_ACTIVE_MOUNTS[@]}") 5 | } 6 | 7 | parse() { 8 | set +x 9 | local bundle=$1 10 | local default=$2 11 | shift 12 | shift 13 | jshon -QF $bundle/config.json $* || echo $default 14 | } 15 | 16 | function cmd_start 17 | { 18 | set -ex 19 | local bundle=$1 20 | if [ -z "$bundle" ] 21 | then 22 | echo "list: bundle cannot be empty" >&2 23 | exit 24 | fi 25 | 26 | if [ -f $bundle/config.json ] 27 | then 28 | true 29 | else 30 | echo "$bundle/config.json doesn't exist" >&2 31 | exit 32 | fi 33 | local jshon="jshon -F $bundle/config.json" 34 | local root=$($jshon -e root -e path -u) 35 | local args=$($jshon -e process -e args -a -u | xargs) 36 | local uid=$(parse $bundle 0 -e process -e user -e uid) 37 | local gid=$(parse $bundle 0 -e process -e user -e gid) 38 | local cwd=/ # temporary until cwd is supported by chroot 39 | #cd $bundle$cwd 40 | 41 | local pid=$$ 42 | local id=$(basename $bundle) 43 | local path=/run/opencontainer/chroots/$id 44 | sudo install -o $UID -d $path 45 | cat >$path/state.json <<-END 46 | { "config" : $(cat $bundle/config.json) 47 | , "init_process_pid" : $pid 48 | , "id" : "$id" 49 | , "created" : "$(date -Is)" 50 | , "bundlePath" : "$(readlink -m $bundle)" 51 | } 52 | END 53 | local newroot=$bundle/$root 54 | # TODO parse config.json to enable the mounts 55 | chroot_add_mount proc "$newroot/proc" -t proc -o nosuid,noexec,nodev || true 56 | chroot_add_mount sys "$newroot/sys" -t sysfs -o nosuid,noexec,nodev,ro || true 57 | chroot_add_mount udev "$newroot/dev" -t devtmpfs -o mode=0755,nosuid || true 58 | exec sudo /usr/sbin/chroot --userspec $uid:$gid $newroot $args 59 | } 60 | 61 | function cmd_delete 62 | { 63 | local id=$1 64 | local path=/run/opencontainer/chroots/$id/state.json 65 | if [ -z "$id" ] 66 | then 67 | echo "runch delete: id cannot be empty" >&2 68 | exit 69 | fi 70 | if [ -f $path ] 71 | then 72 | true 73 | else 74 | echo "$id container doesn't exist" >&2 75 | exit 76 | fi 77 | 78 | local bundle=$(jshon -F $path -e bundlePath -u) 79 | local root=$(jshon -F $path -e config -e root -e path -u) 80 | sudo umount $bundle/$root/{proc,sys,dev} || true 81 | rm $path 82 | sudo rmdir $(dirname $path) 83 | } 84 | 85 | function cmd_kill 86 | { 87 | local id=$1 88 | local path=/run/opencontainer/chroots/$id/state.json 89 | if [ -z "$id" ] 90 | then 91 | echo "runch kill: id cannot be empty" >&2 92 | exit 93 | fi 94 | if [ -f $path ] 95 | then 96 | true 97 | else 98 | echo "$id container doesn't exist (wrong id or already deleted)" >&2 99 | exit 100 | fi 101 | 102 | local pid=$(jshon -F $path -e init_process_pid) 103 | sudo /usr/bin/kill -s 0 $pid 2>/dev/null || ( 104 | echo "runch kill: ($pid) no such process (container $id is destroyed)" >&2 105 | false 106 | ) || exit 107 | 108 | sudo /usr/bin/kill $pid 109 | echo waiting for $pid to exit 110 | while [ -d /proc/$pid ] ; do sleep 1; done 111 | echo process $pid exited 112 | cmd_delete $id 113 | } 114 | 115 | set -e 116 | case $1 in 117 | start|kill|delete) 118 | cmd_$1 $2 119 | ;; 120 | "") 121 | echo "Empty command" >&2 122 | ;; 123 | *) 124 | echo "Invalid command: $1" >&2 125 | exit 126 | ;; 127 | esac 128 | -------------------------------------------------------------------------------- /Roadmap.md: -------------------------------------------------------------------------------- 1 | # Long-term Vision 2 | 3 | VZ strives to become a management middleware for secure libertarian enterprise universal lightweight WAN clusters. 4 | 5 | ## Secure cluster 6 | 7 | ### Damage localization 8 | 9 | There is a general secure design principle that once the system is compromised in one place, the design 10 | should prevent further spreading of the attack. It's easy to see that for example CoreOS Fleet is the opposite of that. 11 | If a single node is hacked the attacker gets the addresses of all other nodes in the cluster and can install arbitrary privileged malware 12 | everywhere. 13 | 14 | ### No management components to attack 15 | 16 | Another principle is minimization of attack surface. All cluster management systems on the market expose the central 17 | manager and in many cases node management interface to the attacker. Think of buffer overflow or a vulnerable TLS implementation 18 | in CoreOS etcd, or attacks on centralized logging server or monitoring/management agents on cluster nodes. 19 | 20 | ## Libertarian cluster 21 | 22 | Basically it means a cluster resistant to shutdown by governments. Imagine something white-hat like 23 | WikiLeaks running multiple mirrors in a CoreOS cluster. Once one node is discovered and imaged by FBI, all the nodes can 24 | be discovered, imaged and shut down by confiscation orders to respective providers. 25 | 26 | Note that this is essentially just strenghtening of the Damage Localization principle. It is not purely anti-government feature 27 | which many may regard as shady, but also serves damage localization for mainstream pro-government security-savvy enterprise users. 28 | 29 | ## Enterprise Cluster 30 | 31 | ### Stability over Cutting Edge 32 | 33 | For enterprises stability is important, so they run software commonly considered outdated, such as CentOS 6 and even 5, and their 34 | RHEL flavours. This generally prevents them from using modern technologies such as Docker and other LXC-based containers, but once stable and widely approved, features get backported. 35 | 36 | ### Fixed Dictated Platforms 37 | 38 | We can't force an enterprise to change the platform it has been running. For example, we can't invent our own distribution of Linux, or can't drop support for hypervisors and architectures considered exotic by the open-source community, such as 32-bit systems, VMware ESXi, Citrix XenServer, Microsoft Hyper-V. 39 | 40 | ### Wide-scale Automated Management 41 | 42 | Enterpises typically deploy some form of automated management (e.g. configuration management). So we can't just drop their solution and invent our own management framework, but must piggyback on what they have. 43 | 44 | ### Legacy, RedHat, Microsoft-friendly 45 | 46 | They may go as far (in the eyes of Linux/GNU fanboys) as using Microsoft OMI to control their RHEL installations from Microsoft SysCenter. OpenPegasus mentions OpenVMS (a non-UNIX OS) in the list of supported systems etc. 47 | 48 | ### High Chances of Acquisition 49 | 50 | In the long run we want to become a part of central management portfolio of an enterprise vendor such as HPE, Oracle or RedHat. 51 | 52 | ## Universal Lightweight Cluster 53 | 54 | ### Lightweight Management 55 | 56 | ### Weak Containers for LTS Versions of Linux 57 | 58 | ## WAN cluster 59 | 60 | All the management software on the market is designed for contention and latency-free datacenters and fails miserably when 61 | failover consensus protocols or even message queues are run over WAN. And these days WAN distribution is essential for disaster 62 | recovery and high availability. Think of a web site running in different Amazon datacenters, or availability zones in their parlance. 63 | 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vz [![Join the chat at https://gitter.im/nponeccop/vz](https://badges.gitter.im/nponeccop/vz.svg)](https://gitter.im/nponeccop/vz?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 2 | 3 | A distributed independent cloud capable of running Podman pods on low RAM hosts. 4 | 5 | - cloud := an API to deploy applications and allocate resources across more than one VPS 6 | - distributed cloud := a cloud with VPS provided by more than one vendor 7 | - independent cloud := a cloud with command & control system not controlled by VPS vendors (talk less locked to a single vendor) 8 | 9 | Distibuted means reliable, independent means free as in freedom, low RAM means cheaper as the VPS cost is dominated by the RAM amount. 10 | 11 | Workflow of 2.x 12 | --------------- 13 | 14 | Prepare the pods: 15 | 16 | - Build your containers as usual 17 | - Use `smith-strace` to minify them (optional) 18 | - Define a pod in YAML 19 | 20 | Configure the nodes: 21 | 22 | - Create a user with your current user name and passwordless `sudo` on the hosts 23 | 24 | Configure the master 25 | 26 | - Configure Ansible and your hosts so `ansible all -m ping` is all green 27 | - Generate an ansible playbook from the Ansible inventory and the pod files 28 | 29 | Enjoy `ansible-playbook -i hosts.ini deploy.yaml` 30 | 31 | Bootstrap on RockyLinux 8 32 | ------------------------- 33 | 34 | AlmaLinux 8 and RHEL 8 should work too. 35 | 36 | - have your SSH public key listed in `ssh-add -l` 37 | - `ssh-copy-id root@{server-ip}` 38 | - `./bootstrap.sh {server-ip}` 39 | - `ssh {server-ip}` - now it should let you in with your key (note no `root@` - the previous step created the same remote user as `whoami`!) 40 | - `sudo yum update --security` 41 | 42 | Status 43 | ------ 44 | 45 | - Slowly migrating the production from 1.x 46 | - `smith-strace` script work 47 | - Image push over SSH works 48 | - Handcrafted playbooks work, but they are not robust enough yet (mostly performance, idempotency and image upgrades are missing) 49 | 50 | Why 51 | --- 52 | 53 | with such low operation cost even a hobbyist can afford operating a complex multi-server web service for years. And I hope that such improved longevity of hobbyist projects will bring more innovations to the web, as entry cost is at least twice as lower. 54 | 55 | One problem of using cheaper VPS providers is that many of them die each year. So some provisions for redundancy must be made, 56 | as a VPS can just disappear along with its hosting company without any notice. 57 | 58 | Idealized Workflow 59 | ------------------ 60 | 61 | - Spend $15/month in total for a few VPS from different hostings 62 | - Run `vzmaster newnode` with only IPs and root passwords from activation emails 63 | - The preinstalled OS is detected and replaced with VzOS, SSH keys are used from now on 64 | - Define application pods configuration in the spirit of Kubernetes/Dokku/Heroku 65 | - Run `vzmaster deploy` to build and push a new version of your application 66 | - Go to sleep 67 | - Notice that one of your VPSes has gone without any emails from the company 68 | - Order a new node from someone else 69 | - Rerun `newnode`/`deploy` 70 | - Go to sleep again 71 | - Write another application and deploy it across the same redundant array of inexpensive VPSes 72 | - Migrate to Docker or VMs and back as your financial power changes over time 73 | 74 | Architecture 75 | ------------ 76 | 77 | - all security is provided by OpenSSH and not by inmature TLS server implementations 78 | - all management is peformed by `ansible`. No management or data collection daemon processes whatsoever on slaves besides `init` and `sshd`. 79 | - ideally all containers are directly supervised by `init`/`PID 0` in the spirit of `/etc/inittab` 80 | - 512 MB nodes. More RAM means more money. Fat runtimes for fat containers already exist. 81 | - Stock RHEL8 software via free downstream distributions (RockyLinux 8 is the primary target, AlmaLinux 8 works) 82 | - image push over SFTP via Ansible `copy` (not pull over HTTPS, so no image registry) 83 | 84 | Non-goals 85 | --------- 86 | 87 | - It's not a full k8s replacement 88 | 89 | Competitors 90 | ----------- 91 | Rootfs: 92 | - CoreOS 93 | - RancherOS 94 | - PhotonOS 95 | - Ubuntu Snap 96 | - RedHat Atomic 97 | - Alpine Linux 98 | - Intel Clear Linux 99 | 100 | Container runners: 101 | - docker/runc 102 | - garden/warden 103 | - Intel Clear Containers 104 | - udocker/proot 105 | 106 | Command and control: 107 | - fleet/etcd 108 | - kubernetes 109 | - Heroku 110 | - Dokku 111 | 112 | Supervision/zombie reaping: 113 | - systemd 114 | - openrc 115 | - raw busybox-based /sbin/init 116 | - supervisord 117 | - pidunu 118 | 119 | Image building: 120 | 121 | - Dockerfile/Docker build/buildkit 122 | - smith 123 | - s2i 124 | - Heroku 125 | 126 | Features as of 1.0-pre 127 | ---------------------- 128 | 129 | - Manual installation (with help from `bootstrap`) 130 | - PoC operation on RockyLinux 8 and AlmaLinux 8 CentOS 6/OpenVZ with manually created images (with help from `strace-chroot` to create the `rootfs` part) 131 | - `vzmaster {push|start|kill}` as a front end to Ansible 132 | - `runch {start|kill}` 133 | - `runch start` monitors using a shell loop 134 | 135 | Master-slave: 136 | 137 | - remote container start/stop 138 | - image transfer and storage 139 | 140 | Slave only: 141 | 142 | - `vzexec` container runner with integrated container crash supervision and auto restart 143 | - stdout/strderr are logged to syslog 144 | 145 | Goals for 0.2 146 | ------------- 147 | 148 | - more automation in `bootstrap` 149 | - shift some work from start/stop Ansible playbooks to `bootstrap` to avoid repetition 150 | - deploy to Ansible host groups other than `all` 151 | - seamless update - autostop older image 152 | - register rc.d services for container autostart 153 | - `iptables` setup to open ports 154 | 155 | Goals for 0.3 156 | ------------- 157 | 158 | - differential image compression using `xdelta3` or `bsdiff` 159 | - Ansible role 160 | - Syslog downloader 161 | 162 | Goals for 1.0 163 | ------------- 164 | 165 | Less ad hoc implementation of what was in 0.x, and in addition: 166 | 167 | Slave only: 168 | 169 | - ability to substitute `runch` with `runc` 170 | 171 | Master only: 172 | 173 | - container rootfs build system 174 | - assembly of OCI bundles 175 | 176 | Goals for 2.0 177 | ------------- 178 | 179 | Master-slave: 180 | 181 | - logging and monitoring 182 | 183 | Slave only: 184 | 185 | - rootfs 186 | - rootfs installer 187 | 188 | Master only: 189 | - central management, orchestration and monitoring console 190 | 191 | Available Components 192 | -------------------- 193 | 194 | ### strace-trace 195 | 196 | For more complex cases, `strace-trace` uses `strace` Linux only tool to trace system calls and find all files opened during the test run: 197 | 198 | ```shell 199 | $ strace-trace perl -MHTTP::Date -e 'print time2str(time())."\n"' 200 | $ cat spec 201 | /etc/localtime 202 | /usr/bin/perl 203 | /usr/lib/libc.so.6 204 | /usr/lib/libcrypt.so.1 205 | /usr/lib/libdl.so.2 206 | /usr/lib/libm.so.6 207 | /usr/lib/libpthread.so.0 208 | /usr/lib/locale/locale-archive 209 | /usr/lib/perl5/core_perl/CORE/libperl.so 210 | /usr/lib/perl5/core_perl/Config.pm 211 | /usr/share/perl5/core_perl/Carp.pm 212 | /usr/share/perl5/core_perl/Exporter.pm 213 | /usr/share/perl5/core_perl/Time/Local.pm 214 | /usr/share/perl5/core_perl/constant.pm 215 | /usr/share/perl5/core_perl/strict.pm 216 | /usr/share/perl5/core_perl/vars.pm 217 | /usr/share/perl5/core_perl/warnings.pm 218 | /usr/share/perl5/core_perl/warnings/register.pm 219 | /usr/share/perl5/vendor_perl/HTTP/Date.pm 220 | ``` 221 | 222 | The `spec` file created in current directory can be used to create a minimal OCI rootfs/chroot 223 | 224 | --------------------------------------------------------------------------------