Commit 4395076d7fa9d2aac8e71e13f679e50d2f8cb067
Committed by
Eduardo Santos
1 parent
be5b7045
Exists in
master
Várias correções nas coletas das impressoras, incluindo problema que só exportava o último contador.
Showing
5 changed files
with
373 additions
and
17 deletions
Show diff stats
README.md
| 1 | -cocar-agente | 1 | +Instalação |
| 2 | ============ | 2 | ============ |
| 3 | 3 | ||
| 4 | Módulo agente coletor para o software Cocar | 4 | Módulo agente coletor para o software Cocar |
| @@ -11,3 +11,26 @@ Para funcionar é necessário primeiro instalar o pacote da distribuição e só | @@ -11,3 +11,26 @@ Para funcionar é necessário primeiro instalar o pacote da distribuição e só | ||
| 11 | virtualenv --system-site-packages -p /usr/bin/python2.7 cocar-agente | 11 | virtualenv --system-site-packages -p /usr/bin/python2.7 cocar-agente |
| 12 | </pre> | 12 | </pre> |
| 13 | 13 | ||
| 14 | + | ||
| 15 | +Operação | ||
| 16 | +================ | ||
| 17 | + | ||
| 18 | +Descrição dos principais comandos de operação | ||
| 19 | + | ||
| 20 | +* Varredura contínua de rede | ||
| 21 | + | ||
| 22 | +<pre> | ||
| 23 | +/srv/cocar-agente/bin/paster scan continous_scan | ||
| 24 | +</pre> | ||
| 25 | + | ||
| 26 | +* Leitura e export do contador das impressoras | ||
| 27 | + | ||
| 28 | +<pre> | ||
| 29 | +/srv/cocar-agente/bin/paster scan printer_scan -t 10000000 | ||
| 30 | +</pre> | ||
| 31 | + | ||
| 32 | +* Coleta de MAC address que não foi inicialmente identificado | ||
| 33 | + | ||
| 34 | +<pre> | ||
| 35 | +/srv/cocar-agente/bin/paster scan scan_mac_all -a eth0 -t 10 | ||
| 36 | +</pre> | ||
| 14 | \ No newline at end of file | 37 | \ No newline at end of file |
cocar/commands/scan_commands.py
| @@ -16,10 +16,11 @@ from ..model.printer import Printer, PrinterCounter | @@ -16,10 +16,11 @@ from ..model.printer import Printer, PrinterCounter | ||
| 16 | from ..model.host import Host | 16 | from ..model.host import Host |
| 17 | from ..model.computer import Computer | 17 | from ..model.computer import Computer |
| 18 | from ..csv_utils import NetworkCSV | 18 | from ..csv_utils import NetworkCSV |
| 19 | -from ..session import NmapSession, SnmpSession | 19 | +from ..session import NmapSession, SnmpSession, ArpSession |
| 20 | from multiprocessing import Process, Queue | 20 | from multiprocessing import Process, Queue |
| 21 | from ..xml_utils import NmapXML | 21 | from ..xml_utils import NmapXML |
| 22 | from sqlalchemy.exc import IntegrityError | 22 | from sqlalchemy.exc import IntegrityError |
| 23 | +from sqlalchemy import and_ | ||
| 23 | 24 | ||
| 24 | log = logging.getLogger() | 25 | log = logging.getLogger() |
| 25 | 26 | ||
| @@ -75,6 +76,12 @@ class ScanCommands(command.Command): | @@ -75,6 +76,12 @@ class ScanCommands(command.Command): | ||
| 75 | help='Arquivo individual de rede para ser carregado' | 76 | help='Arquivo individual de rede para ser carregado' |
| 76 | ) | 77 | ) |
| 77 | 78 | ||
| 79 | + parser.add_option('-a', '--iface', | ||
| 80 | + action='store', | ||
| 81 | + dest='iface', | ||
| 82 | + help='Interface de rede para utilizar no Arping' | ||
| 83 | + ) | ||
| 84 | + | ||
| 78 | def __init__(self, name): | 85 | def __init__(self, name): |
| 79 | """ | 86 | """ |
| 80 | Constructor method | 87 | Constructor method |
| @@ -134,6 +141,15 @@ class ScanCommands(command.Command): | @@ -134,6 +141,15 @@ class ScanCommands(command.Command): | ||
| 134 | if cmd == 'import_printers': | 141 | if cmd == 'import_printers': |
| 135 | self.import_printers() | 142 | self.import_printers() |
| 136 | return | 143 | return |
| 144 | + if cmd == 'get_mac': | ||
| 145 | + self.get_mac() | ||
| 146 | + return | ||
| 147 | + if cmd == 'scan_mac': | ||
| 148 | + self.scan_mac() | ||
| 149 | + return | ||
| 150 | + if cmd == 'scan_mac_all': | ||
| 151 | + self.scan_mac() | ||
| 152 | + return | ||
| 137 | else: | 153 | else: |
| 138 | log.error('Command "%s" not recognized' % (cmd,)) | 154 | log.error('Command "%s" not recognized' % (cmd,)) |
| 139 | 155 | ||
| @@ -286,6 +302,7 @@ class ScanCommands(command.Command): | @@ -286,6 +302,7 @@ class ScanCommands(command.Command): | ||
| 286 | while True: | 302 | while True: |
| 287 | log.info("Iniciando scan de redes...") | 303 | log.info("Iniciando scan de redes...") |
| 288 | self.scan_networks() | 304 | self.scan_networks() |
| 305 | + | ||
| 289 | log.info("Scan de redes finalizado. Iniciando procedimento de " | 306 | log.info("Scan de redes finalizado. Iniciando procedimento de " |
| 290 | "identificação de ativos de rede, computadores e impressoras") | 307 | "identificação de ativos de rede, computadores e impressoras") |
| 291 | self.load_network_files() | 308 | self.load_network_files() |
| @@ -305,17 +322,31 @@ class ScanCommands(command.Command): | @@ -305,17 +322,31 @@ class ScanCommands(command.Command): | ||
| 305 | log.info("EXPORT DE IMPRESSORAS FINALIZADO!!! Reiniciando as coletas") | 322 | log.info("EXPORT DE IMPRESSORAS FINALIZADO!!! Reiniciando as coletas") |
| 306 | #time.sleep(600) | 323 | #time.sleep(600) |
| 307 | 324 | ||
| 325 | + def scan_mac_all(self): | ||
| 326 | + """ | ||
| 327 | + Fica varrendo a rede tentando arrumar os MAC's | ||
| 328 | + """ | ||
| 329 | + print("*** Aperente CTRL+C para encerrar a execução ***") | ||
| 330 | + | ||
| 331 | + while True: | ||
| 332 | + self.scan_mac() | ||
| 333 | + log.info("SCAN DE MAC FINALIZADO!!!") | ||
| 334 | + | ||
| 308 | def export_printers(self): | 335 | def export_printers(self): |
| 309 | """ | 336 | """ |
| 310 | Exporta todos os contadores para o Cocar | 337 | Exporta todos os contadores para o Cocar |
| 311 | """ | 338 | """ |
| 312 | session = self.cocar.Session | 339 | session = self.cocar.Session |
| 313 | - results = session.query(Printer).all() | 340 | + results = session.query(Printer).join( |
| 341 | + PrinterCounter.__table__, | ||
| 342 | + PrinterCounter.network_ip == Printer.network_ip | ||
| 343 | + ).all() | ||
| 314 | for printer in results: | 344 | for printer in results: |
| 315 | log.info("Exportando impressora %s", printer.network_ip) | 345 | log.info("Exportando impressora %s", printer.network_ip) |
| 316 | printer.export_printer(server_url=self.cocar.config.get('cocar', 'server_url'), session=session) | 346 | printer.export_printer(server_url=self.cocar.config.get('cocar', 'server_url'), session=session) |
| 317 | 347 | ||
| 318 | session.close() | 348 | session.close() |
| 349 | + log.info("EXPORT DAS IMPRESSORAS FINALIZADO!!! %s IMPRESSORAS EXPORTADAS!!!", len(results)) | ||
| 319 | 350 | ||
| 320 | def get_printer_attribute(self): | 351 | def get_printer_attribute(self): |
| 321 | """ | 352 | """ |
| @@ -457,6 +488,30 @@ class ScanCommands(command.Command): | @@ -457,6 +488,30 @@ class ScanCommands(command.Command): | ||
| 457 | session = self.cocar.Session | 488 | session = self.cocar.Session |
| 458 | for hostname in nmap_xml.hosts.keys(): | 489 | for hostname in nmap_xml.hosts.keys(): |
| 459 | host = nmap_xml.identify_host(hostname, timeout=self.options.timeout) | 490 | host = nmap_xml.identify_host(hostname, timeout=self.options.timeout) |
| 491 | + # Antes de tudo verifica se ele já está na tabela de contadores | ||
| 492 | + counter = session.query( | ||
| 493 | + PrinterCounter.__table__ | ||
| 494 | + ).outerjoin( | ||
| 495 | + Printer.__table__, | ||
| 496 | + PrinterCounter.network_ip == Printer.network_ip | ||
| 497 | + ).filter( | ||
| 498 | + and_( | ||
| 499 | + PrinterCounter.network_ip == hostname, | ||
| 500 | + Printer.network_ip.is_(None) | ||
| 501 | + ) | ||
| 502 | + ).first() | ||
| 503 | + | ||
| 504 | + if counter is not None: | ||
| 505 | + # Agora insere a impressora | ||
| 506 | + log.info("Inserindo impressora com o IP %s", hostname) | ||
| 507 | + session.execute( | ||
| 508 | + Printer.__table__.insert().values( | ||
| 509 | + network_ip=host.network_ip | ||
| 510 | + ) | ||
| 511 | + ) | ||
| 512 | + session.flush() | ||
| 513 | + continue | ||
| 514 | + | ||
| 460 | if isinstance(host, Printer): | 515 | if isinstance(host, Printer): |
| 461 | # Vê se a impressora já está na base | 516 | # Vê se a impressora já está na base |
| 462 | results = session.query(Printer).filter(Printer.network_ip == hostname).first() | 517 | results = session.query(Printer).filter(Printer.network_ip == hostname).first() |
| @@ -476,8 +531,21 @@ class ScanCommands(command.Command): | @@ -476,8 +531,21 @@ class ScanCommands(command.Command): | ||
| 476 | network_ip=hostname | 531 | network_ip=hostname |
| 477 | ) | 532 | ) |
| 478 | ) | 533 | ) |
| 479 | - session.flush() | ||
| 480 | log.info("Impressora %s adicionada novamente com sucesso", hostname) | 534 | log.info("Impressora %s adicionada novamente com sucesso", hostname) |
| 535 | + | ||
| 536 | + # Agora atualiza informações do host | ||
| 537 | + if host.mac_address is not None: | ||
| 538 | + session.execute( | ||
| 539 | + Host.__table__.update().values( | ||
| 540 | + mac_address=host.mac_address, | ||
| 541 | + name=host.name, | ||
| 542 | + ports=host.ports | ||
| 543 | + ).where( | ||
| 544 | + Host.network_ip == hostname | ||
| 545 | + ) | ||
| 546 | + ) | ||
| 547 | + session.flush() | ||
| 548 | + log.info("Informações do host %s atualizadas com sucesso", hostname) | ||
| 481 | else: | 549 | else: |
| 482 | log.error("ERRO!!! Host não encontrado com o IP!!! %s", hostname) | 550 | log.error("ERRO!!! Host não encontrado com o IP!!! %s", hostname) |
| 483 | else: | 551 | else: |
| @@ -492,8 +560,34 @@ class ScanCommands(command.Command): | @@ -492,8 +560,34 @@ class ScanCommands(command.Command): | ||
| 492 | session.flush() | 560 | session.flush() |
| 493 | except IntegrityError, e: | 561 | except IntegrityError, e: |
| 494 | log.error("Erro adicionando computador com o IP %s. IP Repetido\n%s", hostname, e.message) | 562 | log.error("Erro adicionando computador com o IP %s. IP Repetido\n%s", hostname, e.message) |
| 563 | + # Agora atualiza informações do host | ||
| 564 | + if host.mac_address is not None: | ||
| 565 | + session.execute( | ||
| 566 | + Host.__table__.update().values( | ||
| 567 | + mac_address=host.mac_address, | ||
| 568 | + name=host.name, | ||
| 569 | + ports=host.ports | ||
| 570 | + ).where( | ||
| 571 | + Host.network_ip == hostname | ||
| 572 | + ) | ||
| 573 | + ) | ||
| 574 | + session.flush() | ||
| 575 | + log.info("Informações do host %s atualizadas com sucesso", hostname) | ||
| 495 | else: | 576 | else: |
| 496 | log.info("Computador com o IP %s já cadastrado", hostname) | 577 | log.info("Computador com o IP %s já cadastrado", hostname) |
| 578 | + # Agora atualiza informações do host | ||
| 579 | + if host.mac_address is not None: | ||
| 580 | + session.execute( | ||
| 581 | + Host.__table__.update().values( | ||
| 582 | + mac_address=host.mac_address, | ||
| 583 | + name=host.name, | ||
| 584 | + ports=host.ports | ||
| 585 | + ).where( | ||
| 586 | + Host.network_ip == hostname | ||
| 587 | + ) | ||
| 588 | + ) | ||
| 589 | + session.flush() | ||
| 590 | + log.info("Informações do host %s atualizadas com sucesso", hostname) | ||
| 497 | else: | 591 | else: |
| 498 | # Insere host genérico | 592 | # Insere host genérico |
| 499 | results = session.query(Host).filter(Host.network_ip == hostname).first() | 593 | results = session.query(Host).filter(Host.network_ip == hostname).first() |
| @@ -504,12 +598,42 @@ class ScanCommands(command.Command): | @@ -504,12 +598,42 @@ class ScanCommands(command.Command): | ||
| 504 | session.flush() | 598 | session.flush() |
| 505 | except IntegrityError, e: | 599 | except IntegrityError, e: |
| 506 | log.error("Erro adicionando host genérico com o IP %s. IP Repetido\n%s", hostname, e.message) | 600 | log.error("Erro adicionando host genérico com o IP %s. IP Repetido\n%s", hostname, e.message) |
| 601 | + | ||
| 602 | + # Agora atualiza informações do host | ||
| 603 | + if host.mac_address is not None: | ||
| 604 | + session.execute( | ||
| 605 | + Host.__table__.update().values( | ||
| 606 | + mac_address=host.mac_address, | ||
| 607 | + name=host.name, | ||
| 608 | + ports=host.ports | ||
| 609 | + ).where( | ||
| 610 | + Host.network_ip == hostname | ||
| 611 | + ) | ||
| 612 | + ) | ||
| 613 | + session.flush() | ||
| 614 | + log.info("Informações do host %s atualizadas com sucesso", hostname) | ||
| 507 | else: | 615 | else: |
| 508 | log.info("Host genérico com o IP %s já cadastrado", hostname) | 616 | log.info("Host genérico com o IP %s já cadastrado", hostname) |
| 509 | 617 | ||
| 618 | + # Agora atualiza informações do host | ||
| 619 | + if host.mac_address is not None: | ||
| 620 | + session.execute( | ||
| 621 | + Host.__table__.update().values( | ||
| 622 | + mac_address=host.mac_address, | ||
| 623 | + name=host.name, | ||
| 624 | + ports=host.ports | ||
| 625 | + ).where( | ||
| 626 | + Host.network_ip == hostname | ||
| 627 | + ) | ||
| 628 | + ) | ||
| 629 | + session.flush() | ||
| 630 | + log.info("Informações do host %s atualizadas com sucesso", hostname) | ||
| 631 | + | ||
| 510 | #session.flush() | 632 | #session.flush() |
| 511 | session.close() | 633 | session.close() |
| 512 | 634 | ||
| 635 | + log.info("CARGA DO ARQUIVO DE REDE %s FINALIZADA!!!", network_file) | ||
| 636 | + | ||
| 513 | def import_printers(self): | 637 | def import_printers(self): |
| 514 | """ | 638 | """ |
| 515 | Importa impressoras já cadastradas e não presentes na base local | 639 | Importa impressoras já cadastradas e não presentes na base local |
| @@ -535,6 +659,86 @@ class ScanCommands(command.Command): | @@ -535,6 +659,86 @@ class ScanCommands(command.Command): | ||
| 535 | 659 | ||
| 536 | session.close() | 660 | session.close() |
| 537 | 661 | ||
| 662 | + def get_mac(self): | ||
| 663 | + """ | ||
| 664 | + Atualiza MAC Address para o host selecionado | ||
| 665 | + :return: | ||
| 666 | + """ | ||
| 667 | + if type(self.options.hosts) != list: | ||
| 668 | + self.options.hosts = [self.options.hosts] | ||
| 669 | + | ||
| 670 | + session = self.cocar.Session | ||
| 671 | + for host in self.options.hosts: | ||
| 672 | + arp = ArpSession( | ||
| 673 | + host=host, | ||
| 674 | + iface=self.options.iface, | ||
| 675 | + timeout=self.options.timeout | ||
| 676 | + ) | ||
| 677 | + | ||
| 678 | + result = arp.scan() | ||
| 679 | + | ||
| 680 | + if result is not None: | ||
| 681 | + log.debug("Atualizando MAC = %s para host = %s", result, host) | ||
| 682 | + session.execute( | ||
| 683 | + Host.__table__.update().values( | ||
| 684 | + mac_address=result | ||
| 685 | + ).where( | ||
| 686 | + Host.network_ip == host | ||
| 687 | + ) | ||
| 688 | + ) | ||
| 689 | + session.flush() | ||
| 690 | + | ||
| 691 | + session.close() | ||
| 692 | + | ||
| 693 | + def scan_mac(self): | ||
| 694 | + """ | ||
| 695 | + Scan all hosts to update macs | ||
| 696 | + """ | ||
| 697 | + processes = int(self.cocar.config.get('cocar', 'processes')) | ||
| 698 | + # Create queues | ||
| 699 | + task_queue = Queue() | ||
| 700 | + done_queue = Queue() | ||
| 701 | + | ||
| 702 | + session = self.cocar.Session | ||
| 703 | + results = session.query(Host).all() | ||
| 704 | + for host in results: | ||
| 705 | + arp = ArpSession( | ||
| 706 | + host=host.network_ip, | ||
| 707 | + iface=self.options.iface, | ||
| 708 | + timeout=self.options.timeout | ||
| 709 | + ) | ||
| 710 | + task_queue.put(arp) | ||
| 711 | + | ||
| 712 | + #Start worker processes | ||
| 713 | + for i in range(processes): | ||
| 714 | + Process(target=worker_mac, args=(task_queue, done_queue)).start() | ||
| 715 | + | ||
| 716 | + # Get and print results | ||
| 717 | + print 'Unordered results:' | ||
| 718 | + for i in range(len(results)): | ||
| 719 | + host_list = done_queue.get() | ||
| 720 | + log.debug(host_list) | ||
| 721 | + if host_list[1] is None: | ||
| 722 | + log.error("Nao foi possivel encontrar o mac do host %s", host_list[0]) | ||
| 723 | + continue | ||
| 724 | + try: | ||
| 725 | + log.debug("Atualizando MAC = %s para host = %s", host_list[1], host_list[0]) | ||
| 726 | + session.execute( | ||
| 727 | + Host.__table__.update().values( | ||
| 728 | + mac_address=host_list[1] | ||
| 729 | + ).where( | ||
| 730 | + Host.network_ip == host_list[0] | ||
| 731 | + ) | ||
| 732 | + ) | ||
| 733 | + session.flush() | ||
| 734 | + except AttributeError, e: | ||
| 735 | + log.error("Erro na atualização do MAC para host %s\n%s", host_list[0], e.message) | ||
| 736 | + continue | ||
| 737 | + | ||
| 738 | + # Tell child processes to stop | ||
| 739 | + for i in range(processes): | ||
| 740 | + task_queue.put('STOP') | ||
| 741 | + | ||
| 538 | 742 | ||
| 539 | def make_query(host): | 743 | def make_query(host): |
| 540 | """This does the actual snmp query | 744 | """This does the actual snmp query |
| @@ -558,6 +762,17 @@ def make_query_printer(host): | @@ -558,6 +762,17 @@ def make_query_printer(host): | ||
| 558 | return host.printer_dict() | 762 | return host.printer_dict() |
| 559 | 763 | ||
| 560 | 764 | ||
| 765 | +def make_query_mac(host): | ||
| 766 | + """This does the actual snmp query | ||
| 767 | + | ||
| 768 | + This is a bit fancy as it accepts both instances | ||
| 769 | + of SnmpSession and host/ip addresses. This | ||
| 770 | + allows a user to customize mass queries with | ||
| 771 | + subsets of different hostnames and community strings | ||
| 772 | + """ | ||
| 773 | + return host.scan_list() | ||
| 774 | + | ||
| 775 | + | ||
| 561 | # Function run by worker processes | 776 | # Function run by worker processes |
| 562 | def worker(inp, output): | 777 | def worker(inp, output): |
| 563 | for func in iter(inp.get, 'STOP'): | 778 | for func in iter(inp.get, 'STOP'): |
| @@ -569,4 +784,11 @@ def worker(inp, output): | @@ -569,4 +784,11 @@ def worker(inp, output): | ||
| 569 | def worker_printer(inp, output): | 784 | def worker_printer(inp, output): |
| 570 | for func in iter(inp.get, 'STOP'): | 785 | for func in iter(inp.get, 'STOP'): |
| 571 | result = make_query_printer(func) | 786 | result = make_query_printer(func) |
| 787 | + output.put(result) | ||
| 788 | + | ||
| 789 | + | ||
| 790 | +# Function run by worker processes | ||
| 791 | +def worker_mac(inp, output): | ||
| 792 | + for func in iter(inp.get, 'STOP'): | ||
| 793 | + result = make_query_mac(func) | ||
| 572 | output.put(result) | 794 | output.put(result) |
| 573 | \ No newline at end of file | 795 | \ No newline at end of file |
cocar/model/printer.py
| @@ -46,13 +46,30 @@ class Printer(Host): | @@ -46,13 +46,30 @@ class Printer(Host): | ||
| 46 | """ | 46 | """ |
| 47 | Exporta todos os contadores para a impressora | 47 | Exporta todos os contadores para a impressora |
| 48 | """ | 48 | """ |
| 49 | - counter_list = session.query( | ||
| 50 | - PrinterCounter | ||
| 51 | - ).filter( | ||
| 52 | - PrinterCounter.network_ip == self.network_ip | ||
| 53 | - ).all() | ||
| 54 | - | ||
| 55 | - for counter in counter_list: | 49 | + #query = session.query( |
| 50 | + # PrinterCounter | ||
| 51 | + #).filter( | ||
| 52 | + # PrinterCounter.__table__.c.network_ip == self.network_ip | ||
| 53 | + #) | ||
| 54 | + | ||
| 55 | + stm = """SELECT printer_counter.network_ip as ip_address, | ||
| 56 | + host.mac_address, | ||
| 57 | + host.inclusion_date, | ||
| 58 | + host.scantime, | ||
| 59 | + printer.model, | ||
| 60 | + printer.serial, | ||
| 61 | + printer.description, | ||
| 62 | + printer_counter.counter, | ||
| 63 | + printer_counter.counter_time | ||
| 64 | +FROM host | ||
| 65 | +JOIN printer ON host.network_ip = printer.network_ip | ||
| 66 | +JOIN printer_counter ON printer.network_ip = printer_counter.network_ip | ||
| 67 | +WHERE printer_counter.network_ip = '%s'""" % self.network_ip | ||
| 68 | + | ||
| 69 | + counter_list = session.execute(stm, mapper=PrinterCounter).fetchall() | ||
| 70 | + | ||
| 71 | + for elm in counter_list: | ||
| 72 | + counter = PrinterCounter(**elm) | ||
| 56 | print(counter) | 73 | print(counter) |
| 57 | result = counter.export_counter(server_url, session) | 74 | result = counter.export_counter(server_url, session) |
| 58 | if result: | 75 | if result: |
| @@ -61,6 +78,7 @@ class Printer(Host): | @@ -61,6 +78,7 @@ class Printer(Host): | ||
| 61 | log.error("Erro na remocao do contador %s para a impressora %s", counter.counter, self.network_ip) | 78 | log.error("Erro na remocao do contador %s para a impressora %s", counter.counter, self.network_ip) |
| 62 | return False | 79 | return False |
| 63 | 80 | ||
| 81 | + log.info("EXPORT DA IMPRESSORA %s FINALIZADO!!! %s CONTADORES EXPORTADOS!!!", self.network_ip, len(counter_list)) | ||
| 64 | return True | 82 | return True |
| 65 | 83 | ||
| 66 | 84 | ||
| @@ -157,7 +175,7 @@ class PrinterCounter(Printer): | @@ -157,7 +175,7 @@ class PrinterCounter(Printer): | ||
| 157 | return False | 175 | return False |
| 158 | 176 | ||
| 159 | if response.status_code == 200: | 177 | if response.status_code == 200: |
| 160 | - log.info("Contador para a impressora %s com contador %s" | 178 | + log.info("Contador para a impressora %s com contador %s " |
| 161 | "exportado com sucesso", self.network_ip, self.counter) | 179 | "exportado com sucesso", self.network_ip, self.counter) |
| 162 | # Remove o contador | 180 | # Remove o contador |
| 163 | session.execute( | 181 | session.execute( |
cocar/session.py
| @@ -7,6 +7,7 @@ import netsnmp | @@ -7,6 +7,7 @@ import netsnmp | ||
| 7 | import subprocess | 7 | import subprocess |
| 8 | import logging | 8 | import logging |
| 9 | from . import Cocar | 9 | from . import Cocar |
| 10 | +import re | ||
| 10 | 11 | ||
| 11 | log = logging.getLogger() | 12 | log = logging.getLogger() |
| 12 | 13 | ||
| @@ -247,4 +248,80 @@ class NmapSession(object): | @@ -247,4 +248,80 @@ class NmapSession(object): | ||
| 247 | log.error("Install nmap: sudo apt-get install nmap") | 248 | log.error("Install nmap: sudo apt-get install nmap") |
| 248 | return False | 249 | return False |
| 249 | 250 | ||
| 250 | - return True | ||
| 251 | \ No newline at end of file | 251 | \ No newline at end of file |
| 252 | + return True | ||
| 253 | + | ||
| 254 | + | ||
| 255 | +class ArpSession(object): | ||
| 256 | + """ | ||
| 257 | + Classe para buscar informações de MAC do ativo | ||
| 258 | + """ | ||
| 259 | + def __init__(self, | ||
| 260 | + host, | ||
| 261 | + iface='eth0', | ||
| 262 | + timeout='10'): | ||
| 263 | + """ | ||
| 264 | + :param host: Endereço IP do host a ser escaneado | ||
| 265 | + :param mac: MAC address do host | ||
| 266 | + :param timeout: Timeout esperando pelo reply da interface | ||
| 267 | + """ | ||
| 268 | + self.host = host | ||
| 269 | + self.iface = iface | ||
| 270 | + self.timeout = timeout | ||
| 271 | + | ||
| 272 | + def scan(self): | ||
| 273 | + """ | ||
| 274 | + | ||
| 275 | + :return: Somente MAc | ||
| 276 | + """ | ||
| 277 | + log.debug("Iniciando scan para o host %s", self.host) | ||
| 278 | + try: | ||
| 279 | + scanv = subprocess.Popen(["sudo", | ||
| 280 | + "arping", | ||
| 281 | + "-I", | ||
| 282 | + self.iface, | ||
| 283 | + "-c", | ||
| 284 | + '1', | ||
| 285 | + "-w", | ||
| 286 | + self.timeout, | ||
| 287 | + self.host], | ||
| 288 | + stdout=subprocess.PIPE, | ||
| 289 | + stderr=subprocess.PIPE).communicate()[0] | ||
| 290 | + | ||
| 291 | + match = re.search("(\[)(.*)(\])", scanv) | ||
| 292 | + | ||
| 293 | + if match: | ||
| 294 | + return match.group(2) | ||
| 295 | + | ||
| 296 | + return match | ||
| 297 | + except OSError: | ||
| 298 | + log.error("Install arping: sudo apt-get install arping") | ||
| 299 | + return None | ||
| 300 | + | ||
| 301 | + def scan_list(self): | ||
| 302 | + """ | ||
| 303 | + | ||
| 304 | + :return: List com host e MAC | ||
| 305 | + """ | ||
| 306 | + log.debug("Iniciando scan para o host %s", self.host) | ||
| 307 | + try: | ||
| 308 | + scanv = subprocess.Popen(["sudo", | ||
| 309 | + "arping", | ||
| 310 | + "-I", | ||
| 311 | + self.iface, | ||
| 312 | + "-c", | ||
| 313 | + '1', | ||
| 314 | + "-w", | ||
| 315 | + self.timeout, | ||
| 316 | + self.host], | ||
| 317 | + stdout=subprocess.PIPE, | ||
| 318 | + stderr=subprocess.PIPE).communicate()[0] | ||
| 319 | + | ||
| 320 | + match = re.search("(\[)(.*)(\])", scanv) | ||
| 321 | + | ||
| 322 | + if match: | ||
| 323 | + return [self.host, match.group(2)] | ||
| 324 | + | ||
| 325 | + return [self.host, match] | ||
| 326 | + except OSError: | ||
| 327 | + log.error("Install arping: sudo apt-get install arping") | ||
| 328 | + return None | ||
| 252 | \ No newline at end of file | 329 | \ No newline at end of file |
cocar/xml_utils.py
| @@ -32,10 +32,7 @@ class NmapXML(object): | @@ -32,10 +32,7 @@ class NmapXML(object): | ||
| 32 | if addr.get('addrtype') == 'ipv4': | 32 | if addr.get('addrtype') == 'ipv4': |
| 33 | host = addr.get('addr') | 33 | host = addr.get('addr') |
| 34 | elif addr.get('addrtype') == 'mac': | 34 | elif addr.get('addrtype') == 'mac': |
| 35 | - mac = { | ||
| 36 | - 'address': addr.get('addr'), | ||
| 37 | - 'vendor': addr.get('vendor') | ||
| 38 | - } | 35 | + mac = addr.get('addr') |
| 39 | 36 | ||
| 40 | # A chave do dicionário é o IP | 37 | # A chave do dicionário é o IP |
| 41 | self.hosts[host] = dict() | 38 | self.hosts[host] = dict() |
| @@ -129,6 +126,25 @@ class NmapXML(object): | @@ -129,6 +126,25 @@ class NmapXML(object): | ||
| 129 | open_ports=host['ports'], | 126 | open_ports=host['ports'], |
| 130 | ) | 127 | ) |
| 131 | return printer | 128 | return printer |
| 129 | + elif host.get('os'): | ||
| 130 | + # Nesse caso já sei que é computador. Precisa identificar o OS | ||
| 131 | + for os in host['os'].keys(): | ||
| 132 | + if int(host['os'][os]['accuracy']) > accuracy: | ||
| 133 | + accuracy = int(host['os'][os]['accuracy']) | ||
| 134 | + os_final = os | ||
| 135 | + | ||
| 136 | + scantime = int(host.get('endtime')) - int(host.get('starttime')) | ||
| 137 | + computer = model.computer.Computer( | ||
| 138 | + ip_address=hostname, | ||
| 139 | + mac_address=host.get('mac'), | ||
| 140 | + hostname=host.get('hostname'), | ||
| 141 | + inclusion_date=host.get('endtime'), | ||
| 142 | + scantime=scantime, | ||
| 143 | + open_ports=host.get('ports'), | ||
| 144 | + so=host['os'][os_final] | ||
| 145 | + ) | ||
| 146 | + | ||
| 147 | + return computer | ||
| 132 | else: | 148 | else: |
| 133 | # Desiste e retorna host genérico | 149 | # Desiste e retorna host genérico |
| 134 | host = model.host.Host( | 150 | host = model.host.Host( |