Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CA-62302 #1126

Merged
merged 2 commits into from
Apr 2, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions ocaml/idl/datamodel.ml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2712,6 +2712,14 @@ let host_detach_static_vdis = call
~allowed_roles:_R_LOCAL_ROOT_ONLY ~allowed_roles:_R_LOCAL_ROOT_ONLY
() ()


let host_declare_dead = call
~name:"declare_dead"
~in_product_since:rel_clearwater
~doc:"Declare that a host is dead. This is a dangerous operation, and should only be called if the administrator is absolutely sure the host is definitely dead"
~params:[Ref _host, "host", "The Host to declare is dead"]
~allowed_roles:_R_POOL_OP
()

let host_forget_data_source_archives = call let host_forget_data_source_archives = call
~name:"forget_data_source_archives" ~name:"forget_data_source_archives"
~in_oss_since:None ~in_oss_since:None
Expand Down Expand Up @@ -4185,6 +4193,7 @@ let host =
host_sync_tunnels; host_sync_tunnels;
host_sync_pif_currently_attached; host_sync_pif_currently_attached;
host_migrate_receive; host_migrate_receive;
host_declare_dead;
] ]
~contents: ~contents:
([ uid _host; ([ uid _host;
Expand Down
9 changes: 9 additions & 0 deletions ocaml/xapi/cli_frontend.ml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -423,6 +423,15 @@ let rec cmdtable_data : (string*cmd_spec) list =
flags=[]; flags=[];
}; };


"host-declare-dead",
{
reqd=["uuid"];
optn=[];
help="Declare that the the host is dead without contacting it explicitly. WARNING: This call is dangerous and can cause data loss if the host is not actually dead";
implementation=With_fd Cli_operations.host_declare_dead;
flags=[];
};

"host-disable", "host-disable",
{ {
reqd=[]; reqd=[];
Expand Down
7 changes: 5 additions & 2 deletions ocaml/xapi/cli_operations.ml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2765,7 +2765,7 @@ let vm_cd_insert printer rpc session_id params =
in in
ignore(do_vm_op printer rpc session_id op params ["cd-name"]) ignore(do_vm_op printer rpc session_id op params ["cd-name"])


let host_forget fd printer rpc session_id params = let host_careful_op op fd printer rpc session_id params =
let uuid = List.assoc "uuid" params in let uuid = List.assoc "uuid" params in
let host = Client.Host.get_by_uuid rpc session_id uuid in let host = Client.Host.get_by_uuid rpc session_id uuid in
let pool = List.hd (Client.Pool.get_all rpc session_id) in let pool = List.hd (Client.Pool.get_all rpc session_id) in
Expand All @@ -2774,7 +2774,7 @@ let host_forget fd printer rpc session_id params =


let force = get_bool_param params "force" in let force = get_bool_param params "force" in


let go () = ignore (Client.Host.destroy rpc session_id host) in let go () = ignore (op ~rpc ~session_id ~self:host) in


if force if force
then go () then go ()
Expand All @@ -2788,6 +2788,9 @@ let host_forget fd printer rpc session_id params =
then go () then go ()
end end


let host_forget x = host_careful_op Client.Host.destroy x
let host_declare_dead x = host_careful_op (fun ~rpc ~session_id ~self -> Client.Host.declare_dead ~rpc ~session_id ~host:self) x

let host_license_view printer rpc session_id params = let host_license_view printer rpc session_id params =
let host = let host =
if List.mem_assoc "host-uuid" params then if List.mem_assoc "host-uuid" params then
Expand Down
5 changes: 5 additions & 0 deletions ocaml/xapi/message_forwarding.ml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2107,6 +2107,11 @@ module Forward = functor(Local: Custom_actions.CUSTOM_ACTIONS) -> struct
do_op_on ~local_fn ~__context ~host (fun session_id rpc -> Client.Host.disable rpc session_id host); do_op_on ~local_fn ~__context ~host (fun session_id rpc -> Client.Host.disable rpc session_id host);
Xapi_host_helpers.update_allowed_operations ~__context ~self:host Xapi_host_helpers.update_allowed_operations ~__context ~self:host


let declare_dead ~__context ~host =
info "Host.declare_dead: host = '%s'" (host_uuid ~__context host);
Local.Host.declare_dead ~__context ~host;
Xapi_host_helpers.update_allowed_operations ~__context ~self:host

let enable ~__context ~host = let enable ~__context ~host =
info "Host.enable: host = '%s'" (host_uuid ~__context host); info "Host.enable: host = '%s'" (host_uuid ~__context host);
let local_fn = Local.Host.enable ~host in let local_fn = Local.Host.enable ~host in
Expand Down
2 changes: 2 additions & 0 deletions ocaml/xapi/xapi_hooks.ml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ let scriptname__host_post_declare_dead = "host-post-declare-dead"
(* Host Script hook reason codes *) (* Host Script hook reason codes *)
let reason__assume_failed = "assume-failed" let reason__assume_failed = "assume-failed"
let reason__fenced = "fenced" let reason__fenced = "fenced"
let reason__dbdestroy = "dbdestroy"
let reason__user = "user"
(* or clean-shutdown or clean-reboot *) (* or clean-shutdown or clean-reboot *)


(* Names of Pool script hooks *) (* Names of Pool script hooks *)
Expand Down
34 changes: 29 additions & 5 deletions ocaml/xapi/xapi_host.ml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -615,34 +615,58 @@ let create ~__context ~uuid ~name_label ~name_description ~hostname ~address ~ex
Db.Host_metrics.set_live ~__context ~self:metrics ~value:(uuid=(Helpers.get_localhost_uuid ())); Db.Host_metrics.set_live ~__context ~self:metrics ~value:(uuid=(Helpers.get_localhost_uuid ()));
host host


let destroy ~__context ~self = let precheck_destroy_declare_dead ~__context ~self call =
(* Fail if the host is still online: the user should either isolate the machine from the network (* Fail if the host is still online: the user should either isolate the machine from the network
or use Pool.eject. *) or use Pool.eject. *)
let hostname = Db.Host.get_hostname ~__context ~self in let hostname = Db.Host.get_hostname ~__context ~self in
if is_host_alive ~__context ~host:self then begin if is_host_alive ~__context ~host:self then begin
error "Host.destroy successfully contacted host %s; host is not offline; refusing to destroy record" hostname; error "Host.%s successfully contacted host %s; host is not offline; refusing to %s" call hostname call;
raise (Api_errors.Server_error(Api_errors.host_is_live, [ Ref.string_of self ])) raise (Api_errors.Server_error(Api_errors.host_is_live, [ Ref.string_of self ]))
end; end;


(* This check is probably redundant since the Pool master should always be 'alive': *) (* This check is probably redundant since the Pool master should always be 'alive': *)
(* It doesn't make any sense to destroy the master's own record *) (* It doesn't make any sense to destroy the master's own record *)
let me = Helpers.get_localhost ~__context in let me = Helpers.get_localhost ~__context in
if self=me then raise (Api_errors.Server_error(Api_errors.host_cannot_destroy_self, [ Ref.string_of self ])); if self=me then raise (Api_errors.Server_error(Api_errors.host_is_live, [ Ref.string_of self ]))


(* Returns a tuple of lists: The first containing the control domains, and the second containing the regular VMs *)
let get_resident_vms ~__context ~self =
let my_resident_vms = Db.Host.get_resident_VMs ~__context ~self in
List.partition (fun vm -> Db.VM.get_is_control_domain ~__context ~self:vm) my_resident_vms

let destroy ~__context ~self =
precheck_destroy_declare_dead ~__context ~self "destroy";


(* CA-23732: Block if HA is enabled *) (* CA-23732: Block if HA is enabled *)
let pool = Helpers.get_pool ~__context in let pool = Helpers.get_pool ~__context in
if Db.Pool.get_ha_enabled ~__context ~self:pool if Db.Pool.get_ha_enabled ~__context ~self:pool
then raise (Api_errors.Server_error(Api_errors.ha_is_enabled, [])); then raise (Api_errors.Server_error(Api_errors.ha_is_enabled, []));


let my_resident_vms = Db.Host.get_resident_VMs ~__context ~self in let my_control_domains, my_regular_vms = get_resident_vms ~__context ~self in
let my_control_domains, my_regular_vms = List.partition (fun vm -> Db.VM.get_is_control_domain ~__context ~self:vm) my_resident_vms in


if List.length my_regular_vms > 0 if List.length my_regular_vms > 0
then raise (Api_errors.Server_error(Api_errors.host_has_resident_vms, [ Ref.string_of self ])); then raise (Api_errors.Server_error(Api_errors.host_has_resident_vms, [ Ref.string_of self ]));


(* Call the hook before we destroy the stuff as it will likely need the
database records *)
Xapi_hooks.host_post_declare_dead ~__context ~host:self ~reason:Xapi_hooks.reason__dbdestroy;

Db.Host.destroy ~__context ~self; Db.Host.destroy ~__context ~self;
List.iter (fun vm -> Db.VM.destroy ~__context ~self:vm) my_control_domains List.iter (fun vm -> Db.VM.destroy ~__context ~self:vm) my_control_domains


let declare_dead ~__context ~host =
precheck_destroy_declare_dead ~__context ~self:host "declare_dead";

let my_control_domains, my_regular_vms = get_resident_vms ~__context ~self:host in

Helpers.call_api_functions ~__context (fun rpc session_id ->
List.iter (fun vm -> Client.Client.VM.power_state_reset rpc session_id vm) my_regular_vms);

Db.Host.set_enabled ~__context ~self:host ~value:false;

Xapi_hooks.host_post_declare_dead ~__context ~host ~reason:Xapi_hooks.reason__user

let ha_disable_failover_decisions ~__context ~host = Xapi_ha.ha_disable_failover_decisions __context host let ha_disable_failover_decisions ~__context ~host = Xapi_ha.ha_disable_failover_decisions __context host
let ha_disarm_fencing ~__context ~host = Xapi_ha.ha_disarm_fencing __context host let ha_disarm_fencing ~__context ~host = Xapi_ha.ha_disarm_fencing __context host
let ha_stop_daemon ~__context ~host = Xapi_ha.ha_stop_daemon __context host let ha_stop_daemon ~__context ~host = Xapi_ha.ha_stop_daemon __context host
Expand Down
1 change: 1 addition & 0 deletions ocaml/xapi/xapi_host.mli
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ val create :
chipset_info:(string * string) list -> chipset_info:(string * string) list ->
[ `host ] Ref.t [ `host ] Ref.t
val destroy : __context:Context.t -> self:API.ref_host -> unit val destroy : __context:Context.t -> self:API.ref_host -> unit
val declare_dead : __context:Context.t -> host:API.ref_host -> unit
val ha_disable_failover_decisions : __context:'a -> host:'b -> unit val ha_disable_failover_decisions : __context:'a -> host:'b -> unit
val ha_disarm_fencing : __context:'a -> host:'b -> unit val ha_disarm_fencing : __context:'a -> host:'b -> unit
val ha_stop_daemon : __context:'a -> host:'b -> unit val ha_stop_daemon : __context:'a -> host:'b -> unit
Expand Down
33 changes: 23 additions & 10 deletions scripts/10resetvdis
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -6,15 +6,28 @@
HOSTUUID=$2 HOSTUUID=$2
REASON=$4 REASON=$4


# Only reset the VDIs if the host is actually fenced! function reset {
if [ ! $REASON = "fenced" ]; then echo Resetting VDIs on host $HOSTUUID
exit 0 IFS=","
for i in `xe pbd-list host-uuid=$HOSTUUID --minimal`
do
SR=`xe pbd-param-get uuid=$i param-name=sr-uuid`
"@OPTDIR@/sm/resetvdis.py" $HOSTUUID $SR
done
}

# Only reset the VDIs if the host is actually fenced, or the user has requested it.
if [ $REASON = "fenced" ]; then
reset
fi

if [ $REASON = "user" ]; then
reset
fi fi


echo Resetting VDIs on host $HOSTUUID if [ $REASON = "dbdestroy" ]; then
IFS="," reset
for i in `xe pbd-list host-uuid=$HOSTUUID --minimal` fi
do
SR=`xe pbd-param-get uuid=$i param-name=sr-uuid`
"@OPTDIR@/sm/resetvdis.py" $HOSTUUID $SR
done