@@ -107,23 +107,43 @@ let fork_exec_rpc root_dir script_name args response_of_rpc =
107107 end
108108
109109module Attached_SRs = struct
110- let sr_table = String.Table. create ()
110+ let sr_table : string String.Table.t ref = ref (String.Table. create () )
111+ let state_path = ref None
111112
112113 let add smapiv2 plugin =
113- Hashtbl. replace sr_table smapiv2 plugin;
114+ Hashtbl. replace ! sr_table smapiv2 plugin;
115+ ( match ! state_path with
116+ | None ->
117+ return ()
118+ | Some path ->
119+ let contents = String.Table. sexp_of_t (fun x -> Sexplib.Sexp. Atom x) ! sr_table |> Sexplib.Sexp. to_string in
120+ Writer. save path ~contents
121+ ) >> = fun () ->
114122 return (Ok () )
115123
116124 let find smapiv2 =
117- match Hashtbl. find sr_table smapiv2 with
125+ match Hashtbl. find ! sr_table smapiv2 with
118126 | None ->
119127 let open Storage_interface in
120128 let exnty = Exception. Sr_not_attached smapiv2 in
121129 return (Error (Exception. rpc_of_exnty exnty))
122130 | Some sr -> return (Ok sr)
123131
124132 let remove smapiv2 =
125- Hashtbl. remove sr_table smapiv2;
133+ Hashtbl. remove ! sr_table smapiv2;
126134 return (Ok () )
135+
136+ let reload path =
137+ state_path := Some path;
138+ Sys. is_file ~follow_symlinks: true path
139+ >> = function
140+ | `No | `Unknown ->
141+ return ()
142+ | `Yes ->
143+ Reader. file_contents path
144+ >> = fun contents ->
145+ sr_table := contents |> Sexplib.Sexp. of_string |> String.Table. t_of_sexp (function Sexplib.Sexp. Atom x -> x | _ -> assert false );
146+ return ()
127147end
128148
129149let vdi_of_volume x =
@@ -581,7 +601,9 @@ let sync ~root_dir ~switch_path =
581601 >> = fun () ->
582602 Deferred. all_ignore (List. map ~f: (destroy switch_path) (diff got_already needed))
583603
584- let main ~root_dir ~switch_path =
604+ let main ~root_dir ~state_path ~switch_path =
605+ Attached_SRs. reload state_path
606+ >> = fun () ->
585607 (* We watch and create queues for the Volume plugins only *)
586608 let root_dir = Filename. concat root_dir " volume" in
587609 Async_inotify. create ~recursive: false ~watch_new_dirs: false root_dir
@@ -614,8 +636,8 @@ let main ~root_dir ~switch_path =
614636 loop () in
615637 loop ()
616638
617- let main ~root_dir ~switch_path =
618- let (_: unit Deferred.t ) = main ~root_dir ~switch_path in
639+ let main ~root_dir ~state_path ~ switch_path =
640+ let (_: unit Deferred.t ) = main ~root_dir ~state_path ~ switch_path in
619641 never_returns (Scheduler. go () )
620642
621643open Xcp_service
@@ -629,13 +651,19 @@ let description = String.concat ~sep:" " [
629651
630652let _ =
631653 let root_dir = ref " /var/lib/xapi/storage-scripts" in
654+ let state_path = ref " /var/run/nonpersistent/xapi-storage-script/state.db" in
632655
633656 let resources = [
634657 { Xcp_service. name = " root" ;
635658 description = " directory whose sub-directories contain sets of per-operation scripts, one sub-directory per queue name" ;
636659 essential = true ;
637660 path = root_dir;
638661 perms = [ U. X_OK ];
662+ }; { Xcp_service. name = " state" ;
663+ description = " file containing attached SR information, should be deleted on host boot" ;
664+ essential = false ;
665+ path = state_path;
666+ perms = [ ] ;
639667 }
640668 ] in
641669
@@ -655,5 +683,5 @@ let _ =
655683 use_syslog := true ;
656684 Core.Syslog. openlog ~id: " xapi-storage-script" ~facility: Core.Syslog.Facility. DAEMON () ;
657685 end ;
658- main ~root_dir: ! root_dir ~switch_path: ! Xcp_client. switch_path
686+ main ~root_dir: ! root_dir ~state_path: ! state_path ~ switch_path:! Xcp_client. switch_path
659687
0 commit comments