[pve-devel] [RFC] Adding PVECT resource class so that CT can be HA managed

Thomas Lamprecht t.lamprecht at proxmox.com
Mon Aug 31 16:40:38 CEST 2015


Adding an abstraction so that the HA manager can start, stop and
migrate services independent of the its type.

Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
---
 src/PVE/HA/Config.pm    |   1 +
 src/PVE/HA/Env/PVE2.pm  |  55 ++++++++++------------
 src/PVE/HA/Resources.pm | 121 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 146 insertions(+), 31 deletions(-)

diff --git a/src/PVE/HA/Config.pm b/src/PVE/HA/Config.pm
index 58f5b58..b860abc 100644
--- a/src/PVE/HA/Config.pm
+++ b/src/PVE/HA/Config.pm
@@ -14,6 +14,7 @@ PVE::HA::Groups->register();
 PVE::HA::Groups->init();
 
 PVE::HA::Resources::PVEVM->register();
+PVE::HA::Resources::PVECT->register();
 #PVE::HA::Resources::IPAddr->register();
 
 PVE::HA::Resources->init();
diff --git a/src/PVE/HA/Env/PVE2.pm b/src/PVE/HA/Env/PVE2.pm
index 4193f49..1da6253 100644
--- a/src/PVE/HA/Env/PVE2.pm
+++ b/src/PVE/HA/Env/PVE2.pm
@@ -16,8 +16,6 @@ use PVE::HA::Tools;
 use PVE::HA::Env;
 use PVE::HA::Config;
 
-use PVE::QemuServer;
-use PVE::API2::Qemu;
 
 my $lockdir = "/etc/pve/priv/lock";
 
@@ -99,7 +97,7 @@ sub read_service_config {
 	my $d = $res->{ids}->{$sid};
 	my (undef, undef, $name) = PVE::HA::Tools::parse_sid($sid);
 	$d->{state} = 'enabled' if !defined($d->{state});
-	if ($d->{type} eq 'vm') {
+	if (PVE::HA::Resources->lookup($d->{type})) {
 	    if (my $vmd = $vmlist->{ids}->{$name}) {
 		if (!$vmd) {
 		    warn "no such VM '$name'\n";
@@ -125,9 +123,9 @@ sub change_service_location {
 
     my (undef, $type, $name) = PVE::HA::Tools::parse_sid($sid);
 
-    if ($type eq 'vm') {
-	my $old = PVE::QemuServer::config_file($name, $current_node);
-	my $new = PVE::QemuServer::config_file($name, $new_node);
+    if(my $plugin = PVE::HA::Resources->lookup($type)) {
+	my $old = $plugin->config_file($name, $current_node);
+	my $new = $plugin->config_file($name, $current_node);
 	rename($old, $new) ||
 	    die "rename '$old' to '$new' failed - $!\n";
     } else {
@@ -382,16 +380,18 @@ sub exec_resource_agent {
 
     my (undef, $service_type, $service_name) = PVE::HA::Tools::parse_sid($sid);
 
-    die "service type '$service_type'not implemented" if $service_type ne 'vm';
+    #die "service type '$service_type'not implemented" if $service_type ne 'vm';
+    my $plugin = PVE::HA::Resources->lookup($service_type);
+    die "service type '$service_type' not implemented" if !$plugin;
+
+    # fixme: return valid_exit code
+    die "service '$sid' not on this node" if $service_config->{node} ne $nodename;
 
     my $vmid = $service_name;
 
-    my $running = PVE::QemuServer::check_running($vmid, 1);
- 
-    if ($cmd eq 'started') {
+    my $running = $plugin->check_running($vmid);
 
-	# fixme: return valid_exit code
-	die "service '$sid' not on this node" if $service_config->{node} ne $nodename;
+    if ($cmd eq 'started') {
 
 	# fixme: count failures
 	
@@ -399,10 +399,10 @@ sub exec_resource_agent {
 
 	$self->log("info", "starting service $sid");
 
-	my $upid = PVE::API2::Qemu->vm_start({node => $nodename, vmid => $vmid});
-	$self->upid_wait($upid);
+	my $param = {node => $nodename, vmid => $vmid};
+	$plugin->start($self, $param);
 
-	$running = PVE::QemuServer::check_running($vmid, 1);
+	$running = $plugin->check_running($vmid);
 
 	if ($running) {
 	    $self->log("info", "service status $sid started");
@@ -414,26 +414,22 @@ sub exec_resource_agent {
 
     } elsif ($cmd eq 'request_stop' || $cmd eq 'stopped') {
 
-	# fixme: return valid_exit code
-	die "service '$sid' not on this node" if $service_config->{node} ne $nodename;
-
 	return 0 if !$running;
 
 	$self->log("info", "stopping service $sid");
 
 	my $timeout = 60; # fixme: make this configurable
-	
+
 	my $param = {
-	    node => $nodename, 
-	    vmid => $vmid, 
+	    node => $nodename,
+	    vmid => $vmid,
 	    timeout => $timeout,
 	    forceStop => 1,
 	};
 
-	my $upid = PVE::API2::Qemu->vm_shutdown($param);
-	$self->upid_wait($upid);
+	$plugin->shutdown($self, $param);
 
-	$running = PVE::QemuServer::check_running($vmid, 1);
+	$running = $plugin->check_running($vmid);
 
 	if (!$running) {
 	    $self->log("info", "service status $sid stopped");
@@ -447,9 +443,6 @@ sub exec_resource_agent {
 	my $target = $params[0];
 	die "$cmd '$sid' failed - missing target\n" if !defined($target);
 
-	# fixme: return valid_exit code
-	die "service '$sid' not on this node" if $service_config->{node} ne $nodename;
-	
 	if ($service_config->{node} eq $target) {
 	    # already there
 	    return 0;
@@ -460,7 +453,8 @@ sub exec_resource_agent {
 	    $self->log("info", "service $sid moved to node '$target'");
 	    return 0;
 	} else {
-	    # we alwas do live migration if VM is online
+	    # we always do live migration if it's a VM and it's online
+	    # container get stopped, migrated and then started again
 
 	    my $params = {
 		node => $nodename, 
@@ -469,10 +463,9 @@ sub exec_resource_agent {
 		online => 1,
 	    };
 
-	    my $oldconfig = PVE::QemuServer::config_file($vmid, $nodename);
+	    my $oldconfig = $plugin->config_file($vmid, $nodename);
 
-	    my $upid = PVE::API2::Qemu->migrate_vm($params);
-	    $self->upid_wait($upid);
+	    $plugin->migrate($params);
 
 	    # something went wrong if old config file is still there
 	    if (-f $oldconfig) {
diff --git a/src/PVE/HA/Resources.pm b/src/PVE/HA/Resources.pm
index 099280d..9828e22 100644
--- a/src/PVE/HA/Resources.pm
+++ b/src/PVE/HA/Resources.pm
@@ -8,6 +8,12 @@ use PVE::JSONSchema qw(get_standard_option);
 use PVE::SectionConfig;
 use PVE::HA::Tools;
 
+use PVE::QemuServer;
+use PVE::API2::Qemu;
+
+use PVE::LXC;
+use PVE::API2::LXC::Status;
+
 use base qw(PVE::SectionConfig);
 
 my $defaultData = {
@@ -69,6 +75,26 @@ sub parse_section_header {
     return undef;
 }
 
+sub start {
+    die "implement in subclass";
+}
+
+sub shutdown {
+    die "implement in subclass";
+}
+
+sub migrate {
+    die "implement in subclass";
+}
+
+sub config_file {
+    die "implement in subclass"
+}
+
+sub check_running {
+    die "implement in subclass";
+}
+
 package PVE::HA::Resources::PVEVM;
 
 use strict;
@@ -94,6 +120,101 @@ sub options {
     };
 }
 
+sub config_file {
+    my ($class, $vmid, $nodename);
+
+    return PVE::QemuServer::config_file($vmid, $nodename);
+}
+
+sub start {
+    my ($class, $haenv, $param) = @_;
+
+    my $upid = PVE::API2::Qemu->vm_start($param);
+    $haenv->upid_wait($upid);
+}
+
+sub shutdown {
+    my ($class, $haenv, $param) = @_;
+
+    my $upid = PVE::API2::Qemu->vm_shutdown($param);
+    $haenv->upid_wait($upid);
+}
+
+
+sub migrate {
+    my ($class, $haenv, $params) = @_;
+
+    my $upid = PVE::API2::Qemu->migrate_vm($params);
+    $haenv->upid_wait($upid);
+}
+
+sub check_running {
+    my ($class, $vmid) = @_;
+
+    return PVE::QemuServer::check_running($vmid, 1);
+}
+
+
+package PVE::HA::Resources::PVECT;
+
+use strict;
+use warnings;
+
+use base qw(PVE::HA::Resources);
+
+sub type {
+    return 'ct';
+}
+
+sub verify_name {
+    my ($class, $name) = @_;
+
+    die "invalid VMID\n" if $name !~ m/^[1-9][0-9]+$/;
+}
+
+sub options {
+    return {
+	state => { optional => 1 },
+	group => { optional => 1 },
+	comment => { optional => 1 },
+    };
+}
+
+sub config_file {
+    my ($class, $vmid, $nodename);
+
+    return PVE::LXC::config_file($vmid, $nodename);
+}
+
+sub start {
+    my ($class, $haenv, $param) = @_;
+
+    my $upid = PVE::API2::LXC::Status->vm_start($param);
+    $haenv->upid_wait($upid);
+}
+
+sub shutdown {
+    my ($class, $haenv, $params) = @_;
+
+    my $upid = PVE::API2::LXC::Status->vm_shutdown($params);
+    $haenv->upid_wait($upid);
+}
+
+# no live migration for LXC
+# so we die for now
+sub migrate {
+    my ($class, $haenv, $params) = @_;
+
+    die "no live migration for LXC - stop it then migrate it";
+
+}
+
+sub check_running {
+    my ($class, $vmid) = @_;
+
+    return PVE::LXC::check_running($vmid);
+}
+
 # package PVE::HA::Resources::IPAddr;
 
 # use strict;
-- 
2.1.4




More information about the pve-devel mailing list