MT#10715 Add Polycom Zero Touch Provisioning (ZTP) client.

Change-Id: Ia3671355258dbfcf1533d7d4f87083e3beb10dc6
changes/55/755/1
Irina Peshinskaya 10 years ago
parent d3b4f50b6a
commit ce29d22a53

@ -62,17 +62,6 @@ class_has 'query_params' => (
second => sub {},
},
},
{
param => 'vendor',
description => 'Filter for models matching a vendor name pattern',
query => {
first => sub {
my $q = shift;
{ vendor => { like => $q } };
},
second => sub {},
},
},
]},
);
@ -275,7 +264,7 @@ sub POST :Allow {
$item = $c->model('DB')->resultset('autoprov_devices')->create($resource);
NGCP::Panel::Utils::DeviceBootstrap::devmod_sync_credentials_store($c, $item, $credentials);
NGCP::Panel::Utils::DeviceBootstrap::devmod_sync_parameters_store($c, $item, $sync_parameters);
NGCP::Panel::Utils::DeviceBootstrap::dispatch_devmod($c, 'add_server', $item);
NGCP::Panel::Utils::DeviceBootstrap::dispatch_devmod($c, 'register_model', $item);
foreach my $range(@{ $linerange }) {
unless(ref $range eq "HASH") {

@ -190,7 +190,7 @@ sub devmod_create :Chained('base') :PathPart('model/create') :Args(0) :Does(ACL)
my $devmod = $schema->resultset('autoprov_devices')->create($form->params);
NGCP::Panel::Utils::DeviceBootstrap::devmod_sync_credentials_store($c, $devmod, $credentials);
NGCP::Panel::Utils::DeviceBootstrap::devmod_sync_parameters_store($c, $devmod, $sync_parameters);
NGCP::Panel::Utils::DeviceBootstrap::dispatch_devmod($c, 'add_server', $devmod);
NGCP::Panel::Utils::DeviceBootstrap::dispatch_devmod($c, 'register_model', $devmod);
foreach my $range(@{ $linerange }) {
delete $range->{id};
@ -374,7 +374,7 @@ sub devmod_edit :Chained('devmod_base') :PathPart('edit') :Args(0) :Does(ACL) :A
device_id => $c->stash->{devmod}->id,
})->delete;
NGCP::Panel::Utils::DeviceBootstrap::devmod_sync_parameters_store($c, $c->stash->{devmod}, $sync_parameters);
NGCP::Panel::Utils::DeviceBootstrap::dispatch_devmod($c, 'add_server', $c->stash->{devmod} );
NGCP::Panel::Utils::DeviceBootstrap::dispatch_devmod($c, 'register_model', $c->stash->{devmod} );
my @existing_range = ();
my $range_rs = $c->stash->{devmod}->autoprov_device_line_ranges;

@ -205,6 +205,7 @@ has_field 'bootstrap_method' => (
{ label => 'Cisco', value => 'http' },
{ label => 'Panasonic', value => 'redirect_panasonic' },
{ label => 'Yealink', value => 'redirect_yealink' },
{ label => 'Polycom', value => 'redirect_polycom' },
],
default => 'http',
element_attr => {
@ -309,6 +310,39 @@ has_field 'bootstrap_config_redirect_yealink_password' => (
title => ['Password used to configure bootstrap url on Yealink redirect server. Obtained from Yealink.'],
},
);
has_field 'bootstrap_config_redirect_polycom_user' => (
type => 'Text',
required => 0,
label => 'Polycom username',
default => '',
wrapper_class => [qw/ngcp-bootstrap-config ngcp-bootstrap-config-redirect_polycom/],
element_attr => {
rel => ['tooltip'],
title => ['Username used to configure bootstrap url on Polycom redirect server.'],
},
);
has_field 'bootstrap_config_redirect_polycom_password' => (
type => 'Text',
required => 0,
label => 'Polycom password',
default => '',
wrapper_class => [qw/ngcp-bootstrap-config ngcp-bootstrap-config-redirect_polycom/],
element_attr => {
rel => ['tooltip'],
title => ['Password used to configure bootstrap url on Polycom redirect server.'],
},
);
has_field 'bootstrap_config_redirect_polycom_profile' => (
type => 'Text',
required => 0,
label => 'Polycom profile',
default => '',
wrapper_class => [qw/ngcp-bootstrap-config ngcp-bootstrap-config-redirect_polycom/],
element_attr => {
rel => ['tooltip'],
title => ['Preliminary created in ZeroTouch Provisioning console Polycom ZTP profile. Refer to documentation.'],
},
);
has_field 'save' => (
type => 'Submit',
@ -320,7 +354,7 @@ has_field 'save' => (
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/vendor model linerange linerange_add bootstrap_uri bootstrap_method bootstrap_config_http_sync_uri bootstrap_config_http_sync_method bootstrap_config_http_sync_params bootstrap_config_redirect_panasonic_user bootstrap_config_redirect_panasonic_password bootstrap_config_redirect_yealink_user bootstrap_config_redirect_yealink_password front_image mac_image/],
render_list => [qw/vendor model linerange linerange_add bootstrap_uri bootstrap_method bootstrap_config_http_sync_uri bootstrap_config_http_sync_method bootstrap_config_http_sync_params bootstrap_config_redirect_panasonic_user bootstrap_config_redirect_panasonic_password bootstrap_config_redirect_yealink_user bootstrap_config_redirect_yealink_password bootstrap_config_redirect_polycom_user bootstrap_config_redirect_polycom_password bootstrap_config_redirect_polycom_profile front_image mac_image/],
);
has_block 'actions' => (

@ -7,7 +7,7 @@ use Moose::Util::TypeConstraints;
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/reseller vendor model linerange bootstrap_uri bootstrap_method bootstrap_config_http_sync_uri bootstrap_config_http_sync_method bootstrap_config_http_sync_params bootstrap_config_redirect_panasonic_user bootstrap_config_redirect_panasonic_password bootstrap_config_redirect_yealink_user bootstrap_config_redirect_yealink_password/],
render_list => [qw/reseller vendor model linerange bootstrap_uri bootstrap_method bootstrap_config_http_sync_uri bootstrap_config_http_sync_method bootstrap_config_http_sync_params bootstrap_config_redirect_panasonic_user bootstrap_config_redirect_panasonic_password bootstrap_config_redirect_yealink_user bootstrap_config_redirect_yealink_password bootstrap_config_redirect_polycom_user bootstrap_config_redirect_polycom_password bootstrap_config_redirect_polycom_profile/],
);
override 'field_list' => sub {

@ -26,7 +26,7 @@ has_field 'save' => (
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/reseller vendor model linerange linerange_add bootstrap_uri bootstrap_method bootstrap_config_http_sync_uri bootstrap_config_http_sync_method bootstrap_config_http_sync_params bootstrap_config_redirect_panasonic_user bootstrap_config_redirect_panasonic_password bootstrap_config_redirect_yealink_user bootstrap_config_redirect_yealink_password front_image mac_image/],
render_list => [qw/reseller vendor model linerange linerange_add bootstrap_uri bootstrap_method bootstrap_config_http_sync_uri bootstrap_config_http_sync_method bootstrap_config_http_sync_params bootstrap_config_redirect_panasonic_user bootstrap_config_redirect_panasonic_password bootstrap_config_redirect_yealink_user bootstrap_config_redirect_yealink_password bootstrap_config_redirect_polycom_user bootstrap_config_redirect_polycom_password bootstrap_config_redirect_polycom_profile front_image mac_image/],
);
has_block 'actions' => (

@ -4639,7 +4639,7 @@ msgstr "Methode"
#: lib/NGCP/Panel/Utils/DbStrings.pm:1206
msgid ""
"Method to configure the provisioning server on the phone. One of http, "
"redirect_panasonic, redirect_yealink."
"redirect_panasonic, redirect_yealink, redirect_polycom."
msgstr ""
#: lib/NGCP/Panel/Utils/DbStrings.pm:630

@ -4607,7 +4607,7 @@ msgstr "Método"
#: lib/NGCP/Panel/Utils/DbStrings.pm:1206
msgid ""
"Method to configure the provisioning server on the phone. One of http, "
"redirect_panasonic, redirect_yealink."
"redirect_panasonic, redirect_yealink, redirect_polycom."
msgstr ""
#: lib/NGCP/Panel/Utils/DbStrings.pm:630

@ -4643,7 +4643,7 @@ msgstr "Metodo"
#: lib/NGCP/Panel/Utils/DbStrings.pm:1206
msgid ""
"Method to configure the provisioning server on the phone. One of http, "
"redirect_panasonic, redirect_yealink."
"redirect_panasonic, redirect_yealink, redirect_polycom."
msgstr ""
#: lib/NGCP/Panel/Utils/DbStrings.pm:630

@ -4639,7 +4639,7 @@ msgstr "Метод"
#: lib/NGCP/Panel/Utils/DbStrings.pm:1206
msgid ""
"Method to configure the provisioning server on the phone. One of http, "
"redirect_panasonic, redirect_yealink."
"redirect_panasonic, redirect_yealink, redirect_polycom."
msgstr ""
#: lib/NGCP/Panel/Utils/DbStrings.pm:630

@ -166,7 +166,7 @@ sub update_item {
})->delete;
NGCP::Panel::Utils::DeviceBootstrap::devmod_sync_credentials_store($c, $item, $credentials);
NGCP::Panel::Utils::DeviceBootstrap::devmod_sync_parameters_store($c, $item, $sync_parameters);
NGCP::Panel::Utils::DeviceBootstrap::dispatch_devmod($c, 'add_server', $item);
NGCP::Panel::Utils::DeviceBootstrap::dispatch_devmod($c, 'register_model', $item);
my @existing_range = ();
my $range_rs = $item->autoprov_device_line_ranges;

@ -6,6 +6,7 @@ use Data::Dumper;
use NGCP::Panel::Utils::DeviceBootstrap::VendorRPC;
use NGCP::Panel::Utils::DeviceBootstrap::Panasonic;
use NGCP::Panel::Utils::DeviceBootstrap::Yealink;
use NGCP::Panel::Utils::DeviceBootstrap::Polycom;
sub dispatch{
my($c, $action, $fdev, $old_identifier) = @_;
@ -15,25 +16,30 @@ sub dispatch{
mac => $fdev->identifier,
mac_old => $old_identifier,
};
my $redirect_processor = get_redirect_processor($params);
my $ret;
if($redirect_processor){
if( ('register' eq $action) && $old_identifier && ( $old_identifier ne $fdev->identifier ) ){
$redirect_processor->redirect_server_call('unregister');
}
$ret = $redirect_processor->redirect_server_call($action);
}
return $ret;
return _dispatch($c, $action, $params);
}
sub dispatch_devmod{
my($c, $action, $devmod) = @_;
my $params = get_devmod_params($c,$devmod);
return _dispatch($c, $action, $params);
}
sub _dispatch{
my($c, $action, $params) = @_;
my $redirect_processor = get_redirect_processor($params);
my $ret;
if($redirect_processor){
$c->log->debug( "action=$action;" );
if($redirect_processor->can($action)){
$ret = $redirect_processor->$action();
$c->log->debug( "ret=$ret;" );
}else{
if( ('register' eq $action) && $params->{mac_old} && ( $params->{mac_old} ne $params->{mac} ) ){
$redirect_processor->redirect_server_call('unregister');
}
$ret = $redirect_processor->redirect_server_call($action);
}
}
return $ret;
}
sub get_devmod_params{
@ -46,35 +52,41 @@ sub get_devmod_params{
}
my $sync_params_rs = $devmod->autoprov_sync->search_rs({
'autoprov_sync_parameters.parameter_name' => 'sync_params',
'autoprov_sync_parameters.bootstrap_method' => $devmod->bootstrap_method,
},{
join => 'autoprov_sync_parameters',
select => ['me.parameter_value'],
});
my $sync_params = $sync_params_rs->first ? $sync_params_rs->first->parameter_value : '';
}
);
my $sync_params={};
foreach($sync_params_rs->all){
$sync_params->{$_->autoprov_sync_parameters->parameter_name()} = $_->parameter_value;
}
my $params = {
c => $c,
bootstrap_method => $devmod->bootstrap_method,
redirect_uri => $devmod->bootstrap_uri,
redirect_uri_params => $sync_params,
redirect_params => $sync_params,
credentials => $vcredentials,
};
$c->log->debug(Dumper($sync_params));
return $params;
}
sub get_redirect_processor{
my ($params) = @_;
my $c = $params->{c};
my $bootstrap_method = $params->{bootstrap_method};
$c->log->debug( "bootstrap_method=$bootstrap_method;" );
$c->log->debug( "bootstrap_method AAAAAAAAA =$bootstrap_method;" );
my $redirect_processor;
if('redirect_panasonic' eq $bootstrap_method){
$redirect_processor = NGCP::Panel::Utils::DeviceBootstrap::Panasonic->new( params => $params );
}elsif('redirect_yealink' eq $bootstrap_method){
$redirect_processor = NGCP::Panel::Utils::DeviceBootstrap::Yealink->new( params => $params );
}elsif('redirect_polycom' eq $bootstrap_method){
$redirect_processor = NGCP::Panel::Utils::DeviceBootstrap::Polycom->new( params => $params );
}elsif('http' eq $bootstrap_method){
#$ret = panasonic_bootstrap_register($params);
}
$c->log->debug( "redirect_processor=$redirect_processor;" );
return $redirect_processor;
}

@ -59,30 +59,11 @@ sub unregister_content {
return $self->{unregister_content};
}
sub parse_rpc_response{
my($self,$rpc_response) = @_;
return $rpc_response->value->value;
}
sub extract_response_description{
my($self,$response_value) = @_;
if(('HASH' eq ref $response_value) && $response_value->{faultString}){
return $response_value->{faultString};
} else {
return;
}
}
override 'process_uri' => sub {
override 'process_bootstrap_uri' => sub {
my($self,$uri) = @_;
$self->content_params->{uri} = super($uri);
if ($self->content_params->{uri} !~/\{MAC\}$/){
if ($self->content_params->{uri} !~/\/$/){
$self->content_params->{uri} .= '/' ;
}
$self->content_params->{uri} .= '{MAC}' ;
}
$uri = super($uri);
$uri = $self->bootstrap_uri_mac($uri);
$self->content_params->{uri} = $uri;
return $self->content_params->{uri};
};

@ -0,0 +1,144 @@
package NGCP::Panel::Utils::DeviceBootstrap::Polycom;
use strict;
use URI::Escape;
use XML::Mini::Document;;
use Data::Dumper;
use Moose;
extends 'NGCP::Panel::Utils::DeviceBootstrap::VendorRPC';
has 'rpc_server_params' => (
is => 'rw',
isa => 'HashRef',
accessor => '_rpc_server_params',
);
has 'register_content' => (
is => 'rw',
isa => 'Str',
accessor => '_register_content',
);
has 'unregister_content' => (
is => 'rw',
isa => 'Str',
accessor => '_unregister_content',
);
has 'register_subscriber_content' => (
is => 'rw',
isa => 'Str',
accessor => '_register_subscriber_content',
);
sub rpc_server_params{
my $self = shift;
my $cfg = {
proto => 'https',
host => 'ztpconsole.polycom.com',
port => '443',
path => '/inboundservlet/GenericServlet',
#https://ztpconsole.polycom.com/inboundservlet/GenericServlet
};
#$cfg->{headers} = { %{$self->get_basic_authorization($self->params->{credentials})} };
$self->{rpc_server_params} = $cfg;
return $self->{rpc_server_params};
}
sub register_model{
my($self) = @_;
$self->rpc_server_params;
$self->redirect_server_call('register_package');
}
sub register_package_content {
my $self = shift;
#.'_'.$self->content_params->{mac}
$self->{register_package_content} ||= "<?xml version='1.0' encoding='UTF-8'?>
<request userid='".$self->params->{credentials}->{user}."' password='".$self->params->{credentials}->{password}."' message-id='1001'>
<add-package account-id='".uri_escape($self->params->{redirect_params}->{profile})."'>
<package-data>
<base-package-name>default</base-package-name>
</package-data>
</add-package>
</request>";
return $self->{register_package_content};
}
sub register_content {
my $self = shift;
#.'_'.$self->content_params->{mac}
$self->{register_content} ||= "<?xml version='1.0' encoding='UTF-8'?>
<request userid='".$self->params->{credentials}->{user}."' password='".$self->params->{credentials}->{password}."' message-id='1001'>
<add-sip-device account-id='".uri_escape($self->params->{redirect_params}->{profile})."'>
<device-params><deviceId>".$self->content_params->{mac}."</deviceId>
<serialNo>".$self->content_params->{mac}."</serialNo>
<vendor>Polycom</vendor>
<vendorModel>Polycom_UCS_Device</vendorModel>
</device-params>
<sip-device-common-params>
<templateCriteria>".uri_escape($self->params->{redirect_params}->{profile})."</templateCriteria>
</sip-device-common-params>
<package-data><base-package-name>default</base-package-name></package-data>
<vendor-extensions/>
</add-sip-device>
</request>";
return $self->{register_content};
}
sub unregister_content {
my $self = shift;
#.'_'.$self->content_params->{mac}
$self->{unregister_content} ||= "<?xml version='1.0' encoding='UTF-8'?>
<request userid='".$self->params->{credentials}->{user}."' password='".$self->params->{credentials}->{password}."' message-id='1001' >
<delete-sip-device account-id='".uri_escape($self->params->{redirect_params}->{profile})."'>
<device-params>
<deviceId>".$self->content_params->{mac}."</deviceId>
<serialNo>".$self->content_params->{mac}."</serialNo>
<vendor>Polycom</vendor>
<vendorModel>Polycom_UCS_Device</vendorModel>
</device-params>
</delete-sip-device>
</request>";
return $self->{unregister_content};
}
override 'parse_rpc_response_page' => sub {
my($self, $page) = @_;
my $xmlDoc = XML::Mini::Document->new();
$xmlDoc->parse($page);
my $ref = $xmlDoc->toHash();
return $ref;
};
override 'parse_rpc_response' => sub {
my($self, $rpc_response) = @_;
my $c = $self->params->{c};
my $ret = 0;
my ($code,$message) = @{$rpc_response->{response}->{status}}{qw/ErrorCode ErrorMessage/};
if(0 != $code){
$ret = $message;
}
#todo: configure log4perl (or override) to print out caller info and string
$c->log->debug("NGCP::Panel::Utils::DeviceBootstrap::Polycom::parse_rpc_response: ret=$ret; code=$code; message=$message;");
return $ret;
};
1;
=head1 NAME
NGCP::Panel::Utils::DeviceBootstrap
=head1 DESCRIPTION
Make API requests to configure remote redirect servers for requested MAC with autorpov uri.
=head1 METHODS
=head2 bootstrap
Dispatch to proper vendor API call.
=head1 AUTHOR
Irina Peshinskaya C<< <ipeshinskaya@sipwise.com> >>
=head1 LICENSE
This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
# vim: set tabstop=4 expandtab:

@ -36,6 +36,7 @@ sub redirect_server_call{
}
if($content){
$response_value = $self->rpc_https_call($content);
$c->log->debug(Dumper $response_value);
$ret = $self->extract_response_description($response_value);
}
return $ret;
@ -55,17 +56,34 @@ sub rpc_https_call{
'Content-Type' => 'text/xml',
'content' => $content,
},);
$c->log->info( "response=$response_code; page=$page;" );
$c->log->info( "rpc_https_call: response=$response_code; page=$page;" );
my $response_value = '';
if($page){
my $parser = RPC::XML::ParserFactory->new();
my $rpc_response = $parser->parse($page);
my $rpc_response = $self->parse_rpc_response_page($page);
$response_value = $self->parse_rpc_response($rpc_response);
$c->log->info("response_value=".Dumper($response_value));
}
return $response_value;
}
sub parse_rpc_response_page{
my($self, $page) = @_;
my $parser = RPC::XML::ParserFactory->new();
return $parser->parse($page);
}
sub parse_rpc_response{
my($self,$rpc_response) = @_;
return $rpc_response->value->value;
}
sub extract_response_description{
my($self,$response_value) = @_;
if(('HASH' eq ref $response_value) && $response_value->{faultString}){
return $response_value->{faultString};
} else {
return;
}
}
sub init_content_params{
my($self) = @_;
$self->{content_params} ||= {};
@ -84,7 +102,6 @@ sub normalize_mac {
return $mac;
}
sub get_basic_authorization{
my($self) = @_;
my $authorization = encode_base64(join(':',@{$self->params->{credentials}}{qw/user password/}));
@ -95,24 +112,40 @@ sub get_basic_authorization{
sub get_bootstrap_uri{
my ($self) = @_;
my $uri = $self->params->{redirect_uri};
my $uri_params = $self->params->{redirect_uri_params} || '';
my $uri_params = $self->params->{redirect_params}->{sync_params} || '';
if(!$uri){
my $cfg = $self->get_bootstrap_uri_conf();
my $cfg = $self->bootstrap_uri_conf();
$uri = "$cfg->{schema}://$cfg->{host}:$cfg->{port}/device/autoprov/config/";
}
$uri .= $uri_params;
return $self->process_uri($uri);
return $self->process_bootstrap_uri($uri);
}
sub process_uri{
sub process_bootstrap_uri{
my($self,$uri) = @_;
$uri = $self->bootstrap_uri_protocol($uri);
return $uri;
}
sub bootstrap_uri_protocol{
my($self,$uri) = @_;
if($uri !~/^(?:https?|t?ftp):\/\//i ){
$uri = 'http://'.$uri;
}
return $uri;
}
sub bootstrap_uri_mac{
my($self, $uri) = @_;
if ($uri !~/\{MAC\}$/){
if ($uri !~/\/$/){
$uri .= '/' ;
}
$uri .= '{MAC}' ;
}
return $uri;
}
#separated as this logic also used in other places, so can be moved to other utils module
sub get_bootstrap_uri_conf{
sub bootstrap_uri_conf{
my ($self) = @_;
my $c = $self->params->{c};
my $cfg = {

@ -20,10 +20,10 @@ has 'unregister_content' => (
isa => 'Str',
accessor => '_unregister_content',
);
has 'add_server_content' => (
has 'register_model_content' => (
is => 'rw',
isa => 'Str',
accessor => '_add_server_content',
accessor => '_register_model_content',
);
sub rpc_server_params{
my $self = shift;
@ -68,9 +68,9 @@ sub unregister_content {
</methodCall>";
return $self->{unregister_content};
}
sub add_server_content {
sub register_model_content {
my $self = shift;
$self->{add_server_content} ||= "<?xml version='1.0' encoding='UTF-8'?>
$self->{register_model_content} ||= "<?xml version='1.0' encoding='UTF-8'?>
<methodCall>
<methodName>redirect.addServer</methodName>
<params>
@ -86,34 +86,22 @@ sub add_server_content {
</param>
</params>
</methodCall>";
return $self->{add_server_content};
return $self->{register_model_content};
}
sub parse_rpc_response{
my($self,$rpc_response) = @_;
return $rpc_response->value->value;
}
sub extract_response_description{
my($self,$response_value) = @_;
if(('HASH' eq ref $response_value) && $response_value->{faultString}){
return $response_value->{faultString};
} else {
return;
}
}
override 'process_uri' => sub {
override 'process_bootstrap_uri' => sub {
my($self,$uri) = @_;
$self->content_params->{uri} = super();
$self->uri2server_name();
$uri = super($uri);
$self->content_params->{uri} = $uri;
$self->bootstrap_uri_server_name($uri);
return $self->content_params->{uri};
};
sub uri2server_name{
my($self) = @_;
sub bootstrap_uri_server_name{
my($self,$uri) = @_;
$uri ||= $self->content_params->{uri};
#http://stackoverflow.com/questions/4826403/hash-algorithm-with-alphanumeric-output-of-20-characters-max
$self->content_params->{server_name} ||= substr(md5_hex($self->content_params->{uri}),0,20);
$self->content_params->{server_name} ||= substr(md5_hex($uri),0,20);
return $self->content_params->{server_name};
}
1;

@ -650,9 +650,9 @@
$('#line\\.' + formcnt).remove();
var a = range.annotations[j];
[% IF create_flag == 1 -%]
var status = "unassigned";
var action = '<i class="fa fa-plus-square fa-fw"></i> ' +
[%MACRO unassigned_form BLOCK%]
status = "unassigned";
action = '<i class="fa fa-plus-square fa-fw"></i> ' +
'<select class="subselect" name="line.' + formcnt + '.subscriber_id" id="line.' + formcnt + '.subscriber_id">' +
'<option value="0">[% c.loc("Subscriber") %]</option>' +
[% subs = [] -%]
@ -667,6 +667,10 @@
'</select>' +
'<input type="hidden" name="line.' + formcnt + '.line" id="line.' + formcnt + '.line" value="' + a.range_id + '.' + a.line_index + '"/>' +
'';
[%END%]
[% IF create_flag == 1 -%]
var status, action;
[% unassigned_form() %]
[% ELSIF edit_flag == 1 -%]
var linekeys = {
[% FOR line IN pbx_device.autoprov_field_device_lines.all -%]
@ -701,22 +705,7 @@
'<input type="hidden" name="line.' + formcnt + '.line" id="line.' + formcnt + '.line" value="' + a.range_id + '.' + a.line_index + '"/>' +
'';
} else {
status = "unassigned";
var action = '<i class="fa fa-plus-square fa-fw"></i> ' +
'<select class="subselect" name="line.' + formcnt + '.subscriber_id" id="line.' + formcnt + '.subscriber_id">' +
'<option value="0">[% c.loc("Subscriber") %]</option>' +
[% subs = [] -%]
[% FOR sub IN subs.merge(pbx_groups.all, subscribers.all) -%]
'<option value="[% sub.provisioning_voip_subscriber.id %]">[% sub.provisioning_voip_subscriber.display_name ? sub.provisioning_voip_subscriber.display_name : sub.username %][% sub.provisioning_voip_subscriber.pbx_extension.defined ? " (" _ sub.provisioning_voip_subscriber.pbx_extension _ ")" : "" %]</option>' +
[% END -%]
'</select>' +
'<select class="modeselect" name="line.' + formcnt + '.type" id="line.' + formcnt + '.type">' +
[% FOR opt IN ["private", "shared", "blf"] -%]
(range.can_[% opt %] == "1" ? '<option value="[% opt %]">[% opt %]</option>' : '') +
[% END -%]
'</select>' +
'<input type="hidden" name="line.' + formcnt + '.line" id="line.' + formcnt + '.line" value="' + a.range_id + '.' + a.line_index + '"/>' +
'';
[% unassigned_form() %]
}
[% END -%]
markup += '<div class="caption ' + status + '" style="top:' + a.y + 'px; left:' + a.x + 'px;" data-pos="' + a.position + '">' + action + '</div>';

@ -38,6 +38,10 @@ function vendor2bootstrapMethod(vendorField){
bootstrapMethod = 'redirect_yealink';
break;
;
case "polycom":
bootstrapMethod = 'redirect_polycom';
break;
;
}
if(bootstrapMethod){
var length = bootstrapMethodField.options.length;

Loading…
Cancel
Save