MT#16273 Implement X1 agent interface for REST

On X1 requests, properly update the configured agents on the cluster.
Currently we only throw an error if no agents are configured at all,
but let it slip through if the actual requests are failing, as they
might be down or failing.

Change-Id: I0f4e021a5cc4ba6a30e30bb197ed20d4504797d8
changes/22/3622/2
Andreas Granig 10 years ago
parent 7e7e148292
commit 520b66201e

@ -10,6 +10,7 @@ use HTTP::Headers qw();
use HTTP::Status qw(:constants);
use MooseX::ClassAttribute qw(class_has);
use NGCP::Panel::Utils::DateTime;
use NGCP::Panel::Utils::Interception;
use Path::Tiny qw(path);
use Safe::Isa qw($_isa);
use UUID qw/generate unparse/;
@ -210,9 +211,24 @@ sub POST :Allow {
$resource = $self->resnames_to_dbnames($resource);
try {
$item = $c->model('DB')->resultset('voip_intercept')->create($resource);
my $res = NGCP::Panel::Utils::Interception::request($c, 'POST', undef, {
liid => $resource->{liid},
uuid => $resource->{uuid},
number => $resource->{number},
sip_username => $sub->username,
sip_domain => $sub->domain->domain,
delivery_host => $resource->{x2_host},
delivery_port => $resource->{x2_port},
delivery_user => $resource->{x2_user},
delivery_password => $resource->{x2_password},
cc_required => $resource->{x3_required},
cc_delivery_host => $resource->{x3_host},
cc_delivery_port => $resource->{x3_port},
});
die "Failed to populate capture agents\n" unless($res);
} catch($e) {
$c->log->error("failed to create interception: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create interception.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create interception");
last;
}

@ -8,6 +8,7 @@ use HTTP::Status qw(:constants);
use MooseX::ClassAttribute qw(class_has);
use NGCP::Panel::Utils::DateTime;
use NGCP::Panel::Utils::ValidateJSON qw();
use NGCP::Panel::Utils::Interception;
use Path::Tiny qw(path);
use Safe::Isa qw($_isa);
BEGIN { extends 'Catalyst::Controller::ActionRole'; }
@ -107,6 +108,26 @@ sub PATCH :Allow {
$item = $self->update_item($c, $item, $old_resource, $resource, $form);
last unless $item;
my ($sub, $reseller) = $self->subres_from_number($c, $resource->{number});
last unless($sub && $reseller);
my $res = NGCP::Panel::Utils::Interception::request($c, 'PUT', $item->uuid, {
number => $resource->{number},
sip_username => $sub->username,
sip_domain => $sub->domain->domain,
delivery_host => $resource->{x2_host},
delivery_port => $resource->{x2_port},
delivery_user => $resource->{x2_user},
delivery_password => $resource->{x2_password},
cc_required => $resource->{x3_required},
cc_delivery_host => $resource->{x3_host},
cc_delivery_port => $resource->{x3_port},
});
unless($res) {
$c->log->error("failed to update capture agents");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update capture agents");
last;
}
$guard->commit;
@ -147,6 +168,26 @@ sub PUT :Allow {
$item = $self->update_item($c, $item, $old_resource, $resource, $form);
last unless $item;
my ($sub, $reseller) = $self->subres_from_number($c, $resource->{number});
last unless($sub && $reseller);
my $res = NGCP::Panel::Utils::Interception::request($c, 'PUT', $item->uuid, {
number => $resource->{number},
sip_username => $sub->username,
sip_domain => $sub->domain->domain,
delivery_host => $resource->{x2_host},
delivery_port => $resource->{x2_port},
delivery_user => $resource->{x2_user},
delivery_password => $resource->{x2_password},
cc_required => $resource->{x3_required},
cc_delivery_host => $resource->{x3_host},
cc_delivery_port => $resource->{x3_port},
});
unless($res) {
$c->log->error("failed to update capture agents");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update capture agents");
last;
}
$guard->commit;
@ -173,6 +214,7 @@ sub DELETE :Allow {
my $guard = $c->model('DB')->txn_scope_guard;
{
my $item = $self->item_by_id($c, $id);
my $uuid = $item->uuid;
last unless $self->resource_exists($c, interception => $item);
$item->update({
deleted => 1,
@ -190,6 +232,12 @@ sub DELETE :Allow {
sip_domain => undef,
uuid => undef,
});
my $res = NGCP::Panel::Utils::Interception::request($c, 'DELETE', $uuid);
unless($res) {
$c->log->error("failed to update capture agents");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update capture agents");
last;
}
$guard->commit;

@ -129,29 +129,17 @@ sub update_item {
resource => $resource,
);
my $num_rs = $c->model('DB')->resultset('voip_numbers')->search(
\[ 'concat(cc,ac,sn) = ?', [ {} => $resource->{number} ]]
);
unless($num_rs->first) {
$c->log->error("invalid number '$$resource{number}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Number does not exist");
last;
}
$resource->{reseller_id} = $num_rs->first->reseller_id;
my $sub = $num_rs->first->subscriber;
unless($sub) {
$c->log->error("invalid number '$$resource{number}', not assigned to any subscriber");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Number is not active");
last;
}
my ($sub, $reseller) = $self->subres_from_number($c, $resource->{number});
return unless($sub && $reseller);
$resource->{reseller_id} = $reseller->id;
$resource->{sip_username} = $sub->username;
$resource->{sip_domain} = $sub->domain->domain;
if($resource->{x3_required} && (!defined $resource->{x3_host} || !defined $resource->{x3_port})) {
$c->log->error("Missing parameter 'x3_host' or 'x3_port' with 'x3_required' activated");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Missing parameter 'x3_host' or 'x3_port' with 'x3_required' activated");
last;
return;
}
$resource->{x3_host} = $resource->{x3_port} = undef unless($resource->{x3_required});
@ -163,5 +151,32 @@ sub update_item {
return $item;
}
sub subres_from_number {
my ($self, $c, $number) = @_;
my $num_rs = $c->model('DB')->resultset('voip_numbers')->search(
\[ 'concat(cc,ac,sn) = ?', [ {} => $number ]]
);
unless($num_rs->first) {
$c->log->error("invalid number '$number'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Number does not exist");
return;
}
my $sub = $num_rs->first->subscriber;
unless($sub) {
$c->log->error("invalid number '$number', not assigned to any subscriber");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Number is not active");
return;
}
my $res = $num_rs->first->reseller;
unless($res) {
$c->log->error("invalid number '$number', not assigned to any reseller");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Number is not active");
return;
}
return ($sub, $res);
}
1;
# vim: set tabstop=4 expandtab:

@ -0,0 +1,84 @@
package NGCP::Panel::Utils::Interception;
use Data::Dumper;
use LWP::UserAgent;
use TryCatch;
sub request {
my ($c, $method, $uuid, $data) = @_;
my $a = _init($c);
return unless($a);
return unless($method eq 'POST' || $method eq 'PUT' || $method eq 'DELETE');
my @agents = @{ $a->{ua} };
my @urls = @{ $a->{url} };
for(my $i = 0; $i < scalar(@agents); ++$i) {
my $ua = $agents[$i];
my $url = $urls[$i];
if($method eq 'PUT' or $method eq 'DELETE') {
return unless($uuid);
$url .= '/'.$uuid;
}
$c->log->debug("performing $method for interception at $url");
try {
_request($c, $ua, $url, $method, $data);
} catch($e) {
# skip errors
}
}
return 1;
}
sub _request {
my ($c, $ua, $url, $method, $data) = @_;
my $req = HTTP::Request->new($method => $url);
if($data) {
$req->content_type('application/json');
$req->content($jdata);
}
my $res = $ua->request($req);
if($res->is_success) {
return 1;
} else {
$c->log->error("Failed to do $method on $url: " . $res->status_line);
return;
}
}
sub _init {
my ($c) = @_;
my @ua = ();
my @url = ();
my @cfgs = ();
if(ref $c->config->{intercept}->{agent} eq 'HASH') {
push @cfgs, $c->config->{intercept}->{agent};
} elsif(ref $c->config->{intercept}->{agent} eq 'ARRAY') {
@cfgs = @{ $c->config->{intercept}->{agent} };
}
unless(@cfgs) {
$c->log->error("No intercept agents configured in ngcp_panel.conf, rejecting request");
return;
}
foreach my $cfg(@cfgs) {
my $agent = LWP::UserAgent->new();
$agent->agent("Sipwise NGCP X1/0.2");
$agent->timeout(2);
if($cfg->{user} && $cfg->{pass}) {
$agent->credentials(
$cfg->{host}.":".$cfg->{port},
$cfg->{realm},
$cfg->{user},
$cfg->{pass}
);
}
push @ua, $agent;
push @url, $cfg->{schema}.'://'.$cfg->{host}.':'.$cfg->{port}.$cfg->{url};
}
return { ua => \@ua, url => \@url };
}
1;
Loading…
Cancel
Save