]> git.proxmox.com Git - pve-ha-manager.git/commitdiff
factor out and unify sim_hardware_cmd
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Thu, 19 Jan 2017 12:32:46 +0000 (13:32 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Tue, 24 Jan 2017 08:50:40 +0000 (09:50 +0100)
Most things done by sim_hardware_cmd are already abstracted and
available in both, the TestHardware and the RTHardware class.

Abstract out the CRM and LRM control to allow the unification of both
classes sim_hardware_cmd.

As in the last year mostly the regression test systems TestHardware
class saw new features use it as base.

We return now the current status out of the locked context, this
allows to update the simulators GUI out of the locked context.

This changes increases the power of the HA Simulator, but the new
possible actions must be still implemented in its GUI. This will be
done in future patches.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
src/PVE/HA/Sim/Hardware.pm
src/PVE/HA/Sim/RTHardware.pm
src/PVE/HA/Sim/TestHardware.pm

index 96186de4942680cb0fbb80579563cec66276ea3a..298c3bb78204167129542b3a4b3a0a3a4ead779c 100644 (file)
@@ -498,10 +498,157 @@ sub get_node_info {
 # 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";
 }
 
index 145d73b9bc78d4f3312852bda139f97846f5cf40..33debaa13d99011975d334d883014fd1a0cc150d 100644 (file)
@@ -178,75 +178,56 @@ sub fork_daemon {
     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 {
index 50aef0c3f99809c2b160e704136fc7bbe5697c53..57531c5b1c5157f690c9a6bf2e057be57d661d02 100644 (file)
@@ -81,138 +81,34 @@ sub log {
     $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 {