#929 implement first half of multi tenancy with tenant_databases setting

This commit is contained in:
Oliver Gorwits
2022-09-24 19:01:05 +01:00
parent b391f83d60
commit 1d5f3ce316
71 changed files with 355 additions and 205 deletions

View File

@@ -63,11 +63,40 @@ if (ref {} eq ref setting('database')) {
foreach my $c (@{setting('external_databases')}) { foreach my $c (@{setting('external_databases')}) {
my $schema = delete $c->{tag} or next; my $schema = delete $c->{tag} or next;
next if $schema eq 'netdisco'; next if exists setting('plugins')->{DBIC}->{$schema};
setting('plugins')->{DBIC}->{$schema} = $c; setting('plugins')->{DBIC}->{$schema} = $c;
setting('plugins')->{DBIC}->{$schema}->{schema_class} setting('plugins')->{DBIC}->{$schema}->{schema_class}
||= 'App::Netdisco::GenericDB'; ||= 'App::Netdisco::GenericDB';
} }
foreach my $c (@{setting('tenant_databases')}) {
my $schema = $c->{tag} or next;
next if exists setting('plugins')->{DBIC}->{$schema};
my $name = $c->{name} || $c->{tag};
my $host = $c->{host};
my $user = $c->{user};
my $pass = $c->{pass};
my $dsn = "dbi:Pg:dbname=${name}";
$dsn .= ";host=${host}" if $host;
setting('plugins')->{DBIC}->{$schema} = {
dsn => $dsn,
user => $user,
password => $pass,
options => {
AutoCommit => 1,
RaiseError => 1,
auto_savepoint => 1,
pg_enable_utf8 => 1,
},
schema_class => 'App::Netdisco::DB',
};
}
# and support tenancies by setting what the default schema points to
setting('plugins')->{DBIC}->{'default'}->{'alias'} = 'netdisco';
} }
# always set this # always set this

View File

@@ -58,8 +58,8 @@ sub _get_denied_actions {
} }
sub jq_warm_thrusters { sub jq_warm_thrusters {
my @devices = schema('netdisco')->resultset('Device')->all; my @devices = schema(vars->{'tenant'})->resultset('Device')->all;
my $rs = schema('netdisco')->resultset('DeviceSkip'); my $rs = schema(vars->{'tenant'})->resultset('DeviceSkip');
my %actionset = (); my %actionset = ();
foreach my $d (@devices) { foreach my $d (@devices) {
@@ -67,7 +67,7 @@ sub jq_warm_thrusters {
$actionset{$d->ip} = \@badactions if scalar @badactions; $actionset{$d->ip} = \@badactions if scalar @badactions;
} }
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
$rs->search({ $rs->search({
backend => setting('workers')->{'BACKEND'}, backend => setting('workers')->{'BACKEND'},
}, { for => 'update' }, )->update({ actionset => [] }); }, { for => 'update' }, )->update({ actionset => [] });
@@ -93,9 +93,9 @@ sub jq_warm_thrusters {
# fix up the pseudo devices which need layer 3 # fix up the pseudo devices which need layer 3
# TODO remove this after next release # TODO remove this after next release
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
my @hosts = grep { defined } my @hosts = grep { defined }
map { schema('netdisco')->resultset('Device')->search_for_device($_->{only}) } map { schema(vars->{'tenant'})->resultset('Device')->search_for_device($_->{only}) }
grep { exists $_->{only} and ref '' eq ref $_->{only} } grep { exists $_->{only} and ref '' eq ref $_->{only} }
grep { exists $_->{driver} and $_->{driver} eq 'cli' } grep { exists $_->{driver} and $_->{driver} eq 'cli' }
@{ setting('device_auth') }; @{ setting('device_auth') };
@@ -109,10 +109,10 @@ sub jq_getsome {
my $num_slots = shift; my $num_slots = shift;
return () unless $num_slots and $num_slots > 0; return () unless $num_slots and $num_slots > 0;
my $jobs = schema('netdisco')->resultset('Admin'); my $jobs = schema(vars->{'tenant'})->resultset('Admin');
my @returned = (); my @returned = ();
my $tasty = schema('netdisco')->resultset('Virtual::TastyJobs') my $tasty = schema(vars->{'tenant'})->resultset('Virtual::TastyJobs')
->search(undef,{ bind => [ ->search(undef,{ bind => [
setting('workers')->{'BACKEND'}, setting('job_prio')->{'high'}, setting('workers')->{'BACKEND'}, setting('job_prio')->{'high'},
setting('workers')->{'BACKEND'}, setting('workers')->{'max_deferrals'}, setting('workers')->{'BACKEND'}, setting('workers')->{'max_deferrals'},
@@ -127,7 +127,7 @@ sub jq_getsome {
# and return false if it should have been skipped. # and return false if it should have been skipped.
my @badactions = _get_denied_actions($job->device); my @badactions = _get_denied_actions($job->device);
if (scalar @badactions) { if (scalar @badactions) {
schema('netdisco')->resultset('DeviceSkip')->find_or_create({ schema(vars->{'tenant'})->resultset('DeviceSkip')->find_or_create({
backend => setting('workers')->{'BACKEND'}, device => $job->device, backend => setting('workers')->{'BACKEND'}, device => $job->device,
},{ key => 'device_skip_pkey' })->add_to_actionset(@badactions); },{ key => 'device_skip_pkey' })->add_to_actionset(@badactions);
@@ -182,7 +182,7 @@ sub jq_getsome {
sub jq_locked { sub jq_locked {
my @returned = (); my @returned = ();
my $rs = schema('netdisco')->resultset('Admin')->search({ my $rs = schema(vars->{'tenant'})->resultset('Admin')->search({
status => ('queued-'. setting('workers')->{'BACKEND'}), status => ('queued-'. setting('workers')->{'BACKEND'}),
started => \[q/> (now() - ?::interval)/, setting('jobs_stale_after')], started => \[q/> (now() - ?::interval)/, setting('jobs_stale_after')],
}); });
@@ -196,7 +196,7 @@ sub jq_locked {
sub jq_queued { sub jq_queued {
my $job_type = shift; my $job_type = shift;
return schema('netdisco')->resultset('Admin')->search({ return schema(vars->{'tenant'})->resultset('Admin')->search({
device => { '!=' => undef}, device => { '!=' => undef},
action => $job_type, action => $job_type,
status => { -like => 'queued%' }, status => { -like => 'queued%' },
@@ -209,7 +209,7 @@ sub jq_lock {
# lock db row and update to show job has been picked # lock db row and update to show job has been picked
try { try {
my $updated = schema('netdisco')->resultset('Admin') my $updated = schema(vars->{'tenant'})->resultset('Admin')
->search({ job => $job->id, status => 'queued' }, { for => 'update' }) ->search({ job => $job->id, status => 'queued' }, { for => 'update' })
->update({ ->update({
status => ('queued-'. setting('workers')->{'BACKEND'}), status => ('queued-'. setting('workers')->{'BACKEND'}),
@@ -237,15 +237,15 @@ sub jq_defer {
# behaviour seems reasonable, to me (or desirable, perhaps). # behaviour seems reasonable, to me (or desirable, perhaps).
try { try {
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
if ($job->device) { if ($job->device) {
schema('netdisco')->resultset('DeviceSkip')->find_or_create({ schema(vars->{'tenant'})->resultset('DeviceSkip')->find_or_create({
backend => setting('workers')->{'BACKEND'}, device => $job->device, backend => setting('workers')->{'BACKEND'}, device => $job->device,
},{ key => 'device_skip_pkey' })->increment_deferrals; },{ key => 'device_skip_pkey' })->increment_deferrals;
} }
# lock db row and update to show job is available # lock db row and update to show job is available
schema('netdisco')->resultset('Admin') schema(vars->{'tenant'})->resultset('Admin')
->find($job->id, {for => 'update'}) ->find($job->id, {for => 'update'})
->update({ status => 'queued', started => undef }); ->update({ status => 'queued', started => undef });
}); });
@@ -269,14 +269,14 @@ sub jq_complete {
# connection failures counter to forget about occasional connect glitches. # connection failures counter to forget about occasional connect glitches.
try { try {
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
if ($job->device) { if ($job->device) {
schema('netdisco')->resultset('DeviceSkip')->find_or_create({ schema(vars->{'tenant'})->resultset('DeviceSkip')->find_or_create({
backend => setting('workers')->{'BACKEND'}, device => $job->device, backend => setting('workers')->{'BACKEND'}, device => $job->device,
},{ key => 'device_skip_pkey' })->update({ deferrals => 0 }); },{ key => 'device_skip_pkey' })->update({ deferrals => 0 });
} }
schema('netdisco')->resultset('Admin') schema(vars->{'tenant'})->resultset('Admin')
->find($job->id, {for => 'update'})->update({ ->find($job->id, {for => 'update'})->update({
status => $job->status, status => $job->status,
log => $job->log, log => $job->log,
@@ -297,7 +297,7 @@ sub jq_complete {
} }
sub jq_log { sub jq_log {
return schema('netdisco')->resultset('Admin')->search({ return schema(vars->{'tenant'})->resultset('Admin')->search({
'me.action' => { '-not_like' => 'hook::%' }, 'me.action' => { '-not_like' => 'hook::%' },
-or => [ -or => [
{ 'me.log' => undef }, { 'me.log' => undef },
@@ -312,7 +312,7 @@ sub jq_log {
sub jq_userlog { sub jq_userlog {
my $user = shift; my $user = shift;
return schema('netdisco')->resultset('Admin')->search({ return schema(vars->{'tenant'})->resultset('Admin')->search({
username => $user, username => $user,
log => { '-not_like' => 'duplicate of %' }, log => { '-not_like' => 'duplicate of %' },
finished => { '>' => \"(now() - interval '5 seconds')" }, finished => { '>' => \"(now() - interval '5 seconds')" },
@@ -328,8 +328,8 @@ sub jq_insert {
my $happy = false; my $happy = false;
try { try {
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
schema('netdisco')->resultset('Admin')->populate([ schema(vars->{'tenant'})->resultset('Admin')->populate([
map {{ map {{
device => $_->{device}, device => $_->{device},
device_key => $_->{device_key}, device_key => $_->{device_key},
@@ -355,14 +355,14 @@ sub jq_delete {
my $id = shift; my $id = shift;
if ($id) { if ($id) {
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
schema('netdisco')->resultset('Admin')->find($id)->delete(); schema(vars->{'tenant'})->resultset('Admin')->find($id)->delete();
}); });
} }
else { else {
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
schema('netdisco')->resultset('Admin')->delete(); schema(vars->{'tenant'})->resultset('Admin')->delete();
schema('netdisco')->resultset('DeviceSkip')->delete(); schema(vars->{'tenant'})->resultset('DeviceSkip')->delete();
}); });
} }
} }

View File

@@ -97,7 +97,7 @@ sub test_connection {
# avoid renumbering to localhost loopbacks # avoid renumbering to localhost loopbacks
return undef if $addr->addr eq '0.0.0.0' return undef if $addr->addr eq '0.0.0.0'
or check_acl_no($addr->addr, 'group:__LOOPBACK_ADDRESSES__'); or check_acl_no($addr->addr, 'group:__LOOPBACK_ADDRESSES__');
my $device = schema('netdisco')->resultset('Device') my $device = schema(vars->{'tenant'})->resultset('Device')
->new_result({ ip => $addr->addr }) or return undef; ->new_result({ ip => $addr->addr }) or return undef;
my $readers = $class->instance->readers or return undef; my $readers = $class->instance->readers or return undef;
return $readers->{$device->ip} if exists $readers->{$device->ip}; return $readers->{$device->ip} if exists $readers->{$device->ip};

View File

@@ -57,12 +57,12 @@ sub get_device {
# in case the management IP of one device is in use on another device, # in case the management IP of one device is in use on another device,
# we first try to get an exact match for the IP as mgmt interface. # we first try to get an exact match for the IP as mgmt interface.
my $alias = my $alias =
schema('netdisco')->resultset('DeviceIp')->find($ip, $ip) schema(vars->{'tenant'})->resultset('DeviceIp')->find($ip, $ip)
|| ||
schema('netdisco')->resultset('DeviceIp')->search({alias => $ip})->first; schema(vars->{'tenant'})->resultset('DeviceIp')->search({alias => $ip})->first;
$ip = $alias->ip if defined $alias; $ip = $alias->ip if defined $alias;
return schema('netdisco')->resultset('Device')->with_times return schema(vars->{'tenant'})->resultset('Device')->with_times
->find_or_new({ip => $ip}); ->find_or_new({ip => $ip});
} }
@@ -82,12 +82,12 @@ sub delete_device {
return 0 if not $device->in_storage; return 0 if not $device->in_storage;
my $happy = 0; my $happy = 0;
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
# will delete everything related too... # will delete everything related too...
schema('netdisco')->resultset('Device') schema(vars->{'tenant'})->resultset('Device')
->search({ ip => $device->ip })->delete({archive_nodes => $archive}); ->search({ ip => $device->ip })->delete({archive_nodes => $archive});
schema('netdisco')->resultset('UserLog')->create({ schema(vars->{'tenant'})->resultset('UserLog')->create({
username => session('logged_in_user'), username => session('logged_in_user'),
userip => scalar eval {request->remote_address}, userip => scalar eval {request->remote_address},
event => (sprintf "Delete device %s", $device->ip), event => (sprintf "Delete device %s", $device->ip),
@@ -116,11 +116,11 @@ sub renumber_device {
return 0 if not $device->in_storage; return 0 if not $device->in_storage;
my $happy = 0; my $happy = 0;
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
$device->renumber($new_ip) $device->renumber($new_ip)
or die "cannot renumber to: $new_ip"; # rollback or die "cannot renumber to: $new_ip"; # rollback
schema('netdisco')->resultset('UserLog')->create({ schema(vars->{'tenant'})->resultset('UserLog')->create({
username => session('logged_in_user'), username => session('logged_in_user'),
userip => scalar eval {request->remote_address}, userip => scalar eval {request->remote_address},
event => (sprintf "Renumber device %s to %s", $ip, $new_ip), event => (sprintf "Renumber device %s to %s", $ip, $new_ip),

View File

@@ -373,13 +373,13 @@ Nodes without topology information are not included.
sub make_graph { sub make_graph {
my $G = Graph::Undirected->new(); my $G = Graph::Undirected->new();
my $devices = schema('netdisco')->resultset('Device') my $devices = schema(vars->{'tenant'})->resultset('Device')
->search({}, { columns => [qw/ip dns location /] }); ->search({}, { columns => [qw/ip dns location /] });
my $links = schema('netdisco')->resultset('DevicePort') my $links = schema(vars->{'tenant'})->resultset('DevicePort')
->search({remote_ip => { -not => undef }}, ->search({remote_ip => { -not => undef }},
{ columns => [qw/ip remote_ip speed remote_type/]}); { columns => [qw/ip remote_ip speed remote_type/]});
my %aliases = map {$_->alias => $_->ip} my %aliases = map {$_->alias => $_->ip}
schema('netdisco')->resultset('DeviceIp') schema(vars->{'tenant'})->resultset('DeviceIp')
->search({}, { columns => [qw/ip alias/] })->all; ->search({}, { columns => [qw/ip alias/] })->all;
my %devs = ( map {($_->ip => $_->dns)} $devices->all ); my %devs = ( map {($_->ip => $_->dns)} $devices->all );

View File

@@ -120,7 +120,7 @@ sub _filter_nbname {
unless ( check_mac( $mac, $ip ) ) { unless ( check_mac( $mac, $ip ) ) {
# Just assume it's the last MAC we saw this IP at. # Just assume it's the last MAC we saw this IP at.
my $node_ip = schema('netdisco')->resultset('NodeIp') my $node_ip = schema(vars->{'tenant'})->resultset('NodeIp')
->single( { ip => $ip, -bool => 'active' } ); ->single( { ip => $ip, -bool => 'active' } );
if ( !defined $node_ip ) { if ( !defined $node_ip ) {
@@ -158,7 +158,7 @@ sub store_nbt {
my ( $hash_ref, $now ) = @_; my ( $hash_ref, $now ) = @_;
$now ||= 'now()'; $now ||= 'now()';
schema('netdisco')->resultset('NodeNbt')->update_or_create( schema(vars->{'tenant'})->resultset('NodeNbt')->update_or_create(
{ mac => $hash_ref->{'mac'}, { mac => $hash_ref->{'mac'},
ip => $hash_ref->{'ip'}, ip => $hash_ref->{'ip'},
nbname => $hash_ref->{'nbname'}, nbname => $hash_ref->{'nbname'},

View File

@@ -175,13 +175,13 @@ sub store_arp {
debug sprintf 'store_arp - mac %s ip %s', $mac->as_ieee, $ip; debug sprintf 'store_arp - mac %s ip %s', $mac->as_ieee, $ip;
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
my $current = schema('netdisco')->resultset('NodeIp') my $current = schema(vars->{'tenant'})->resultset('NodeIp')
->search( ->search(
{ ip => $ip, -bool => 'active'}, { ip => $ip, -bool => 'active'},
{ columns => [qw/mac ip/] })->update({active => \'false'}); { columns => [qw/mac ip/] })->update({active => \'false'});
schema('netdisco')->resultset('NodeIp') schema(vars->{'tenant'})->resultset('NodeIp')
->update_or_create( ->update_or_create(
{ {
mac => $mac->as_ieee, mac => $mac->as_ieee,

View File

@@ -29,7 +29,7 @@ sub _email {
} }
sub monitor { sub monitor {
my $monitor = schema('netdisco')->resultset('Virtual::NodeMonitor'); my $monitor = schema(vars->{'tenant'})->resultset('Virtual::NodeMonitor');
while (my $entry = $monitor->next) { while (my $entry = $monitor->next) {
my $body = <<"end_body"; my $body = <<"end_body";

View File

@@ -152,7 +152,7 @@ sub get_port {
# accept either ip or dbic object # accept either ip or dbic object
$device = get_device($device); $device = get_device($device);
my $port = schema('netdisco')->resultset('DevicePort') my $port = schema(vars->{'tenant'})->resultset('DevicePort')
->find({ip => $device->ip, port => $portname}); ->find({ip => $device->ip, port => $portname});
return $port; return $port;

View File

@@ -36,7 +36,7 @@ sub get_port_macs {
my $bindarray = [ { sqlt_datatype => "array" }, $fw_mac_list ]; my $bindarray = [ { sqlt_datatype => "array" }, $fw_mac_list ];
my $macs my $macs
= schema('netdisco')->resultset('Virtual::PortMacs')->search({}, = schema(vars->{'tenant'})->resultset('Virtual::PortMacs')->search({},
{ bind => [$bindarray, $bindarray], select => [ 'mac', 'ip' ], group_by => [ 'mac', 'ip' ] } ); { bind => [$bindarray, $bindarray], select => [ 'mac', 'ip' ], group_by => [ 'mac', 'ip' ] } );
my $cursor = $macs->cursor; my $cursor = $macs->cursor;
while ( my @vals = $cursor->next ) { while ( my @vals = $cursor->next ) {

View File

@@ -31,7 +31,7 @@ figures.
=cut =cut
sub update_stats { sub update_stats {
my $schema = schema('netdisco'); my $schema = schema(vars->{'tenant'});
eval { require SNMP::Info }; eval { require SNMP::Info };
my $snmpinfo_ver = ($@ ? 'n/a' : $SNMP::Info::VERSION); my $snmpinfo_ver = ($@ ? 'n/a' : $SNMP::Info::VERSION);
my $postgres_ver = pretty_version($schema->storage->dbh->{pg_server_version}, 2); my $postgres_ver = pretty_version($schema->storage->dbh->{pg_server_version}, 2);

View File

@@ -18,6 +18,7 @@ use Path::Class 'dir';
use Module::Load (); use Module::Load ();
use Data::Visitor::Tiny; use Data::Visitor::Tiny;
use Scalar::Util 'blessed'; use Scalar::Util 'blessed';
use Storable 'dclone';
use App::Netdisco::Util::Web qw/ use App::Netdisco::Util::Web qw/
interval_to_daterange interval_to_daterange
@@ -27,8 +28,9 @@ use App::Netdisco::Util::Web qw/
/; /;
BEGIN { BEGIN {
# https://github.com/PerlDancer/Dancer/issues/967
no warnings 'redefine'; no warnings 'redefine';
# https://github.com/PerlDancer/Dancer/issues/967
*Dancer::_redirect = sub { *Dancer::_redirect = sub {
my ($destination, $status) = @_; my ($destination, $status) = @_;
my $response = Dancer::SharedData->response; my $response = Dancer::SharedData->response;
@@ -52,6 +54,49 @@ BEGIN {
code => $status || 500)->render() code => $status || 500)->render()
)->throw; )->throw;
}; };
# to insert /t/$tenant if set
# which is fine for building links, but not fine for
# comparison to request->path, because when is_forward() the
# request->path is changed...
*Dancer::Request::uri_for = sub {
my ($self, $part, $params, $dont_escape) = @_;
my $uri = $self->base;
if (vars->{'tenant'}) {
$part = '/t/'. vars->{'tenant'} . $part;
}
# Make sure there's exactly one slash between the base and the new part
my $base = $uri->path;
$base =~ s|/$||;
$part =~ s|^/||;
$uri->path("$base/$part");
$uri->query_form($params) if $params;
return $dont_escape ? uri_unescape($uri->canonical) : $uri->canonical;
};
# ...so here we are monkeypatching request->path as well
*Dancer::Request::path = sub {
die "path is accessor not mutator" if scalar @_ > 1;
my $self = shift;
$self->_build_path() unless $self->{path};
if (vars->{'tenant'} and $self->{path} !~ m{/t/}) {
my $path = $self->{path};
my $base = setting('path');
my $tenant = '/t/' . vars->{'tenant'};
$tenant = ($base . $tenant) if $base ne '/';
$tenant .= '/' if $base eq '/';
$path =~ s/^$base/$tenant/;
return $path;
}
return $self->{path};
};
} }
use App::Netdisco::Web::AuthN; use App::Netdisco::Web::AuthN;
@@ -140,6 +185,18 @@ hook after_error_render => sub { setting('layout' => 'main') };
for @port_columns; for @port_columns;
} }
# build lookup for tenancies
{
set('tenant_displaynames' => {
map { ( $_->{tag} => { displayname => $_->{displayname},
path => config->{url_base}->with("/t/$_->{tag}")->path } ) }
@{ setting('tenant_databases') },
{ tag => 'netdisco', displayname => 'Default' }
});
config->{'tenant_displaynames'}->{'netdisco'}->{'path'}
= URI::Based->new((config->{path} eq '/') ? '' : config->{path})->path;
}
hook 'before' => sub { hook 'before' => sub {
my $key = request->path; my $key = request->path;
if (param('tab') and ($key !~ m/ajax/)) { if (param('tab') and ($key !~ m/ajax/)) {
@@ -183,6 +240,8 @@ hook 'before_template' => sub {
# allow portable static content # allow portable static content
$tokens->{uri_base} = request->base->path $tokens->{uri_base} = request->base->path
if request->base->path ne '/'; if request->base->path ne '/';
$tokens->{uri_base} .= ('/t/'. vars->{'tenant'})
if vars->{'tenant'};
# allow portable dynamic content # allow portable dynamic content
$tokens->{uri_for} = sub { uri_for(@_)->path_query }; $tokens->{uri_for} = sub { uri_for(@_)->path_query };
@@ -287,8 +346,23 @@ hook before_layout_render => sub {
hook 'after' => sub { hook 'after' => sub {
my $r = shift; # a Dancer::Response my $r = shift; # a Dancer::Response
if (request->path eq uri_for('/swagger.json')->path) { if (request->path eq uri_for('/swagger.json')->path
$r->content( to_json( $r->content ) ); and ref {} eq ref $r->content) {
my $spec = dclone $r->content;
if (vars->{'tenant'}) {
my $base = setting('path');
my $tenant = '/t/' . vars->{'tenant'};
$tenant = ($base . $tenant) if $base ne '/';
$tenant .= '/' if $base eq '/';
foreach my $path (sort keys %{ $spec->{paths} }) {
(my $newpath = $path) =~ s/^$base/$tenant/;
$spec->{paths}->{$newpath} = delete $spec->{paths}->{$path};
}
}
$r->content( to_json( $spec ) );
header('Content-Type' => 'application/json'); header('Content-Type' => 'application/json');
} }
@@ -364,6 +438,18 @@ hook 'after' => sub {
} }
}; };
# support for tenancies
any qr{^/t/(?<tenant>[^/]+)/?$} => sub {
my $capture = captures;
var tenant => $capture->{'tenant'};
forward '/';
};
any '/t/*/**' => sub {
my ($tenant, $path) = splat;
var tenant => $tenant;
forward (join '/', '', @$path, (request->path =~ m{/$} ? '' : ()));
};
any qr{.*} => sub { any qr{.*} => sub {
var('notfound' => true); var('notfound' => true);
status 'not_found'; status 'not_found';

View File

@@ -20,7 +20,7 @@ swagger_path {
], ],
responses => { default => {} }, responses => { default => {} },
}, get '/api/v1/object/device/:ip' => require_role api => sub { }, get '/api/v1/object/device/:ip' => require_role api => sub {
my $device = try { schema('netdisco')->resultset('Device') my $device = try { schema(vars->{'tenant'})->resultset('Device')
->find( params->{ip} ) } or send_error('Bad Device', 404); ->find( params->{ip} ) } or send_error('Bad Device', 404);
return to_json $device->TO_JSON; return to_json $device->TO_JSON;
}; };
@@ -39,7 +39,7 @@ foreach my $rel (qw/device_ips vlans ports modules port_vlans wireless_ports ssi
], ],
responses => { default => {} }, responses => { default => {} },
}, get "/api/v1/object/device/:ip/$rel" => require_role api => sub { }, get "/api/v1/object/device/:ip/$rel" => require_role api => sub {
my $rows = try { schema('netdisco')->resultset('Device') my $rows = try { schema(vars->{'tenant'})->resultset('Device')
->find( params->{ip} )->$rel } or send_error('Bad Device', 404); ->find( params->{ip} )->$rel } or send_error('Bad Device', 404);
return to_json [ map {$_->TO_JSON} $rows->all ]; return to_json [ map {$_->TO_JSON} $rows->all ];
}; };
@@ -65,7 +65,7 @@ foreach my $rel (qw/nodes active_nodes nodes_with_age active_nodes_with_age vlan
responses => { default => {} }, responses => { default => {} },
}, get qr{/api/v1/object/device/(?<ip>[^/]+)/port/(?<port>.+)/${rel}$} => require_role api => sub { }, get qr{/api/v1/object/device/(?<ip>[^/]+)/port/(?<port>.+)/${rel}$} => require_role api => sub {
my $params = captures; my $params = captures;
my $rows = try { schema('netdisco')->resultset('DevicePort') my $rows = try { schema(vars->{'tenant'})->resultset('DevicePort')
->find( $$params{port}, $$params{ip} )->$rel } ->find( $$params{port}, $$params{ip} )->$rel }
or send_error('Bad Device or Port', 404); or send_error('Bad Device or Port', 404);
return to_json [ map {$_->TO_JSON} $rows->all ]; return to_json [ map {$_->TO_JSON} $rows->all ];
@@ -92,7 +92,7 @@ foreach my $rel (qw/power properties ssid wireless agg_master neighbor last_node
responses => { default => {} }, responses => { default => {} },
}, get qr{/api/v1/object/device/(?<ip>[^/]+)/port/(?<port>.+)/${rel}$} => require_role api => sub { }, get qr{/api/v1/object/device/(?<ip>[^/]+)/port/(?<port>.+)/${rel}$} => require_role api => sub {
my $params = captures; my $params = captures;
my $row = try { schema('netdisco')->resultset('DevicePort') my $row = try { schema(vars->{'tenant'})->resultset('DevicePort')
->find( $$params{port}, $$params{ip} )->$rel } ->find( $$params{port}, $$params{ip} )->$rel }
or send_error('Bad Device or Port', 404); or send_error('Bad Device or Port', 404);
return to_json $row->TO_JSON; return to_json $row->TO_JSON;
@@ -119,7 +119,7 @@ swagger_path {
responses => { default => {} }, responses => { default => {} },
}, get qr{/api/v1/object/device/(?<ip>[^/]+)/port/(?<port>.+)$} => require_role api => sub { }, get qr{/api/v1/object/device/(?<ip>[^/]+)/port/(?<port>.+)$} => require_role api => sub {
my $params = captures; my $params = captures;
my $port = try { schema('netdisco')->resultset('DevicePort') my $port = try { schema(vars->{'tenant'})->resultset('DevicePort')
->find( $$params{port}, $$params{ip} ) } ->find( $$params{port}, $$params{ip} ) }
or send_error('Bad Device or Port', 404); or send_error('Bad Device or Port', 404);
return to_json $port->TO_JSON; return to_json $port->TO_JSON;
@@ -145,7 +145,7 @@ swagger_path {
responses => { default => {} }, responses => { default => {} },
}, get '/api/v1/object/device/:ip/nodes' => require_role api => sub { }, get '/api/v1/object/device/:ip/nodes' => require_role api => sub {
my $active = (params->{active_only} and ('true' eq params->{active_only})) ? 1 : 0; my $active = (params->{active_only} and ('true' eq params->{active_only})) ? 1 : 0;
my $rows = try { schema('netdisco')->resultset('Node') my $rows = try { schema(vars->{'tenant'})->resultset('Node')
->search({ switch => params->{ip}, ($active ? (-bool => 'active') : ()) }) } ->search({ switch => params->{ip}, ($active ? (-bool => 'active') : ()) }) }
or send_error('Bad Device', 404); or send_error('Bad Device', 404);
return to_json [ map {$_->TO_JSON} $rows->all ]; return to_json [ map {$_->TO_JSON} $rows->all ];
@@ -172,7 +172,7 @@ swagger_path {
responses => { default => {} }, responses => { default => {} },
}, get '/api/v1/object/vlan/:vlan/nodes' => require_role api => sub { }, get '/api/v1/object/vlan/:vlan/nodes' => require_role api => sub {
my $active = (params->{active_only} and ('true' eq params->{active_only})) ? 1 : 0; my $active = (params->{active_only} and ('true' eq params->{active_only})) ? 1 : 0;
my $rows = try { schema('netdisco')->resultset('Node') my $rows = try { schema(vars->{'tenant'})->resultset('Node')
->search({ vlan => params->{vlan}, ($active ? (-bool => 'active') : ()) }) } ->search({ vlan => params->{vlan}, ($active ? (-bool => 'active') : ()) }) }
or send_error('Bad VLAN', 404); or send_error('Bad VLAN', 404);
return to_json [ map {$_->TO_JSON} $rows->all ]; return to_json [ map {$_->TO_JSON} $rows->all ];

View File

@@ -79,7 +79,7 @@ ajax "/ajax/control/admin/snapshot_req" => require_role admin => sub {
if ! $device or $device->addr eq '0.0.0.0'; if ! $device or $device->addr eq '0.0.0.0';
add_job('loadmibs') add_job('loadmibs')
if not schema('netdisco')->resultset('SNMPObject')->count(); if not schema(vars->{'tenant'})->resultset('SNMPObject')->count();
# will store for download and for browsing # will store for download and for browsing
add_job('snapshot', $device->addr, 'yes') or send_error('Bad device', 400); add_job('snapshot', $device->addr, 'yes') or send_error('Bad device', 400);
@@ -90,7 +90,7 @@ get "/ajax/content/admin/snapshot_get" => require_role admin => sub {
send_error('Bad device', 400) send_error('Bad device', 400)
if ! $device or $device->addr eq '0.0.0.0'; if ! $device or $device->addr eq '0.0.0.0';
my $content = schema('netdisco')->resultset('DeviceSnapshot')->find($device->addr)->cache; my $content = schema(vars->{'tenant'})->resultset('DeviceSnapshot')->find($device->addr)->cache;
send_file( \$content, content_type => 'text/plain', filename => ($device->addr .'-snapshot.txt') ); send_file( \$content, content_type => 'text/plain', filename => ($device->addr .'-snapshot.txt') );
}; };
@@ -99,8 +99,8 @@ ajax "/ajax/control/admin/snapshot_del" => require_role setting('defanged_admin'
send_error('Bad device', 400) send_error('Bad device', 400)
if ! $device or $device->addr eq '0.0.0.0'; if ! $device or $device->addr eq '0.0.0.0';
schema('netdisco')->resultset('DeviceSnapshot')->find($device->addr)->delete; schema(vars->{'tenant'})->resultset('DeviceSnapshot')->find($device->addr)->delete;
schema('netdisco')->resultset('DeviceBrowser')->search({ip => $device->addr})->delete; schema(vars->{'tenant'})->resultset('DeviceBrowser')->search({ip => $device->addr})->delete;
}; };
get '/admin/*' => require_role admin => sub { get '/admin/*' => require_role admin => sub {

View File

@@ -63,7 +63,7 @@ hook 'before_template' => sub {
get '/device' => require_login sub { get '/device' => require_login sub {
my $q = param('q'); my $q = param('q');
my $devices = schema('netdisco')->resultset('Device'); my $devices = schema(vars->{'tenant'})->resultset('Device');
# we are passed either dns or ip # we are passed either dns or ip
my $dev = $devices->search({ my $dev = $devices->search({
@@ -86,7 +86,7 @@ get '/device' => require_login sub {
template 'device', { template 'device', {
is_pseudo => $first->is_pseudo, is_pseudo => $first->is_pseudo,
display_name => ($others ? $first->ip : ($first->dns || $first->ip)), display_name => ($others ? $first->ip : ($first->dns || $first->ip)),
lgroup_list => [ schema('netdisco')->resultset('Device')->get_distinct_col('location') ], lgroup_list => [ schema(vars->{'tenant'})->resultset('Device')->get_distinct_col('location') ],
hgroup_list => setting('host_group_displaynames'), hgroup_list => setting('host_group_displaynames'),
device => params->{'tab'}, device => params->{'tab'},
}, { layout => 'main' }; }, { layout => 'main' };

View File

@@ -13,8 +13,8 @@ register_admin_task({
}); });
ajax '/ajax/content/admin/duplicatedevices' => require_role admin => sub { ajax '/ajax/content/admin/duplicatedevices' => require_role admin => sub {
my @set = schema('netdisco')->resultset('Device')->search({ my @set = schema(vars->{'tenant'})->resultset('Device')->search({
serial => { '-in' => schema('netdisco')->resultset('Device')->search({ serial => { '-in' => schema(vars->{'tenant'})->resultset('Device')->search({
'-and' => [serial => { '!=', undef }, serial => { '!=', '' }], '-and' => [serial => { '!=', undef }, serial => { '!=', '' }],
}, { }, {
group_by => ['serial'], group_by => ['serial'],

View File

@@ -24,8 +24,8 @@ sub _sanity_ok {
ajax '/ajax/control/admin/nodemonitor/add' => require_role admin => sub { ajax '/ajax/control/admin/nodemonitor/add' => require_role admin => sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
my $monitor = schema('netdisco')->resultset('NodeMonitor') my $monitor = schema(vars->{'tenant'})->resultset('NodeMonitor')
->create({ ->create({
mac => param('mac'), mac => param('mac'),
matchoui => (param('matchoui') ? \'true' : \'false'), matchoui => (param('matchoui') ? \'true' : \'false'),
@@ -39,8 +39,8 @@ ajax '/ajax/control/admin/nodemonitor/add' => require_role admin => sub {
ajax '/ajax/control/admin/nodemonitor/del' => require_role admin => sub { ajax '/ajax/control/admin/nodemonitor/del' => require_role admin => sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
schema('netdisco')->resultset('NodeMonitor') schema(vars->{'tenant'})->resultset('NodeMonitor')
->find({mac => param('mac')})->delete; ->find({mac => param('mac')})->delete;
}); });
}; };
@@ -48,8 +48,8 @@ ajax '/ajax/control/admin/nodemonitor/del' => require_role admin => sub {
ajax '/ajax/control/admin/nodemonitor/update' => require_role admin => sub { ajax '/ajax/control/admin/nodemonitor/update' => require_role admin => sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
my $monitor = schema('netdisco')->resultset('NodeMonitor') my $monitor = schema(vars->{'tenant'})->resultset('NodeMonitor')
->find({mac => param('mac')}); ->find({mac => param('mac')});
return unless $monitor; return unless $monitor;
@@ -65,7 +65,7 @@ ajax '/ajax/control/admin/nodemonitor/update' => require_role admin => sub {
}; };
ajax '/ajax/content/admin/nodemonitor' => require_role admin => sub { ajax '/ajax/content/admin/nodemonitor' => require_role admin => sub {
my $set = schema('netdisco')->resultset('NodeMonitor') my $set = schema(vars->{'tenant'})->resultset('NodeMonitor')
->search(undef, { order_by => [qw/active date mac/] }); ->search(undef, { order_by => [qw/active date mac/] });
content_type('text/html'); content_type('text/html');

View File

@@ -17,11 +17,11 @@ register_admin_task(
get '/ajax/content/admin/orphaned' => require_role admin => sub { get '/ajax/content/admin/orphaned' => require_role admin => sub {
my @tree = schema('netdisco')->resultset('Virtual::UnDirEdgesAgg') my @tree = schema(vars->{'tenant'})->resultset('Virtual::UnDirEdgesAgg')
->search( undef, { prefetch => 'device' } )->hri->all; ->search( undef, { prefetch => 'device' } )->hri->all;
my @orphans my @orphans
= schema('netdisco')->resultset('Virtual::OrphanedDevices')->search() = schema(vars->{'tenant'})->resultset('Virtual::OrphanedDevices')->search()
->order_by('ip')->hri->all; ->order_by('ip')->hri->all;
return unless ( scalar @tree || scalar @orphans ); return unless ( scalar @tree || scalar @orphans );

View File

@@ -13,7 +13,7 @@ register_admin_task({
}); });
ajax '/ajax/content/admin/performance' => require_role admin => sub { ajax '/ajax/content/admin/performance' => require_role admin => sub {
my $set = schema('netdisco')->resultset('Virtual::PollerPerformance'); my $set = schema(vars->{'tenant'})->resultset('Virtual::PollerPerformance');
content_type('text/html'); content_type('text/html');
template 'ajax/admintask/performance.tt', { template 'ajax/admintask/performance.tt', {

View File

@@ -32,8 +32,8 @@ sub _sanity_ok {
ajax '/ajax/control/admin/pseudodevice/add' => require_role admin => sub { ajax '/ajax/control/admin/pseudodevice/add' => require_role admin => sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
my $device = schema('netdisco')->resultset('Device') my $device = schema(vars->{'tenant'})->resultset('Device')
->create({ ->create({
ip => param('ip'), ip => param('ip'),
dns => (hostname_from_ip(param('ip')) || ''), dns => (hostname_from_ip(param('ip')) || ''),
@@ -55,7 +55,7 @@ ajax '/ajax/control/admin/pseudodevice/add' => require_role admin => sub {
]); ]);
# device_ip table is used to show whether topo is "broken" # device_ip table is used to show whether topo is "broken"
schema('netdisco')->resultset('DeviceIp') schema(vars->{'tenant'})->resultset('DeviceIp')
->create({ ->create({
ip => param('ip'), ip => param('ip'),
alias => param('ip'), alias => param('ip'),
@@ -66,8 +66,8 @@ ajax '/ajax/control/admin/pseudodevice/add' => require_role admin => sub {
ajax '/ajax/control/admin/pseudodevice/update' => require_role admin => sub { ajax '/ajax/control/admin/pseudodevice/update' => require_role admin => sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
my $device = schema('netdisco')->resultset('Device') my $device = schema(vars->{'tenant'})->resultset('Device')
->with_port_count->find({ip => param('ip')}); ->with_port_count->find({ip => param('ip')});
return unless $device; return unless $device;
my $count = $device->port_count; my $count = $device->port_count;
@@ -87,7 +87,7 @@ ajax '/ajax/control/admin/pseudodevice/update' => require_role admin => sub {
->single({port => "Port${port}"})->delete; ->single({port => "Port${port}"})->delete;
# clear outdated manual topology links # clear outdated manual topology links
schema('netdisco')->resultset('Topology')->search({ schema(vars->{'tenant'})->resultset('Topology')->search({
-or => [ -or => [
{ dev1 => $device->ip, port1 => "Port${port}" }, { dev1 => $device->ip, port1 => "Port${port}" },
{ dev2 => $device->ip, port2 => "Port${port}" }, { dev2 => $device->ip, port2 => "Port${port}" },
@@ -106,7 +106,7 @@ ajax '/ajax/control/admin/pseudodevice/update' => require_role admin => sub {
}; };
ajax '/ajax/content/admin/pseudodevice' => require_role admin => sub { ajax '/ajax/content/admin/pseudodevice' => require_role admin => sub {
my $set = schema('netdisco')->resultset('Device') my $set = schema(vars->{'tenant'})->resultset('Device')
->search( ->search(
{-bool => 'is_pseudo'}, {-bool => 'is_pseudo'},
{order_by => { -desc => 'last_discover' }}, {order_by => { -desc => 'last_discover' }},

View File

@@ -13,7 +13,7 @@ register_admin_task({
}); });
ajax '/ajax/content/admin/slowdevices' => require_role admin => sub { ajax '/ajax/content/admin/slowdevices' => require_role admin => sub {
my $set = schema('netdisco')->resultset('Virtual::SlowDevices'); my $set = schema(vars->{'tenant'})->resultset('Virtual::SlowDevices');
content_type('text/html'); content_type('text/html');
template 'ajax/admintask/slowdevices.tt', { template 'ajax/admintask/slowdevices.tt', {

View File

@@ -17,13 +17,13 @@ ajax '/ajax/control/admin/timedoutdevices/del' => require_role admin => sub {
send_error('Missing backend', 400) unless param('backend'); send_error('Missing backend', 400) unless param('backend');
send_error('Missing device', 400) unless param('device'); send_error('Missing device', 400) unless param('device');
schema('netdisco')->resultset('DeviceSkip')->find_or_create({ schema(vars->{'tenant'})->resultset('DeviceSkip')->find_or_create({
backend => param('backend'), device => param('device'), backend => param('backend'), device => param('device'),
},{ key => 'device_skip_pkey' })->update({ deferrals => 0 }); },{ key => 'device_skip_pkey' })->update({ deferrals => 0 });
}; };
ajax '/ajax/content/admin/timedoutdevices' => require_role admin => sub { ajax '/ajax/content/admin/timedoutdevices' => require_role admin => sub {
my @set = schema('netdisco')->resultset('DeviceSkip')->search({ my @set = schema(vars->{'tenant'})->resultset('DeviceSkip')->search({
deferrals => { '>' => 0 } deferrals => { '>' => 0 }
},{ rows => (setting('dns')->{max_outstanding} || 50), order_by => },{ rows => (setting('dns')->{max_outstanding} || 50), order_by =>
[{ -desc => 'deferrals' }, { -asc => [qw/device backend/] }] [{ -desc => 'deferrals' }, { -asc => [qw/device backend/] }]

View File

@@ -35,7 +35,7 @@ sub _sanity_ok {
ajax '/ajax/control/admin/topology/add' => require_any_role [qw(admin port_control)] => sub { ajax '/ajax/control/admin/topology/add' => require_any_role [qw(admin port_control)] => sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
my $device = schema('netdisco')->resultset('Topology') my $device = schema(vars->{'tenant'})->resultset('Topology')
->create({ ->create({
dev1 => param('dev1'), dev1 => param('dev1'),
port1 => param('port1'), port1 => param('port1'),
@@ -46,7 +46,7 @@ ajax '/ajax/control/admin/topology/add' => require_any_role [qw(admin port_contr
# re-set remote device details in affected ports # re-set remote device details in affected ports
# could fail for bad device or port names # could fail for bad device or port names
try { try {
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
# only work on root_ips # only work on root_ips
my $left = get_device(param('dev1')); my $left = get_device(param('dev1'));
my $right = get_device(param('dev2')); my $right = get_device(param('dev2'));
@@ -84,8 +84,8 @@ ajax '/ajax/control/admin/topology/add' => require_any_role [qw(admin port_contr
ajax '/ajax/control/admin/topology/del' => require_any_role [qw(admin port_control)] => sub { ajax '/ajax/control/admin/topology/del' => require_any_role [qw(admin port_control)] => sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
my $device = schema('netdisco')->resultset('Topology') my $device = schema(vars->{'tenant'})->resultset('Topology')
->search({ ->search({
dev1 => param('dev1'), dev1 => param('dev1'),
port1 => param('port1'), port1 => param('port1'),
@@ -97,7 +97,7 @@ ajax '/ajax/control/admin/topology/del' => require_any_role [qw(admin port_contr
# re-set remote device details in affected ports # re-set remote device details in affected ports
# could fail for bad device or port names # could fail for bad device or port names
try { try {
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
# only work on root_ips # only work on root_ips
my $left = get_device(param('dev1')); my $left = get_device(param('dev1'));
my $right = get_device(param('dev2')); my $right = get_device(param('dev2'));
@@ -133,7 +133,7 @@ ajax '/ajax/control/admin/topology/del' => require_any_role [qw(admin port_contr
}; };
ajax '/ajax/content/admin/topology' => require_any_role [qw(admin port_control)] => sub { ajax '/ajax/content/admin/topology' => require_any_role [qw(admin port_control)] => sub {
my $set = schema('netdisco')->resultset('Topology') my $set = schema(vars->{'tenant'})->resultset('Topology')
->search({},{order_by => [qw/dev1 dev2 port1/]}); ->search({},{order_by => [qw/dev1 dev2 port1/]});
content_type('text/html'); content_type('text/html');

View File

@@ -23,7 +23,7 @@ register_admin_task(
get '/ajax/content/admin/undiscoveredneighbors' => require_role admin => sub { get '/ajax/content/admin/undiscoveredneighbors' => require_role admin => sub {
my @results my @results
= schema('netdisco')->resultset('Virtual::UndiscoveredNeighbors')->hri->all; = schema(vars->{'tenant'})->resultset('Virtual::UndiscoveredNeighbors')->hri->all;
return unless scalar @results; return unless scalar @results;
if ( request->is_ajax ) { if ( request->is_ajax ) {

View File

@@ -18,7 +18,7 @@ ajax '/ajax/control/admin/userlog/data' => require_role admin => sub {
send_error( 'Missing parameter', 400 ) send_error( 'Missing parameter', 400 )
unless ( param('draw') && param('draw') =~ /\d+/ ); unless ( param('draw') && param('draw') =~ /\d+/ );
my $rs = schema('netdisco')->resultset('UserLog'); my $rs = schema(vars->{'tenant'})->resultset('UserLog');
my $exp_params = expand_hash( scalar params ); my $exp_params = expand_hash( scalar params );
@@ -41,18 +41,18 @@ ajax '/ajax/control/admin/userlog/data' => require_role admin => sub {
ajax '/ajax/control/admin/userlog/del' => require_role admin => sub { ajax '/ajax/control/admin/userlog/del' => require_role admin => sub {
send_error( 'Missing entry', 400 ) unless param('entry'); send_error( 'Missing entry', 400 ) unless param('entry');
schema('netdisco')->txn_do( schema(vars->{'tenant'})->txn_do(
sub { sub {
my $device = schema('netdisco')->resultset('UserLog') my $device = schema(vars->{'tenant'})->resultset('UserLog')
->search( { entry => param('entry') } )->delete; ->search( { entry => param('entry') } )->delete;
} }
); );
}; };
ajax '/ajax/control/admin/userlog/delall' => require_role admin => sub { ajax '/ajax/control/admin/userlog/delall' => require_role admin => sub {
schema('netdisco')->txn_do( schema(vars->{'tenant'})->txn_do(
sub { sub {
my $device = schema('netdisco')->resultset('UserLog')->delete; my $device = schema(vars->{'tenant'})->resultset('UserLog')->delete;
} }
); );
}; };

View File

@@ -34,8 +34,8 @@ sub _make_password {
ajax '/ajax/control/admin/users/add' => require_role setting('defanged_admin') => sub { ajax '/ajax/control/admin/users/add' => require_role setting('defanged_admin') => sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
my $user = schema('netdisco')->resultset('User') my $user = schema(vars->{'tenant'})->resultset('User')
->create({ ->create({
username => param('username'), username => param('username'),
password => _make_password(param('password')), password => _make_password(param('password')),
@@ -53,8 +53,8 @@ ajax '/ajax/control/admin/users/add' => require_role setting('defanged_admin') =
ajax '/ajax/control/admin/users/del' => require_role setting('defanged_admin') => sub { ajax '/ajax/control/admin/users/del' => require_role setting('defanged_admin') => sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
schema('netdisco')->resultset('User') schema(vars->{'tenant'})->resultset('User')
->find({username => param('username')})->delete; ->find({username => param('username')})->delete;
}); });
}; };
@@ -62,8 +62,8 @@ ajax '/ajax/control/admin/users/del' => require_role setting('defanged_admin') =
ajax '/ajax/control/admin/users/update' => require_role setting('defanged_admin') => sub { ajax '/ajax/control/admin/users/update' => require_role setting('defanged_admin') => sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
my $user = schema('netdisco')->resultset('User') my $user = schema(vars->{'tenant'})->resultset('User')
->find({username => param('username')}); ->find({username => param('username')});
return unless $user; return unless $user;
@@ -83,7 +83,7 @@ ajax '/ajax/control/admin/users/update' => require_role setting('defanged_admin'
}; };
get '/ajax/content/admin/users' => require_role admin => sub { get '/ajax/content/admin/users' => require_role admin => sub {
my @results = schema('netdisco')->resultset('User') my @results = schema(vars->{'tenant'})->resultset('User')
->search(undef, { ->search(undef, {
'+columns' => { '+columns' => {
created => \"to_char(creation, 'YYYY-MM-DD HH24:MI')", created => \"to_char(creation, 'YYYY-MM-DD HH24:MI')",

View File

@@ -13,7 +13,7 @@ get '/ajax/content/device/addresses' => require_login sub {
my $q = param('q'); my $q = param('q');
my $device my $device
= schema('netdisco')->resultset('Device')->search_for_device($q) = schema(vars->{'tenant'})->resultset('Device')->search_for_device($q)
or send_error( 'Bad device', 400 ); or send_error( 'Bad device', 400 );
my @results = $device->device_ips my @results = $device->device_ips

View File

@@ -12,11 +12,11 @@ register_device_tab({ tag => 'details', label => 'Details' });
# device details table # device details table
ajax '/ajax/content/device/details' => require_login sub { ajax '/ajax/content/device/details' => require_login sub {
my $q = param('q'); my $q = param('q');
my $device = schema('netdisco')->resultset('Device') my $device = schema(vars->{'tenant'})->resultset('Device')
->search_for_device($q) or send_error('Bad device', 400); ->search_for_device($q) or send_error('Bad device', 400);
my @results my @results
= schema('netdisco')->resultset('Device') = schema(vars->{'tenant'})->resultset('Device')
->search({ 'me.ip' => $device->ip }, ->search({ 'me.ip' => $device->ip },
{ {
'+select' => ['snapshot.ip'], '+select' => ['snapshot.ip'],
@@ -27,11 +27,11 @@ ajax '/ajax/content/device/details' => require_login sub {
->hri->all; ->hri->all;
my @power my @power
= schema('netdisco')->resultset('DevicePower') = schema(vars->{'tenant'})->resultset('DevicePower')
->search( { 'me.ip' => $device->ip } )->with_poestats->hri->all; ->search( { 'me.ip' => $device->ip } )->with_poestats->hri->all;
my @interfaces my @interfaces
= schema('netdisco')->resultset('Device') = schema(vars->{'tenant'})->resultset('Device')
->find($device->ip) ->find($device->ip)
->device_ips->hri->all; ->device_ips->hri->all;

View File

@@ -13,7 +13,7 @@ register_device_tab({ tag => 'modules', label => 'Modules' });
ajax '/ajax/content/device/modules' => require_login sub { ajax '/ajax/content/device/modules' => require_login sub {
my $q = param('q'); my $q = param('q');
my $device = schema('netdisco')->resultset('Device') my $device = schema(vars->{'tenant'})->resultset('Device')
->search_for_device($q) or send_error('Bad device', 400); ->search_for_device($q) or send_error('Bad device', 400);
my @set = $device->modules->search({}, {order_by => { -asc => [qw/parent class pos index/] }}); my @set = $device->modules->search({}, {order_by => { -asc => [qw/parent class pos index/] }});

View File

@@ -19,7 +19,7 @@ ajax '/ajax/content/device/netmap' => require_login sub {
ajax '/ajax/data/device/netmappositions' => require_login sub { ajax '/ajax/data/device/netmappositions' => require_login sub {
my $q = param('q'); my $q = param('q');
my $qdev = schema('netdisco')->resultset('Device') my $qdev = schema(vars->{'tenant'})->resultset('Device')
->search_for_device($q) or send_error('Bad device', 400); ->search_for_device($q) or send_error('Bad device', 400);
my $p = param('positions') or send_error('Missing positions', 400); my $p = param('positions') or send_error('Missing positions', 400);
@@ -55,7 +55,7 @@ ajax '/ajax/data/device/netmappositions' => require_login sub {
} }
return unless scalar keys %clean; return unless scalar keys %clean;
my $posrow = schema('netdisco')->resultset('NetmapPositions')->find({ my $posrow = schema(vars->{'tenant'})->resultset('NetmapPositions')->find({
device => (($mapshow eq 'neighbors') ? $qdev->ip : undef), device => (($mapshow eq 'neighbors') ? $qdev->ip : undef),
host_groups => \[ '= ?', [host_groups => [sort @hgrplist]] ], host_groups => \[ '= ?', [host_groups => [sort @hgrplist]] ],
locations => \[ '= ?', [locations => [sort @lgrplist]] ], locations => \[ '= ?', [locations => [sort @lgrplist]] ],
@@ -66,7 +66,7 @@ ajax '/ajax/data/device/netmappositions' => require_login sub {
$posrow->update({ positions => to_json(\%clean) }); $posrow->update({ positions => to_json(\%clean) });
} }
else { else {
schema('netdisco')->resultset('NetmapPositions')->create({ schema(vars->{'tenant'})->resultset('NetmapPositions')->create({
device => (($mapshow eq 'neighbors') ? $qdev->ip : undef), device => (($mapshow eq 'neighbors') ? $qdev->ip : undef),
host_groups => [sort @hgrplist], host_groups => [sort @hgrplist],
locations => [sort @lgrplist], locations => [sort @lgrplist],
@@ -136,7 +136,7 @@ sub make_link_infostring {
ajax '/ajax/data/device/netmap' => require_login sub { ajax '/ajax/data/device/netmap' => require_login sub {
my $q = param('q'); my $q = param('q');
my $qdev = schema('netdisco')->resultset('Device') my $qdev = schema(vars->{'tenant'})->resultset('Device')
->search_for_device($q) or send_error('Bad device', 400); ->search_for_device($q) or send_error('Bad device', 400);
my $vlan = param('vlan'); my $vlan = param('vlan');
@@ -168,7 +168,7 @@ ajax '/ajax/data/device/netmap' => require_login sub {
# LINKS # LINKS
my %seen_link = (); my %seen_link = ();
my $links = schema('netdisco')->resultset('Virtual::DeviceLinks')->search({ my $links = schema(vars->{'tenant'})->resultset('Virtual::DeviceLinks')->search({
($mapshow eq 'neighbors' ? ( -or => [ ($mapshow eq 'neighbors' ? ( -or => [
{ left_ip => $qdev->ip }, { left_ip => $qdev->ip },
{ right_ip => $qdev->ip }, { right_ip => $qdev->ip },
@@ -195,7 +195,7 @@ ajax '/ajax/data/device/netmap' => require_login sub {
# DEVICES (NODES) # DEVICES (NODES)
my $posrow = schema('netdisco')->resultset('NetmapPositions')->find({ my $posrow = schema(vars->{'tenant'})->resultset('NetmapPositions')->find({
device => (($mapshow eq 'neighbors') ? $qdev->ip : undef), device => (($mapshow eq 'neighbors') ? $qdev->ip : undef),
host_groups => \[ '= ?', [host_groups => [sort @hgrplist]] ], host_groups => \[ '= ?', [host_groups => [sort @hgrplist]] ],
locations => \[ '= ?', [locations => [sort @lgrplist]] ], locations => \[ '= ?', [locations => [sort @lgrplist]] ],
@@ -203,7 +203,7 @@ ajax '/ajax/data/device/netmap' => require_login sub {
}); });
my $pos_for = from_json( $posrow ? $posrow->positions : '{}' ); my $pos_for = from_json( $posrow ? $posrow->positions : '{}' );
my $devices = schema('netdisco')->resultset('Device')->search({}, { my $devices = schema(vars->{'tenant'})->resultset('Device')->search({}, {
'+select' => [\'floor(log(throughput.total))'], '+as' => ['log'], '+select' => [\'floor(log(throughput.total))'], '+as' => ['log'],
join => 'throughput', distinct => 1, join => 'throughput', distinct => 1,
})->with_times; })->with_times;

View File

@@ -18,7 +18,7 @@ get '/ajax/content/device/ports' => require_login sub {
$prefer = '' $prefer = ''
unless defined $prefer and $prefer =~ m/^(?:port|name|vlan)$/; unless defined $prefer and $prefer =~ m/^(?:port|name|vlan)$/;
my $device = schema('netdisco')->resultset('Device') my $device = schema(vars->{'tenant'})->resultset('Device')
->search_for_device($q) or send_error('Bad device', 400); ->search_for_device($q) or send_error('Bad device', 400);
my $set = $device->ports->with_properties; my $set = $device->ports->with_properties;

View File

@@ -15,10 +15,10 @@ use Module::Load ();
use Try::Tiny; use Try::Tiny;
register_device_tab({ tag => 'snmp', label => 'SNMP', register_device_tab({ tag => 'snmp', label => 'SNMP',
render_if => sub { schema('netdisco')->resultset('DeviceBrowser')->count() } }); render_if => sub { schema(vars->{'tenant'})->resultset('DeviceBrowser')->count() } });
get '/ajax/content/device/snmp' => require_login sub { get '/ajax/content/device/snmp' => require_login sub {
my $device = try { schema('netdisco')->resultset('Device') my $device = try { schema(vars->{'tenant'})->resultset('Device')
->search_for_device( param('q') ) } ->search_for_device( param('q') ) }
or send_error('Bad Device', 404); or send_error('Bad Device', 404);
@@ -27,7 +27,7 @@ get '/ajax/content/device/snmp' => require_login sub {
}; };
ajax '/ajax/data/device/:ip/snmptree/:base' => require_login sub { ajax '/ajax/data/device/:ip/snmptree/:base' => require_login sub {
my $device = try { schema('netdisco')->resultset('Device') my $device = try { schema(vars->{'tenant'})->resultset('Device')
->find( param('ip') ) } ->find( param('ip') ) }
or send_error('Bad Device', 404); or send_error('Bad Device', 404);
@@ -41,14 +41,14 @@ ajax '/ajax/data/device/:ip/snmptree/:base' => require_login sub {
children => \0, children => \0,
state => { disabled => \1 }, state => { disabled => \1 },
icon => 'icon-search', icon => 'icon-search',
}] unless schema('netdisco')->resultset('DeviceSnapshot')->find($device->ip); }] unless schema(vars->{'tenant'})->resultset('DeviceSnapshot')->find($device->ip);
return to_json [{ return to_json [{
text => 'No MIB data. Please run `~/bin/netdisco-do loadmibs`.', text => 'No MIB data. Please run `~/bin/netdisco-do loadmibs`.',
children => \0, children => \0,
state => { disabled => \1 }, state => { disabled => \1 },
icon => 'icon-search', icon => 'icon-search',
}] unless schema('netdisco')->resultset('SNMPObject')->count(); }] unless schema(vars->{'tenant'})->resultset('SNMPObject')->count();
my $items = _get_snmp_data($device->ip, $base); my $items = _get_snmp_data($device->ip, $base);
to_json $items; to_json $items;
@@ -61,7 +61,7 @@ ajax '/ajax/data/snmp/typeahead' => require_login sub {
my $deviceonly = param('deviceonly'); my $deviceonly = param('deviceonly');
my $table = ($deviceonly ? 'DeviceBrowser' : 'SNMPObject'); my $table = ($deviceonly ? 'DeviceBrowser' : 'SNMPObject');
my @found = schema('netdisco')->resultset($table) my @found = schema(vars->{'tenant'})->resultset($table)
->search({ -or => [ oid => $term, ->search({ -or => [ oid => $term,
oid => { -like => ($term .'.%') }, oid => { -like => ($term .'.%') },
leaf => { -ilike => ('%'. $term .'%') } ], leaf => { -ilike => ('%'. $term .'%') } ],
@@ -80,14 +80,14 @@ ajax '/ajax/data/snmp/nodesearch' => require_login sub {
my $found = undef; my $found = undef;
if ($partial) { if ($partial) {
$found = schema('netdisco')->resultset('SNMPObject') $found = schema(vars->{'tenant'})->resultset('SNMPObject')
->search({ -or => [ oid => $to_match, ->search({ -or => [ oid => $to_match,
oid => { -like => ($to_match .'.%') }, oid => { -like => ($to_match .'.%') },
leaf => { -ilike => ($to_match .'%') } ] }, leaf => { -ilike => ($to_match .'%') } ] },
{ rows => 1, order_by => 'oid_parts' })->first; { rows => 1, order_by => 'oid_parts' })->first;
} }
else { else {
$found = schema('netdisco')->resultset('SNMPObject') $found = schema(vars->{'tenant'})->resultset('SNMPObject')
->search({ -or => [ oid => $to_match, ->search({ -or => [ oid => $to_match,
leaf => $to_match ] }, leaf => $to_match ] },
{ rows => 1, order_by => 'oid_parts' })->first; { rows => 1, order_by => 'oid_parts' })->first;
@@ -108,14 +108,14 @@ ajax '/ajax/data/snmp/nodesearch' => require_login sub {
}; };
ajax '/ajax/content/device/:ip/snmpnode/:oid' => require_login sub { ajax '/ajax/content/device/:ip/snmpnode/:oid' => require_login sub {
my $device = try { schema('netdisco')->resultset('Device') my $device = try { schema(vars->{'tenant'})->resultset('Device')
->find( param('ip') ) } ->find( param('ip') ) }
or send_error('Bad Device', 404); or send_error('Bad Device', 404);
my $oid = param('oid'); my $oid = param('oid');
$oid =~ m/^\.1(\.\d+)*$/ or send_error('Bad OID', 404); $oid =~ m/^\.1(\.\d+)*$/ or send_error('Bad OID', 404);
my $object = schema('netdisco')->resultset('DeviceBrowser') my $object = schema(vars->{'tenant'})->resultset('DeviceBrowser')
->with_snmp_object($device->ip)->find({ 'snmp_object.oid' => $oid }) ->with_snmp_object($device->ip)->find({ 'snmp_object.oid' => $oid })
or send_error('Bad OID', 404); or send_error('Bad OID', 404);
@@ -138,7 +138,7 @@ sub _get_snmp_data {
my @parts = grep {length} split m/\./, $base; my @parts = grep {length} split m/\./, $base;
my %meta = map { ('.'. join '.', @{$_->{oid_parts}}) => $_ } my %meta = map { ('.'. join '.', @{$_->{oid_parts}}) => $_ }
schema('netdisco')->resultset('Virtual::FilteredSNMPObject') schema(vars->{'tenant'})->resultset('Virtual::FilteredSNMPObject')
->search({}, { bind => [ ->search({}, { bind => [
$ip, $ip,
(scalar @parts + 1), (scalar @parts + 1),

View File

@@ -15,7 +15,7 @@ register_device_tab({ tag => 'vlans', label => 'VLANs', provides_csv => 1 });
get '/ajax/content/device/vlans' => require_login sub { get '/ajax/content/device/vlans' => require_login sub {
my $q = param('q'); my $q = param('q');
my $device = schema('netdisco')->resultset('Device') my $device = schema(vars->{'tenant'})->resultset('Device')
->search_for_device($q) or send_error('Bad device', 400); ->search_for_device($q) or send_error('Bad device', 400);
my @results = $device->vlans->search( my @results = $device->vlans->search(
{ vlan => { '>' => 0 } }, { order_by => 'vlan' } )->hri->all; { vlan => { '>' => 0 } }, { order_by => 'vlan' } )->hri->all;

View File

@@ -13,8 +13,8 @@ register_navbar_item({
}); });
get '/inventory' => require_login sub { get '/inventory' => require_login sub {
my $platforms = schema('netdisco')->resultset('Device')->get_platforms(); my $platforms = schema(vars->{'tenant'})->resultset('Device')->get_platforms();
my $releases = schema('netdisco')->resultset('Device')->get_releases(); my $releases = schema(vars->{'tenant'})->resultset('Device')->get_releases();
my %release_map = ( my %release_map = (
map { (join '', map {sprintf '%05s', $_} split m/(\D)/, ($_->{os_ver} || '')) => $_ } map { (join '', map {sprintf '%05s', $_} split m/(\D)/, ($_->{os_ver} || '')) => $_ }

View File

@@ -16,7 +16,7 @@ register_report(
); );
get '/ajax/content/report/apchanneldist' => require_login sub { get '/ajax/content/report/apchanneldist' => require_login sub {
my @results = schema('netdisco')->resultset('DevicePortWireless')->search( my @results = schema(vars->{'tenant'})->resultset('DevicePortWireless')->search(
{ channel => { '!=', '0' } }, { channel => { '!=', '0' } },
{ select => [ 'channel', { count => 'channel' } ], { select => [ 'channel', { count => 'channel' } ],
as => [qw/ channel ch_count /], as => [qw/ channel ch_count /],

View File

@@ -16,7 +16,7 @@ register_report(
); );
get '/ajax/content/report/apclients' => require_login sub { get '/ajax/content/report/apclients' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search( my @results = schema(vars->{'tenant'})->resultset('Device')->search(
{ 'nodes.time_last' => { '>=', \'me.last_macsuck' } }, { 'nodes.time_last' => { '>=', \'me.last_macsuck' } },
{ select => [ 'ip', 'dns', 'name', 'model', 'location' ], { select => [ 'ip', 'dns', 'name', 'model', 'location' ],
join => { 'ports' => { 'ssid' => 'nodes' } }, join => { 'ports' => { 'ssid' => 'nodes' } },

View File

@@ -20,7 +20,7 @@ get '/ajax/content/report/apradiochannelpower/data' => require_login sub {
send_error( 'Missing parameter', 400 ) send_error( 'Missing parameter', 400 )
unless ( param('draw') && param('draw') =~ /\d+/ ); unless ( param('draw') && param('draw') =~ /\d+/ );
my $rs = schema('netdisco')->resultset('Virtual::ApRadioChannelPower'); my $rs = schema(vars->{'tenant'})->resultset('Virtual::ApRadioChannelPower');
my $exp_params = expand_hash( scalar params ); my $exp_params = expand_hash( scalar params );
my $recordsTotal = $rs->count; my $recordsTotal = $rs->count;
my @data = $rs->get_datatables_data($exp_params)->hri->all; my @data = $rs->get_datatables_data($exp_params)->hri->all;
@@ -43,7 +43,7 @@ get '/ajax/content/report/apradiochannelpower' => require_login sub {
} }
else { else {
my @results my @results
= schema('netdisco')->resultset('Virtual::ApRadioChannelPower') = schema(vars->{'tenant'})->resultset('Virtual::ApRadioChannelPower')
->hri->all; ->hri->all;
return unless scalar @results; return unless scalar @results;

View File

@@ -16,7 +16,7 @@ register_report(
); );
get '/ajax/content/report/deviceaddrnodns' => require_login sub { get '/ajax/content/report/deviceaddrnodns' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search( my @results = schema(vars->{'tenant'})->resultset('Device')->search(
{ 'device_ips.dns' => undef }, { 'device_ips.dns' => undef },
{ select => [ 'ip', 'dns', 'name', 'location', 'contact' ], { select => [ 'ip', 'dns', 'name', 'location', 'contact' ],
join => [qw/device_ips/], join => [qw/device_ips/],

View File

@@ -17,7 +17,7 @@ register_report(
get '/ajax/content/report/devicebylocation' => require_login sub { get '/ajax/content/report/devicebylocation' => require_login sub {
my @results my @results
= schema('netdisco')->resultset('Device') = schema(vars->{'tenant'})->resultset('Device')
->columns( [qw/ ip dns name location vendor model /] ) ->columns( [qw/ ip dns name location vendor model /] )
->order_by( [qw/ location name ip vendor model /] )->hri->all; ->order_by( [qw/ location name ip vendor model /] )->hri->all;

View File

@@ -20,7 +20,7 @@ get '/ajax/content/report/devicednsmismatch' => require_login sub {
(my $suffix = '***:'. setting('domain_suffix')) =~ s|\Q(?^\Eu?|(?|g; (my $suffix = '***:'. setting('domain_suffix')) =~ s|\Q(?^\Eu?|(?|g;
my @results my @results
= schema('netdisco')->resultset('Virtual::DeviceDnsMismatch') = schema(vars->{'tenant'})->resultset('Virtual::DeviceDnsMismatch')
->search( undef, { bind => [ $suffix, $suffix ] } ) ->search( undef, { bind => [ $suffix, $suffix ] } )
->columns( [qw/ ip dns name location contact /] )->hri->all; ->columns( [qw/ ip dns name location contact /] )->hri->all;

View File

@@ -20,7 +20,7 @@ get '/ajax/content/report/devicepoestatus/data' => require_login sub {
send_error( 'Missing parameter', 400 ) send_error( 'Missing parameter', 400 )
unless ( param('draw') && param('draw') =~ /\d+/ ); unless ( param('draw') && param('draw') =~ /\d+/ );
my $rs = schema('netdisco')->resultset('Virtual::DevicePoeStatus'); my $rs = schema(vars->{'tenant'})->resultset('Virtual::DevicePoeStatus');
my $exp_params = expand_hash( scalar params ); my $exp_params = expand_hash( scalar params );
my $recordsTotal = $rs->count; my $recordsTotal = $rs->count;
@@ -44,7 +44,7 @@ get '/ajax/content/report/devicepoestatus' => require_login sub {
} }
else { else {
my @results my @results
= schema('netdisco')->resultset('Virtual::DevicePoeStatus') = schema(vars->{'tenant'})->resultset('Virtual::DevicePoeStatus')
->hri->all; ->hri->all;
return unless scalar @results; return unless scalar @results;

View File

@@ -17,7 +17,7 @@ register_report(
get '/ajax/content/report/duplexmismatch' => require_login sub { get '/ajax/content/report/duplexmismatch' => require_login sub {
my @results my @results
= schema('netdisco')->resultset('Virtual::DuplexMismatch')->hri->all; = schema(vars->{'tenant'})->resultset('Virtual::DuplexMismatch')->hri->all;
return unless scalar @results; return unless scalar @results;

View File

@@ -17,7 +17,7 @@ register_report(
get '/ajax/content/report/halfduplex' => require_login sub { get '/ajax/content/report/halfduplex' => require_login sub {
my @results my @results
= schema('netdisco')->resultset('DevicePort') = schema(vars->{'tenant'})->resultset('DevicePort')
->columns( [qw/ ip port name duplex /] )->search( ->columns( [qw/ ip port name duplex /] )->search(
{ up => 'up', duplex => { '-ilike' => 'half' } }, { up => 'up', duplex => { '-ilike' => 'half' } },
{ '+columns' => [qw/ device.dns device.name /], { '+columns' => [qw/ device.dns device.name /],

View File

@@ -15,7 +15,7 @@ register_report(
); );
get '/ajax/content/report/inventorybymodelbyos' => require_login sub { get '/ajax/content/report/inventorybymodelbyos' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search(undef, { my @results = schema(vars->{'tenant'})->resultset('Device')->search(undef, {
columns => [qw/vendor model os os_ver/], columns => [qw/vendor model os os_ver/],
select => [ { count => 'os_ver' } ], select => [ { count => 'os_ver' } ],
as => [qw/ os_ver_count /], as => [qw/ os_ver_count /],

View File

@@ -66,7 +66,7 @@ get '/ajax/content/report/ipinventory' => require_login sub {
# server-side to provide user feedback # server-side to provide user feedback
$limit = 8192 if $limit > 8192; $limit = 8192 if $limit > 8192;
my $rs1 = schema('netdisco')->resultset('DeviceIp')->search( my $rs1 = schema(vars->{'tenant'})->resultset('DeviceIp')->search(
undef, undef,
{ join => ['device', 'device_port'], { join => ['device', 'device_port'],
select => [ select => [
@@ -86,7 +86,7 @@ get '/ajax/content/report/ipinventory' => require_login sub {
} }
)->hri; )->hri;
my $rs2 = schema('netdisco')->resultset('NodeIp')->search( my $rs2 = schema(vars->{'tenant'})->resultset('NodeIp')->search(
undef, undef,
{ join => ['oui', 'netbios'], { join => ['oui', 'netbios'],
columns => [qw( ip mac time_first time_last dns active)], columns => [qw( ip mac time_first time_last dns active)],
@@ -99,7 +99,7 @@ get '/ajax/content/report/ipinventory' => require_login sub {
} }
)->hri; )->hri;
my $rs3 = schema('netdisco')->resultset('NodeNbt')->search( my $rs3 = schema(vars->{'tenant'})->resultset('NodeNbt')->search(
undef, undef,
{ join => ['oui'], { join => ['oui'],
columns => [qw( ip mac time_first time_last )], columns => [qw( ip mac time_first time_last )],
@@ -120,7 +120,7 @@ get '/ajax/content/report/ipinventory' => require_login sub {
if ( $never ) { if ( $never ) {
$subnet = NetAddr::IP::Lite->new('0.0.0.0/32') if ($subnet->bits ne 32); $subnet = NetAddr::IP::Lite->new('0.0.0.0/32') if ($subnet->bits ne 32);
my $rs4 = schema('netdisco')->resultset('Virtual::CidrIps')->search( my $rs4 = schema(vars->{'tenant'})->resultset('Virtual::CidrIps')->search(
undef, undef,
{ bind => [ $subnet->cidr ], { bind => [ $subnet->cidr ],
columns => [qw( ip mac time_first time_last dns active node age vendor nbname )], columns => [qw( ip mac time_first time_last dns active node age vendor nbname )],

View File

@@ -41,11 +41,11 @@ get '/ajax/content/report/moduleinventory/data' => require_login sub {
send_error( 'Missing parameter', 400 ) send_error( 'Missing parameter', 400 )
unless ( param('draw') && param('draw') =~ /\d+/ ); unless ( param('draw') && param('draw') =~ /\d+/ );
my $rs = schema('netdisco')->resultset('DeviceModule'); my $rs = schema(vars->{'tenant'})->resultset('DeviceModule');
$rs = $rs->search( { -bool => 'fru' } ) if param('fruonly'); $rs = $rs->search( { -bool => 'fru' } ) if param('fruonly');
if ( param('device') ) { if ( param('device') ) {
my @ips = schema('netdisco')->resultset('Device') my @ips = schema(vars->{'tenant'})->resultset('Device')
->search_fuzzy( param('device') )->get_column('ip')->all; ->search_fuzzy( param('device') )->get_column('ip')->all;
params->{'ips'} = \@ips; params->{'ips'} = \@ips;
@@ -87,14 +87,14 @@ get '/ajax/content/report/moduleinventory' => require_login sub {
my $has_opt = List::MoreUtils::any { param($_) } my $has_opt = List::MoreUtils::any { param($_) }
qw/device description name type model serial class/; qw/device description name type model serial class/;
my $rs = schema('netdisco')->resultset('DeviceModule'); my $rs = schema(vars->{'tenant'})->resultset('DeviceModule');
$rs = $rs->search( { -bool => 'fru' } ) if param('fruonly'); $rs = $rs->search( { -bool => 'fru' } ) if param('fruonly');
my @results; my @results;
if ( $has_opt && !request->is_ajax ) { if ( $has_opt && !request->is_ajax ) {
if ( param('device') ) { if ( param('device') ) {
my @ips = schema('netdisco')->resultset('Device') my @ips = schema(vars->{'tenant'})->resultset('Device')
->search_fuzzy( param('device') )->get_column('ip')->all; ->search_fuzzy( param('device') )->get_column('ip')->all;
params->{'ips'} = \@ips; params->{'ips'} = \@ips;

View File

@@ -41,7 +41,7 @@ get '/ajax/content/report/netbios/data' => require_login sub {
my $domain = param('domain'); my $domain = param('domain');
my $rs = schema('netdisco')->resultset('NodeNbt'); my $rs = schema(vars->{'tenant'})->resultset('NodeNbt');
my $search = $domain eq 'blank' ? '' : $domain; my $search = $domain eq 'blank' ? '' : $domain;
$rs = $rs->search( { domain => $search } ) $rs = $rs->search( { domain => $search } )
@@ -69,7 +69,7 @@ get '/ajax/content/report/netbios' => require_login sub {
my $domain = param('domain'); my $domain = param('domain');
my $rs = schema('netdisco')->resultset('NodeNbt'); my $rs = schema(vars->{'tenant'})->resultset('NodeNbt');
my @results; my @results;
if ( defined $domain && !request->is_ajax ) { if ( defined $domain && !request->is_ajax ) {

View File

@@ -16,7 +16,7 @@ register_report(
); );
get '/ajax/content/report/nodemultiips' => require_login sub { get '/ajax/content/report/nodemultiips' => require_login sub {
my @results = schema('netdisco')->resultset('Node')->search( my @results = schema(vars->{'tenant'})->resultset('Node')->search(
{}, {},
{ select => [ 'mac', 'switch', 'port' ], { select => [ 'mac', 'switch', 'port' ],
join => [qw/device ips oui/], join => [qw/device ips oui/],

View File

@@ -42,7 +42,7 @@ get '/ajax/content/report/nodevendor/data' => require_login sub {
my $vendor = param('vendor'); my $vendor = param('vendor');
my $rs = schema('netdisco')->resultset('Node'); my $rs = schema(vars->{'tenant'})->resultset('Node');
my $match = $vendor eq 'blank' ? undef : $vendor; my $match = $vendor eq 'blank' ? undef : $vendor;
@@ -78,7 +78,7 @@ get '/ajax/content/report/nodevendor' => require_login sub {
my $vendor = param('vendor'); my $vendor = param('vendor');
my $rs = schema('netdisco')->resultset('Node'); my $rs = schema(vars->{'tenant'})->resultset('Node');
my @results; my @results;
if ( defined $vendor && !request->is_ajax ) { if ( defined $vendor && !request->is_ajax ) {

View File

@@ -42,7 +42,7 @@ register_report(
get '/ajax/content/report/nodesdiscovered' => require_login sub { get '/ajax/content/report/nodesdiscovered' => require_login sub {
my $op = param('matchall') ? '-and' : '-or'; my $op = param('matchall') ? '-and' : '-or';
my @results = schema('netdisco')->resultset('Virtual::NodesDiscovered') my @results = schema(vars->{'tenant'})->resultset('Virtual::NodesDiscovered')
->search({ ->search({
$op => [ $op => [
(param('aps') ? (param('aps') ?

View File

@@ -16,7 +16,7 @@ register_report(
); );
get '/ajax/content/report/portadmindown' => require_login sub { get '/ajax/content/report/portadmindown' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search( my @results = schema(vars->{'tenant'})->resultset('Device')->search(
{ 'up_admin' => 'down' }, { 'up_admin' => 'down' },
{ select => [ 'ip', 'dns', 'name' ], { select => [ 'ip', 'dns', 'name' ],
join => [ 'ports' ], join => [ 'ports' ],

View File

@@ -16,7 +16,7 @@ register_report(
); );
get '/ajax/content/report/portblocking' => require_login sub { get '/ajax/content/report/portblocking' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search( my @results = schema(vars->{'tenant'})->resultset('Device')->search(
{ 'stp' => [ 'blocking', 'broken' ], 'up' => { '!=', 'down' } }, { 'stp' => [ 'blocking', 'broken' ], 'up' => { '!=', 'down' } },
{ select => [ 'ip', 'dns', 'name' ], { select => [ 'ip', 'dns', 'name' ],
join => ['ports'], join => ['ports'],

View File

@@ -26,8 +26,8 @@ sub _sanity_ok {
ajax '/ajax/control/report/portlog/add' => require_login sub { ajax '/ajax/control/report/portlog/add' => require_login sub {
send_error('Bad Request', 400) unless _sanity_ok(); send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
my $user = schema('netdisco')->resultset('DevicePortLog') my $user = schema(vars->{'tenant'})->resultset('DevicePortLog')
->create({ ->create({
ip => param('ip'), ip => param('ip'),
port => param('port'), port => param('port'),
@@ -45,11 +45,11 @@ ajax '/ajax/content/report/portlog' => require_login sub {
my $port = param('f'); my $port = param('f');
send_error('Bad Request', 400) unless $device and $port; send_error('Bad Request', 400) unless $device and $port;
$device = schema('netdisco')->resultset('Device') $device = schema(vars->{'tenant'})->resultset('Device')
->search_for_device($device); ->search_for_device($device);
return unless $device; return unless $device;
my $set = schema('netdisco')->resultset('DevicePortLog')->search({ my $set = schema(vars->{'tenant'})->resultset('DevicePortLog')->search({
ip => $device->ip, ip => $device->ip,
port => $port, port => $port,
}, { }, {

View File

@@ -22,7 +22,7 @@ register_report(
); );
get '/ajax/content/report/portmultinodes' => require_login sub { get '/ajax/content/report/portmultinodes' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search( my @results = schema(vars->{'tenant'})->resultset('Device')->search(
{ 'ports.remote_ip' => undef, { 'ports.remote_ip' => undef,
(param('vlan') ? (param('vlan') ?
('ports.vlan' => param('vlan'), 'nodes.vlan' => param('vlan')) : ()), ('ports.vlan' => param('vlan'), 'nodes.vlan' => param('vlan')) : ()),

View File

@@ -46,7 +46,7 @@ get '/ajax/content/report/portssid' => require_login sub {
my $ssid = param('ssid'); my $ssid = param('ssid');
my $rs = schema('netdisco')->resultset('DevicePortSsid'); my $rs = schema(vars->{'tenant'})->resultset('DevicePortSsid');
if ( defined $ssid ) { if ( defined $ssid ) {

View File

@@ -28,11 +28,11 @@ register_report(
); );
get '/ajax/content/report/portutilization' => require_login sub { get '/ajax/content/report/portutilization' => require_login sub {
return unless schema('netdisco')->resultset('Device')->count; return unless schema(vars->{'tenant'})->resultset('Device')->count;
my $age_num = param('age_num') || 3; my $age_num = param('age_num') || 3;
my $age_unit = param('age_unit') || 'months'; my $age_unit = param('age_unit') || 'months';
my @results = schema('netdisco')->resultset('Virtual::PortUtilization') my @results = schema(vars->{'tenant'})->resultset('Virtual::PortUtilization')
->search(undef, { bind => [ "$age_num $age_unit", "$age_num $age_unit", "$age_num $age_unit" ] })->hri->all; ->search(undef, { bind => [ "$age_num $age_unit", "$age_num $age_unit", "$age_num $age_unit" ] })->hri->all;
if (request->is_ajax) { if (request->is_ajax) {

View File

@@ -17,8 +17,8 @@ register_report(
); );
get '/ajax/content/report/portvlanmismatch' => require_login sub { get '/ajax/content/report/portvlanmismatch' => require_login sub {
return unless schema('netdisco')->resultset('Device')->count; return unless schema(vars->{'tenant'})->resultset('Device')->count;
my @results = schema('netdisco') my @results = schema(vars->{'tenant'})
->resultset('Virtual::PortVLANMismatch')->search({},{ ->resultset('Virtual::PortVLANMismatch')->search({},{
bind => [ setting('sidebar_defaults')->{'device_ports'}->{'p_hide1002'}->{'default'} bind => [ setting('sidebar_defaults')->{'device_ports'}->{'p_hide1002'}->{'default'}
? (1002, 1003, 1004, 1005) : (0, 0, 0, 0) ], ? (1002, 1003, 1004, 1005) : (0, 0, 0, 0) ],

View File

@@ -16,7 +16,7 @@ register_report(
); );
get '/ajax/content/report/ssidinventory' => require_login sub { get '/ajax/content/report/ssidinventory' => require_login sub {
my @results = schema('netdisco')->resultset('DevicePortSsid') my @results = schema(vars->{'tenant'})->resultset('DevicePortSsid')
->get_ssids->hri->all; ->get_ssids->hri->all;
return unless scalar @results; return unless scalar @results;

View File

@@ -40,7 +40,7 @@ get '/ajax/content/report/subnets' => require_login sub {
$start = $start . ' 00:00:00'; $start = $start . ' 00:00:00';
$end = $end . ' 23:59:59'; $end = $end . ' 23:59:59';
my @results = schema('netdisco')->resultset('Virtual::SubnetUtilization') my @results = schema(vars->{'tenant'})->resultset('Virtual::SubnetUtilization')
->search(undef,{ ->search(undef,{
bind => [ $subnet, $start, $end, $start, $subnet, $start, $start ], bind => [ $subnet, $start, $end, $start, $subnet, $start, $start ],
})->hri->all; })->hri->all;

View File

@@ -16,7 +16,7 @@ register_report(
); );
get '/ajax/content/report/vlaninventory' => require_login sub { get '/ajax/content/report/vlaninventory' => require_login sub {
my @results = schema('netdisco')->resultset('DeviceVlan')->search( my @results = schema(vars->{'tenant'})->resultset('DeviceVlan')->search(
{ 'me.description' => { '!=', 'NULL' }, { 'me.description' => { '!=', 'NULL' },
'me.vlan' => { '>' => 0 }, 'me.vlan' => { '>' => 0 },
'ports.vlan' => { '>' => 0 }, 'ports.vlan' => { '>' => 0 },

View File

@@ -72,10 +72,10 @@ get '/ajax/content/search/device' => require_login sub {
my $see_all = param('seeallcolumns'); my $see_all = param('seeallcolumns');
if ($see_all) { if ($see_all) {
$rs_columns = schema('netdisco')->resultset('Device'); $rs_columns = schema(vars->{'tenant'})->resultset('Device');
} }
else { else {
$rs_columns = schema('netdisco')->resultset('Device')->columns( $rs_columns = schema(vars->{'tenant'})->resultset('Device')->columns(
[ "ip", "dns", "name", [ "ip", "dns", "name",
"location", "model", "os_ver", "serial", "chassis_id" "location", "model", "os_ver", "serial", "chassis_id"
] ]

View File

@@ -131,7 +131,7 @@ get '/ajax/content/search/node' => require_login sub {
($using_wildcards ? \['me.mac::text ILIKE ?', $likeval] ($using_wildcards ? \['me.mac::text ILIKE ?', $likeval]
: ((!defined $mac or $mac->errstr) ? \'0=1' : ('me.mac' => $mac->as_ieee)) ); : ((!defined $mac or $mac->errstr) ? \'0=1' : ('me.mac' => $mac->as_ieee)) );
my $sightings = schema('netdisco')->resultset('Node') my $sightings = schema(vars->{'tenant'})->resultset('Node')
->search({-and => [@where_mac, @active, @times]}, { ->search({-and => [@where_mac, @active, @times]}, {
order_by => {'-desc' => 'time_last'}, order_by => {'-desc' => 'time_last'},
'+columns' => [ '+columns' => [
@@ -143,7 +143,7 @@ get '/ajax/content/search/node' => require_login sub {
join => 'device', join => 'device',
}); });
my $ips = schema('netdisco')->resultset('NodeIp') my $ips = schema(vars->{'tenant'})->resultset('NodeIp')
->search({-and => [@where_mac, @active, @times]}, { ->search({-and => [@where_mac, @active, @times]}, {
order_by => {'-desc' => 'time_last'}, order_by => {'-desc' => 'time_last'},
'+columns' => [ '+columns' => [
@@ -155,7 +155,7 @@ get '/ajax/content/search/node' => require_login sub {
join => 'oui' join => 'oui'
}); });
my $netbios = schema('netdisco')->resultset('NodeNbt') my $netbios = schema(vars->{'tenant'})->resultset('NodeNbt')
->search({-and => [@where_mac, @active, @times]}, { ->search({-and => [@where_mac, @active, @times]}, {
order_by => {'-desc' => 'time_last'}, order_by => {'-desc' => 'time_last'},
'+columns' => [ '+columns' => [
@@ -167,7 +167,7 @@ get '/ajax/content/search/node' => require_login sub {
join => 'oui' join => 'oui'
}); });
my $wireless = schema('netdisco')->resultset('NodeWireless')->search( my $wireless = schema(vars->{'tenant'})->resultset('NodeWireless')->search(
{ -and => [@where_mac, @wifitimes] }, { -and => [@where_mac, @wifitimes] },
{ order_by => { '-desc' => 'time_last' }, { order_by => { '-desc' => 'time_last' },
'+columns' => [ '+columns' => [
@@ -180,7 +180,7 @@ get '/ajax/content/search/node' => require_login sub {
} }
); );
my $rs_dp = schema('netdisco')->resultset('DevicePort'); my $rs_dp = schema(vars->{'tenant'})->resultset('DevicePort');
if ($sightings->has_rows or $ips->has_rows or $netbios->has_rows) { if ($sightings->has_rows or $ips->has_rows or $netbios->has_rows) {
my $ports = param('deviceports') my $ports = param('deviceports')
? $rs_dp->search({ -and => [@where_mac] }, { order_by => { '-desc' => 'creation' }}) : undef; ? $rs_dp->search({ -and => [@where_mac] }, { order_by => { '-desc' => 'creation' }}) : undef;
@@ -208,7 +208,7 @@ get '/ajax/content/search/node' => require_login sub {
} }
} }
my $set = schema('netdisco')->resultset('NodeNbt') my $set = schema(vars->{'tenant'})->resultset('NodeNbt')
->search_by_name({nbname => $likeval, @active, @times}); ->search_by_name({nbname => $likeval, @active, @times});
unless ( $set->has_rows ) { unless ( $set->has_rows ) {
@@ -216,11 +216,11 @@ get '/ajax/content/search/node' => require_login sub {
and my $ip = NetAddr::IP::Lite->new($node)) { and my $ip = NetAddr::IP::Lite->new($node)) {
# search_by_ip() will extract cidr notation if necessary # search_by_ip() will extract cidr notation if necessary
$set = schema('netdisco')->resultset('NodeIp') $set = schema(vars->{'tenant'})->resultset('NodeIp')
->search_by_ip({ip => $ip, @active, @times}); ->search_by_ip({ip => $ip, @active, @times});
} }
else { else {
$set = schema('netdisco')->resultset('NodeIp') $set = schema(vars->{'tenant'})->resultset('NodeIp')
->search_by_dns({ ->search_by_dns({
($using_wildcards ? (dns => $likeval) : ($using_wildcards ? (dns => $likeval) :
(dns => "${likeval}.\%", (dns => "${likeval}.\%",
@@ -233,7 +233,7 @@ get '/ajax/content/search/node' => require_login sub {
# we'll try the OUI company name as a fallback # we'll try the OUI company name as a fallback
if (param('show_vendor') and not $set->has_rows) { if (param('show_vendor') and not $set->has_rows) {
$set = schema('netdisco')->resultset('NodeIp') $set = schema(vars->{'tenant'})->resultset('NodeIp')
->with_times ->with_times
->search( ->search(
{'oui.company' => { -ilike => ''.sql_match($node)}, @times}, {'oui.company' => { -ilike => ''.sql_match($node)}, @times},

View File

@@ -45,7 +45,7 @@ get '/ajax/content/search/port' => require_login sub {
my $rs; my $rs;
if ($q =~ m/^[0-9]+$/ and $q < 4096) { if ($q =~ m/^[0-9]+$/ and $q < 4096) {
$rs = schema('netdisco')->resultset('DevicePort') $rs = schema(vars->{'tenant'})->resultset('DevicePort')
->columns( [qw/ ip port name up up_admin speed /] )->search({ ->columns( [qw/ ip port name up up_admin speed /] )->search({
"port_vlans.vlan" => $q, "port_vlans.vlan" => $q,
( param('uplink') ? () : (-or => [ ( param('uplink') ? () : (-or => [
@@ -70,7 +70,7 @@ get '/ajax/content/search/port' => require_login sub {
and (($mac->as_ieee eq '00:00:00:00:00:00') and (($mac->as_ieee eq '00:00:00:00:00:00')
or ($mac->as_ieee !~ m/$RE{net}{MAC}/))); or ($mac->as_ieee !~ m/$RE{net}{MAC}/)));
$rs = schema('netdisco')->resultset('DevicePort') $rs = schema(vars->{'tenant'})->resultset('DevicePort')
->columns( [qw/ ip port name up up_admin speed /] ) ->columns( [qw/ ip port name up up_admin speed /] )
->search({ ->search({
-and => [ -and => [

View File

@@ -27,11 +27,11 @@ get '/ajax/content/search/vlan' => require_login sub {
my $rs; my $rs;
if ( $q =~ m/^\d+$/ ) { if ( $q =~ m/^\d+$/ ) {
$rs = schema('netdisco')->resultset('Device') $rs = schema(vars->{'tenant'})->resultset('Device')
->carrying_vlan( { vlan => $q } ); ->carrying_vlan( { vlan => $q } );
} }
else { else {
$rs = schema('netdisco')->resultset('Device') $rs = schema(vars->{'tenant'})->resultset('Device')
->carrying_vlan_name( { name => $q } ); ->carrying_vlan_name( { name => $q } );
} }

View File

@@ -29,13 +29,13 @@ ajax '/ajax/portcontrol' => require_any_role [qw(admin port_control)] => sub {
? (param('action') ."-other") ? (param('action') ."-other")
: param('value')); : param('value'));
schema('netdisco')->txn_do(sub { schema(vars->{'tenant'})->txn_do(sub {
if (param('port')) { if (param('port')) {
my $act = "$action $subaction"; my $act = "$action $subaction";
$act =~ s/-other$//; $act =~ s/-other$//;
$act =~ s/^portcontrol/port/; $act =~ s/^portcontrol/port/;
schema('netdisco')->resultset('DevicePortLog')->create({ schema(vars->{'tenant'})->resultset('DevicePortLog')->create({
ip => param('device'), ip => param('device'),
port => param('port'), port => param('port'),
action => $act, action => $act,

View File

@@ -11,24 +11,24 @@ get '/report/*' => require_login sub {
my ( $domain_list, $class_list, $ssid_list, $type_list, $vendor_list ); my ( $domain_list, $class_list, $ssid_list, $type_list, $vendor_list );
if ( $tag eq 'netbios' ) { if ( $tag eq 'netbios' ) {
$domain_list = [ schema('netdisco')->resultset('NodeNbt') $domain_list = [ schema(vars->{'tenant'})->resultset('NodeNbt')
->get_distinct_col('domain') ]; ->get_distinct_col('domain') ];
} }
elsif ( $tag eq 'moduleinventory' ) { elsif ( $tag eq 'moduleinventory' ) {
$class_list = [ schema('netdisco')->resultset('DeviceModule') $class_list = [ schema(vars->{'tenant'})->resultset('DeviceModule')
->get_distinct_col('class') ]; ->get_distinct_col('class') ];
} }
elsif ( $tag eq 'portssid' ) { elsif ( $tag eq 'portssid' ) {
$ssid_list = [ schema('netdisco')->resultset('DevicePortSsid') $ssid_list = [ schema(vars->{'tenant'})->resultset('DevicePortSsid')
->get_distinct_col('ssid') ]; ->get_distinct_col('ssid') ];
} }
elsif ( $tag eq 'nodesdiscovered' ) { elsif ( $tag eq 'nodesdiscovered' ) {
$type_list = [ schema('netdisco')->resultset('DevicePort') $type_list = [ schema(vars->{'tenant'})->resultset('DevicePort')
->get_distinct_col('remote_type') ]; ->get_distinct_col('remote_type') ];
} }
elsif ( $tag eq 'nodevendor' ) { elsif ( $tag eq 'nodevendor' ) {
$vendor_list = [ $vendor_list = [
schema('netdisco')->resultset('Node')->search( schema(vars->{'tenant'})->resultset('Node')->search(
{}, {},
{ join => 'oui', { join => 'oui',
columns => ['oui.abbrev'], columns => ['oui.abbrev'],

View File

@@ -24,7 +24,7 @@ hook 'before_template' => sub {
get '/search' => require_login sub { get '/search' => require_login sub {
my $q = param('q'); my $q = param('q');
my $s = schema('netdisco'); my $s = schema(vars->{'tenant'});
if (not param('tab')) { if (not param('tab')) {
if (not $q) { if (not $q) {

View File

@@ -6,7 +6,7 @@ use Dancer::Plugin::Auth::Extensible;
get '/ajax/content/statistics' => require_login sub { get '/ajax/content/statistics' => require_login sub {
my $stats = schema('netdisco')->resultset('Statistics') my $stats = schema(vars->{'tenant'})->resultset('Statistics')
->search(undef, { order_by => { -desc => 'day' }, rows => 1 }); ->search(undef, { order_by => { -desc => 'day' }, rows => 1 });
$stats = ($stats->count ? $stats->first : undef); $stats = ($stats->count ? $stats->first : undef);

View File

@@ -11,7 +11,7 @@ ajax '/ajax/data/devicename/typeahead' => require_login sub {
return '[]' unless setting('navbar_autocomplete'); return '[]' unless setting('navbar_autocomplete');
my $q = param('query') || param('term'); my $q = param('query') || param('term');
my $set = schema('netdisco')->resultset('Device')->search_fuzzy($q); my $set = schema(vars->{'tenant'})->resultset('Device')->search_fuzzy($q);
content_type 'application/json'; content_type 'application/json';
to_json [map {$_->dns || $_->name || $_->ip} $set->all]; to_json [map {$_->dns || $_->name || $_->ip} $set->all];
@@ -19,7 +19,7 @@ ajax '/ajax/data/devicename/typeahead' => require_login sub {
ajax '/ajax/data/deviceip/typeahead' => require_login sub { ajax '/ajax/data/deviceip/typeahead' => require_login sub {
my $q = param('query') || param('term'); my $q = param('query') || param('term');
my $set = schema('netdisco')->resultset('Device')->search_fuzzy($q); my $set = schema(vars->{'tenant'})->resultset('Device')->search_fuzzy($q);
my @data = (); my @data = ();
while (my $d = $set->next) { while (my $d = $set->next) {
@@ -40,7 +40,7 @@ ajax '/ajax/data/port/typeahead' => require_login sub {
my $port = param('port1') || param('port2'); my $port = param('port1') || param('port2');
send_error('Missing device', 400) unless $dev; send_error('Missing device', 400) unless $dev;
my $device = schema('netdisco')->resultset('Device') my $device = schema(vars->{'tenant'})->resultset('Device')
->find({ip => $dev}); ->find({ip => $dev});
send_error('Bad device', 400) unless $device; send_error('Bad device', 400) unless $device;
@@ -60,7 +60,7 @@ ajax '/ajax/data/port/typeahead' => require_login sub {
ajax '/ajax/data/subnet/typeahead' => require_login sub { ajax '/ajax/data/subnet/typeahead' => require_login sub {
my $q = param('query') || param('term'); my $q = param('query') || param('term');
$q = "$q\%" if $q !~ m/\%/; $q = "$q\%" if $q !~ m/\%/;
my $nets = schema('netdisco')->resultset('Subnet')->search( my $nets = schema(vars->{'tenant'})->resultset('Subnet')->search(
{ 'me.net::text' => { '-ilike' => $q }}, { 'me.net::text' => { '-ilike' => $q }},
{ columns => ['net'], order_by => 'net' } ); { columns => ['net'], order_by => 'net' } );

View File

@@ -17,6 +17,7 @@ include_paths: []
template_paths: [] template_paths: []
site_local_files: false site_local_files: false
external_databases: [] external_databases: []
tenant_databases: []
# ------------ # ------------
# WEB FRONTEND # WEB FRONTEND

View File

@@ -76,7 +76,7 @@
<div class="navbar navbar-inverse navbar-fixed-top"> <div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner"> <div class="navbar-inner">
<div class="container"> <div class="container">
<a class="brand" href="[% uri_for('/') | none %]">Netdisco</a> <a class="brand" href="[% uri_for('') | none %]">Netdisco</a>
[% IF session.logged_in_user %] [% IF session.logged_in_user %]
<ul class="nav"> <ul class="nav">
[% FOREACH ni IN settings._navbar_items %] [% FOREACH ni IN settings._navbar_items %]
@@ -170,8 +170,29 @@
</ul> </ul>
</div> </div>
</form> </form>
[% IF settings.tenant_databases.size %]
[% SET tenant = vars.tenant %]
<ul class="nav pull-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="icon-home text-success"></i>
&nbsp;[% settings.tenant_displaynames.$tenant.displayname || 'Default' | html_entity %]
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
[% FOREACH t IN settings.tenant_displaynames.keys %]
[% NEXT IF tenant AND t == tenant %]
[% NEXT IF NOT tenant and t == 'netdisco' %]
<li><a class="nd_navtenant" href=""
data-currenttenant="[% settings.tenant_displaynames.$tenant.path || settings.tenant_displaynames.netdisco.path %]"
data-tenantpath="[% settings.tenant_displaynames.$t.path %]"
data-tenant="[% t %]">[% settings.tenant_displaynames.$t.displayname | html_entity %]</a></li>
[% END %]
</ul>
</li> <!-- /dropdown -->
</ul>
[% END %]
<ul class="nav pull-right"> <ul class="nav pull-right">
<li class="nd_navbar-text">Logged in as&nbsp;</li>
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">
[% IF user_has_role('admin') %] [% IF user_has_role('admin') %]
@@ -202,6 +223,19 @@
<script type="text/javascript"> <script type="text/javascript">
[%+ INCLUDE 'js/common.js' -%] [%+ INCLUDE 'js/common.js' -%]
// tenant change
$('.nd_navtenant').click(function(event) {
event.preventDefault();
var url = new URL(window.History.getState()['url']);
var newpath = url.pathname;
newpath = newpath.replace($(this).data('currenttenant'), "");
newpath = newpath.replace("[% settings.path %]", "/");
newpath = newpath.replace("//", "/");
newpath = $(this).data('tenantpath').concat(newpath, url.search);
window.location = newpath;
});
</script> </script>
</body> </body>