Commit 5a399ad1e35fd6a14f125befbecd560004a29ae2

Authored by Eduardo Santos
Committed by Eduardo Santos
2 parents 0e110c5b d04ac9d9
Exists in master

Versão do agente do Cocar que exporta os dados da impressora para o Módulo Gerente

cocar/commands/scan_commands.py
@@ -97,6 +97,9 @@ class ScanCommands(command.Command): @@ -97,6 +97,9 @@ class ScanCommands(command.Command):
97 if cmd == 'printer_scan': 97 if cmd == 'printer_scan':
98 self.printer_scan() 98 self.printer_scan()
99 return 99 return
  100 + if cmd == 'export_printers':
  101 + self.export_printers()
  102 + return
100 else: 103 else:
101 log.error('Command "%s" not recognized' % (cmd,)) 104 log.error('Command "%s" not recognized' % (cmd,))
102 105
@@ -313,6 +316,16 @@ class ScanCommands(command.Command): @@ -313,6 +316,16 @@ class ScanCommands(command.Command):
313 log.info("SCAN DE IMPRESSORAS FINALIZADO!!! Dormindo...") 316 log.info("SCAN DE IMPRESSORAS FINALIZADO!!! Dormindo...")
314 time.sleep(600) 317 time.sleep(600)
315 318
  319 + def export_printers(self):
  320 + """
  321 + Exporta todos os contadores para o Cocar
  322 + """
  323 + session = self.cocar.Session
  324 + results = session.query(Printer).all()
  325 + for printer in results:
  326 + log.info("Exportando impressora %s", printer.network_ip)
  327 + printer.export_printer(server_url=self.cocar.config.get('cocar', 'server_url'), session=session)
  328 +
316 329
317 def make_query(host): 330 def make_query(host):
318 """This does the actual snmp query 331 """This does the actual snmp query
cocar/model/printer.py
@@ -2,6 +2,10 @@ @@ -2,6 +2,10 @@
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 __author__ = 'eduardo' 3 __author__ = 'eduardo'
4 import logging 4 import logging
  5 +import requests
  6 +import json
  7 +from requests.exceptions import HTTPError
  8 +from sqlalchemy.orm import aliased
5 from .host import Host 9 from .host import Host
6 from sqlalchemy import ForeignKey 10 from sqlalchemy import ForeignKey
7 from sqlalchemy.schema import Column 11 from sqlalchemy.schema import Column
@@ -38,6 +42,26 @@ class Printer(Host): @@ -38,6 +42,26 @@ class Printer(Host):
38 self.serial = serial 42 self.serial = serial
39 self.description = description 43 self.description = description
40 44
  45 + def export_printer(self, server_url, session):
  46 + """
  47 + Exporta todos os contadores para a impressora
  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:
  56 + result = counter.export_counter(server_url, session)
  57 + if result:
  58 + log.info("Contador %s para a impressora %s exportado com sucesso")
  59 + else:
  60 + log.error("Erro na remocao do contador %s para a impressora %s", counter.counter, self.network_ip)
  61 + return False
  62 +
  63 + return True
  64 +
41 65
42 class PrinterCounter(Printer): 66 class PrinterCounter(Printer):
43 """ 67 """
@@ -67,9 +91,10 @@ class PrinterCounter(Printer): @@ -67,9 +91,10 @@ class PrinterCounter(Printer):
67 results = session.query(self.__table__).filter( 91 results = session.query(self.__table__).filter(
68 and_( 92 and_(
69 self.__table__.c.counter == self.counter, 93 self.__table__.c.counter == self.counter,
70 - self.__table__.c.counter_time == self.counter_time)  
71 - ).first()  
72 - print(results) 94 + self.__table__.c.counter_time == self.counter_time
  95 + )
  96 + ).first()
  97 + #print(results)
73 if results is None: 98 if results is None:
74 log.debug("Inserindo contador para impressora %s serial %s", self.network_ip, self.serial) 99 log.debug("Inserindo contador para impressora %s serial %s", self.network_ip, self.serial)
75 session.execute( 100 session.execute(
@@ -92,4 +117,49 @@ class PrinterCounter(Printer): @@ -92,4 +117,49 @@ class PrinterCounter(Printer):
92 ) 117 )
93 118
94 session.flush() 119 session.flush()
95 - return False  
96 \ No newline at end of file 120 \ No newline at end of file
  121 + return False
  122 +
  123 + def export_counter(self, server_url, session):
  124 + """
  125 + Exporta contador da impressora para o Cocar
  126 +
  127 + :param server_url: URL do servidor do Cocar
  128 + :param session: Sessão do banco de dados
  129 + :return: Verdadeiro ou falso dependendo do sucesso
  130 + """
  131 + export_url = server_url + '/api/printer/' + self.network_ip
  132 + counter_json = {
  133 + 'ip_address': self.network_ip,
  134 + 'model': self.model,
  135 + 'serial': self.serial,
  136 + 'description': self.description,
  137 + 'counter': self.counter,
  138 + 'counter_time': int(float(self.counter_time))
  139 + }
  140 +
  141 + # Envia a requisição HTTP
  142 + headers = {'content-type': 'application/json'}
  143 + response = requests.put(
  144 + export_url,
  145 + data=json.dumps(counter_json),
  146 + headers=headers
  147 + )
  148 +
  149 + try:
  150 + # Check if request has gone wrong
  151 + response.raise_for_status()
  152 + except HTTPError:
  153 + # Something got wrong, raise error
  154 + log.error("Erro na insercao do contador para a impressora %s\n", self.network_ip, response.text)
  155 + return False
  156 +
  157 + if response.status_code == 200:
  158 + log.info("Contador para a impressora %s com contador %s"
  159 + "exportado com sucesso", self.network_ip, self.counter)
  160 + # Remove o contador
  161 + session.remove(self)
  162 + session.flush()
  163 + return True
  164 + else:
  165 + log.error("Erro na remoção da impressora %s. Status code = %s", self.network_ip, response.status)
  166 + return False
97 \ No newline at end of file 167 \ No newline at end of file
cocar/tests/__init__.py
@@ -5,6 +5,7 @@ from .. import Cocar @@ -5,6 +5,7 @@ from .. import Cocar
5 import os 5 import os
6 import os.path 6 import os.path
7 import logging 7 import logging
  8 +from urlparse import urlparse
8 from ..model import Base 9 from ..model import Base
9 10
10 cocar = Cocar(environment='test') 11 cocar = Cocar(environment='test')
@@ -12,6 +13,18 @@ test_dir = os.path.dirname(os.path.realpath(__file__)) @@ -12,6 +13,18 @@ test_dir = os.path.dirname(os.path.realpath(__file__))
12 log = logging.getLogger() 13 log = logging.getLogger()
13 14
14 15
  16 +def fake_urlopen(url):
  17 + """
  18 + A stub urlopen() implementation that load json responses from
  19 + the filesystem.
  20 + """
  21 + # Map path from url to a file
  22 + parsed_url = urlparse(url)
  23 + resource_file = os.path.normpath('tests/fixtures/resources/printer%s' % parsed_url.path)
  24 + # Must return a file-like object
  25 + return open(resource_file, mode='rb')
  26 +
  27 +
15 def setup_package(): 28 def setup_package():
16 """ 29 """
17 Setup test data for the package 30 Setup test data for the package
cocar/tests/test_persistence.py
@@ -5,11 +5,14 @@ __author__ = 'eduardo' @@ -5,11 +5,14 @@ __author__ = 'eduardo'
5 import unittest 5 import unittest
6 import cocar.tests 6 import cocar.tests
7 import time 7 import time
  8 +from mock import patch
8 from ..xml_utils import NmapXML 9 from ..xml_utils import NmapXML
9 -from..csv_utils import NetworkCSV 10 +from ..csv_utils import NetworkCSV
10 from ..model.computer import Computer 11 from ..model.computer import Computer
11 from ..model.printer import Printer, PrinterCounter 12 from ..model.printer import Printer, PrinterCounter
12 from ..model.network import Network 13 from ..model.network import Network
  14 +from . import fake_urlopen
  15 +
13 16
14 17
15 class TestPersistence(unittest.TestCase): 18 class TestPersistence(unittest.TestCase):
@@ -26,6 +29,8 @@ class TestPersistence(unittest.TestCase): @@ -26,6 +29,8 @@ class TestPersistence(unittest.TestCase):
26 self.printer_file = cocar.tests.test_dir + "/fixtures/printer.xml" 29 self.printer_file = cocar.tests.test_dir + "/fixtures/printer.xml"
27 self.network_csv = cocar.tests.test_dir + "/fixtures/networks.csv" 30 self.network_csv = cocar.tests.test_dir + "/fixtures/networks.csv"
28 self.session = cocar.tests.cocar.Session 31 self.session = cocar.tests.cocar.Session
  32 + self.patcher = patch('requests.put', fake_urlopen)
  33 + self.patcher.start()
29 34
30 def test_connect(self): 35 def test_connect(self):
31 """ 36 """
@@ -184,9 +189,65 @@ class TestPersistence(unittest.TestCase): @@ -184,9 +189,65 @@ class TestPersistence(unittest.TestCase):
184 result = printer_counter.update_counter(self.session) 189 result = printer_counter.update_counter(self.session)
185 self.assertFalse(result) 190 self.assertFalse(result)
186 191
  192 + def test_export_printer(self):
  193 + """
  194 + Exporta a impressora para a interface do Cocar
  195 + """
  196 + hostname = '10.72.168.3'
  197 + nmap_xml = NmapXML(self.printer_file)
  198 + host = nmap_xml.parse_xml()
  199 + assert host
  200 +
  201 + printer = nmap_xml.identify_host(hostname)
  202 + self.assertIsInstance(printer, Printer)
  203 +
  204 + printer_counter = PrinterCounter(
  205 + ip_address=printer.ip_address,
  206 + mac_address=printer.mac_address,
  207 + hostname=printer.hostname,
  208 + inclusion_date=printer.inclusion_date,
  209 + open_ports=printer.open_ports,
  210 + scantime=printer.scantime,
  211 + model='Samsung SCX-6x55X Series',
  212 + serial='Z7EUBQBCB03539E',
  213 + description='Samsung SCX-6x55X Series; V2.00.03.01 03-23-2012;Engine 0.41.69;NIC V5.01.82(SCX-6x55X) 02-28-2012;S/N Z7EUBQBCB03539E',
  214 + counter=1280,
  215 + counter_time=time.time()
  216 + )
  217 +
  218 + result = printer_counter.update_counter(self.session)
  219 + assert result
  220 +
  221 + # Adiciona outro contador
  222 + printer_counter = PrinterCounter(
  223 + ip_address=printer.ip_address,
  224 + mac_address=printer.mac_address,
  225 + hostname=printer.hostname,
  226 + inclusion_date=printer.inclusion_date,
  227 + open_ports=printer.open_ports,
  228 + scantime=printer.scantime,
  229 + model='Samsung SCX-6x55X Series',
  230 + serial='Z7EUBQBCB03539E',
  231 + description='Samsung SCX-6x55X Series; V2.00.03.01 03-23-2012;Engine 0.41.69;NIC V5.01.82(SCX-6x55X) 02-28-2012;S/N Z7EUBQBCB03539E',
  232 + counter=1290,
  233 + counter_time=(time.time() + 1)
  234 + )
  235 +
  236 + result = printer_counter.update_counter(self.session)
  237 + assert result
  238 +
  239 + # Exportar a impressora deve retornar 200
  240 + result = printer.export_printer(cocar.tests.cocar.config.get('cocar', 'server_url'), self.session)
  241 + assert result
  242 +
  243 + # Não deve ter mais nenhum impressora na tabela
  244 + result = self.session.query(PrinterCounter).all()
  245 + self.assertEqual(len(result), 0)
  246 +
187 def tearDown(self): 247 def tearDown(self):
188 """ 248 """
189 Remove dados 249 Remove dados
190 """ 250 """
  251 + self.patcher.stop()
191 self.session.close() 252 self.session.close()
192 pass 253 pass
193 \ No newline at end of file 254 \ No newline at end of file
development.ini-dist
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 data_dir = /srv/cocar-agente/cocar_data 2 data_dir = /srv/cocar-agente/cocar_data
3 networks_csv = /srv/cocar-agente/cocar_data/networks.csv 3 networks_csv = /srv/cocar-agente/cocar_data/networks.csv
4 processes = 4 4 processes = 4
  5 +server_url = http://localhost/cocar
5 6
6 [sqlalchemy] 7 [sqlalchemy]
7 url = sqlite:////srv/cocar-agente/cocar-data/tests/cocar-test.db 8 url = sqlite:////srv/cocar-agente/cocar-data/tests/cocar-test.db
@@ -9,7 +9,9 @@ requires = [ @@ -9,7 +9,9 @@ requires = [
9 'lxml', 9 'lxml',
10 'sqlalchemy', 10 'sqlalchemy',
11 'PasteScript', 11 'PasteScript',
12 - 'iptools' 12 + 'iptools',
  13 + 'requests',
  14 + 'mock'
13 ] 15 ]
14 16
15 17