Commit 55a73f12f2d9a0b09e25505f60baf2d9e2ba4019
Committed by
Eduardo Santos
Exists in
master
Versão que já é capaz de armazenar as impressoras e seus contadores no banco de dados.
Showing
8 changed files
with
433 additions
and
16 deletions
Show diff stats
cocar/commands/scan_commands.py
@@ -4,13 +4,20 @@ __author__ = 'eduardo' | @@ -4,13 +4,20 @@ __author__ = 'eduardo' | ||
4 | import logging | 4 | import logging |
5 | import os | 5 | import os |
6 | import os.path | 6 | import os.path |
7 | +import lxml.etree | ||
8 | +import time | ||
9 | +import pickle | ||
7 | from paste.script import command | 10 | from paste.script import command |
8 | from .. import Cocar | 11 | from .. import Cocar |
9 | from ..model import Base | 12 | from ..model import Base |
10 | from ..model.network import Network | 13 | from ..model.network import Network |
14 | +from ..model.printer import Printer, PrinterCounter | ||
15 | +from ..model.host import Host | ||
16 | +from ..model.computer import Computer | ||
11 | from ..csv_utils import NetworkCSV | 17 | from ..csv_utils import NetworkCSV |
12 | -from ..session import NmapSession | 18 | +from ..session import NmapSession, SnmpSession |
13 | from multiprocessing import Process, Queue | 19 | from multiprocessing import Process, Queue |
20 | +from ..xml_utils import NmapXML | ||
14 | 21 | ||
15 | log = logging.getLogger() | 22 | log = logging.getLogger() |
16 | 23 | ||
@@ -26,7 +33,7 @@ class ScanCommands(command.Command): | @@ -26,7 +33,7 @@ class ScanCommands(command.Command): | ||
26 | paster scan networks -c <path to config file> | 33 | paster scan networks -c <path to config file> |
27 | - Faz a busca das redes | 34 | - Faz a busca das redes |
28 | 35 | ||
29 | - Os comandos devem ser executados a partir da raiz do módulo Cocar | 36 | + Os comandos devem ser executados a partir da raiz do modulo Cocar |
30 | """ | 37 | """ |
31 | max_args = 1 | 38 | max_args = 1 |
32 | min_args = 1 | 39 | min_args = 1 |
@@ -77,6 +84,15 @@ class ScanCommands(command.Command): | @@ -77,6 +84,15 @@ class ScanCommands(command.Command): | ||
77 | if cmd == 'scan_networks': | 84 | if cmd == 'scan_networks': |
78 | self.scan_networks() | 85 | self.scan_networks() |
79 | return | 86 | return |
87 | + if cmd == 'load_network_files': | ||
88 | + self.load_network_files() | ||
89 | + return | ||
90 | + if cmd == 'get_printers': | ||
91 | + self.get_printers() | ||
92 | + return | ||
93 | + if cmd == 'continous_scan': | ||
94 | + self.continuous_scan() | ||
95 | + return | ||
80 | else: | 96 | else: |
81 | log.error('Command "%s" not recognized' % (cmd,)) | 97 | log.error('Command "%s" not recognized' % (cmd,)) |
82 | 98 | ||
@@ -148,6 +164,123 @@ class ScanCommands(command.Command): | @@ -148,6 +164,123 @@ class ScanCommands(command.Command): | ||
148 | for i in range(processes): | 164 | for i in range(processes): |
149 | task_queue.put('STOP') | 165 | task_queue.put('STOP') |
150 | 166 | ||
167 | + def load_network_files(self): | ||
168 | + """ | ||
169 | + Load printers from networks files | ||
170 | + :return: | ||
171 | + """ | ||
172 | + onlyfiles = [ f for f in os.listdir(self.networks_dir) if os.path.isfile(os.path.join(self.networks_dir, f)) ] | ||
173 | + for i in range(len(onlyfiles)): | ||
174 | + network_file = self.networks_dir + "/" + onlyfiles[i] | ||
175 | + log.info("Processando arquivo de rede %s", network_file) | ||
176 | + nmap_xml = NmapXML(network_file) | ||
177 | + try: | ||
178 | + host_dict = nmap_xml.parse_xml() | ||
179 | + except AttributeError, e: | ||
180 | + log.error("Erro realizando parsing do arquivo %s\n%s", network_file, e.message) | ||
181 | + continue | ||
182 | + except lxml.etree.XMLSyntaxError, e: | ||
183 | + log.error("Erro realizando parsing do arquivo %s\n%s", network_file, e.message) | ||
184 | + continue | ||
185 | + | ||
186 | + if not host_dict: | ||
187 | + log.error("File %s not found", network_file) | ||
188 | + continue | ||
189 | + session = self.cocar.Session | ||
190 | + for hostname in nmap_xml.hosts.keys(): | ||
191 | + host = nmap_xml.identify_host(hostname) | ||
192 | + if isinstance(host, Printer): | ||
193 | + # Vê se a impressora já está na base | ||
194 | + results = session.query(Printer).filter(Printer.network_ip == hostname).first() | ||
195 | + if results is None: | ||
196 | + log.info("Inserindo impressora com o IP %s", hostname) | ||
197 | + session.add(host) | ||
198 | + else: | ||
199 | + log.info("Impressora com o IP %s já cadastrada", hostname) | ||
200 | + elif isinstance(host, Computer): | ||
201 | + # Vê se o host já está na base | ||
202 | + results = session.query(Computer).filter(Computer.network_ip == hostname).first() | ||
203 | + if results is None: | ||
204 | + log.info("Inserindo computador com o IP %s", hostname) | ||
205 | + session.add(host) | ||
206 | + else: | ||
207 | + log.info("Computador com o IP %s já cadastrado", hostname) | ||
208 | + else: | ||
209 | + # Insere host genérico | ||
210 | + results = session.query(Host).filter(Host.network_ip == hostname).first() | ||
211 | + if results is None: | ||
212 | + log.info("Inserindo host genérico com o IP %s", hostname) | ||
213 | + session.add(host) | ||
214 | + else: | ||
215 | + log.info("Host genérico com o IP %s já cadastrado", hostname) | ||
216 | + | ||
217 | + session.flush() | ||
218 | + | ||
219 | + def get_printers(self): | ||
220 | + """ | ||
221 | + Read printers SNMP Information | ||
222 | + :return: | ||
223 | + """ | ||
224 | + processes = int(self.cocar.config.get('cocar', 'processes')) | ||
225 | + # Create queues | ||
226 | + task_queue = Queue() | ||
227 | + done_queue = Queue() | ||
228 | + | ||
229 | + session = self.cocar.Session | ||
230 | + results = session.query(Printer).all() | ||
231 | + for printer in results: | ||
232 | + log.info("Coletando informacoes da impressora %s", printer.network_ip) | ||
233 | + #printer.network_ip = printer.ip_network | ||
234 | + snmp_session = SnmpSession( | ||
235 | + DestHost=printer.network_ip | ||
236 | + ) | ||
237 | + if snmp_session is None: | ||
238 | + log.error("Erro na coleta SNMP da impressora %s", printer.network_ip) | ||
239 | + continue | ||
240 | + else: | ||
241 | + task_queue.put(snmp_session) | ||
242 | + | ||
243 | + #Start worker processes | ||
244 | + for i in range(processes): | ||
245 | + Process(target=worker_printer, args=(task_queue, done_queue)).start() | ||
246 | + | ||
247 | + # Get and print results | ||
248 | + log.debug('Unordered results:') | ||
249 | + for i in range(len(results)): | ||
250 | + printer_dict = done_queue.get() | ||
251 | + log.debug(printer_dict) | ||
252 | + if printer_dict['counter'] is None: | ||
253 | + log.error("Nao foi possivel ler o contador da impressora %s", printer_dict['network_ip']) | ||
254 | + continue | ||
255 | + | ||
256 | + try: | ||
257 | + log.debug("Gravando contador = %s para a impressora = %s serial = %s", printer_dict['counter'], printer_dict['network_ip'], printer_dict['serial']) | ||
258 | + printer = PrinterCounter( | ||
259 | + ip_address=printer_dict['network_ip'], | ||
260 | + model=printer_dict['model'], | ||
261 | + serial=printer_dict['serial'], | ||
262 | + description=printer_dict['description'], | ||
263 | + counter=printer_dict['counter'], | ||
264 | + counter_time=time.time() | ||
265 | + ) | ||
266 | + printer.update_counter(session) | ||
267 | + except AttributeError, e: | ||
268 | + log.error("Erro na inserção do contador para a impressora %s\n%s", printer_dict['network_ip'], e.message) | ||
269 | + continue | ||
270 | + | ||
271 | + # Tell child processes to stop | ||
272 | + for i in range(processes): | ||
273 | + task_queue.put('STOP') | ||
274 | + | ||
275 | + def continuous_scan(self): | ||
276 | + """ | ||
277 | + Fica varrendo a rede até parar por execução forçada | ||
278 | + """ | ||
279 | + print("*** Aperente CTRL+C para encerrar a execução ***") | ||
280 | + | ||
281 | + while True: | ||
282 | + self.scan_networks() | ||
283 | + | ||
151 | 284 | ||
152 | def make_query(host): | 285 | def make_query(host): |
153 | """This does the actual snmp query | 286 | """This does the actual snmp query |
@@ -160,8 +293,26 @@ def make_query(host): | @@ -160,8 +293,26 @@ def make_query(host): | ||
160 | return host.scan() | 293 | return host.scan() |
161 | 294 | ||
162 | 295 | ||
296 | +def make_query_printer(host): | ||
297 | + """This does the actual snmp query | ||
298 | + | ||
299 | + This is a bit fancy as it accepts both instances | ||
300 | + of SnmpSession and host/ip addresses. This | ||
301 | + allows a user to customize mass queries with | ||
302 | + subsets of different hostnames and community strings | ||
303 | + """ | ||
304 | + return host.printer_dict() | ||
305 | + | ||
306 | + | ||
163 | # Function run by worker processes | 307 | # Function run by worker processes |
164 | def worker(inp, output): | 308 | def worker(inp, output): |
165 | for func in iter(inp.get, 'STOP'): | 309 | for func in iter(inp.get, 'STOP'): |
166 | result = make_query(func) | 310 | result = make_query(func) |
311 | + output.put(result) | ||
312 | + | ||
313 | + | ||
314 | +# Function run by worker processes | ||
315 | +def worker_printer(inp, output): | ||
316 | + for func in iter(inp.get, 'STOP'): | ||
317 | + result = make_query_printer(func) | ||
167 | output.put(result) | 318 | output.put(result) |
168 | \ No newline at end of file | 319 | \ No newline at end of file |
cocar/model/host.py
@@ -47,9 +47,15 @@ class Host(Base): | @@ -47,9 +47,15 @@ class Host(Base): | ||
47 | 47 | ||
48 | # Parâmetros do SQLAlchemy | 48 | # Parâmetros do SQLAlchemy |
49 | self.network_ip = str(self.ip_address) | 49 | self.network_ip = str(self.ip_address) |
50 | - self.ports = ','.join(map(str, self.open_ports.keys())) | ||
51 | - if len(self.hostname.values()) > 0: | ||
52 | - self.name = self.hostname.values()[0] | 50 | + if self.open_ports is not None: |
51 | + self.ports = ','.join(map(str, self.open_ports.keys())) | ||
52 | + else: | ||
53 | + self.ports = None | ||
54 | + if self.hostname is not None: | ||
55 | + if len(self.hostname.values()) > 0: | ||
56 | + self.name = self.hostname.values()[0] | ||
57 | + else: | ||
58 | + self.name = None | ||
53 | else: | 59 | else: |
54 | self.name = None | 60 | self.name = None |
55 | 61 |
cocar/model/printer.py
1 | #!/bin/env python | 1 | #!/bin/env python |
2 | # -*- coding: utf-8 -*- | 2 | # -*- coding: utf-8 -*- |
3 | __author__ = 'eduardo' | 3 | __author__ = 'eduardo' |
4 | - | 4 | +import logging |
5 | from .host import Host | 5 | from .host import Host |
6 | from sqlalchemy import ForeignKey | 6 | from sqlalchemy import ForeignKey |
7 | from sqlalchemy.schema import Column | 7 | from sqlalchemy.schema import Column |
8 | from sqlalchemy.types import String, Integer | 8 | from sqlalchemy.types import String, Integer |
9 | +from sqlalchemy import and_, insert, update | ||
10 | + | ||
11 | +log = logging.getLogger() | ||
9 | 12 | ||
10 | 13 | ||
11 | class Printer(Host): | 14 | class Printer(Host): |
@@ -14,12 +17,11 @@ class Printer(Host): | @@ -14,12 +17,11 @@ class Printer(Host): | ||
14 | """ | 17 | """ |
15 | __tablename__ = 'printer' | 18 | __tablename__ = 'printer' |
16 | network_ip = Column(String(16), ForeignKey("host.network_ip"), nullable=False, primary_key=True) | 19 | network_ip = Column(String(16), ForeignKey("host.network_ip"), nullable=False, primary_key=True) |
17 | - counter = Column(Integer) | 20 | + model = Column(String) |
18 | serial = Column(String(50)) | 21 | serial = Column(String(50)) |
19 | description = Column(String) | 22 | description = Column(String) |
20 | 23 | ||
21 | def __init__(self, | 24 | def __init__(self, |
22 | - counter=None, | ||
23 | model=None, | 25 | model=None, |
24 | serial=None, | 26 | serial=None, |
25 | description=None, | 27 | description=None, |
@@ -32,7 +34,62 @@ class Printer(Host): | @@ -32,7 +34,62 @@ class Printer(Host): | ||
32 | :param serial: Número de série da impressora | 34 | :param serial: Número de série da impressora |
33 | """ | 35 | """ |
34 | Host.__init__(self, *args, **kwargs) | 36 | Host.__init__(self, *args, **kwargs) |
35 | - self.counter = counter | ||
36 | self.model = model | 37 | self.model = model |
37 | self.serial = serial | 38 | self.serial = serial |
38 | - self.description = description | ||
39 | \ No newline at end of file | 39 | \ No newline at end of file |
40 | + self.description = description | ||
41 | + | ||
42 | + | ||
43 | +class PrinterCounter(Printer): | ||
44 | + """ | ||
45 | + Classe que armazena o contador das impressoras | ||
46 | + """ | ||
47 | + __tablename__ = 'printer_counter' | ||
48 | + network_ip = Column(String(16), ForeignKey("printer.network_ip"), nullable=False) | ||
49 | + counter = Column(Integer, nullable=False, primary_key=True) | ||
50 | + counter_time = Column(String(50), nullable=False, primary_key=True) | ||
51 | + | ||
52 | + def __init__(self, | ||
53 | + counter, | ||
54 | + counter_time, | ||
55 | + *args, | ||
56 | + **kwargs | ||
57 | + ): | ||
58 | + super(PrinterCounter, self).__init__(*args, **kwargs) | ||
59 | + self.counter = counter | ||
60 | + self.counter_time = counter_time | ||
61 | + | ||
62 | + def update_counter(self, session): | ||
63 | + """ | ||
64 | + Atualiza contador da impressora | ||
65 | + :param session: SQLAlchemy session | ||
66 | + :return boolean: True if inserted | ||
67 | + """ | ||
68 | + results = session.query(self.__table__).filter( | ||
69 | + and_( | ||
70 | + self.__table__.c.counter == self.counter, | ||
71 | + self.__table__.c.counter_time == self.counter_time) | ||
72 | + ).first() | ||
73 | + print(results) | ||
74 | + if results is None: | ||
75 | + log.debug("Inserindo contador para impressora %s serial %s", self.network_ip, self.serial) | ||
76 | + session.execute( | ||
77 | + self.__table__.insert().values( | ||
78 | + network_ip=self.network_ip, | ||
79 | + counter=self.counter, | ||
80 | + counter_time=self.counter_time | ||
81 | + ) | ||
82 | + ) | ||
83 | + return True | ||
84 | + | ||
85 | + session.execute( | ||
86 | + Printer.__table__.update().values( | ||
87 | + model=self.model, | ||
88 | + description=self.description, | ||
89 | + serial=self.serial | ||
90 | + ).where( | ||
91 | + Printer.__table__.c.network_ip == self.network_ip | ||
92 | + ) | ||
93 | + ) | ||
94 | + | ||
95 | + session.flush() | ||
96 | + return False | ||
40 | \ No newline at end of file | 97 | \ No newline at end of file |
cocar/session.py
@@ -23,7 +23,7 @@ class Host(object): | @@ -23,7 +23,7 @@ class Host(object): | ||
23 | self.query = query | 23 | self.query = query |
24 | 24 | ||
25 | 25 | ||
26 | -class SnmpSession(Cocar): | 26 | +class SnmpSession(object): |
27 | """A SNMP Session""" | 27 | """A SNMP Session""" |
28 | def __init__(self, | 28 | def __init__(self, |
29 | oid=".1.3.6.1.2.1.1.1.0", | 29 | oid=".1.3.6.1.2.1.1.1.0", |
@@ -33,7 +33,6 @@ class SnmpSession(Cocar): | @@ -33,7 +33,6 @@ class SnmpSession(Cocar): | ||
33 | Community="public", | 33 | Community="public", |
34 | Verbose=True, | 34 | Verbose=True, |
35 | ): | 35 | ): |
36 | - Cocar.__init__(self) | ||
37 | self.oid = oid | 36 | self.oid = oid |
38 | self.Version = Version | 37 | self.Version = Version |
39 | self.DestHost = DestHost | 38 | self.DestHost = DestHost |
@@ -43,6 +42,12 @@ class SnmpSession(Cocar): | @@ -43,6 +42,12 @@ class SnmpSession(Cocar): | ||
43 | self.hostrec = Host() | 42 | self.hostrec = Host() |
44 | self.hostrec.hostname = self.DestHost | 43 | self.hostrec.hostname = self.DestHost |
45 | 44 | ||
45 | + self.status = ['1.3.6.1.2.1.25.3.5.1.1.1'] | ||
46 | + self.serial = ['1.3.6.1.2.1.43.5.1.1.17'] | ||
47 | + self.model = ['1.3.6.1.2.1.25.3.2.1.3.1'] | ||
48 | + self.counter = ['1.3.6.1.2.1.43.10.2.1.4.1.1'] | ||
49 | + self.messages = ['1.3.6.1.2.1.43.18.1.1.8'] | ||
50 | + | ||
46 | def query(self): | 51 | def query(self): |
47 | """Creates SNMP query | 52 | """Creates SNMP query |
48 | 53 | ||
@@ -61,6 +66,114 @@ class SnmpSession(Cocar): | @@ -61,6 +66,114 @@ class SnmpSession(Cocar): | ||
61 | finally: | 66 | finally: |
62 | return self.hostrec | 67 | return self.hostrec |
63 | 68 | ||
69 | + def printer_full(self): | ||
70 | + """ | ||
71 | + Retorna status full da impressora, com todos os atributos | ||
72 | + """ | ||
73 | + status = self.query() | ||
74 | + if status is None: | ||
75 | + return None | ||
76 | + else: | ||
77 | + return status.query | ||
78 | + | ||
79 | + def printer_status(self): | ||
80 | + """ | ||
81 | + Retorna status da impressora | ||
82 | + | ||
83 | + Opções de status: | ||
84 | + | ||
85 | + 1 - unknown | ||
86 | + 2 - runnning | ||
87 | + 3 - warning | ||
88 | + 4 - testing | ||
89 | + 5 - down | ||
90 | + """ | ||
91 | + status = None | ||
92 | + for elm in self.status: | ||
93 | + self.oid = elm | ||
94 | + status = self.query() | ||
95 | + # A primeira vez que conseguir retornar um status, para | ||
96 | + if status is not None: | ||
97 | + break | ||
98 | + if status is None: | ||
99 | + return None | ||
100 | + else: | ||
101 | + return status.query | ||
102 | + | ||
103 | + def printer_counter(self): | ||
104 | + """ | ||
105 | + Retorna contador da impressora | ||
106 | + """ | ||
107 | + status = None | ||
108 | + for elm in self.counter: | ||
109 | + self.oid = elm | ||
110 | + status = self.query() | ||
111 | + # A primeira vez que conseguir retornar um status, para | ||
112 | + if status is not None: | ||
113 | + break | ||
114 | + | ||
115 | + if status is None: | ||
116 | + return None | ||
117 | + else: | ||
118 | + return status.query | ||
119 | + | ||
120 | + def printer_model(self): | ||
121 | + """ | ||
122 | + Retorna contador da impressora | ||
123 | + """ | ||
124 | + status = None | ||
125 | + for elm in self.model: | ||
126 | + self.oid = elm | ||
127 | + status = self.query() | ||
128 | + # A primeira vez que conseguir retornar um status, para | ||
129 | + if status is not None: | ||
130 | + break | ||
131 | + | ||
132 | + if status is None: | ||
133 | + return None | ||
134 | + else: | ||
135 | + return status.query | ||
136 | + | ||
137 | + def printer_serial(self): | ||
138 | + """ | ||
139 | + Retorna contador da impressora | ||
140 | + """ | ||
141 | + status = None | ||
142 | + for elm in self.serial: | ||
143 | + self.oid = elm | ||
144 | + status = self.query() | ||
145 | + # A primeira vez que conseguir retornar um status, para | ||
146 | + if status is not None: | ||
147 | + break | ||
148 | + | ||
149 | + if status is None: | ||
150 | + return None | ||
151 | + else: | ||
152 | + return status.query | ||
153 | + | ||
154 | + def printer_dict(self): | ||
155 | + """ | ||
156 | + Retorna o status de todos os atributos em um dicionário | ||
157 | + """ | ||
158 | + full = self.printer_full() | ||
159 | + serial = self.printer_serial() | ||
160 | + model = self.printer_model() | ||
161 | + counter = self.printer_counter() | ||
162 | + status = self.printer_status() | ||
163 | + | ||
164 | + return_dict = { | ||
165 | + 'description': full[0], | ||
166 | + 'serial': serial[0], | ||
167 | + 'model': model[0], | ||
168 | + 'counter': counter[0], | ||
169 | + 'status': status[0], | ||
170 | + 'network_ip': self.DestHost | ||
171 | + } | ||
172 | + | ||
173 | + log.debug(return_dict) | ||
174 | + | ||
175 | + return return_dict | ||
176 | + | ||
64 | 177 | ||
65 | class NmapSession(object): | 178 | class NmapSession(object): |
66 | """ | 179 | """ |
@@ -103,7 +216,7 @@ class NmapSession(object): | @@ -103,7 +216,7 @@ class NmapSession(object): | ||
103 | "nmap", | 216 | "nmap", |
104 | "-PE", | 217 | "-PE", |
105 | "-PP", | 218 | "-PP", |
106 | - "-PS21,22,23,25,80,443,3306,3389,8080", | 219 | + "-PS21,22,23,25,80,443,631,3306,3389,8080,9100", |
107 | "-O", | 220 | "-O", |
108 | str(self.host), | 221 | str(self.host), |
109 | "-oX", | 222 | "-oX", |
cocar/tests/__init__.py
@@ -4,16 +4,25 @@ __author__ = 'eduardo' | @@ -4,16 +4,25 @@ __author__ = 'eduardo' | ||
4 | from .. import Cocar | 4 | from .. import Cocar |
5 | import os | 5 | import os |
6 | import os.path | 6 | import os.path |
7 | +import logging | ||
7 | from ..model import Base | 8 | from ..model import Base |
8 | 9 | ||
9 | cocar = Cocar(environment='test') | 10 | cocar = Cocar(environment='test') |
10 | test_dir = os.path.dirname(os.path.realpath(__file__)) | 11 | test_dir = os.path.dirname(os.path.realpath(__file__)) |
12 | +log = logging.getLogger() | ||
11 | 13 | ||
12 | 14 | ||
13 | def setup_package(): | 15 | def setup_package(): |
14 | """ | 16 | """ |
15 | Setup test data for the package | 17 | Setup test data for the package |
16 | """ | 18 | """ |
19 | + log.debug("Diretório de dados do Cocar: %s", cocar.cocar_data_dir) | ||
20 | + test_dir = cocar.cocar_data_dir + "/tests" | ||
21 | + if not os.path.isdir(test_dir): | ||
22 | + log.info("Criando diretório de testes %s", test_dir) | ||
23 | + os.mkdir(test_dir) | ||
24 | + | ||
25 | + log.info(cocar.engine) | ||
17 | Base.metadata.create_all(cocar.engine) | 26 | Base.metadata.create_all(cocar.engine) |
18 | pass | 27 | pass |
19 | 28 |
cocar/tests/test_persistence.py
@@ -4,10 +4,11 @@ __author__ = 'eduardo' | @@ -4,10 +4,11 @@ __author__ = 'eduardo' | ||
4 | 4 | ||
5 | import unittest | 5 | import unittest |
6 | import cocar.tests | 6 | import cocar.tests |
7 | +import time | ||
7 | from ..xml_utils import NmapXML | 8 | from ..xml_utils import NmapXML |
8 | from..csv_utils import NetworkCSV | 9 | from..csv_utils import NetworkCSV |
9 | from ..model.computer import Computer | 10 | from ..model.computer import Computer |
10 | -from ..model.printer import Printer | 11 | +from ..model.printer import Printer, PrinterCounter |
11 | from ..model.network import Network | 12 | from ..model.network import Network |
12 | 13 | ||
13 | 14 | ||
@@ -107,6 +108,82 @@ class TestPersistence(unittest.TestCase): | @@ -107,6 +108,82 @@ class TestPersistence(unittest.TestCase): | ||
107 | results = self.session.query(Network).first() | 108 | results = self.session.query(Network).first() |
108 | self.assertIsNotNone(results) | 109 | self.assertIsNotNone(results) |
109 | 110 | ||
111 | + def test_printer_counter(self): | ||
112 | + """ | ||
113 | + Testa inserção do contador em uma impressora | ||
114 | + """ | ||
115 | + hostname = '10.72.168.4' | ||
116 | + ports = { | ||
117 | + "9100": { | ||
118 | + "state": "open", | ||
119 | + "protocol": "tcp", | ||
120 | + "service": "vnc-http" | ||
121 | + }, | ||
122 | + "631": { | ||
123 | + "state": "open", | ||
124 | + "protocol": "tcp", | ||
125 | + "service": "vnc-http" | ||
126 | + } | ||
127 | + } | ||
128 | + | ||
129 | + # Agora verifica a inserção do contador | ||
130 | + counter = PrinterCounter( | ||
131 | + ip_address=hostname, | ||
132 | + mac_address=None, | ||
133 | + hostname=None, | ||
134 | + inclusion_date=time.time(), | ||
135 | + open_ports=ports, | ||
136 | + scantime='3600', | ||
137 | + model='Samsung SCX-6x55X Series', | ||
138 | + serial='Z7EUBQBCB03539E', | ||
139 | + 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', | ||
140 | + counter=1280, | ||
141 | + counter_time=time.time() | ||
142 | + ) | ||
143 | + | ||
144 | + self.assertIsInstance(counter, PrinterCounter) | ||
145 | + self.assertEqual(counter.counter, 1280) | ||
146 | + self.assertEqual(counter.network_ip, hostname) | ||
147 | + | ||
148 | + self.session.add(counter) | ||
149 | + self.session.flush() | ||
150 | + # Tenta ver se gravou | ||
151 | + results = self.session.query(PrinterCounter).first() | ||
152 | + self.assertIsNotNone(results) | ||
153 | + | ||
154 | + def test_update_counter(self): | ||
155 | + """ | ||
156 | + Testa inserção dos parâmetros do contador em impressora existente | ||
157 | + """ | ||
158 | + hostname = '10.72.168.3' | ||
159 | + nmap_xml = NmapXML(self.printer_file) | ||
160 | + host = nmap_xml.parse_xml() | ||
161 | + assert host | ||
162 | + | ||
163 | + printer = nmap_xml.identify_host(hostname) | ||
164 | + self.assertIsInstance(printer, Printer) | ||
165 | + | ||
166 | + printer_counter = PrinterCounter( | ||
167 | + ip_address=printer.ip_address, | ||
168 | + mac_address=printer.mac_address, | ||
169 | + hostname=printer.hostname, | ||
170 | + inclusion_date=printer.inclusion_date, | ||
171 | + open_ports=printer.open_ports, | ||
172 | + scantime=printer.scantime, | ||
173 | + model='Samsung SCX-6x55X Series', | ||
174 | + serial='Z7EUBQBCB03539E', | ||
175 | + 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', | ||
176 | + counter=1280, | ||
177 | + counter_time=time.time() | ||
178 | + ) | ||
179 | + | ||
180 | + result = printer_counter.update_counter(self.session) | ||
181 | + assert result | ||
182 | + | ||
183 | + # Aqui não pode inserir de novo | ||
184 | + result = printer_counter.update_counter(self.session) | ||
185 | + self.assertFalse(result) | ||
186 | + | ||
110 | def tearDown(self): | 187 | def tearDown(self): |
111 | """ | 188 | """ |
112 | Remove dados | 189 | Remove dados |
cocar/xml_utils.py
@@ -50,10 +50,14 @@ class NmapXML(object): | @@ -50,10 +50,14 @@ class NmapXML(object): | ||
50 | ports = element.find('ports') | 50 | ports = element.find('ports') |
51 | self.hosts[host]['ports'] = dict() | 51 | self.hosts[host]['ports'] = dict() |
52 | for port_xml in ports.findall('port'): | 52 | for port_xml in ports.findall('port'): |
53 | + if port_xml.find('service') is not None: | ||
54 | + service = port_xml.find('service').get('name') | ||
55 | + else: | ||
56 | + service = None | ||
53 | self.hosts[host]['ports'][port_xml.get('portid')] = { | 57 | self.hosts[host]['ports'][port_xml.get('portid')] = { |
54 | 'protocol': port_xml.get('protocol'), | 58 | 'protocol': port_xml.get('protocol'), |
55 | 'state': port_xml.find('state').get('state'), | 59 | 'state': port_xml.find('state').get('state'), |
56 | - 'service': port_xml.find('service').get('name'), | 60 | + 'service': service, |
57 | } | 61 | } |
58 | 62 | ||
59 | # OS Matches | 63 | # OS Matches |
development.ini-dist