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/DialogicImg.pm

1653 lines
49 KiB

use strict;
use warnings;
{
package My::Serializer::Custom;
use Moo;
extends 'Role::REST::Client::Serializer';
sub _set_serializer {
my $s = Data::Serializer::Raw->new(
serializer => 'XML::Simple',
options => {
RootName => 'object',
# KeyAttr => { 'object' => '+classname' },
# ForceArray => ['IPProfile'],
} );
return $s;
}
has '+serializer' => ( default => \&_set_serializer, );
1;
}
{
package LWP_Wrapper;
use Moo;
use HTTP::Request;
use HTTP::Headers;
extends 'LWP::UserAgent';
around request => sub {
my ($next, $self, $method, $uri, $opts) = @_;
my @headers;
if ($opts->{headers}) {
@headers = HTTP::Headers->new(%{ $opts->{headers} });
}
my $req = HTTP::Request->new($method, $uri, @headers);
if ($opts->{content}) {
$req->content($opts->{content});
}
my $res = $self->$next($req);
return $res;
};
}
package NGCP::Panel::Utils::DialogicImg;
use Moo;
use Digest::MD5 qw/md5_hex/;
use HTTP::Tiny;
use Storable qw/freeze/;
use Types::Standard qw(Int HashRef);
with 'Role::REST::Client';
has '+type' => ( default => 'application/xml', is => 'rw' );
# has '+serializer_options' => (default => sub {
# my $s = Data::Serializer::Raw->new(
# serializer => 'XML::Simple',
# options => { RootName => 'object' } );
# return { serializer => $s };
# });
has '+serializer_class' =>
( is => 'rw', default => sub {'My::Serializer::Custom'} );
has '+clientattrs' => ( default => sub {
return {timeout => 5};
});
has 'appid' => ( is => 'rw', isa => Int, default => 0 );
has 'pids' => (
is => 'rw',
isa => HashRef,
default => sub {
return {
root => 10_000,
bn2020 => 10_001,
};
} );
has 'classinfo' => ( is => 'ro', isa => HashRef, default => sub{
return {
bn2020 => { # dummy, not used by _create_generic
name => 'Node',
parent => 'root',
revalidate => 0,
},
network => {
name => 'NetworkInterfaces',
parent => 'bn2020',
revalidate => 0,
},
interface_collection => {
name => 'NetworkLogicalInterfaces',
parent => 'network',
revalidate => 0,
},
interface => {
name => 'NetworkLogicalInterface',
parent => 'interface_collection',
revalidate => 0,
},
ip_address => {
name => 'NetworkInterface',
parent => 'interface',
revalidate => 1,
},
facility => {
name => 'Facility',
parent => 'bn2020',
revalidate => 0,
},
packet_facility_collection => {
name => 'PacketFacilities',
parent => 'facility',
revalidate => 0,
},
packet_facility => {
name => 'PacketFacility',
parent => 'packet_facility_collection',
revalidate => 0,
},
ds1_spans => {
name => 'SpanGroup',
parent => 'facility',
revalidate => 0,
},
ds3_optical => {
name => 'DS3_Optical',
parent => 'facility',
revalidate => 1,
},
optical_interface => {
name => 'Optical_Interface',
parent => 'ds3_optical',
revalidate => 0,
},
optical_link => {
name => 'Optical_Link',
parent => 'optical_interface',
revalidate => 0,
},
ds3_interface => {
name => 'TDM_DS3',
parent => 'optical_interface',
revalidate => 0,
},
ds1_spans_optical => {
name => 'SpanGroup', # TODO: double occurrence, is that acceptable?
parent => 'ds3_interface',
revalidate => 0,
},
signaling => {
name => 'Signaling',
parent => 'bn2020',
revalidate => 0,
},
isdn => {
name => 'ISDN',
parent => 'signaling',
revalidate => 0,
},
isdn_d_chan => {
name => 'ISDNDChan',
parent => 'isdn',
revalidate => 1,
},
isdn_group => {
name => 'ISDNGroup',
parent => 'isdn_d_chan',
revalidate => 0,
},
isdn_circuit_group => {
name => 'ISDNCircuitGroup',
parent => 'isdn_group',
revalidate => 1,
},
sip => {
name => 'SIP',
parent => 'signaling',
revalidate => 0,
},
sip_ip => {
name => 'SIPIP',
parent => 'sip',
revalidate => 0,
},
call_tracing => {
name => 'CallTracing',
parent => 'bn2020',
revalidate => 0,
},
snmp_agent => {
name => 'SNMPClient',
parent => 'bn2020',
revalidate => 0,
},
ss7 => {
name => 'SS7',
parent => 'root',
revalidate => 0,
},
ss7_network => {
name => 'SS7Network',
parent => 'ss7',
revalidate => 0,
},
ss7_node_collection => {
name => 'SS7Nodes',
parent => 'ss7_network',
revalidate => 0,
},
ss7_node_primary => {
name => 'SS7PrimaryNode',
parent => 'ss7_node_collection',
revalidate => 0,
},
ss7_stack => {
name => 'SS7Stack',
parent => 'ss7_network',
revalidate => 1,
},
ss7_link_set => {
name => 'SS7LinkSet',
parent => 'ss7_stack',
revalidate => 1,
},
ss7_link => {
name => 'SS7Link',
parent => 'ss7_link_set',
revalidate => 1,
},
ss7_destination => {
name => 'SS7Destination',
parent => 'ss7_stack',
revalidate => 1,
},
ss7_route => {
name => 'SS7Route',
parent => 'ss7_destination',
revalidate => 1,
},
ss7_isup_group => { # note: needs isup profile
name => 'ISUPGroup',
parent => 'ss7_destination',
revalidate => 1,
},
ss7_circuit_group => {
name => 'SS7CircuitGroup',
parent => 'ss7_isup_group',
revalidate => 1,
},
profile_collection => {
name => 'Profiles',
parent => 'root',
revalidate => 0,
},
ip_profile_collection => {
name => 'IPProfiles',
parent => 'profile_collection',
revalidate => 0,
},
ip_profile => {
name => 'IPProfile',
parent => 'ip_profile_collection',
revalidate => 1,
},
vocoder_profile => {
name => 'VocoderProfile',
parent => 'ip_profile',
revalidate => 1,
},
sip_profile_collection => {
name => 'SIPProfiles',
parent => 'profile_collection',
revalidate => 0,
},
sip_profile => {
name => 'SIPSGP',
parent => 'sip_profile_collection',
revalidate => 1,
},
sip_headers => {
name => 'SIPHeaders',
parent => 'sip_profile',
revalidate => 0,
},
tdm_profile_collection => {
name => 'TDMProfiles',
parent => 'profile_collection',
revalidate => 0,
},
e1_profile => {
name => 'E1Profile',
parent => 'tdm_profile_collection',
revalidate => 0,
},
isup_profile_collection => {
name => 'ISUPProfiles',
parent => 'profile_collection',
revalidate => 0,
},
isup_itu_profile => {
name => 'ISUP_ITUProfile',
parent => 'isup_profile_collection',
revalidate => 0,
},
isup_ansi_profile => {
name => 'ISUP_ANSIProfile',
parent => 'isup_profile_collection',
revalidate => 0,
},
external_network_elements => {
name => 'ExternalNetworkElements',
parent => 'root',
revalidate => 0,
},
external_gateway_collection => {
name => 'ExternalGateways',
parent => 'external_network_elements',
revalidate => 0,
},
external_gateway => {
name => 'ExternalGateway',
parent => 'external_gateway_collection',
revalidate => 1,
},
external_nfsserver_collection => {
name => 'NFSServers',
parent => 'external_network_elements',
revalidate => 0,
},
external_nfsserver => {
name => 'NFSServer',
parent => 'external_nfsserver_collection',
revalidate => 1,
},
external_snmpmanager_collection => {
name => 'SNMPServers',
parent => 'external_network_elements',
revalidate => 0,
},
external_snmpmanager => {
name => 'SNMPServer',
parent => 'external_snmpmanager_collection',
revalidate => 1,
},
routing_configuration => {
name => 'RoutingConfiguration',
parent => 'root',
revalidate => 0,
},
channel_group_collection => {
name => 'ChannelGroups',
parent => 'routing_configuration',
revalidate => 0,
},
channel_group => {
name => 'ChannelGroup',
parent => 'channel_group_collection',
revalidate => 1,
},
route_table_collection => {
name => 'RoutingTables',
parent => 'routing_configuration',
revalidate => 0,
},
route_table => {
name => 'RouteTable',
parent => 'route_table_collection',
revalidate => 1,
},
route_element => {
name => 'RouteElement',
parent => 'route_table',
revalidate => 1,
},
cg_network_element => {
name => 'NetworkElement',
parent => 'channel_group',
revalidate => 0,
},
node_association => {
name => 'NodeAssociation',
parent => 'cg_network_element',
revalidate => 0,
},
cg_isdn_circuit_group => {
name => 'SSLCircuitGroup',
parent => 'channel_group',
revalidate => 0,
},
};
});
# returns appid or 0
sub login {
my ( $self, $username, $password ) = @_;
my $resp = $self->post(
'/oamp/user_management/users/logged_in?appid=0',
{ user => { name => $username, password => $password } } );
if ( $resp->code == 200 ) {
my $data = $resp->data;
$self->appid( $data->{appid} );
return $self->appid;
}
return 0;
}
sub obtain_lock {
my ($self) = @_;
$self->set_header( 'Content-Length' => '0', );
my $resp = $self->delete(
'/oamp/user_management/locks?appid=' . $self->appid );
$resp = $self->post( '/oamp/user_management/locks?appid=' . $self->appid,
{} );
return $resp;
}
###### CREATE methods ######
sub create_bn2020 {
my ($self) = @_;
my $data = $self->objects->{bn2020};
my $resp = $self->post(
'/oamp/configuration/objects/Node/NULL?pid=10000&appid='
. $self->appid,
$data,
);
if ( $resp->code == 200 ) {
$self->pids->{bn2020} = $resp->data->{oid};
}
return $resp;
}
sub create_network {
my ($self) = @_;
return $self->_create_generic(undef, 'network');
}
sub create_interface_collection {
my ($self) = @_;
return $self->_create_generic(undef, 'interface_collection');
}
sub create_interface {
my ($self) = @_;
my $resp = $self->_create_generic(undef, 'interface');
if ( $resp->code == 200 ) {
if ( $resp->data->{property}{Interface}{value} eq "Control" ) {
$self->pids->{interface_control} = $resp->data->{oid};
} elsif ( $resp->data->{property}{Interface}{value} eq "Data A" ) {
$self->pids->{interface_dataa} = $resp->data->{oid};
}
}
return $resp;
}
sub create_ip_address {
my ( $self, $options ) = @_;
if ( defined $options->{NIIPAddress} && !defined $options->{NIIPGateway} )
{
$options->{NIIPGateway} = $options->{NIIPAddress} =~ s/\.[0-9]+$/.1/r;
}
return $self->_create_generic($options, 'ip_address');
}
sub create_facility {
my ($self) = @_;
return $self->_create_generic(undef, 'facility');
}
sub create_packet_facility_collection {
my ($self) = @_;
return $self->_create_generic(undef, 'packet_facility_collection');
}
sub create_packet_facility {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'packet_facility');
}
sub create_ds1_spans {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ds1_spans');
}
sub create_ds3_optical {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ds3_optical');
}
sub create_optical_interface {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'optical_interface');
}
sub create_optical_link {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'optical_link');
}
sub create_ds3_interface {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ds3_interface');
}
sub create_ds1_spans_optical {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ds1_spans_optical');
}
sub create_signaling {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'signaling');
}
sub create_isdn {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'isdn');
}
sub create_isdn_d_chan {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'isdn_d_chan');
}
sub create_isdn_group {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'isdn_group');
}
sub create_isdn_circuit_group {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'isdn_circuit_group');
}
sub create_sip {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'sip');
}
sub create_sip_ip {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'sip_ip');
}
sub create_call_tracing {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'call_tracing');
}
sub create_snmp_agent {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'snmp_agent');
}
sub create_ss7 {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7');
}
sub create_ss7_network {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7_network');
}
sub create_ss7_node_collection {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7_node_collection');
}
sub create_ss7_node_primary {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7_node_primary');
}
sub create_ss7_stack {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7_stack');
}
sub create_ss7_link_set {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7_link_set');
}
sub create_ss7_link {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7_link');
}
sub create_ss7_destination {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7_destination');
}
sub create_ss7_route {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7_route');
}
sub create_ss7_isup_group {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7_isup_group');
}
sub create_ss7_circuit_group {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ss7_circuit_group');
}
sub create_profile_collection {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'profile_collection');
}
sub create_ip_profile_collection {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ip_profile_collection');
}
sub create_ip_profile {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'ip_profile');
}
sub create_vocoder_profile {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'vocoder_profile');
}
sub create_sip_profile_collection {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'sip_profile_collection');
}
sub create_sip_profile {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'sip_profile');
}
sub create_sip_headers {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'sip_headers');
}
sub create_tdm_profile_collection {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'tdm_profile_collection');
}
sub create_e1_profile {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'e1_profile');
}
sub create_isup_profile_collection {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'isup_profile_collection');
}
sub create_isup_itu_profile {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'isup_itu_profile');
}
sub create_isup_ansi_profile {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'isup_ansi_profile');
}
sub create_external_network_elements {
my ( $self ) = @_;
return $self->_create_generic(undef, 'external_network_elements');
}
sub create_external_gateway_collection {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'external_gateway_collection');
}
sub create_external_gateway {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'external_gateway');
}
sub create_external_nfsserver_collection {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'external_nfsserver_collection');
}
sub create_external_nfsserver {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'external_nfsserver');
}
sub create_external_snmpmanager_collection {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'external_snmpmanager_collection');
}
sub create_external_snmpmanager {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'external_snmpmanager');
}
sub create_routing_configuration {
my ($self) = @_;
return $self->_create_generic(undef, 'routing_configuration');
}
sub create_channel_group_collection {
my ($self) = @_;
return $self->_create_generic(undef, 'channel_group_collection');
}
sub create_channel_group {
my ($self, $options) = @_;
return $self->_create_generic($options, 'channel_group');
}
sub create_route_table_collection {
my ($self, $options) = @_;
return $self->_create_generic($options, 'route_table_collection');
}
sub create_route_table {
my ($self, $options) = @_;
return $self->_create_generic($options, 'route_table');
}
sub create_route_element {
my ($self, $options) = @_;
return $self->_create_generic($options, 'route_element');
}
sub create_cg_network_element {
my ($self, $options) = @_;
return $self->_create_generic($options, 'cg_network_element');
}
sub create_node_association {
my ($self, $options) = @_;
return $self->_create_generic($options, 'node_association');
}
sub create_cg_isdn_circuit_group {
my ( $self, $options ) = @_;
return $self->_create_generic($options, 'cg_isdn_circuit_group');
}
sub _create_generic {
my ($self, $options, $class) = @_;
my $classinfo = $self->classinfo->{$class};
my $pid = $self->pids->{$classinfo->{parent}};
unless ($pid) {
warn "$class: no valid pid available\n";
return; # TODO wrong format
}
my $classname = $classinfo->{name};
my $appid = $self->appid;
my $resp = $self->get(
"/oamp/configuration/objects/$classname/NULL?detaillevel=4&pid=$pid&appid=$appid",
);
if ( $resp->code != 200 ) {
warn "$class: Failed to fetch resource\n";
return $resp;
}
if ($classinfo->{revalidate}) {
my $validation_data = $self->_build_validation_data( $resp->data, $pid, $options );
$resp = $self->get(
"/oamp/configuration/objects/$classname/NULL",
$validation_data,
);
if ( $resp->code != 200 ) {
warn "$class: Failed to fetch resource second time (revalidate)\n";
return $resp;
}
}
my $new_data = $self->_build_response_data( $resp->data, $pid, $options );
$resp = $self->post(
"/oamp/configuration/objects/$classname/NULL?pid=$pid&appid=$appid",
$new_data,
);
if ( $resp->code == 200 ) {
$self->pids->{$class} = $resp->data->{oid};
}
return $resp;
}
# log: 0: none, 1: short, 2: everything
# necessary keys: ip_sip, ip_rtp, ip_client, out_codecs
# optional: in_codecs, ip_sip_subnet, ip_rtp_subnet
# for nfs: ip_nfs_server, nfs_path
# for snmp: snmp_system_name, snmp_system_location, snmp_system_contact, snmp_community_name
# for snmp optional: ip_snmp_manager, snmp_version
# The management IP, the SIP IP and the RTP IP have to be in different subnets
sub create_general_part_schedule {
my ($self, $settings, $log) = @_;
$self->_create_indent;
my $in_codecs = ['G711 ulaw', 'G711 alaw', 'G729', 'AMR',
'AMR Bandwidth Efficient', 'AMR-WB', 'AMR-WB Bandwidth Efficient',
'Clear Channel', 'G723 5.3 Kbps', 'G723 6.3 Kbps', 'G722', 'iLBC 30ms',
'GSM-FR Static Payload Type', 'GSM-FR Dynamic Payload Type',
'G726-32/G721 Static Payload Type', 'G726-32/G721 Dynamic Payload Type',
'GSM-EFR'];
my $resp = $self->create_bn2020;
my @in_schedule = map {
{
name => 'vocoder_profile', options =>
{ PayloadType => $_ },
};
} @{ $settings->{in_codecs} // $in_codecs };
my @out_schedule = map {
{
name => 'vocoder_profile', options =>
{ PayloadType => $_ },
};
} @{ $settings->{out_codecs} };
my @nfs_schedule;
if (defined $settings->{ip_nfs_server} &&
defined $settings->{nfs_path}) {
@nfs_schedule = (
{name => 'external_nfsserver_collection', options => undef}, # needs external_network_elements
{name => 'external_nfsserver', options => {
Name => 'ngcp_nfs_server',
IPAddress => $settings->{ip_nfs_server},
}},
{name => 'call_tracing', options => {
TraceTime => '600',
MountDirectory => $settings->{nfs_path},
}},
);
}
my @snmp_schedule;
if (defined $settings->{snmp_system_name} &&
defined $settings->{snmp_system_location} &&
defined $settings->{snmp_system_contact} &&
defined $settings->{snmp_community_name}) {
@snmp_schedule = (
{name => 'external_snmpmanager_collection', options => undef},
{name => 'external_snmpmanager', options => {
UserName => 'ngcp',
CommunityName => $settings->{snmp_community_name},
ServerIPAddress => $settings->{ip_snmp_manager} // $settings->{ip_client},
defined $settings->{snmp_version} ? (ServerVersion => $settings->{snmp_version} ) : (),
}},
{name => 'snmp_agent', options => {
SystemName => $settings->{snmp_system_name},
SystemLoc => $settings->{snmp_system_location},
SystemContact => $settings->{snmp_system_contact},
}},
);
}
my $schedule = [
{name => 'network', options => undef},
{name => 'interface_collection', options => undef},
{name => 'interface', options => undef}, # Control
{name => 'interface', options => undef}, # Data A
{name => 'ip_address', options => {
NIIPAddress => $settings->{ip_sip},
NIIPPhy => 'Services',
NIIPSubnet => $settings->{ip_sip_subnet} || '24',
}},
{name => 'interface', options => undef}, # Data B
{name => 'ip_address', options => {
NIIPAddress => $settings->{ip_rtp},
NIIPPhy => 'Media 0',
NIIPSubnet => $settings->{ip_rtp_subnet} || '24',
}},
{name => 'facility', options => undef},
{name => 'packet_facility_collection', options => undef},
{name => 'packet_facility', options => {
ChannelCount => 50,
}},
{name => 'signaling', options => undef},
{name => 'sip', options => undef},
{name => 'sip_ip', options => {
IPAddress => $settings->{ip_sip},
}},
{name => 'profile_collection', options => undef},
{name => 'ip_profile_collection', options => undef},
{name => 'ip_profile', options => {
DigitRelay => 'DTMF Packetized',
Name => 'ngcp_in_profile',
}},
@in_schedule,
{name => 'ip_profile', options => {
DigitRelay => 'DTMF Packetized',
Name => 'ngcp_out_profile',
}},
@out_schedule,
{name => 'sip_profile_collection', options => undef},
{name => 'sip_profile', options => undef},
{name => 'sip_profile', options => {
ProfileName => 'SIP-profile-ngcp',
}},
{name => 'sip_headers', options => {
UnsupportedHeader => 'Enabled',
}},
#{run => 'download_profiles'},
{name => 'external_network_elements', options => undef},
{name => 'external_gateway_collection', options => undef},
{name => 'external_gateway', options => {
Name => 'Phone1',
IPAddress => $settings->{ip_client},
IPAddress4 => $settings->{ip_client},
SGP => 'ID: 1 - SIP-profile-ngcp',
SGPId => '1',
}},
@nfs_schedule,
@snmp_schedule,
];
return $schedule;
}
# log: 0: none, 1: short, 2: everything
# necessary keys: ip_sip, ip_rtp, ip_client, out_codecs, optional: in_codecs
sub create_all_sipsip {
my ($self, $settings, $log) = @_;
my $general_schedule = $self->create_general_part_schedule($settings, $log);
my $schedule = [
@{ $general_schedule },
{name => 'routing_configuration', options => undef},
{name => 'channel_group_collection', options => undef},
{name => 'route_table_collection', options => undef},
{name => 'route_table', options => {
Name => 'ngcp_route_table',
}},
{name => 'channel_group', options => {
SignalingType => 'SIP',
InRouteTable => 'ngcp_route_table - ID: 5',
InIPProfile => 'ngcp_in_profile',
InIPProfileId => '1',
OutIPProfile => 'ngcp_out_profile',
SupportA2F => 'True',
Name => 'cg_ngcp_sipclient',
}},
{name => 'cg_network_element', options => undef},
{name => 'node_association', options => undef},
{name => 'route_element', options => {
StringType => 'Channel Group',
InChannelGroup => 'cg_ngcp_sipclient',
RouteActionType => 'Channel Group',
RouteActionList => 'cg_ngcp_sipclient',
}},
#{run => 'download_route_table'},
#{run => 'download_channel_groups'},
];
$self->_run_schedule($schedule, $log);
$self->download_profiles;
$self->download_route_table;
$self->download_channel_groups;
return 0;
}
# log: 0: none, 1: short
# necessary keys: ip_sip, ip_rtp, ip_client, out_codecs, optional: in_codecs
# optional: use_optical_spans (bool), is_isdn_userside (bool)
sub create_all_sipisdn {
my ($self, $settings, $log) = @_;
my $general_schedule = $self->create_general_part_schedule($settings, $log);
my @ds1_spans;
if ($settings->{use_optical_spans}) {
@ds1_spans = (
{name => 'ds3_optical', options => {
FacilityType => 'Optical',
}},
{name => 'optical_interface', options => undef},
{name => 'optical_link', options => undef},
{name => 'ds3_interface', options => undef},
{name => 'ds1_spans_optical', options => undef},
);
} else {
@ds1_spans = (
{name => 'ds1_spans', options => {
EndingOffset => '3',
}},
);
}
my $resp;
my $schedule = [
@{ $general_schedule },
{name => 'isdn', options => undef},
{name => 'tdm_profile_collection', options => undef},
{name => 'e1_profile', options => undef},
@ds1_spans,
{name => 'isdn_d_chan', options => $settings->{is_isdn_userside} ?
{
BaseVariant => 'Euro-ISDN User Side',
BChanSelection => 'Linear Counter Clockwise',
} : undef,
},
{name => 'isdn_group', options => undef},
{name => 'isdn_circuit_group', options => {
EndChannel => 'Span ID: 0 CID: 30',
}},
{name => 'isdn_d_chan', options => $settings->{is_isdn_userside} ?
undef : {
BaseVariant => 'Euro-ISDN User Side',
BChanSelection => 'Linear Counter Clockwise',
},
},
{name => 'isdn_group', options => undef},
{name => 'isdn_circuit_group', options => {
EndChannel => 'Span ID: 1 CID: 30',
}},
#{run => 'download_profiles'},
{name => 'routing_configuration', options => undef},
{name => 'channel_group_collection', options => undef},
{name => 'route_table_collection', options => undef},
{name => 'route_table', options => {
Name => 'ngcp_route_table',
}},
{name => 'channel_group', options => {
SignalingType => 'SIP',
InRouteTable => 'ngcp_route_table - ID: 5',
InIPProfile => 'ngcp_in_profile',
InIPProfileId => '1',
OutIPProfile => 'ngcp_out_profile',
SupportA2F => 'True',
Name => 'cg_ngcp_sipclient',
}},
{name => 'cg_network_element', options => undef},
{name => 'node_association', options => undef},
{name => 'channel_group', options => {
SignalingType => 'ISDN',
InRouteTable => 'ngcp_route_table - ID: 5',
SupportA2F => 'True',
Name => 'cg_ngcp_isdn_1',
}},
{name => 'cg_isdn_circuit_group', options => undef},
{name => 'channel_group', options => {
SignalingType => 'ISDN',
InRouteTable => 'ngcp_route_table - ID: 5',
SupportA2F => 'True',
Name => 'cg_ngcp_isdn_2',
}},
{name => 'cg_isdn_circuit_group', options => undef},
{name => 'route_element', options => {
StringType => 'Channel Group',
InChannelGroup => 'cg_ngcp_sipclient',
RouteActionType => 'Channel Group',
RouteActionList => 'cg_ngcp_isdn_1',
}},
{name => 'route_element', options => {
StringType => 'Channel Group',
InChannelGroup => 'cg_ngcp_isdn_1',
RouteActionType => 'Channel Group',
RouteActionList => 'cg_ngcp_sipclient',
}},
{name => 'route_element', options => {
StringType => 'Channel Group',
InChannelGroup => 'cg_ngcp_isdn_2',
RouteActionType => 'Channel Group',
RouteActionList => 'cg_ngcp_sipclient',
}},
#{run => 'download_route_table'},
#{run => 'download_channel_groups'},
];
$self->_run_schedule($schedule, $log);
$self->download_profiles;
$self->download_route_table;
$self->download_channel_groups;
return 0;
}
# log: 0: none, 1: short
# necessary keys: ip_sip, ip_rtp, ip_client, out_codecs, ss7_opc, ss7_apc, ss7_dpc
# optionalkeys: in_codecs
# optional: use_optical_spans (bool)
sub create_all_sipss7 {
my ($self, $settings, $log) = @_;
my $general_schedule = $self->create_general_part_schedule($settings, $log);
my @ds1_spans;
if ($settings->{use_optical_spans}) {
@ds1_spans = (
{name => 'ds3_optical', options => {
FacilityType => 'Optical',
}},
{name => 'optical_interface', options => undef},
{name => 'optical_link', options => undef},
{name => 'ds3_interface', options => undef},
{name => 'ds1_spans_optical', options => undef},
);
} else {
@ds1_spans = (
{name => 'ds1_spans', options => {
EndingOffset => '3',
}},
);
}
my $schedule = [
@{ $general_schedule },
{name => 'tdm_profile_collection', options => undef},
{name => 'e1_profile', options => undef},
{name => 'isup_profile_collection', options => undef},
{name => 'isup_itu_profile', options => undef},
@ds1_spans,
#{run => 'download_profiles'},
{name => 'ss7', options => undef},
{name => 'ss7_network', options => undef},
{name => 'ss7_node_collection', options => undef},
{name => 'ss7_node_primary', options => undef},
{name => 'ss7_stack', options => {
OPC => $settings->{ss7_opc},
}},
{name => 'ss7_link_set', options => {
APC => $settings->{ss7_apc},
}},
{name => 'ss7_link', options => undef},
{name => 'ss7_destination', options => {
DPC => $settings->{ss7_dpc},
}},
{name => 'ss7_route', options => {
Linkset => 'SS7 Link Set APC: ' . $settings->{ss7_apc},
}},
{name => 'ss7_isup_group', options => undef},
{name => 'ss7_circuit_group', options => {
StartCIC => '1',
}},
{name => 'ss7_stack', options => { # for loopback purposes
OPC => $settings->{ss7_dpc},
}},
{name => 'ss7_link_set', options => {
APC => $settings->{ss7_opc},
}},
{name => 'ss7_link', options => undef},
{name => 'ss7_destination', options => {
DPC => $settings->{ss7_opc},
}},
{name => 'ss7_route', options => {
Linkset => 'SS7 Link Set APC: ' . $settings->{ss7_opc},
}},
{name => 'ss7_isup_group', options => undef},
{name => 'ss7_circuit_group', options => {
StartCIC => '1',
}},
{name => 'routing_configuration', options => undef},
{name => 'channel_group_collection', options => undef},
{name => 'route_table_collection', options => undef},
{name => 'route_table', options => {
Name => 'ngcp_route_table',
}},
{name => 'channel_group', options => {
SignalingType => 'SIP',
InRouteTable => 'ngcp_route_table - ID: 5',
InIPProfile => 'ngcp_in_profile',
InIPProfileId => '1',
OutIPProfile => 'ngcp_out_profile',
SupportA2F => 'True',
Name => 'cg_ngcp_sipclient',
}},
{name => 'cg_network_element', options => undef},
{name => 'node_association', options => undef},
{name => 'channel_group', options => {
SignalingType => 'SS7_ISUP',
InRouteTable => 'ngcp_route_table - ID: 5',
SupportA2F => 'True',
Name => 'cg_ngcp_ss7_1',
}},
{name => 'cg_isdn_circuit_group', options => undef},
{name => 'channel_group', options => {
SignalingType => 'SS7_ISUP',
InRouteTable => 'ngcp_route_table - ID: 5',
SupportA2F => 'True',
Name => 'cg_ngcp_ss7_2',
}},
{name => 'cg_isdn_circuit_group', options => undef},
{name => 'route_element', options => {
StringType => 'Channel Group',
InChannelGroup => 'cg_ngcp_sipclient',
RouteActionType => 'Channel Group',
RouteActionList => 'cg_ngcp_ss7_1',
}},
{name => 'route_element', options => {
StringType => 'Channel Group',
InChannelGroup => 'cg_ngcp_ss7_1',
RouteActionType => 'Channel Group',
RouteActionList => 'cg_ngcp_sipclient',
}},
{name => 'route_element', options => {
StringType => 'Channel Group',
InChannelGroup => 'cg_ngcp_ss7_2',
RouteActionType => 'Channel Group',
RouteActionList => 'cg_ngcp_sipclient',
}},
#{run => 'download_route_table'},
#{run => 'download_channel_groups'},
];
$self->_run_schedule($schedule, $log);
$self->download_profiles;
$self->download_route_table;
$self->download_channel_groups;
return 0;
}
###### OTHER STUFF ######
sub _run_schedule {
my ($self, $schedule, $log) = @_;
my $resp;
my $ntotal = $#{$schedule};
my $i = 0;
for my $elem (@{ $schedule }) {
if (exists $elem->{run}) {
my $command = $elem->{run};
$self->$command;
next;
}
my ($name, $options) = @{ $elem }{('name', 'options')};
my $fun = "create_$name";
$resp = $self->$fun($options);
# $resp = $self->_create_generic($options, $name);
if ($log) {
my $ind = " " x ($self->classinfo->{$name}{indent}*4);
my $percent = (100 * $i++) / $ntotal;
my $shortline = sprintf "%3d%% - %-37s: %d\n", $percent, "$ind$name", $resp->code;
if ('CODE' eq ref $log) {
&{ $log }($shortline, $resp);
} elsif ($log >= 1) {
print $shortline;
if ($resp->code != 200) {
use DDP; p $resp->data;
}
}
}
}
return 0;
}
sub hash_config {
my ($self, $config) = @_;
$Storable::canonical = 1;
return md5_hex(freeze $config);
}
sub get_config {
my ($self) = @_;
my $appid = $self->appid;
my $resp = $self->get("/oamp/configuration/objects?appid=$appid");
my $config = {};
if ($resp->code != 200) {
warn "failed to get objects\n";
return $resp;
}
my $classinfo = $self->classinfo;
my $rev_lookup = {};
@{$rev_lookup}{map {$_->{name}} values %{$classinfo}} = keys %{$classinfo};
my $root = $resp->data->{object}[0];
for my $ch (_get_all_children($root)) {
$self->_recursive_get($ch, $rev_lookup);
}
if ($classinfo->{ip_address}{configuredids}[0]) {
($config->{ip1}) = $self->_get_specifics(
'ip_address', $classinfo->{ip_address}{configuredids}[0], ['NIIPAddress']);
}
if ($classinfo->{ip_address}{configuredids}[1]) {
($config->{ip2}) = $self->_get_specifics(
'ip_address', $classinfo->{ip_address}{configuredids}[1], ['NIIPAddress']);
}
if ($classinfo->{external_gateway}{configuredids}[0]) {
($config->{ip_client}) = $self->_get_specifics(
'external_gateway', $classinfo->{external_gateway}{configuredids}[0], ['IPAddress']);
}
if (exists $classinfo->{vocoder_profile}{configuredids}) {
for my $id (@{ $classinfo->{vocoder_profile}{configuredids} }) {
push @{ $config->{in_codecs} }, $self->_get_specifics(
'vocoder_profile', $id, ['PayloadType']);
}
}
return $config;
}
sub _recursive_get {
my ($self, $node, $rev_lookup) = @_;
my $classname = $node->{classname};
my $oname = $rev_lookup->{$classname};
my $oid = $node->{oid};
my $appid = $self->appid;
for my $ch (_get_all_children($node)) {
$self->_recursive_get($ch, $rev_lookup);
}
if ($oname) {
$self->pids->{$oname} = $oid;
push @{ $self->classinfo->{$oname}{configuredids} }, $oid;
}
return;
}
sub _get_specifics {
my ($self, $class, $id, $keys) = @_;
my $appid = $self->appid;
my $classinfo = $self->classinfo->{$class};
my $classname = $classinfo->{name};
my @res;
my $resp = $self->get("/oamp/configuration/objects/$classname/$id?appid=$appid&detaillevel=4");
if ($resp->code != 200) {
warn "failed to get objects\n";
return ();
}
for my $key (@{ $keys }) {
push @res, $resp->data->{property}{$key}{value};
}
return @res;
}
sub _create_indent {
my ($self, @class) = @_;
my $classinfo = $self->classinfo;
@class = keys %{ $classinfo } unless @class;
for my $class (@class) {
next if (exists $classinfo->{$class}{indent});
my $parent = $classinfo->{$class}{parent};
if ($parent eq 'root') {
$classinfo->{$class}{indent} = 0;
} else {
$self->_create_indent($parent);
$classinfo->{$class}{indent} = $classinfo->{$parent}{indent} + 1;
}
}
return;
}
sub download_profiles {
my ($self) = @_;
my $appid = $self->appid;
my $pid = $self->pids->{profile_collection};
$self->set_header( 'Content-Length' => '0', );
my $resp = $self->put(
"/oamp/configuration/objects/Profiles/$pid/provisions/Cached?appid=$appid&sync_key=0",
);
return $resp;
}
sub download_route_table {
my ($self) = @_;
my $appid = $self->appid;
my $pid = $self->pids->{route_table};
$self->set_header( 'Content-Length' => '0', );
my $resp = $self->put(
"/oamp/configuration/objects/RouteTable/$pid/provisions/Cached?appid=$appid&sync_key=0",
);
return $resp;
}
sub download_channel_groups {
my ($self) = @_;
my $appid = $self->appid;
my $pid = $self->pids->{channel_group_collection};
$self->set_header( 'Content-Length' => '0', );
my $resp = $self->put(
"/oamp/configuration/objects/ChannelGroups/$pid/provisions/Cached?appid=$appid&sync_key=0",
);
return $resp;
}
#delete all children of bn2020 but not the node itself
sub delete_all_bn2020 {
my ($self) = @_;
my $appid = $self->appid;
my $resp = $self->get(
"/oamp/configuration/objects?appid=$appid",
);
if ($resp->code != 200) {
warn "failed to get objects\n";
return $resp;
}
my $root = $resp->data->{object}[0]; #bn2020
for my $ch (_get_all_children($root)) {
$self->_recursive_delete($ch);
}
return $resp;
}
sub _get_all_children {
my $node = shift;
if (defined $node->{object}) {
if ("HASH" eq ref $node->{object}) {
return ($node->{object},);
}
elsif ("ARRAY" eq ref $node->{object}) {
return @{ $node->{object} };
}
}
return ();
}
sub _recursive_delete {
my ($self, $node) = @_;
my $classname = $node->{classname};
my $oid = $node->{oid};
my $appid = $self->appid;
for my $ch (_get_all_children($node)) {
$self->_recursive_delete($ch);
}
return if $classname eq "Node"; # don't delete the bn2020 object (causes reboot)
my $path = "/oamp/configuration/objects/$classname/$oid?appid=$appid&sync_key=0";
$self->set_header( 'Content-Length' => '0', );
my $resp = $self->delete($path);
#use DDP; p $path; p $resp->code;
return;
}
sub reboot_and_wait {
my ($self) = @_;
my $appid = $self->appid;
$self->set_header( 'Content-Length' => '0', );
# my $resp = $self->delete("/oamp/configuration/database/new?appid=$appid",
# '<database name="boot.xml"/>');
my $resp = $self->_request_with_body("DELETE",
"/oamp/configuration/database/new?appid=$appid",
'<database name="boot.xml"/>');
if ($resp->code != 200) {
warn "failed to reset config\n";
return $resp;
}
sleep 2; # not to catch the old server
for (my $i = 0; $i < 30; $i++) { # 600 seconds on 20 seconds timeout
$resp = $self->get("/");
last if $resp->code < 400;
}
return $resp;
}
# warning: does create a lot of open transactions without deleting them.
# see the scriptfile for an example how to generate documentation of this
sub build_documentation {
my ($self) = @_;
my $classinfo = $self->classinfo;
for my $class (keys %{ $classinfo }) {
my $classname = $classinfo->{$class}{name};
my $appid = $self->appid;
my $pid = 10_000;
my $resp = $self->get(
"/oamp/configuration/objects/$classname/NULL?detaillevel=4&pid=$pid&appid=$appid",
);
if ($resp->code != 200) {
warn "$class: couldn't fetch info\n";
next;
}
my $data = $resp->data;
my $options = [];
for my $p ( keys %{ $data->{property} } ) {
next if lc($data->{property}{$p}{type}) ne "configure";
my @choices;
if ($data->{property}{$p}{choiceset}{choice} &&
ref $data->{property}{$p}{choiceset}{choice} eq "ARRAY") {
for my $v (@{ $data->{property}{$p}{choiceset}{choice} }) {
push @choices, $v->{value} =~ s/^value\((.*)\)$/$1/r;
}
}
push @{ $options }, {
name => $p,
default => $data->{property}{$p}{value},
displayname => $data->{property}{$p}{displayname},
@choices ? (choices => [@choices]) : (),
};
}
$classinfo->{$class}{options} = $options;
}
return $classinfo;
}
sub _build_response_data {
my ( $self, $req, $pid, $options ) = @_;
my $resp = {
pid => $pid,
property => {},
};
for my $p ( keys %{ $req->{property} } ) {
next
if lc($req->{property}{$p}{type}) ne "configure";
$resp->{property}{$p}
= { configuredvalue => $req->{property}{$p}{value} };
if ( defined $options->{$p} ) {
$resp->{property}{$p}{configuredvalue} = $options->{$p};
}
}
return $resp;
}
sub _build_validation_data {
my ( $self, $req, $pid, $options ) = @_;
my $response_data = $self->_build_response_data($req, $pid, $options);
my @changedopt = ();
if ("HASH" eq ref $options && keys %{ $options }) {
@changedopt = (
changedproperty => (keys %{ $options })[0],
);
}
my $resp = {
pid => $pid,
appid => $self->appid,
@changedopt,
};
for my $prop (keys %{ $response_data->{property} }) {
$resp->{$prop} = $response_data->{property}{$prop}{configuredvalue};
}
return $resp;
}
sub _build_user_agent {
my $ua = LWP_Wrapper->new(
ssl_opts => { verify_hostname => 0 },
timeout => 20,
);
return $ua;
}
sub objects {
return {
bn2020 => {
'property' => {
'IPType' => { 'configuredvalue' => 'IPv4' },
'_position_' => { 'configuredvalue' => '' },
'_localDbSyncKey_' => { 'configuredvalue' => '0' },
'PacketAudioChannels' => { 'configuredvalue' => 'Unknown' },
'CFCMode' => { 'configuredvalue' => 'Unknown' },
'srtpEnable' => { 'configuredvalue' => 'Disabled' },
'InterfaceType' => { 'configuredvalue' => 'Unknown' },
'MediaMode' => { 'configuredvalue' => 'Audio Dynamic Density Management' },
'SwVersion' => { 'configuredvalue' => 'Unknown' },
'SubNetMask' => { 'configuredvalue' => '' },
'Name' => { 'configuredvalue' => 'Node0' },
'ResendLogic' => { 'configuredvalue' => 'Disable' },
'PacketMultimediaChannels' =>
{ 'configuredvalue' => 'Unknown' },
'NetworkMultimediaChannels' =>
{ 'configuredvalue' => 'Unknown' },
'IPAddress' => { 'configuredvalue' => '' },
'ACLName' => { 'configuredvalue' => 'Unrestricted' },
'NodeType' => { 'configuredvalue' => 'Unknown' },
'ACL_ID' => { 'configuredvalue' => '0' },
'IPChannels' => { 'configuredvalue' => 'Unknown' },
'ID' => { 'configuredvalue' => '0' },
'_objectName_' =>
{ 'configuredvalue' => 'BN2020: Node0 - ID: 0' },
'LicIPChannels' => { 'configuredvalue' => '0' },
},
'pid' => '10000',
},
};
}
1;
# vim: set tabstop=4 expandtab: