WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-api

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

To: xen-api@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-API] [PATCH] updates for tap-ctl
From: David Scott <dave.scott@xxxxxxxxxxxxx>
Date: Mon, 23 Aug 2010 14:02:54 +0100
Delivery-date: Mon, 23 Aug 2010 06:25:44 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-api-request@lists.xensource.com?subject=help>
List-id: Discussion of API issues surrounding Xen <xen-api.lists.xensource.com>
List-post: <mailto:xen-api@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-api-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mercurial-patchbomb/1.4.3
# 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
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-API] [PATCH] updates for tap-ctl, David Scott <=