Changeset 6357
- Timestamp:
- Nov 2, 2008, 9:49:33 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Makefile
r6353 r6357 48 48 batch: clean debug-init run 49 49 #Intended usage for batch runs only e.g. no debug server 50 51 52 -
trunk/exodus/models.py
r6347 r6357 37 37 def as_list(self): 38 38 meta = self._meta 39 values = [(f.verbose_name, getattr(self, f.attname)) for f in meta.local_fields if f.verbose_name not in ( 'ID')] 39 values = [(f.verbose_name, getattr(self, f.attname)) \ 40 for f in meta.local_fields if f.verbose_name not in ( 'ID')] 40 41 return values 41 42 … … 49 50 class Location(ExtendedModel): 50 51 description = models.CharField(max_length=200, unique=True) 51 Longitude = models.DecimalField(max_digits=8,decimal_places=6)52 Latitude = models.DecimalField(max_digits=8,decimal_places=6)52 longitude = models.DecimalField(max_digits=8,decimal_places=6) 53 latitude = models.DecimalField(max_digits=8,decimal_places=6) 53 54 54 55 class Meta: … … 98 99 class Interface(ExtendedModel): 99 100 node = models.ForeignKey(Node) 100 type = models.CharField(max_length=10, choices=INTERFACE_TYPE_CHOICES, default=1) 101 iface = models.CharField(max_length=10, verbose_name="interface", default='eth0') 101 type = models.CharField(max_length=10, choices=INTERFACE_TYPE_CHOICES, \ 102 default=1) 103 iface = models.CharField(max_length=10, verbose_name="interface", \ 104 default='eth0') 102 105 ip = models.IPAddressField(unique=True) 103 106 netmask = models.IntegerField(default=30) -
trunk/exodus/settings.py
r6351 r6357 12 12 MANAGERS = ADMINS 13 13 14 # Nodes get a /24 15 MASTERIP_NETMASK = 24 16 14 17 # Master super path, set to current working path 15 EXODUS_ROOT = '/srv/wleiden/exodus/trunk' 18 EXODUS_ROOT = os.path.dirname(__file__) 19 # EXODUS_ROOT = '/srv/wleiden/exodus/trunk' 16 20 17 21 # Whether to find static files which are going to be served by django if running static mode 18 EXODUS_STATIC_ROOT = EXODUS_ROOT + '/exodus/static' 22 EXODUS_STATIC_ROOT = os.path.join(EXODUS_ROOT, 'static') 23 #EXODUS_STATIC_ROOT = EXODUS_ROOT + 'exodus/static' 19 24 20 25 DATABASE_ENGINE = 'sqlite3' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'. 21 DATABASE_NAME = EXODUS_ROOT + '/exodus.db' # Or path to database file if using sqlite3. 26 DATABASE_NAME = os.path.join(EXODUS_ROOT, 'exodus.db') 27 #DATABASE_NAME = EXODUS_ROOT + '/exodus.db' # Or path to database file if using sqlite3. 22 28 DATABASE_USER = '' # Not used with sqlite3. 23 29 DATABASE_PASSWORD = '' # Not used with sqlite3. -
trunk/exodus/templatetags/network.py
r6257 r6357 10 10 self.subnet = subnet 11 11 def render(self, context): 12 return (wllogic.getNetwork(resolve_variable(self.address, context),resolve_variable(self.subnet,context))) 12 return (wllogic.getNetwork(resolve_variable(self.address, context), \ 13 resolve_variable(self.subnet,context))) 13 14 14 15 class BroadcastNode(template.Node): … … 17 18 self.subnet = subnet 18 19 def render(self, context): 19 return (wllogic.getBroadcast(resolve_variable(self.address, context),resolve_variable(self.subnet,context))) 20 return (wllogic.getBroadcast(resolve_variable(self.address, context), \ 21 resolve_variable(self.subnet,context))) 20 22 21 23 @register.tag … … 25 27 tag_name, address, subnet = token.split_contents() 26 28 except ValueError: 27 raise template.TemplateSyntaxError, "%r tag requires a two arguments" % token.contents.split()[0] 29 raise template.TemplateSyntaxError, "%r tag requires a two arguments" \ 30 % token.contents.split()[0] 28 31 return NetworkNode(address, subnet) 29 32 … … 34 37 tag_name, address, subnet = token.split_contents() 35 38 except ValueError: 36 raise template.TemplateSyntaxError, "%r tag requires a two arguments" % token.contents.split()[0] 39 raise template.TemplateSyntaxError, "%r tag requires a two arguments" \ 40 % token.contents.split()[0] 37 41 return BroadcastNode(address, subnet) 38 42 … … 40 44 def subnet(value): 41 45 return wllogic.getSubnet(value) 42 -
trunk/exodus/tests.py
r6354 r6357 12 12 #Set up the database 13 13 self.olddbname = settings.DATABASE_NAME 14 self.dbname = connection.creation.create_test_db( )14 self.dbname = connection.creation.create_test_db(0) 15 15 16 16 def tearDown(self): 17 connection.creation.destroy_test_db(self.olddbname )17 connection.creation.destroy_test_db(self.olddbname, 0) 18 18 19 19 def test_addlocation(self): 20 post_data = {'description': 'JohnLaan2', ' Longitude': '34.55', \21 ' Latitude' : '44.55', 'pro/ceed': 'OK, proceed'}22 response = self.client.post('/add/ Location/new/', post_data)20 post_data = {'description': 'JohnLaan2', 'longitude': '34.55', \ 21 'latitude' : '44.55', 'pro/ceed': 'OK, proceed'} 22 response = self.client.post('/add/location/new/', post_data) 23 23 24 24 self.failUnlessEqual(response.status_code, 200) … … 33 33 34 34 class wllogic(unittest.TestCase): 35 def setUp(self): 36 #Set up the client 37 self.client = Client() 38 39 #Set up the database 40 self.olddbname = settings.DATABASE_NAME 41 self.dbname = connection.creation.create_test_db(0) 42 43 def tearDown(self): 44 connection.creation.destroy_test_db(self.olddbname, 0) 45 35 46 def test_new_SSID_name(self): 36 node = {} 37 node['name'] = 'testnode' 38 #XXX figure out node.name = 'testnode' and node.network.name='iets' 47 class node(object): 48 name = 'CeTIM' 49 class network(object): 50 name = 'wleiden.net' 51 nic = 'ath0' 52 desc = '2cope' 53 from exodus.wllogic import newSSIDName 54 ssid = newSSIDName(node(), nic, desc) 55 56 self.failUnless(ssid, '2cope-ath0.CeTIM.wleiden.net') 39 57 40 58 def test_parse_show_addr(self): … … 61 79 valid_subnet = netmask2subnet(30) 62 80 self.failUnlessEqual(str(valid_subnet), '17179869180') 81 82 def test_getSubnet(self): 83 from wllogic import getSubnet 84 self.failUnlessRaises(ValueError, getSubnet, -1) 85 self.failUnlessRaises(ValueError, getSubnet, 33) 86 87 valid_netmask = getSubnet(30) 88 self.failUnless(valid_netmask, '255.255.255.252') 89 90 def test_network(self): 91 from wllogic import network 92 from wllogic import showaddr 93 network_addr = showaddr(network('172.18.5.10', 24)) 94 self.failUnlessEqual(network_addr, '172.18.5.0') 63 95 96 def test_broadcast(self): 97 from wllogic import broadcast 98 from wllogic import showaddr 99 100 broadcast_addr = showaddr(broadcast('172.16.5.232', 24)) 101 self.failUnlessEqual(broadcast_addr, '172.16.5.255') 102 103 self.failUnlessRaises(ValueError, broadcast, '172.16.5.1', -1) 104 self.failUnlessRaises(ValueError, broadcast, '172.16.5.1', 33) 105 106 def test_getNetwork(self): 107 from wllogic import getNetwork 108 network_addr = getNetwork('172.17.2.2', 30) 109 self. failUnlessEqual(network_addr, '172.17.2.0') 110 111 self.failUnlessRaises(ValueError, getNetwork, '172.17.2.0', -1) 112 self.failUnlessRaises(ValueError, getNetwork, '172.17.2.0', 33) 113 114 def test_getBroadcast(self): 115 from wllogic import getBroadcast 116 broadcast_addr = getBroadcast('172.17.2.2', 24) 117 self.failUnlessEqual(broadcast_addr, '172.17.2.255') 118 119 self.failUnlessRaises(ValueError, getBroadcast, '172.17.2.0', -1) 120 self.failUnlessRaises(ValueError, getBroadcast, '172.17.2.0', 33) 121 122 def test_freeMasterIP(self): 123 from wllogic import freeMasterIP 124 from exodus.models import Node, Network 125 126 node = Node.objects.create(location_id = 1, \ 127 masterip = '172.16.0.1', name = 'testnode') 128 network = Network.objects.get(pk=1) 129 ip = freeMasterIP(network) 130 self.failIfEqual(ip, '172.16.0.0') 131 self.failUnlessEqual(ip, '172.16.1.0') 132 133 def test_freePublicAPIP(self): 134 from wllogic import freePublicAPIP 135 self.fail('test not implemented') 136 137 def test_freeInterlinkIP(self): 138 from wllogic import freeInterlinkIP 139 self.fail('Test not implemented') 140 141 def test_addInterlinkIP(self): 142 from wllogic import addInterlinkIP 143 self.fail('Test not implemented') 144 64 145 def suite(): 65 146 s = unittest.TestSuite() -
trunk/exodus/urls.py
r6351 r6357 15 15 urlpatterns = patterns('', 16 16 # generic view 17 url(r'^$', 'exodus.urls.direct_to_template', {'template': 'index.html'}, "root"), 17 url(r'^$', 'exodus.urls.direct_to_template', {'template': 'index.html'}, \ 18 "root"), 18 19 (r'^view/nodelist/$', 'exodus.views.viewNodelist'), 19 20 (r'^view/list/(?P<model>.+)/$', 'exodus.views.viewList'), -
trunk/exodus/views.py
r6347 r6357 11 11 12 12 from exodus.models import * 13 from exodus.wllogic import freeMasterIP, newSSIDName, addInterlinkIP, freeInterlinkIP, freePublicAPIP 14 15 def pdebug(level, message): 16 if level > 0: 17 print "DEBUG [%s] %s" % (level, message) 18 19 class GenericHandler(): 20 """Conventions used: type has to to the same name as the dependency object, delet template is named delete<type>.html""" 13 from exodus.wllogic import freeMasterIP, newSSIDName, addInterlinkIP, \ 14 freeInterlinkIP, freePublicAPIP 15 16 from exodus.utils import pdebug 17 18 class GenericHandler(object): 19 """Conventions used: type has to to the same name as the dependency 20 object, delet template is named delete<type>.html 21 """ 21 22 def __init__(self, request, mode): 22 23 pdebug(100, "Function: GenericHandler.__init__") … … 50 51 if self.form.is_valid(): 51 52 pdebug(100, "Form valid") 52 # Set response on forehand, to allow override in procedure 53 # Set response on forehand, to allow override \ 54 # in procedure 53 55 try: 54 self.response = HttpResponseRedirect(reverse('exodus.views.viewNode', args=[self.node.name])) 56 self.response = HttpResponseRedirect(reverse( \ 57 'exodus.views.viewNode', args=[self.node.name])) 55 58 except (AttributeError, NoReverseMatch): 56 self.response = HttpResponseRedirect(reverse('exodus.views.viewNodelist')) 59 self.response = HttpResponseRedirect(reverse( \ 60 'exodus.views.viewNodelist')) 57 61 58 62 #Checking whether data did change … … 61 65 for key,value in _instance.items(): 62 66 if value != _oldInstance[key]: 63 pdebug(100, "Key %s changed value '%s' -> '%s'" % (key, _oldInstance[key], value)) 67 pdebug(100, "Key %s changed value '%s' -> '%s'"\ 68 % (key, _oldInstance[key], value)) 64 69 self.is_changed[key] = value 65 70 … … 75 80 except ValueError, message: 76 81 self.response = render_to_response('genericForm.html', { 77 'form': self.form, 'message' : message, 'title' : self.title, 78 'mode' : mode, 'type' : type, 'object': self.object, 82 'form': self.form, 'message' : message, 83 'title' : self.title, 'mode' : mode, 84 'type' : type, 'object': self.object, 79 85 'delInclude' : "delete" + type.capitalize() + ".html", 80 86 'addInclude' : "add" + type.capitalize() + ".html", … … 83 89 message = 'Please edit and submit' 84 90 85 # Dirty? hack to allow initial form to be filled with date for GET request, no errors raised 91 # Dirty? hack to allow initial form to be filled with date \ 92 # for GET request, no errors raised 86 93 if request.GET and mode == 'add': 87 94 self.form = formClass(request.GET, instance=self.object) … … 108 115 pdebug(100, "Function: GenericHandler._delete") 109 116 self.object.delete() 110 self.response = HttpResponseRedirect(reverse('exodus.views.viewNode', args=[self.node.name])) 117 self.response = HttpResponseRedirect(reverse('exodus.views.viewNode',\ 118 args=[self.node.name])) 111 119 112 120 def _cancel(self): 113 121 pdebug(100, "Function: GenericHandler._cancel") 114 self.response = HttpResponseRedirect(reverse('exodus.views.viewNode', args=[self.node.name])) 122 self.response = HttpResponseRedirect(reverse('exodus.views.viewNode',\ 123 args=[self.node.name])) 115 124 #self.response = HttpResponseRedirect(reverse('exodus.views.viewNodelist')) 116 125 … … 136 145 self.publicAP = PublicAP(iface=self.interface) 137 146 else: 138 self.publicAP = PublicAP.objects.get(iface=self.interface, pk=publicAP) 139 GenericHandler.__init__(self, request, mode) 140 147 self.publicAP = PublicAP.objects.get(iface=self.interface, \ 148 pk=publicAP) 149 super(PublicAPHandler, self).__init__(request, mode) 150 #GenericHandler.__init__(self, request, mode) 141 151 142 152 def _add(self): … … 148 158 _instance.dhcpstop = 2 149 159 # If wireless generate ssid name 150 _instance.ssid = newSSIDName(_instance.iface.node, _instance.iface, 'omni') 160 _instance.ssid = newSSIDName(_instance.iface.node, _instance.iface, \ 161 'omni') 151 162 _instance.save() 152 163 … … 156 167 return handler.render_to_response() 157 168 158 159 160 169 # 161 170 # Interface … … 172 181 self.interface = Interface(node=self.node) 173 182 else: 174 self.interface = Interface.objects.get(node=self.node, iface=interface) 175 GenericHandler.__init__(self, request, mode) 183 self.interface = Interface.objects.get(node=self.node, \ 184 iface=interface) 185 super(InterfaceHandler, self).__init__(request, mode) 176 186 177 187 def _add(self): … … 189 199 raise ValueError,'Type of local and remote interface needs to match' 190 200 if str(_instance.type) != "eth": 191 _instance.ssid = newSSIDName(_instance.node, _instance.iface, 'unused') 201 _instance.ssid = newSSIDName(_instance.node, _instance.iface, \ 202 'unused') 192 203 _instance.channel = '1' 193 204 _instance.mode = 1 # set to master 194 205 195 206 # Only change IP if changes in interface link/mask or new of course :-) 196 if self.mode == 'add' or self.is_changed.has_key('link') or self.is_changed.has_key('netmask'): 207 if self.mode == 'add' or self.is_changed.has_key('link') or \ 208 self.is_changed.has_key('netmask'): 197 209 if not _instance.link: 198 210 _instance.ip = freeInterlinkIP(_instance) … … 200 212 _instance.ip = addInterlinkIP(_instance.link) 201 213 202 # XXX: Change in netmask requires full range of netmask changes on slaves 214 # XXX: Change in netmask requires full range of netmask changes \ 215 # on slaves 203 216 _instance.save() 204 217 #Dirty to hack to get reference to self working … … 207 220 _instance.save() 208 221 209 210 222 def genericInterface(request, node, interface, mode): 211 223 pdebug(100, "Function: genericInterface") … … 227 239 else: 228 240 self.node = Node.objects.get(name=node) 229 GenericHandler.__init__(self,request, mode)241 super(NodeHandler, self).__init__(request, mode) 230 242 231 243 def _add(self): … … 233 245 # input a valid master ip into new_data 234 246 _instance = self.form.save(commit=False) 235 _instance.masterip = freeMasterIP(_instance) 247 import pdb; pdb.set_trace() ; 248 _instance.masterip = freeMasterIP(_instance.network) 236 249 _instance.save() 237 self.response = HttpResponseRedirect(reverse('exodus.views.viewNode', args=[_instance.name])) 250 self.response = HttpResponseRedirect(reverse('exodus.views.viewNode', \ 251 args=[_instance.name])) 238 252 239 253 def _delete(self): … … 246 260 self.object.delete() 247 261 # As node is deleted, goto overview page 248 self.response = HttpResponseRedirect(reverse('exodus.views.viewNodelist')) 262 self.response = HttpResponseRedirect(reverse( \ 263 'exodus.views.viewNodelist')) 249 264 250 265 def _cancel(self): 251 266 pdebug(100, "Function: NodeHandler._cancel") 252 267 if self.mode == 'new': 253 self.response = HttpResponseRedirect(reverse('exodus.views.viewNodelist')) 254 else: 255 self.response = HttpResponseRedirect(reverse('exodus.views.viewNode', args=[self.node.name])) 268 self.response = HttpResponseRedirect(reverse( \ 269 'exodus.views.viewNodelist')) 270 else: 271 self.response = HttpResponseRedirect(reverse( \ 272 'exodus.views.viewNode', args=[self.node.name])) 256 273 257 274 def genericNode(request, node, mode): … … 261 278 262 279 # 263 # Location280 # location 264 281 class LocationForm(forms.ModelForm): 265 282 class Meta: … … 273 290 else: 274 291 self.location = Location.objects.get(description=location) 275 GenericHandler.__init__(self, request, mode) 292 293 super(LocationHandler,self).__init__(request, mode) 276 294 277 295 def _add(self): … … 279 297 _instance = self.form.save() 280 298 # After adding a location, allow adding a Node with this location 281 self.response = HttpResponseRedirect( 282 reverse('exodus.views.genericNode', args=["add", "new"]) + "?location=%i" % _instance.pk) 299 self.response = HttpResponseRedirect( \ 300 reverse('exodus.views.genericNode', args=["add", "new"]) + \ 301 "?location=%i" % _instance.pk) 283 302 284 303 def _delete(self): 285 304 pdebug(100, "Function: LocationHandler._delete") 286 305 self.object.delete() 287 self.response = HttpResponseRedirect(reverse('exodus.views.viewNodelist')) 306 self.response = HttpResponseRedirect(reverse( \ 307 'exodus.views.viewNodelist')) 288 308 289 309 def _cancel(self): 290 310 pdebug(100, "Function: LocationHandler._cancel") 291 self.response = HttpResponseRedirect(reverse('exodus.views.viewNodelist')) 311 self.response = HttpResponseRedirect(reverse( \ 312 'exodus.views.viewNodelist')) 292 313 293 314 # … … 307 328 'named.conf', 308 329 'resolv.conf' ) 309 return render_to_response('viewNodelist.html', {'nodes' : nodes, 'configFiles' : configFiles}) 330 return render_to_response('viewNodelist.html', {'nodes' : nodes, \ 331 'configFiles' : configFiles}) 310 332 311 333 def configFile(request, version, node, file): … … 318 340 319 341 templateFile = version + '/' + file 320 return render_to_response(templateFile, {'node' : node, 'server' : server}, 321 342 return render_to_response(templateFile, {'node' : node, 'server' : server},\ 343 mimetype='text/plain') 322 344 323 345 # … … 334 356 else: 335 357 self.dnsServer= DnsServer.objects.get(ipaddress=dnsServer) 336 GenericHandler.__init__(self,request, mode)358 super(DnsServerHandler, self).__init__(request, mode) 337 359 338 360 def _add(self): 339 361 pdebug(100, "Function: DnsServerHandler._add") 340 362 _instance = self.form.save() 341 self.response = HttpResponseRedirect(reverse('exodus.views.viewList', args=['dnsServer'])) 363 self.response = HttpResponseRedirect(reverse('exodus.views.viewList', \ 364 args=['dnsServer'])) 342 365 343 366 def _delete(self): 344 367 pdebug(100, "Function: DnsServerHandler._delete") 345 368 self.object.delete() 346 self.response = HttpResponseRedirect(reverse('exodus.views.viewList', args=['dnsServer'])) 369 self.response = HttpResponseRedirect(reverse('exodus.views.viewList', \ 370 args=['dnsServer'])) 347 371 348 372 def _cancel(self): 349 373 pdebug(100, "Function: DnsServerHandler._cancel") 350 self.response = HttpResponseRedirect(reverse('exodus.views.viewList', args=['dnsServer'])) 374 self.response = HttpResponseRedirect(reverse('exodus.views.viewList', \ 375 args=['dnsServer'])) 351 376 352 377 def genericModel(request, model, mode, object): … … 360 385 def viewList(request, model): 361 386 pdebug(100, "Function: viewList") 362 """Standard interface for simple overview pages, with view/edit/delete buttons on it""" 387 """Standard interface for simple overview pages, with view/edit/delete 388 buttons on it 389 """ 363 390 modelURL = model 364 391 model = model[0].upper() + model[1::] … … 366 393 model = eval(model) 367 394 objects = model.objects.all() 368 return render_to_response('viewList.html', {'objects': objects, 'modelURL' : modelURL, 'modelName' : modelName}) 395 return render_to_response('viewList.html', {'objects': objects, \ 396 'modelURL' : modelURL, 'modelName' : modelName}) -
trunk/exodus/wllogic.py
r6354 r6357 2 2 3 3 from exodus.models import Node, Interface, PublicAP 4 from exodus.settings import MASTERIP_NETMASK 4 5 5 6 def newSSIDName(node, nic, desc): … … 15 16 # 16 17 def parseaddr(s): 18 """Remember when using an address has a section which is higher than 19 255, such as 172.16.0.256, the ip address from showaddr turns out as 20 172.16.1.0 21 """ 17 22 f = s.split('.') 18 23 return (long(f[0]) << 24L) + \ … … 25 30 26 31 def netmask2subnet(s): 27 28 29 30 32 """IPv4 netmask to subnet""" 33 if s < 0 : 34 raise ValueError, 'subnet is too small' 35 return (0xffffffff << (32 - s)) 31 36 32 37 def getSubnet(netmask): … … 39 44 def broadcast(address, netmask): 40 45 """IPv4 network address when address and netmask are given""" 46 if netmask > 32: 47 raise ValueError, 'netmask too large' 41 48 return(parseaddr(address) | 0xffffffff >> netmask) 42 49 … … 48 55 49 56 #XXX: freeMasterIP/addInterlinkIP should be more general by writing a function 50 # with finds a range based on a given range, taken ip/netmask and requested subnet 57 # which finds a range based on a given range, taken ip/netmask and 58 # requested subnet 51 59 52 def freeMasterIP(node): 60 def freeMasterIP(city_network, netmask = None): 61 if netmask == None: 62 netmask = MASTERIP_NETMASK 63 64 if netmask < 0 or netmask > 32 : 65 raise ValueError, 'netmask out of bounds' 66 53 67 taken = {} 54 68 55 69 for node in Node.objects.all(): 56 addr = network(node.masterip, 24)70 addr = network(node.masterip, netmask) 57 71 taken[addr] = 1 58 59 #Currently claiming a /24 for every node 60 size = 24 61 numaddrs = 1 << (32 - size) 72 73 numaddrs = 1 << (32 - netmask) 62 74 63 75 #XXX: No out of bond checking done yet 64 i = parseaddr( node.network.ipspacestart)76 i = parseaddr(city_network.ipspacestart) 65 77 while taken.has_key(i): 66 78 i = i + numaddrs … … 69 81 70 82 # 71 # XXX: Needs merging with freeInterlinkIP as interface could have both AP, interlink difined on one link 83 # XXX: Needs merging with freeInterlinkIP as interface could have both AP, 84 # interlink defined on one link 72 85 def freePublicAPIP(masterLink, netmask): 73 86 taken = {}
Note:
See TracChangeset
for help on using the changeset viewer.