You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ngcp-panel/lib/NGCP/Panel/Utils/DeviceBootstrap/ALE.pm

198 lines
7.6 KiB

package NGCP::Panel::Utils::DeviceBootstrap::ALE;
use strict;
use warnings;
use URI::Escape;
use Moo;
use Types::Standard qw(Str);
use JSON qw/encode_json decode_json/;
use MIME::Base64;
use Digest::MD5 qw/md5_hex/;
extends 'NGCP::Panel::Utils::DeviceBootstrap::VendorREST';
sub rpc_server_params{
my $self = shift;
my $cfg = {
proto => 'https',
host => 'api.rps.ce.al-enterprise.com',
path => 'api',
};
$self->{rpc_server_params} = $cfg;
return $self->{rpc_server_params};
}
sub rest_prepare_request {
my ($self, $action) = @_;
my $c = $self->params->{c};
my $ret;
my $new_mac = $self->content_params->{mac};
my $old_mac = $self->content_params->{mac_old};
my $param_servername = $self->content_params->{server_name};
my $param_uri = $self->content_params->{uri};
my $token;
$self->{rpc_server_params} //= $self->rpc_server_params;
my $cfg = $self->{rpc_server_params};
$c->log->debug("ALE prepare request for action $action");
# first, generate token
my $url = "$$cfg{proto}://$$cfg{host}/$$cfg{path}/bp_user/generate/token";
$c->log->debug("ALE generate token '$url'");
my $req = HTTP::Request->new(GET => $url);
$req->header(':api_user_name' => $self->params->{credentials}->{user});
$req->header(':api_password' => $self->params->{credentials}->{password});
my $res = $self->_ua->request($req);
my $data = decode_json($res->decoded_content);
if ($res->is_success && $data->{success}) {
$c->log->debug("Token generation successful, data: " . $res->decoded_content);
$token = $data->{data}->{token};
} else {
$c->log->error("Token generation failed (" . $res->status_line . "): " . $res->decoded_content);
return;
}
if ($action eq 'register_content') {
# fetch server
$url = "$$cfg{proto}://$$cfg{host}/$$cfg{path}/servers";
$c->log->debug("ALE check server '$url'");
$req = HTTP::Request->new(GET => $url);
$req->header(token => $token);
$res = $self->_ua->request($req);
my $server_id;
$data = decode_json($res->decoded_content);
if ($res->is_success && $data->{success}) {
$c->log->debug("ALE check server query successful, data: " . $res->decoded_content);
my ($server) = grep {$_->{server_url} eq $param_uri} @{$data->{data}->{server_list}};
if ($server) {
$server_id = $server->{server_id};
}
else {
#server does not exist, create it
$c->log->debug("ALE create server '$url'");
$req = HTTP::Request->new(POST => $url);
$req->header(token => $token);
$req->content_type('application/json');
$req->content(encode_json({
server_name => $param_servername,
server_url => $param_uri,
})
);
$res = $self->_ua->request($req);
$data = decode_json($res->decoded_content);
if ($res->is_success && $data->{success}) {
$c->log->debug("ALE create server query successful, data: " . $res->decoded_content);
$server_id = $data->{data}->{server_id};
}
else{
$c->log->error("ALE create server query failed (" . $res->status_line . "): " . $res->decoded_content);
return;
}
}
} else {
$c->log->error("ALE check server query failed (" . $res->status_line . "): " . $res->decoded_content);
return;
}
# fetch profile
$url = "$$cfg{proto}://$$cfg{host}/$$cfg{path}/profiles";
$c->log->debug("ALE check server '$url'");
$req = HTTP::Request->new(GET => $url);
$req->header(token => $token);
$res = $self->_ua->request($req);
$data = decode_json($res->decoded_content);
if ($res->is_success && $data->{success}) {
$c->log->debug("ALE check profile query successful, data: " . $res->decoded_content);
my $profile_id;
my ($profile) = grep {$_->{server_id} == $server_id} @{$data->{data}->{profile_list}};
if ($profile) {
$profile_id = $profile->{profile_id};
}
else {
#profile does not exist, create it
$c->log->debug("ALE create profile '$url'");
$req = HTTP::Request->new(POST => $url);
$req->header(token => $token);
$req->content_type('application/json');
$req->content(encode_json({
profile_name => $param_servername,
server_id => $server_id,
})
);
$res = $self->_ua->request($req);
$data = decode_json($res->decoded_content);
if ($res->is_success && $data->{success}) {
$c->log->debug("ALE create profile query successful, data: " . $res->decoded_content);
$profile_id = $data->{data}->{profile_id};
}
else{
$c->log->error("ALE create profile query failed (" . $res->status_line . "): " . $res->decoded_content);
return;
}
}
$ret = {
method =>'POST',
url => "$$cfg{proto}://$$cfg{host}/$$cfg{path}/devices",
body => { macs => [{mac =>$new_mac}], profile_id => $profile_id},
token => $token,
};
} else {
$c->log->error("ALE check profile query failed (" . $res->status_line . "): " . $res->decoded_content);
return;
}
} elsif ($action eq 'unregister_content') {
# we've to fetch the id first before constructing the delete request
$url = "$$cfg{proto}://$$cfg{host}/$$cfg{path}/devices";
$c->log->debug("ALE check devices '$url'");
$req = HTTP::Request->new(GET => $url);
$req->header(token => $token);
$res = $self->_ua->request($req);
$data = decode_json($res->decoded_content);
if ($res->is_success && $data->{success}) {
$c->log->debug("ALE check devices query successful, data: " . $res->decoded_content);
my $device_id;
my ($device) = grep {$_->{mac} == $old_mac} @{$data->{data}->{device_list}};
if ($device) {
$device_id = $device->{device_id};
}
$c->log->debug("ALE unregister query successful, data: " . $res->decoded_content);
$data = decode_json($res->decoded_content);
$ret = {
method =>'DELETE',
url => "$$cfg{proto}://$$cfg{host}/$$cfg{path}/devices/$device_id",
body => undef,
token => $token,
};
} else {
$c->log->error("ALE unregister query failed (" . $res->status_line . "): " . $res->decoded_content);
return;
}
}
return $ret;
}
around 'process_bootstrap_uri' => sub {
my($orig_method, $self, $uri) = @_;
$uri = $self->$orig_method($uri);
$self->content_params->{uri} = $uri;
$self->bootstrap_uri_server_name($uri);
return $self->content_params->{uri};
};
sub bootstrap_uri_server_name{
my($self,$uri) = @_;
$uri ||= $self->content_params->{uri};
#http://stackoverflow.com/questions/4826403/hash-algorithm-with-alphanumeric-output-of-20-characters-max
$self->content_params->{server_name} ||= substr(md5_hex($uri),0,20);
return $self->content_params->{server_name};
}
1;