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/tools_bin/ngcp-provisioning-template

444 lines
14 KiB

#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long qw(:config posix_default no_ignorecase);
use Pod::Usage qw(pod2usage);
use Config::General qw();
use File::Slurp qw();
use XML::Simple qw();
#use lib "/home/rkrenn/sipwise/git/ngcp-schema/lib";
#use lib "/home/rkrenn/sipwise/git/sipwise-base/lib";
#use lib "/usr/local/devel/ngcp-schema/lib";
#use lib "/usr/local/devel/sipwise-base/lib";
use NGCP::Schema qw();
#use lib "/home/rkrenn/sipwise/git/ngcp-panel/lib";
#use lib "/usr/local/devel/ngcp-panel/lib";
use NGCP::Panel::Utils::ProvisioningTemplates qw();
my @panel_configs = qw(
/etc/ngcp-panel/ngcp_panel.conf
/etc/ngcp_panel.conf
/ngcp_panel.conf
);
#/home/rkrenn/sipwise/git/vagrant-ngcp/ngcp_panel.conf
#/usr/local/devel/vagrant-ngcp/ngcp_panel.conf
my @provisioning_configs = qw(
/etc/ngcp-panel/provisioning.conf
);
#/etc/ngcp-panel/provisioning.conf
#/home/rkrenn/sipwise/git/vagrant-ngcp/provisioning.conf
#/usr/local/devel/vagrant-ngcp/provisioning.conf
my %db = (
host => undef, #'192.168.0.99'
port => 3306,
user => 'root',
password => undef,
);
my $template_name = shift @ARGV;
#my $template_name = 'My First Provisioning Template';
pod2usage(2) unless $template_name;
pod2usage(1) if $template_name =~ /help|\?/;
my $help;
my $log_level;
Getopt::Long::Configure("pass_through");
Getopt::Long::Configure("permute");
GetOptions(
( map { ('db_' . $_ . ':s') => \&parse_old_db_option } keys %db ),
( map { ('db-' . $_ . ':s') => \$db{$_}; } keys %db ),
'log_level:s' => \&parse_old_log_level_option,
'log-level:s' => \$log_level,
"help|?" => \$help,
) or pod2usage(2);
pod2usage(1) if $help;
my %mock_objs = ();
my $c = _create_c();
NGCP::Panel::Utils::ProvisioningTemplates::load_template_map($c);
if (exists $c->stash->{'provisioning_templates'}->{$template_name}) {
$c->stash->{'provisioning_template_name'} = $template_name;
my $fields = NGCP::Panel::Utils::ProvisioningTemplates::get_fields($c,0);
my $values = { map { $_ => undef; } grep { $_ ne 'purge'; } keys %$fields };
my $csv_file;
#my $csv_file = '/home/rkrenn/temp/provisioning_templates/CCS_ICM_Nummern.csv';
my $purge;
Getopt::Long::Configure("no_pass_through");
Getopt::Long::Configure("no_permute");
GetOptions(
( map { ($_ . ($fields->{$_}->{required} ? '=' : ':') . 's') => \$values->{$_}; } keys %$values ),
"purge" => \$purge,
"file:s" => \$csv_file,
) or pod2usage(2);
if ($csv_file) {
my $csv_data = File::Slurp::read_file($csv_file);
my ($linecount,$errors) = NGCP::Panel::Utils::ProvisioningTemplates::process_csv(
c => $c,
data => \$csv_data,
purge => $purge,
);
if (scalar @$errors) {
die("CSV file ($linecount lines) processed, " . scalar @$errors . " error(s)\n");
} else {
print("CSV file ($linecount lines) processed, 0 error(s)\n");
}
} else {
$values->{purge} = $purge;
eval {
my $context = NGCP::Panel::Utils::ProvisioningTemplates::provision_begin(
c => $c,
);
NGCP::Panel::Utils::ProvisioningTemplates::provision_commit_row(
c => $c,
context => $context,
'values' => $values,
#'values' => {
# first_name => 'John',
# last_name => 'Doe',
# cc => "43",
# ac => "316",
# sn => "1234567",
# purge => 1,
#}
#'values' => {
# service_number => '800010144',
# switch3_number => '19768988',
# company => "test12",
# purge => 1,
#}
);
NGCP::Panel::Utils::ProvisioningTemplates::provision_finish(
c => $c,
context => $context,
);
print ("Provisioning template '$template_name' done: subscriber " . $context->{subscriber}->{username} . '@' . $context->{domain}->{domain} . " created\n");
};
if ($@) {
die("Provisioning template '$template_name' failed: " . $@ . "\n");
}
}
} else {
die("Unknown provisioning template '$template_name'\n");
}
exit(0);
sub parse_old_db_option {
my ($name, $value) = @_;
my $newname = $name =~ tr/_/-/r;
$db{$name} = $value;
#warn "$0: option --$name is deprecated; use --$newname instead\n";
}
sub parse_old_log_level_option {
my ($name, $value) = @_;
my $newname = $name =~ tr/_/-/r;
$log_level = $value;
#warn "$0: option --$name is deprecated; use --$newname instead\n";
}
sub _create_c {
my $config = _get_panel_config();
{
no strict "refs"; ## no critic (ProhibitNoStrict)
*{'NGCP::Schema::set_transaction_isolation'} = sub {
my ($self,$level) = @_;
return $self->storage->dbh_do(
sub {
my ($storage, $dbh, @args) = @_;
$dbh->do("SET TRANSACTION ISOLATION LEVEL " . $args[0]);
},
$level,
);
};
*{'NGCP::Schema::set_wait_timeout'} = sub {
my ($self,$timeout) = @_;
return $self->storage->dbh_do(
sub {
my ($storage, $dbh, @args) = @_;
$dbh->do("SET SESSION wait_timeout = " . $args[0]);
},
$timeout,
);
};
}
my $db = _get_schema();
my $req = sub {
my $self = shift;
return _create_mock('_request',
_param => {
# '$c->request->params' => undef,
},
param => sub {
my $self = shift;
my $key = shift;
return $self->{param}->{$key} if $key;
return $self->{param};
},
path => sub {
my $self = shift;
return 'api/';
},
);
};
$c = _create_mock('c',
_stash => {
},
stash => sub {
my $self = shift;
my $key = shift;
return $self->{stash}->{$key} if $key;
return $self->{stash};
},
_model => {
DB => $db,
},
model => sub {
my $self = shift;
my $key = shift;
return $self->{model}->{$key} if $key;
return $self->{model};
},
log => sub {
my $self = shift;
return _create_mock('log',
debug => sub {
my $self = shift;
my $str = shift;
my @params = @_;
print $str . "\n" if ($log_level and grep { $_ eq lc($log_level); } qw(debug));
},
info => sub {
my $self = shift;
my $str = shift;
my @params = @_;
print $str . "\n" if ($log_level and grep { $_ eq lc($log_level); } qw(info debug));
},
warn => sub {
my $self = shift;
my $str = shift;
my @params = @_;
print $str . "\n" if ($log_level and grep { $_ eq lc($log_level); } qw(warn info debug));
},
error => sub {
my $self = shift;
my $str = shift;
my @params = @_;
print $str . "\n" if ($log_level and grep { $_ eq lc($log_level); } qw(error warn info debug));
},
);
},
config => sub {
my $self = shift;
return $config;
},
user => sub {
my $self = shift;
return _create_mock('user',
roles => sub {
my $self = shift;
return 'admin';
},
#webusername => sub {
# my $self = shift;
# return '$c->user->webusername';
#},
#domain => sub {
# my $self = shift;
# return _create_mock('_domain',
# domain => sub {
# my $self = shift;
# return '$c->user->domain->domain';
# },
# );
#},
);
},
request => $req,
req => $req,
);
}
sub _create_mock {
my $class = shift;
return $mock_objs{$class} if exists $mock_objs{$class};
my %members = @_;
my $obj = bless({},$class);
foreach my $member (keys %members) {
if ('CODE' eq ref $members{$member}) {
no strict "refs"; ## no critic (ProhibitNoStrict)
*{$class.'::'.$member} = $members{$member};
} else {
$obj->{substr($member,1)} = $members{$member};
}
}
$mock_objs{$class} = $obj;
return $obj;
}
sub _get_schema {
my $schema;
if ($db{host}) {
$schema = NGCP::Schema->connect({
dsn => "DBI:mysql:database=provisioning;host=$db{host};port=$db{port}",
user => $db{user},
( exists $db{password} ? (password => $db{password}) : ()),
mysql_enable_utf8 => "1",
on_connect_do => "SET NAMES utf8mb4",
quote_char => "`",
});
$schema->set_wait_timeout(3600);
return $schema;
} else {
foreach my $provisioning_config (@provisioning_configs) {
if (-f $provisioning_config) {
my $conf = XML::Simple->new->XMLin($provisioning_config, ForceArray => 1);
if ($conf && $conf->{ngcp_connect_info}) {
my $connectors;
if (exists $conf->{ngcp_connect_info}->[0]->{connectors}) {
$connectors = $conf->{ngcp_connect_info}->[0]->{connectors};
} else {
$connectors = $conf->{ngcp_connect_info};
}
$connectors //= [];
$schema = NGCP::Schema->connect($connectors->[0]);
$schema->set_wait_timeout(3600);
return $schema;
}
}
}
die("no provisioning.conf found\n") unless $schema;
}
}
sub _get_panel_config {
my $config;
foreach my $panel_config (@panel_configs) {
if( -f $panel_config ){
my $catalyst_config = Config::General->new($panel_config);
my %config = $catalyst_config->getall();
$config = \%config;
last;
}
}
die("no ngcp_panel.conf found\n") unless $config;
return $config;
}
__END__
=head1 NAME
ngcp-provisioning-template - Create subscribers with detailed settings according to provisioning templates
=head1 SYNOPSIS
For templates defined in config.yml file:
E<9>B<ngcp-provisioning-template> "I<provisioning-template-name>" [I<options>]
For templates defined in database:
E<9>B<ngcp-provisioning-template> "I<reseller-name>B</>I<provisioning-template-name>" [I<options>]
=head1 DESCRIPTION
This program allows to run a 'provisioning template' from database or config.yml. This will produce a
subscriber setup including required billing contact, contract, preferences, etc. from an input form defined
by that template. The form fields can be passed as command line options.
=head1 OPTIONS
=over 4
=item B<--help>
Print a brief help message and exits.
=item B<--db-host=>I<db-host-IP-address>
The host of the ngcp database to connect to. If omitted, the database connection settings of ngcp-panel will be used.
=item B<--db-port=>I<db-host-port>
The port of the ngcp database to connect to.
Only relevant if B<--db-host> is specified.
=item B<--db-user=>I<db-username>
The database user for the ngcp database to connect to.
Only relevant if B<--db-host> is specified.
=item B<--db-password=>I<db-password>
The database user password (if any) for the ngcp database to connect to.
Only relevant if B<--db-host> is specified.
=item B<--file=>I<csv-filename>
Specify a .csv file to process. Each row represents form values for one subscriber to create.
=item B<--[input-attribute-name]=>I<[attribute-value]>
Provide an input attribute name and its value, as defined within the 'fields' tag in the provisioning template (Attribute must not be internal, i.e. 'calculated' type). Only relevant if no --file is specified.
=item B<--purge>
Terminate an existing subscriber with duplicate number/aliases first.
=item B<--log-level>
Verbosity of printed messages while processing (debug, info, warn, error).
=back
=head1 EXAMPLES
ngcp-provisioning-template "My First Provisioning Template" --first-name="John" --last-name="Doe" --cc="43" --ac="316" --sn="123456" --purge
... runs "My First Provisioning Template" from config.yml using first_name "John", last_name "Doe" etc.
ngcp-provisioning-template "Reseller1/Provisioning Template 1" --file="subscriberdata.csv" --purge
... runs "Provisioning Template 1" of "Reseller1" for each row in "subscriberdata.csv"
=head1 AUTHOR
Sipwise Development Team C<< <support@sipwise.com> >>
=head1 LICENSE
This software is Copyright © 2020 by Sipwise GmbH, Austria.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this package. If not, see <https://www.gnu.org/licenses/>.
=cut