efficient device delete which does not walk nodes

This commit is contained in:
Oliver Gorwits
2013-09-02 21:27:22 +01:00
parent 5807fd0323
commit be806d5ab1
16 changed files with 193 additions and 32 deletions

View File

@@ -130,7 +130,15 @@ sub _set_canonical_ip {
my $gone = $device->device_ips->delete;
debug sprintf ' [%s] device - removed %s aliases',
$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;
});

View File

@@ -78,7 +78,6 @@ __PACKAGE__->add_columns(
);
__PACKAGE__->set_primary_key("ip");
# 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

View File

@@ -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;

View File

@@ -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;

View File

@@ -8,7 +8,9 @@ __PACKAGE__->load_components(qw/
+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});
@@ -63,4 +65,57 @@ sub search_by_mac {
->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;

View File

@@ -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 {
my ($tag) = splat;

View File

@@ -56,15 +56,7 @@ ajax '/ajax/control/admin/pseudodevice/add' => require_role admin => sub {
ajax '/ajax/control/admin/pseudodevice/del' => require_role admin => sub {
send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub {
my $device = schema('netdisco')->resultset('Device')
->find({ip => param('ip')});
$device->ports->delete;
$device->device_ips->delete;
$device->delete;
});
forward '/ajax/control/admin/delete', { device => param('ip') };
};
ajax '/ajax/control/admin/pseudodevice/update' => require_role admin => sub {

View File

@@ -85,6 +85,11 @@ div.content > div.tab-content table.nd_floatinghead thead {
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 */

View File

@@ -4,8 +4,8 @@ var nd_save_ok = false;
// user clicked or asked for port changes to be submitted via ajax
function port_control (e) {
var td = $(e).closest('td'),
logmessage = $('#nd_portlog_log').val();
$('#nd_portlog_log').val('');
logmessage = $('#nd_portlog-log').val();
$('#nd_portlog-log').val('');
if (nd_save_ok == false) {
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 :(
$('#ports_pane').on('click', '#nd_portlog_submit', function() {
$('#ports_pane').on('click', '#nd_portlog-submit', function() {
nd_save_ok = true;
});

View File

@@ -35,10 +35,10 @@
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"
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">
<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 class="modal-body">
<blockquote>

View File

@@ -54,10 +54,10 @@
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"
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">
<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 class="modal-body">
<blockquote>

View File

@@ -53,10 +53,10 @@
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"
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">
<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 class="modal-body">
<blockquote>

View File

@@ -109,25 +109,29 @@
data-toggle="modal" data-target="#nd_devdel" type="button">Delete</button>
<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">
<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 class="modal-body">
<blockquote>
<ul>
<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>
</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>
<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"/>
</div>
<div class="modal-footer">
<button class="btn btn-success" data-dismiss="modal" aria-hidden="true">No !</button>
<button class="btn btn-danger nd_adminbutton" name="delete" data-dismiss="modal">Really Delete</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">Confirm</button>
</div>
</div>
</td>

View File

@@ -278,12 +278,12 @@
<div id="nd_portlog" class="nd_modal nd_deep-horizon modal hide fade" tabindex="-1"
role="dialog" aria-hidden="true">
<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>
</div>
<div class="modal-footer">
<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>
[% END %]

View File

@@ -59,6 +59,7 @@
</div>
</div>
[% 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 %]
</div>

View File

@@ -104,12 +104,12 @@
,url: uri_base + '/ajax/control/admin/' + mode
,data: tr.find('input[data-form="' + mode + '"],textarea[data-form="' + mode + '"]').serializeArray()
,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
// TODO: fix sanity_ok in Netdisco Web
,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 () {
$(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);
});
});