Permalink
Browse files

Examples and tests for LXC

  • Loading branch information...
1 parent 1d04634 commit c84485817c9c9cc5fa0b2d099453358027aa4459 @msantos committed Sep 13, 2012
Showing with 121 additions and 7 deletions.
  1. +51 −0 README.md
  2. +70 −7 test/verx_tests.erl
View
@@ -396,6 +396,54 @@ Here is an example of using the libvirt stream interface.
{ok, Mime, File}.
+## CREATING LINUX CONTAINERS
+
+This example will generate many Linux containers (LXC) attached to a
+bridge (br0).
+
+ -module(clxc).
+ -export([start/2, start/3, create/2, template/2]).
+
+ start(Prefix, Num) ->
+ {ok, Ref} = verx_client:start(),
+ ok = verx:open(Ref, ["lxc:///", 0]),
+ start(Ref, Prefix, Num).
+
+ start(_Ref, _Prefix, 0) ->
+ ok;
+
+ start(Ref, Prefix, Num) ->
+ Name = Prefix ++ integer_to_list(Num),
+
+ <<Bytes:3/bytes, _/binary>> = erlang:md5(Name),
+ Macaddr = "52:54:00:" ++ string:join([ httpd_util:integer_to_hexlist(N)
+ || <<N:8>> <= Bytes ], ":"),
+
+ XML = template(Name, Macaddr),
+ ok = create(Ref, XML),
+
+ start(Ref, Prefix, Num-1).
+
+ create(Ref, XML) ->
+ {ok, [Domain]} = verx:domain_define_xml(Ref, [XML]),
+ verx:domain_create(Ref, [Domain]).
+
+ template(Name, Macaddr) ->
+ "<domain type='lxc'>
+ <name>" ++ Name ++ "</name>
+ <memory>102400</memory>
+ <os>
+ <type>exe</type>
+ <init>/bin/sh</init>
+ </os>
+ <devices>
+ <console type='pty'/>
+ <interface type='bridge'>
+ <mac address='" ++ Macaddr ++ "'/>
+ <source bridge='br0'/>
+ </interface>
+ </devices>
+ </domain>".
## GENERATING THE REMOTE PROTOCOL MODULE
@@ -423,3 +471,6 @@ If there are any errors, read through `bin/gen_remote_protocol.escript`.
* verx\_client\_tcp
* gen\_server halts when receiving a tcp\_closed message, causes an
error if the caller does a verx\_client:close/1
+
+* need to support multiple, active calls?
+ * have a process per serial number with a timeout
View
@@ -38,17 +38,21 @@
verx_test_() ->
{timeout, 120, [
- {?LINE, fun() -> run_vm(verx_client_unix) end},
- {?LINE, fun() -> run_vm(verx_client_tcp) end},
- {?LINE, fun() -> run_vm(verx_client_tls) end}
+ {?LINE, fun() -> run(kvm, verx_client_unix) end},
+ {?LINE, fun() -> run(kvm, verx_client_tcp) end},
+ {?LINE, fun() -> run(kvm, verx_client_tls) end},
+
+ {?LINE, fun() -> run(lxc, verx_client_unix) end},
+ {?LINE, fun() -> run(lxc, verx_client_tcp) end},
+ {?LINE, fun() -> run(lxc, verx_client_tls) end}
]}.
-run_vm(Transport) ->
- error_logger:info_report([{transport, Transport}]),
+run(kvm, Transport) ->
+ error_logger:info_report([{vm, kvm}, {transport, Transport}]),
{ok, Ref} = verx_client:start([{transport, Transport}]),
ok = verx:open(Ref),
- {ok, Domain} = create(Ref),
+ {ok, Domain} = create(kvm, Ref),
[ begin ok = ?MODULE:Fun({Ref, Domain}) end ||
Fun <- [
@@ -59,6 +63,20 @@ run_vm(Transport) ->
ok = destroy(Ref, Domain),
+ ok;
+
+run(lxc, Transport) ->
+ error_logger:info_report([{vm, lxc}, {transport, Transport}]),
+
+ {ok, Ref} = verx_client:start([{transport, Transport}]),
+ ok = verx:open(Ref, ["lxc:///", 0]),
+ {ok, Domain} = create(lxc, Ref),
+
+ % XXX be careful here, the container is running as root
+ ok = console_create_file(Ref, Transport, Domain),
+
+ ok = destroy(Ref, Domain),
+
ok.
domain_list_info({Ref, Domain}) ->
@@ -139,7 +157,7 @@ result(Call, {error, _Error} = N) ->
%%% Internal functions
%%-------------------------------------------------------------------------
-create(Ref) ->
+create(kvm, Ref) ->
Path = filename:join([
filename:dirname(code:which(vert)),
"..",
@@ -151,11 +169,56 @@ create(Ref) ->
{ok, [Domain]} = verx:domain_define_xml(Ref, [XML]),
ok = verx:domain_create(Ref, [Domain]),
+ {ok, Domain};
+
+create(lxc, Ref) ->
+ Name = "test-" ++ integer_to_list(erlang:phash2(Ref)),
+
+ <<Bytes:3/bytes, _/binary>> = erlang:md5(Name),
+ Macaddr = "52:54:00:" ++ string:join([ httpd_util:integer_to_hexlist(N)
+ || <<N:8>> <= Bytes ], ":"),
+
+ XML = template(Name, Macaddr),
+
+ {ok, [Domain]} = verx:domain_define_xml(Ref, [XML]),
+ verx:domain_create(Ref, [Domain]),
+
{ok, Domain}.
+template(Name, Macaddr) ->
+"<domain type='lxc'>
+ <name>" ++ Name ++ "</name>
+ <memory>102400</memory>
+ <os>
+ <type>exe</type>
+ <init>/bin/sh</init>
+ </os>
+ <devices>
+ <console type='pty'/>
+ <interface type='bridge'>
+ <mac address='" ++ Macaddr ++ "'/>
+ <source bridge='br0'/>
+ </interface>
+ </devices>
+</domain>".
+
destroy(Ref, Domain) ->
ok = verx:domain_destroy(Ref, [Domain]),
ok = verx:domain_undefine(Ref, [Domain]),
verx:close(Ref),
catch verx_client:stop(Ref),
ok.
+
+console_create_file(Ref, verx_client_unix, Domain) ->
+ File = "/tmp/console-test-" ++ os:getpid(),
+ {ok, FH} = file:open(File, [raw, write, exclusive]),
+ ok = file:close(FH),
+ ok = verx:domain_open_console(Ref, [Domain, void, 0]),
+ ok = verx_client:send(Ref, [list_to_binary(["/bin/rm ", File, "\n"])]),
+ verx_client:finish(Ref),
+ % XXX race condition: must wait for the file to disappear from /tmp
+ timer:sleep(1000),
+ {error, enoent} = file:read_file(File),
+ ok;
+console_create_file(_Ref, _, _Domain) ->
+ ok.

0 comments on commit c844858

Please sign in to comment.