On 11/20/19 5:43 PM, Stefan Reiter wrote:
> Same as we do in assert_joinable, a cluster with unconfigured IPs will
> fail start after creation anyway.
> 
> Make "check_ip" a standalone sub ("check_ip_configured") and improve
> error messages all around.
> 
> Also move call to create_conf up, so if it fails we exit before SSH and
> auth-key setup.
> 
> Signed-off-by: Stefan Reiter <s.rei...@proxmox.com>
> ---
>  data/PVE/API2/ClusterConfig.pm | 10 ++++-----
>  data/PVE/Cluster/Setup.pm      | 40 ++++++++++------------------------
>  data/PVE/Corosync.pm           | 29 ++++++++++++++++++++++++
>  3 files changed, 45 insertions(+), 34 deletions(-)
> 
> diff --git a/data/PVE/API2/ClusterConfig.pm b/data/PVE/API2/ClusterConfig.pm
> index bff0c48..0454947 100644
> --- a/data/PVE/API2/ClusterConfig.pm
> +++ b/data/PVE/API2/ClusterConfig.pm
> @@ -115,6 +115,11 @@ __PACKAGE__->register_method ({
>       my $authuser = $rpcenv->get_user();
>  
>       my $code = sub {
> +         my $nodename = PVE::INotify::nodename();
> +
> +         # get the corosync basis config for the new cluster
> +         my $config = PVE::Corosync::create_conf($nodename, $param);
> +
>           STDOUT->autoflush();
>           PVE::Cluster::Setup::setup_sshd_config(1);
>           PVE::Cluster::Setup::setup_rootsshconfig();
> @@ -124,11 +129,6 @@ __PACKAGE__->register_method ({
>               if !-f $authfile;
>           die "no authentication key available\n" if -f !$authfile;
>  
> -         my $nodename = PVE::INotify::nodename();
> -
> -         # get the corosync basis config for the new cluster
> -         my $config = PVE::Corosync::create_conf($nodename, $param);
> -
>           print "Writing corosync config to /etc/pve/corosync.conf\n";
>           PVE::Corosync::atomic_write_conf($config);
>  
> diff --git a/data/PVE/Cluster/Setup.pm b/data/PVE/Cluster/Setup.pm
> index c6f6c9e..77d3664 100644
> --- a/data/PVE/Cluster/Setup.pm
> +++ b/data/PVE/Cluster/Setup.pm
> @@ -566,55 +566,37 @@ sub assert_joinable {
>      my ($local_addr, $links, $force) = @_;
>  
>      my $errors = '';
> -    my $error = sub { $errors .= "* $_[0]\n"; };
> +    my $error = sub { $errors .= "* $_[0]"; };
>  
>      if (-f $authfile) {
> -     $error->("authentication key '$authfile' already exists");
> +     $error->("authentication key '$authfile' already exists\n");
>      }
>  
>      if (-f $clusterconf)  {
> -     $error->("cluster config '$clusterconf' already exists");
> +     $error->("cluster config '$clusterconf' already exists\n");
>      }
>  
>      my $vmlist = PVE::Cluster::get_vmlist();
>      if ($vmlist && $vmlist->{ids} && scalar(keys %{$vmlist->{ids}})) {
> -     $error->("this host already contains virtual guests");
> +     $error->("this host already contains virtual guests\n");
>      }

please avoid that manual \n, I did that with reason.. maype use chomp
on the string for your $@ case below (or in the errors sub?

>  
>      if (PVE::Tools::run_command(['corosync-quorumtool', '-l'], noerr => 1, 
> quiet => 1) == 0) {
> -     $error->("corosync is already running, is this node already in a 
> cluster?!");
> -    }
> -
> -    # check if corosync ring IPs are configured on the current nodes 
> interfaces
> -    my $check_ip = sub {
> -     my $ip = shift // return;
> -     my $logid = shift;
> -     if (!PVE::JSONSchema::pve_verify_ip($ip, 1)) {
> -         my $host = $ip;
> -         eval { $ip = PVE::Network::get_ip_from_hostname($host); };
> -         if ($@) {
> -             $error->("$logid: cannot use '$host': $@\n") ;
> -             return;
> -         }
> -     }
> -
> -     my $cidr = (Net::IP::ip_is_ipv6($ip)) ? "$ip/128" : "$ip/32";
> -     my $configured_ips = PVE::Network::get_local_ip_from_cidr($cidr);
> -
> -     $error->("$logid: cannot use IP '$ip', it must be configured exactly 
> once on local node!\n")
> -         if (scalar(@$configured_ips) != 1);
> -    };
> +     $error->("corosync is currently running, is this node already in a 
> cluster?\n");
> +    }
>  
> -    $check_ip->($local_addr, 'local node address');
> +    eval { PVE::Corosync::check_ip_configured($local_addr, 'local node 
> address'); };
> +    $error->($@) if $@;
>  
>      if ($links) {
>       foreach my $link (keys %$links) {
> -         $check_ip->($links->{$link}->{address}, "link$link");
> +         eval { 
> PVE::Corosync::check_ip_configured($links->{$link}->{address}, "link$link"); 
> };
> +         $error->($@) if $@;
>       }
>      }
>  
>      if ($errors) {
> -     warn "detected the following error(s):\n$errors";
> +     warn "Detected the following error(s):\n$errors";
>       die "Check if node may join a cluster failed!\n" if !$force;
>      }
>  }
> diff --git a/data/PVE/Corosync.pm b/data/PVE/Corosync.pm
> index 69927ff..19c8976 100644
> --- a/data/PVE/Corosync.pm
> +++ b/data/PVE/Corosync.pm
> @@ -11,6 +11,7 @@ use Socket qw(AF_INET AF_INET6 inet_ntop);
>  
>  use PVE::Cluster;
>  use PVE::JSONSchema;
> +use PVE::Network;
>  use PVE::Tools;
>  use PVE::Tools qw($IPV4RE $IPV6RE);
>  
> @@ -267,6 +268,32 @@ sub atomic_write_conf {
>       || die "activating corosync.conf.new failed - $!\n";
>  }
>  
> +# check if an IP address is configured exactly once on the local node, so 
> that
> +# corosync can safely use it as a link
> +sub check_ip_configured {
> +    my ($ip, $logid) = @_;
> +
> +    return if !defined($ip);
> +    $logid //= "error";
> +
> +    if (!PVE::JSONSchema::pve_verify_ip($ip, 1)) {
> +     my $host = $ip;
> +     eval { $ip = PVE::Network::get_ip_from_hostname($host); };
> +     if ($@) {
> +         die "$logid: cannot use '$host': $@\n";
> +     }
> +    }
> +
> +    my $cidr = (Net::IP::ip_is_ipv6($ip)) ? "$ip/128" : "$ip/32";
> +    my $configured_ips = PVE::Network::get_local_ip_from_cidr($cidr);
> +
> +    die "$logid: cannot use IP '$ip', it is not configured on local node 
> (must exist exactly once)!\n"
> +     if (scalar(@$configured_ips) < 1);
> +
> +    die "$logid: cannot use IP '$ip', it is configured multiple times on 
> local node (must exist exactly once)!\n"
> +     if (scalar(@$configured_ips) > 1);
> +};
> +
>  # for creating a new cluster with the current node
>  # params are those from the API/CLI cluster create call
>  sub create_conf {
> @@ -317,6 +344,8 @@ sub create_conf {
>      foreach my $lnum (keys %$links) {
>       my $link = $links->{$lnum};
>  
> +     check_ip_configured($link->{address}, "link$lnum");
> +
>       $totem->{interface}->{$lnum} = { linknumber => $lnum };
>  
>       my $prio = $link->{priority};
> 


_______________________________________________
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to