Skip to content

Commit

Permalink
Merge pull request #834 from johnelse/sxm-cli-updates-minimal-rebased
Browse files Browse the repository at this point in the history
  • Loading branch information
xen-git committed Aug 17, 2012
2 parents 02d9a6b + 5c953fe commit 7f1ac9e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 17 deletions.
4 changes: 2 additions & 2 deletions ocaml/xapi/cli_frontend.ml
Expand Up @@ -1156,8 +1156,8 @@ let rec cmdtable_data : (string*cmd_spec) list =
"vm-migrate",
{
reqd=[];
optn=["live"; "host"; "host-uuid"; "remote-address"; "remote-username"; "remote-password"; "remote-network"; "destination-sr-uuid"; "encrypt"; "force"; "vif:"; "vdi:"];
help="Migrate the selected VM(s). The parameter '--live' will migrate the VM without shutting it down. The 'host' parameter matches can be either the name or the uuid of the host. The parameter '--encrypt' will encrypt the memory image transfer.";
optn=["live"; "host"; "host-uuid"; "remote-master"; "remote-username"; "remote-password"; "remote-network"; "destination-sr-uuid"; "force"; "vif:"; "vdi:"];
help="Migrate the selected VM(s). The parameter '--live' will migrate the VM without shutting it down. The 'host' parameter matches can be either the name or the uuid of the host. If you are migrating a VM to a remote pool, you will need to specify the remote-master, remote-username, and remote-password parameters. remote-master is the network address of the master host. To migrate to a particular host within a remote pool, you may additionally specify the host or host-uuid parameters. The vif and vdi mapping parameters take the form 'vif:<source vif uuid>=<dest vif uuid>' (and the same for vdi map). You may simplify this mapping by using the destination-sr-uuid parameter. Unfortunately, destination uuids cannot be tab-completed.";
implementation=No_fd Cli_operations.vm_migrate;
flags=[Standard; Vm_selectors];
};
Expand Down
66 changes: 51 additions & 15 deletions ocaml/xapi/cli_operations.ml
Expand Up @@ -2462,16 +2462,19 @@ let vm_retrieve_wlb_recommendations printer rpc session_id params =
| Records.CLI_failed_to_find_param name ->
failwith ("Parameter '"^name^"' is not a field of the VM class. Failed to select VM for operation.")

let vm_migrate_sxm_params = ["remote-master"; "remote-username"; "vif"; "remote-password";
"remote-network"; "destination-sr-uuid"; "vdi"]

let vm_migrate printer rpc session_id params =
(* Hack to match host-uuid and host-name for backwards compatibility *)
let params = List.map (fun (k, v) -> if (k = "host-uuid") || (k = "host-name") then ("host", v) else (k, v)) params in
let options = List.map_assoc_with_key (string_of_bool +++ bool_of_string) (List.restrict_with_default "false" ["force"; "live"; "encrypt"] params) in
(* If we specify all of: remote-address, remote-username, remote-password
let options = List.map_assoc_with_key (string_of_bool +++ bool_of_string) (List.restrict_with_default "false" ["force"; "live"] params) in
(* If we specify all of: remote-master, remote-username, remote-password
then we're using the new codepath *)
if List.mem_assoc "remote-address" params && (List.mem_assoc "remote-username" params)
if List.mem_assoc "remote-master" params && (List.mem_assoc "remote-username" params)
&& (List.mem_assoc "remote-password" params) then begin
printer (Cli_printer.PMsg "Using the new cross-host, cross-pool, cross-everything codepath.");
let ip = List.assoc "remote-address" params in
printer (Cli_printer.PMsg "Performing a Storage XenMotion migration. Your VM's VDIs will be migrated with the VM.");
let ip = List.assoc "remote-master" params in
let remote_rpc xml =
let open Xmlrpc_client in
let http = xmlrpc ~version:"1.0" "/" in
Expand All @@ -2490,7 +2493,6 @@ let vm_migrate printer rpc session_id params =
with Not_found ->
failwith (Printf.sprintf "Failed to find host: %s" x)
end else begin
printer (Cli_printer.PMsg "No host specified; I will choose automatically");
List.hd all
end in
let network, network_record =
Expand All @@ -2502,7 +2504,6 @@ let vm_migrate printer rpc session_id params =
with Not_found ->
failwith (Printf.sprintf "Failed to find network: %s" x)
end else begin
printer (Cli_printer.PMsg "No network specified; I will try to find the remote host management network");
let pifs = host_record.API.host_PIFs in
let management_pifs = List.filter (fun pif ->
Client.PIF.get_management remote_rpc remote_session pif) pifs in
Expand All @@ -2512,29 +2513,64 @@ let vm_migrate printer rpc session_id params =
let net = Client.PIF.get_network remote_rpc remote_session pif in
(net, Client.Network.get_record remote_rpc remote_session net)
end in
let vdi_map = List.map (fun (vdi_uuid,sr_uuid) ->
let vdi = Client.VDI.get_by_uuid rpc session_id vdi_uuid in
let sr = Client.SR.get_by_uuid remote_rpc remote_session sr_uuid in
vdi,sr) (read_map_params "vdi" params) in
let vif_map = List.map (fun (vif_uuid,net_uuid) ->
let vif = Client.VIF.get_by_uuid rpc session_id vif_uuid in
let net = Client.Network.get_by_uuid remote_rpc remote_session net_uuid in
vif,net) (read_map_params "vif" params) in

let vdi_map = List.map (fun (vdi_uuid,sr_uuid) ->
let vdi = Client.VDI.get_by_uuid rpc session_id vdi_uuid in
let sr = Client.SR.get_by_uuid remote_rpc remote_session sr_uuid in
vdi,sr) (read_map_params "vdi" params) in

let default_sr =
if List.mem_assoc "destination-sr-uuid" params
then let sr_uuid = List.assoc "destination-sr-uuid" params in
try Some (Client.SR.get_by_uuid remote_rpc remote_session sr_uuid)
with _ -> failwith (Printf.sprintf "Couldn't find destination SR: %s" sr_uuid)
else try let pools = Client.Pool.get_all remote_rpc remote_session in
printer (Cli_printer.PMsg "Selecting remote pool's default SR for migrating VDIs") ;
Some (Client.Pool.get_default_SR remote_rpc remote_session
(List.hd pools))
with _ -> None in

let vdi_map = match default_sr with
| None -> vdi_map
| Some default_sr ->
let vms = select_vms rpc session_id params
( "host" :: "host-uuid" :: "host-name" :: "live"
:: vm_migrate_sxm_params ) in
if vms = [] then failwith "No matching VMs found" ;
let vbds = Client.VM.get_VBDs rpc session_id ((List.hd vms).getref ()) in
let vbds = List.filter (fun vbd ->
not (Client.VBD.get_empty rpc session_id vbd)) vbds in
let vdis = List.map
(fun vbd -> Client.VBD.get_VDI rpc session_id vbd) vbds in
List.map (fun vdi ->
if List.mem_assoc vdi vdi_map
then (vdi, List.assoc vdi vdi_map)
else (vdi, default_sr)
) vdis in

let params = List.filter (fun (s,_) -> if String.length s < 5 then true
else let start = String.sub s 0 4 in start <> "vif:" && start <> "vdi:") params in
printer (Cli_printer.PMsg (Printf.sprintf "Will migrate to remote host: %s, using remote network: %s" host_record.API.host_name_label network_record.API.network_name_label));
printer (Cli_printer.PMsg (Printf.sprintf "Will migrate to remote host: %s, using remote network: %s. Here is the VDI mapping:" host_record.API.host_name_label network_record.API.network_name_label));
List.iter (fun (vdi,sr) ->
printer (Cli_printer.PMsg (Printf.sprintf "VDI %s -> SR %s"
(Client.VDI.get_uuid rpc session_id vdi)
(Client.SR.get_uuid remote_rpc remote_session sr))))
vdi_map ;
let token = Client.Host.migrate_receive remote_rpc remote_session host network options in
printer (Cli_printer.PMsg (Printf.sprintf "Received token: [ %s ]" (String.concat "; " (List.map (fun (k, v) -> k ^ ":" ^ v) token))));
ignore(do_vm_op ~include_control_vms:true printer rpc session_id (fun vm -> Client.VM.migrate_send rpc session_id (vm.getref ()) token true vdi_map vif_map options)
params ["host"; "host-uuid"; "host-name"; "live"; "encrypt"; "remote-address"; "remote-username"; "remote-password"; "remote-network"; "vdi"; "vif" ])
params (["host"; "host-uuid"; "host-name"; "live"] @ vm_migrate_sxm_params))
)
(fun () -> Client.Session.logout remote_rpc remote_session)
end else begin
if not (List.mem_assoc "host" params) then failwith "No destination host specified";
let host = (get_host_by_name_or_id rpc session_id (List.assoc "host" params)).getref () in

ignore(do_vm_op ~include_control_vms:true printer rpc session_id (fun vm -> Client.VM.pool_migrate rpc session_id (vm.getref ()) host options)
params ["host"; "host-uuid"; "host-name"; "live"; "encrypt"])
params ["host"; "host-uuid"; "host-name"; "live"])
end
let vm_disk_list_aux vm is_cd_list printer rpc session_id params =
let vbds = List.filter (fun vbd -> Client.VBD.get_type rpc session_id vbd = (if is_cd_list then `CD else `Disk)) (vm.record()).API.vM_VBDs in
Expand Down

0 comments on commit 7f1ac9e

Please sign in to comment.