From 9c4662aeba0228cfbe635aa1d81e6fcf7a39d177 Mon Sep 17 00:00:00 2001 From: Vincent Hanquez Date: Thu, 16 Jul 2009 21:42:44 +0100 Subject: [PATCH] xenvm: switch the uuid into state instead of config. allow xenvm to be start without config but a uuid, so that we can start and fill the config through the interface with get/set calls. lots of other small cleanups/changes --- xenvm/vmact.ml | 25 +++++++------- xenvm/vmconfig.ml | 83 ++++++++++++++++++++++++++++++++++++++--------- xenvm/vmstate.ml | 4 ++- xenvm/xenvm.ml | 81 ++++++++++++++++++++++++++++----------------- 4 files changed, 135 insertions(+), 58 deletions(-) diff --git a/xenvm/vmact.ml b/xenvm/vmact.ml index c3956d6..a43b6a2 100644 --- a/xenvm/vmact.ml +++ b/xenvm/vmact.ml @@ -32,11 +32,11 @@ exception Vm_shutdown_wrong_reason of Domain.shutdown_reason * Xal.died_reason exception Vm_didnt_shutdown exception Vm_is_already_created of int * vmlifestate -let mntdir_path uuid = "/var/lib/xenvm/mnt-" ^ (Uuid.to_string uuid) +let mntdir_path uuid = "/var/lib/xenvm/mnt-" ^ uuid -let _notify cfg code l = +let _notify state code l = let fdopt = - match cfg.notify with + match state.vm_cfg.notify with | NotifyUnix path -> let fd = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in Unix.connect fd (Unix.ADDR_UNIX path); @@ -54,15 +54,15 @@ let _notify cfg code l = | None -> () | Some fd -> (* notification format is "::\n" *) - let s = String.concat ":" (Uuid.to_string cfg.uuid :: string_of_int code :: l) ^ "\n" in + let s = String.concat ":" (state.vm_uuid :: string_of_int code :: l) ^ "\n" in let (_: int) = Unix.write fd s 0 (String.length s) in (* FIXME we might want to cache it later on .. and catch EBADF or ECONNRESET for reopen signal. *) Unix.close fd -let notify cfg code l = +let notify state code l = info "sending notification %s" (String.concat ":" l); try - _notify cfg code l + _notify state code l with exn -> warn "notify failed: %s" (Printexc.to_string exn) @@ -227,7 +227,7 @@ let do_trigger xc state args = let change_vmstate state newstate = state.vm_lifestate <- newstate; - notify state.vm_cfg Xenvmlib.code_vmstate [ "vm"; "state"; string_of_vmlifestate newstate ]; + notify state Xenvmlib.code_vmstate [ "vm"; "state"; string_of_vmlifestate newstate ]; if newstate = VmShutdown then ( maybe (fun cfg -> state.vm_cfg <- cfg) state.vm_next_cfg ) @@ -324,8 +324,9 @@ let check_uuid_exists xc uuid = let create_vm xc xs state = with_create_lock state (fun () -> + let uuid = Uuid.uuid_of_string state.vm_uuid in if state.vm_domid <> -1 then ( - let uuid_exists = check_uuid_exists xc state.vm_cfg.uuid in + let uuid_exists = check_uuid_exists xc uuid in if uuid_exists then raise (Vm_is_already_created (state.vm_domid, state.vm_lifestate)); warn "internal error: domain was marked as existing but wasn't -- state corrected" @@ -338,7 +339,7 @@ let create_vm xc xs state = Domain.platformdata = state.vm_cfg.platform; Domain.xsdata = []; } in - let domid = Domain.make ~xc ~xs info state.vm_cfg.uuid in + let domid = Domain.make ~xc ~xs info uuid in state.vm_domid <- domid; change_vmstate state VmCreated ) @@ -460,7 +461,7 @@ let suspend_to_file xc xs xal state flags file = let suspend xc xs state flags file = match String.split ':' file with | "xenserver" :: dev :: _ -> - let mntpoint = mntdir_path state.vm_cfg.uuid in + let mntpoint = mntdir_path state.vm_uuid in Misc.create_ext3fs_on dev; (* mount dev to some mkdir'ed tmp directory *) Misc.with_mounted_fs dev mntpoint (fun () -> @@ -480,7 +481,7 @@ let restore_from_file xc xs state file = let restore xc xs state delete file = match String.split ':' file with | "xenserver" :: dev :: _ -> - let mntpoint = mntdir_path state.vm_cfg.uuid in + let mntpoint = mntdir_path state.vm_uuid in Misc.with_mounted_fs dev mntpoint (fun () -> restore_from_file xc xs state (mntpoint ^ "/suspend-image") ) @@ -534,7 +535,7 @@ let device_cmd xc xs state ty subcmd args = Xenvmlib.Ok in let nic_add args = - let nic = Config.config_nic_of_string cfg.uuid (List.hd args) in + let nic = Config.config_nic_of_string state.vm_uuid (List.hd args) in add_nic_to_vm ~xs state nic; Xenvmlib.Ok in diff --git a/xenvm/vmconfig.ml b/xenvm/vmconfig.ml index 9ea0fd5..142c304 100644 --- a/xenvm/vmconfig.ml +++ b/xenvm/vmconfig.ml @@ -66,7 +66,7 @@ type config_nic = { } type config = { - uuid: [ `domain ] Uuid.t; + __uuid: string option; (* do not use anymore *) name: string option; verbose: bool; debug: bool; @@ -175,7 +175,7 @@ let config_nic_of_string vm_uuid s = let vector = (if nic_id = -1 then [] else [ string_of_int nic_id ]) @ (match nic_model with None -> [] | Some x -> [ x ]) @ - [ Uuid.string_of_uuid vm_uuid ] + [ vm_uuid ] in let digest = Digest.to_hex (Digest.string (String.concat " " vector)) in let hexs = List.map (fun i -> s_of_c digest.[i] digest.[i + 12]) [ 0; 2; 1; 7; 6; 4 ] in @@ -333,11 +333,66 @@ let set cfg field value = | "inject-sci" -> { cfg with inject_sci = int_of_string value } | _ -> raise (Unknown_field field) -let of_file error_report file = - let hvm = ref false - and debug = ref false - and verbose = ref false - and no_mem_check = ref false +let empty = + { + __uuid = None; + name = None; + debug = false; + verbose = false; + no_mem_check = false; + output = ""; + startup = StartupStart; + hvm = false; + kernel = ""; + cmdline = ""; + serial = ""; + initrd = None; + memory = -1L; + vcpus = 1; + pae = false; + acpi = false; + apic = false; + nx = false; + smbios_pt = false; + acpi_pt = false; + diskinfo_pt = false; + viridian = false; + videoram = None; + on_halt = ActionDestroy; + on_restart = ActionRestart; + on_crash = ActionDestroy; + disks = []; + nics = []; + pcis = []; + boot = "cd"; + vnc = 0; + vnc_keymap = "en-us"; + cpuid = []; + datadir = ""; + platform = []; + extrahvm = []; + notify = NotifyNone; + daemonize = false; + power_management = 0; + oem_features = 0; + timer_mode = None; + timeoffset = None; + hpet = None; + vpt_align = None; + snapshot_mode = NoSnapshot; + extra_local_watches = []; + extra_vm_watches = []; + global_pci_msitranslate = 0; + global_pci_power_mgmt = 0; + sound = None; + inject_sci = 0; + } + +let of_file uuid error_report file = + let hvm = ref empty.hvm + and debug = ref empty.debug + and verbose = ref empty.verbose + and no_mem_check = ref empty.no_mem_check and output = ref "" and kernel = ref "" and cmdline = ref "" @@ -363,7 +418,7 @@ let of_file error_report file = and boot = ref "cd" and vnc = ref 0 and vnc_keymap = ref "en-us" - and uuid = ref (Uuid.make_uuid ()) + and __uuid = ref None and name = ref "" and cpuid = ref [] and startup = ref StartupStart @@ -403,7 +458,7 @@ let of_file error_report file = in let set_nic s = try - let nic = config_nic_of_string !uuid s in + let nic = config_nic_of_string uuid s in nics := nic :: !nics; with exn -> eprintf "error: vif config: %s\n%!" @@ -498,11 +553,7 @@ let of_file error_report file = ("output", Config.Set_string output); ("verbose", Config.Set_bool verbose); ("name", Config.Set_string name); - ("uuid", Config.String (fun s -> - if String.length s = 36 then - uuid := Uuid.of_string s - else - eprintf "uuid format problem -- ignoring\n%!")); + ("uuid", Config.String (fun s -> __uuid := Some s)); ("kernel", Config.Set_string kernel); ("cmdline", Config.Set_string cmdline); ("serial", Config.Set_string serial); @@ -593,7 +644,7 @@ let of_file error_report file = if !memory = -1 then failwith "you need to set memory"; { - uuid = !uuid; + __uuid = !__uuid; name = string_option_of_string !name; debug = !debug; verbose = !verbose; @@ -645,4 +696,6 @@ let of_file error_report file = sound = !sound; inject_sci = !inject_sci; } + + end diff --git a/xenvm/vmstate.ml b/xenvm/vmstate.ml index 3841792..94aef38 100644 --- a/xenvm/vmstate.ml +++ b/xenvm/vmstate.ml @@ -38,6 +38,7 @@ type locks = { } type vm_state = { + vm_uuid: string; mutable vm_config_path: string; mutable vm_arch: Domain.domarch; mutable vm_domid: int; @@ -51,8 +52,9 @@ type vm_state = { locks: locks; } -let state_init config_path cfg = +let state_init uuid config_path cfg = { + vm_uuid = uuid; vm_config_path = config_path; vm_arch = if cfg.hvm then Domain.Arch_HVM else Domain.Arch_native; vm_domid = (-1); diff --git a/xenvm/xenvm.ml b/xenvm/xenvm.ml index 59959d4..ff56df0 100644 --- a/xenvm/xenvm.ml +++ b/xenvm/xenvm.ml @@ -90,7 +90,7 @@ let bind_unix_socket filename listen_queue = let open_monitor_socket uuid name = Unixext.mkdir_rec "/var/lib/xenvm" 0o640; - let filename = sprintf "/var/lib/xenvm/vm-%s" (Uuid.to_string uuid) in + let filename = sprintf "/var/lib/xenvm/vm-%s" uuid in bind_unix_socket filename 10, filename let close_monitor_socket socket filename = Unix.close socket; Unixext.unlink_safe filename; () @@ -117,7 +117,7 @@ let with_xcs f = let check_vm uuid = let is_running = try - let reply = Xenvmlib.request ~timeout:10. (Uuid.to_string uuid) ("status", []) in + let reply = Xenvmlib.request ~timeout:10. uuid ("status", []) in begin match reply with | Xenvmlib.Msg _ -> () | _ -> () @@ -130,13 +130,13 @@ let check_vm uuid = info "VM is already handled by another xenvm"; exit 1; ); - let path = Xenvmlib.path_of_socket (Uuid.to_string uuid) in + let path = Xenvmlib.path_of_socket uuid in if Sys.file_exists path then ( info "stale socket left by previous xenvm. removing"; Unixext.unlink_safe path ); with_xc (fun xc -> - let domid = Vmact.domid_of_uuid xc uuid in + let domid = Vmact.domid_of_uuid xc (Uuid.uuid_of_string uuid) in match domid with | Some domid -> info "domain still present at domid=%d. exiting" domid; @@ -241,7 +241,7 @@ let monitor_vm state = let callback_introduce ctx id = let xc = Xal.xc_of_ctx ctx in try - if Domain.get_uuid ~xc id = state.vm_cfg.uuid then + if Uuid.to_string (Domain.get_uuid ~xc id) = state.vm_uuid then state.vm_domid <- id with Xc.Error _ -> () and callback_release ctx id = @@ -251,7 +251,7 @@ let monitor_vm state = info "domain died asynchronously: %s" (Xal.string_of_died_reason reason); let action = match reason with | Xal.Crashed -> - Vmact.notify state.vm_cfg Xenvmlib.code_error [ "error"; "crashed" ]; + Vmact.notify state Xenvmlib.code_error [ "error"; "crashed" ]; state.vm_cfg.on_crash | Xal.Vanished -> ActionPreserve | Xal.Halted -> state.vm_cfg.on_halt @@ -302,15 +302,15 @@ let monitor_vm state = ) in let change_rtc uuid data = - if uuid = (Uuid.to_string state.vm_cfg.uuid) then - Vmact.notify state.vm_cfg Xenvmlib.code_vmset [ "rtc"; data ]; + if uuid = state.vm_uuid then + Vmact.notify state Xenvmlib.code_vmset [ "rtc"; data ]; in let extra_notification uuid node value = (* either we are because it's a domain extra event in this case we have a null uuid or in vm event we're suppose to get the vm's uuid *) - if uuid = "" || uuid = (Uuid.to_string state.vm_cfg.uuid) then ( + if uuid = "" || uuid = state.vm_uuid then ( let data = node :: match value with None -> [] | Some d -> [ d ] in - Vmact.notify state.vm_cfg Xenvmlib.code_vmtrigger data + Vmact.notify state Xenvmlib.code_vmtrigger data ) in if state.vm_domid = id then ( @@ -382,7 +382,7 @@ let reread_config state path = | None -> state.vm_config_path | Some path -> path in - let cfg = Config.of_file (fun errors -> () ) path in + let cfg = Config.of_file state.vm_uuid (fun errors -> ()) path in state.vm_next_cfg <- Some cfg let do_task quit state (task, args) = @@ -660,9 +660,9 @@ let do_snapshot .. = *********) let main state = - let socket, name = open_monitor_socket state.vm_cfg.uuid state.vm_cfg.name in + let socket, name = open_monitor_socket state.vm_uuid state.vm_cfg.name in - Vmact.notify state.vm_cfg Xenvmlib.code_ping [ "ping" ]; + Vmact.notify state Xenvmlib.code_ping [ "ping" ]; finally (fun () -> try (* start the domain *) @@ -671,7 +671,7 @@ let main state = | StartupPause | StartupStart -> with_xcs (fun xc xs -> Vmact.start_vm xc xs state); if state.vm_cfg.verbose then ( - info "started domain: %s" (Uuid.to_string state.vm_cfg.uuid); + info "started domain: %s" state.vm_uuid; ); | StartupRestore (file, del) -> Unixext.with_file (with_datadir state.vm_cfg file) [ Unix.O_RDONLY ] 0o640 (fun fd -> @@ -681,17 +681,17 @@ let main state = try Sys.remove file with _ -> () ); if state.vm_cfg.verbose then ( - info "resumed domain: %s" (Uuid.to_string state.vm_cfg.uuid); + info "resumed domain: %s" state.vm_uuid; ); ); monitor socket state; with exn -> let exnstr = string_of_exn exn in error "fatal exception: %s" exnstr; - Vmact.notify state.vm_cfg Xenvmlib.code_error [ "error"; exnstr ]; + Vmact.notify state Xenvmlib.code_error [ "error"; exnstr ]; raise exn ) (fun () -> - Vmact.notify state.vm_cfg Xenvmlib.code_hup [ "hup" ]; + Vmact.notify state Xenvmlib.code_hup [ "hup" ]; close_monitor_socket socket name ) @@ -731,11 +731,6 @@ let () = config := List.hd !anon; ); - if !config = "" then ( - eprintf "usage: %s \n" Sys.argv.(0); - exit 2 - ); - Random.self_init (); let error_report errs = @@ -747,19 +742,46 @@ let () = config_errors := errors_str; in - let cfg = Config.of_file error_report !config in + let uuid, state = + match !uuid, !config with + | "", "" -> + eprintf "error: you need to specify a uuid or a config file\n"; + exit 3; + | "", configfile -> + let cfg = Config.of_file !uuid error_report configfile in + let uuid = + match cfg.__uuid with + | None -> eprintf "error: you need to specify a uuid in your config file\n"; exit 3; + | Some uuid -> uuid + in + (* reparse the config for things that are dependents of the uuid *) + let cfg = Config.of_file uuid error_report configfile in + verify_config cfg; + uuid, (state_init uuid configfile cfg) + | uuid, "" -> + uuid, (state_init uuid "" Config.empty) + | uuid, configfile -> + let cfg = Config.of_file uuid error_report configfile in + verify_config cfg; + uuid, (state_init uuid configfile cfg) + in - verify_config cfg; + (* + if uuid = "" && cfg.__uuid !config = "" then ( + eprintf "error: you need to specify a uuid or a config\n"; + exit 2 + ); + *) if !daemonize then Unixext.daemonize (); - if cfg.debug then ( + if state.vm_cfg.debug then ( let a = - if cfg.output = "" then - sprintf "file:/tmp/xenvm-debug-%s" (Uuid.to_string cfg.uuid) + if state.vm_cfg.output = "" then + sprintf "file:/tmp/xenvm-debug-%s" uuid else - "file:/" ^ cfg.output + "file:/" ^ state.vm_cfg.output in Logs.set_default Log.Debug [ a ]; Logs.set_default Log.Info [ a ]; @@ -772,6 +794,5 @@ let () = List.iter (fun s -> warn "%s" s) !config_errors ); - let state = state_init !config cfg in - check_vm cfg.uuid; + check_vm uuid; main state -- 2.39.5