diff --git a/.github/workflows/commits.yml b/.github/workflows/commits.yml deleted file mode 100644 index 541a8f9..0000000 --- a/.github/workflows/commits.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Commits -on: - - pull_request - -permissions: - contents: read - -jobs: - dco-check: - permissions: - pull-requests: read # for tim-actions/get-pr-commits to get list of commits from the PR - name: Signed-off-by (DCO) - runs-on: ubuntu-20.04 - steps: - - name: Get PR Commits - id: 'get-pr-commits' - uses: tim-actions/get-pr-commits@master - with: - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Check that all commits are signed-off - uses: tim-actions/dco@master - with: - commits: ${{ steps.get-pr-commits.outputs.commits }} - - target-branch: - permissions: - contents: none - name: Branch target - runs-on: ubuntu-20.04 - steps: - - name: Check branch target - env: - TARGET: ${{ github.event.pull_request.base.ref }} - run: | - set -x - [ "${TARGET}" = "main" ] && exit 0 - - echo "Invalid branch target: ${TARGET}" - exit 1 diff --git a/.travis.yml b/.travis.yml index 5eec734..0cd65ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,11 +11,6 @@ before_install: - sudo apt-get install -y python-software-properties - sudo add-apt-repository -y ppa:ubuntu-lxc/daily - sudo apt-get update -y - - sudo apt-get install -y liblxc1 + - sudo apt-get install -y liblxc0 lxc lxc-dbg lxc-dev lxc-templates lxc-tests lxctl python3-lxc script: - bundle exec rake clean package - -notifications: - webhooks: https://linuxcontainers.org/webhook-lxcbot/ - email: - - andrenth@gmail.com diff --git a/README.md b/README.md index 26d2c53..44d3f85 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Ruby-LXC -[![Build Status](https://travis-ci.org/lxc/ruby-lxc.svg?branch=master)](https://travis-ci.org/lxc/ruby-lxc) - ## Introduction Ruby-LXC is a Ruby binding for liblxc. It allows the creation and management @@ -13,23 +11,19 @@ Assuming a current installation of LXC is available, to install Ruby-LXC simply run the commands below ```sh -sudo apt-get install ruby-dev lxc-dev - bundle install bundle exec rake compile -bundle exec rake gem -gem install pkg/ruby-lxc-1.2.0.gem +gem install pkg/ruby-lxc-1.0.2.gem ``` or just add this to your ```Gemfile``` ```ruby -gem "ruby-lxc", github: "lxc/ruby-lxc", require: "lxc" +gem "ruby-lxc", github: "lxc/ruby-lxc" ``` ## Usage - Container lifecycle management (create, start, stop and destroy containers) ```ruby -require 'lxc' c = LXC::Container.new('foo') c.create('ubuntu') # create a container named foo with ubuntu template c.start diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 43c1c39..0000000 --- a/debian/changelog +++ /dev/null @@ -1,35 +0,0 @@ -ruby-lxc (1.2.3-0digirati1) trusty; urgency=low - - * Version 1.2.3. - - -- Andre Nathan Mon, 10 Jul 2018 10:29:03 -0300 - -ruby-lxc (1.2.2-0digirati1) trusty; urgency=low - - * Version 1.2.2. - - -- Andre Nathan Mon, 24 Oct 2016 10:55:05 -0200 - -ruby-lxc (1.2.1-0digirati1) trusty; urgency=low - - * Version 1.2.1. - - -- Andre Nathan Fri, 04 Jan 2016 11:43:33 -0200 - -ruby-lxc (1.2.0-0digirati1) trusty; urgency=low - - * Version 1.2.0. - - -- Andre Nathan Fri, 13 Jun 2014 14:37:26 -0300 - -ruby-lxc (1.1.1-0digirati1) trusty; urgency=low - - * Version 1.1.1. - - -- Andre Nathan Fri, 06 Jun 2014 11:23:11 -0300 - -ruby-lxc (1.1.0-0digirati1) trusty; urgency=low - - * Version 1.1.0. - - -- Andre Nathan Tue, 20 May 2014 09:37:12 -0300 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 7f8f011..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -7 diff --git a/debian/control b/debian/control deleted file mode 100644 index 96283e8..0000000 --- a/debian/control +++ /dev/null @@ -1,14 +0,0 @@ -Source: ruby-lxc -Section: ruby -Priority: optional -Maintainer: Andre Nathan -Build-Depends: debhelper (>= 7.0.50~), gem2deb (>= 0.2.3~), lxc-dev -Standards-Version: 3.9.5 -XS-Ruby-Versions: all - -Package: ruby-lxc -Architecture: any -XB-Ruby-Versions: ${ruby:Versions} -Depends: ${misc:Depends}, ${shlibs:Depends}, ruby | ruby-interpreter, liblxc1 -Description: Ruby bindings for liblxc - This package provides liblxc bindings for the Ruby programming language. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index b9c9e9f..0000000 --- a/debian/copyright +++ /dev/null @@ -1,9 +0,0 @@ -Format: http://anonscm.debian.org/viewvc/dep/web/deps/dep5.mdwn?revision=173 -Upstream-Name: ruby-lxc - -Files: * -Copyright: Copyright 2014 Andre Nathan -License: LGPL-2.1 - On Debian systems, the full text of the GNU General Public - License version 2 can be found in the file - `/usr/share/common-licenses/LGPL-2.1'. diff --git a/debian/rules b/debian/rules deleted file mode 100755 index a4b9e28..0000000 --- a/debian/rules +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/make -f -#export DH_VERBOSE=1 -# -# Uncomment to ignore all test failures (but the tests will run anyway) -#export DH_RUBY_IGNORE_TESTS=all -# -# Uncomment to ignore some test failures (but the tests will run anyway). -# Valid values: -#export DH_RUBY_IGNORE_TESTS=ruby1.8 ruby1.9.1 require-rubygems - -%: - dh $@ --buildsystem=ruby --with ruby diff --git a/debian/source/format b/debian/source/format deleted file mode 100644 index 163aaf8..0000000 --- a/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/debian/watch b/debian/watch deleted file mode 100644 index 9e7c0da..0000000 --- a/debian/watch +++ /dev/null @@ -1 +0,0 @@ -version=3 diff --git a/ext/lxc/lxc.c b/ext/lxc/lxc.c index 6a1f394..b3ad0fc 100644 --- a/ext/lxc/lxc.c +++ b/ext/lxc/lxc.c @@ -6,7 +6,6 @@ #include #include #include -#include #define SYMBOL(s) ID2SYM(rb_intern(s)) @@ -41,28 +40,9 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, #define RELEASING_GVL2(func, arg, killfunc, killarg) func(arg) #endif -//extern int lxc_wait_for_pid_status(pid_t pid); -#include -#include -int lxc_wait_for_pid_status(pid_t pid) -{ - int status, ret; - -again: - ret = waitpid(pid, &status, 0); - if (ret == -1) { - if (errno == EINTR) - goto again; - - return -1; - } - - if (ret != pid) - goto again; - - return status; -} -//extern long lxc_config_parse_arch(const char *arch); +extern int lxc_wait_for_pid_status(pid_t pid); +extern long lxc_config_parse_arch(const char *arch); +extern const char *lxc_strerror(int error); static VALUE Container; static VALUE Error; @@ -118,24 +98,24 @@ free_c_string_array(char **arr) * "personality", either +:linux32+ or +:linux+, for the 32-bit and 64-bit * architectures, respectively. */ -//static VALUE -//lxc_arch_to_personality(VALUE self, VALUE rb_arch) -//{ -// int ret; -// char *arch; -// -// arch = StringValuePtr(rb_arch); -// ret = lxc_config_parse_arch(arch); -// -// switch (ret) { -// case PER_LINUX32: -// return SYMBOL("linux32"); -// case PER_LINUX: -// return SYMBOL("linux"); -// default: -// rb_raise(Error, "unknown personality"); -// } -//} +static VALUE +lxc_arch_to_personality(VALUE self, VALUE rb_arch) +{ + int ret; + char *arch; + + arch = StringValuePtr(rb_arch); + ret = lxc_config_parse_arch(arch); + + switch (ret) { + case PER_LINUX32: + return SYMBOL("linux32"); + case PER_LINUX: + return SYMBOL("linux"); + default: + rb_raise(Error, "unknown personality"); + } +} /* * call-seq: @@ -446,15 +426,6 @@ container_running_p(VALUE self) * container.state * * Returns a symbol representing the state of the container. - * - * * +:stopped+ - * * +:starting+ - * * +:running+ - * * +:stopping+ - * * +:aborting+ - * * +:freezing+ - * * +:frozen+ - * * +:thawed+ */ static VALUE container_state(VALUE self) @@ -566,10 +537,10 @@ is_string_array(VALUE v) } static int -has_file_descriptor(VALUE v) +is_io(VALUE v) { - return rb_respond_to(v, rb_intern("fileno")) && - rb_funcall(v, rb_intern("fileno"), 0) != Qnil; + return rb_respond_to(v, rb_intern("sysread")) && + rb_respond_to(v, rb_intern("syswrite")); } static void @@ -589,12 +560,11 @@ lxc_attach_free_options(lxc_attach_options_t *opts) static lxc_attach_options_t * lxc_attach_parse_options(VALUE rb_opts) { - char *error = NULL; lxc_attach_options_t default_opts = LXC_ATTACH_OPTIONS_DEFAULT; lxc_attach_options_t *opts; VALUE rb_attach_flags, rb_namespaces, rb_personality, rb_initial_cwd; VALUE rb_uid, rb_gid, rb_env_policy, rb_extra_env_vars, rb_extra_keep_env; - VALUE rb_stdin_opt, rb_stdout_opt, rb_stderr_opt; + VALUE rb_stdin, rb_stdout, rb_stderr; opts = malloc(sizeof(*opts)); if (opts == NULL) @@ -604,125 +574,96 @@ lxc_attach_parse_options(VALUE rb_opts) if (NIL_P(rb_opts)) return opts; - error = NULL; - rb_attach_flags = rb_hash_aref(rb_opts, SYMBOL("flags")); if (!NIL_P(rb_attach_flags)) { - if (is_integer(rb_attach_flags)) { + if (is_integer(rb_attach_flags)) opts->attach_flags = NUM2INT(rb_attach_flags); - } else { - error = "flags must be an integer"; + else goto err; - } } rb_namespaces = rb_hash_aref(rb_opts, SYMBOL("namespaces")); if (!NIL_P(rb_namespaces)) { - if (is_integer(rb_namespaces)) { + if (is_integer(rb_namespaces)) opts->namespaces = NUM2INT(rb_namespaces); - } else { - error = "namespaces must be an integer"; + else goto err; - } } rb_personality = rb_hash_aref(rb_opts, SYMBOL("personality")); if (!NIL_P(rb_personality)) { - if (is_integer(rb_personality)) { + if (is_integer(rb_personality)) opts->personality = NUM2INT(rb_personality); - } else { - error = "personality must be an integer"; + else goto err; - } } rb_initial_cwd = rb_hash_aref(rb_opts, SYMBOL("initial_cwd")); if (!NIL_P(rb_initial_cwd)) { - if (is_string(rb_initial_cwd)) { + if (is_string(rb_initial_cwd)) opts->initial_cwd = StringValuePtr(rb_initial_cwd); - } else { - error = "initial_cwd must be a string"; + else goto err; - } } rb_uid = rb_hash_aref(rb_opts, SYMBOL("uid")); if (!NIL_P(rb_uid)) { - if (is_integer(rb_uid)) { + if (is_integer(rb_uid)) opts->uid = NUM2INT(rb_uid); - } else { - error = "uid must be an integer"; + else goto err; - } } rb_gid = rb_hash_aref(rb_opts, SYMBOL("gid")); if (!NIL_P(rb_gid)) { - if (is_integer(rb_gid)) { + if (is_integer(rb_gid)) opts->gid = NUM2INT(rb_gid); - } else { - error = "gid must be an integer"; + else goto err; - } } rb_env_policy = rb_hash_aref(rb_opts, SYMBOL("env_policy")); if (!NIL_P(rb_env_policy)) { - if (is_integer(rb_env_policy)) { + if (is_integer(rb_env_policy)) opts->env_policy = NUM2INT(rb_env_policy); - } else { - error = "env_policy must be an integer"; + else goto err; - } } rb_extra_env_vars = rb_hash_aref(rb_opts, SYMBOL("extra_env_vars")); if (!NIL_P(rb_extra_env_vars)) { - if (is_string_array(rb_extra_env_vars)) { + if (is_string_array(rb_extra_env_vars)) opts->extra_env_vars = ruby_to_c_string_array(rb_extra_env_vars); - } else { - error = "extra_env_vars must be a array of strings"; + else goto err; - } } rb_extra_keep_env = rb_hash_aref(rb_opts, SYMBOL("extra_keep_env")); if (!NIL_P(rb_extra_keep_env)) { - if (is_string_array(rb_extra_keep_env)) { + if (is_string_array(rb_extra_keep_env)) opts->extra_keep_env = ruby_to_c_string_array(rb_extra_keep_env); - } else { - error = "extra_keep_env must be a array of strings"; + else goto err; - } } - rb_stdin_opt = rb_hash_aref(rb_opts, SYMBOL("stdin")); - if (!NIL_P(rb_stdin_opt)) { - if (has_file_descriptor(rb_stdin_opt)) { - opts->stdin_fd = io_fileno(rb_stdin_opt); - } else { - error = "stdin object must have a file descriptor"; + rb_stdin = rb_hash_aref(rb_opts, SYMBOL("stdin")); + if (!NIL_P(rb_stdin)) { + if (is_io(rb_stdin)) + opts->stdin_fd = io_fileno(rb_stdin); + else goto err; - } } - rb_stdout_opt = rb_hash_aref(rb_opts, SYMBOL("stdout")); - if (!NIL_P(rb_stdout_opt)) { - if (has_file_descriptor(rb_stdout_opt)) { - opts->stdout_fd = io_fileno(rb_stdout_opt); - } else { - error = "stdout object must have a file descriptor"; + rb_stdout = rb_hash_aref(rb_opts, SYMBOL("stdout")); + if (!NIL_P(rb_stdout)) { + if (is_io(rb_stdout)) + opts->stdout_fd = io_fileno(rb_stdout); + else goto err; - } } - rb_stderr_opt = rb_hash_aref(rb_opts, SYMBOL("stderr")); - if (!NIL_P(rb_stderr_opt)) { - if (has_file_descriptor(rb_stderr_opt)) { - opts->stderr_fd = io_fileno(rb_stderr_opt); - } else { - error = "stderr object must have a file descriptor"; + rb_stderr = rb_hash_aref(rb_opts, SYMBOL("stderr")); + if (!NIL_P(rb_stderr)) { + if (is_io(rb_stderr)) + opts->stderr_fd = io_fileno(rb_stderr); + else goto err; - } } return opts; err: lxc_attach_free_options(opts); - if (error != NULL) - rb_raise(rb_eArgError, "%s", error); - else - return NULL; + return NULL; } static RETURN_WITHOUT_GVL_TYPE @@ -1069,7 +1010,6 @@ struct container_create_without_gvl_args { struct container_data *data; char *template; char *bdevtype; - struct bdev_specs *bdevspecs; int flags; char **args; }; @@ -1081,14 +1021,14 @@ container_create_without_gvl(void *args_void) (struct container_create_without_gvl_args *)args_void; RETURN_WITHOUT_GVL( args->data->container->create(args->data->container, args->template, - args->bdevtype, args->bdevspecs, args->flags, + args->bdevtype, NULL, args->flags, args->args) ); } /* * call-seq: - * container.create(template, bdevtype = nil, bdevspecs = {}, flags = 0, args = []) + * container.create(template, bdevtype = nil, flags = 0, args = []) * * Creates a structure for the container according to the given template. * This usually consists of downloading and installing a Linux distribution @@ -1100,57 +1040,17 @@ static VALUE container_create(int argc, VALUE *argv, VALUE self) { int ret; - struct bdev_specs spec; + VALUE rb_template, rb_bdevtype, rb_flags, rb_args; struct container_create_without_gvl_args args; char **default_args = { NULL }; - VALUE rb_template, rb_bdevtype, rb_bdevspecs, rb_flags, rb_args; - VALUE fstype, fssize, zfsroot, lvname, vgname, thinpool, dir; args.args = default_args; - rb_scan_args(argc, argv, "14", - &rb_template, &rb_bdevtype, &rb_bdevspecs, &rb_flags, - &rb_args); - - if (!NIL_P(rb_bdevspecs)) { - memset(&spec, 0, sizeof(spec)); - - fstype = rb_hash_aref(rb_bdevspecs, SYMBOL("fstype")); - if (!NIL_P(fstype)) - spec.fstype = StringValuePtr(fstype); - - fssize = rb_hash_aref(rb_bdevspecs, SYMBOL("fssize")); - if (!NIL_P(fssize)) - spec.fssize = NUM2ULONG(fssize); - - zfsroot = rb_hash_aref(rb_bdevspecs, SYMBOL("zfsroot")); - if (!NIL_P(zfsroot)) - spec.zfs.zfsroot = StringValuePtr(zfsroot); - - lvname = rb_hash_aref(rb_bdevspecs, SYMBOL("lvname")); - if (!NIL_P(lvname)) - spec.lvm.lv = StringValuePtr(lvname); - - vgname = rb_hash_aref(rb_bdevspecs, SYMBOL("vgname")); - if (!NIL_P(vgname)) - spec.lvm.vg = StringValuePtr(vgname); - - thinpool = rb_hash_aref(rb_bdevspecs, SYMBOL("thinpool")); - if (!NIL_P(thinpool)) - spec.lvm.thinpool = StringValuePtr(thinpool); - - dir = rb_hash_aref(rb_bdevspecs, SYMBOL("dir")); - if (!NIL_P(dir)) - spec.dir = StringValuePtr(dir); - - args.bdevspecs = &spec; - - } else { - args.bdevspecs = NULL; - } + rb_scan_args(argc, argv, "13", + &rb_template, &rb_bdevtype, &rb_flags, &rb_args); args.template = StringValuePtr(rb_template); args.bdevtype = NIL_P(rb_bdevtype) ? NULL : StringValuePtr(rb_bdevtype); - args.flags = NIL_P(rb_flags) ? 0 : NUM2INT(rb_flags); + args.flags = NIL_P(rb_flags) ? 0 : NUM2INT(rb_flags); if (!NIL_P(rb_args)) args.args = ruby_to_c_string_array(rb_args); @@ -1167,6 +1067,7 @@ container_create(int argc, VALUE *argv, VALUE self) return self; } + static RETURN_WITHOUT_GVL_TYPE destroy_without_gvl(void *data_void) { @@ -1283,9 +1184,6 @@ container_config_item(VALUE self, VALUE rb_key) if (len1 < 0) rb_raise(Error, "invalid configuration key: %s", key); - if (len1 == 0) - return Qnil; - value = malloc(sizeof(char) * len1 + 1); if (value == NULL) rb_raise(rb_eNoMemError, "unable to allocate configuration value"); @@ -1322,10 +1220,6 @@ container_config_path(VALUE self) * container.keys(key) * * Returns a list of valid sub-keys for the given configuration key. - * - * Keys can be in the format 'lxc.network.', (eg. 'lxc.network.0', - * 'lxc.network.1'). The result shows which keys are valid according to - * type of network interface. */ static VALUE container_keys(VALUE self, VALUE rb_key) @@ -2089,7 +1983,7 @@ container_unfreeze(VALUE self) ret = RELEASING_GVL(unfreeze_without_gvl, data); if (!ret) - rb_raise(Error, "unable to unfreeze container"); + rb_raise(Error, "unable to unfreeze container: %s", lxc_strerror(ret)); return self; } @@ -2147,8 +2041,8 @@ Init_lxc(void) { VALUE LXC = rb_define_module("LXC"); - //rb_define_singleton_method(LXC, "arch_to_personality", - // lxc_arch_to_personality, 1); + rb_define_singleton_method(LXC, "arch_to_personality", + lxc_arch_to_personality, 1); rb_define_singleton_method(LXC, "run_command", lxc_run_command, 1); rb_define_singleton_method(LXC, "run_shell", lxc_run_shell, 0); rb_define_singleton_method(LXC, "global_config_item", @@ -2173,7 +2067,7 @@ Init_lxc(void) rb_define_method(Container, "add_device_node", container_add_device_node, -1); rb_define_method(Container, "attach", container_attach, -1); - rb_define_method(Container, "clear_config", container_clear_config, 0); + rb_define_method(Container, "clear_config", container_clear_config, -1); rb_define_method(Container, "clear_config_item", container_clear_config_item, 1); rb_define_method(Container, "clone", container_clone, -1); diff --git a/lib/lxc/version.rb b/lib/lxc/version.rb index 15bb139..1584e3a 100644 --- a/lib/lxc/version.rb +++ b/lib/lxc/version.rb @@ -1,3 +1,3 @@ module LXC - VERSION = '1.2.3' + VERSION = '1.0.2' end diff --git a/ruby-lxc.gemspec b/ruby-lxc.gemspec index 4df7fcb..2802efa 100644 --- a/ruby-lxc.gemspec +++ b/ruby-lxc.gemspec @@ -13,8 +13,6 @@ Gem::Specification.new do |s| s.extensions = 'ext/lxc/extconf.rb' s.has_rdoc = true - s.add_development_dependency "rdoc" - s.add_development_dependency "rdoc-data" s.add_development_dependency "rake-compiler" s.homepage = 'https://github.com/lxc/ruby-lxc' diff --git a/test/test_lxc_created.rb b/test/test_lxc_created.rb index 5784855..120e1cf 100644 --- a/test/test_lxc_created.rb +++ b/test/test_lxc_created.rb @@ -28,7 +28,6 @@ class TestLXCCreated < Test::Unit::TestCase def test_container_configuration capdrop = @container.config_item('lxc.cap.drop') - assert_instance_of(Array, @container.config_item('lxc.cap.drop')) @container.clear_config_item('lxc.cap.drop') @container.set_config_item('lxc.cap.drop', capdrop[0...-1]) @container.set_config_item('lxc.cap.drop', capdrop[-1]) @@ -41,35 +40,6 @@ class TestLXCCreated < Test::Unit::TestCase assert_match(/^00:16:3e:/, @container.config_item('lxc.network.0.hwaddr')) end - def test_container_fstab - config_path = @container.config_path + '/' + @name + '/config' - fstab_path = @container.config_path + '/' + @name + '/fstab' - - @container.set_config_item('lxc.mount', fstab_path) - @container.save_config(config_path) - - assert_instance_of(String, @container.config_item('lxc.mount')) - assert_not_nil(@container.config_item('lxc.mount')) - - f = File.readlines(config_path) - f.reject! { |l| /^lxc\.mount = (.*)$/ =~ l } - File.write(config_path, f.join) - - @container.clear_config - @container.load_config(config_path) - - assert(@container.config_item('lxc.mount').nil?) - end - - def test_clear_config - assert_not_nil(@container.config_item('lxc.utsname')) - assert(@container.clear_config) - - assert_raise(LXC::Error) do - @container.config_item('lxc.utsname').nil? - end - end - def test_container_mount_points assert_instance_of(Array, @container.config_item('lxc.mount.entry')) end