# simulate hardware commands
# power <node> <on|off>
# network <node> <on|off>
+# reboot <node>
+# shutdown <node>
+# restart-lrm <node>
+# service <sid> <started|disabled|stopped>
+# service <sid> <migrate|relocate> <target>
+# service <sid> lock/unlock [lockname]
sub sim_hardware_cmd {
my ($self, $cmdstr, $logid) = @_;
+ my $code = sub {
+ my ($lock_fh) = @_;
+
+ my $cstatus = $self->read_hardware_status_nolock();
+
+ my ($cmd, $objid, $action, $target) = split(/\s+/, $cmdstr);
+
+ die "sim_hardware_cmd: no node or service for command specified"
+ if !$objid;
+
+ my ($node, $sid, $d);
+
+ if ($cmd eq 'service') {
+ $sid = PVE::HA::Tools::pve_verify_ha_resource_id($objid);
+ } else {
+ $node = $objid;
+ $d = $self->{nodes}->{$node} ||
+ die "sim_hardware_cmd: no such node '$node'\n";
+ }
+
+ $self->log('info', "execute $cmdstr", $logid);
+
+ if ($cmd eq 'power') {
+ die "sim_hardware_cmd: unknown action '$action'\n"
+ if $action !~ m/^(on|off)$/;
+
+ if ($cstatus->{$node}->{power} ne $action) {
+ if ($action eq 'on') {
+
+ $d->{crm} = $self->crm_control('start', $d, $lock_fh) if !defined($d->{crm});
+ $d->{lrm} = $self->lrm_control('start', $d, $lock_fh) if !defined($d->{lrm});
+ $d->{lrm_restart} = undef;
+
+ } else {
+
+ if ($d->{crm}) {
+ $d->{crm_env}->log('info', "killed by poweroff");
+ $self->crm_control('stop', $d, $lock_fh);
+ $d->{crm} = undef;
+ }
+ if ($d->{lrm}) {
+ $d->{lrm_env}->log('info', "killed by poweroff");
+ $self->lrm_control('stop', $d, $lock_fh);
+ $d->{lrm} = undef;
+ $d->{lrm_restart} = undef;
+ }
+
+ $self->watchdog_reset_nolock($node);
+ $self->write_service_status($node, {});
+ }
+ }
+
+ $cstatus->{$node}->{power} = $action;
+ $cstatus->{$node}->{network} = $action;
+ $cstatus->{$node}->{shutdown} = undef;
+
+ $self->write_hardware_status_nolock($cstatus);
+
+ } elsif ($cmd eq 'network') {
+ die "sim_hardware_cmd: unknown network action '$action'"
+ if $action !~ m/^(on|off)$/;
+ $cstatus->{$node}->{network} = $action;
+
+ $self->write_hardware_status_nolock($cstatus);
+
+ } elsif ($cmd eq 'reboot' || $cmd eq 'shutdown') {
+ $cstatus->{$node}->{shutdown} = $cmd;
+
+ $self->write_hardware_status_nolock($cstatus);
+
+ $self->lrm_control('shutdown', $d, $lock_fh) if defined($d->{lrm});
+ } elsif ($cmd eq 'restart-lrm') {
+ if ($d->{lrm}) {
+ $d->{lrm_restart} = 1;
+ $self->lrm_control('shutdown', $d, $lock_fh);
+ }
+ } elsif ($cmd eq 'crm') {
+
+ if ($action eq 'stop') {
+ if ($d->{crm}) {
+ $d->{crm_stop} = 1;
+ $self->crm_control('shutdown', $d, $lock_fh);
+ }
+ } elsif ($action eq 'start') {
+ $d->{crm} = $self->crm_control('start', $d, $lock_fh) if !defined($d->{crm});
+ } else {
+ die "sim_hardware_cmd: unknown action '$action'";
+ }
+
+ } elsif ($cmd eq 'service') {
+ if ($action eq 'started' || $action eq 'disabled' || $action eq 'stopped') {
+
+ $self->set_service_state($sid, $action);
+
+ } elsif ($action eq 'migrate' || $action eq 'relocate') {
+
+ die "sim_hardware_cmd: missing target node for '$action' command"
+ if !$target;
+
+ $self->queue_crm_commands_nolock("$action $sid $target");
+
+ } elsif ($action eq 'add') {
+
+ $self->add_service($sid, {state => 'started', node => $target});
+
+ } elsif ($action eq 'delete') {
+
+ $self->delete_service($sid);
+
+ } elsif ($action eq 'lock') {
+
+ $self->lock_service($sid, $target);
+
+ } elsif ($action eq 'unlock') {
+
+ $self->unlock_service($sid, $target);
+
+ } else {
+ die "sim_hardware_cmd: unknown service action '$action' " .
+ "- not implemented\n"
+ }
+ } else {
+ die "sim_hardware_cmd: unknown command '$cmdstr'\n";
+ }
+
+ return $cstatus;
+ };
+
+ return $self->global_lock($code);
+}
+
+# for controlling the resource manager services
+sub crm_control {
+ my ($self, $action, $data, $lock_fh) = @_;
+
+ die "implement in subclass";
+}
+
+sub lrm_control {
+ my ($self, $action, $data, $lock_fh) = @_;
+
die "implement in subclass";
}
return $pid;
}
-# simulate hardware commands
-# power <node> <on|off>
-# network <node> <on|off>
+# for controlling the resource manager services (CRM and LRM)
+sub crm_control {
+ my ($self, $action, $data, $lock_fh) = @_;
-sub sim_hardware_cmd {
- my ($self, $cmdstr, $logid) = @_;
+ if ($action eq 'start') {
- my $cstatus;
+ return $self->fork_daemon($lock_fh, 'crm', $data->{crm_env});
- # note: do not fork when we own the lock!
- my $code = sub {
- my ($lockfh) = @_;
+ } elsif ($action eq 'stop') {
- $cstatus = $self->read_hardware_status_nolock();
+ kill(9, $data->{crm});
+ while (waitpid($data->{crm}, 0) != $data->{crm}) {}
- my ($cmd, $node, $action) = split(/\s+/, $cmdstr);
+ } else {
+ die "unknown CRM control action: '$action'\n";
+ }
+}
- die "sim_hardware_cmd: no node specified" if !$node;
- die "sim_hardware_cmd: unknown action '$action'" if $action !~ m/^(on|off)$/;
+sub lrm_control {
+ my ($self, $action, $data, $lock_fh) = @_;
- my $d = $self->{nodes}->{$node};
- die "sim_hardware_cmd: no such node '$node'\n" if !$d;
+ if ($action eq 'start') {
- $self->log('info', "execute $cmdstr", $logid);
-
- if ($cmd eq 'power') {
- if ($cstatus->{$node}->{power} ne $action) {
- if ($action eq 'on') {
- $d->{crm} = $self->fork_daemon($lockfh, 'crm', $d->{crm_env}) if !$d->{crm};
- $d->{lrm} = $self->fork_daemon($lockfh, 'lrm', $d->{lrm_env}) if !$d->{lrm};
- } else {
- if ($d->{crm}) {
- $self->log('info', "crm on node '$node' killed by poweroff");
- kill(9, $d->{crm});
- $d->{crm} = undef;
- }
- if ($d->{lrm}) {
- $self->log('info', "lrm on node '$node' killed by poweroff");
- kill(9, $d->{lrm});
- $d->{lrm} = undef;
- }
- $self->watchdog_reset_nolock($node);
- $self->write_service_status($node, {});
- }
- }
+ return $self->fork_daemon($lock_fh, 'lrm', $data->{lrm_env});
- $cstatus->{$node}->{power} = $action;
- $cstatus->{$node}->{network} = $action;
+ } elsif ($action eq 'stop') {
- } elsif ($cmd eq 'network') {
- $cstatus->{$node}->{network} = $action;
- } else {
- die "sim_hardware_cmd: unknown command '$cmd'\n";
- }
+ kill(9, $data->{lrm});
+ while (waitpid($data->{lrm}, 0) != $data->{lrm}) {}
- $self->write_hardware_status_nolock($cstatus);
- };
+ } else {
+ die "unknown LRM control action: '$action'\n";
+ }
- my $res = $self->global_lock($code);
+}
- # update GUI outside lock
+# simulate hardware commands
+sub sim_hardware_cmd {
+ my ($self, $cmdstr, $logid) = @_;
+ my $cstatus = $self->SUPER::sim_hardware_cmd($cmdstr, $logid);
+
+ # update GUI outside lock
foreach my $node (keys %$cstatus) {
my $d = $self->{nodes}->{$node};
$d->{network_btn}->set_active($cstatus->{$node}->{network} eq 'on');
$d->{power_btn}->set_active($cstatus->{$node}->{power} eq 'on');
}
- return $res;
+ return $cstatus;
}
sub cleanup {
$self->{logfh}->flush();
}
-# simulate hardware commands
-# power <node> <on|off>
-# network <node> <on|off>
-# reboot <node>
-# shutdown <node>
-# restart-lrm <node>
-# service <sid> <started|disabled|stopped>
-# service <sid> <migrate|relocate> <target>
-# service <sid> lock/unlock [lockname]
-
-sub sim_hardware_cmd {
- my ($self, $cmdstr, $logid) = @_;
-
- my $code = sub {
-
- my $cstatus = $self->read_hardware_status_nolock();
-
- my ($cmd, $objid, $action, $target) = split(/\s+/, $cmdstr);
-
- die "sim_hardware_cmd: no node or service for command specified"
- if !$objid;
-
- my ($node, $sid, $d);
-
- if ($cmd eq 'service') {
- $sid = PVE::HA::Tools::pve_verify_ha_resource_id($objid);
- } else {
- $node = $objid;
- $d = $self->{nodes}->{$node} ||
- die "sim_hardware_cmd: no such node '$node'\n";
- }
-
- $self->log('info', "execute $cmdstr", $logid);
-
- if ($cmd eq 'power') {
- die "sim_hardware_cmd: unknown action '$action'" if $action !~ m/^(on|off)$/;
- if ($cstatus->{$node}->{power} ne $action) {
- if ($action eq 'on') {
- $d->{crm} = PVE::HA::CRM->new($d->{crm_env}) if !$d->{crm};
- $d->{lrm} = PVE::HA::LRM->new($d->{lrm_env}) if !$d->{lrm};
- $d->{lrm_restart} = undef;
- } else {
- if ($d->{crm}) {
- $d->{crm_env}->log('info', "killed by poweroff");
- $d->{crm} = undef;
- }
- if ($d->{lrm}) {
- $d->{lrm_env}->log('info', "killed by poweroff");
- $d->{lrm} = undef;
- $d->{lrm_restart} = undef;
- }
- $self->watchdog_reset_nolock($node);
- $self->write_service_status($node, {});
- }
- }
-
- $cstatus->{$node}->{power} = $action;
- $cstatus->{$node}->{network} = $action;
- $cstatus->{$node}->{shutdown} = undef;
-
- $self->write_hardware_status_nolock($cstatus);
-
- } elsif ($cmd eq 'network') {
- die "sim_hardware_cmd: unknown network action '$action'"
- if $action !~ m/^(on|off)$/;
- $cstatus->{$node}->{network} = $action;
-
- $self->write_hardware_status_nolock($cstatus);
-
- } elsif ($cmd eq 'reboot' || $cmd eq 'shutdown') {
- $cstatus->{$node}->{shutdown} = $cmd;
-
- $self->write_hardware_status_nolock($cstatus);
-
- $d->{lrm}->shutdown_request() if $d->{lrm};
- } elsif ($cmd eq 'restart-lrm') {
- if ($d->{lrm}) {
- $d->{lrm_restart} = 1;
- $d->{lrm}->shutdown_request();
- }
- } elsif ($cmd eq 'crm') {
-
- if ($action eq 'stop') {
- if ($d->{crm}) {
- $d->{crm_stop} = 1;
- $d->{crm}->shutdown_request();
- }
- } elsif ($action eq 'start') {
- $d->{crm} = PVE::HA::CRM->new($d->{crm_env}) if !$d->{crm};
- } else {
- die "sim_hardware_cmd: unknown action '$action'";
- }
-
- } elsif ($cmd eq 'service') {
- if ($action eq 'started' || $action eq 'disabled' || $action eq 'stopped') {
-
- $self->set_service_state($sid, $action);
-
- } elsif ($action eq 'migrate' || $action eq 'relocate') {
-
- die "sim_hardware_cmd: missing target node for '$action' command"
- if !$target;
-
- $self->queue_crm_commands_nolock("$action $sid $target");
-
- } elsif ($action eq 'add') {
-
- $self->add_service($sid, {state => 'started', node => $target});
-
- } elsif ($action eq 'delete') {
-
- $self->delete_service($sid);
-
- } elsif ($action eq 'lock') {
-
- $self->lock_service($sid, $target);
-
- } elsif ($action eq 'unlock') {
-
- $self->unlock_service($sid, $target);
-
- } else {
- die "sim_hardware_cmd: unknown service action '$action' " .
- "- not implemented\n"
- }
- } else {
- die "sim_hardware_cmd: unknown command '$cmdstr'\n";
- }
+# for controlling the resource manager services (CRM and LRM)
+sub crm_control {
+ my ($self, $action, $data, $lock_fh) = @_;
+
+ if ($action eq 'start') {
+ return PVE::HA::CRM->new($data->{crm_env});
+ } elsif ($action eq 'stop') {
+ # nothing todo sim_hardware_cmd sets us to undef, thats enough
+ } elsif ($action eq 'shutdown') {
+ $data->{crm}->shutdown_request();
+ } else {
+ die "unknown CRM control action: '$action'\n";
+ }
+}
- };
+sub lrm_control {
+ my ($self, $action, $data, $lock_fh) = @_;
+
+ if ($action eq 'start') {
+ return PVE::HA::LRM->new($data->{lrm_env});
+ } elsif ($action eq 'stop') {
+ # nothing todo sim_hardware_cmd sets us to undef, thats enough
+ } elsif ($action eq 'shutdown') {
+ $data->{lrm}->shutdown_request();
+ } else {
+ die "unknown LRM control action: '$action'\n";
+ }
- return $self->global_lock($code);
}
sub run {