Exabgp.pm 4.37 KB
Newer Older
Luc Didry's avatar
Luc Didry committed
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
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
package Erco::Controller::API::Exabgp;
use Mojo::Base 'Mojolicious::Controller';
use Mojo::JSON qw(true false encode_json);
use Mojo::IOLoop;
use Mojo::UserAgent;

# Gives the list of available commands
sub commands {
    my $c = shift;

    $c->render(
        json => $c->config('commands')
    );
}

# Exec exabgp commands
sub command {
    my $c = shift;
    my $a = $c->param('action');

    my $msg = {
        success => false,
        msg     => ''
    };

    # Special case: this one doesn't have to be configured
    if ($a eq 'reload') {
        my $delay = Mojo::IOLoop->delay;

        $delay->on(finish => sub {
            my $delay = shift;
            my $result = $_[0];
            if ($result->{success}) {
                my $running = $c->is_exa_running;

                # Give time to exabgp to reload, just in case
                unless ($running) {
                    sleep 1;
                    $running = $c->is_exa_running;
                }
                if ($running) {
                    $msg->{success} = true;
                    $msg->{msg}     = $c->l('Exabgp has been successfully reloaded.');
                } else {
                    $msg->{msg} = $c->l('Exabgp has been reloaded but is not running.');
                }
            } else {
                $msg->{msg} = $result->{msg};
            }

            $c->render(
                json => $msg
            );
        });
        $c->exaconf->reload_exabgp($delay->begin(0));
        $delay->wait;
    } else {
        chomp $a;

        # Is the command authorized?
        if (grep (/^$a$/, @{$c->config('commands')})) {
            my @msgs;

            $c->render_later;
            my $ua = $c->ua;
            $ua->inactivity_timeout(300);
            $ua->websocket('ws://127.0.0.1:3005/' => sub {
                my ($ua, $ws) = @_;
                unless ($ws->is_websocket) {
                    $msg->{msg} = $c->l('WebSocket handshake failed!');
                    return $c->render(
                        json => $msg
                    );
                }

                $ws->send($a);
                $ws->on(
                    message => sub {
                        my ($ws, $msg) = @_;
                        push @msgs, $msg;
                    }
                );
                $ws->on(
                    finish => sub {
                        $msg->{success} = true;
                        $msg->{msg}     = join("\n", @msgs);
                        $c->render(
                            json => $msg
                        );
                    }
                );
            });
        } else {
            $c->app->log->info(sprintf('IP %s tried to launch the following unauthorized command: %s', $c->remote_addr, $a));
96
97
98
99
            $msg->{msg} = $c->l('You tried to launch an unauthorized command. Contact an administrator.');
            $c->render(
                json => $msg
            );
Luc Didry's avatar
Luc Didry committed
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
        }
    }
}

# Gives Exabgp status (running or not?)
sub status {
    my $c = shift;

    # Websocket part
    if ($c->tx->is_websocket) {
        $c->debug('Client connected');

        # Let's start a loop to keep client up to date
        my $loop = Mojo::IOLoop->singleton;
        $loop->stream($c->tx->connection)->timeout(10);

        $loop->recurring(1 => sub {
            if (defined($c->tx)) {
                $c->app->log->info('PID file ('.$c->config('exabgp_pid_file').') is missing or not readable!') unless (-r $c->config('exabgp_pid_file'));
                $c->tx->send(
                    {
                        json => {
                            file_missing => (-r $c->config('exabgp_pid_file')) ? false : true,
                            running      => ($c->is_exa_running) ? true : false
                        }
                    }
                );
            }
        });

        $c->on(
            finish => sub {
                $c->debug('Client disconnected');
            }
        );
    } else { # Ajax fallback part (the client is polling)
        $c->app->log->info('PID file ('.$c->config('exabgp_pid_file').') is missing or not readable!') unless (-r $c->config('exabgp_pid_file'));
        $c->render(
            json => {
                file_missing => (-r $c->config('exabgp_pid_file')) ? false : true,
                running      => ($c->is_exa_running) ? true : false
            }
        );
    }
}

1;