[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-API] [PATCH] updates for tap-ctl



# HG changeset patch
# User Jon Ludlam <jonathan.ludlam@xxxxxxxxxxxxx>
# Date 1282568559 -3600
# Node ID 0cf8a11ad69a7e2012384bf6b8e63b5f3fac8dc3
# Parent  0adab5c36ecab8252b6f354a9b6d285d30c94254
Updates for the tap-ctl module: initial implementation of dummy mode.

Signed-off-by: Jon Ludlam <jonathan.ludlam@xxxxxxxxxxxxx>

diff -r 0adab5c36eca -r 0cf8a11ad69a tapctl/tapctl.ml
--- a/tapctl/tapctl.ml  Mon Aug 23 13:59:08 2010 +0100
+++ b/tapctl/tapctl.ml  Mon Aug 23 14:02:39 2010 +0100
@@ -8,7 +8,8 @@
        tapdisk_pid : int;
 } with rpc
 
-type t = tapdev * string * (string * string) option
+type t = tapdev * string * (string * string) option 
+
 
 type context = {
        host_local_dir: string;
@@ -16,6 +17,8 @@
 }
 
 let create () = { host_local_dir = ""; dummy = false }
+let create_dummy dir = 
+       {host_local_dir=dir; dummy=true }
 
 let get_devnode_dir ctx =
        let d = Printf.sprintf "%s/dev/xen/blktap-2" ctx.host_local_dir in
@@ -30,86 +33,292 @@
 | Vhd -> "vhd"
 | Aio -> "aio"
 
+(* DUMMY MODE FUNCTIONS *)
+
+let get_minor tapdev = tapdev.minor
+let get_tapdisk_pid tapdev = tapdev.tapdisk_pid
+
+module Dummy = struct 
+       type dummy_tap = {
+               d_minor : int option;
+               d_pid : int option;
+               d_state : string option;
+               d_args : string option;
+       } and dummy_tap_list = dummy_tap list with rpc
+                       
+       let d_lock = Mutex.create ()
+               
+       let get_dummy_tapdisk_list_filename ctx =
+               let file = Printf.sprintf "%s/dev/tapdisks" ctx.host_local_dir 
in
+               Unixext.mkdir_rec (Filename.dirname file) 0o777;
+               file
+                       
+       let get_dummy_tapdisk_list ctx =
+               let filename = get_dummy_tapdisk_list_filename ctx in
+               try
+                       dummy_tap_list_of_rpc (Jsonrpc.of_string 
(Unixext.read_whole_file_to_string filename))
+               with _ -> []
+                       
+       let write_dummy_tapdisk_list ctx list =
+               let filename = get_dummy_tapdisk_list_filename ctx in
+               let str = Jsonrpc.to_string (rpc_of_dummy_tap_list list) in
+               Unixext.write_string_to_file filename str
+                       
+       let find_next_unused_number list =
+               if List.length list = 0 then 0 else
+                       let list_plus_one = List.map ((+) 1) list in
+                       let diff = List.set_difference list_plus_one list in
+                       List.hd diff
+                               
+       let find_next_unused_minor list =
+               let minors = List.filter_map (fun t -> t.d_minor) list in
+               find_next_unused_number minors
+                       
+       let find_next_unused_pid list =
+               let pids = List.filter_map (fun t -> t.d_pid) list in
+               find_next_unused_number pids
+                       
+       let get_entry_from_pid pid list =
+               try Some (List.find (fun entry -> entry.d_pid = Some pid) list) 
with _ -> None
+                       
+       let get_entry_from_minor minor list =
+               try Some (List.find (fun entry -> entry.d_minor = Some minor) 
list) with _ -> None
+                       
+       let allocate ctx =
+               Mutex.execute d_lock (fun () -> 
+                       let list = get_dummy_tapdisk_list ctx in
+                       let minor = find_next_unused_minor list in
+                       let entry = {
+                               d_minor = Some minor;
+                               d_pid = None;
+                               d_state = None;
+                               d_args = None;
+                       } in
+                       write_dummy_tapdisk_list ctx (entry::list);
+                       minor
+               )
+                       
+       let spawn ctx =
+               Mutex.execute d_lock (fun () -> 
+                       let list = get_dummy_tapdisk_list ctx in
+                       let pid = find_next_unused_pid list in
+                       let entry = {
+                               d_minor = None;
+                               d_pid = Some pid;
+                               d_state = None;
+                               d_args = None;
+                       } in
+                       write_dummy_tapdisk_list ctx (entry::list);
+                       pid
+               )
+                       
+       let attach ctx pid minor =
+               Mutex.execute d_lock (fun () -> 
+                       let list = get_dummy_tapdisk_list ctx in
+                       begin (* sanity check *)
+                               match (get_entry_from_pid pid list, 
get_entry_from_minor minor list) with
+                                       | Some e1, Some e2 ->
+                                               if e1.d_minor <> None then 
failwith "pid already attached!";
+                                               if e2.d_pid <> None then 
failwith "minor already in use!";
+                                       | None, Some _ -> 
+                                               failwith "pid nonexistant"
+                                       | Some _, None ->
+                                               failwith "minor nonexistant"
+                                       | None, None -> 
+                                               failwith "neither pid nor minor 
exist!"
+                       end;
+                       let new_entry = {
+                               d_minor = Some minor;
+                               d_pid = Some pid;
+                               d_state = Some "0";
+                               d_args = None;
+                       } in
+                       let list = List.filter (fun e -> e.d_pid <> Some pid && 
e.d_minor <> Some minor) list in
+                       write_dummy_tapdisk_list ctx (new_entry::list);
+                       {tapdisk_pid=pid; minor=minor})
+               
+       let _open ctx t leaf_path driver =
+               let args = Printf.sprintf "%s:%s" (string_of_driver driver) 
leaf_path in
+               Mutex.execute d_lock (fun () -> 
+                       let list = get_dummy_tapdisk_list ctx in
+                       let list = List.map (fun e -> 
+                               if e.d_pid = Some t.tapdisk_pid && e.d_minor = 
Some t.minor 
+                               then { e with 
+                                       d_state = Some "0";
+                                       d_args = Some args }
+                               else e) list in
+                       write_dummy_tapdisk_list ctx list)
+
+       let close ctx t =
+               Mutex.execute d_lock (fun () -> 
+                       let list = get_dummy_tapdisk_list ctx in
+                       let list = List.map (fun e -> 
+                               if e.d_pid = Some t.tapdisk_pid && e.d_minor = 
Some t.minor 
+                               then { e with 
+                                       d_state = Some "0x2";
+                                       d_args = None }
+                               else e) list in
+                       write_dummy_tapdisk_list ctx list)
+
+       let pause ctx t =
+               Mutex.execute d_lock (fun () -> 
+                       let list = get_dummy_tapdisk_list ctx in
+                       let list = List.map (fun e -> 
+                               if e.d_pid = Some t.tapdisk_pid && e.d_minor = 
Some t.minor 
+                               then { e with d_state = Some "0x2a" }
+                               else e) list in
+                       write_dummy_tapdisk_list ctx list)
+
+       let unpause ctx t leaf_path driver =
+               let args = Printf.sprintf "%s:%s" (string_of_driver driver) 
leaf_path in
+               Mutex.execute d_lock (fun () -> 
+                       let list = get_dummy_tapdisk_list ctx in
+                       let list = List.map (fun e -> 
+                               if e.d_pid = Some t.tapdisk_pid && e.d_minor = 
Some t.minor 
+                               then { e with 
+                                       d_state = Some "0";
+                                       d_args = Some args }
+                               else e) list in
+                       write_dummy_tapdisk_list ctx list)
+
+       let detach ctx t = 
+               Mutex.execute d_lock (fun () -> 
+                       let list = get_dummy_tapdisk_list ctx in
+                       let (a,b) = get_entry_from_pid t.tapdisk_pid list, 
get_entry_from_minor t.minor list in
+                       if a<>None && a <> b then failwith "Not attached";
+                       let list = List.filter (fun entry -> entry.d_pid <> 
Some t.tapdisk_pid) list in
+                       let list = { d_minor = Some t.minor;
+                                    d_pid = None;
+                                                d_state = None;
+                                                d_args = None; }::list in
+                       write_dummy_tapdisk_list ctx list)
+
+       let free ctx minor =
+               Mutex.execute d_lock (fun () ->
+                       let list = get_dummy_tapdisk_list ctx in
+                       let entry = get_entry_from_minor minor list in
+                       begin (* sanity check *)
+                               match entry with
+                                       | Some e -> if e.d_pid <> None then 
failwith "Can't free an attached minor"
+                                       | None -> failwith "Unknown minor"
+                       end;
+                       let list = List.filter (fun e -> e.d_minor <> Some 
minor) list in
+                       write_dummy_tapdisk_list ctx list)
+
+       let list ?t ctx =
+               Mutex.execute d_lock (fun () -> 
+                       let list = get_dummy_tapdisk_list ctx in
+                       List.filter_map (fun e -> 
+                               let args = 
+                                       match Opt.map (String.split ':') 
e.d_args with
+                                               | Some (ty::arguments) ->
+                                                       Some (ty,String.concat 
":" arguments)
+                                               | _ -> None
+                               in
+                               match (e.d_minor, e.d_pid, e.d_state, t) with
+                                       | Some m, Some p, Some s, None ->
+                                               Some ({tapdisk_pid=p; 
minor=m},s,args) 
+                                       | Some m, Some p, Some s, Some t ->
+                                               if t.tapdisk_pid = p && 
t.minor=m then 
+                                                       Some ({tapdisk_pid=p; 
minor=m},s,args) 
+                                               else 
+                                                       None
+                                       | _ -> None) list)
+end
+               
+
+(* END OF DUMMY STUFF *)
+
 let invoke_tap_ctl ctx cmd args =
-       if ctx.dummy then
-               match cmd with
-                       | "allocate" ->
-                               let path = Printf.sprintf "%s%d" 
(get_blktapstem ctx) (Random.int max_int) in
-                               Unixext.mkdir_rec (Filename.dirname path) 0o700;
-                               Unix.close (Unix.openfile path [Unix.O_RDWR; 
Unix.O_CREAT; Unix.O_EXCL] 0o700);
-                               path
-                       | _ -> ""
-       else
-               let stdout, stderr = execute_command_get_output ~env:[|"PATH=" 
^ (Sys.getenv "PATH") |] "/usr/sbin/tap-ctl" (cmd::args) in
-               stdout
+       let stdout, stderr = execute_command_get_output ~env:[|"PATH=" ^ 
(Sys.getenv "PATH") |] "/usr/sbin/tap-ctl" (cmd::args) in
+       stdout
 
 let allocate ctx =
-       let result = invoke_tap_ctl ctx "allocate" [] in
-       let stem = get_tapdevstem ctx in
-       let stemlen = String.length stem in
-       assert(String.startswith stem result);
-       let minor_str = (String.sub result stemlen (String.length result - 
stemlen)) in
-       let minor = Scanf.sscanf minor_str "%d" (fun d -> d) in
-       minor
+       if ctx.dummy then Dummy.allocate ctx else begin
+               let result = invoke_tap_ctl ctx "allocate" [] in
+               let stem = get_tapdevstem ctx in
+               let stemlen = String.length stem in
+               assert(String.startswith stem result);
+               let minor_str = (String.sub result stemlen (String.length 
result - stemlen)) in
+               let minor = Scanf.sscanf minor_str "%d" (fun d -> d) in
+               minor
+       end
 
 let devnode ctx minor =
        Printf.sprintf "%s%d" (get_tapdevstem ctx) minor
 
 let spawn ctx =
-       let result = invoke_tap_ctl ctx "spawn" [] in
-       let pid = Scanf.sscanf result "%d" (fun d -> d) in
-       pid
+       if ctx.dummy then Dummy.spawn ctx else begin
+               let result = invoke_tap_ctl ctx "spawn" [] in
+               let pid = Scanf.sscanf result "%d" (fun d -> d) in
+               pid
+       end
 
 let attach ctx pid minor =
-       let _ = invoke_tap_ctl ctx "attach" ["-p"; string_of_int pid; "-m"; 
string_of_int minor] in
-       {minor=minor; tapdisk_pid=pid}
+       if ctx.dummy then Dummy.attach ctx pid minor else begin
+               let _ = invoke_tap_ctl ctx "attach" ["-p"; string_of_int pid; 
"-m"; string_of_int minor] in
+               {minor=minor; tapdisk_pid=pid}
+       end
 
 let args tapdev =
        ["-p"; string_of_int tapdev.tapdisk_pid; "-m"; string_of_int 
tapdev.minor]
 
 let _open ctx t leaf_path driver =
-       ignore(invoke_tap_ctl ctx "open" (args t @ ["-a"; Printf.sprintf 
"%s:%s" (string_of_driver driver) leaf_path]))
+       if ctx.dummy then Dummy._open ctx t leaf_path driver else begin
+               ignore(invoke_tap_ctl ctx "open" (args t @ ["-a"; 
Printf.sprintf "%s:%s" (string_of_driver driver) leaf_path]))
+       end
 
 let close ctx t =
-       ignore(invoke_tap_ctl ctx "close" (args t))
-
+       if ctx.dummy then Dummy.close ctx t else begin
+               ignore(invoke_tap_ctl ctx "close" (args t))
+       end
 let pause ctx t =
-       ignore(invoke_tap_ctl ctx "pause" (args t))
+       if ctx.dummy then Dummy.pause ctx t else begin
+               ignore(invoke_tap_ctl ctx "pause" (args t))
+       end
 
 let unpause ctx t leaf_path driver =
-       ignore(invoke_tap_ctl ctx "unpause" (args t @ [ "-a"; Printf.sprintf 
"%s:%s" (string_of_driver driver) leaf_path ]))
+       if ctx.dummy then Dummy.unpause ctx t leaf_path driver else begin
+               ignore(invoke_tap_ctl ctx "unpause" (args t @ [ "-a"; 
Printf.sprintf "%s:%s" (string_of_driver driver) leaf_path ]))
+       end
 
 let detach ctx t =
-       ignore(invoke_tap_ctl ctx "detach" (args t))
+       if ctx.dummy then Dummy.detach ctx t else begin
+               ignore(invoke_tap_ctl ctx "detach" (args t))
+       end
 
 let free ctx minor =
-       ignore(invoke_tap_ctl ctx "free" ["-m"; string_of_int minor])
+       if ctx.dummy then Dummy.free ctx minor else begin
+               ignore(invoke_tap_ctl ctx "free" ["-m"; string_of_int minor])
+       end
 
 let list ?t ctx =
-       let args = match t with
-               | Some tapdev -> args tapdev
-               | None -> []
-       in
-       let result = invoke_tap_ctl ctx "list" args in
-       let lines = String.split '\n' result in
-       List.filter_map (fun line ->
-               try 
-                       let fields = String.split_f String.isspace line in
-                       let assoc = List.filter_map (fun field -> 
-                               match String.split '=' field with
-                                       | x::ys -> 
-                                               Some (x,String.concat "=" ys)
-                                       | _ -> 
-                                               None) fields
-                       in
-                       let args = 
-                               match String.split ':' (List.assoc "args" 
assoc) with
-                                       | ty::arguments ->
-                                               Some (ty,String.concat ":" 
arguments)
-                                       | _ -> None
-                       in
-                       Some ({tapdisk_pid=int_of_string (List.assoc "pid" 
assoc); minor=int_of_string (List.assoc "minor" assoc)},(List.assoc "state" 
assoc),args)
-               with _ -> None) lines
+       if ctx.dummy then Dummy.list ?t ctx else begin
+               let args = match t with
+                       | Some tapdev -> args tapdev
+                       | None -> []
+               in
+               let result = invoke_tap_ctl ctx "list" args in
+               let lines = String.split '\n' result in
+               List.filter_map (fun line ->
+                       try 
+                               let fields = String.split_f String.isspace line 
in
+                               let assoc = List.filter_map (fun field -> 
+                                       match String.split '=' field with
+                                               | x::ys -> 
+                                                       Some (x,String.concat 
"=" ys)
+                                               | _ -> 
+                                                       None) fields
+                               in
+                               let args = 
+                                       match String.split ':' (List.assoc 
"args" assoc) with
+                                               | ty::arguments ->
+                                                       Some (ty,String.concat 
":" arguments)
+                                               | _ -> None
+                               in
+                               Some ({tapdisk_pid=int_of_string (List.assoc 
"pid" assoc); minor=int_of_string (List.assoc "minor" assoc)},(List.assoc 
"state" assoc),args)
+                       with _ -> None) lines
+       end
 
 let is_paused ctx t =
        let result = list ~t ctx in
diff -r 0adab5c36eca -r 0cf8a11ad69a tapctl/tapctl.mli
--- a/tapctl/tapctl.mli Mon Aug 23 13:59:08 2010 +0100
+++ b/tapctl/tapctl.mli Mon Aug 23 14:02:39 2010 +0100
@@ -3,14 +3,21 @@
 val tapdev_of_rpc : Rpc.t -> tapdev
 val rpc_of_tapdev : tapdev -> Rpc.t
 
+val get_minor : tapdev -> int
+val get_tapdisk_pid : tapdev -> int
+
 type t = tapdev * string * (string * string) option
 
 type context
 val create : unit -> context
+val create_dummy : string -> context
 
 type driver = Vhd | Aio
 val string_of_driver : driver -> string
 
+val get_devnode_dir : context -> string
+val get_tapdevstem : context -> string
+
 val allocate : context -> int
 val devnode : context -> int -> string
 val spawn : context -> int
 tapctl/tapctl.ml  |  319 ++++++++++++++++++++++++++++++++++++++++++++---------
 tapctl/tapctl.mli |    7 +
 2 files changed, 271 insertions(+), 55 deletions(-)


Attachment: xen-api-libs.hg.patch
Description: Text Data

_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.