[pve-devel] [PATCH ha-manager 3/7] factor out and unify sim_hardware_cmd

Thomas Lamprecht t.lamprecht at proxmox.com
Fri Jan 13 14:22:15 CET 2017


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 at proxmox.com>
---
 src/PVE/HA/Sim/Hardware.pm     | 146 ++++++++++++++++++++++++++++++++++++++
 src/PVE/HA/Sim/RTHardware.pm   |  78 ++++++++-------------
 src/PVE/HA/Sim/TestHardware.pm | 156 +++++++----------------------------------
 3 files changed, 202 insertions(+), 178 deletions(-)

diff --git a/src/PVE/HA/Sim/Hardware.pm b/src/PVE/HA/Sim/Hardware.pm
index 96186de..fe6a6ed 100644
--- a/src/PVE/HA/Sim/Hardware.pm
+++ b/src/PVE/HA/Sim/Hardware.pm
@@ -498,10 +498,156 @@ 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 $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) if !defined($d->{crm});
+		    $d->{lrm} = $self->lrm_control('start', $d) 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);
+			$d->{crm} = undef;
+		    }
+		    if ($d->{lrm}) {
+			$d->{lrm_env}->log('info', "killed by poweroff");
+			$self->lrm_control('stop', $d);
+			$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) if defined($d->{lrm});
+	} elsif ($cmd eq 'restart-lrm') {
+	    if ($d->{lrm}) {
+		$d->{lrm_restart} = 1;
+		$self->lrm_control('shutdown', $d);
+	    }
+	} elsif ($cmd eq 'crm') {
+
+	    if ($action eq 'stop') {
+		if ($d->{crm}) {
+		    $d->{crm_stop} = 1;
+		    $self->crm_control('shutdown', $d);
+		}
+	    } elsif ($action eq 'start') {
+		$d->{crm} = $self->crm_control('start', $d) 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) = @_;
+
+    die "implement in subclass";
+}
+
+sub lrm_control {
+    my ($self, $action, $data) = @_;
+
     die "implement in subclass";
 }
 
diff --git a/src/PVE/HA/Sim/RTHardware.pm b/src/PVE/HA/Sim/RTHardware.pm
index ffcf593..ca15275 100644
--- a/src/PVE/HA/Sim/RTHardware.pm
+++ b/src/PVE/HA/Sim/RTHardware.pm
@@ -178,74 +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) = @_;
 
-sub sim_hardware_cmd {
-    my ($self, $cmdstr, $logid) = @_;
+    if ($action eq 'start') {
 
-    my $cstatus;
+	return  $self->fork_daemon('crm', $data->{crm_env});
 
-    # note: do not fork when we own the lock!
-    my $code = sub {
+    } 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) = @_;
 
-	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('crm', $d->{crm_env}) if !$d->{crm};
-		    $d->{lrm} = $self->fork_daemon('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('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 {
diff --git a/src/PVE/HA/Sim/TestHardware.pm b/src/PVE/HA/Sim/TestHardware.pm
index 50aef0c..2bd1d22 100644
--- a/src/PVE/HA/Sim/TestHardware.pm
+++ b/src/PVE/HA/Sim/TestHardware.pm
@@ -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) = @_;
+
+    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) = @_;
+
+    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 {
-- 
2.1.4




More information about the pve-devel mailing list