--- /dev/null
+# Global configuration file for strongSwan UML testing.
+#
+# Copyright (C) 2009 Tobias Brunner
+# Hochschule fuer Technik Rapperswil
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+
+# All tarballs must have on of the following extensions:
+# .tar, .tar.gz, .tgz, .tar.bz2, .tbz
+
+<% testdir=TESTING_ROOT %>
+
+guests:
+ defaults:
+ # the strongswan version to be used. either the name of a strongswan config
+ # defined below or an inline strongswan config.
+ strongswan: default
+#strongswan:
+# source: git
+ # the kernel to be used. either the name of a kernel config defined below or
+ # an inline kernel config.
+ kernel: default
+ # the masterfs to be used (folder or tarball)
+ #masterfs: <%= testdir %>/master-fs-20090325.tar.bz2
+ masterfs: <%= testdir %>/master
+ # templates (config files etc.) that are copied to the guests. a directory
+ # with the guest's name must exist in the directry set here.
+ templates: <%= testdir %>/hosts
+ # memory in MB per guest
+ mem: 64
+ # consoles: xterm|pts
+ consoles:
+ - xterm
+ - pts
+ # allows to customize the values above for each host (options set here
+ # replace the defaults above for the specified host). Only the hosts listed
+ # here are actually built.
+ # possible values are: sun, moon, dave, carol, alice, venus bob and winnetou.
+ # of course, you can add other hostnames for your own scenarios.
+ hosts:
+ - sun:
+ strongswan: other
+ - moon:
+ - dave
+ - carol:
+# kernel: older
+ - alice:
+ - venus
+ - bob:
+ kernel: already_built
+ mem: 128
+ - winnetou
+
+# list of kernels
+kernels:
+ default:
+ # which source is used to build the kernel (none|dir|git|tar)
+ # where 'dir' is synonymous with 'git' but 'checkout' is ignored
+ # if this option is omitted, 'none' is assumed
+ source: git
+ # if you set source to 'git', set the path to the git repository here
+ path: /home/tbrunner/kernel/net-next-2.6/
+ # if source is 'git', this is the local branch, tag or commit to build.
+ # a tarball is created from there (using git archive) and that tarball
+ # is then used to build the kernel.
+ # if this option is omitted or empty, the build takes place directly in
+ # the repository.
+ checkout: 'v2.6.28'
+ patches:
+ - /home/tbrunner/workspace/git/src/dumm/patches/mconsole-exec-2.6.28.patch
+ # kernel configuration file, if no config file is defined, it is assumed
+ # that the config file is available in the source directory
+ config: <%= testdir %>/.config-2.6.28
+ older:
+ # tarball source
+ source: tar
+ path: <%= testdir %>/linux-2.6.29.4.tar.bz2
+ # list of optional kernel patches (.patch, .patch.bz2, .patch.gz extension)
+ patches:
+ #- <%= testdir %>/aead_init.patch.bz2
+ # kernel configuration file
+ config: <%= testdir %>/.config-2.6.29
+
+ already_built:
+ # if source is not defined or set to 'none' the kernel can be specified
+ # directly
+#source: none
+ path: /home/tbrunner/tbrunner/testing/umlbuild/linux-uml-2.6.21.1
+
+strongswan:
+ default:
+ # same as for the kernel (dir|git|tar)
+ source: git
+ path: /home/tbrunner/workspace/git/
+ checkout: master
+ # list of configure options
+ # e.g. eap_aka: yes -> --enable-eap-aka
+ # or eap_md5: no -> --disable-eap-md5
+ options:
+ - curl: no
+ - ldap: no
+ - eap_aka: yes
+ - eap_sim: yes
+ - eap_sim_file: yes
+ - eap_md5: yes
+ - eap_mschapv2: yes
+ - eap_identity: yes
+ - eap_radius: yes
+ - sql: no
+ - sqlite: no
+ - md4: yes # required by eap-mschapv2
+ - mediation: yes
+ - openssl: yes
+ - blowfish: yes
+ - twofish: yes
+ - serpent: yes
+ - kernel_pfkey: yes
+ - integrity_test: yes
+ - leak_detective: yes
+ - load_tests: yes
+ other:
+ source: tar
+ path: <%= testdir %>/strongswan-4.3.1.tar.gz
+ options:
+ - gmp: no
+ - openssl: yes
+
--- /dev/null
+=begin
+ Copyright (C) 2009 Tobias Brunner
+ Hochschule fuer Technik Rapperswil
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+=end
+
+require 'ostruct'
+
+require 'kernel_config'
+require 'strongswan_config'
+require 'guest_config'
+
+module Dumm
+ class Config
+
+ # Creates a new Config instance, initialized with the values
+ # loaded from the config file.
+ def initialize(file)
+ @config = read_config(file)
+ @kernels = prepare_kernels
+ @strongswan = prepare_strongswan
+ @guests = prepare_guests
+ end
+
+ # Return all strongSwan configurations that are referenced by any guest.
+ def strongswan
+ @strongswan.select do |name, strongswan|
+ @guests.any? { |name, guest| strongswan.eql? guest.strongswan }
+ end
+ end
+
+ # Return all kernel configurations that are referenced by any guest.
+ def kernels
+ @kernels.select do |name, kernel|
+ @guests.any? { |name, guest| kernel.eql? guest.kernel }
+ end
+ end
+
+ # Return all valid guest configurations.
+ def guests
+ @guests.reject { |name, guest| guest.invalid }
+ end
+
+ private
+
+ # Reads the config file. The file is processed with ERB before being
+ # loaded by YAML and converted into an OpenStruct.
+ def read_config(file)
+ require 'yaml'
+ require 'erb'
+ OpenStruct.new(YAML::load(ERB.new(IO.read(file)).result))
+ end
+
+ # Initializes the kernel configurations.
+ def prepare_kernels
+ @config.kernels ||= []
+ @kernels = @config.kernels.inject({}) do |h, conf|
+ name, conf = *conf
+ h[name] = KernelConfig.new name, OpenStruct.new(conf)
+ h
+ end
+ end
+
+ # Initializes the strongswan configurations.
+ def prepare_strongswan
+ @config.strongswan ||= []
+ @strongswan = @config.strongswan.inject({}) do |h, conf|
+ name, conf = *conf
+ h[name] = StrongswanConfig.new name, OpenStruct.new(conf)
+ h
+ end
+ end
+
+ # Initializes the guest configurations.
+ def prepare_guests
+ guests = OpenStruct.new @config.guests
+ defaults = read_guest_config("guests_defaults", guests.defaults)
+ guests.hosts ||= []
+ @guests = guests.hosts.inject({}) do |h, conf|
+ name, conf = conf.is_a?(Hash) ? conf.shift : [conf, {}]
+ conf = read_guest_config("guests_#{name}", conf).delete_if { |k, v| v == nil }
+ conf = defaults.merge(conf)
+ h[name] = GuestConfig.new name, OpenStruct.new(conf)
+ h
+ end
+ end
+
+ # Read a guest config and return it as Hash.
+ def read_guest_config(name, config)
+ c = OpenStruct.new config
+ h = OpenStruct.new
+ h.strongswan = if c.strongswan && c.strongswan.is_a?(Hash)
+ @strongswan[name] = StrongswanConfig.new name, c.strongswan
+ else
+ @strongswan[c.strongswan]
+ end
+ h.kernel = if c.kernel && c.kernel.is_a?(Hash)
+ @kernels[name] = KernelConfig.new name, c.kernel
+ else
+ @kernels[c.kernel]
+ end
+ h.masterfs = c.masterfs if c.masterfs && (Testing.tarball?(c.masterfs) || File.directory?(c.masterfs))
+ h.templates = c.templates if c.templates && (c.templates.empty? || File.directory?(c.templates))
+ h.mem = c.mem.to_i if c.mem
+ h.consoles = c.consoles.select { |c| c =~ /^(xterm|pts)$/ } if c.consoles
+ h.marshal_dump
+ end
+
+ end
+end
--- /dev/null
+=begin
+ Copyright (C) 2008 Tobias Brunner
+ Hochschule fuer Technik Rapperswil
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ $Id$
+=end
+
+# Simplifies formatting console output by using ANSI escape codes
+
+module Dumm
+ module ConsoleFormat
+ @@colors = {
+ :black => 0,
+ :red => 1,
+ :green => 2,
+ :yellow => 3,
+ :blue => 4,
+ :magenta => 5,
+ :cyan => 6,
+ :white => 7
+ }
+ @@colors.default = 9
+
+ @@intensity = { :bold => 1 }
+ @@intensity.default = 22
+
+ @@blink = { :slow => 5, :rapid => 6 }
+ @@blink.default = 25
+
+ @@underline = { :single => 4, :double => 21 }
+ @@underline.default = 24
+
+ @@codes = @@colors.inject({}) { |codes, color|
+ codes[color[0]] = 30 + color[1]
+ codes[("b#{color[0]}".to_s).to_sym] = 40 + color[1]
+ codes
+ }
+ @@codes = @@codes.merge(@@intensity).merge(@@blink).merge(@@underline)
+ @@keywords = @@codes.keys.join("|")
+
+ # returns the text either with or without ansi codes wrapped around
+ # depending on whether stdout is currently attached to a tty.
+ # FIXME: what if we want to write the text to a file i.e. not stdout
+ def self.format_text(text, code, force = false)
+ STDOUT.isatty || force ? "\e[0#{code}m#{text}\e[0m" : text
+ end
+
+ # format is a hash with the following parameters:
+ # - :color: foreground color
+ # - :background: background color
+ # - :intensity: :bold
+ # - :blink: :slow, :rapid
+ # - :underline: :single, :double
+ def self.format(text, format = {}, force = false)
+ code = ";#{@@blink[format[:blink]]}"
+ code += ";#{@@underline[format[:underline]]}"
+ code += ";#{@@intensity[format[:intensity]]}"
+ code += ";3#{@@colors[format[:color]]}"
+ code += ";4#{@@colors[format[:background]]}"
+ format_text(text, code, force)
+ end
+
+ # catches formats of the form:
+ # red_bwhite("red on white")
+ # red_bold("red bold")
+ # red_single("red underline single")
+ # ...
+ # background colors start with a 'b'
+ def self.method_missing(method, text)
+ method = method.to_s
+ if method =~ /^(#{@@keywords})(_(#{@@keywords}))*$/
+ code = method.split(/_/).inject("") { |c, format|
+ c += ";#{@@codes[format.to_sym]}"
+ }
+ format_text(text, code)
+ end
+ end
+
+ module ConsoleFormatWrapper
+ def self.method_missing(method, text)
+ ConsoleFormat.__send__ method, text
+ end
+ end
+
+ # global shortcut function 'fmt'
+ module ::Kernel
+ def fmt(text = nil, format = {}, force = false)
+ if text
+ ConsoleFormat.format(text, format, force)
+ else
+ ConsoleFormatWrapper
+ end
+ end
+ end
+ end
+
+ # Test
+ if __FILE__ == $0
+ fmt "blank"
+ fmt "red", { :color => :red }
+ fmt.red_bold "red bold"
+ fmt.red_blue_byellow_single_bold "blue on yellow underline single_bold"
+ puts ConsoleFormat.format("red", { :color => :red })
+ puts ConsoleFormat.format("blue background", { :background => :blue })
+ puts ConsoleFormat.format("red on white background", { :color => :red, :background => :white })
+ puts ConsoleFormat.format("red bold", { :color => :red, :intensity => :bold })
+ puts ConsoleFormat.format("red blink (slow)", { :color => :red, :intensity => :bold, :blink => :slow })
+ puts ConsoleFormat.format("red bold blink (rapid)", { :color => :red, :intensity => :bold, :blink => :rapid })
+ puts ConsoleFormat.format("green underline single", { :color => :green, :underline => :single })
+ puts ConsoleFormat.format("green underline double", { :color => :green, :underline => :double })
+ puts ConsoleFormat.red_bold("red bold")
+ puts ConsoleFormat.red_bwhite_bold("red on white bold")
+ puts ConsoleFormat.red_single("red underline single")
+ puts ConsoleFormat.bold_red_single("red underline single bold")
+ puts ConsoleFormat.black_bwhite("black on white")
+ end
+end
+
--- /dev/null
+=begin
+ Copyright (C) 2009 Tobias Brunner
+ Hochschule fuer Technik Rapperswil
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+=end
+
+module Dumm
+ class GuestConfig
+ # The name of this guest config.
+ attr_reader :name
+ # The strongSwan config.
+ attr_reader :strongswan
+ # The kernel config
+ attr_reader :kernel
+ # The root directory of this guest (i.e. the diff to the master).
+ attr_reader :root
+ # True if this guest config is invalid
+ attr_reader :invalid
+
+ def initialize(name, config)
+ @name = name
+ @needs_build = true
+ @strongswan, @kernel = config.strongswan, config.kernel
+ @masterfs, @templates = config.masterfs, config.templates
+ @mem, @consoles = config.mem, config.consoles
+ unless @strongswan && @kernel && @masterfs && @mem > 0 && @consoles && !@consoles.empty?
+ puts "Invalid guest configuration: #{name} #{config.inspect}"
+ @invalid = true
+ end
+ end
+
+ def build
+ return unless @needs_build
+ args = "mem=#{@mem}M"
+ @consoles.each_with_index do |con, i|
+ args << " con#{i.next}=#{con}"
+ end
+ # TODO if the masterfs is a tarball, extract that first
+ #Dir.chdir(Testing.root) do
+ # Guest.new @name, @kernel.path || "/home/tbrunner/tbrunner/testing/umlbuild/linux-uml-2.6.21.1", @masterfs, args
+ #end
+ Dir.chdir(Testing.guests_dir) do
+ Dir.mkdir(name, 0775)
+ Dir.chdir(name) do
+ File.symlink(@masterfs, 'master')
+ File.symlink(@kernel.path, 'linux')
+ Dir.mkdir('diff', 0775)
+ Dir.mkdir('union', 0775)
+ File.open('args', 'w') { |f| f.write args }
+ end
+ end
+ @root = File.join(Testing.guests_dir, name, 'diff')
+ tmpl = File.join(@templates, name)
+ if File.directory?(tmpl)
+ FileUtils.cp_r(tmpl + '/.', @root) # '/.' is required to copy the contents of tmpl and not tmpl itself
+ end
+ @needs_build = false
+ end
+
+ end
+end
--- /dev/null
+=begin
+ Copyright (C) 2009 Tobias Brunner
+ Hochschule fuer Technik Rapperswil
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+=end
+
+module Dumm
+ class KernelConfig
+ # The name of this kernel
+ attr_reader :name
+ # The path to the kernel
+ attr_reader :path
+
+ # Creates a new Kernel instance from the given configuration
+ def initialize(name, config)
+ @name = name
+ @needs_build = true
+ @source = (config.source || "none").to_sym
+ @config = config.config if File.file?(config.config || "")
+ config.patches ||= []
+ @patches = config.patches.select { |p| File.exists?(p) && p =~ /\.patch(\.(bz2|gz))?$/ }
+ case @source
+ when :git, :dir
+ unless File.directory?(config.path)
+ raise "Path '#{config.path}' not found!"
+ end
+ @source_path = config.path
+ unless @source == :dir
+ raise "'#{@source_path} is not a git repository!" unless Testing.git?(@source_path)
+ @checkout = config.checkout if Testing.git_tree?(@source_path, config.checkout)
+ end
+ when :tar
+ raise "Tarball '#{config.path}' not found!" unless Testing.tarball?(config.path)
+ @source_path = config.path
+ else
+ raise "Kernel '#{config.path}' not found!" unless File.executable?(config.path)
+ @path = config.path
+ @needs_build = false
+ end
+ end
+
+ # Build the kernel.
+ def build
+ return unless @needs_build
+ build_path = @source_path
+ case @source
+ when :git
+ if @checkout
+ tarball = Testing.archive_git(@source_path, @checkout, "kernel-#{@name}", Testing.build_dir)
+ build_path = Testing.extract_tarball(tarball, Testing.build_dir)
+ end
+ when :tar
+ build_path = Testing.extract_tarball(@source_path, Testing.build_dir)
+ end
+
+ apply_patches(build_path)
+ ensure_config(build_path)
+ @path = File.join(Testing.build_dir, "kernel-#{name}-linux")
+ build_kernel(build_path, @path)
+
+ # TODO we could remove the directory extracted from a tarball and the
+ # tarball itself if it was exported from git.
+
+ @needs_build = false
+ end
+
+ private
+
+ # Apply a list of patches to the given source tree.
+ def apply_patches(dir)
+ Dir.chdir(dir) do
+ @patches.each do |patch|
+ comp = case patch
+ when /\.bz2$/: 'bz'
+ when /\.gz$/: 'z'
+ else ''
+ end
+ `#{comp}cat #{patch} | patch -p1 2>&1`
+ unless $?.success?
+ raise "Failed to apply patch '#{patch}' in '#{dir}'!"
+ end
+ end
+ end
+ end
+
+ # Ensure that we have a kernel config.
+ def ensure_config(dir)
+ config = File.join(dir, ".config")
+ @config ||= config
+ raise "No kernel config found!" unless File.file?(@config)
+ FileUtils.copy_file(@config, config)
+ end
+
+ # Build the kernel and move it to the given location.
+ def build_kernel(dir, kernel)
+ Dir.chdir(dir) do
+ # TODO what about logging
+ `make clean ARCH=um 2>&1`
+ # the next command might interact with the user. since '`' redirects
+ # stdout we would have to use 'system'. currently we use 'yes' to
+ # chose the default value for new kernel options.
+ `yes "" | make oldconfig ARCH=um 2>&1`
+ `make -j 2 linux ARCH=um 2>&1`
+ FileUtils.mv 'linux', kernel
+ end
+ end
+
+ end
+end
--- /dev/null
+=begin
+ Copyright (C) 2009 Tobias Brunner
+ Hochschule fuer Technik Rapperswil
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+=end
+
+module Dumm
+ class StrongswanConfig
+ # The name of this strongSwan config.
+ attr_reader :name
+
+ def initialize(name, config)
+ @name = name
+ @needs_build = true
+ @options = config.options
+ @source = (config.source || "none").to_sym
+ case @source
+ when :git, :dir
+ unless File.directory?(config.path)
+ raise "Path '#{config.path}' not found!"
+ end
+ @source_path = config.path
+ unless @source == :dir
+ raise "'#{@source_path} is not a git repository!" unless Testing.git?(@source_path)
+ @checkout = config.checkout if Testing.git_tree?(@source_path, config.checkout)
+ end
+ when :tar
+ raise "Tarball '#{config.path}' not found!" unless Testing.tarball?(config.path)
+ @source_path = config.path
+ else
+ raise "Specify the source type of strongSwan config '#{name}'"
+ end
+ end
+
+ # Build the strongSwan sources. We build them only within the source tree
+ # if we extracted the sources from a tarball. Otherwise an out-of-tree build
+ # in a subdir of the testing build dir is done.
+ def build
+ return unless @needs_build
+ @build_path = File.join(Testing.build_dir, "strongswan-#{name}")
+ case @source
+ when :git
+ if @checkout
+ tarball = Testing.archive_git(@source_path, @checkout, "strongswan-#{@name}", Testing.build_dir)
+ @source_path = @build_path = Testing.extract_tarball(tarball, Testing.build_dir)
+ end
+ when :tar
+ @source_path = @build_path = Testing.extract_tarball(@source_path, Testing.build_dir)
+ end
+
+ FileUtils.mkdir_p(@build_path)
+ configure(@source_path, @build_path)
+ make(@build_path)
+
+ @needs_build = false
+ end
+
+ def install(target)
+ Dir.chdir(@build_path) do
+ `make install DESTDIR="#{target}" 2>&1`
+ raise "Failed to install strongSwan '#{name}'!" unless $?.success?
+ # FIXME is ldconfig required? how do we run this
+ end
+ end
+
+ private
+
+ # Run the configure script located in directory 'sources' within the
+ # directory given as 'build'. autogen.sh is run if configure does not yet
+ # exist.
+ def configure(sources, build)
+ script = File.join(sources, "configure")
+ unless File.executable?(script)
+ Dir.chdir(sources) do
+ `./autogen.sh 2>&1`
+ raise "Failed to build configure script for strongSwan '#{name}'!" unless $?.success?
+ end
+ end
+ options = [ '--sysconfdir=/etc', '--with-random-device=/dev/urandom' ]
+ @options.each do |opt|
+ key, val = opt.shift
+ options << "--#{val ? 'enable' : 'disable'}-#{key.sub(/_/, '-')}"
+ end
+ Dir.chdir(build) do
+ `#{script} #{options.join(" ")} 2>&1`
+ raise "Failed to configure strongSwan '#{name}'!" unless $?.success?
+ end
+ end
+
+ # Build the strongSwan sources.
+ def make(build)
+ Dir.chdir(build) do
+ `make -j 2>&1`
+ raise "Failed to build strongSwan '#{name}'!" unless $?.success?
+ end
+ end
+
+ end
+end
--- /dev/null
+=begin
+ Copyright (C) 2009 Tobias Brunner
+ Hochschule fuer Technik Rapperswil
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+=end
+
+$LOAD_PATH.unshift File.dirname(__FILE__)
+require 'config'
+
+module Dumm
+ class Testing
+ class << self
+ # The base directory.
+ attr_reader :root
+ # The build directory.
+ attr_reader :build_dir
+ # The guests directory.
+ attr_reader :guests_dir
+ # The global Config instance
+ attr_reader :config
+
+ def init
+ set_directories!
+ config_file = "#{root}/config/default.yml"
+ @config = Config.new(config_file)
+ end
+
+ # Create the testing environment.
+ def make
+ make_kernel
+ make_guests
+ make_strongswan
+ end
+
+ # Check if the given file is a tarball.
+ def tarball?(file)
+ file && File.file?(file) && file =~ /(\.tar(\.(bz2|gz))?|\.t[bg]z)$/
+ end
+
+ # Returns the name of the tarball without extension and path.
+ # This is the assumed name of the directory that the tarball extracts to.
+ def tarball_name(file)
+ file.sub(/^.*\/([^\/]+)(\.tar(\.(bz2|gz))?|\.t[bg]z)$/, '\1')
+ end
+
+ # Check the given path for a git repository. If 'tree' is given we check
+ # that there exists such a point in the git history.
+ def git?(dir)
+ return false unless File.directory?(dir)
+ Dir.chdir(dir) do
+ !`git status`.empty?
+ end
+ end
+
+ # Check that tree points to a valid point in the history of the git
+ # repository (commit, tag, branch).
+ def git_tree?(dir, tree)
+ return false unless File.directory?(dir)
+ Dir.chdir(dir) do
+ tree && !tree.empty? && !`git show #{tree}`.empty?
+ end
+ end
+
+ # Extract the given tarball in directory 'dir'. The tarball is expected
+ # to extract into a directory of the same name. Returns the path to the
+ # extracted directory.
+ # If the expected directory already exists, nothing is done.
+ def extract_tarball(file, dir)
+ target = File.join(dir, tarball_name(file))
+ return target if File.directory?(target)
+ Dir.chdir(dir) do
+ comp = case file
+ when /\.(bz2|tbz)$/: 'j'
+ when /\.(gz|tgz)$/: 'z'
+ else ''
+ end
+ unless system("tar x#{comp}f #{file} 2>&1")
+ raise "Failed to extract tarball '#{file}'!"
+ end
+ unless File.directory?(target)
+ raise "Tarball '#{file}' extracted to unexpected directory!"
+ end
+ end
+ target
+ end
+
+ # Uses 'git archive' to build a tarball from the git repository in
+ # directory 'repo'. 'tree' is the tag, branch or commit from which the
+ # archive is built. The tarball is written to 'dir'/'name'.tar and it will
+ # extract to a directory named 'name'. The filename of the tarball is
+ # returned.
+ def archive_git(repo, tree, name, dir)
+ target = File.join(dir, "#{name}.tar")
+ Dir.chdir(repo) do
+ unless system("git archive --format=tar --prefix=#{name}/ #{tree} > #{target}")
+ raise "Failed to build archive from git repository '#{git}'!"
+ end
+ end
+ target
+ end
+
+ private
+
+ # Sets root to TESTING_ROOT and canonalizes it. Also sets the build
+ # and guest dir based on the root.
+ def set_directories!
+ require 'pathname'
+ raise 'TESTING_ROOT is not set' unless defined?(::TESTING_ROOT)
+ raise 'TESTING_ROOT is not a directory' unless File.directory?(::TESTING_ROOT)
+ @root = Pathname.new(::TESTING_ROOT).realpath.to_s
+ ::TESTING_ROOT.replace @root
+ @build_dir = File.join(@root, 'build')
+ @guests_dir = File.join(@root, 'guests')
+ end
+
+ # Build all required kernels.
+ def make_kernel
+ config.kernels.each do |name, kernel|
+ kernel.build
+ end
+ end
+
+ # Create all the guests.
+ def make_guests
+ config.guests.each do |name, guest|
+ guest.build
+ end
+ end
+
+ # Build and install all strongSwan versions.
+ def make_strongswan
+ config.strongswan.each do |name, strongswan|
+ strongswan.build
+ guests = config.guests.select { |n, g| strongswan.eql? g.strongswan }
+ guests.each do |name, guest|
+ strongswan.install guest.root
+ end
+ end
+ end
+
+ end
+ end
+end
--- /dev/null
+#!/usr/bin/ruby
+
+=begin
+ Copyright (C) 2009 Tobias Brunner
+ Hochschule fuer Technik Rapperswil
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+=end
+
+#require 'dumm'
+require 'lib/testing'
+require 'fileutils'
+
+include Dumm
+
+# are we running as superuser
+unless Process.uid == 0
+ puts "Please run #{$0} as superuser!"
+ exit 1
+end
+
+TESTING_ROOT = File.dirname(__FILE__)
+
+Testing.init
+
+def continue?(msg)
+ puts msg
+ print "Continue? [Y|n]: "
+ if gets.capitalize =~ /^N.*/
+ exit 1
+ end
+end
+
+# cleanup the build dir
+build_dir = Testing.build_dir
+if File.directory?(build_dir)
+ continue?("The existing build directory #{build_dir} will be deleted!")
+ FileUtils.remove_entry_secure(build_dir, force = true)
+end
+FileUtils.mkdir_p(build_dir)
+
+# cleanup the guest dir
+guests_dir = Testing.guests_dir
+if File.directory?(guests_dir)
+ continue?("All guests in #{guests_dir} will be deleted!")
+ #Guest.each { |g| g.delete }
+ FileUtils.remove_entry_secure(guests_dir, force = true)
+end
+FileUtils.mkdir_p(guests_dir)
+
+Testing.make
+
+puts "built"
+