302 |
312 |
303 class ListHandler (BaseHandler) : |
313 class ListHandler (BaseHandler) : |
304 # pagination |
314 # pagination |
305 PAGE = 10 |
315 PAGE = 10 |
306 |
316 |
|
317 # views |
|
318 VIEWS = ( |
|
319 ("Last hour", dict(seen='1h')), |
|
320 ("Last day", dict(seen='24h')), |
|
321 ("All", dict()), |
|
322 ) + tuple( |
|
323 ("Network " + network, dict(ip=network)) for network in ( |
|
324 '194.197.235.0/24', |
|
325 '10.1.0.0/16', |
|
326 '10.4.0.0/16', |
|
327 '10.5.0.0/16', |
|
328 '10.6.0.0/16', |
|
329 '10.10.0.0/16', |
|
330 ) |
|
331 ) + ( |
|
332 ("Valid", dict(state=('DHCPACK', 'DHCPRELEASE'))), |
|
333 ("Incomplete", dict(state=('DHCPDISCOVER', 'DHCPOFFER', 'DHCPREQUEST'))), |
|
334 ("Invalid", dict(state=('DHCPNAK', ))), |
|
335 ) |
|
336 |
|
337 def filter (self, attr, value) : |
|
338 """ |
|
339 Return filter expression for given attr == value |
|
340 """ |
|
341 |
|
342 if attr == 'seen' : |
|
343 column = Host.last_seen |
|
344 |
|
345 if value.isdigit() : |
|
346 # specific date |
|
347 date = datetime.datetime.strptime(value, Host.DATE_FMT).date() |
|
348 |
|
349 return db.between(date.strftime(Host.DATE_FMT), |
|
350 db.func.strftime(Host.DATE_FMT, Host.first_seen), |
|
351 db.func.strftime(Host.DATE_FMT, Host.last_seen) |
|
352 ) |
|
353 else : |
|
354 # recent |
|
355 timedelta = parse_timedelta(value) |
|
356 |
|
357 return ((db.func.now() - Host.last_seen) < timedelta) |
|
358 |
|
359 # XXX: for sqlite, pgsql should handle this natively? |
|
360 # to seconds |
|
361 #timeout = timedelta.days * (24 * 60 * 60) + timedelta.seconds |
|
362 |
|
363 # WHERE strftime('%s', 'now') - strftime('%s', last_seen) < :timeout |
|
364 #filter = (db.func.strftime('%s', 'now') - db.func.strftime('%s', Host.last_seen) < timeout) |
|
365 |
|
366 elif attr == 'ip' : |
|
367 column = Host.ip |
|
368 |
|
369 # column is IPv4 string literal format... |
|
370 if '/' in value : |
|
371 return (db.func.inet(Host.ip).op('<<')(db.func.cidr(value))) |
|
372 else : |
|
373 return (db.func.inet(Host.ip) == db.func.inet(value)) |
|
374 |
|
375 else : |
|
376 # preprocess |
|
377 like = False |
|
378 |
|
379 if value.endswith('*') : |
|
380 like = value.replace('*', '%') |
|
381 |
|
382 elif attr == 'mac' : |
|
383 value = Host.normalize_mac(value) |
|
384 |
|
385 # filter |
|
386 column = self.HOST_ATTRS[attr] |
|
387 |
|
388 if like : |
|
389 return (column.like(like)) |
|
390 else : |
|
391 return (column == value) |
|
392 |
307 def process (self) : |
393 def process (self) : |
308 hosts = self.query() |
394 hosts = self.query() |
309 |
395 |
310 # filter? |
396 # filter? |
311 column = None |
|
312 self.filters = {} |
397 self.filters = {} |
313 |
398 |
314 for attr in self.HOST_ATTRS : |
399 for attr in self.HOST_ATTRS : |
315 value = self.request.args.get(attr) |
400 values = self.request.args.getlist(attr) |
316 |
401 |
317 if not value : |
402 if not values : |
318 continue |
403 continue |
319 |
|
320 if attr == 'seen' : |
|
321 column = Host.last_seen |
|
322 |
|
323 if value.isdigit() : |
|
324 # specific date |
|
325 date = datetime.datetime.strptime(value, Host.DATE_FMT).date() |
|
326 |
|
327 filter = db.between(date.strftime(Host.DATE_FMT), |
|
328 db.func.strftime(Host.DATE_FMT, Host.first_seen), |
|
329 db.func.strftime(Host.DATE_FMT, Host.last_seen) |
|
330 ) |
|
331 else : |
|
332 # recent |
|
333 timedelta = parse_timedelta(value) |
|
334 |
|
335 filter = ((db.func.now() - Host.last_seen) < timedelta) |
|
336 |
|
337 # XXX: for sqlite, pgsql should handle this natively? |
|
338 # to seconds |
|
339 #timeout = timedelta.days * (24 * 60 * 60) + timedelta.seconds |
|
340 |
|
341 # WHERE strftime('%s', 'now') - strftime('%s', last_seen) < :timeout |
|
342 #filter = (db.func.strftime('%s', 'now') - db.func.strftime('%s', Host.last_seen) < timeout) |
|
343 |
404 |
344 elif attr == 'ip' : |
405 filter = db.or_(*[self.filter(attr, value) for value in values]) |
345 column = Host.ip |
406 |
346 |
407 log.debug("filter %s: %s", attr, filter) |
347 # column is IPv4 string literal format... |
408 |
348 if '/' in value : |
|
349 filter = (db.func.inet(Host.ip).op('<<')(db.func.cidr(value))) |
|
350 else : |
|
351 filter = (db.func.inet(Host.ip) == db.func.inet(value)) |
|
352 |
|
353 else : |
|
354 # preprocess |
|
355 like = False |
|
356 |
|
357 if value.endswith('*') : |
|
358 like = value.replace('*', '%') |
|
359 |
|
360 elif attr == 'mac' : |
|
361 value = Host.normalize_mac(value) |
|
362 |
|
363 # filter |
|
364 column = self.HOST_ATTRS[attr] |
|
365 |
|
366 if like : |
|
367 filter = (column.like(like)) |
|
368 else : |
|
369 filter = (column == value) |
|
370 |
|
371 hosts = hosts.filter(filter) |
409 hosts = hosts.filter(filter) |
372 self.filters[attr] = value |
410 self.filters[attr] = values |
373 |
411 |
374 # sort XXX: default per filter column |
412 # sort XXX: default per filter column? |
375 hosts = self.sort(hosts) #, column) |
413 hosts = self.sort(hosts) |
376 |
414 |
377 # page? |
415 # page? |
378 self.page = self.request.args.get('page') |
416 self.page = self.request.args.get('page') |
379 |
417 |
380 if self.page : |
418 if self.page : |