Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
506808b
Initial js for batch update
church29 Nov 1, 2013
55bffaf
Setup js to sent post data to batch_update
church29 Nov 1, 2013
f3c072b
Implemented updating range for dynamic interfaces
church29 Nov 2, 2013
cd50ea2
Fixed comment in js, added make
church29 Nov 23, 2013
7dc4d62
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Nov 23, 2013
b5a4315
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Nov 26, 2013
79f10c2
Dont display bulk update form if not objects in ctnr
church29 Nov 27, 2013
475b0c8
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Nov 27, 2013
138be46
Added range type selector for batch update form
church29 Nov 27, 2013
971c0db
range_type now submits along with the form through ajax
church29 Nov 28, 2013
18e329a
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Dec 2, 2013
3009ab1
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Dec 3, 2013
c4a6ca4
Update batch_update to handle range_type not being selected
church29 Dec 3, 2013
8f95e46
Merge branch 'Batch_Update' of https://github.com/church29/cyder into…
church29 Dec 3, 2013
1366a6c
Can now filter ranges by type
church29 Dec 3, 2013
0d4928d
Added url for get_ranges
church29 Dec 4, 2013
7781b05
Refactor interface/views
church29 Dec 4, 2013
99c34de
Can now migrate static interfaces between static ranges
church29 Dec 5, 2013
ee42993
Added site to batch update form
church29 Dec 5, 2013
1416495
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Dec 10, 2013
79aca71
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Dec 30, 2013
17ecf4d
A little refactoring to make batch update more robust
church29 Dec 30, 2013
a3b2c69
Fixed batch update not working if site is not selected
church29 Dec 30, 2013
fc05351
Can now migrate static interfaces to dynamic interfaces
church29 Dec 30, 2013
30dfdcd
can now migrate from dynamic interfaces to static interfaces
church29 Dec 31, 2013
96f9a4a
Fixed issue with interfaces being assigned the same ip and not valida…
church29 Jan 3, 2014
36ed24f
Slight adjustment to batch update form logic
church29 Jan 11, 2014
eff5007
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Jan 28, 2014
46bf81e
Updates after merge
church29 Jan 28, 2014
005da6b
More fixes after merge
church29 Jan 28, 2014
937a73e
refactored batch_update
church29 Feb 4, 2014
6031a13
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Feb 4, 2014
7ac59f0
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Feb 10, 2014
21286c1
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Feb 24, 2014
95d9011
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Apr 3, 2014
a28ec9c
Fix issue with enable batch update mode not showing up on interface l…
church29 Apr 3, 2014
580099a
Fix issue with retrieving model
church29 Apr 4, 2014
4dc808b
Handle issues with get_model
church29 Apr 26, 2014
3c48c91
Merge branch 'master' of https://github.com/OSU-Net/cyder into Batch_…
church29 Jan 22, 2015
f7e16ee
Fix error due to missing endif tag
church29 Jan 22, 2015
2e609e6
Minor bug fixes
church29 Jan 22, 2015
7fdeb9f
Light formatting
church29 Jan 22, 2015
8832fad
Remove accidentally added imgs
church29 Jan 23, 2015
bbe4840
Use already created get_ranges
church29 Jan 27, 2015
53144e5
Progress on refactoring batch_update
church29 Feb 2, 2015
fc43158
Fix args for batch_update sub functions
church29 Feb 3, 2015
696f7cc
Switch from .post to .ajax
church29 Feb 3, 2015
225ec4f
Dont manually call full clean
church29 Feb 3, 2015
2564b20
Styling for select all checkbox
church29 Feb 3, 2015
b0a7fda
Add exit batch update mode link and remove enable checkbox
church29 Feb 16, 2015
25ec99d
Increase size of checkboxes in batch-update table
church29 Feb 16, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cyder/base/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ def cy_view(request, template, pk=None, obj_type=None):
Klass, FormKlass = get_klasses(obj_type)
obj = get_object_or_404(Klass, pk=pk) if pk else None
form = None
batchInterfaceForm = None
if request.method == 'POST':
object_table = None
page_obj = None
Expand Down Expand Up @@ -190,6 +191,11 @@ def cy_view(request, template, pk=None, obj_type=None):
page_obj = make_paginator(request, do_sort(request, object_list), 50)
object_table = tablefy(page_obj, request=request)

if obj_type in ['static_interface', 'dynamic_interface']:
from cyder.cydhcp.interface.forms import BatchInterfaceForm
batchInterfaceForm = BatchInterfaceForm()
batchInterfaceForm.make_usable(request)

if isinstance(form, UsabilityFormMixin):
form.make_usable(request)

Expand All @@ -201,6 +207,7 @@ def cy_view(request, template, pk=None, obj_type=None):
'obj_type': obj_type,
'pretty_obj_type': Klass.pretty_type,
'pk': pk,
'batchInterfaceForm': batchInterfaceForm,
})


Expand Down
11 changes: 11 additions & 0 deletions cyder/cydhcp/interface/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django import forms

from cyder.cydhcp.range.models import Range
from cyder.base.mixins import UsabilityFormMixin


class BatchInterfaceForm(forms.Form, UsabilityFormMixin):
range_type = forms.ChoiceField(
widget=forms.RadioSelect,
choices=(('static', 'Static'), ('dynamic', 'Dynamic')))
range = forms.ModelChoiceField(queryset=Range.objects.all())
5 changes: 4 additions & 1 deletion cyder/cydhcp/interface/urls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from django.conf.urls.defaults import patterns, url

from cyder.cydhcp.interface.views import is_last_interface
from cyder.cydhcp.interface.views import batch_update, batch_update_get_ranges

urlpatterns = patterns(
'',
url(r'^last_interface/', is_last_interface, name='is_last_interface'),
url(r'^batch_update/', batch_update, name='batch_update'),
url(r'^batch_update_get_ranges/', batch_update_get_ranges,
name='batch_update_get_ranges'),
)
130 changes: 128 additions & 2 deletions cyder/cydhcp/interface/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from django.db.models.loading import get_model
from django.shortcuts import get_object_or_404
from django.core.exceptions import ValidationError
from django.shortcuts import get_object_or_404, redirect
from django.http import HttpResponse

from cyder.cydhcp.interface.dynamic_intr.models import DynamicInterface
from cyder.cydhcp.interface.static_intr.models import StaticInterface

from cyder.cydhcp.range.range_usage import range_usage
from cyder.cydhcp.network.utils import get_ranges
import json


Expand All @@ -19,3 +21,127 @@ def is_last_interface(request):
last_interface = True

return HttpResponse(json.dumps({'last_interface': last_interface}))


def batch_update_get_ranges(request):
if not request.POST:
return redirect(request.META.get('HTTP_REFERER', ''))
ranges = []
ctnr = request.session['ctnr']
range_type = request.POST.get('range_type', None)
if range_type:
range_type = [range_type[:2]]
range_qs = get_ranges([], ctnr, range_type, all_ranges=True)
else:
range_qs = get_ranges([], ctnr, all_ranges=True)

for n, rng in enumerate(range_qs):
ranges.append([rng.id, rng.__str__()])

return HttpResponse(json.dumps({'ranges': ranges}))


def batch_update_same_type(rng, ip, intr, intr_type):
if 'static' in intr_type:
intr.ip_str = str(ip)
intr.ip_type = rng.ip_type
else:
intr.range = rng

return intr



def batch_update_different_type(rng, ip, intr, intr_type):
new_intr_type = 'staticdynamicinterface'.replace(
intr_type, '')
NewInterface = get_model('cyder', new_intr_type)
kwargs = {'mac': intr.mac, 'dhcp_enabled': intr.dhcp_enabled,
'ctnr': intr.ctnr, 'workgroup': intr.workgroup,
'system': intr.system}
if 'static' in new_intr_type:
label = '{0}-{1}'.format(intr.system.name, intr.mac)
kwargs.update({'ip_str': str(ip), 'ip_type': rng.ip_type,
'dns_enabled': True, 'domain': rng.domain,
'label': label})
else:
kwargs.update({'range': rng})

return NewInterface(**kwargs)


def batch_update(request):
if not request.POST:
return redirect(request.META.get('HTTP_REFERER', ''))

for field in ['range', 'range_type', 'interfaces']:
if not request.POST.get(field, None):
field = ' '.join(field.split('_'))
return HttpResponse(json.dumps({
'error': 'Please select {0}'.format(field)}))

Range = get_model('cyder', 'range')
rng_qs = Range.objects.filter(id=request.POST['range'])
if rng_qs.exists():
rng = rng_qs.get()
else:
return HttpResponse(json.dumps({
'error': 'That range does not exist'}))

success = True
ip = None
start_lower = None
intr_type = ('').join(request.POST['interface_type'].split()[:-1])
new_intrs = []
same_type = intr_type[:2] == rng.range_type
Interface = get_model('cyder', intr_type + 'interface')
interfaces = request.POST['interfaces'].split(',')
interface_qs = Interface.objects.filter(pk__in=interfaces)

if rng.range_type == 'st':
used_ips, _ = range_usage(
rng.start_lower, rng.end_lower, rng.ip_type)
if (len(interfaces) >
(((rng.end_lower - rng.start_lower) + 1) - len(used_ips))):
return HttpResponse(json.dumps({
'error': 'Range does not have enough space for selected '
'interfaces'}))

for intr in interface_qs:
if rng.range_type == 'st':
if ip:
start_lower = ip._ip + 1

ip = rng.get_next_ip(start_lower=start_lower)

if same_type:
new_intr = batch_update_same_type(rng, ip, intr, intr_type)

else:
new_intr = batch_update_different_type(rng, ip, intr, intr_type)

new_intrs.append(new_intr)

if same_type:
for intr in new_intrs:
intr.save()
else:
for intr in new_intrs:
try:
intr.save()
except ValidationError as e:
success = False
break

if success:
interface_qs.delete()
rng.save()
else:
for intr in new_intrs:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might consider rolling back the transaction here instead of manually deleting things. If not, you need to at least handle ValidationErrors, although I'm not sure how that would work.

intr.delete()

rng.save()
return HttpResponse(json.dumps({
'error': 'Batch update was unsuccessful: {0}'.format(str(e))}))

return HttpResponse(json.dumps({'success': True}))
9 changes: 6 additions & 3 deletions cyder/cydhcp/range/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,19 +371,22 @@ def get_usage(self):

return usage

def get_next_ip(self):
def get_next_ip(self, start_lower=None):
"""Finds the most appropriate IP address within a range. If it can't
find an IP it returns None. If it finds an IP it returns an IPv4Address
object.

:returns: ipaddr.IPv4Address
"""
if self.network.ip_type != '4':
if not start_lower:
start_lower = self.start_lower

if self.network and self.network.ip_type != '4':
return None
elif self.ip_type != '4':
return None

ip = find_free_ip(self.start_lower, self.end_lower, ip_type='4')
ip = find_free_ip(start_lower, self.end_lower, ip_type='4')
if ip:
return ip
else:
Expand Down
8 changes: 8 additions & 0 deletions cyder/templates/base/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@
</a>
</div>
</div>
<div class="batch-update">
{% if pretty_obj_type in ["static interface", "dynamic interface"] %}
<form id="enable-batch-update">
<input type="checkbox" name="batch" id="enable-batch-check">
<label for="enable-batch-check">Enter batch update mode</label>
</form>
{% endif %}
</div>
{% endif %}
{% endif %}

Expand Down
18 changes: 18 additions & 0 deletions cyder/templates/cydhcp/cydhcp_view.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
Create {{ pretty_obj_type }}
</a>
{% endif %}
{% if batchInterfaceForm %}
<a id="batch_update_btn" style="display:none" class="btn submit c">Update Interfaces</a>
{% endif %}
{% endif %}
{% endblock %}

Expand Down Expand Up @@ -55,6 +58,21 @@ <h2 id="form-title">{{ 'Updating ' if obj else 'Creating ' + pretty_obj_type }}<
</form>
</div>
{% endif %}
{% if batchInterfaceForm %}
<div class="hidden" id="batch-form">
<form class="form" method="POST">
<h2 id="form-title">Batch update for selected interfaces</h2>
<div class="inner-form" id="batch-hidden-inner-form">
{{ batchInterfaceForm.as_p() }}
</div>
<div class="form-btns">
<hr>
<a class="btn c" id="batch-submit">Update</a>
<a class="btn cancel c" id="batch-cancel">Cancel</a>
</div>
</form>
</div>
{% endif %}
{% if obj_type == 'range' %}
{{ js('rangeform') }}
{% endif %}
Expand Down
17 changes: 16 additions & 1 deletion media/css/tables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ table.table {
top: 2px;
}
td, th {
vertical-align: middle;
padding: 5px 0;
}
thead {
Expand Down Expand Up @@ -123,6 +124,20 @@ table {
}
}
.editable-grid {
clear: both;
float: right;
margin-right: 17px;
}
.batch-update {
clear: both;
float: right;
margin-right: 1.5%;
margin-right: 10px;
}
.batch-update-checkbox {
width: 15px;
height: 15px;
}
#selectAll {
margin-left: 5px;
vertical-align: middle;
}
Loading