[pve-devel] [PATCH RFC 19/21] use https API call for addnode

Dietmar Maurer dietmar at proxmox.com
Mon Nov 28 08:09:11 CET 2016


And remove 'addnode' from pvecm command line tool. It has too
many parameters now, and confuses the user anyways ('add' is
the correct command for the user).

Signed-off-by: Dietmar Maurer <dietmar at proxmox.com>
---
 data/PVE/API2/ClusterConfig.pm |  51 +++++++++++++++--
 data/PVE/CLI/pvecm.pm          | 123 ++++++++++++++++++++---------------------
 2 files changed, 106 insertions(+), 68 deletions(-)

diff --git a/data/PVE/API2/ClusterConfig.pm b/data/PVE/API2/ClusterConfig.pm
index 6ac2378..7398621 100644
--- a/data/PVE/API2/ClusterConfig.pm
+++ b/data/PVE/API2/ClusterConfig.pm
@@ -99,19 +99,41 @@ __PACKAGE__->register_method ({
 	    },
 	    ring0_addr => {
 		type => 'string', format => 'address',
-		description => "Hostname (or IP) of the corosync ring0 address of this node.".
-		    " Defaults to nodes hostname.",
+		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 bindnet1_addr.",
+		description => "Hostname (or IP) of the corosync ring1 address, this needs an valid bindnet1_addr.",
 		optional => 1,
 	    },
+	    ssh_host_pubkey => {
+		type => 'string',
+		description => "Contents of /etc/ssh/ssh_host_rsa_key.pub from joining node.",
+	    },
+	    ssh_root_pubkey => {
+		type => 'string',
+		description => "Contents of /root/.ssh/id_rsa.pub from joining node.",
+	    },
+	},
+    },
+    returns => {
+	type => "object",
+	properties => {
+	    ssh_host_cert => {
+		type => 'string',
+	    },
+	    ssh_root_cert => {
+		type => 'string',
+	    },
+	    corosync_authkey => {
+		type => 'string',
+	    },
+	    corosync_conf => {
+		type => 'string',
+	    }
 	},
     },
-    returns => { type => 'null' },
     code => sub {
 	my ($param) = @_;
 
@@ -180,7 +202,24 @@ __PACKAGE__->register_method ({
 
 	PVE::Cluster::corosync_update_nodelist($conf, $nodelist);
 
-	return undef;
+	my $res = {};
+
+	$res->{ssh_host_cert} = PVE::Cluster::gen_pve_ssh_cert(
+	    $param->{ssh_host_pubkey}, $name, "PVE-HOST-$name", 1);
+	$res->{ssh_root_cert} = PVE::Cluster::gen_pve_ssh_cert(
+	    $param->{ssh_root_pubkey}, 'root', "PVE-ROOT-$name");
+
+	my $basedir = "/etc/pve";
+	my $clusterconf = "$basedir/corosync.conf";
+	my $authfile = "/etc/corosync/authkey";
+
+	$res->{corosync_authkey} =
+	    PVE::Tools::file_get_contents($authfile);
+
+	$res->{corosync_conf} =
+	    PVE::Tools::file_get_contents($clusterconf);
+
+	return $res;
     }});
 
 
diff --git a/data/PVE/CLI/pvecm.pm b/data/PVE/CLI/pvecm.pm
index 5063b4e..4bc406a 100755
--- a/data/PVE/CLI/pvecm.pm
+++ b/data/PVE/CLI/pvecm.pm
@@ -29,10 +29,15 @@ $ENV{HOME} = '/root'; # for ssh-copy-id
 
 my $basedir = "/etc/pve";
 my $clusterconf = "$basedir/corosync.conf";
+my $localclusterconf = "/etc/corosync/corosync.conf";
 my $libdir = "/var/lib/pve-cluster";
 my $backupdir = "/var/lib/pve-cluster/backup";
 my $dbfile = "$libdir/config.db";
 my $authfile = "/etc/corosync/authkey";
+my $ssh_rsa_id = "/root/.ssh/id_rsa.pub";
+my $ssh_rsa_cert = "/root/.ssh/id_rsa-cert.pub";
+my $ssh_host_rsa_id = "/etc/ssh/ssh_host_rsa_key.pub";
+my $ssh_host_rsa_cert = "/etc/ssh/ssh_host_rsa_key-cert.pub";
 
 sub read_password {
     my $term = new Term::ReadLine ('pvecm');
@@ -499,92 +504,87 @@ __PACKAGE__->register_method ({
 	# make sure known_hosts is on local filesystem
 	PVE::Cluster::ssh_unmerge_known_hosts();
 
-	my $cmd = ['ssh-copy-id', '-i', '/root/.ssh/id_rsa', "root\@$host"];
-	PVE::Tools::run_command($cmd, 'outfunc' => sub {}, 'errfunc' => sub {},
-				'errmsg' => "unable to copy ssh ID");
+	# call addnode on remote cluster
 
-	$cmd = ['ssh', $host, '-o', 'BatchMode=yes',
-		'pvecm', 'addnode', $nodename, '--force', 1];
+	my $password = read_password();
 
-	push @$cmd, '--nodeid', $param->{nodeid} if $param->{nodeid};
-
-	push @$cmd, '--votes', $param->{votes} if defined($param->{votes});
+	# load certs for all existing nodes
+	my $nodelist = PVE::Cluster::get_nodelist();
+	foreach my $n (@$nodelist) {
+	    PVE::Cluster::initialize_cert_cache($n);
+	}
 
-	push @$cmd, '--ring0_addr', $param->{ring0_addr} if defined($param->{ring0_addr});
+	my $agent = api2_connect($host, $password);
 
-	push @$cmd, '--ring1_addr', $param->{ring1_addr} if defined($param->{ring1_addr});
+	my $ssh_root_pubkey = PVE::Tools::file_get_contents($ssh_rsa_id);
+	my $ssh_host_pubkey = PVE::Tools::file_get_contents($ssh_host_rsa_id);
 
-	if (system (@$cmd) != 0) {
-	    my $cmdtxt = join (' ', @$cmd);
-	    die "unable to add node: command failed ($cmdtxt)\n";
-	}
+	my $args = {
+	    node => $nodename,
+	    force => 1, # fixme: why?
+	    ssh_root_pubkey => $ssh_root_pubkey,
+	    ssh_host_pubkey => $ssh_host_pubkey,
+	};
 
-	my $tmpdir = "$libdir/.pvecm_add.tmp.$$";
-	mkdir $tmpdir;
+	$args->{nodeid} = $param->{nodeid} if $param->{nodeid};
 
-	eval {
-	    print "copy corosync auth key\n";
-	    $cmd = ['rsync', '--rsh=ssh -l root -o BatchMode=yes', '-lpgoq', 
-		    "[$host]:$authfile $clusterconf", $tmpdir];
+	$args->{votes} = $param->{votes} if defined($param->{votes});
 
-	    system(@$cmd) == 0 || die "can't rsync data from host '$host'\n";
+	$args->{ring0_addr} = $param->{ring0_addr} if defined($param->{ring0_addr});
 
-	    mkdir "/etc/corosync";
-	    my $confbase = basename($clusterconf);
+	$args->{ring1_addr} = $param->{ring1_addr} if defined($param->{ring1_addr});
 
-	    $cmd = "cp '$tmpdir/$confbase' '/etc/corosync/$confbase'";
-	    system($cmd) == 0 || die "can't copy cluster configuration\n";
+	my $data = api2_post($agent, $host, 'cluster/addnode', $args);
 
-	    my $keybase = basename($authfile);
-	    system ("cp '$tmpdir/$keybase' '$authfile'") == 0 ||
-		die "can't copy '$tmpdir/$keybase' to '$authfile'\n";
+	# added successfuly - now prepare local node
 
-	    print "stopping pve-cluster service\n";
+	PVE::Tools::file_set_contents($ssh_host_rsa_cert, $data->{ssh_host_cert});
+	PVE::Tools::file_set_contents($ssh_rsa_cert, $data->{ssh_root_cert});
 
-	    system("umount $basedir -f >/dev/null 2>&1");
-	    system("systemctl stop pve-cluster") == 0 ||
-		die "can't stop pve-cluster service\n";
+	mkdir "/etc/corosync";
+	PVE::Tools::file_set_contents($localclusterconf, $data->{corosync_conf});
+	PVE::Tools::file_set_contents($authfile, $data->{corosync_authkey});
 
-	    backup_database();
+	print "stopping pve-cluster service\n";
 
-	    unlink $dbfile;
+	system("umount $basedir -f >/dev/null 2>&1");
+	system("systemctl stop pve-cluster") == 0 ||
+	    die "can't stop pve-cluster service\n";
 
-	    system("systemctl start pve-cluster") == 0 ||
-		die "starting pve-cluster failed\n";
+	backup_database();
 
-	    system("systemctl start corosync");
+	unlink $dbfile;
 
-	    # wait for quorum
-	    my $printqmsg = 1;
-	    while (!PVE::Cluster::check_cfs_quorum(1)) {
-		if ($printqmsg) {
-		    print "waiting for quorum...";
-		    STDOUT->flush();
-		    $printqmsg = 0;
-		}
-		sleep(1);
-	    }
-	    print "OK\n" if !$printqmsg;
+	system("systemctl start pve-cluster") == 0 ||
+	    die "starting pve-cluster failed\n";
 
-	    # system("systemctl start clvm");
+	system("systemctl start corosync");
 
-	    my $local_ip_address = PVE::Cluster::remote_node_ip($nodename);
+	# wait for quorum
+	my $printqmsg = 1;
+	while (!PVE::Cluster::check_cfs_quorum(1)) {
+	    if ($printqmsg) {
+		print "waiting for quorum...";
+		STDOUT->flush();
+		$printqmsg = 0;
+	    }
+	    sleep(1);
+	}
+	print "OK\n" if !$printqmsg;
 
-	    $update_cluster_files->(1, $nodename, $local_ip_address, 1);
+	# system("systemctl start clvm");
 
-	    print "restart services\n";
-	    # restart pvedaemon (changed certs)
-	    system("systemctl restart pvedaemon");
-	    # restart pveproxy (changed certs)
-	    system("systemctl restart pveproxy");
+	my $local_ip_address = PVE::Cluster::remote_node_ip($nodename);
 
-	    print "successfully added node '$nodename' to cluster.\n";
-	};
-	my $err = $@;
+	$update_cluster_files->(1, $nodename, $local_ip_address, 1);
 
-	rmtree $tmpdir;
+	print "restart services\n";
+	# restart pvedaemon (changed certs)
+	system("systemctl restart pvedaemon");
+	# restart pveproxy (changed certs)
+	system("systemctl restart pveproxy");
 
-	die $err if $err;
+	print "successfully added node '$nodename' to cluster.\n";
 
 	return undef;
     }});
@@ -763,7 +763,6 @@ our $cmddef = {
     keygen => [ __PACKAGE__, 'keygen', ['filename']],
     create => [ __PACKAGE__, 'create', ['clustername']],
     add => [ __PACKAGE__, 'add', ['hostname']],
-    addnode => [ 'PVE::API2::ClusterConfig', 'addnode', ['node']],
     delnode => [ 'PVE::API2::ClusterConfig', 'delnode', ['node']],
     status => [ __PACKAGE__, 'status' ],
     nodes => [ __PACKAGE__, 'nodes' ],
-- 
2.1.4




More information about the pve-devel mailing list