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 97 if cmd == 'printer_scan':
98 98 self.printer_scan()
99 99 return
  100 + if cmd == 'export_printers':
  101 + self.export_printers()
  102 + return
100 103 else:
101 104 log.error('Command "%s" not recognized' % (cmd,))
102 105  
... ... @@ -313,6 +316,16 @@ class ScanCommands(command.Command):
313 316 log.info("SCAN DE IMPRESSORAS FINALIZADO!!! Dormindo...")
314 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 330 def make_query(host):
318 331 """This does the actual snmp query
... ...
cocar/model/printer.py
... ... @@ -2,6 +2,10 @@
2 2 # -*- coding: utf-8 -*-
3 3 __author__ = 'eduardo'
4 4 import logging
  5 +import requests
  6 +import json
  7 +from requests.exceptions import HTTPError
  8 +from sqlalchemy.orm import aliased
5 9 from .host import Host
6 10 from sqlalchemy import ForeignKey
7 11 from sqlalchemy.schema import Column
... ... @@ -38,6 +42,26 @@ class Printer(Host):
38 42 self.serial = serial
39 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 66 class PrinterCounter(Printer):
43 67 """
... ... @@ -67,9 +91,10 @@ class PrinterCounter(Printer):
67 91 results = session.query(self.__table__).filter(
68 92 and_(
69 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 98 if results is None:
74 99 log.debug("Inserindo contador para impressora %s serial %s", self.network_ip, self.serial)
75 100 session.execute(
... ... @@ -92,4 +117,49 @@ class PrinterCounter(Printer):
92 117 )
93 118  
94 119 session.flush()
95   - return False
96 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 167 \ No newline at end of file
... ...
cocar/tests/__init__.py
... ... @@ -5,6 +5,7 @@ from .. import Cocar
5 5 import os
6 6 import os.path
7 7 import logging
  8 +from urlparse import urlparse
8 9 from ..model import Base
9 10  
10 11 cocar = Cocar(environment='test')
... ... @@ -12,6 +13,18 @@ test_dir = os.path.dirname(os.path.realpath(__file__))
12 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 28 def setup_package():
16 29 """
17 30 Setup test data for the package
... ...
cocar/tests/test_persistence.py
... ... @@ -5,11 +5,14 @@ __author__ = 'eduardo'
5 5 import unittest
6 6 import cocar.tests
7 7 import time
  8 +from mock import patch
8 9 from ..xml_utils import NmapXML
9   -from..csv_utils import NetworkCSV
  10 +from ..csv_utils import NetworkCSV
10 11 from ..model.computer import Computer
11 12 from ..model.printer import Printer, PrinterCounter
12 13 from ..model.network import Network
  14 +from . import fake_urlopen
  15 +
13 16  
14 17  
15 18 class TestPersistence(unittest.TestCase):
... ... @@ -26,6 +29,8 @@ class TestPersistence(unittest.TestCase):
26 29 self.printer_file = cocar.tests.test_dir + "/fixtures/printer.xml"
27 30 self.network_csv = cocar.tests.test_dir + "/fixtures/networks.csv"
28 31 self.session = cocar.tests.cocar.Session
  32 + self.patcher = patch('requests.put', fake_urlopen)
  33 + self.patcher.start()
29 34  
30 35 def test_connect(self):
31 36 """
... ... @@ -184,9 +189,65 @@ class TestPersistence(unittest.TestCase):
184 189 result = printer_counter.update_counter(self.session)
185 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 247 def tearDown(self):
188 248 """
189 249 Remove dados
190 250 """
  251 + self.patcher.stop()
191 252 self.session.close()
192 253 pass
193 254 \ No newline at end of file
... ...
development.ini-dist
... ... @@ -2,6 +2,7 @@
2 2 data_dir = /srv/cocar-agente/cocar_data
3 3 networks_csv = /srv/cocar-agente/cocar_data/networks.csv
4 4 processes = 4
  5 +server_url = http://localhost/cocar
5 6  
6 7 [sqlalchemy]
7 8 url = sqlite:////srv/cocar-agente/cocar-data/tests/cocar-test.db
... ...
setup.py
... ... @@ -9,7 +9,9 @@ requires = [
9 9 'lxml',
10 10 'sqlalchemy',
11 11 'PasteScript',
12   - 'iptools'
  12 + 'iptools',
  13 + 'requests',
  14 + 'mock'
13 15 ]
14 16  
15 17  
... ...