apitest.lua revision f080ffd7d656fbd9505a8e8eb52a05d61355c677
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek#!/usr/bin/env lua
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek--
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- test the lxc lua api
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek--
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- Copyright © 2012 Oracle.
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek--
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- Authors:
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- Dwight Engen <dwight.engen@oracle.com>
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek--
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- This library is free software; you can redistribute it and/or modify
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- it under the terms of the GNU General Public License version 2, as
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- published by the Free Software Foundation.
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek--
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- This program is distributed in the hope that it will be useful,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- but WITHOUT ANY WARRANTY; without even the implied warranty of
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- GNU General Public License for more details.
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek--
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- You should have received a copy of the GNU General Public License along
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- with this program; if not, write to the Free Software Foundation, Inc.,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek--
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozeklocal lxc = require("lxc")
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozeklocal getopt = require("alt_getopt")
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozeklocal LXC_PATH = lxc.path_get()
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozeklocal container
1a542b3698d8c42cf075b722f8838f106eb09fccPavel Březinalocal cfg_containers = {}
1a542b3698d8c42cf075b722f8838f106eb09fccPavel Březinalocal optarg = {}
1a542b3698d8c42cf075b722f8838f106eb09fccPavel Březinalocal optind = {}
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina
1a542b3698d8c42cf075b722f8838f106eb09fccPavel Březinafunction printf(...)
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek local function wrapper(...) io.write(string.format(...)) end
fb4e4c4eb6a6dc732370584f70d23dd4a2c5c7b6Pavel Březina local status, result = pcall(wrapper, ...)
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek if not status then
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek error(result, 2)
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek end
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozekend
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozekfunction log(level, ...)
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek if (optarg["v"] >= level) then
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek printf(os.date("%Y-%m-%d %T "))
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek printf(...)
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek printf("\n")
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek end
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozekend
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březinafunction die(...)
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina printf(...)
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina os.exit(1)
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březinaend
f7af8c5b369938725e47585c641ae5b017d442a1Pavel Březina
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březinafunction test_global_info()
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina local cfg_containers
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina local run_containers
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina log(0, "%-20s %s", "LXC version:", lxc.version_get())
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina log(0, "%-20s %s", "Container name:", optarg["n"])
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek if (optarg["c"]) then
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina log(0, "%-20s %s", "Creating container:", "yes")
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina log(0, "%-20s %s", "With template:", optarg["t"])
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina end
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina log(0, "%-20s %s", "Containers path:", LXC_PATH)
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina cfg_containers = lxc.containers_configured()
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina log(0, "%-20s", "Containers configured:")
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek for _,v in ipairs(cfg_containers) do
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek log(0, " %s", v)
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek end
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek run_containers = lxc.containers_running(true)
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek log(0, "%-20s", "Containers running:")
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce for _,v in ipairs(run_containers) do
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce log(0, " %s", v)
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce end
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozekend
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozekfunction test_container_new()
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce container = lxc.container:new(optarg["n"])
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce assert(container ~= nil)
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce assert(container:config_file_name() == string.format("%s/%s/config", LXC_PATH, optarg["n"]))
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorceend
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorcefunction test_container_create()
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce if (optarg["c"]) then
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce log(0, "%-20s %s", "Destroy existing container:", optarg["n"])
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce container:destroy()
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce assert(container:defined() == false)
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce else
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina local cfg_containers = lxc.containers_configured()
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina if (cfg_containers[optarg["n"]]) then
b0fa48b0d612b46a86e45f8e4b5d9feae9784c2bSimo Sorce log(0, "%-20s %s", "Use existing container:", optarg["n"])
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina return
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina end
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina end
9675bccabff4e79d224f64611ad9ff3e073b488eSimo Sorce log(0, "%-20s %s", "Creating rootfs using:", optarg["t"])
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina container:create(optarg["t"])
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina assert(container:defined() == true)
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek assert(container:name() == optarg["n"])
end
function test_container_started()
local now_running
log(2, "state:%s pid:%d\n", container:state(), container:init_pid())
assert(container:init_pid() > 1)
assert(container:running() == true)
assert(container:state() == "RUNNING")
now_running = lxc.containers_running(true)
assert(now_running[optarg["n"]] ~= nil)
log(1, "%-20s %s", "Running, init pid:", container:init_pid())
end
function test_container_stopped()
local now_running
assert(container:init_pid() == -1)
assert(container:running() == false)
assert(container:state() == "STOPPED")
now_running = lxc.containers_running(true)
assert(now_running[optarg["n"]] == nil)
end
function test_container_frozen()
local now_running
assert(container:init_pid() > 1)
assert(container:running() == true)
assert(container:state() == "FROZEN")
now_running = lxc.containers_running(true)
assert(now_running[optarg["n"]] ~= nil)
end
function test_container_start()
log(0, "Starting...")
if (not container:start()) then
log(1, "Start returned failure, waiting another 10 seconds...")
container:wait("RUNNING", 10)
end
container:wait("RUNNING", 1)
end
function test_container_stop()
log(0, "Stopping...")
if (not container:stop()) then
log(1, "Stop returned failure, waiting another 10 seconds...")
container:wait("STOPPED", 10)
end
container:wait("STOPPED", 1)
end
function test_container_freeze()
log(0, "Freezing...")
if (not container:freeze()) then
log(1, "Freeze returned failure, waiting another 10 seconds...")
container:wait("FROZEN", 10)
end
end
function test_container_unfreeze()
log(0, "Unfreezing...")
if (not container:unfreeze()) then
log(1, "Unfreeze returned failure, waiting another 10 seconds...")
container:wait("RUNNING", 10)
end
end
function test_container_shutdown()
log(0, "Shutting down...")
container:shutdown(5)
if (container:running()) then
test_container_stop()
end
end
function test_container_in_cfglist(should_find)
local cfg_containers = lxc.containers_configured()
if (should_find) then
assert(cfg_containers[container:name()] ~= nil)
else
assert(cfg_containers[container:name()] == nil)
end
end
function test_config_items()
log(0, "Test set/clear configuration items...")
-- test setting a 'single type' item
assert(container:get_config_item("lxc.utsname") == optarg["n"])
container:set_config_item("lxc.utsname", "foobar")
assert(container:get_config_item("lxc.utsname") == "foobar")
container:set_config_item("lxc.utsname", optarg["n"])
assert(container:get_config_item("lxc.utsname") == optarg["n"])
-- test clearing/setting a 'list type' item
container:clear_config_item("lxc.cap.drop")
container:set_config_item("lxc.cap.drop", "new_cap1")
container:set_config_item("lxc.cap.drop", "new_cap2")
local cap_drop = container:get_config_item("lxc.cap.drop")
assert(cap_drop["new_cap1"] ~= nil)
assert(cap_drop["new_cap2"] ~= nil)
-- note: clear_config_item only works on list type items
container:clear_config_item("lxc.cap.drop")
assert(container:get_config_item("lxc.cap.drop") == nil)
local altname = "/tmp/" .. optarg["n"] .. ".altconfig"
log(0, "Test saving to an alternate (%s) config file...", altname)
assert(container:save_config(altname))
assert(os.remove(altname))
end
function test_config_mount_entries()
local mntents
-- mount entries are a list type item
mntents = container:get_config_item("lxc.mount.entry")
log(0, "Mount entries:")
for _,v in ipairs(mntents) do
log(0, " %s", v)
end
end
function test_config_keys()
local keys
keys = container:get_keys()
log(0, "Top level keys:")
for k,v in pairs(keys) do
log(0, " %s = %s", k, v or "")
end
end
function test_config_network(net_nr)
log(0, "Test network %d config...", net_nr)
local netcfg
netcfg = container:get_keys("lxc.network." .. net_nr)
if (netcfg == nil) then
return
end
for k,v in pairs(netcfg) do
log(0, " %s = %s", k, v or "")
end
assert(netcfg["flags"] == "up")
assert(container:get_config_item("lxc.network."..net_nr..".type") == "veth")
end
function usage()
die("Usage: apitest <options>\n" ..
" -v|--verbose increase verbosity with each -v\n" ..
" -h|--help print help message\n" ..
" -n|--name name of container to use for testing\n" ..
" -c|--create create the test container anew\n" ..
" -l|--login do interactive login test\n" ..
" -t|--template template to use when creating test container\n"
)
end
local long_opts = {
verbose = "v",
help = "h",
name = "n",
create = "c",
template = "t",
}
optarg,optind = alt_getopt.get_opts (arg, "hvn:ct:", long_opts)
optarg["v"] = tonumber(optarg["v"]) or 0
optarg["n"] = optarg["n"] or "lua-apitest"
optarg["c"] = optarg["c"] or nil
optarg["t"] = optarg["t"] or "busybox"
if (optarg["h"] ~= nil) then
usage()
end
test_global_info()
test_container_new()
test_container_create()
test_container_stopped()
test_container_in_cfglist(true)
test_config_items()
test_config_keys()
test_config_mount_entries()
test_config_network(0)
test_container_start()
test_container_started()
test_container_freeze()
test_container_frozen()
test_container_unfreeze()
test_container_started()
test_container_shutdown()
test_container_stopped()
container:destroy()
test_container_in_cfglist(false)
log(0, "All tests passed")