summaryrefslogtreecommitdiffstats
path: root/vespaclient/src/perl/lib/Yahoo/Vespa/Bin/GetClusterState.pm
blob: 13d645d46de6f4e45afd5cd722afbda14e5b24ac (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

package Yahoo::Vespa::Bin::GetClusterState;

use strict;
use warnings;
use Yahoo::Vespa::ArgParser;
use Yahoo::Vespa::ClusterController;
use Yahoo::Vespa::ConsoleOutput;
use Yahoo::Vespa::ContentNodeSelection;
use Yahoo::Vespa::Utils;
use Yahoo::Vespa::VespaModel;

BEGIN {
    use base 'Exporter';
    our @EXPORT = qw(
        getClusterState
    );
}

my %cluster_states;

return &init();

sub init {
    %cluster_states = ();
    return 1;
}

# Run the get node state tool
sub getClusterState { # (Command line arguments)
    my ($argsref) = @_;
    &handleCommandLine($argsref);
    detectClusterController();
    &showSettings();
    &showNodeStates();
}

# Parse command line arguments
sub handleCommandLine { # (Command line arguments)
    my ($args) = @_;
    my $description = <<EOS;
Get the cluster state of a given cluster.

EOS
    $description =~ s/(\S)\n(\S)/$1 $2/gs;
    chomp $description;

    setProgramDescription($description);
    Yahoo::Vespa::ContentNodeSelection::registerCommandLineArguments(
            NO_LOCALHOST_CONSTRAINT | CLUSTER_ONLY_LIMITATION);
    Yahoo::Vespa::VespaModel::registerCommandLineArguments();
    handleCommandLineArguments($args);
}

# Show what settings this tool is running with (if verbosity is high enough)
sub showSettings { # ()
    &Yahoo::Vespa::ClusterController::showSettings();
}

# Print all state we want to show for this request
sub showNodeStates { # ()
    
    Yahoo::Vespa::ContentNodeSelection::visit(\&showNodeStateForNode);
}

# Get the node state from cluster controller, unless already cached
sub getStateForNode { # (Type, Index, Cluster)
    my ($type, $index, $cluster) = @_;
    if (!exists $cluster_states{$cluster}) {
        my $state = getContentClusterState($cluster);
        $cluster_states{$cluster} = $state;
        if ($state->globalState eq "up") {
            printResult "\nCluster $cluster:\n";
        } else {
            printResult "\nCluster $cluster is " . COLOR_ERR
                    . $state->globalState . COLOR_RESET
                    . ". Too few nodes available.\n";
        }
    }
    return $cluster_states{$cluster}->$type->{$index};
}

# Print all states for a given node
sub showNodeStateForNode { # (Service, Index, NodeState, Model, ClusterName)
    my ($info) = @_;
    my ($cluster, $type, $index) = (
            $$info{'cluster'}, $$info{'type'}, $$info{'index'});
    my $nodestate = &getStateForNode($type, $index, $cluster);
    defined $nodestate or confess "No nodestate for $type $index $cluster";
    my $generated = $nodestate->generated;
    my $id = $cluster . "/";
    if (defined $nodestate->group) {
        $id .= $nodestate->group;
    }
    my $msg = "$cluster/$type/$index: ";
    if ($generated->state ne 'up') {
        $msg .= COLOR_ERR;
    }
    $msg .= $generated->state;
    if ($generated->state ne 'up') {
        $msg .= COLOR_RESET;
    }
    # TODO: Make the Cluster Controller always populate the reason for the
    # generated state.  Until then we'll avoid printing it to avoid confusion.
    # Use vespa-get-node-state to see the reasons on generated, user, and unit.
    #
    # if (length $generated->reason > 0) {
    #     $msg .= ': ' . $generated->reason;
    # }
    printResult $msg . "\n";
}

# ClusterState(Version: 7, Cluster state: Up, Distribution bits: 1) {
#   Group 0: mygroup. 1 node [0] {
#     All nodes in group up and available.
#   }
# }

# ClusterState(Version: 7, Cluster state: Up, Distribution bits: 1) {
#   Group 0: mygroup. 1 node [0] {
#     storage.0: Retired: foo
#   }
# }