]> git.proxmox.com Git - pmg-api.git/commitdiff
implement cluster join - first version
authorDietmar Maurer <dietmar@proxmox.com>
Thu, 6 Apr 2017 14:32:43 +0000 (16:32 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Thu, 6 Apr 2017 14:32:43 +0000 (16:32 +0200)
PMG/API2/Cluster.pm
PMG/CLI/pmgcm.pm

index 7d8f694259dbe005b44416261a3f389b8e9260ca..99d82fb6d797b6c23a6326efc6530c286c06149a 100644 (file)
@@ -11,11 +11,23 @@ use Storable qw(dclone);
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::RESTHandler;
 use PVE::INotify;
+use PVE::APIClient::LWP;
 
 use PMG::ClusterConfig;
+use PMG::Cluster;
 
 use base qw(PVE::RESTHandler);
 
+sub cluster_join {
+    my ($conn_setup) = @_;
+
+    my $conn = PVE::APIClient::LWP->new(%$conn_setup);
+
+    my $info = PMG::Cluster::read_local_cluster_info();
+
+    my $res = $conn->post("/config/cluster/nodes", $info);
+}
+
 __PACKAGE__->register_method({
     name => 'index',
     path => '',
@@ -82,6 +94,51 @@ __PACKAGE__->register_method({
        return PVE::RESTHandler::hash_to_array($cfg->{ids}, 'cid');
     }});
 
+my $add_node_schema = PMG::ClusterConfig::Node->createSchema(1);
+delete  $add_node_schema->{properties}->{cid};
+
+__PACKAGE__->register_method({
+    name => 'add_node',
+    path => 'nodes',
+    method => 'POST',
+    description => "Add an node to the cluster config.",
+    proxyto => 'master',
+    protected => 1,
+    parameters => $add_node_schema,
+    returns => { type => 'null' },
+    code => sub {
+       my ($param) = @_;
+
+       my $code = sub {
+           my $cfg = PMG::ClusterConfig->new();
+
+           die "no cluster defined\n" if !scalar(keys %{$cfg->{ids}});
+
+           my $master = $cfg->{master} || die "unable to lookup master node\n";
+
+           $master->{maxcid}++;
+
+           my $node = {
+               type => 'node',
+               cid => $master->{maxcid},
+           };
+
+           foreach my $k (qw(ip name hostrsapubkey rootrsapubkey fingerprint)) {
+               $node->{$k} = $param->{$k};
+           }
+
+           # fixme: test if IP or name already exists
+
+           $cfg->{ids}->{$node->{cid}} = $node;
+
+           $cfg->write();
+       };
+
+       PMG::ClusterConfig::lock_config($code, "create cluster failed");
+
+       return undef;
+    }});
+
 __PACKAGE__->register_method({
     name => 'create',
     path => 'create',
@@ -134,6 +191,11 @@ __PACKAGE__->register_method({
                type => 'string',
                pattern => '^(:?[A-Z0-9][A-Z0-9]:){31}[A-Z0-9][A-Z0-9]$',
            },
+           password => {
+               description => "Superuser password.",
+               type => 'string',
+               maxLength => 128,
+           },
        },
     },
     returns => { type => 'null' },
@@ -145,7 +207,17 @@ __PACKAGE__->register_method({
 
            die "cluster alreayd defined\n" if scalar(keys %{$cfg->{ids}});
 
-           die "implement me";
+           my $setup = {
+               username => 'root@pam',
+               password => $param->{password},
+               cookie_name => 'PMGAuthCookie',
+               host => $param->{master_ip},
+               cached_fingerprints => {
+                   $param->{fingerprint} => 1,
+               }
+           };
+
+           cluster_join($setup);
        };
 
        PMG::ClusterConfig::lock_config($code, "cluster join failed");
index cc30add08fb71526e27ac73094bd82f4577797b8..b99eaeb67bb83b4d8dd5bc2bdde11b1411dbd925 100644 (file)
@@ -3,6 +3,8 @@ package PMG::CLI::pmgcm;
 use strict;
 use warnings;
 use Data::Dumper;
+use Term::ReadLine;
+use JSON;
 
 use PVE::SafeSyslog;
 use PVE::Tools qw(extract_param);
@@ -54,7 +56,7 @@ __PACKAGE__->register_method({
            my $master = $cfg->{master} ||
                die "no master found\n";
 
-           print "pmgcm join --master_ip $master->{ip} --fingerprint $master->{fingerprint}\n";
+           print "pmgcm join $master->{ip} --fingerprint $master->{fingerprint}\n";
 
        } else {
            die "no cluster defined\n";
@@ -63,10 +65,67 @@ __PACKAGE__->register_method({
        return undef;
     }});
 
+__PACKAGE__->register_method({
+    name => 'join',
+    path => 'join',
+    method => 'GET',
+    description => "Join a new node to an existing cluster.",
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           master_ip => {
+               description => "IP address.",
+               type => 'string', format => 'ip',
+           },
+           fingerprint => {
+               description => "SSL certificate fingerprint.",
+               type => 'string',
+               pattern => '^(:?[A-Z0-9][A-Z0-9]:){31}[A-Z0-9][A-Z0-9]$',
+               optional => 1,
+           },
+       },
+    },
+    returns => { type => 'null' },
+    code => sub {
+       my ($param) = @_;
+
+       my $code = sub {
+           my $cfg = PVE::INotify::read_file('cluster.conf');
+
+           die "cluster alreayd defined\n" if scalar(keys %{$cfg->{ids}});
+
+           my $term = new Term::ReadLine ('pmgcm');
+           my $attribs = $term->Attribs;
+           $attribs->{redisplay_function} = $attribs->{shadow_redisplay};
+           my $password = $term->readline('Enter password: ');
+
+           my $setup = {
+               username => 'root@pam',
+               password => $password,
+               cookie_name => 'PMGAuthCookie',
+               host => $param->{master_ip},
+           };
+           if ($param->{fingerprint}) {
+               $setup->{cached_fingerprints} = {
+                   $param->{fingerprint} => 1,
+               };
+           } else {
+               # allow manual fingerprint verification
+               $setup->{manual_verification} = 1;
+           }
+
+           PMG::API2::Cluster::cluster_join($setup);
+       };
+
+       PMG::ClusterConfig::lock_config($code, "cluster join failed");
+
+       return undef;
+    }});
+
 our $cmddef = {
     nodes => [ 'PMG::API2::Cluster', 'nodes', [], {}, $format_nodelist],
     create => [ 'PMG::API2::Cluster', 'create', []],
-    join => [ 'PMG::API2::Cluster', 'join', ['master_ip', 'fingerprint']],
+    join => [ __PACKAGE__, 'join', ['master_ip']],
     join_cmd => [ __PACKAGE__, 'join_cmd', []],
 };