[pve-devel] [RFC cluster 4/6] api: add joint cluster endpoint

Thomas Lamprecht t.lamprecht at proxmox.com
Mon Nov 27 14:13:01 CET 2017


Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
---
 data/PVE/API2/ClusterConfig.pm | 125 ++++++++++++++++++++++++++++++++++++++++-
 debian/control.in              |   2 +
 2 files changed, 126 insertions(+), 1 deletion(-)

diff --git a/data/PVE/API2/ClusterConfig.pm b/data/PVE/API2/ClusterConfig.pm
index c38feb2..9a4d9f5 100644
--- a/data/PVE/API2/ClusterConfig.pm
+++ b/data/PVE/API2/ClusterConfig.pm
@@ -9,6 +9,7 @@ use PVE::RESTHandler;
 use PVE::RPCEnvironment;
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::Cluster;
+use PVE::APIClient::LWP;
 use PVE::Corosync;
 
 use base qw(PVE::RESTHandler);
@@ -39,7 +40,8 @@ __PACKAGE__->register_method({
 	my $result = [
 	    { name => 'nodes' },
 	    { name => 'totem' },
-	    ];
+	    { name => 'join' },
+	];
 
 	return $result;
     }});
@@ -96,6 +98,127 @@ my $config_change_lock = sub {
 
 
 __PACKAGE__->register_method ({
+    name => 'join',
+    path => 'join',
+    method => 'POST',
+    description => "Joins this node to an existing cluster.",
+    parameters => {
+	additionalProperties => 0,
+	properties => {
+	    hostname => {
+		type => 'string',
+		description => "Hostname (or IP) of an existing cluster member."
+	    },
+	    nodeid => {
+		type => 'integer',
+		description => "Node id for this node.",
+		minimum => 1,
+		optional => 1,
+	    },
+	    votes => {
+		type => 'integer',
+		description => "Number of votes for this node",
+		minimum => 0,
+		optional => 1,
+	    },
+	    force => {
+		type => 'boolean',
+		description => "Do not throw error if node already exists.",
+		optional => 1,
+	    },
+	    ring0_addr => {
+		type => 'string', format => 'address',
+		description => "Hostname (or IP) of the corosync ring0 address of this node.".
+		    " Defaults to nodes hostname.",
+		optional => 1,
+	    },
+	    ring1_addr => {
+		type => 'string', format => 'address',
+		description => "Hostname (or IP) of the corosync ring1 address, this".
+		    " needs an valid configured ring 1 interface in the cluster.",
+		optional => 1,
+	    },
+	    fingerprint => {
+		description => "SSL certificate fingerprint. Optional in CLI environment.",
+		type => 'string',
+		pattern => '^(:?[A-Z0-9][A-Z0-9]:){31}[A-Z0-9][A-Z0-9]$',
+		optional => 1,
+	    },
+	    password => {
+		description => "Superuser (root) password of peer node.",
+		type => 'string',
+		maxLength => 128,
+	    },
+	},
+    },
+    returns => { type => 'null' },
+
+    code => sub {
+	my ($param) = @_;
+
+	my $nodename = PVE::INotify::nodename();
+	my $rpcenv = PVE::RPCEnvironment::get();
+
+	PVE::Cluster::setup_sshd_config();
+	PVE::Cluster::setup_rootsshconfig();
+	PVE::Cluster::setup_ssh_keys();
+
+	# check if we can join with the given parameters and current node state
+	PVE::Cluster::assert_joinable($param->{ring0_addr}, $param->{ring1_addr}, $param->{force});
+
+	# make sure known_hosts is on local filesystem
+	PVE::Cluster::ssh_unmerge_known_hosts();
+
+	my $host = $param->{hostname};
+
+	my $conn_args = {
+	    username => 'root at pam',
+	    password => $param->{password},
+	    cookie_name => 'PVEAuthCookie',
+	    protocol => 'https',
+	    host => $host,
+	    port => 8006,
+	};
+
+	if (my $fp = $param->{fingerprint}) {
+	    $conn_args->{cached_fingerprints} = { $fp => 1 };
+	} elsif ($rpcenv->{type} eq 'cli') {
+	    $conn_args->{manual_verification} = 1;
+	} else {
+	    raise_param_exc({
+		fingerprint => "Param 'fingerprint' only optional in interactive CLI environment."
+	    });
+	}
+
+	print "Etablishing API connection with host '$host'\n";
+
+	my $conn = PVE::APIClient::LWP->new(%$conn_args);
+	$conn->login();
+
+	print "Login succeeded.\n";
+
+	my $args = {
+	    node => $nodename,
+	};
+	$args->{force} = $param->{force} if defined($param->{force});
+	$args->{nodeid} = $param->{nodeid} if $param->{nodeid};
+	$args->{votes} = $param->{votes} if defined($param->{votes});
+	$args->{ring0_addr} = $param->{ring0_addr} if defined($param->{ring0_addr});
+	$args->{ring1_addr} = $param->{ring1_addr} if defined($param->{ring1_addr});
+
+	print "Request addition of this node\n";
+
+	my $res = $conn->post("/cluster/config/nodes", $args);
+
+	# added successfuly - now prepare local node
+
+	PVE::Cluster::finish_join($nodename, $res->{corosync_conf}, $res->{corosync_authkey});
+
+	return undef;
+    }});
+
+
+__PACKAGE__->register_method ({
     name => 'addnode',
     path => 'nodes',
     method => 'POST',
diff --git a/debian/control.in b/debian/control.in
index e6ccc90..2fce9f4 100644
--- a/debian/control.in
+++ b/debian/control.in
@@ -21,6 +21,7 @@ Build-Depends: debhelper (>= 7),
                libdigest-hmac-perl,
                dh-systemd,
                pve-doc-generator,
+               libpve-apiclient-perl,
                libuuid-perl
 Standards-Version: 3.7.3
 
@@ -47,6 +48,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, @PERLAPI@,
          faketime,
          libcrypt-ssleay-perl,
          libuuid-perl,
+         libpve-apiclient-perl,
          lsb-base
 Breaks: pve-ha-manager (<<2.0-4)
 Description: Cluster Infrastructure for Proxmox Virtual Environment
-- 
2.11.0





More information about the pve-devel mailing list