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.
bulk-processor/lib/NGCP/BulkProcessor/Projects/Migration/Teletek/Provisioning.pm

1447 lines
63 KiB

package NGCP::BulkProcessor::Projects::Migration::Teletek::Provisioning;
use strict;
## no critic
use threads::shared qw();
use String::MkPasswd qw();
#use List::Util qw();
use JSON qw();
use Tie::IxHash;
use NGCP::BulkProcessor::Projects::Migration::Teletek::Settings qw(
$dry
$skip_errors
$report_filename
$provision_subscriber_multithreading
$provision_subscriber_numofthreads
$webpassword_length
$webusername_length
$sippassword_length
$default_channels_map
$reseller_mapping
$barring_profiles
$cf_default_priority
$cf_default_timeout
$cft_default_ringtimeout
);
use NGCP::BulkProcessor::Logging qw (
getlogger
processing_info
processing_debug
);
use NGCP::BulkProcessor::LogError qw(
rowprocessingerror
rowprocessingwarn
fileerror
);
use NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Subscriber qw();
use NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::AllowedCli qw();
use NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Clir qw();
use NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::CallForward qw();
use NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Registration qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::billing_profiles qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::products qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::contacts qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::contracts qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::billing_mappings qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::contract_balances qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::domains qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::resellers qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::voip_subscribers qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::voip_numbers qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::domain_resellers qw();
use NGCP::BulkProcessor::Dao::Trunk::billing::ncos_levels qw();
use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_domains qw();
use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases qw();
use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_subscribers qw();
use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences qw();
use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_usr_preferences qw();
use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings qw();
use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destination_sets qw();
use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destinations qw();
use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_trusted_sources qw();
use NGCP::BulkProcessor::Dao::Trunk::kamailio::voicemail_users qw();
use NGCP::BulkProcessor::Dao::Trunk::kamailio::location qw();
use NGCP::BulkProcessor::RestRequests::Trunk::Subscribers qw();
use NGCP::BulkProcessor::RestRequests::Trunk::Customers qw();
use NGCP::BulkProcessor::Projects::Migration::Teletek::Preferences qw(
set_subscriber_preference
get_subscriber_preference
clear_subscriber_preferences
delete_subscriber_preference
set_allowed_ips_preferences
cleanup_aig_sequence_ids
);
use NGCP::BulkProcessor::ConnectorPool qw(
get_xa_db
);
use NGCP::BulkProcessor::Projects::Migration::Teletek::ProjectConnectorPool qw(
destroy_all_dbs
ping_all_dbs
);
use NGCP::BulkProcessor::Utils qw(create_uuid threadid timestamp stringtobool check_ipnet trim);
use NGCP::BulkProcessor::DSSorter qw(sort_by_configs);
use NGCP::BulkProcessor::RandomString qw(createtmpstring);
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(
provision_subscribers
);
my $split_ipnets_pattern = join('|',(
quotemeta(','),
quotemeta(';'),
#quotemeta('/')
));
my $cf_types_pattern = '^' . $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::CFB_TYPE . '|'
. $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::CFT_TYPE . '|'
. $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::CFU_TYPE . '|'
. $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::CFNA_TYPE . '$';
my $db_lock :shared = undef;
my $file_lock :shared = undef;
my $default_barring = 'default';
my $contact_hash_field = 'gpp9';
sub provision_subscribers {
my $static_context = { now => timestamp(), _rowcount => undef };
my $result = _provision_subscribers_checks($static_context);
destroy_all_dbs();
my $warning_count :shared = 0;
my %nonunique_contacts :shared = ();
return ($result && NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Subscriber::process_records(
static_context => $static_context,
process_code => sub {
my ($context,$records,$row_offset) = @_;
ping_all_dbs();
$context->{_rowcount} = $row_offset;
my @report_data = ();
foreach my $domain_sipusername (@$records) {
$context->{_rowcount} += 1;
next unless _provision_susbcriber($context,
NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Subscriber::findby_domain_sipusername(@$domain_sipusername));
push(@report_data,_get_report_obj($context));
}
cleanup_aig_sequence_ids($context);
if (defined $report_filename) {
lock $file_lock;
open(my $fh, '>>', $report_filename) or fileerror('cannot open file ' . $report_filename . ': ' . $!,getlogger(__PACKAGE__));
binmode($fh);
print $fh JSON::to_json(\@report_data,{ allow_nonref => 1, allow_blessed => 1, convert_blessed => 1, pretty => 1, });
close $fh;
}
return 1;
},
init_process_context_code => sub {
my ($context)= @_;
$context->{db} = &get_xa_db();
$context->{error_count} = 0;
$context->{warning_count} = 0;
$context->{nonunique_contacts} = {};
# below is not mandatory..
#_check_insert_tables();
},
uninit_process_context_code => sub {
my ($context)= @_;
undef $context->{db};
destroy_all_dbs();
{
lock $warning_count;
$warning_count += $context->{warning_count};
}
{
lock %nonunique_contacts;
foreach my $sip_username (keys %{$context->{nonunique_contacts}}) {
$nonunique_contacts{$sip_username} = $context->{nonunique_contacts}->{$sip_username};
}
}
},
load_recursive => 0,
multithreading => $provision_subscriber_multithreading,
numofthreads => $provision_subscriber_numofthreads,
),$warning_count,\%nonunique_contacts);
}
sub _get_report_obj {
my ($context) = @_;
my %dump = ();
tie(%dump, 'Tie::IxHash');
foreach my $key (sort keys %$context) {
$dump{$key} = $context->{$key} if 'CODE' ne ref $context->{$key};
}
foreach my $key (qw/
sip_account_product
reseller
billing_profile
reseller_map
domain_map
domain
now
error_count
warning_count
attributes
ncos_level_map
ncos_level
nonunique_contacts
tid
db
blocksize
errorstates
queue
readertid
/) {
delete $dump{$key};
}
return \%dump;
}
sub _provision_susbcriber {
my ($context,$subscriber_group) = @_;
return 0 unless _provision_susbcriber_init_context($context,$subscriber_group);
eval {
lock $db_lock;
$context->{db}->db_begin();
#_warn($context,'AutoCommit is on') if $context->{db}->{drh}->{AutoCommit};
my $existing_billing_voip_subscribers = NGCP::BulkProcessor::Dao::Trunk::billing::voip_subscribers::findby_domainid_username_states(
$context->{db},
$context->{domain}->{id},
$context->{prov_subscriber}->{username},
{ 'NOT IN' => $NGCP::BulkProcessor::Dao::Trunk::billing::voip_subscribers::TERMINATED_STATE}
);
if ((scalar @$existing_billing_voip_subscribers) == 0) {
_update_contact($context);
_update_contract($context);
#{
# lock $db_lock; #concurrent writes to voip_numbers causes deadlocks
_update_subscriber($context);
_create_aliases($context);
#}
_update_preferences($context);
_set_registrations($context);
_set_callforwards($context);
#todo: additional prefs, AllowedIPs, NCOS, Callforwards. still thinking wether to integrate it
#in this main provisioning loop, or align it in separate run-modes, according to the files given.
} else {
_warn($context,(scalar @$existing_billing_voip_subscribers) . ' existing billing subscribers found, skipping');
}
if ($dry) {
$context->{db}->db_rollback(0);
} else {
$context->{db}->db_commit();
}
};
my $err = $@;
if ($err) {
eval {
$context->{db}->db_rollback(1);
};
if ($skip_errors) {
_warn($context, $err);
} else {
_error($context, $err);
}
}
return 1;
}
sub _provision_subscribers_checks {
my ($context) = @_;
my $result = 1;
my $subscribercount = 0;
eval {
$subscribercount = NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Subscriber::countby_ccacsn();
};
if ($@ or $subscribercount == 0) {
rowprocessingerror(threadid(),'please import subscribers first',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"$subscribercount subscriber found",getlogger(__PACKAGE__));
}
my $allowedclicount = 0;
eval {
$allowedclicount = NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::AllowedCli::countby_ccacsn();
};
if ($@ or $allowedclicount == 0) {
rowprocessingerror(threadid(),'please import allowed clis first',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"$allowedclicount allowed clis found",getlogger(__PACKAGE__));
}
my $clircount = 0;
eval {
$clircount = NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Clir::countby_clir();
};
if ($@ or $clircount == 0) {
rowprocessingerror(threadid(),'please import clir first',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"$clircount clir records found",getlogger(__PACKAGE__));
}
my $domain_billingprofilename_resellernames = [];
eval {
$domain_billingprofilename_resellernames = NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Subscriber::list_domain_billingprofilename_resellernames();
};
if ($@ or (scalar @$domain_billingprofilename_resellernames) == 0) {
rowprocessingerror(threadid(),"no domains/billing profile names/reseller names",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
$context->{domain_map} = {};
$context->{reseller_map} = {};
foreach my $domain_billingprofilename_resellername (@$domain_billingprofilename_resellernames) {
my $domain = $domain_billingprofilename_resellername->{domain};
unless ($domain) {
rowprocessingerror(threadid(),"empty domain detected",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
}
my $billingprofilename = $domain_billingprofilename_resellername->{billing_profile_name};
unless ($billingprofilename) {
rowprocessingerror(threadid(),"empty billing profile name detected",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
}
my $resellername = _apply_reseller_mapping($domain_billingprofilename_resellername->{reseller_name});
unless ($resellername) {
rowprocessingerror(threadid(),"empty reseller name detected",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
}
if (not exists $context->{reseller_map}->{$resellername}) {
eval {
$context->{reseller_map}->{$resellername} = NGCP::BulkProcessor::Dao::Trunk::billing::resellers::findby_name($resellername);
};
if ($@ or not $context->{reseller_map}->{$resellername}) {
rowprocessingerror(threadid(),"cannot find reseller '$resellername'",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
$context->{reseller_map}->{$resellername}->{billingprofile_map} = {};
processing_info(threadid(),"reseller '$resellername' found",getlogger(__PACKAGE__));
}
}
if (not exists $context->{domain_map}->{$domain}) {
eval {
$context->{domain_map}->{$domain} = NGCP::BulkProcessor::Dao::Trunk::billing::domains::findby_domain($domain);
};
if ($@ or not $context->{domain_map}->{$domain}) {
rowprocessingerror(threadid(),"cannot find billing domain '$domain'",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"billing domain '$domain' found",getlogger(__PACKAGE__));
eval {
$context->{domain_map}->{$domain}->{prov_domain} =
NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_domains::findby_domain($domain);
};
if ($@ or not $context->{domain_map}->{$domain}->{prov_domain}) {
rowprocessingerror(threadid(),"cannot find provisioning domain '$domain'",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"provisioning domain '$domain' found",getlogger(__PACKAGE__));
}
}
}
my $domain_reseller;
eval {
$domain_reseller = NGCP::BulkProcessor::Dao::Trunk::billing::domain_resellers::findby_domainid_resellerid(
$context->{domain_map}->{$domain}->{id},
$context->{reseller_map}->{$resellername}->{id})->[0];
};
if ($@ or not $domain_reseller) {
rowprocessingerror(threadid(),"domain $domain does not belong to reseller $resellername",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"domain $domain belongs to reseller $resellername",getlogger(__PACKAGE__));
}
if ($context->{reseller_map}->{$resellername}->{billingprofile_map} and
not exists $context->{reseller_map}->{$resellername}->{billingprofile_map}->{$billingprofilename}) {
eval {
$context->{reseller_map}->{$resellername}->{billingprofile_map}->{$billingprofilename} =
NGCP::BulkProcessor::Dao::Trunk::billing::billing_profiles::findby_resellerid_name_handle(
$context->{reseller_map}->{$resellername}->{id},
$billingprofilename,
)->[0];
};
if ($@ or not $context->{reseller_map}->{$resellername}->{billingprofile_map}->{$billingprofilename}) {
rowprocessingerror(threadid(),"cannot find billing profile '$billingprofilename' of reseller '$resellername'",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"billing profile '$billingprofilename' of reseller '$resellername' found",getlogger(__PACKAGE__));
}
}
}
}
eval {
$context->{sip_account_product} = NGCP::BulkProcessor::Dao::Trunk::billing::products::findby_resellerid_handle(undef,
$NGCP::BulkProcessor::Dao::Trunk::billing::products::SIP_ACCOUNT_HANDLE)->[0];
};
if ($@ or not defined $context->{sip_account_product}) {
rowprocessingerror(threadid(),"cannot find $NGCP::BulkProcessor::Dao::Trunk::billing::products::SIP_ACCOUNT_HANDLE product",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"$NGCP::BulkProcessor::Dao::Trunk::billing::products::SIP_ACCOUNT_HANDLE product found",getlogger(__PACKAGE__));
}
$context->{attributes} = {};
eval {
$context->{attributes}->{allowed_clis} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute(
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::ALLOWED_CLIS_ATTRIBUTE);
};
if ($@ or not defined $context->{attributes}->{allowed_clis}) {
rowprocessingerror(threadid(),'cannot find allowed_clis attribute',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"allowed_clis attribute found",getlogger(__PACKAGE__));
}
eval {
$context->{attributes}->{cli} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute(
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::CLI_ATTRIBUTE);
};
if ($@ or not defined $context->{attributes}->{cli}) {
rowprocessingerror(threadid(),'cannot find cli attribute',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"cli attribute found",getlogger(__PACKAGE__));
}
eval {
$context->{attributes}->{ac} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute(
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::AC_ATTRIBUTE);
};
if ($@ or not defined $context->{attributes}->{ac}) {
rowprocessingerror(threadid(),'cannot find ac attribute',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"ac attribute found",getlogger(__PACKAGE__));
}
eval {
$context->{attributes}->{cc} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute(
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::CC_ATTRIBUTE);
};
if ($@ or not defined $context->{attributes}->{cc}) {
rowprocessingerror(threadid(),'cannot find cc attribute',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"cc attribute found",getlogger(__PACKAGE__));
}
eval {
$context->{attributes}->{account_id} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute(
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::ACCOUNT_ID_ATTRIBUTE);
};
if ($@ or not defined $context->{attributes}->{account_id}) {
rowprocessingerror(threadid(),'cannot find account_id attribute',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"account_id attribute found",getlogger(__PACKAGE__));
}
eval {
$context->{attributes}->{concurrent_max_total} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute(
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::CONCURRENT_MAX_TOTAL_ATTRIBUTE);
};
if ($@ or not defined $context->{attributes}->{concurrent_max_total}) {
rowprocessingerror(threadid(),'cannot find concurrent_max_total attribute',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"concurrent_max_total attribute found",getlogger(__PACKAGE__));
}
eval {
$context->{attributes}->{clir} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute(
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::CLIR_ATTRIBUTE);
};
if ($@ or not defined $context->{attributes}->{clir}) {
rowprocessingerror(threadid(),'cannot find clir attribute',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"clir attribute found",getlogger(__PACKAGE__));
}
eval {
$context->{attributes}->{allowed_ips_grp} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute(
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::ALLOWED_IPS_GRP_ATTRIBUTE);
};
if ($@ or not defined $context->{attributes}->{allowed_ips_grp}) {
rowprocessingerror(threadid(),'cannot find allowed_ips_grp attribute',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"allowed_ips_grp attribute found",getlogger(__PACKAGE__));
}
my $barring_resellernames = [];
eval {
$barring_resellernames = NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Subscriber::list_barring_resellernames();
};
if ($@) {
rowprocessingerror(threadid(),'error retrieving barrings',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
$context->{ncos_level_map} = {};
foreach my $barring_resellername (@$barring_resellernames) {
my $resellername = _apply_reseller_mapping($barring_resellername->{reseller_name});
#unless ($resellername) {
# rowprocessingerror(threadid(),"empty reseller name detected",getlogger(__PACKAGE__));
# $result = 0; #even in skip-error mode..
#}
my $barring = $barring_resellername->{barrings};
$barring = $default_barring unless ($barring);
$result &= _check_ncos_level($context,$resellername,$barring);
}
}
eval {
$context->{attributes}->{adm_ncos_id} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute(
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::ADM_NCOS_ID_ATTRIBUTE);
};
if ($@ or not defined $context->{attributes}->{adm_ncos_id}) {
rowprocessingerror(threadid(),'cannot find adm_ncos_id attribute',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"adm_ncos_id attribute found",getlogger(__PACKAGE__));
}
foreach my $cf_attribute (@NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::CF_ATTRIBUTES) {
eval {
$context->{attributes}->{$cf_attribute} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute($cf_attribute);
};
if ($@ or not defined $context->{attributes}->{$cf_attribute}) {
rowprocessingerror(threadid(),"cannot find $cf_attribute attribute",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"$cf_attribute attribute found",getlogger(__PACKAGE__));
}
}
eval {
$context->{attributes}->{ringtimeout} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute(
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::RINGTIMEOUT_ATTRIBUTE);
};
if ($@ or not defined $context->{attributes}->{ringtimeout}) {
rowprocessingerror(threadid(),'cannot find ringtimeout attribute',getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
processing_info(threadid(),"ringtimeout attribute found",getlogger(__PACKAGE__));
}
return $result;
}
sub _check_ncos_level {
my ($context,$resellername,$barring) = @_;
my $result = 1;
if ($barring ne $default_barring and not exists $barring_profiles->{$resellername}) {
rowprocessingerror(threadid(),"barring mappings for reseller $resellername missing",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} elsif ($barring ne $default_barring and not exists $barring_profiles->{$resellername}->{$barring}) {
rowprocessingerror(threadid(),"mappings for barring '" . $barring . "' of reseller $resellername missing",getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
my $reseller_id = $context->{reseller_map}->{$resellername}->{id};
$context->{ncos_level_map}->{$reseller_id} = {} unless exists $context->{ncos_level_map}->{$reseller_id};
my $level = $barring_profiles->{$resellername}->{$barring};
unless (exists $context->{ncos_level_map}->{$reseller_id}->{$barring}) {
if (not defined $level or length($level) == 0) {
$context->{ncos_level_map}->{$reseller_id}->{$barring} = undef;
} else {
eval {
$context->{ncos_level_map}->{$reseller_id}->{$barring} = NGCP::BulkProcessor::Dao::Trunk::billing::ncos_levels::findby_resellerid_level(
$reseller_id,$level);
};
if ($@ or not defined $context->{ncos_level_map}->{$reseller_id}->{$barring}) {
my $err = "cannot find ncos level '$level' of reseller $resellername";
if (not defined $context->{_rowcount}) {
if ($barring ne $default_barring) {
rowprocessingerror(threadid(),$err,getlogger(__PACKAGE__));
$result = 0; #even in skip-error mode..
} else {
rowprocessingwarn(threadid(),$err,getlogger(__PACKAGE__));
}
} elsif ($skip_errors) {
_warn($context, $err);
} else {
_error($context, $err);
$result = 0; #even in skip-error mode..
}
} else {
processing_info(threadid(),"ncos level '$level' of reseller $resellername found",getlogger(__PACKAGE__));
}
}
}
}
return $result;
}
sub _update_contact {
my ($context) = @_;
my $existing_contacts = NGCP::BulkProcessor::Dao::Trunk::billing::contacts::findby_reselleridfields(
$context->{reseller}->{id},
{ $contact_hash_field => $context->{contract}->{contact}->{$contact_hash_field} },
);
if ((scalar @$existing_contacts) == 0) {
$context->{contract}->{contact}->{id} = NGCP::BulkProcessor::Dao::Trunk::billing::contacts::insert_row($context->{db},
$context->{contract}->{contact},
);
$context->{contract}->{contact_id} = $context->{contract}->{contact}->{id};
_info($context,"contact id $context->{contract}->{contact}->{id} created",1);
} else {
my $existing_contact = $existing_contacts->[0];
if ((scalar @$existing_contacts) > 1) {
_warn($context,(scalar @$existing_contacts) . " existing contacts found, using first contact id $existing_contact->{id}");
} else {
_info($context,"existing contact id $existing_contact->{id} found",1);
}
$context->{contract}->{contact}->{id} = $existing_contact->{id};
$context->{contract}->{contact_id} = $context->{contract}->{contact}->{id};
my $existing_contracts = NGCP::BulkProcessor::Dao::Trunk::billing::contracts::findby_contactid($existing_contact->{id});
if ((scalar @$existing_contracts) > 0) {
my $existing_contract = $existing_contracts->[0];
if ((scalar @$existing_contracts) > 1) {
_warn($context,(scalar @$existing_contracts) . " existing contracts found, using first contact id $existing_contract->{id}");
} else {
_info($context,"existing contract id $existing_contact->{id} found",1);
}
$context->{contract}->{id} = $existing_contract->{id};
$context->{bill_subscriber}->{contract_id} = $context->{contract}->{id};
$context->{prov_subscriber}->{account_id} = $context->{contract}->{id};
} else {
_warn($context,"no existing contract of contact id $existing_contact->{id} found, will be created");
}
}
$context->{contract}->{contact_id} = $context->{contract}->{contact}->{id};
#if ($context->{contract}->{contact_id}) {
# #NGCP::BulkProcessor::Dao::Trunk::billing::contacts::update_row($context->{db},
# # { @{ $context->{contract}->{contact} }, id => $context->{contract}->{contact_id}, }
# #);
#} else {
# $context->{contract}->{contact}->{id} = NGCP::BulkProcessor::Dao::Trunk::billing::contacts::insert_row($context->{db},
# $context->{contract}->{contact},
# );
# $context->{contract}->{contact_id} = $context->{contract}->{contact}->{id};
# _info($context,"contact id $context->{contract}->{contact}->{id} created",1);
#}
return 1;
}
sub _update_contract {
my ($context) = @_;
if ($context->{bill_subscriber}->{contract_id}) {
#todo: the update case
} else {
#the insert case
$context->{contract}->{id} = NGCP::BulkProcessor::Dao::Trunk::billing::contracts::insert_row($context->{db},
$context->{contract}
);
$context->{bill_subscriber}->{contract_id} = $context->{contract}->{id};
$context->{prov_subscriber}->{account_id} = $context->{contract}->{id};
$context->{contract}->{billing_mapping_id} = NGCP::BulkProcessor::Dao::Trunk::billing::billing_mappings::insert_row($context->{db},
billing_profile_id => $context->{billing_profile}->{id},
contract_id => $context->{contract}->{id},
product_id => $context->{sip_account_product}->{id},
);
$context->{contract}->{contract_balance_id} = NGCP::BulkProcessor::Dao::Trunk::billing::contract_balances::insert_row($context->{db},
contract_id => $context->{contract}->{id},
);
_info($context,"contract id $context->{contract}->{id} created",1);
}
return 1;
}
sub _update_subscriber {
my ($context) = @_;
my $result = 1;
if ($context->{bill_subscriber}->{id}) {
#todo: the update case
} else {
#the insert case
$context->{bill_subscriber}->{id} = NGCP::BulkProcessor::Dao::Trunk::billing::voip_subscribers::insert_row($context->{db},
$context->{bill_subscriber},
);
$context->{prov_subscriber}->{id} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_subscribers::insert_row($context->{db},
$context->{prov_subscriber},
);
my $number = $context->{numbers}->{primary};
$context->{voip_numbers}->{primary} = NGCP::BulkProcessor::Dao::Trunk::billing::voip_numbers::forupdate_cc_ac_sn_subscriberid($context->{db},
$number->{cc},
$number->{ac},
$number->{sn},
$context->{bill_subscriber}->{id});
if (defined $context->{voip_numbers}->{primary}) {
NGCP::BulkProcessor::Dao::Trunk::billing::voip_numbers::update_row($context->{db},{
id => $context->{voip_numbers}->{primary}->{id},
reseller_id => $context->{reseller}->{id},
subscriber_id => $context->{bill_subscriber}->{id},
status => 'active',
});
} else {
$context->{voip_numbers}->{primary}->{id} = NGCP::BulkProcessor::Dao::Trunk::billing::voip_numbers::insert_row($context->{db},
cc => $number->{cc},
ac => $number->{ac},
sn => $number->{sn},
reseller_id => $context->{reseller}->{id},
subscriber_id => $context->{bill_subscriber}->{id},
);
}
$context->{preferences}->{cli} = { id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{cli},
$number->{number}), value => $number->{number} };
NGCP::BulkProcessor::Dao::Trunk::billing::voip_subscribers::update_row($context->{db},{
id => $context->{bill_subscriber}->{id},
primary_number_id => $context->{voip_numbers}->{primary}->{id},
});
_info($context,"subscriber uuid $context->{prov_subscriber}->{uuid} created",1);
#primary alias
$context->{aliases}->{primary}->{id} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::insert_row($context->{db},
domain_id => $context->{prov_subscriber}->{domain_id},
subscriber_id => $context->{prov_subscriber}->{id},
username => $number->{number},
);
my @allowed_clis = ();
push(@allowed_clis,{ id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{allowed_clis},
$number->{number}), value => $number->{number}});
$context->{preferences}->{allowed_clis} = \@allowed_clis;
NGCP::BulkProcessor::Dao::Trunk::billing::voip_numbers::release_subscriber_numbers($context->{db},
$context->{bill_subscriber}->{id},{ 'NOT IN' => $context->{voip_numbers}->{primary}->{id} });
NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::delete_dbaliases($context->{db},
$context->{prov_subscriber}->{id},{ 'NOT IN' => $number->{number} });
clear_subscriber_preferences($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{allowed_clis},
$number->{number});
_info($context,"primary alias $number->{number} created",1);
$context->{voicemail_user}->{id} = NGCP::BulkProcessor::Dao::Trunk::kamailio::voicemail_users::insert_row($context->{db},
$context->{voicemail_user},
);
$context->{preferences}->{account_id} = { id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{account_id},
$context->{contract}->{id}), value => $context->{contract}->{id} };
if (length($number->{ac}) > 0) {
$context->{preferences}->{ac} = { id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{ac},
$number->{ac}), value => $number->{ac} };
}
if (length($number->{cc}) > 0) {
$context->{preferences}->{cc} = { id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{cc},
$number->{cc}), value => $number->{cc} };
}
}
return $result;
}
sub _update_preferences {
my ($context) = @_;
my $result = 1;
if (defined $context->{channels}) {
$context->{preferences}->{concurrent_max_total} = { id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{concurrent_max_total},
$context->{channels}), value => $context->{channels} };
_info($context,"concurrent_max_total preference set to $context->{channels}",1);
}
if ($context->{clir}) {
$context->{preferences}->{clir} = { id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{clir},
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_usr_preferences::TRUE), value => $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_usr_preferences::TRUE };
_info($context,"clir preference set to $context->{clir}",1);
}
if ((scalar @{$context->{allowed_ips}}) > 0) {
my ($allowed_ip_group_preferrence_id, $allowed_ip_group_id) = set_allowed_ips_preferences($context,
$context->{prov_subscriber}->{id},
$context->{prov_subscriber}->{username},
$context->{attributes}->{allowed_ips_grp},
$context->{allowed_ips},
);
$context->{preferences}->{allowed_ips_grp} = { id => $allowed_ip_group_preferrence_id, value => $allowed_ip_group_id };
_info($context,"allowed_ips_grp preference set to $allowed_ip_group_id - " . join(',',@{$context->{allowed_ips}}),1);
}
if (defined $context->{ncos_level}) {
$context->{preferences}->{adm_ncos_id} = { id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{adm_ncos_id},
$context->{ncos_level}->{id}), value => $context->{ncos_level}->{id} };
_info($context,"adm_ncos_id preference set to $context->{ncos_level}->{id} - $context->{ncos_level}->{level}",1);
}
return $result;
}
sub _create_aliases {
my ($context) = @_;
my $result = 1;
if ((scalar @{$context->{numbers}->{other}}) > 0) {
my @voip_number_ids = ();
my @usernames = ();
foreach my $number (@{$context->{numbers}->{other}}) {
my $voip_number = NGCP::BulkProcessor::Dao::Trunk::billing::voip_numbers::forupdate_cc_ac_sn_subscriberid($context->{db},
$number->{cc},
$number->{ac},
$number->{sn},
$context->{bill_subscriber}->{id});
if (defined $voip_number) {
NGCP::BulkProcessor::Dao::Trunk::billing::voip_numbers::update_row($context->{db},{
id => $voip_number->{id},
reseller_id => $context->{reseller}->{id},
subscriber_id => $context->{bill_subscriber}->{id},
status => 'active',
});
} else {
$voip_number->{id} = NGCP::BulkProcessor::Dao::Trunk::billing::voip_numbers::insert_row($context->{db},
cc => $number->{cc},
ac => $number->{ac},
sn => $number->{sn},
reseller_id => $context->{reseller}->{id},
subscriber_id => $context->{bill_subscriber}->{id},
);
}
push(@{$context->{voip_numbers}->{other}}, $voip_number);
push(@voip_number_ids, $voip_number->{id});
my $alias;
if ($alias = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::findby_subscriberid_username($context->{db},
$context->{prov_subscriber}->{id},
$number->{number},
)->[0]) {
NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::update_row($context->{db},{
id => $alias->{id},
is_primary => '0',
});
$alias->{is_primary} = '0';
} else {
$alias->{id} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::insert_row($context->{db},{
domain_id => $context->{prov_subscriber}->{domain_id},
subscriber_id => $context->{prov_subscriber}->{id},
is_primary => '0',
username => $number->{number},
});
}
push(@{$context->{aliases}->{other}},$alias);
push(@usernames,$number->{number});
delete_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{allowed_clis},
$number->{number});
push(@{$context->{preferences}->{allowed_clis}},{ id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{allowed_clis},
$number->{number}), value => $number->{number}});
_info($context,"alias $number->{number} created",1);
}
push(@voip_number_ids,$context->{voip_numbers}->{primary}->{id});
push(@usernames,$context->{numbers}->{primary}->{number});
NGCP::BulkProcessor::Dao::Trunk::billing::voip_numbers::release_subscriber_numbers($context->{db},
$context->{bill_subscriber}->{id},{ 'NOT IN' => \@voip_number_ids });
NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::delete_dbaliases($context->{db},$context->{prov_subscriber}->{id},
{ 'NOT IN' => \@usernames });
clear_subscriber_preferences($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{allowed_clis},
\@usernames );
#test:
#my $allowed_clis = get_subscriber_preference($context,
# $context->{prov_subscriber}->{id},
# $context->{attributes}->{allowed_clis});
#my $voip_numbers = NGCP::BulkProcessor::Dao::Trunk::billing::voip_numbers::findby_subscriberid($context->{db},
# $context->{bill_subscriber}->{id});
#my $aliases = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::findby_subscriberid_username($context->{db},
# $context->{prov_subscriber}->{id},undef);
#_info($context,(scalar @{$context->{numbers}->{other}}) . " aliases created: " . join(',',(map { $_->{number}; } @{$context->{numbers}->{other}})));
}
return $result;
}
sub _set_registrations {
my ($context) = @_;
my $result = 1;
foreach my $registration (@{$context->{registrations}}) {
#print "blah";
$registration->{id} = NGCP::BulkProcessor::Dao::Trunk::kamailio::location::insert_row($context->{db},
%$registration);
_info($context,"permanent registration $registration->{contact} added",1);
}
foreach my $trusted_source (@{$context->{trusted_sources}}) {
#print "blah";
$trusted_source->{id} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_trusted_sources::insert_row($context->{db},{
%$trusted_source,
subscriber_id => $context->{prov_subscriber}->{id},
uuid => $context->{prov_subscriber}->{uuid},
});
_info($context,"trusted source $trusted_source->{protocol} $trusted_source->{src_ip} from $trusted_source->{from_pattern} added",1);
}
return $result;
}
sub _set_callforwards {
my ($context) = @_;
my $result = 1;
foreach my $type (keys %{$context->{callforwards}}) {
#use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destination_sets qw();
#use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destinations qw();
my $destination_set_id = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destination_sets::insert_row($context->{db},{
subscriber_id => $context->{prov_subscriber}->{id},
name => "quickset_$type",
});
foreach my $callforward (@{$context->{callforwards}->{$type}}) {
$callforward->{id} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destinations::insert_row($context->{db},{
%$callforward,
destination_set_id => $destination_set_id,
});
}
my $cf_mapping_id = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::insert_row($context->{db},{
subscriber_id => $context->{prov_subscriber}->{id},
type => $type,
destination_set_id => $destination_set_id,
#time_set_id
});
$context->{preferences}->{$type} = { id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{$type},
$cf_mapping_id), value => $cf_mapping_id };
if (defined $context->{ringtimeout}) {
$context->{preferences}->{ringtimeout} = { id => set_subscriber_preference($context,
$context->{prov_subscriber}->{id},
$context->{attributes}->{ringtimeout},
$context->{ringtimeout}), value => $context->{ringtimeout} };
}
_info($context,"$type created (destination(s) " . join(', ',(map { $_->{destination}; } @{$context->{callforwards}->{$type}})) . ")",1);
$context->{callforwards}->{$type} = {
destination_set => {
destinations => $context->{callforwards}->{$type},
id => $destination_set_id,
},
id => $cf_mapping_id,
};
}
return $result;
}
sub _provision_susbcriber_init_context {
my ($context,$subscriber_group) = @_;
my $result = 1;
$context->{log_info} = [];
$context->{log_warning} = [];
$context->{log_error} = [];
my $first = $subscriber_group->[0];
unless (defined $first->{sip_username} and length($first->{sip_username}) > 0) {
_warn($context,'empty sip_username ignored');
$result = 0;
}
$context->{domain} = $context->{domain_map}->{$first->{domain}};
my $resellername = _apply_reseller_mapping($first->{reseller_name});
$context->{reseller} = $context->{reseller_map}->{$resellername};
$context->{billing_profile} = $context->{reseller}->{billingprofile_map}->{$first->{billing_profile_name}};
$context->{prov_subscriber} = {};
$context->{prov_subscriber}->{username} = $first->{sip_username};
$context->{prov_subscriber}->{password} = $first->{sip_password};
$context->{prov_subscriber}->{webusername} = $first->{web_username};
$context->{prov_subscriber}->{webpassword} = $first->{web_password};
my $webusername = $first->{web_username};
$context->{prov_subscriber}->{uuid} = create_uuid();
$context->{prov_subscriber}->{domain_id} = $context->{domain}->{prov_domain}->{id};
$context->{bill_subscriber} = {};
$context->{bill_subscriber}->{username} = $first->{sip_username};
$context->{bill_subscriber}->{domain_id} = $context->{domain}->{id};
$context->{bill_subscriber}->{uuid} = $context->{prov_subscriber}->{uuid};
undef $context->{contract};
undef $context->{channels};
my @numbers = ();
my %number_dupes = ();
my %contact_dupes = ();
my %allowed_ips = ();
my %barrings = ();
my $voicemail = 0;
foreach my $subscriber (@$subscriber_group) {
my $number = $subscriber->{cc} . $subscriber->{ac} . $subscriber->{sn};
if (not exists $number_dupes{$number}) {
push(@numbers,{
cc => $subscriber->{cc},
ac => $subscriber->{ac},
sn => $subscriber->{sn},
number => $number,
#delta => $subscriber->{delta},
additional => 0,
filename => $subscriber->{filename},
});
$number_dupes{$number} = 1;
} else {
_warn($context,"duplicate number $number ($subscriber->{filename}) ignored");
}
if (not exists $contact_dupes{$subscriber->{contact_hash}}) {
if (not $context->{contract}) {
$context->{contract} = {
external_id => $subscriber->{customer_id},
create_timestamp => $context->{now},
contact => {
reseller_id => $context->{reseller}->{id},
firstname => $subscriber->{first_name},
lastname => $subscriber->{last_name},
compregnum => $subscriber->{company_registration_number},
company => $subscriber->{company},
street => $subscriber->{street},
postcode => $subscriber->{postal_code},
city => $subscriber->{city_name},
#country => $context->{contract}->{contact}->{country},
phonenumber => $subscriber->{phone_number},
email => $subscriber->{email},
vatnum => $subscriber->{vat_number},
$contact_hash_field => $subscriber->{contact_hash},
},
};
$contact_dupes{$subscriber->{contact_hash}} = 1;
} else {
_warn($context,'non-unique contact data, skipped');
$context->{nonunique_contacts}->{$context->{prov_subscriber}->{username}} += 1;
$result = 0;
}
}
my $channels = $subscriber->{channels};
if (defined $channels and length($channels) > 0) {
if (not ($channels > 0)) {
_warn($context,"invalid number of channels $subscriber->{channels}, ignoring");
} elsif (not defined $context->{channels} or $channels > $context->{channels}) {
$context->{channels} = $channels;
}
}
#print $subscriber->{allowed_ips} . "\n";
if (defined $subscriber->{allowed_ips} and length($subscriber->{allowed_ips}) > 0) {
foreach my $ipnet (map { local $_ = $_; trim($_); } split(/$split_ipnets_pattern/,$subscriber->{allowed_ips})) {
if (check_ipnet($ipnet)) {
if ('0.0.0.0' ne $ipnet) {
$allowed_ips{$ipnet} = 1;
} else {
_info($context,"allowed_ip '$ipnet' ignored",1);
}
} else {
_warn($context,"invalid allowed_ip '$ipnet', ignored");
}
}
}
#$context->{allowed_ips} = \@allowed_ips;
unless (defined $context->{prov_subscriber}->{password} and length($context->{prov_subscriber}->{password}) > 0) {
$context->{prov_subscriber}->{password} = $subscriber->{sip_password};
}
unless (defined $context->{prov_subscriber}->{webusername} and length($context->{prov_subscriber}->{webusername}) > 0
and defined $context->{prov_subscriber}->{webpassword} and length($context->{prov_subscriber}->{webpassword}) > 0) {
$context->{prov_subscriber}->{webusername} = $subscriber->{web_username};
$context->{prov_subscriber}->{webpassword} = $subscriber->{web_password};
}
unless (defined $webusername and length($webusername) > 0) {
$webusername = $subscriber->{web_username};
}
if (defined $subscriber->{barrings} and length($subscriber->{barrings}) > 0) {
$barrings{$subscriber->{barrings}} = 1;
}
$voicemail = stringtobool($subscriber->{voicemail}) unless $voicemail;
}
unless (defined $context->{channels}) {
my $default_channels = 1;
foreach my $numbers (sort { $a <=> $b } keys %$default_channels_map) {
if ((scalar @numbers) > $numbers) {
$default_channels = $default_channels_map->{$numbers};
}
}
_info($context,"using $default_channels channels by default for " . (scalar @numbers) . ' numbers',1);
$context->{channels} = $default_channels;
}
unless (defined $context->{prov_subscriber}->{password} and length($context->{prov_subscriber}->{password}) > 0) {
my $generated = _generate_sippassword();
$context->{prov_subscriber}->{password} = $generated;
_info($context,"empty sip_password, using generated '$generated'",1);
}
unless (defined $context->{prov_subscriber}->{webusername} and length($context->{prov_subscriber}->{webusername}) > 0) {
$context->{prov_subscriber}->{webusername} = $webusername;
$context->{prov_subscriber}->{webpassword} = undef;
}
if (not (defined $context->{prov_subscriber}->{webusername} and length($context->{prov_subscriber}->{webusername}) > 0)) {
$context->{prov_subscriber}->{webusername} = undef;
$context->{prov_subscriber}->{webpassword} = undef;
_info($context,"empty web_username for sip_username '$first->{sip_username}'",1);
} else {
$webusername = $context->{prov_subscriber}->{webusername};
my %webusername_dupes = map { $_->{sip_username} => 1; }
@{NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Subscriber::findby_domain_webusername(
$first->{domain},$webusername)};
if ((scalar keys %webusername_dupes) > 1) {
my $generated = _generate_webusername(); #$first->{sip_username};
_info($context,"duplicate web_username '$webusername', using generated '$generated'",1);
$context->{prov_subscriber}->{webusername} = $generated;
}
#$context->{prov_subscriber}->{webpassword} = $first->{web_password};
if (not (defined $context->{prov_subscriber}->{webpassword} and length($context->{prov_subscriber}->{webpassword}) > 0)) {
my $generated = _generate_webpassword();
_info($context,"empty web_password for web_username '$webusername', using generated '$generated'",1);
$context->{prov_subscriber}->{webpassword} = $generated;
#} elsif (defined $first->{web_password} and length($first->{web_password}) < 8) {
# $context->{prov_subscriber}->{webpassword} = _generate_webpassword();
# _info($context,"web_password for web_username '$first->{web_username}' is too short, using '$context->{prov_subscriber}->{webpassword}'");
}
}
$context->{allowed_ips} = [ keys %allowed_ips ];
$context->{ncos_level} = undef;
if ((scalar keys %barrings) > 1) {
my $combined_barring = join('_',sort keys %barrings);
#$result &=
_check_ncos_level($context,$resellername,$combined_barring);
_info($context,"barrings combination $combined_barring");
$context->{ncos_level} = $context->{ncos_level_map}->{$context->{reseller}->{id}}->{$combined_barring};
} elsif ((scalar keys %barrings) == 1) {
my ($barring) = keys %barrings;
$context->{ncos_level} = $context->{ncos_level_map}->{$context->{reseller}->{id}}->{$barring};
} else {
if (exists $context->{ncos_level_map}->{$context->{reseller}->{id}}->{$default_barring}) {
$context->{ncos_level} = $context->{ncos_level_map}->{$context->{reseller}->{id}}->{$default_barring};
_info($context,"no ncos level, using default '$context->{ncos_level}->{level}'",1);
}
}
foreach my $allowed_cli (@{NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::AllowedCli::findby_sipusername($first->{sip_username})}) {
my $number = $allowed_cli->{cc} . $allowed_cli->{ac} . $allowed_cli->{sn};
if (not exists $number_dupes{$number}) {
push(@numbers,{
cc => $allowed_cli->{cc},
ac => $allowed_cli->{ac},
sn => $allowed_cli->{sn},
number => $number,
#delta => $allowed_cli->{delta},
additional => 1,
filename => $allowed_cli->{filename},
});
$number_dupes{$number} = 1;
} else {
_warn($context,"duplicate number $number ($allowed_cli->{filename}) ignored");
}
}
$context->{numbers} = {};
$context->{numbers}->{other} = sort_by_configs(\@numbers,[
{ numeric => 1,
dir => 1, #-1,
memberchain => [ 'additional' ],
},
{ numeric => 0,
dir => 1, #-1,
memberchain => [ 'cc' ],
},
{ numeric => 0,
dir => 1, #-1,
memberchain => [ 'ac' ],
},
{ numeric => 0,
dir => 1, #-1,
memberchain => [ 'sn' ],
},
]);
$context->{numbers}->{primary} = shift(@{$context->{numbers}->{other}});
#return 0 unless scalar @{$context->{numbers}->{other}};
$context->{voip_numbers} = {};
$context->{voip_numbers}->{primary} = undef;
$context->{voip_numbers}->{other} = [];
$context->{aliases} = {};
$context->{aliases}->{primary} = undef;
$context->{aliases}->{other} = [];
$context->{voicemail_user} = {};
$context->{voicemail_user}->{customer_id} = $context->{prov_subscriber}->{uuid};
$context->{voicemail_user}->{mailbox} = $context->{numbers}->{primary}->{number};
$context->{voicemail_user}->{password} = sprintf("%04d", int(rand 10000));
$context->{preferences} = {};
$context->{clir} = 0;
if (my $clir = NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Clir::findby_sipusername($first->{sip_username})) {
$context->{clir} = stringtobool($clir->{clir});
}
$context->{ringtimeout} = undef;
my %cfsimple = ();
my $callforwards = NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::CallForward::findby_sipusername($first->{sip_username});
if ((scalar @$callforwards) > 0 or $voicemail) {
my %vmcf = ();
my %maxpriority = ();
foreach my $callforward (@$callforwards) {
my $type = lc($callforward->{type});
if ($type =~ /$cf_types_pattern/) {
unless (defined $callforward->{destination} and length($callforward->{destination}) > 0) {
_warn($context,"empty callforward destination, ignoring");
next;
}
if ($callforward->{destination} =~ /voicemail/i) {
$callforward->{destination} = 'sip:vm' . ('cfb' eq $type ? 'b' : 'u') . $context->{numbers}->{primary}->{number} . '@voicebox.local';
$vmcf{$type} = 1 unless $vmcf{$type};
} elsif ($callforward->{destination} !~ /^\d+$/i) {
_warn($context,"invalid callforward destination '$callforward->{destination}', ignoring");
next;
} else { #todo: allow sip uri destinations
$callforward->{destination} .= '@' . $context->{domain}->{domain};
}
$callforward->{priority} //= $cf_default_priority;
$callforward->{timeout} //= $cf_default_timeout;
$callforward->{ringtimeout} //= $cft_default_ringtimeout if 'cft' eq $type;
$context->{ringtimeout} = $callforward->{ringtimeout} if ('cft' eq $type and (not defined $context->{ringtimeout} or $callforward->{ringtimeout} > $context->{ringtimeout}));
$cfsimple{$type} = [] unless exists $cfsimple{$type};
push(@{$cfsimple{$type}},{
destination => $callforward->{destination},
priority => $callforward->{priority},
timeout => $callforward->{timeout},
});
#$vmcf{$type} = ($callforward->{destination} =~ /voicemail/i) unless $vmcf{$type};
$maxpriority{$type} = $callforward->{priority} if (not defined $maxpriority{$type} or $callforward->{priority} > $maxpriority{$type});
} else {
_warn($context,"invalid callforward type '$type', ignoring");
}
}
if ($voicemail) {
foreach my $type (($NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::CFNA_TYPE,
$NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::CFT_TYPE)) {
next if $vmcf{$type};
$cfsimple{$type} = [] unless exists $cfsimple{$type};
push(@{$cfsimple{$type}},{
destination => 'sip:vmu' . $context->{numbers}->{primary}->{number} . '@voicebox.local',
priority => (defined $maxpriority{$type} ? $maxpriority{$type} + 1 : $cf_default_priority),
timeout => $cf_default_timeout,
});
$context->{ringtimeout} = $cft_default_ringtimeout if ('cft' eq $type and not defined $context->{ringtimeout}); # or $cft_default_ringtimeout > $context->{ringtimeout}));
}
}
}
$context->{callforwards} = \%cfsimple;
my @registrations = ();
my @trusted_sources = ();
if (my $registration = NGCP::BulkProcessor::Projects::Migration::Teletek::Dao::import::Registration::findby_sipusername($first->{sip_username})) {
#todo: check/transform, multiple contacts
push(@registrations,{
username => $registration->{sip_username},
domain => $registration->{domain},
contact => $registration->{sip_contact},
ruid => NGCP::BulkProcessor::Dao::Trunk::kamailio::location::next_ruid(),
});
if ($registration->{sip_contact} =~ /(\d{0,3}\.\d{0,3}\.\d{0,3}\.\d{0,3})/) {
if (check_ipnet($1)) {
push(@trusted_sources,{
src_ip => $1,
protocol => $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_trusted_sources::PROTOCOL_UDP,
from_pattern => 'sip:.+' . quotemeta($context->{domain}->{domain}),
});
} else {
_warn($context,"invalid IP address in sip contact '$registration->{sip_contact}', skipping trusted source");
}
} else {
_warn($context,"cannot extract IP address from sip contact '$registration->{sip_contact}', skipping trusted source");
}
}
$context->{registrations} = \@registrations;
$context->{trusted_sources} = \@trusted_sources;
#$context->{counts} = {} unless defined $context->{counts};
return $result;
}
sub _generate_webpassword {
return String::MkPasswd::mkpasswd(
-length => $webpassword_length,
-minnum => 1, -minlower => 1, -minupper => 1, -minspecial => 1,
-distribute => 1, -fatal => 1,
);
}
sub _generate_sippassword {
return createtmpstring($sippassword_length);
}
sub _generate_webusername {
return createtmpstring($webusername_length);
}
sub _apply_reseller_mapping {
my $reseller_name = shift;
if (defined $reseller_name and exists $reseller_mapping->{$reseller_name}) {
return $reseller_mapping->{$reseller_name};
}
return $reseller_name;
}
sub _error {
my ($context,$message) = @_;
$context->{error_count} = $context->{error_count} + 1;
push(@{$context->{log_error}},$message) if exists $context->{log_error};
if ($context->{prov_subscriber}) {
$message = ($context->{prov_subscriber}->{username} ? $context->{prov_subscriber}->{username} : '<empty sip_username>') . ': ' . $message;
}
rowprocessingerror($context->{tid},$message,getlogger(__PACKAGE__));
}
sub _warn {
my ($context,$message) = @_;
$context->{warning_count} = $context->{warning_count} + 1;
push(@{$context->{log_warning}},$message) if exists $context->{log_warning};
if ($context->{prov_subscriber}) {
$message = ($context->{prov_subscriber}->{username} ? $context->{prov_subscriber}->{username} : '<empty sip_username>') . ': ' . $message;
}
rowprocessingwarn($context->{tid},$message,getlogger(__PACKAGE__));
}
sub _info {
my ($context,$message,$debug) = @_;
push(@{$context->{log_info}},$message) if exists $context->{log_info};
if ($context->{prov_subscriber}) {
$message = ($context->{prov_subscriber}->{username} ? $context->{prov_subscriber}->{username} : '<empty sip_username>') . ': ' . $message;
}
if ($debug) {
processing_debug($context->{tid},$message,getlogger(__PACKAGE__));
} else {
processing_info($context->{tid},$message,getlogger(__PACKAGE__));
}
}
1;