efficient device delete which does not walk nodes
This commit is contained in:
@@ -130,7 +130,15 @@ sub _set_canonical_ip {
|
|||||||
my $gone = $device->device_ips->delete;
|
my $gone = $device->device_ips->delete;
|
||||||
debug sprintf ' [%s] device - removed %s aliases',
|
debug sprintf ' [%s] device - removed %s aliases',
|
||||||
$oldip, $gone;
|
$oldip, $gone;
|
||||||
$device->delete;
|
|
||||||
|
# our special delete which is more efficient
|
||||||
|
schema('netdisco')->resultset('Device')
|
||||||
|
->search({ ip => $device->ip })->delete;
|
||||||
|
|
||||||
|
# a new row object from the old one
|
||||||
|
$device = schema('netdisco')->resultset('Device')
|
||||||
|
->new({ $device->get_columns });
|
||||||
|
|
||||||
debug sprintf ' [%s] device - deleted self', $oldip;
|
debug sprintf ' [%s] device - deleted self', $oldip;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ __PACKAGE__->add_columns(
|
|||||||
);
|
);
|
||||||
__PACKAGE__->set_primary_key("ip");
|
__PACKAGE__->set_primary_key("ip");
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.07015 @ 2012-01-07 14:20:02
|
# Created by DBIx::Class::Schema::Loader v0.07015 @ 2012-01-07 14:20:02
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:671/XuuvsO2aMB1+IRWFjg
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:671/XuuvsO2aMB1+IRWFjg
|
||||||
|
|
||||||
|
|||||||
@@ -528,4 +528,44 @@ sub with_port_count {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=head1 SPECIAL METHODS
|
||||||
|
|
||||||
|
=head2 delete( \%options? )
|
||||||
|
|
||||||
|
Overrides the built-in L<DBIx::Class> delete method to more efficiently
|
||||||
|
handle the removal or archiving of nodes.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub delete {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my $schema = $self->result_source->schema;
|
||||||
|
my $devices = $self->search(undef, { columns => 'ip' });
|
||||||
|
|
||||||
|
foreach my $set (qw/
|
||||||
|
Community
|
||||||
|
DeviceIp
|
||||||
|
DeviceVlan
|
||||||
|
DevicePower
|
||||||
|
DeviceModule
|
||||||
|
/) {
|
||||||
|
$schema->resultset($set)->search(
|
||||||
|
{ ip => { '-in' => $devices->as_query }},
|
||||||
|
)->delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
$schema->resultset('Admin')->search({
|
||||||
|
device => { '-in' => $devices->as_query },
|
||||||
|
action => { '-like' => 'queued%' },
|
||||||
|
})->delete;
|
||||||
|
|
||||||
|
$schema->resultset('DevicePort')->search(
|
||||||
|
{ ip => { '-in' => $devices->as_query }},
|
||||||
|
)->delete(@_);
|
||||||
|
|
||||||
|
# now let DBIC do its thing
|
||||||
|
return $self->next::method();
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
@@ -133,4 +133,39 @@ sub with_vlan_count {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=head1 SPECIAL METHODS
|
||||||
|
|
||||||
|
=head2 delete( \%options? )
|
||||||
|
|
||||||
|
Overrides the built-in L<DBIx::Class> delete method to more efficiently
|
||||||
|
handle the removal or archiving of nodes.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub delete {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my $schema = $self->result_source->schema;
|
||||||
|
my $ports = $self->search(undef, { columns => 'ip' });
|
||||||
|
|
||||||
|
foreach my $set (qw/
|
||||||
|
DevicePortPower
|
||||||
|
DevicePortVlan
|
||||||
|
DevicePortWireless
|
||||||
|
DevicePortSsid
|
||||||
|
DevicePortLog
|
||||||
|
/) {
|
||||||
|
$schema->resultset($set)->search(
|
||||||
|
{ ip => { '-in' => $ports->as_query }},
|
||||||
|
)->delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
$schema->resultset('Node')->search(
|
||||||
|
{ switch => { '-in' => $ports->as_query }},
|
||||||
|
)->delete(@_);
|
||||||
|
|
||||||
|
# now let DBIC do its thing
|
||||||
|
return $self->next::method();
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ __PACKAGE__->load_components(qw/
|
|||||||
+App::Netdisco::DB::ExplicitLocking
|
+App::Netdisco::DB::ExplicitLocking
|
||||||
/);
|
/);
|
||||||
|
|
||||||
=head1 search_by_mac( \%cond, \%attrs? )
|
=head1 ADDITIONAL METHODS
|
||||||
|
|
||||||
|
=head2 search_by_mac( \%cond, \%attrs? )
|
||||||
|
|
||||||
my $set = $rs->search_by_mac({mac => '00:11:22:33:44:55', active => 1});
|
my $set = $rs->search_by_mac({mac => '00:11:22:33:44:55', active => 1});
|
||||||
|
|
||||||
@@ -63,4 +65,57 @@ sub search_by_mac {
|
|||||||
->search($cond, $attrs);
|
->search($cond, $attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=head1 SPECIAL METHODS
|
||||||
|
|
||||||
|
=head2 delete( \%options? )
|
||||||
|
|
||||||
|
Overrides the built-in L<DBIx::Class> delete method to more efficiently
|
||||||
|
handle the removal or archiving of nodes.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub delete {
|
||||||
|
my $self = shift;
|
||||||
|
my ($opts) = @_;
|
||||||
|
|
||||||
|
my $schema = $self->result_source->schema;
|
||||||
|
my $nodes = $self->search(undef, { columns => 'mac' });
|
||||||
|
|
||||||
|
if (ref {} eq ref $opts
|
||||||
|
and exists $opts->{archive} and $opts->{archive}) {
|
||||||
|
|
||||||
|
foreach my $set (qw/
|
||||||
|
NodeIp
|
||||||
|
NodeNbt
|
||||||
|
NodeMonitor
|
||||||
|
Node
|
||||||
|
/) {
|
||||||
|
$schema->resultset($set)->search(
|
||||||
|
{ mac => { '-in' => $nodes->as_query }},
|
||||||
|
)->update({ active => \'false' });
|
||||||
|
}
|
||||||
|
|
||||||
|
$schema->resultset('NodeWireless')
|
||||||
|
->search({ mac => { '-in' => $nodes->as_query }})->delete;
|
||||||
|
|
||||||
|
# avoid letting DBIC delete nodes
|
||||||
|
return 0E0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foreach my $set (qw/
|
||||||
|
NodeIp
|
||||||
|
NodeNbt
|
||||||
|
NodeMonitor
|
||||||
|
NodeWireless
|
||||||
|
/) {
|
||||||
|
$schema->resultset($set)->search(
|
||||||
|
{ mac => { '-in' => $nodes->as_query }},
|
||||||
|
)->delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
# now let DBIC do its thing
|
||||||
|
return $self->next::method();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
@@ -59,6 +59,22 @@ foreach my $jobtype (keys %jobs_all, keys %jobs) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ajax '/ajax/control/admin/delete' => require_role admin => sub {
|
||||||
|
send_error('Missing device', 400) unless param('device');
|
||||||
|
|
||||||
|
my $device = NetAddr::IP::Lite->new(param('device'));
|
||||||
|
send_error('Bad device', 400)
|
||||||
|
if ! $device or $device->addr eq '0.0.0.0';
|
||||||
|
|
||||||
|
schema('netdisco')->txn_do(sub {
|
||||||
|
my $device = schema('netdisco')->resultset('Device')
|
||||||
|
->search({ip => param('device')});
|
||||||
|
|
||||||
|
# will delete everything related too...
|
||||||
|
$device->delete;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
get '/admin/*' => require_role admin => sub {
|
get '/admin/*' => require_role admin => sub {
|
||||||
my ($tag) = splat;
|
my ($tag) = splat;
|
||||||
|
|
||||||
|
|||||||
@@ -56,15 +56,7 @@ ajax '/ajax/control/admin/pseudodevice/add' => require_role admin => sub {
|
|||||||
|
|
||||||
ajax '/ajax/control/admin/pseudodevice/del' => require_role admin => sub {
|
ajax '/ajax/control/admin/pseudodevice/del' => require_role admin => sub {
|
||||||
send_error('Bad Request', 400) unless _sanity_ok();
|
send_error('Bad Request', 400) unless _sanity_ok();
|
||||||
|
forward '/ajax/control/admin/delete', { device => param('ip') };
|
||||||
schema('netdisco')->txn_do(sub {
|
|
||||||
my $device = schema('netdisco')->resultset('Device')
|
|
||||||
->find({ip => param('ip')});
|
|
||||||
|
|
||||||
$device->ports->delete;
|
|
||||||
$device->device_ips->delete;
|
|
||||||
$device->delete;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ajax '/ajax/control/admin/pseudodevice/update' => require_role admin => sub {
|
ajax '/ajax/control/admin/pseudodevice/update' => require_role admin => sub {
|
||||||
|
|||||||
@@ -85,6 +85,11 @@ div.content > div.tab-content table.nd_floatinghead thead {
|
|||||||
z-index: -1000;
|
z-index: -1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* for when we pinch h4 styling but don't want bold */
|
||||||
|
.nd_unbolden {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||||
/* styles to adjust the hero box used for homepage + login */
|
/* styles to adjust the hero box used for homepage + login */
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ var nd_save_ok = false;
|
|||||||
// user clicked or asked for port changes to be submitted via ajax
|
// user clicked or asked for port changes to be submitted via ajax
|
||||||
function port_control (e) {
|
function port_control (e) {
|
||||||
var td = $(e).closest('td'),
|
var td = $(e).closest('td'),
|
||||||
logmessage = $('#nd_portlog_log').val();
|
logmessage = $('#nd_portlog-log').val();
|
||||||
$('#nd_portlog_log').val('');
|
$('#nd_portlog-log').val('');
|
||||||
|
|
||||||
if (nd_save_ok == false) {
|
if (nd_save_ok == false) {
|
||||||
td.find('.nd_editable-cell-content').text(td.data('default'));
|
td.find('.nd_editable-cell-content').text(td.data('default'));
|
||||||
@@ -109,7 +109,7 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// to tell whether bootstrap's modal had Submit button pressed :(
|
// to tell whether bootstrap's modal had Submit button pressed :(
|
||||||
$('#ports_pane').on('click', '#nd_portlog_submit', function() {
|
$('#ports_pane').on('click', '#nd_portlog-submit', function() {
|
||||||
nd_save_ok = true;
|
nd_save_ok = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -35,10 +35,10 @@
|
|||||||
data-target="#nd_devdel-[% count %]" type="button"><i class="icon-trash text-error"></i></button>
|
data-target="#nd_devdel-[% count %]" type="button"><i class="icon-trash text-error"></i></button>
|
||||||
|
|
||||||
<div id="nd_devdel-[% count %]" class="nd_modal modal hide fade" tabindex="-1"
|
<div id="nd_devdel-[% count %]" class="nd_modal modal hide fade" tabindex="-1"
|
||||||
role="dialog" aria-labelledby="nd_devdel_label-[% count %]" aria-hidden="true">
|
role="dialog" aria-labelledby="nd_devdel-label-[% count %]" aria-hidden="true">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
||||||
<h3 id="nd_devdel_label-[% count %]">Are you sure?</h3>
|
<h3 id="nd_devdel-label-[% count %]">Are you sure?</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<blockquote>
|
<blockquote>
|
||||||
|
|||||||
@@ -54,10 +54,10 @@
|
|||||||
data-target="#nd_devdel-[% count %]" type="button"><i class="icon-trash text-error"></i></button>
|
data-target="#nd_devdel-[% count %]" type="button"><i class="icon-trash text-error"></i></button>
|
||||||
|
|
||||||
<div id="nd_devdel-[% count %]" class="nd_modal modal hide fade" tabindex="-1"
|
<div id="nd_devdel-[% count %]" class="nd_modal modal hide fade" tabindex="-1"
|
||||||
role="dialog" aria-labelledby="nd_devdel_label-[% count %]" aria-hidden="true">
|
role="dialog" aria-labelledby="nd_devdel-label-[% count %]" aria-hidden="true">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
||||||
<h3 id="nd_devdel_label-[% count %]">Are you sure?</h3>
|
<h3 id="nd_devdel-label-[% count %]">Are you sure?</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<blockquote>
|
<blockquote>
|
||||||
|
|||||||
@@ -53,10 +53,10 @@
|
|||||||
data-target="#nd_devdel-[% count %]" type="button"><i class="icon-trash text-error"></i></button>
|
data-target="#nd_devdel-[% count %]" type="button"><i class="icon-trash text-error"></i></button>
|
||||||
|
|
||||||
<div id="nd_devdel-[% count %]" class="nd_modal modal hide fade" tabindex="-1"
|
<div id="nd_devdel-[% count %]" class="nd_modal modal hide fade" tabindex="-1"
|
||||||
role="dialog" aria-labelledby="nd_devdel_label-[% count %]" aria-hidden="true">
|
role="dialog" aria-labelledby="nd_devdel-label-[% count %]" aria-hidden="true">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
||||||
<h3 id="nd_devdel_label-[% count %]">Are you sure?</h3>
|
<h3 id="nd_devdel-label-[% count %]">Are you sure?</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<blockquote>
|
<blockquote>
|
||||||
|
|||||||
@@ -109,25 +109,29 @@
|
|||||||
data-toggle="modal" data-target="#nd_devdel" type="button">Delete</button>
|
data-toggle="modal" data-target="#nd_devdel" type="button">Delete</button>
|
||||||
|
|
||||||
<div id="nd_devdel" class="nd_modal modal hide fade" tabindex="-1"
|
<div id="nd_devdel" class="nd_modal modal hide fade" tabindex="-1"
|
||||||
role="dialog" aria-labelledby="nd_devdel_label" aria-hidden="true">
|
role="dialog" aria-labelledby="nd_devdel-label" aria-hidden="true">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
||||||
<h3 id="nd_devdel_label">Confirm Delete: [% d.dns || d.ip | html_entity %]</h3>
|
<h3 id="nd_devdel-label">Confirm Delete: [% d.dns || d.ip | html_entity %]</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<ul>
|
<ul>
|
||||||
<li><p>This action is immediate and not reversible</p></li>
|
<li><p>This action is immediate and not reversible</p></li>
|
||||||
<li><p>All associated Nodes will be removed from the database</p></li>
|
<li><p>All associated Nodes may be removed from the database</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<textarea class="input-block-level" rows="2" data-form="delete"
|
<textarea id="nd_devdel-log" class="input-block-level" rows="2" data-form="delete"
|
||||||
placeholder="Enter a log message" name="log"></textarea>
|
placeholder="Enter a log message" name="log"></textarea>
|
||||||
|
<label class="checkbox">
|
||||||
|
<input id="nd_devdel-archive" type="checkbox" data-form="delete" name="archive">
|
||||||
|
<h4 class="nd_unbolden">Archive Nodes</h4>
|
||||||
|
</label>
|
||||||
<input type="hidden" data-form="delete" value="[% d.ip %]" name="device"/>
|
<input type="hidden" data-form="delete" value="[% d.ip %]" name="device"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn btn-success" data-dismiss="modal" aria-hidden="true">No !</button>
|
<button class="btn btn-success" data-dismiss="modal" aria-hidden="true">Cancel</button>
|
||||||
<button class="btn btn-danger nd_adminbutton" name="delete" data-dismiss="modal">Really Delete</button>
|
<button class="btn btn-danger nd_adminbutton" name="delete" data-dismiss="modal">Confirm</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -278,12 +278,12 @@
|
|||||||
<div id="nd_portlog" class="nd_modal nd_deep-horizon modal hide fade" tabindex="-1"
|
<div id="nd_portlog" class="nd_modal nd_deep-horizon modal hide fade" tabindex="-1"
|
||||||
role="dialog" aria-hidden="true">
|
role="dialog" aria-hidden="true">
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<textarea id="nd_portlog_log" class="input-block-level" rows="2" name="log"
|
<textarea id="nd_portlog-log" class="input-block-level" rows="2" name="log"
|
||||||
placeholder="Enter a log message"></textarea>
|
placeholder="Enter a log message"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
|
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
|
||||||
<button id="nd_portlog_submit" class="btn btn-info" data-dismiss="modal">Continue</button>
|
<button id="nd_portlog-submit" class="btn btn-info" data-dismiss="modal">Continue</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|||||||
@@ -59,6 +59,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<div class="span4 alert alert-info">No devices found. Do you need to run a Discover?</div>
|
<div class="span4 alert alert-info">No devices found. Do you need to run a
|
||||||
|
<a href="[% uri_for('/') %]">Discover?</a></div>
|
||||||
[% END %]
|
[% END %]
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -104,12 +104,12 @@
|
|||||||
,url: uri_base + '/ajax/control/admin/' + mode
|
,url: uri_base + '/ajax/control/admin/' + mode
|
||||||
,data: tr.find('input[data-form="' + mode + '"],textarea[data-form="' + mode + '"]').serializeArray()
|
,data: tr.find('input[data-form="' + mode + '"],textarea[data-form="' + mode + '"]').serializeArray()
|
||||||
,success: function() {
|
,success: function() {
|
||||||
toastr.info('Queued '+ mode +' for device '+ tr.data('for-device'));
|
toastr.info('Requested '+ mode +' for device '+ tr.data('for-device'));
|
||||||
}
|
}
|
||||||
// skip any error reporting for now
|
// skip any error reporting for now
|
||||||
// TODO: fix sanity_ok in Netdisco Web
|
// TODO: fix sanity_ok in Netdisco Web
|
||||||
,error: function() {
|
,error: function() {
|
||||||
toastr.error('Failed to queue '+ mode +' for device '+ tr.data('for-device'));
|
toastr.error('Failed to '+ mode +' for device '+ tr.data('for-device'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -122,4 +122,10 @@
|
|||||||
$('#ports_pane').on('hidden', '.nd_modal', function () {
|
$('#ports_pane').on('hidden', '.nd_modal', function () {
|
||||||
$(this).toggleClass('nd_deep-horizon');
|
$(this).toggleClass('nd_deep-horizon');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// clear any values in the delete confirm dialog
|
||||||
|
$('#details_pane').on('hidden', '.nd_modal', function () {
|
||||||
|
$('#nd_devdel-log').val('');
|
||||||
|
$('#nd_devdel-archive').attr('checked', false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user