· 9 years ago · Apr 06, 2017, 08:02 AM
1# -*- coding: utf-8; -*-
2#
3# (c) 2004-2007 Linbox / Free&ALter Soft, http://linbox.com
4# (c) 2007-2010 Mandriva, http://www.mandriva.com
5#
6# $Id$
7#
8# This file is part of Mandriva Management Console (MMC).
9#
10# MMC is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# MMC is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with MMC. If not, see <http://www.gnu.org/licenses/>.
22
23"""
24This module declare all the necessary stuff to connect to a glpi database in it's
25version 9.1
26"""
27import os
28import logging
29import re
30from sets import Set
31import datetime
32import calendar, hashlib
33import time
34from configobj import ConfigObj
35from xmlrpclib import ProtocolError
36
37from sqlalchemy import and_, create_engine, MetaData, Table, Column, String, \
38 Integer, Date, ForeignKey, asc, or_, not_, desc, func, distinct
39from sqlalchemy.orm import create_session, mapper, relationship
40
41try:
42 from sqlalchemy.sql.expression import ColumnOperators
43except ImportError:
44 from sqlalchemy.sql.operators import ColumnOperators
45from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
46from sqlalchemy.exc import OperationalError
47from mmc.support.mmctools import shlaunch
48import base64
49import json
50import requests
51from mmc.site import mmcconfdir
52from mmc.database.database_helper import DatabaseHelper
53# TODO rename location into entity (and locations in location)
54from pulse2.utils import same_network, unique, noNone
55from pulse2.database.dyngroup.dyngroup_database_helper import DyngroupDatabaseHelper
56from pulse2.managers.group import ComputerGroupManager
57from mmc.plugins.glpi.config import GlpiConfig
58from mmc.plugins.glpi.GLPIClient import XMLRPCClient
59from mmc.plugins.glpi.utilities import complete_ctx
60from mmc.plugins.glpi.database_utils import decode_latin1, encode_latin1, decode_utf8, encode_utf8, fromUUID, toUUID, \
61 setUUID
62from mmc.plugins.glpi.database_utils import DbTOA # pyflakes.ignore
63from mmc.plugins.dyngroup.config import DGConfig
64from distutils.version import LooseVersion, StrictVersion
65
66
67class Glpi91(DyngroupDatabaseHelper):
68 """
69 Singleton Class to query the glpi database in version > 0.80.
70
71 """
72 is_activated = False
73
74 def db_check(self):
75 self.my_name = "Glpi"
76 self.configfile = "glpi.ini"
77 return DyngroupDatabaseHelper.db_check(self)
78
79 def try_activation(self, config):
80 """
81 function to see if that glpi database backend is the one we need to use
82 """
83 self.config = config
84 dburi = self.makeConnectionPath()
85 self.db = create_engine(dburi, pool_recycle=self.config.dbpoolrecycle, pool_size=self.config.dbpoolsize)
86 logging.getLogger().debug('Trying to detect if GLPI version is higher than 9.1')
87 try:
88 self._glpi_version = self.db.execute('SELECT version FROM glpi_configs').fetchone().values()[0].replace(' ',
89 '')
90 except OperationalError:
91 self._glpi_version = \
92 self.db.execute('SELECT value FROM glpi_configs WHERE name = "version"').fetchone().values()[0].replace(' ',
93 '')
94 if LooseVersion(self._glpi_version) >= LooseVersion("9.1") and LooseVersion(self._glpi_version) <= LooseVersion(
95 "9.1.1"):
96 logging.getLogger().debug('GLPI version %s found !' % self._glpi_version)
97 return True
98 else:
99 logging.getLogger().debug('GLPI higher than version 9.1 was not detected')
100 return False
101
102 @property
103 def glpi_version(self):
104 return self._glpi_version
105
106 def glpi_version_new(self):
107 return False
108
109 def activate(self, config=None):
110 self.logger = logging.getLogger()
111 DyngroupDatabaseHelper.init(self)
112 if self.is_activated:
113 self.logger.info("Glpi don't need activation")
114 return None
115 self.logger.info("Glpi is activating")
116 if config != None:
117 self.config = config
118 else:
119 self.config = GlpiConfig("glpi")
120 dburi = self.makeConnectionPath()
121 self.db = create_engine(dburi, pool_recycle=self.config.dbpoolrecycle, pool_size=self.config.dbpoolsize)
122 try:
123 self.db.execute(u'SELECT "\xe9"')
124 setattr(Glpi91, "decode", decode_utf8)
125 setattr(Glpi91, "encode", encode_utf8)
126 except:
127 self.logger.warn("Your database is not in utf8, will fallback in latin1")
128 setattr(Glpi91, "decode", decode_latin1)
129 setattr(Glpi91, "encode", encode_latin1)
130 try:
131 self._glpi_version = self.db.execute('SELECT version FROM glpi_configs').fetchone().values()[0].replace(' ',
132 '')
133 except OperationalError:
134 self._glpi_version = \
135 self.db.execute('SELECT value FROM glpi_configs WHERE name = "version"').fetchone().values()[0].replace(' ',
136 '')
137 self.metadata = MetaData(self.db)
138 self.initMappers()
139 self.logger.info("Glpi is in version %s" % (self.glpi_version))
140 self.metadata.create_all()
141 self.is_activated = True
142 self.logger.debug("Glpi finish activation")
143
144 searchOptionConfFile = os.path.join(mmcconfdir, "plugins", "glpi_search_options.ini")
145 self.searchOptions = ConfigObj(searchOptionConfFile)
146
147 return True
148
149 def getTableName(self, name):
150 return ''.join(map(lambda x: x.capitalize(), name.split('_')))
151
152 def initMappers(self):
153 """
154 Initialize all SQLalchemy mappers needed for the inventory database
155 """
156
157 self.klass = {}
158
159 # simply declare some tables (that dont need and FK relations, or anything special to declare)
160 for i in ('glpi_operatingsystemversions', 'glpi_computertypes', 'glpi_operatingsystems',
161 'glpi_operatingsystemservicepacks', 'glpi_domains', \
162 'glpi_computermodels', 'glpi_networks'):
163 setattr(self, i, Table(i, self.metadata, autoload=True))
164 j = self.getTableName(i)
165 exec "class %s(DbTOA): pass" % j
166 mapper(eval(j), getattr(self, i))
167 self.klass[i] = eval(j)
168
169 # declare all the glpi_device* and glpi_computer_device*
170 # two of these tables have a nomenclature one (devicecasetypes and devicememorytypes) but we dont need it for the moment.
171 #
172 # List of devices:
173 # cases, controls, drives, graphiccards, harddrives, motherboards, networkcards,
174 # pcis, powersupplies, soundcards
175
176 self.devices = ('devicecases', 'devicecontrols', 'devicedrives', 'devicegraphiccards', 'deviceharddrives', \
177 'devicemotherboards', 'devicenetworkcards', 'devicepcis', 'devicepowersupplies',
178 'devicesoundcards')
179 for i in self.devices:
180 setattr(self, i, Table("glpi_%s" % i, self.metadata, autoload=True))
181 j = self.getTableName(i)
182 exec "class %s(DbTOA): pass" % j
183 mapper(eval(j), getattr(self, i))
184 self.klass[i] = eval(j)
185
186 setattr(self, "computers_%s" % i, Table("glpi_items_%s" % i, self.metadata,
187 Column('items_id', Integer, ForeignKey('glpi_computers.id')),
188 Column('%s_id' % i, Integer, ForeignKey('glpi_%s.id' % i)),
189 autoload=True))
190 j = self.getTableName("computers_%s" % i)
191 exec "class %s(DbTOA): pass" % j
192 mapper(eval(j), getattr(self, "computers_%s" % i))
193 self.klass["computers_%s" % i] = eval(j)
194
195 # entity
196 self.entities = Table("glpi_entities", self.metadata, autoload=True)
197 mapper(Entities, self.entities)
198
199 # rules
200 self.rules = Table("glpi_rules", self.metadata, autoload=True)
201 mapper(Rule, self.rules)
202
203 self.rule_criterias = Table("glpi_rulecriterias", self.metadata, autoload=True)
204 mapper(RuleCriterion, self.rule_criterias)
205
206 self.rule_actions = Table("glpi_ruleactions", self.metadata, autoload=True)
207 mapper(RuleAction, self.rule_actions)
208
209 # location
210 self.locations = Table("glpi_locations", self.metadata, autoload=True)
211 mapper(Locations, self.locations)
212
213 # logs
214 self.logs = Table("glpi_logs", self.metadata,
215 Column('items_id', Integer, ForeignKey('glpi_computers.id')),
216 autoload=True)
217 mapper(Logs, self.logs)
218
219 # processor
220 self.processor = Table("glpi_deviceprocessors", self.metadata, autoload=True)
221 mapper(Processor, self.processor)
222
223 self.computerProcessor = Table("glpi_items_deviceprocessors", self.metadata,
224 Column('items_id', Integer, ForeignKey('glpi_computers.id')),
225 Column('deviceprocessors_id', Integer, ForeignKey('glpi_deviceprocessors.id')),
226 autoload=True)
227 mapper(ComputerProcessor, self.computerProcessor)
228
229 # memory
230 self.memory = Table("glpi_devicememories", self.metadata,
231 Column('devicememorytypes_id', Integer, ForeignKey('glpi_devicememorytypes.id')),
232 autoload=True)
233 mapper(Memory, self.memory)
234
235 self.memoryType = Table("glpi_devicememorytypes", self.metadata, autoload=True)
236 mapper(MemoryType, self.memoryType)
237
238 self.computerMemory = Table("glpi_items_devicememories", self.metadata,
239 Column('items_id', Integer, ForeignKey('glpi_computers.id')),
240 Column('devicememories_id', Integer, ForeignKey('glpi_devicememories.id')),
241 autoload=True)
242 mapper(ComputerMemory, self.computerMemory)
243
244 # interfaces types
245 self.interfaceType = Table("glpi_interfacetypes", self.metadata, autoload=True)
246
247 # os
248 self.os = Table("glpi_operatingsystems", self.metadata, autoload=True)
249 mapper(OS, self.os)
250
251 self.os_sp = Table("glpi_operatingsystemservicepacks", self.metadata, autoload=True)
252 mapper(OsSp, self.os_sp)
253
254 # domain
255 self.domain = Table('glpi_domains', self.metadata, autoload=True)
256 mapper(Domain, self.domain)
257
258 # glpi_infocoms
259 self.infocoms = Table('glpi_infocoms', self.metadata,
260 Column('suppliers_id', Integer, ForeignKey('glpi_suppliers.id')),
261 Column('items_id', Integer, ForeignKey('glpi_computers.id')),
262 autoload=True)
263 mapper(Infocoms, self.infocoms)
264
265 # glpi_suppliers
266 self.suppliers = Table('glpi_suppliers', self.metadata, autoload=True)
267 mapper(Suppliers, self.suppliers)
268
269 # glpi_filesystems
270 self.diskfs = Table('glpi_filesystems', self.metadata, autoload=True)
271 mapper(DiskFs, self.diskfs)
272
273 ## Fusion Inventory tables
274
275 self.fusionantivirus = None
276 try:
277 self.logger.debug('Try to load fusion antivirus table...')
278 self.fusionantivirus = Table('glpi_computerantiviruses', self.metadata,
279 Column('computers_id', Integer, ForeignKey('glpi_computers.id')),
280 Column('manufacturers_id', Integer, ForeignKey('glpi_manufacturers.id')),
281 autoload=True)
282 mapper(FusionAntivirus, self.fusionantivirus)
283 self.logger.debug('... Success !!')
284 except:
285 self.logger.warn('Load of fusion antivirus table failed')
286 self.logger.warn('This means you can not know antivirus statuses of your machines.')
287 self.logger.warn('This feature comes with Fusioninventory GLPI plugin')
288
289 # glpi_plugin_fusioninventory_locks
290 self.fusionlocks = None
291 # glpi_plugin_fusioninventory_agents
292 self.fusionagents = None
293
294 if self.fusionantivirus is not None: # Fusion is not installed
295 self.logger.debug('Load glpi_plugin_fusioninventory_locks')
296 self.fusionlocks = Table('glpi_plugin_fusioninventory_locks', self.metadata,
297 Column('items_id', Integer, ForeignKey('glpi_computers.id')),
298 autoload=True)
299 mapper(FusionLocks, self.fusionlocks)
300 self.logger.debug('Load glpi_plugin_fusioninventory_agents')
301 self.fusionagents = Table('glpi_plugin_fusioninventory_agents', self.metadata,
302 Column('computers_id', Integer, ForeignKey('glpi_computers.id')),
303 autoload=True)
304 mapper(FusionAgents, self.fusionagents)
305
306 # glpi_computerdisks
307 self.disk = Table('glpi_computerdisks', self.metadata,
308 Column('computers_id', Integer, ForeignKey('glpi_computers.id')),
309 Column('filesystems_id', Integer, ForeignKey('glpi_filesystems.id')),
310 autoload=True)
311 mapper(Disk, self.disk)
312
313 #####################################
314 # GLPI 0.90 Network tables
315 # TODO take care with the itemtype should we always set it to Computer => Yes
316 #####################################
317
318 # TODO Are these table needed (inherit of previous glpi database*py files) ?
319 self.networkinterfaces = Table("glpi_networkinterfaces", self.metadata, autoload=True)
320 mapper(NetworkInterfaces, self.networkinterfaces)
321
322 self.net = Table("glpi_networks", self.metadata, autoload=True)
323 mapper(Net, self.net)
324
325 # New network tables
326 self.ipnetworks = Table("glpi_ipnetworks", self.metadata, autoload=True)
327 mapper(IPNetworks, self.ipnetworks)
328
329 self.ipaddresses_ipnetworks = Table("glpi_ipaddresses_ipnetworks", self.metadata,
330 Column('ipaddresses_id', Integer, ForeignKey('glpi_ipaddresses.id')),
331 Column('ipnetworks_id', Integer, ForeignKey('glpi_networks.id')),
332 autoload=True)
333 mapper(IPAddresses_IPNetworks, self.ipaddresses_ipnetworks)
334
335 self.ipaddresses = Table("glpi_ipaddresses", self.metadata, autoload=True)
336 mapper(IPAddresses, self.ipaddresses, properties={
337 'ipnetworks': relationship(IPNetworks, secondary=self.ipaddresses_ipnetworks,
338 primaryjoin=self.ipaddresses.c.id == self.ipaddresses_ipnetworks.c.ipaddresses_id,
339 secondaryjoin=self.ipnetworks.c.id == self.ipaddresses_ipnetworks.c.ipnetworks_id,
340 foreign_keys=[
341 self.ipaddresses_ipnetworks.c.ipaddresses_id,
342 self.ipaddresses_ipnetworks.c.ipnetworks_id,
343 ])
344 })
345
346 self.networknames = Table("glpi_networknames", self.metadata, autoload=True)
347 mapper(NetworkNames, self.networknames, properties={
348 # ipaddresses is a one2many relation from NetworkNames to IPAddresses
349 # so uselist must be set to True
350 'ipaddresses': relationship(IPAddresses, primaryjoin=and_(
351 IPAddresses.items_id == self.networknames.c.id,
352 IPAddresses.itemtype == 'NetworkName'
353 ), uselist=True, foreign_keys=[self.networknames.c.id]),
354 })
355
356 self.networkports = Table("glpi_networkports", self.metadata, autoload=True)
357 mapper(NetworkPorts, self.networkports, properties={
358 'networknames': relationship(NetworkNames, primaryjoin=and_(
359 NetworkNames.items_id == self.networkports.c.id,
360 NetworkNames.itemtype == 'NetworkPort'
361 ), foreign_keys=[self.networkports.c.id]),
362 })
363
364 # machine (we need the foreign key, so we need to declare the table by hand ...
365 # as we don't need all columns, we don't declare them all)
366 self.machine = Table("glpi_computers", self.metadata,
367 Column('id', Integer, primary_key=True),
368 Column('entities_id', Integer, ForeignKey('glpi_entities.id')),
369 Column('operatingsystems_id', Integer, ForeignKey('glpi_operatingsystems.id')),
370 Column('operatingsystemversions_id', Integer,
371 ForeignKey('glpi_operatingsystemversions.id')),
372 Column('operatingsystemservicepacks_id', Integer,
373 ForeignKey('glpi_operatingsystemservicepacks.id')),
374 Column('locations_id', Integer, ForeignKey('glpi_locations.id')),
375 Column('domains_id', Integer, ForeignKey('glpi_domains.id')),
376 Column('networks_id', Integer, ForeignKey('glpi_networks.id')),
377 Column('computermodels_id', Integer, ForeignKey('glpi_computermodels.id')),
378 Column('computertypes_id', Integer, ForeignKey('glpi_computertypes.id')),
379 Column('groups_id', Integer, ForeignKey('glpi_groups.id')),
380 Column('users_id', Integer, ForeignKey('glpi_users.id')),
381 Column('manufacturers_id', Integer, ForeignKey('glpi_manufacturers.id')),
382 Column('name', String(255), nullable=False),
383 Column('serial', String(255), nullable=False),
384 Column('os_license_number', String(255), nullable=True),
385 Column('os_licenseid', String(255), nullable=True),
386 Column('is_deleted', Integer, nullable=False),
387 Column('is_template', Integer, nullable=False),
388 Column('states_id', Integer, ForeignKey('glpi_states.id'), nullable=False),
389 Column('comment', String(255), nullable=False),
390 Column('date_mod', Date, nullable=False),
391 autoload=True)
392 mapper(Machine, self.machine, properties={
393 # networkports is a one2many relation from Machine to NetworkPorts
394 # so uselist must be set to True
395 'networkports': relationship(NetworkPorts, primaryjoin=and_(
396 NetworkPorts.items_id == self.machine.c.id,
397 NetworkPorts.itemtype == 'Computer'
398 ), uselist=True, foreign_keys=[self.machine.c.id]),
399 'domains': relationship(Domain),
400 })
401
402 # states
403 self.state = Table("glpi_states", self.metadata, autoload=True)
404 mapper(State, self.state)
405 # profile
406 self.profile = Table("glpi_profiles", self.metadata,
407 Column('id', Integer, primary_key=True),
408 Column('name', String(255), nullable=False))
409 mapper(Profile, self.profile)
410
411 # user
412 self.user = Table("glpi_users", self.metadata,
413 Column('id', Integer, primary_key=True),
414 Column('name', String(255), nullable=False),
415 Column('password', String(40), nullable=False),
416 Column('firstname', String(255), nullable=False),
417 Column('realname', String(255), nullable=False),
418 Column('auths_id', Integer, nullable=False),
419 Column('is_deleted', Integer, nullable=False),
420 Column('is_active', Integer, nullable=False))
421 mapper(User, self.user)
422
423 # userprofile
424 self.userprofile = Table("glpi_profiles_users", self.metadata,
425 Column('id', Integer, primary_key=True),
426 Column('users_id', Integer, ForeignKey('glpi_users.id')),
427 Column('profiles_id', Integer, ForeignKey('glpi_profiles.id')),
428 Column('entities_id', Integer, ForeignKey('glpi_entities.id')),
429 Column('is_dynamic', Integer),
430 Column('is_recursive', Integer))
431 mapper(UserProfile, self.userprofile)
432
433 # glpi_manufacturers
434 self.manufacturers = Table("glpi_manufacturers", self.metadata, autoload=True)
435 mapper(Manufacturers, self.manufacturers)
436
437 # software
438 self.software = Table("glpi_softwares", self.metadata,
439 Column('manufacturers_id', Integer, ForeignKey('glpi_manufacturers.id')),
440 autoload=True)
441 mapper(Software, self.software)
442
443 # glpi_inst_software
444 self.inst_software = Table("glpi_computers_softwareversions", self.metadata,
445 Column('computers_id', Integer, ForeignKey('glpi_computers.id')),
446 Column('softwareversions_id', Integer, ForeignKey('glpi_softwareversions.id')),
447 autoload=True)
448 mapper(InstSoftware, self.inst_software)
449
450 # glpi_licenses
451 self.licenses = Table("glpi_softwarelicenses", self.metadata,
452 Column('softwares_id', Integer, ForeignKey('glpi_softwares.id')),
453 autoload=True)
454 mapper(Licenses, self.licenses)
455
456 # glpi_softwareversions
457 self.softwareversions = Table("glpi_softwareversions", self.metadata,
458 Column('softwares_id', Integer, ForeignKey('glpi_softwares.id')),
459 autoload=True)
460 mapper(SoftwareVersion, self.softwareversions)
461
462 # collects
463 self.collects = Table("glpi_plugin_fusioninventory_collects", self.metadata, autoload=True)
464 mapper(Collects, self.collects)
465
466 # model
467 self.model = Table("glpi_computermodels", self.metadata, autoload=True)
468 mapper(Model, self.model)
469
470 # group
471 self.group = Table("glpi_groups", self.metadata, autoload=True)
472 mapper(Group, self.group)
473
474 # registries
475 self.registries = Table("glpi_plugin_fusioninventory_collects_registries", self.metadata, autoload=True)
476 mapper(Registries, self.registries)
477
478 # registries contents
479 self.regcontents = Table("glpi_plugin_fusioninventory_collects_registries_contents", self.metadata,
480 autoload=True)
481 mapper(RegContents, self.regcontents)
482
483 ##################### internal query generators
484 def __filter_on(self, query):
485 """
486 Use the glpi.ini conf parameter filter_on to filter machines on some parameters
487 The request is in OR not in AND, so be carefull with what you want
488 """
489 ret = self.__filter_on_filter(query)
490 if type(ret) == type(None):
491 return query
492 else:
493 return query.filter(ret)
494
495 def __filter_on_filter(self, query):
496 if self.config.filter_on != None:
497 a_filter_on = []
498 for filter_key, filter_values in self.config.filter_on.items():
499 if filter_key == 'state':
500 self.logger.debug('will filter %s in (%s)' % (filter_key, str(filter_values)))
501 a_filter_on.append(self.machine.c.states_id.in_(filter_values))
502 if filter_key == 'type':
503 self.logger.debug('will filter %s in (%s)' % (filter_key, str(filter_values)))
504 a_filter_on.append(self.machine.c.computertypes_id.in_(filter_values))
505 if filter_key == 'entity':
506 self.logger.debug('will filter %s in (%s)' % (filter_key, str(filter_values)))
507 a_filter_on.append(self.machine.c.entities_id.in_(filter_values))
508 if filter_key == 'autoupdatesystems_id':
509 self.logger.debug('will filter %s in (%s)' % (filter_key, str(filter_values)))
510 a_filter_on.append(self.machine.c.autoupdatesystems_id.in_(filter_values))
511 if not filter_key in ('state', 'type', 'entity', 'autoupdatesystems_id'):
512 self.logger.warn('dont know how to filter on %s' % (filter_key))
513 if len(a_filter_on) == 0:
514 return None
515 elif len(a_filter_on) == 1:
516 return a_filter_on[0]
517 else:
518 return and_(*a_filter_on)
519 return None
520
521 def __filter_on_entity(self, query, ctx, other_locids=None):
522 # Mutable list used other_locids as default argument to a method or function
523 other_locids = other_locids or []
524 ret = self.__filter_on_entity_filter(query, ctx, other_locids)
525 return query.filter(ret)
526
527 def __filter_on_entity_filter(self, query, ctx, other_locids=None):
528 # FIXME: I put the locationsid in the security context to optimize the
529 # number of requests. locationsid is set by
530 # glpi.utilities.complete_ctx, but when querying via the dyngroup
531 # plugin it is not called.
532 # Mutable list used other_locids as default argument to a method or function
533 other_locids = other_locids or []
534 if not hasattr(ctx, 'locationsid'):
535 complete_ctx(ctx)
536 return self.machine.c.entities_id.in_(ctx.locationsid + other_locids)
537
538 def __getRestrictedComputersListQuery(self, ctx, filt=None, session=create_session(), displayList=False,
539 count=False):
540 """
541 Get the sqlalchemy query to get a list of computers with some filters
542 If displayList is True, we are displaying computers list
543 """
544 if session == None:
545 session = create_session()
546 query = count and session.query(func.count(Machine.id)) or session.query(Machine)
547 if filt:
548 # filtering on query
549 join_query = self.machine
550
551 if displayList and not count:
552 if 'os' in self.config.summary:
553 query = query.add_column(self.os.c.name)
554 if 'type' in self.config.summary:
555 query = query.add_column(self.glpi_computertypes.c.name)
556 if 'inventorynumber' in self.config.summary:
557 query = query.add_column(self.machine.c.otherserial)
558 if 'state' in self.config.summary:
559 query = query.add_column(self.state.c.name)
560 if 'entity' in self.config.summary:
561 query = query.add_column(self.entities.c.name) # entities
562 if 'location' in self.config.summary:
563 query = query.add_column(self.locations.c.name) # locations
564 if 'model' in self.config.summary:
565 query = query.add_column(self.glpi_computermodels.c.name)
566 if 'manufacturer' in self.config.summary:
567 query = query.add_column(self.manufacturers.c.name)
568 if 'owner_firstname' in self.config.summary:
569 query = query.add_column(self.user.c.firstname)
570 if 'owner_realname' in self.config.summary:
571 query = query.add_column(self.user.c.realname)
572 if 'owner' in self.config.summary:
573 query = query.add_column(self.user.c.name)
574
575 query_filter = None
576
577 filters = [self.machine.c.is_deleted == 0, self.machine.c.is_template == 0, self.__filter_on_filter(query),
578 self.__filter_on_entity_filter(query, ctx)]
579
580 join_query, query_filter = self.filter(ctx, self.machine, filt, session.query(Machine), self.machine.c.id,
581 filters)
582
583 # filtering on locations
584 if 'location' in filt:
585 location = filt['location']
586 if location == '' or location == u'' or not self.displayLocalisationBar:
587 location = None
588 else:
589 location = None
590
591 # Imaging group
592 if 'imaging_entities' in filt:
593 location = filt['imaging_entities']
594
595 if 'ctxlocation' in filt:
596 ctxlocation = filt['ctxlocation']
597 if not self.displayLocalisationBar:
598 ctxlocation = None
599 else:
600 ctxlocation = None
601
602 if ctxlocation != None:
603 locsid = []
604 if isinstance(ctxlocation, list):
605 for loc in ctxlocation:
606 locsid.append(self.__getId(loc))
607 join_query = join_query.join(self.entities)
608
609 if location is not None:
610 # Imaging group case
611 if isinstance(location, list):
612 locationids = [int(x.replace('UUID', '')) for x in location]
613 for locationid in locationids:
614 if not locationid in locsid:
615 self.logger.warn(
616 "User '%s' is trying to get the content of an unauthorized entity : '%s'" % (
617 ctx.userid, 'UUID' + location))
618 session.close()
619 return None
620 query_filter = self.__addQueryFilter(query_filter,
621 (self.machine.c.entities_id.in_(locationids)))
622 else:
623 locationid = int(location.replace('UUID', ''))
624 if locationid in locsid:
625 query_filter = self.__addQueryFilter(query_filter,
626 (self.machine.c.entities_id == locationid))
627 else:
628 self.logger.warn(
629 "User '%s' is trying to get the content of an unauthorized entity : '%s'" % (
630 ctx.userid, location))
631 session.close()
632 return None
633
634 if displayList:
635 if 'os' in self.config.summary:
636 join_query = join_query.outerjoin(self.os)
637 if 'type' in self.config.summary:
638 join_query = join_query.outerjoin(self.glpi_computertypes)
639 if 'state' in self.config.summary:
640 join_query = join_query.outerjoin(self.state)
641 if 'location' in self.config.summary:
642 join_query = join_query.outerjoin(self.locations)
643 if 'model' in self.config.summary:
644 join_query = join_query.outerjoin(self.glpi_computermodels)
645 if 'manufacturer' in self.config.summary:
646 join_query = join_query.outerjoin(self.manufacturers)
647 if 'owner' in self.config.summary or \
648 'owner_firstname' in self.config.summary or \
649 'owner_realname' in self.config.summary:
650 join_query = join_query.outerjoin(self.user)
651
652 if self.fusionagents is not None:
653 join_query = join_query.outerjoin(self.fusionagents)
654 if 'antivirus' in filt: # Used for Antivirus dashboard
655 join_query = join_query.outerjoin(self.fusionantivirus)
656 join_query = join_query.outerjoin(self.os)
657
658 if query_filter is None:
659 query = query.select_from(join_query)
660 else:
661 query = query.select_from(join_query).filter(query_filter)
662 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
663 query = self.__filter_on(query)
664 query = self.__filter_on_entity(query, ctx)
665
666 if filt.get('hostname'):
667 if displayList:
668 clauses = []
669 # UUID filtering
670 if filt['hostname'].lower().startswith('uuid') and len(filt['hostname']) > 3:
671 try:
672 clauses.append(self.machine.c.id == fromUUID(filt['hostname']))
673 except:
674 pass
675 if 'cn' in self.config.summary:
676 clauses.append(self.machine.c.name.like('%' + filt['hostname'] + '%'))
677 if 'os' in self.config.summary:
678 clauses.append(self.os.c.name.like('%' + filt['hostname'] + '%'))
679 if 'description' in self.config.summary:
680 clauses.append(self.machine.c.comment.like('%' + filt['hostname'] + '%'))
681 if 'type' in self.config.summary:
682 clauses.append(self.glpi_computertypes.c.name.like('%' + filt['hostname'] + '%'))
683 if 'owner' in self.config.summary:
684 clauses.append(self.user.c.name.like('%' + filt['hostname'] + '%'))
685 if 'owner_firstname' in self.config.summary:
686 clauses.append(self.user.c.firstname.like('%' + filt['hostname'] + '%'))
687 if 'owner_realname' in self.config.summary:
688 clauses.append(self.user.c.realname.like('%' + filt['hostname'] + '%'))
689 if 'user' in self.config.summary:
690 clauses.append(self.machine.c.contact.like('%' + filt['hostname'] + '%'))
691 if 'state' in self.config.summary:
692 clauses.append(self.state.c.name.like('%' + filt['hostname'] + '%'))
693 if 'inventorynumber' in self.config.summary:
694 clauses.append(self.machine.c.otherserial.like('%' + filt['hostname'] + '%'))
695 if 'entity' in self.config.summary:
696 clauses.append(self.entities.c.name.like('%' + filt['hostname'] + '%'))
697 if 'location' in self.config.summary:
698 clauses.append(self.locations.c.name.like('%' + filt['hostname'] + '%'))
699 if 'model' in self.config.summary:
700 clauses.append(self.glpi_computermodels.c.name.like('%' + filt['hostname'] + '%'))
701 if 'manufacturer' in self.config.summary:
702 clauses.append(self.manufacturers.c.name.like('%' + filt['hostname'] + '%'))
703 # Filtering on computer list page
704 if clauses:
705 query = query.filter(or_(*clauses))
706 else:
707 # filtering on machines (name or uuid)
708 query = query.filter(self.machine.c.name.like('%' + filt['hostname'] + '%'))
709 if 'name' in filt:
710 query = query.filter(self.machine.c.name.like('%' + filt['name'] + '%'))
711
712 if 'filter' in filt: # Used with search field of static group creation
713 query = query.filter(self.machine.c.name.like('%' + filt['filter'] + '%'))
714
715 if 'uuid' in filt:
716 query = self.filterOnUUID(query, filt['uuid'])
717
718 if 'uuids' in filt and type(filt['uuids']) == list and len(filt['uuids']) > 0:
719 query = self.filterOnUUID(query, filt['uuids'])
720
721 if 'gid' in filt:
722 gid = filt['gid']
723 machines = []
724 if ComputerGroupManager().isrequest_group(ctx, gid):
725 machines = map(lambda m: fromUUID(m),
726 ComputerGroupManager().requestresult_group(ctx, gid, 0, -1, ''))
727 else:
728 machines = map(lambda m: fromUUID(m), ComputerGroupManager().result_group(ctx, gid, 0, -1, ''))
729 query = query.filter(self.machine.c.id.in_(machines))
730
731 if 'request' in filt:
732 request = filt['request']
733 if request != 'EMPTY':
734 bool = None
735 if 'equ_bool' in filt:
736 bool = filt['equ_bool']
737 machines = map(lambda m: fromUUID(m), ComputerGroupManager().request(ctx, request, bool, 0, -1, ''))
738 query = query.filter(self.machine.c.id.in_(machines))
739
740 if 'date' in filt:
741 state = filt['date']['states']
742 date_mod = filt['date']['date_mod']
743 value = filt['date']['value']
744
745 if 'green' in value:
746 query = query.filter(date_mod > state['orange'])
747 if 'orange' in value:
748 query = query.filter(and_(date_mod < state['orange'], date_mod > state['red']))
749 if 'red' in value:
750 query = query.filter(date_mod < state['red'])
751
752 if 'antivirus' in filt:
753 if filt['antivirus'] == 'green':
754 query = query.filter(
755 and_(
756 FusionAntivirus.is_active == 1,
757 FusionAntivirus.is_uptodate == 1,
758 OS.name.ilike('%windows%'),
759 not_(FusionAntivirus.name.in_(self.config.av_false_positive)),
760 )
761 )
762 elif filt['antivirus'] == 'orange':
763 query = query.filter(
764 and_(
765 OS.name.ilike('%windows%'),
766 not_(
767 and_(
768 FusionAntivirus.is_active == 1,
769 FusionAntivirus.is_uptodate == 1,
770 ),
771 ),
772 not_(FusionAntivirus.name.in_(self.config.av_false_positive)),
773 )
774 )
775 elif filt['antivirus'] == 'red':
776 query = query.filter(
777 and_(
778 OS.name.ilike('%windows%'),
779 or_(
780 FusionAntivirus.is_active == None,
781 FusionAntivirus.is_uptodate == None,
782 and_(
783 FusionAntivirus.name.in_(self.config.av_false_positive),
784 not_(FusionAntivirus.computers_id.in_(
785 self.getMachineIdsNotInAntivirusRed(ctx),
786 )),
787 ),
788 ),
789 )
790 )
791
792 if count: query = query.scalar()
793 return query
794
795 def __getId(self, obj):
796 if type(obj) == dict:
797 return obj['uuid']
798 if type(obj) != str and type(obj) != unicode:
799 return obj.id
800 return obj
801
802 def __getName(self, obj):
803 if type(obj) == dict:
804 return obj['name']
805 if type(obj) != str and type(obj) != unicode:
806 return obj.name
807 if type(obj) == str and re.match('UUID', obj):
808 l = self.getLocation(obj)
809 if l: return l.name
810 return obj
811
812 def __addQueryFilter(self, query_filter, eq):
813 if str(query_filter) == str(
814 None): # don't remove the str, sqlalchemy.sql._BinaryExpression == None return True!
815 query_filter = eq
816 else:
817 query_filter = and_(query_filter, eq)
818 return query_filter
819
820 def computersTable(self):
821 return [self.machine]
822
823 def computersMapping(self, computers, invert=False):
824 if not invert:
825 return Machine.id.in_(map(lambda x: fromUUID(x), computers))
826 else:
827 return Machine.id.not_(ColumnOperators.in_(map(lambda x: fromUUID(x), computers)))
828
829 def mappingTable(self, ctx, query):
830 """
831 Map a table name on a table mapping
832 """
833 base = []
834 base.append(self.entities)
835 if query[2] == 'OS':
836 return base + [self.os]
837 elif query[2] == 'Entity':
838 return base
839 elif query[2] == 'SOFTWARE':
840 return base + [self.inst_software, self.licenses, self.software]
841 elif query[2] == 'Computer name':
842 return base
843 elif query[2] == 'Contact':
844 return base
845 elif query[2] == 'Contact number':
846 return base
847 elif query[2] == 'Description':
848 return base
849 elif query[2] == 'System model':
850 return base + [self.model]
851 elif query[2] == 'System manufacturer':
852 return base + [self.manufacturers]
853 elif query[2] == 'State':
854 return base + [self.state]
855 elif query[2] == 'System type':
856 return base + [self.glpi_computertypes]
857 elif query[2] == 'Inventory number':
858 return base
859 elif query[2] == 'Location':
860 return base + [self.locations]
861 elif query[2] == 'Operating system':
862 return base + [self.os]
863 elif query[2] == 'Service Pack':
864 return base + [self.os_sp]
865 elif query[2] == 'Group':
866 return base + [self.group]
867 elif query[2] == 'Network':
868 return base + [self.net]
869 elif query[2] == 'Installed software':
870 return base + [self.inst_software, self.softwareversions, self.software]
871 elif query[2] == 'Installed software (specific version)':
872 return base + [self.inst_software, self.softwareversions, self.software]
873 elif query[2] == 'Installed software (specific vendor and version)': # hidden internal dyngroup
874 return base + [self.inst_software, self.softwareversions, self.software, self.manufacturers]
875 return []
876
877 def mapping(self, ctx, query, invert=False):
878 """
879 Map a name and request parameters on a sqlalchemy request
880 """
881 if len(query) == 4:
882 # in case the glpi database is in latin1, don't forget dyngroup is in utf8
883 # => need to convert what comes from the dyngroup database
884 query[3] = self.encode(query[3])
885 r1 = re.compile('\*')
886 like = False
887 if type(query[3]) == list:
888 q3 = []
889 for q in query[3]:
890 if r1.search(q):
891 like = True
892 q = r1.sub('%', q)
893 q3.append(q)
894 query[3] = q3
895 else:
896 if r1.search(query[3]):
897 like = True
898 query[3] = r1.sub('%', query[3])
899
900 parts = self.__getPartsFromQuery(ctx, query)
901 ret = []
902
903 for part in parts:
904 partA, partB = part
905 partBcanBeNone = partB == '%'
906 if invert:
907 if like:
908 if partBcanBeNone:
909 ret.append(not_(
910 or_(
911 partA.like(self.encode(partB)),
912 partA == None,
913 )
914 ))
915 else:
916 ret.append(not_(partA.like(self.encode(partB))))
917 else:
918 ret.append(not_(partA.like(self.encode(partB))))
919 else:
920 if like:
921 if partBcanBeNone:
922 ret.append(
923 or_(
924 partA.like(self.encode(partB)),
925 partA == None,
926 )
927 )
928 else:
929 ret.append(partA.like(self.encode(partB)))
930 else:
931 ret.append(partA.like(self.encode(partB)))
932 if ctx.userid != 'root':
933 ret.append(self.__filter_on_entity_filter(None, ctx))
934 return and_(*ret)
935 else:
936 return self.__treatQueryLevel(query)
937
938 def __getPartsFromQuery(self, ctx, query):
939 if query[2] in ['OS', 'Operating system']:
940 return [[self.os.c.name, query[3]]]
941 elif query[2] == 'Entity':
942 locid = None
943 for loc in ctx.locations:
944 if self.__getName(loc) == query[3]:
945 locid = self.__getId(loc)
946 if locid is not None:
947 return [[self.machine.c.entities_id, locid]]
948 else:
949 return [[self.entities.c.name, query[3]]]
950 elif query[2] == 'SOFTWARE':
951 return [[self.software.c.name, query[3]]]
952 elif query[2] == 'Computer name':
953 return [[self.machine.c.name, query[3]]]
954 elif query[2] == 'Contact':
955 return [[self.machine.c.contact, query[3]]]
956 elif query[2] == 'Contact number':
957 return [[self.machine.c.contact_num, query[3]]]
958 elif query[2] == 'Description':
959 return [[self.machine.c.comment, query[3]]]
960 elif query[2] == 'System model':
961 return [[self.model.c.name, query[3]]]
962 elif query[2] == 'System manufacturer':
963 return [[self.manufacturers.c.name, query[3]]]
964 elif query[2] == 'State':
965 return [[self.state.c.name, query[3]]]
966 elif query[2] == 'System type':
967 return [[self.glpi_computertypes.c.name, query[3]]]
968 elif query[2] == 'Inventory number':
969 return [[self.machine.c.otherserial, query[3]]]
970 elif query[2] == 'Location':
971 return [[self.locations.c.completename, query[3]]]
972 elif query[2] == 'Service Pack':
973 return [[self.os_sp.c.name, query[3]]]
974 elif query[2] == 'Group': # TODO double join on Entity
975 return [[self.group.c.name, query[3]]]
976 elif query[2] == 'Network':
977 return [[self.net.c.name, query[3]]]
978 elif query[2] == 'Installed software': # TODO double join on Entity
979 return [[self.software.c.name, query[3]]]
980 elif query[2] == 'Installed software (specific version)': # TODO double join on Entity
981 return [[self.software.c.name, query[3][0]], [self.softwareversions.c.name, query[3][1]]]
982 elif query[2] == 'Installed software (specific vendor and version)': # hidden internal dyngroup
983 return [[self.manufacturers.c.name, query[3][0]], [self.software.c.name, query[3][1]],
984 [self.softwareversions.c.name, query[3][2]]]
985 return []
986
987 def __getTable(self, table):
988 if table == 'OS':
989 return self.os.c.name
990 elif table == 'Entity':
991 return self.entities.c.name
992 elif table == 'SOFTWARE':
993 return self.software.c.name
994 raise Exception("dont know table for %s" % (table))
995
996 ##################### machine list management
997 def getComputer(self, ctx, filt, empty_macs=False):
998 """
999 Get the first computers that match filters parameters
1000 """
1001 ret = self.getRestrictedComputersList(ctx,
1002 0,
1003 10,
1004 filt,
1005 displayList=False,
1006 empty_macs=empty_macs)
1007 if len(ret) != 1:
1008 for i in ['location', 'ctxlocation']:
1009 try:
1010 filt.pop(i)
1011 except:
1012 pass
1013 ret = self.getRestrictedComputersList(ctx,
1014 0,
1015 10,
1016 filt,
1017 displayList=False,
1018 empty_macs=empty_macs)
1019 if len(ret) > 0:
1020 raise Exception("NOPERM##%s" % (ret[0][1]['fullname']))
1021 return False
1022 return ret.values()[0]
1023
1024 def getRestrictedComputersListStatesLen(self, ctx, filt, orange, red):
1025 """
1026 Return number of computers by state
1027 """
1028 session = create_session()
1029 now = datetime.datetime.now()
1030 states = {
1031 'orange': now - datetime.timedelta(orange),
1032 'red': now - datetime.timedelta(red),
1033 }
1034
1035 date_mod = self.machine.c.date_mod
1036 if self.fusionagents is not None:
1037 date_mod = FusionAgents.last_contact
1038
1039 for value in ['green', 'orange', 'red']:
1040 # This loop instanciate self.filt_green,
1041 # self.filt_orange and self.filt_red
1042 setattr(self, 'filt_%s' % value, filt.copy())
1043
1044 newFilter = getattr(self, 'filt_%s' % value)
1045 values = {
1046 'states': states,
1047 'date_mod': date_mod,
1048 'value': value,
1049 }
1050 newFilter['date'] = values
1051
1052 ret = {
1053 "green": int(self.__getRestrictedComputersListQuery(ctx, self.filt_green, session, count=True)),
1054 "orange": int(self.__getRestrictedComputersListQuery(ctx, self.filt_orange, session, count=True)),
1055 "red": int(self.__getRestrictedComputersListQuery(ctx, self.filt_red, session, count=True)),
1056 }
1057 session.close()
1058 return ret
1059
1060 def getRestrictedComputersListLen(self, ctx, filt=None):
1061 """
1062 Get the size of the computer list that match filters parameters
1063 """
1064 session = create_session()
1065
1066 displayList = None
1067
1068 # When search field is used on main computer's list page,
1069 # Pagination PHP Widget must know total machine result
1070 # So, set displayList to True to count on glpi_computers
1071 # and all needed joined tables
1072 if 'hostname' in filt:
1073 if len(filt['hostname']) > 0:
1074 displayList = True
1075
1076 ret = self.__getRestrictedComputersListQuery(ctx, filt, session, displayList, count=True)
1077 if ret == None:
1078 return 0
1079 session.close()
1080 return ret
1081
1082 def getRestrictedComputersList(self,
1083 ctx,
1084 min=0,
1085 max=-1,
1086 filt=None,
1087 advanced=True,
1088 justId=False,
1089 toH=False,
1090 displayList=None,
1091 empty_macs=False):
1092 """
1093 Get the computer list that match filters parameters between min and max
1094
1095 FIXME: may return a list or a dict according to the parameters
1096
1097 @param displayList: if True, we are displaying Computers list main page
1098 @type displayList: None or bool
1099 """
1100 session = create_session()
1101 ret = {}
1102
1103 # If we are displaying Computers list main page, set displayList to True
1104 if displayList is None:
1105 if justId or toH or 'uuid' in filt: # if 'uuid' in filt: used where adding a command to a group
1106 displayList = False
1107 else:
1108 displayList = True
1109
1110 query = self.__getRestrictedComputersListQuery(ctx, filt, session, displayList)
1111 if query == None:
1112 return {}
1113
1114 if self.config.ordered:
1115 query = query.order_by(asc(self.machine.c.name))
1116
1117 if min != 0:
1118 query = query.offset(min)
1119 if max != -1:
1120 max = int(max) - int(min)
1121 query = query.limit(max)
1122
1123 if justId:
1124 ret = map(lambda m: self.getMachineUUID(m), query.all())
1125 elif toH:
1126 ret = map(lambda m: m.toH(), query.all())
1127 else:
1128 if filt is not None and 'get' in filt:
1129 ret = self.__formatMachines(query.all(),
1130 advanced,
1131 filt['get'],
1132 empty_macs=empty_macs)
1133 else:
1134 ret = self.__formatMachines(query.all(),
1135 advanced,
1136 None,
1137 empty_macs=empty_macs)
1138 session.close()
1139 return ret
1140
1141 def getTotalComputerCount(self):
1142 session = create_session()
1143 query = session.query(Machine)
1144 query = self.__filter_on(query)
1145 c = query.count()
1146 session.close()
1147 return c
1148
1149 def getComputerCount(self, ctx, filt=None):
1150 """
1151 Same as getRestrictedComputersListLen
1152 TODO : remove this one
1153 """
1154 return self.getRestrictedComputersListLen(ctx, filt)
1155
1156 def getComputersList(self, ctx, filt=None):
1157 """
1158 Same as getRestrictedComputersList without limits
1159 """
1160 return self.getRestrictedComputersList(ctx, 0, -1, filt)
1161
1162 ##################### UUID policies
1163 def getMachineUUID(self, machine):
1164 """
1165 Get this machine UUID
1166 """
1167 return toUUID(str(machine.id))
1168
1169 def getMachineByUUID(self, uuid):
1170 """
1171 Get the machine that as this UUID
1172 """
1173 session = create_session()
1174 ret = session.query(Machine).filter(self.machine.c.id == int(str(uuid).replace("UUID", "")))
1175 ret = ret.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
1176 ret = self.__filter_on(ret).first()
1177 session.close()
1178 return ret
1179
1180 def filterOnUUID(self, query, uuid):
1181 """
1182 Modify the given query to filter on the machine UUID
1183 """
1184 if type(uuid) == list:
1185 return query.filter(self.machine.c.id.in_([int(str(a).replace("UUID", "")) for a in uuid]))
1186 else:
1187 return query.filter(self.machine.c.id == int(str(uuid).replace("UUID", "")))
1188
1189 ##################### Machine output format (for ldap compatibility)
1190 def __getAttr(self, machine, get):
1191 ma = {}
1192 for field in get:
1193 if hasattr(machine, field):
1194 ma[field] = getattr(machine, field)
1195 if field == 'uuid' or field == 'objectUUID':
1196 ma[field] = toUUID(str(machine.id))
1197 if field == 'cn':
1198 ma[field] = machine.name
1199 return ma
1200
1201 def __formatMachines(self, machines, advanced, get=None, empty_macs=False):
1202 """
1203 Give an LDAP like version of machines
1204 """
1205 ret = {}
1206 if get != None:
1207 for m in machines:
1208 if isinstance(m, tuple):
1209 m = m[0]
1210 ret[m.getUUID()] = self.__getAttr(m, get)
1211 return ret
1212
1213 names = {}
1214 for m in machines:
1215 displayList = False
1216 if isinstance(m, tuple):
1217 displayList = True
1218 # List of fields defined around line 439
1219 # m, os, type, inventorynumber, state, entity, location, model, manufacturer, owner = m
1220 l = list(m)
1221 if 'owner' in self.config.summary:
1222 owner_login = l.pop()
1223 if 'owner_firstname' in self.config.summary:
1224 owner_firstname = l.pop()
1225 if 'owner_realname' in self.config.summary:
1226 owner_realname = l.pop()
1227 if 'manufacturer' in self.config.summary:
1228 manufacturer = l.pop()
1229 if 'model' in self.config.summary:
1230 model = l.pop()
1231 if 'location' in self.config.summary:
1232 location = l.pop()
1233 if 'entity' in self.config.summary:
1234 entity = l.pop()
1235 if 'state' in self.config.summary:
1236 state = l.pop()
1237 if 'inventorynumber' in self.config.summary:
1238 inventorynumber = l.pop()
1239 if 'type' in self.config.summary:
1240 type = l.pop()
1241 if 'os' in self.config.summary:
1242 os = l.pop()
1243
1244 m = l.pop()
1245 owner_login, owner_firstname, owner_realname = self.getMachineOwner(m)
1246 datas = {
1247 'cn': m.name not in ['', None] and [m.name] or ['(%s)' % m.id],
1248 'displayName': [m.comment],
1249 'objectUUID': [m.getUUID()],
1250 'user': [m.contact],
1251 'owner': [owner_login],
1252 'owner_realname': [owner_realname],
1253 'owner_firstname': [owner_firstname],
1254 }
1255
1256 if displayList:
1257 if 'manufacturer' in self.config.summary:
1258 datas['manufacturer'] = manufacturer
1259 if 'model' in self.config.summary:
1260 datas['model'] = model
1261 if 'location' in self.config.summary:
1262 datas['location'] = location
1263 if 'entity' in self.config.summary:
1264 datas['entity'] = entity
1265 if 'state' in self.config.summary:
1266 datas['state'] = state
1267 if 'inventorynumber' in self.config.summary:
1268 datas['inventorynumber'] = inventorynumber
1269 if 'type' in self.config.summary:
1270 datas['type'] = type
1271 if 'os' in self.config.summary:
1272 datas['os'] = os
1273 if 'owner' in self.config.summary:
1274 datas['owner'] = owner_login
1275 if 'owner_firstname' in self.config.summary:
1276 datas['owner_firstname'] = owner_firstname
1277 if 'owner_realname' in self.config.summary:
1278 datas['owner_realname'] = owner_realname
1279
1280 ret[m.getUUID()] = [None, datas]
1281
1282 if advanced:
1283 names[m.getUUID()] = m.name
1284 if advanced:
1285 uuids = []
1286 for m in machines:
1287 if isinstance(m, tuple):
1288 m = m[0]
1289 uuids.append(m.getUUID())
1290
1291 nets = self.getMachinesNetwork(uuids)
1292 for uuid in ret:
1293 try:
1294 (ret[uuid][1]['macAddress'],
1295 ret[uuid][1]['ipHostNumber'],
1296 ret[uuid][1]['subnetMask'],
1297 ret[uuid][1]['domain'],
1298 ret[uuid][1]['networkUuids']) = self.orderIpAdresses(uuid,
1299 names[uuid],
1300 nets[uuid],
1301 empty_macs=empty_macs)
1302 if ret[uuid][1]['domain'] != '' and len(ret[uuid][1]['domain']) > 0:
1303 ret[uuid][1]['fullname'] = ret[uuid][1]['cn'][0] + '.' + ret[uuid][1]['domain'][0]
1304 else:
1305 ret[uuid][1]['fullname'] = ret[uuid][1]['cn'][0]
1306 except KeyError:
1307 ret[uuid][1]['macAddress'] = []
1308 ret[uuid][1]['ipHostNumber'] = []
1309 ret[uuid][1]['subnetMask'] = []
1310 ret[uuid][1]['domain'] = ''
1311 ret[uuid][1]['fullname'] = ret[uuid][1]['cn'][0]
1312 return ret
1313
1314 def __formatMachine(self, machine, advanced, get=None):
1315 """
1316 Give an LDAP like version of the machine
1317 """
1318
1319 uuid = self.getMachineUUID(machine)
1320
1321 if get != None:
1322 return self.__getAttr(machine, get)
1323
1324 ret = {
1325 'cn': [machine.name],
1326 'displayName': [machine.comment],
1327 'objectUUID': [uuid]
1328 }
1329 if advanced:
1330 (ret['macAddress'], ret['ipHostNumber'], ret['subnetMask'], domain,
1331 ret['networkUuids']) = self.orderIpAdresses(uuid, machine.name, self.getMachineNetwork(uuid))
1332 if domain == None:
1333 domain = ''
1334 elif domain != '':
1335 domain = '.' + domain
1336 ret['fullname'] = machine.name + domain
1337 return [None, ret]
1338
1339 ##################### entities, profiles and user rigths management
1340 def displayLocalisationBar(self):
1341 """
1342 This module know how to give data to localisation bar
1343 """
1344 return True
1345
1346 def getMachineOwner(self, machine):
1347 """
1348 Returns the owner of computer.
1349
1350 @param machine: computer's instance
1351 @type machine: Machine
1352
1353 @return: owner (glpi_computers.user_id -> name)
1354 @rtype: str
1355 """
1356
1357 ret = None, None, None
1358 session = create_session()
1359 query = session.query(User).select_from(self.user.join(self.machine))
1360 query = query.filter(self.machine.c.id == machine.id).first()
1361 if query is not None:
1362 ret = query.name, query.firstname, query.realname
1363
1364 session.close()
1365 return ret
1366
1367 def getUserProfile(self, user):
1368 """
1369 @return: Return the first user GLPI profile as a string, or None
1370 """
1371 session = create_session()
1372 qprofile = session.query(Profile).select_from(self.profile.join(self.userprofile).join(self.user)).filter(
1373 self.user.c.name == user).first()
1374 if qprofile == None:
1375 ret = None
1376 else:
1377 ret = qprofile.name
1378 session.close()
1379 return ret
1380
1381 def getUserProfiles(self, user):
1382 """
1383 @return: Return all user GLPI profiles as a list of string, or None
1384 """
1385 session = create_session()
1386 profiles = session.query(Profile).select_from(self.profile.join(self.userprofile).join(self.user)).filter(
1387 self.user.c.name == user)
1388 if profiles:
1389 ret = []
1390 for profile in profiles:
1391 ret.append(profile.name)
1392 else:
1393 ret = None
1394 session.close()
1395 return ret
1396
1397 @DatabaseHelper._session
1398 def getAllUserProfiles(self, session):
1399 """
1400 @return: Return all GLPI profiles as a dict
1401 """
1402 result = {}
1403 for profile in session.query(Profile):
1404 result[profile.id] = profile.name
1405 return result
1406
1407 def getUserParentLocations(self, user):
1408 """
1409 get
1410 return: the list of user locations'parents
1411 """
1412 pass
1413
1414 def getUserLocation(self, user):
1415 """
1416 @return: Return one user GLPI entities as a list of string, or None
1417 TODO : check it is still used!
1418 """
1419 session = create_session()
1420 qentities = session.query(Entities).select_from(self.entities.join(self.userprofile).join(self.user)).filter(
1421 self.user.c.name == user).first()
1422 if qentities == None:
1423 ret = None
1424 else:
1425 ret = qentities.name
1426 return ret
1427
1428 def getUserLocations(self, user):
1429 """
1430 Get the GPLI user locations.
1431
1432 @return: the list of user locations
1433 @rtype: list
1434 """
1435 ret = []
1436 if user == 'root':
1437 ret = self.__get_all_locations()
1438 else:
1439 # check if user is linked to the root entity
1440 # (which is not declared explicitly in glpi...
1441 # we have to emulate it...)
1442 session = create_session()
1443 entids = session.query(UserProfile).select_from(self.userprofile.join(self.user).join(self.profile)).filter(
1444 self.user.c.name == user).filter(self.profile.c.name.in_(self.config.activeProfiles)).all()
1445 for entid in entids:
1446 if entid.entities_id == 0 and entid.is_recursive == 1:
1447 session.close()
1448 return self.__get_all_locations()
1449
1450 # the normal case...
1451 plocs = session.query(Entities).add_column(self.userprofile.c.is_recursive).select_from(
1452 self.entities.join(self.userprofile).join(self.user).join(self.profile)).filter(
1453 self.user.c.name == user).filter(self.profile.c.name.in_(self.config.activeProfiles)).all()
1454 for ploc in plocs:
1455 if ploc[1]:
1456 # The user profile link to the entities is recursive, and so
1457 # the children locations should be added too
1458 for l in self.__add_children(ploc[0]):
1459 ret.append(l)
1460 else:
1461 ret.append(ploc[0])
1462 if len(ret) == 0:
1463 ret = []
1464 session.close()
1465
1466 ret = map(lambda l: setUUID(l), ret)
1467 return ret
1468
1469 def __get_all_locations(self):
1470 ret = []
1471 session = create_session()
1472 q = session.query(Entities).group_by(self.entities.c.completename).order_by(
1473 asc(self.entities.c.completename)).all()
1474 session.close()
1475 for entities in q:
1476 ret.append(entities)
1477 return ret
1478
1479 def __add_children(self, child):
1480 """
1481 Recursive function used by getUserLocations to get entities tree if needed
1482 """
1483 session = create_session()
1484 children = session.query(Entities).filter(self.entities.c.entities_id == child.id).all()
1485 ret = [child]
1486 for c in children:
1487 for res in self.__add_children(c):
1488 ret.append(res)
1489 session.close()
1490 return ret
1491
1492 def getLocation(self, uuid):
1493 """
1494 Get a Location by it's uuid
1495 """
1496 session = create_session()
1497 ret = session.query(Entities).filter(self.entities.c.id == uuid.replace('UUID', '')).first()
1498 session.close()
1499 return ret
1500
1501 def getLocationName(self, uuid):
1502 if isinstance(uuid, list):
1503 uuid = uuid[0]
1504
1505 return self.getLocation(uuid).name
1506
1507 def getLocationsList(self, ctx, filt=None):
1508 """
1509 Get the list of all entities that user can access
1510 """
1511 ret = []
1512 complete_ctx(ctx)
1513 filtr = re.compile(filt)
1514 for loc in ctx.locations:
1515 if filt:
1516 if filtr.search(loc.name):
1517 ret.append(loc.name)
1518 else:
1519 ret.append(loc.name)
1520
1521 return ret
1522
1523 def getLocationsCount(self):
1524 """
1525 Returns the total count of entities
1526 """
1527 session = create_session()
1528 ret = session.query(Entities).count()
1529 session.close()
1530 return ret
1531
1532 def getMachinesLocations(self, machine_uuids):
1533 session = create_session()
1534 q = session.query(Entities.id, Entities.name, Entities.completename, Entities.comment,
1535 Entities.level).add_column(self.machine.c.id).select_from(
1536 self.entities.join(self.machine)).filter(self.machine.c.id.in_(map(fromUUID, machine_uuids))).all()
1537 ret = {}
1538 for idp, namep, namepc, commentp, levelp, machineid in q:
1539 val = {}
1540 val['uuid'] = toUUID(idp)
1541 val['name'] = namep
1542 val['completename'] = namepc
1543 val['comments'] = commentp
1544 val['level'] = levelp
1545 ret[toUUID(machineid)] = val
1546 session.close()
1547 return ret
1548
1549 def getUsersInSameLocations(self, userid, locations=None):
1550 """
1551 Returns all users name that share the same locations with the given
1552 user
1553 """
1554 if locations == None:
1555 locations = self.getUserLocations(userid)
1556 ret = []
1557 if locations:
1558 inloc = []
1559 for location in locations:
1560 inloc.append(location.name)
1561 session = create_session()
1562 q = session.query(User).select_from(self.user.join(self.userprofile).join(self.entities)).filter(
1563 self.entities.c.name.in_(inloc)).filter(self.user.c.name != userid).distinct().all()
1564 session.close()
1565 # Only returns the user names
1566 ret = map(lambda u: u.name, q)
1567 # Always append the given userid
1568 ret.append(userid)
1569 return ret
1570
1571 def getComputerInLocation(self, location=None):
1572 """
1573 Get all computers in that location
1574 """
1575 session = create_session()
1576 query = session.query(Machine).select_from(self.machine.join(self.entities)).filter(
1577 self.entities.c.name == location)
1578 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
1579 query = self.__filter_on(query)
1580 ret = []
1581 for machine in query.group_by(self.machine.c.name).order_by(asc(self.machine.c.name)):
1582 ret[machine.name] = self.__formatMachine(machine)
1583 session.close()
1584 return ret
1585
1586 def getLocationsFromPathString(self, location_path):
1587 """
1588 """
1589 session = create_session()
1590 ens = []
1591 for loc_path in location_path:
1592 loc_path = " > ".join(loc_path)
1593 q = session.query(Entities).filter(self.entities.c.completename == loc_path).all()
1594 if len(q) != 1:
1595 ens.append(False)
1596 else:
1597 ens.append(toUUID(str(q[0].id)))
1598 session.close()
1599 return ens
1600
1601 def getLocationParentPath(self, loc_uuid):
1602 session = create_session()
1603 path = []
1604 en_id = fromUUID(loc_uuid)
1605 en = session.query(Entities).filter(self.entities.c.id == en_id).first()
1606 parent_id = en.entities_id
1607 if parent_id == -1: # parent_id is -1 for root entity
1608 parent_id = 0
1609
1610 while parent_id != 0:
1611 en_id = parent_id
1612 en = session.query(Entities).filter(self.entities.c.id == parent_id).first()
1613 path.append(toUUID(en.id))
1614 parent_id = en.entities_id
1615 path.append('UUID0')
1616 return path
1617
1618 def doesUserHaveAccessToMachines(self, ctx, a_machine_uuid, all=True):
1619 """
1620 Check if the user has correct permissions to access more than one or to all machines
1621
1622 Return always true for the root user.
1623
1624 @rtype: bool
1625 """
1626 if not self.displayLocalisationBar:
1627 return True
1628
1629 session = create_session()
1630 # get the number of computers the user have access to
1631 query = session.query(Machine)
1632 if ctx.userid == "root":
1633 query = self.filterOnUUID(query, a_machine_uuid)
1634 else:
1635 a_locations = map(lambda loc: loc.name, ctx.locations)
1636 query = query.select_from(self.machine.join(self.entities))
1637 query = query.filter(self.entities.c.name.in_(a_locations))
1638 query = self.filterOnUUID(query, a_machine_uuid)
1639 ret = query.group_by(self.machine.c.id).all()
1640 # get the number of computers that had not been deleted
1641 machines_uuid_size = len(a_machine_uuid)
1642 all_computers = session.query(Machine)
1643 all_computers = self.filterOnUUID(all_computers, a_machine_uuid).all()
1644 all_computers = Set(map(lambda m: toUUID(str(m.id)), all_computers))
1645 if len(all_computers) != machines_uuid_size:
1646 self.logger.info("some machines have been deleted since that list was generated (%s)" % (
1647 str(Set(a_machine_uuid) - all_computers)))
1648 machines_uuid_size = len(all_computers)
1649 size = 1
1650 if type(ret) == list:
1651 size = len(ret)
1652 if all and size == machines_uuid_size:
1653 return True
1654 elif (not all) and machines_uuid_size == 0:
1655 return True
1656 elif (not all) and len(ret) > 0:
1657 return True
1658 ret = Set(map(lambda m: toUUID(str(m.id)), ret))
1659 self.logger.info("dont have permissions on %s" % (str(Set(a_machine_uuid) - ret)))
1660 return False
1661
1662 def doesUserHaveAccessToMachine(self, ctx, machine_uuid):
1663 """
1664 Check if the user has correct permissions to access this machine
1665
1666 @rtype: bool
1667 """
1668 return self.doesUserHaveAccessToMachines(ctx, [machine_uuid])
1669
1670 ##################### for inventory purpose (use the same API than OCSinventory to keep the same GUI)
1671 def getLastMachineInventoryFull(self, uuid):
1672 session = create_session()
1673 # there is glpi_entreprise missing
1674 query = self.filterOnUUID(session.query(Machine) \
1675 .add_column(self.glpi_operatingsystems.c.name) \
1676 .add_column(self.glpi_operatingsystemservicepacks.c.name) \
1677 .add_column(self.glpi_operatingsystemversions.c.name) \
1678 .add_column(self.glpi_domains.c.name) \
1679 .add_column(self.locations.c.name) \
1680 .add_column(self.glpi_computermodels.c.name) \
1681 .add_column(self.glpi_computertypes.c.name) \
1682 .add_column(self.glpi_networks.c.name) \
1683 .add_column(self.entities.c.completename) \
1684 .select_from( \
1685 self.machine.outerjoin(self.glpi_operatingsystems).outerjoin(
1686 self.glpi_operatingsystemservicepacks).outerjoin(self.glpi_operatingsystemversions).outerjoin(
1687 self.glpi_computertypes) \
1688 .outerjoin(self.glpi_domains).outerjoin(self.locations).outerjoin(self.glpi_computermodels).outerjoin(
1689 self.glpi_networks) \
1690 .join(self.entities)
1691 ), uuid).all()
1692 ret = []
1693 ind = {'os': 1, 'os_sp': 2, 'os_version': 3, 'type': 7, 'domain': 4, 'location': 5, 'model': 6, 'network': 8,
1694 'entity': 9} # 'entreprise':9
1695 for m in query:
1696 ma1 = m[0].to_a()
1697 ma2 = []
1698 for x, y in ma1:
1699 if x in ind.keys():
1700 ma2.append([x, m[ind[x]]])
1701 else:
1702 ma2.append([x, y])
1703 ret.append(ma2)
1704 if type(uuid) == list:
1705 return ret
1706 return ret[0]
1707
1708 def inventoryExists(self, uuid):
1709 machine = self.getMachineByUUID(uuid)
1710 if machine:
1711 return True
1712 else:
1713 return False
1714
1715 def getWarrantyEndDate(self, infocoms):
1716 """
1717 Get a computer's warranty end date
1718 @param infocoms: Content of glpi_infocoms SQL table
1719 @type infocoms: self.infocoms sqlalchemy object
1720
1721 @return: computer's warranty end date if exists, else None
1722 @rtype: string or None
1723 """
1724
1725 def add_months(sourcedate, months):
1726 """
1727 Add x months to a datetime object
1728 thanks to http://stackoverflow.com/questions/4130922/how-to-increment-datetime-month-in-python
1729 """
1730 month = sourcedate.month - 1 + months
1731 year = sourcedate.year + month / 12
1732 month = month % 12 + 1
1733 day = min(sourcedate.day, calendar.monthrange(year, month)[1])
1734 return datetime.date(year, month, day)
1735
1736 if infocoms is not None and infocoms.warranty_date is not None:
1737 endDate = add_months(infocoms.warranty_date, infocoms.warranty_duration)
1738 if datetime.datetime.now().date() > endDate:
1739 return '<span style="color:red;font-weight: bold;">%s</span>' % endDate.strftime('%Y-%m-%d')
1740 else:
1741 return endDate.strftime('%Y-%m-%d')
1742
1743 return ''
1744
1745 def getManufacturerWarranty(self, manufacturer, serial):
1746 for manufacturer_key, manufacturer_infos in self.config.manufacturerWarranty.items():
1747 if manufacturer in manufacturer_infos['names']:
1748 manufacturer_info = manufacturer_infos.copy()
1749 manufacturer_info['url'] = manufacturer_info['url'].replace('@@SERIAL@@', serial)
1750 manufacturer_info['params'] = manufacturer_info['params'].replace('@@SERIAL@@', serial)
1751 return manufacturer_info
1752 return False
1753
1754 def getSearchOptionId(self, filter, lang='en_US'):
1755 """
1756 return a list of ids corresponding to filter
1757 @param filter: a value to search
1758 @type filter: string
1759 """
1760
1761 ids = []
1762 dict = self.searchOptions[lang]
1763 for key, value in dict.iteritems():
1764 if filter.lower() in value.lower():
1765 ids.append(key)
1766
1767 return ids
1768
1769 def getLinkedActionKey(self, filter, lang='en_US'):
1770 """
1771 return a list of ids corresponding to filter
1772 """
1773 ids = []
1774 dict = self.getLinkedActions()
1775 for key, value in dict.iteritems():
1776 if filter.lower() in value.lower():
1777 ids.append(key)
1778
1779 return ids
1780
1781 def countLastMachineInventoryPart(self, uuid, part, filt=None, options={}):
1782 # Mutable dict options used as default argument to a method or function
1783 return self.getLastMachineInventoryPart(uuid, part, filt=filt, options=options, count=True)
1784
1785 @property
1786 def _network_types(self):
1787 """
1788 Dict with GLPI available Network types
1789 """
1790 return {
1791 'NetworkPortLocal': 'Local',
1792 'NetworkPortEthernet': 'Ethernet',
1793 'NetworkPortWifi': 'Wifi',
1794 'NetworkPortDialup': 'Dialup',
1795 'NetworkPortAggregate': 'Aggregate',
1796 'NetworkPortAlias': 'Alias',
1797 }
1798
1799 def _get_network_type(self, instantiation_type):
1800 """
1801 Return human readable glpi network type for given instantiation_type
1802 If not found, return instantiation_type
1803 """
1804 if instantiation_type in self._network_types:
1805 return self._network_types[instantiation_type]
1806 return instantiation_type
1807
1808 def getLastMachineNetworkPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
1809 # Mutable dict options used as default argument to a method or function
1810 query = self.filterOnUUID(session.query(Machine), uuid)
1811
1812 ret = []
1813 for machine in query:
1814 if count:
1815 ret = len(machine.networkports)
1816 else:
1817 for networkport in machine.networkports:
1818 # Get IP, one networkport can have multiple IPs
1819 ipaddresses = []
1820 gateways = []
1821 netmasks = []
1822 if networkport.networknames is not None:
1823 ipaddresses = list(
1824 set([ip.name for ip in networkport.networknames.ipaddresses if ip.name != '']))
1825 gateways = []
1826 netmasks = []
1827 for ip in networkport.networknames.ipaddresses:
1828 gateways += [ipnetwork.gateway for ipnetwork in ip.ipnetworks if
1829 ipnetwork.gateway not in ['', '0.0.0.0']]
1830 netmasks += [ipnetwork.netmask for ipnetwork in ip.ipnetworks if
1831 ipnetwork.netmask not in ['', '0.0.0.0']]
1832 gateways = list(set(gateways))
1833 netmasks = list(set(netmasks))
1834 l = [
1835 ['Name', networkport.name],
1836 ['Network Type', self._get_network_type(networkport.instantiation_type)],
1837 ['MAC Address', networkport.mac],
1838 ['IP', ' / '.join(ipaddresses)],
1839 ['Netmask', ' / '.join(netmasks)],
1840 ['Gateway', ' / '.join(gateways)],
1841 ]
1842 ret.append(l)
1843 return ret
1844
1845 def getLastMachineStoragePart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
1846 # Mutable dict options used as default argument to a method or function
1847 query = self.filterOnUUID(
1848 session.query(Disk).add_column(self.diskfs.c.name).select_from(
1849 self.machine.outerjoin(self.disk).outerjoin(self.diskfs)
1850 ), uuid)
1851 if count:
1852 ret = query.count()
1853 else:
1854 ret = []
1855 for disk, diskfs in query:
1856 if diskfs not in ['rootfs', 'tmpfs', 'devtmpfs']:
1857 if disk is not None:
1858 l = [
1859 ['Name', disk.name],
1860 ['Device', disk.device],
1861 ['Mount Point', disk.mountpoint],
1862 ['Filesystem', diskfs],
1863 ['Size', disk.totalsize and str(disk.totalsize) + ' MB' or ''],
1864 ['Free Size', disk.freesize and str(disk.freesize) + ' MB' or ''],
1865 ]
1866 ret.append(l)
1867 return ret
1868
1869 def getLastMachineAdministrativePart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
1870 # Mutable dict options used as default argument to a method or function
1871 query = self.filterOnUUID(
1872 session.query(Infocoms).add_column(self.suppliers.c.name).select_from(
1873 self.machine.outerjoin(self.infocoms).outerjoin(self.suppliers)
1874 ), uuid)
1875
1876 if count:
1877 ret = query.count()
1878 else:
1879 ret = []
1880 for infocoms, supplierName in query:
1881 if infocoms is not None:
1882 endDate = self.getWarrantyEndDate(infocoms)
1883 dateOfPurchase = ''
1884 if infocoms.buy_date is not None:
1885 dateOfPurchase = infocoms.buy_date.strftime('%Y-%m-%d')
1886
1887 l = [
1888 ['Supplier', supplierName],
1889 ['Invoice Number', infocoms.bill],
1890 ['Date Of Purchase', dateOfPurchase],
1891 ['Warranty End Date', endDate],
1892 ]
1893 ret.append(l)
1894 return ret
1895
1896 def getLastMachineAntivirusPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
1897 # Mutable dict options used as default argument to a method or function
1898 if self.fusionantivirus is None: # glpi_plugin_fusinvinventory_antivirus doesn't exists
1899 return []
1900
1901 query = self.filterOnUUID(
1902 session.query(FusionAntivirus).add_column(self.manufacturers.c.name).select_from(
1903 self.machine.outerjoin(self.fusionantivirus).outerjoin(self.manufacturers)
1904 ), uuid)
1905
1906 def __getAntivirusName(manufacturerName, antivirusName):
1907 """
1908 Return complete antivirus name (manufacturer + antivirus name)
1909 if antivirus name is a false positive, display it in bracket
1910 """
1911 if antivirusName in self.config.av_false_positive:
1912 antivirusName += '@@FALSE_POSITIVE@@'
1913
1914 return manufacturerName and ' '.join([manufacturerName, antivirusName]) or antivirusName
1915
1916 if count:
1917 ret = query.count()
1918 else:
1919 ret = []
1920 for antivirus, manufacturerName in query:
1921 if antivirus:
1922 l = [
1923 ['Name', __getAntivirusName(manufacturerName, antivirus.name)],
1924 ['Enabled', antivirus.is_active == 1 and 'Yes' or 'No'],
1925 ['Up-to-date', antivirus.is_uptodate == 1 and 'Yes' or 'No'],
1926 ]
1927 if antivirus.version:
1928 l.insert(1, ['Version', antivirus.version])
1929 ret.append(l)
1930 return ret
1931
1932 def getLastMachineSoftwaresPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
1933 # Mutable dict options used as default argument to a method or function
1934 hide_win_updates = False
1935 if 'hide_win_updates' in options:
1936 hide_win_updates = options['hide_win_updates']
1937
1938 query = self.filterOnUUID(
1939 session.query(Software).add_column(self.manufacturers.c.name) \
1940 .add_column(self.softwareversions.c.name).select_from(
1941 self.machine.outerjoin(self.inst_software) \
1942 .outerjoin(self.softwareversions) \
1943 .outerjoin(self.software) \
1944 .outerjoin(self.manufacturers)
1945 ), uuid)
1946 query = query.order_by(self.software.c.name)
1947
1948 if filt:
1949 clauses = []
1950 clauses.append(self.manufacturers.c.name.like('%' + filt + '%'))
1951 clauses.append(self.softwareversions.c.name.like('%' + filt + '%'))
1952 clauses.append(self.software.c.name.like('%' + filt + '%'))
1953 query = query.filter(or_(*clauses))
1954
1955 if hide_win_updates:
1956 query = query.filter(
1957 not_(
1958 and_(
1959 self.manufacturers.c.name.contains('microsoft'),
1960 self.software.c.name.op('regexp')('KB[0-9]+(-v[0-9]+)?(v[0-9]+)?')
1961 )
1962 )
1963 )
1964
1965 if min != 0:
1966 query = query.offset(min)
1967 if max != -1:
1968 max = int(max) - int(min)
1969 query = query.limit(max)
1970
1971 if count:
1972 ret = query.count()
1973 else:
1974 ret = []
1975 for software, manufacturer, version in query:
1976 if software is not None:
1977 l = [
1978 ['Vendor', manufacturer],
1979 ['Name', software.name],
1980 ['Version', version],
1981 ]
1982 ret.append(l)
1983 return ret
1984
1985 def __getTableAndFieldFromName(self, name):
1986 """
1987 return table class and field name for a given name
1988 used for editable fields
1989
1990 @param name: a given name
1991 @type name: string
1992
1993 @return: table class and field name
1994 @rtype: tuple
1995 """
1996
1997 # Reminder:
1998 # If you add some other classes, check
1999 # if __tablename__ exists for these classes
2000
2001 values = {
2002 'computer_name': (Machine, 'name'),
2003 'description': (Machine, 'comment'),
2004 'inventory_number': (Machine, 'otherserial'),
2005 }
2006
2007 return values[name]
2008
2009 def setGlpiEditableValue(self, uuid, name, value):
2010 """
2011 Set a new value for a Glpi field
2012
2013 @param uuid: machine uuid
2014 @type uuid: string
2015
2016 @param name: Glpi field who will be updated
2017 @param name: string
2018
2019 @param value: The new value
2020 @param value: string
2021 """
2022
2023 self.logger.debug("Update an editable field")
2024 self.logger.debug("%s: Set %s as new value for %s" % (uuid, value, name))
2025 try:
2026 session = create_session()
2027
2028 # Get SQL field who will be updated
2029 table, field = self.__getTableAndFieldFromName(name)
2030 session.query(table).filter_by(id=fromUUID(uuid)).update({field: value})
2031
2032 # Set updated field as a locked field so it won't be updated
2033 # at next inventory
2034 query = session.query(FusionLocks).filter(self.fusionlocks.c.items_id == fromUUID(uuid))
2035 flocks = query.first()
2036 if flocks is not None:
2037 # Update glpi_plugin_fusioninventory_locks tablefields table
2038 flocksFields = eval(flocks.tablefields)
2039 if field not in flocksFields:
2040 flocksFields.append(field)
2041 query.update({'tablefields': str(flocksFields).replace("'", '"')})
2042 else:
2043 # Create new glpi_plugin_fusioninventory_locks entry
2044 session.execute(
2045 self.fusionlocks.insert().values({
2046 'tablename': table.__tablename__,
2047 'items_id': fromUUID(uuid),
2048 'tablefields': str([field]).replace("'", '"'),
2049 })
2050 )
2051
2052 session.close()
2053 return True
2054 except Exception, e:
2055 self.logger.error(e)
2056 return False
2057
2058 def getLastMachineSummaryPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
2059 # Mutable dict options used as default argument to a method or function
2060 query = self.filterOnUUID(
2061 session.query(Machine).add_entity(Infocoms) \
2062 .add_column(self.entities.c.name) \
2063 .add_column(self.locations.c.name) \
2064 .add_column(self.os.c.name) \
2065 .add_column(self.manufacturers.c.name) \
2066 .add_column(self.glpi_computertypes.c.name) \
2067 .add_column(self.glpi_computermodels.c.name) \
2068 .add_column(self.glpi_operatingsystemservicepacks.c.name) \
2069 .add_column(self.glpi_domains.c.name) \
2070 .add_column(self.state.c.name) \
2071 .add_column(self.fusionagents.c.last_contact) \
2072 .select_from(
2073 self.machine.outerjoin(self.entities) \
2074 .outerjoin(self.locations) \
2075 .outerjoin(self.os) \
2076 .outerjoin(self.manufacturers) \
2077 .outerjoin(self.infocoms) \
2078 .outerjoin(self.glpi_computertypes) \
2079 .outerjoin(self.glpi_computermodels) \
2080 .outerjoin(self.glpi_operatingsystemservicepacks) \
2081 .outerjoin(self.state) \
2082 .outerjoin(self.fusionagents) \
2083 .outerjoin(self.glpi_domains)
2084 ), uuid)
2085
2086 if count:
2087 ret = query.count()
2088 else:
2089 ret = []
2090 for machine, infocoms, entity, location, os, manufacturer, type, model, servicepack, domain, state, last_contact in query:
2091 endDate = ''
2092 if infocoms is not None:
2093 endDate = self.getWarrantyEndDate(infocoms)
2094
2095 modelType = []
2096 if model is not None:
2097 modelType.append(model)
2098 if type is not None:
2099 modelType.append(type)
2100
2101 if len(modelType) == 0:
2102 modelType = ''
2103 elif len(modelType) == 1:
2104 modelType = modelType[0]
2105 elif len(modelType) == 2:
2106 modelType = " / ".join(modelType)
2107
2108 manufacturerWarranty = False
2109 if machine.serial is not None and len(machine.serial) > 0:
2110 manufacturerWarranty = self.getManufacturerWarranty(manufacturer, machine.serial)
2111
2112 if manufacturerWarranty:
2113 if manufacturerWarranty['type'] == 'get':
2114 url = manufacturerWarranty['url'] + '?' + manufacturerWarranty['params']
2115 serialNumber = '%s / <a href="%s" target="_blank">@@WARRANTY_LINK_TEXT@@</a>' % (
2116 machine.serial, url)
2117 else:
2118 url = manufacturerWarranty['url']
2119 serialNumber = '%s / <form action="%s" method="post" target="_blank" id="warrantyCheck" style="display: inline">' % (
2120 machine.serial, url)
2121 for param in manufacturerWarranty['params'].split('&'):
2122 name, value = param.split('=')
2123 serialNumber += '<input type="hidden" name="%s" value="%s" />' % (name, value)
2124 serialNumber += '<a href="#" onclick="jQuery(\'#warrantyCheck\').submit(); return false;">@@WARRANTY_LINK_TEXT@@</a></form>'
2125 else:
2126 serialNumber = machine.serial
2127
2128 entityValue = ''
2129 if entity:
2130 entityValue += entity
2131 if location:
2132 entityValue += ' (%s)' % location
2133
2134 owner_login, owner_firstname, owner_realname = self.getMachineOwner(machine)
2135
2136 # Last inventory date
2137 date_mod = machine.date_mod
2138 if self.fusionagents is not None and last_contact is not None:
2139 date_mod = last_contact
2140
2141 l = [
2142 ['Computer Name', ['computer_name', 'text', machine.name]],
2143 ['Description', ['description', 'text', machine.comment]],
2144 ['Entity (Location)', '%s' % entityValue],
2145 ['Domain', domain],
2146 ['Last Logged User', machine.contact],
2147 ['Owner', owner_login],
2148 ['Owner Firstname', owner_firstname],
2149 ['Owner Realname', owner_realname],
2150 ['OS', os],
2151 ['Service Pack', servicepack],
2152 ['Windows Key', machine.os_license_number],
2153 ['Model / Type', modelType],
2154 ['Manufacturer', manufacturer],
2155 ['Serial Number', serialNumber],
2156 ['Inventory Number', ['inventory_number', 'text', machine.otherserial]],
2157 ['State', state],
2158 ['Warranty End Date', endDate],
2159 ['Last Inventory Date', date_mod.strftime("%Y-%m-%d %H:%M:%S")],
2160 ]
2161 ret.append(l)
2162 return ret
2163
2164 def getLastMachineProcessorsPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
2165 # Mutable dict options used as default argument to a method or function
2166 # options = options or {}
2167 query = self.filterOnUUID(
2168 session.query(ComputerProcessor).add_column(self.processor.c.designation) \
2169 .select_from(
2170 self.machine.outerjoin(self.computerProcessor) \
2171 .outerjoin(self.processor)
2172 ), uuid)
2173
2174 if count:
2175 ret = query.count()
2176 else:
2177 ret = []
2178 for processor, designation in query:
2179 if processor is not None:
2180 l = [
2181 ['Name', designation],
2182 ['Frequency', processor.frequency and str(processor.frequency) + ' MHz' or ''],
2183 ]
2184 ret.append(l)
2185 return ret
2186
2187 def getLastMachineMemoryPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
2188 # Mutable dict options used as default argument to a method or function
2189 # options = options or {}
2190 query = self.filterOnUUID(
2191 session.query(ComputerMemory) \
2192 .add_column(self.memoryType.c.name) \
2193 .add_column(self.memory.c.frequence) \
2194 .add_column(self.memory.c.designation).select_from(
2195 self.machine.outerjoin(self.computerMemory) \
2196 .outerjoin(self.memory) \
2197 .outerjoin(self.memoryType)
2198 ), uuid)
2199
2200 if count:
2201 ret = query.count()
2202 else:
2203 ret = []
2204 for memory, type, frequence, designation in query:
2205 if memory is not None:
2206 l = [
2207 ['Name', designation],
2208 ['Type', type],
2209 ['Frequency', frequence],
2210 ['Size', memory.size and str(memory.size) + ' MB' or ''],
2211 ]
2212 ret.append(l)
2213 return ret
2214
2215 def getLastMachineHarddrivesPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
2216 # Mutable dict options used as default argument to a method or function
2217 # options = options or {}
2218 query = self.filterOnUUID(
2219 session.query(self.klass['computers_deviceharddrives']) \
2220 .add_column(self.deviceharddrives.c.designation) \
2221 .select_from(
2222 self.machine.outerjoin(self.computers_deviceharddrives) \
2223 .outerjoin(self.deviceharddrives)
2224 ), uuid)
2225
2226 if count:
2227 ret = query.count()
2228 else:
2229 ret = []
2230 for hd, designation in query:
2231 if hd is not None:
2232 l = [
2233 ['Name', designation],
2234 ['Size', hd.capacity and str(hd.capacity) + ' MB' or ''],
2235 ]
2236 ret.append(l)
2237 return ret
2238
2239 def getLastMachineNetworkCardsPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
2240 # Mutable dict options used as default argument to a method or function
2241 # options = options or {}
2242 query = self.filterOnUUID(
2243 session.query(self.klass['computers_devicenetworkcards']) \
2244 .add_entity(self.klass['devicenetworkcards']) \
2245 .select_from(
2246 self.machine.outerjoin(self.computers_devicenetworkcards) \
2247 .outerjoin(self.devicenetworkcards)
2248 ), uuid)
2249
2250 if count:
2251 ret = query.count()
2252 else:
2253 ret = []
2254 for mac, network in query:
2255 if network is not None:
2256 l = [
2257 ['Name', network.designation],
2258 ['Bandwidth', network.bandwidth],
2259 ['MAC Address', mac.mac],
2260 ]
2261 ret.append(l)
2262 return ret
2263
2264 def getLastMachineDrivesPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
2265 # Mutable dict options used as default argument to a method or function
2266 # options = options or {}
2267 query = self.filterOnUUID(
2268 session.query(self.klass['devicedrives']).select_from(
2269 self.machine.outerjoin(self.computers_devicedrives) \
2270 .outerjoin(self.devicedrives)
2271 ), uuid)
2272
2273 if count:
2274 ret = query.count()
2275 else:
2276 ret = []
2277 for drive in query:
2278 if drive is not None:
2279 l = [
2280 ['Name', drive.designation],
2281 ['Writer', drive.is_writer and 'Yes' or 'No'],
2282 ]
2283 ret.append(l)
2284 return ret
2285
2286 def getLastMachineGraphicCardsPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
2287 # Mutable dict options used as default argument to a method or function
2288 # options = options or {}
2289 query = self.filterOnUUID(
2290 session.query(self.klass['devicegraphiccards']).add_column(self.interfaceType.c.name) \
2291 .select_from(
2292 self.machine.outerjoin(self.computers_devicegraphiccards) \
2293 .outerjoin(self.devicegraphiccards) \
2294 .outerjoin(self.interfaceType,
2295 self.interfaceType.c.id == self.devicegraphiccards.c.interfacetypes_id)
2296 ), uuid)
2297
2298 if count:
2299 ret = query.count()
2300 else:
2301 ret = []
2302 for card, interfaceType in query:
2303 if card is not None:
2304 l = [
2305 ['Name', card.designation],
2306 ['Memory', card.memory_default and str(card.memory_default) + ' MB' or ''],
2307 ['Type', interfaceType],
2308 ]
2309 ret.append(l)
2310 return ret
2311
2312 def getLastMachineSoundCardsPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
2313 # Mutable dict options used as default argument to a method or function
2314 # options = options or {}
2315 query = self.filterOnUUID(
2316 session.query(self.klass['devicesoundcards']).select_from(
2317 self.machine.outerjoin(self.computers_devicesoundcards) \
2318 .outerjoin(self.devicesoundcards)
2319 ), uuid)
2320
2321 if count:
2322 ret = query.count()
2323 else:
2324 ret = []
2325 for sound in query:
2326 if sound is not None:
2327 l = [
2328 ['Name', sound.designation],
2329 ]
2330 ret.append(l)
2331 return ret
2332
2333 def getLastMachineControllersPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
2334 # Mutable dict options used as default argument to a method or function
2335 # options = options or {}
2336 query = self.filterOnUUID(
2337 session.query(self.klass['computers_devicecontrols']) \
2338 .add_entity(self.klass['devicecontrols']).select_from(
2339 self.machine.outerjoin(self.computers_devicecontrols) \
2340 .outerjoin(self.devicecontrols)
2341 ), uuid)
2342
2343 if count:
2344 ret = query.count()
2345 else:
2346 ret = []
2347 for computerControls, deviceControls in query:
2348 if computerControls is not None:
2349 l = [
2350 ['Name', deviceControls.designation],
2351 ]
2352 ret.append(l)
2353 return ret
2354
2355 def getLastMachineOthersPart(self, session, uuid, part, min=0, max=-1, filt=None, options=None, count=False):
2356 # Mutable dict options used as default argument to a method or function
2357 options = options or {}
2358 query = self.filterOnUUID(
2359 session.query(self.klass['devicepcis']).select_from(
2360 self.machine.outerjoin(self.computers_devicepcis) \
2361 .outerjoin(self.devicepcis)
2362 ), uuid)
2363
2364 if count:
2365 ret = query.count()
2366 else:
2367 ret = []
2368 for pci in query:
2369 if pci is not None:
2370 l = [
2371 ['Name', pci.designation],
2372 ['Comment', pci.comment],
2373 ]
2374 ret.append(l)
2375 return ret
2376
2377 def getLastMachineHistoryPart(self, session, uuid, part, min=0, max=-1, filt=None, options={}, count=False):
2378 # Mutable dict options used as default argument to a method or function
2379 # options = options or {}
2380 # Set options
2381 history_delta = 'All'
2382 if 'history_delta' in options:
2383 history_delta = options['history_delta']
2384
2385 query = session.query(Logs)
2386 query = query.filter(and_(
2387 self.logs.c.items_id == int(uuid.replace('UUID', '')),
2388 self.logs.c.itemtype == "Computer"
2389 ))
2390
2391 now = datetime.datetime.now()
2392 if history_delta == 'today':
2393 query = query.filter(self.logs.c.date_mod > now - datetime.timedelta(1))
2394 elif history_delta == 'week':
2395 query = query.filter(self.logs.c.date_mod > now - datetime.timedelta(7))
2396 if history_delta == 'month':
2397 query = query.filter(self.logs.c.date_mod > now - datetime.timedelta(30))
2398
2399 if filt:
2400 clauses = []
2401 clauses.append(self.logs.c.date_mod.like('%' + filt + '%'))
2402 clauses.append(self.logs.c.user_name.like('%' + filt + '%'))
2403 clauses.append(self.logs.c.old_value.like('%' + filt + '%'))
2404 clauses.append(self.logs.c.new_value.like('%' + filt + '%'))
2405 clauses.append(self.logs.c.id_search_option.in_(self.getSearchOptionId(filt)))
2406 clauses.append(self.logs.c.itemtype_link.in_(self.getLinkedActionKey(filt)))
2407 # Treat Software case
2408 if filt.lower() in 'software':
2409 clauses.append(self.logs.c.linked_action.in_([4, 5]))
2410 query = query.filter(or_(*clauses))
2411
2412 if count:
2413 ret = query.count()
2414 else:
2415 query = query.order_by(desc(self.logs.c.date_mod))
2416
2417 if min != 0:
2418 query = query.offset(min)
2419 if max != -1:
2420 max = int(max) - int(min)
2421 query = query.limit(max)
2422
2423 ret = []
2424 for log in query:
2425 if log is not None:
2426 update = ''
2427 if log.old_value == '' and log.new_value != '':
2428 update = '%s' % log.new_value
2429 elif log.old_value != '' and log.new_value == '':
2430 update = '%s' % log.old_value
2431 else:
2432 update = '%s --> %s' % (log.old_value, log.new_value)
2433
2434 update = '%s%s' % (self.getLinkedActionValues(log)['update'], update)
2435
2436 l = [
2437 ['Date', log.date_mod.strftime('%Y-%m-%d %H:%m')],
2438 ['User', log.user_name],
2439 ['Category', self.getLinkedActionValues(log)['field']],
2440 ['Action', update],
2441 ]
2442 ret.append(l)
2443 return ret
2444
2445 def getLastMachineInventoryPart(self, uuid, part, minbound=0, maxbound=-1, filt=None, options=None, count=False):
2446 # Mutable dict options used as default argument to a method or function
2447 options = options or {}
2448 session = create_session()
2449
2450 ret = None
2451 if hasattr(self, 'getLastMachine%sPart' % part):
2452 ret = getattr(self, 'getLastMachine%sPart' % part)(session, uuid, part, minbound, maxbound, filt, options,
2453 count)
2454
2455 session.close()
2456 return ret
2457
2458 def getSearchOptionValue(self, log):
2459 try:
2460 return self.searchOptions['en_US'][str(log.id_search_option)]
2461 except:
2462 if log.id_search_option != 0:
2463 logging.getLogger().warn('I can\'t get a search option for id %s' % log.id_search_option)
2464 return ''
2465
2466 def getLinkedActionValues(self, log):
2467 d = {
2468 0: {
2469 'update': '',
2470 'field': self.getSearchOptionValue(log),
2471 },
2472 1: {
2473 'update': 'Add a component: ',
2474 'field': self.getLinkedActionField(log.itemtype_link),
2475 },
2476 2: {
2477 'update': 'Update a component: ',
2478 'field': self.getLinkedActionField(log.itemtype_link),
2479 },
2480 3: {
2481 'update': 'Deletion of a component: ',
2482 'field': self.getLinkedActionField(log.itemtype_link),
2483 },
2484 4: {
2485 'update': 'Install software: ',
2486 'field': 'Software',
2487 },
2488 5: {
2489 'update': 'Uninstall software: ',
2490 'field': 'Software',
2491 },
2492 6: {
2493 'update': 'Disconnect device: ',
2494 'field': log.itemtype_link,
2495 },
2496 7: {
2497 'update': 'Connect device: ',
2498 'field': log.itemtype_link,
2499 },
2500 8: {
2501 'update': 'OCS Import: ',
2502 'field': '',
2503 },
2504 9: {
2505 'update': 'OCS Delete: ',
2506 'field': '',
2507 },
2508 10: {
2509 'update': 'OCS ID Changed: ',
2510 'field': '',
2511 },
2512 11: {
2513 'update': 'OCS Link: ',
2514 'field': '',
2515 },
2516 12: {
2517 'update': 'Other (often from plugin): ',
2518 'field': '',
2519 },
2520 13: {
2521 'update': 'Delete item (put in trash): ',
2522 'field': '',
2523 },
2524 14: {
2525 'update': 'Restore item from trash: ',
2526 'field': '',
2527 },
2528 15: {
2529 'update': 'Add relation: ',
2530 'field': log.itemtype_link,
2531 },
2532 16: {
2533 'update': 'Delete relation: ',
2534 'field': log.itemtype_link,
2535 },
2536 17: {
2537 'update': 'Add an item: ',
2538 'field': self.getLinkedActionField(log.itemtype_link),
2539 },
2540 18: {
2541 'update': 'Update an item: ',
2542 'field': self.getLinkedActionField(log.itemtype_link),
2543 },
2544 19: {
2545 'update': 'Deletion of an item: ',
2546 'field': self.getLinkedActionField(log.itemtype_link),
2547 },
2548 }
2549
2550 if log.linked_action in d:
2551 return d[log.linked_action]
2552 else:
2553 return {
2554 'update': '',
2555 'field': '',
2556 }
2557
2558 def getLinkedActions(self):
2559 return {
2560 'DeviceDrive': 'Drive',
2561 'DeviceGraphicCard': 'Graphic Card',
2562 'DeviceHardDrive': 'Hard Drive',
2563 'DeviceMemory': 'Memory',
2564 'DeviceNetworkCard': 'Network Card',
2565 'DevicePci': 'Other Component',
2566 'DeviceProcessor': 'Processor',
2567 'DeviceSoundCard': 'Sound Card',
2568 'ComputerDisk': 'Volume',
2569 'NetworkPort': 'Network Port',
2570 }
2571
2572 def getLinkedActionField(self, itemtype):
2573 """
2574 return Field content
2575 """
2576 field = self.getLinkedActions()
2577 try:
2578 return field[itemtype]
2579 except:
2580 return itemtype
2581
2582 def getUnknownPXEOSId(self, unknownOsString):
2583 """
2584 Return id of Unknown OS depending given string
2585
2586 @param unknownOsString: unknown OS string
2587 @type: str
2588
2589 @return: id of Unknown OS string
2590 @rtype: int
2591 """
2592 ret = None
2593 session = create_session()
2594 query = session.query(OS).filter(self.os.c.name == unknownOsString)
2595 result = query.first()
2596 if result is not None:
2597 ret = result.id
2598 session.close()
2599 return ret
2600
2601 def hasKnownOS(self, uuid):
2602 """
2603 Return True if machine has a known Operating System
2604 Used to know if a PXE inventory will be sent or not
2605 * If no known OS: send inventory
2606 * if known OS: don't send inventory
2607
2608 @param uuid: UUID of machine
2609 @type uuid: str
2610
2611 @return: True or False if machine has a known OS
2612 @rtype: boolean
2613 """
2614 session = create_session()
2615 # In GLPI, unknown OS id is 0
2616 # PXE Inventory create a new one with name: "Unknown operating system (PXE network boot inventory)"
2617 unknown_os_ids = [0]
2618 unknown_os_pxe_id = self.getUnknownPXEOSId("Unknown operating system (PXE network boot inventory)")
2619 if unknown_os_pxe_id:
2620 unknown_os_ids.append(unknown_os_pxe_id)
2621
2622 query = self.filterOnUUID(
2623 session.query(Machine).filter(not_(self.machine.c.operatingsystems_id.in_(unknown_os_ids))), uuid)
2624 session.close()
2625
2626 return query.first() and True or False
2627
2628 ##################### functions used by querymanager
2629 def getAllOs(self, ctx, filt=''):
2630 """
2631 @return: all os defined in the GLPI database
2632 """
2633 session = create_session()
2634 query = session.query(OS).select_from(self.os.join(self.machine))
2635 query = self.__filter_on(query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0))
2636 query = self.__filter_on_entity(query, ctx)
2637 if filter != '':
2638 query = query.filter(self.os.c.name.like('%' + filt + '%'))
2639 ret = query.all()
2640 session.close()
2641 return ret
2642
2643 def getMachineByOs(self, ctx, osname):
2644 """
2645 @return: all machines that have this os
2646 """
2647 # TODO use the ctx...
2648 session = create_session()
2649 query = session.query(Machine).select_from(self.machine.join(self.os)).filter(self.os.c.name == osname)
2650 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
2651 query = self.__filter_on(query)
2652 query = self.__filter_on_entity(query, ctx)
2653 ret = query.all()
2654 session.close()
2655 return ret
2656
2657 @DatabaseHelper._session
2658 def getMachineByOsLike(self, session, ctx, osnames, count=0):
2659 """
2660 @return: all machines that have this os using LIKE
2661 """
2662 if isinstance(osnames, basestring):
2663 osnames = [osnames]
2664
2665 if int(count) == 1:
2666 query = session.query(func.count(Machine.id)).select_from(self.machine.outerjoin(self.os))
2667 else:
2668 query = session.query(Machine).select_from(self.machine.outerjoin(self.os))
2669
2670 query = query.filter(Machine.is_deleted == 0).filter(Machine.is_template == 0)
2671 query = self.__filter_on(query)
2672 query = self.__filter_on_entity(query, ctx)
2673
2674 if osnames == ["other"]:
2675 query = query.filter(
2676 or_(
2677 and_(
2678 not_(OS.name.like('%Windows%')), not_(OS.name.like('%Mageia%')),
2679 ), Machine.operatingsystems_id == 0,
2680 ))
2681 elif osnames == ["otherw"]:
2682 query = query.filter(and_(not_(OS.name.like('%Windows%10%')), not_(OS.name.like('%Windows%8%')), \
2683 not_(OS.name.like('%Windows%7%')), not_(OS.name.like('%Windows%Vista%')), \
2684 not_(OS.name.like('%Windows%XP%')), OS.name.like('%Windows%')))
2685 # if osnames == ['%'], we want all machines, including machines without OS (used for reporting, per example...)
2686 elif osnames != ['%']:
2687 os_filter = [OS.name.like('%' + osname + '%') for osname in osnames]
2688 query = query.filter(or_(*os_filter))
2689
2690 if int(count) == 1:
2691 return int(query.scalar())
2692 else:
2693 return [[q.id, q.name] for q in query]
2694
2695 def getAllEntities(self, ctx, filt=''):
2696 """
2697 @return: all entities defined in the GLPI database
2698 """
2699 session = create_session()
2700 query = session.query(Entities)
2701 if filter != '':
2702 query = query.filter(self.entities.c.name.like('%' + filt + '%'))
2703
2704 # Request only entites current user can access
2705 if not hasattr(ctx, 'locationsid'):
2706 complete_ctx(ctx)
2707 query = query.filter(self.entities.c.id.in_(ctx.locationsid))
2708
2709 query = query.order_by(self.entities.c.name)
2710 ret = query.all()
2711 session.close()
2712 return ret
2713
2714 def getMachineByEntity(self, ctx, enname):
2715 """
2716 @return: all machines that are in this entity
2717 """
2718 # TODO use the ctx...
2719 session = create_session()
2720 query = session.query(Machine).select_from(self.machine.join(self.entities)).filter(
2721 self.entities.c.name == enname)
2722 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
2723 query = self.__filter_on(query)
2724 query = self.__filter_on_entity(query, ctx)
2725 ret = query.all()
2726 session.close()
2727 return ret
2728
2729 def getEntitiesParentsAsList(self, lids):
2730 my_parents_ids = []
2731 my_parents = self.getEntitiesParentsAsDict(lids)
2732 for p in my_parents:
2733 for i in my_parents[p]:
2734 if not my_parents_ids.__contains__(i):
2735 my_parents_ids.append(i)
2736 return my_parents_ids
2737
2738 def getEntitiesParentsAsDict(self, lids):
2739 session = create_session()
2740 if type(lids) != list and type(lids) != tuple:
2741 lids = (lids)
2742 query = session.query(Entities).all()
2743 locs = {}
2744 for l in query:
2745 locs[l.id] = l.entities_id
2746
2747 def __getParent(i):
2748 if i in locs:
2749 return locs[i]
2750 else:
2751 return None
2752
2753 ret = {}
2754 for i in lids:
2755 t = []
2756 p = __getParent(i)
2757 while p != None:
2758 t.append(p)
2759 p = __getParent(p)
2760 ret[i] = t
2761 return ret
2762
2763 @DatabaseHelper._session
2764 def getAllVersion4Software(self, session, ctx, softname, version=''):
2765 """
2766 @return: all softwares defined in the GLPI database
2767 """
2768 if not hasattr(ctx, 'locationsid'):
2769 complete_ctx(ctx)
2770 query = session.query(distinct(SoftwareVersion.name)) \
2771 .select_from(self.softwareversions.join(self.software))
2772
2773 my_parents_ids = self.getEntitiesParentsAsList(ctx.locationsid)
2774 query = query.filter(
2775 or_(
2776 Software.entities_id.in_(ctx.locationsid),
2777 and_(
2778 Software.is_recursive == 1,
2779 Software.entities_id.in_(my_parents_ids)
2780 )
2781 )
2782 )
2783
2784 query = query.filter(Software.name.like('%' + softname + '%'))
2785
2786 if version:
2787 query = query.filter(SoftwareVersion.name.like('%' + version + '%'))
2788
2789 # Last softwareversion entries first
2790 query = query.order_by(desc(SoftwareVersion.id))
2791
2792 ret = query.all()
2793 return ret
2794
2795 @DatabaseHelper._session
2796 def getAllSoftwares(self, session, ctx, softname='', vendor=None, limit=None):
2797 """
2798 @return: all softwares defined in the GLPI database
2799 """
2800 if not hasattr(ctx, 'locationsid'):
2801 complete_ctx(ctx)
2802
2803 query = session.query(distinct(Software.name))
2804 query = query.select_from(
2805 self.software \
2806 .join(self.softwareversions) \
2807 .join(self.inst_software) \
2808 .join(self.manufacturers, isouter=True)
2809 )
2810 my_parents_ids = self.getEntitiesParentsAsList(ctx.locationsid)
2811 query = query.filter(
2812 or_(
2813 Software.entities_id.in_(ctx.locationsid),
2814 and_(
2815 Software.is_recursive == 1,
2816 Software.entities_id.in_(my_parents_ids)
2817 )
2818 )
2819 )
2820 if vendor is not None:
2821 query = query.filter(Manufacturers.name.like(vendor))
2822
2823 if softname != '':
2824 query = query.filter(Software.name.like('%' + softname + '%'))
2825
2826 # Last software entries first
2827 query = query.order_by(desc(Software.id))
2828
2829 if limit is None:
2830 ret = query.all()
2831 else:
2832 ret = query.limit(limit).all()
2833 return ret
2834
2835 @DatabaseHelper._session
2836 def getAllSoftwaresByManufacturer(self, session, ctx, vendor):
2837 """
2838 Return all softwares of a vendor
2839 """
2840 if not hasattr(ctx, 'locationsid'):
2841 complete_ctx(ctx)
2842 query = session.query(Software)
2843 query = query.join(Manufacturers)
2844 query = query.filter(Manufacturers.name.like(vendor))
2845 ret = query.group_by(Software.name).order_by(Software.name).all()
2846 return ret
2847
2848 @DatabaseHelper._session
2849 def getMachineBySoftware(self,
2850 session,
2851 ctx,
2852 name,
2853 vendor=None,
2854 version=None,
2855 count=0):
2856 """
2857 @return: all machines that have this software
2858 """
2859
2860 def all_elem_are_none(params):
2861 for param in params:
2862 if param is not None:
2863 return False
2864 return True
2865
2866 def check_list(param):
2867 if not isinstance(param, list):
2868 return [param]
2869 elif all_elem_are_none(param):
2870 return None
2871 elif not param:
2872 return None
2873 else:
2874 return param
2875
2876 name = check_list(name)
2877 if vendor is not None: vendor = check_list(vendor)
2878 if version is not None: version = check_list(version)
2879
2880 if int(count) == 1:
2881 query = session.query(func.count(distinct(self.machine.c.id)))
2882 else:
2883 query = session.query(distinct(self.machine.c.id))
2884
2885 query = query.select_from(self.machine
2886 .join(self.inst_software)
2887 .join(self.softwareversions)
2888 .join(self.software)
2889 .outerjoin(self.manufacturers))
2890 query = query.filter(Machine.is_deleted == 0)
2891 query = query.filter(Machine.is_template == 0)
2892 query = self.__filter_on(query)
2893 query = self.__filter_on_entity(query, ctx)
2894
2895 name_filter = [Software.name.like(n) for n in name]
2896 query = query.filter(or_(*name_filter))
2897
2898 if version is not None:
2899 version_filter = [SoftwareVersion.name.like(v) for v in version]
2900 query = query.filter(or_(*version_filter))
2901
2902 if vendor is not None:
2903 vendor_filter = [Manufacturers.name.like(v) for v in vendor]
2904 query = query.filter(or_(*vendor_filter))
2905
2906 if int(count) == 1:
2907 ret = int(query.scalar())
2908 else:
2909 ret = query.all()
2910 return ret
2911
2912 @DatabaseHelper._session
2913 def getAllSoftwaresImproved(self,
2914 session,
2915 ctx,
2916 name,
2917 vendor=None,
2918 version=None,
2919 count=0):
2920 """
2921 if count == 1
2922 This method is used for reporting and license count
2923 it's inspired from getMachineBySoftware method, but instead of count
2924 number of machines who have this soft, this method count number of
2925 softwares
2926
2927 Example: 5 firefox with different version on a single machine:
2928 getMachineBySoftware: return 1
2929 this method: return 5
2930
2931 I should use getAllSoftwares method, but deadline is yesterday....
2932 if count = 3
2933 return: all machines that have this software and the entity
2934
2935 """
2936
2937 def all_elem_are_none(params):
2938 for param in params:
2939 if param is not None:
2940 return False
2941 return True
2942
2943 def check_list(param):
2944 if not isinstance(param, list):
2945 return [param]
2946 elif all_elem_are_none(param):
2947 return None
2948 elif not param:
2949 return None
2950 else:
2951 return param
2952
2953 name = check_list(name)
2954 if vendor is not None: vendor = check_list(vendor)
2955 if version is not None: version = check_list(version)
2956
2957 if int(count) == 1:
2958 query = session.query(func.count(self.software.c.name))
2959 elif int(count) == 2:
2960 query = session.query(self.software.c.name)
2961 else:
2962 query = session.query(self.machine.c.id.label('computers_id'), self.machine.c.name.label('computers_name'),
2963 self.machine.c.entities_id.label('entity_id'))
2964
2965 if int(count) >= 3:
2966 query = query.select_from(self.machine
2967 .join(self.inst_software)
2968 .join(self.softwareversions)
2969 .join(self.software)
2970 .outerjoin(self.manufacturers))
2971 else:
2972 query = query.select_from(self.software
2973 .join(self.softwareversions)
2974 .join(self.inst_software)
2975 .outerjoin(self.manufacturers))
2976
2977 name_filter = [Software.name.like(n) for n in name]
2978 query = query.filter(or_(*name_filter))
2979
2980 if version is not None:
2981 version_filter = [SoftwareVersion.name.like(v) for v in version]
2982 query = query.filter(or_(*version_filter))
2983
2984 if vendor is not None:
2985 vendor_filter = [Manufacturers.name.like(v) for v in vendor]
2986 query = query.filter(or_(*vendor_filter))
2987
2988 if hasattr(ctx, 'locationsid'):
2989 query = query.filter(Software.entities_id.in_(ctx.locationsid))
2990 if int(count) >= 3:
2991 query = query.filter(Machine.is_deleted == 0)
2992 query = query.filter(Machine.is_template == 0)
2993
2994 if int(count) == 1:
2995 return {'count': int(query.scalar())}
2996 elif int(count) == 2:
2997 return query.all()
2998 else:
2999 print query
3000 ret = query.all()
3001 return [{'computer': a[0], 'name': a[1], 'entityid': a[2]} for a in ret]
3002
3003 def getMachineBySoftwareAndVersion(self, ctx, swname, count=0):
3004 # FIXME: the way the web interface process dynamic group sub-query
3005 # is wrong, so for the moment we need this loop:
3006 version = None
3007 if type(swname) == list:
3008 while type(swname[0]) == list:
3009 swname = swname[0]
3010 name = swname[0]
3011 version = swname[1]
3012 return self.getMachineBySoftware(ctx, name, version, count=count)
3013
3014 def getAllHostnames(self, ctx, filt=''):
3015 """
3016 @return: all hostnames defined in the GLPI database
3017 """
3018 session = create_session()
3019 query = session.query(Machine)
3020 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3021 query = self.__filter_on(query)
3022 query = self.__filter_on_entity(query, ctx)
3023 if filter != '':
3024 query = query.filter(self.machine.c.name.like('%' + filt + '%'))
3025 ret = query.all()
3026 session.close()
3027 return ret
3028
3029 def getMachineByHostname(self, ctx, hostname):
3030 """
3031 @return: all machines that have this hostname
3032 """
3033 # TODO use the ctx...
3034 session = create_session()
3035 query = session.query(Machine)
3036 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3037 query = self.__filter_on(query)
3038 query = self.__filter_on_entity(query, ctx)
3039 query = query.filter(self.machine.c.name == hostname)
3040 ret = query.all()
3041 session.close()
3042 return ret
3043
3044 def getAllContacts(self, ctx, filt=''):
3045 """
3046 @return: all hostnames defined in the GLPI database
3047 """
3048 session = create_session()
3049 query = session.query(Machine)
3050 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3051 query = self.__filter_on(query)
3052 query = self.__filter_on_entity(query, ctx)
3053 if filter != '':
3054 query = query.filter(self.machine.c.contact.like('%' + filt + '%'))
3055 ret = query.group_by(self.machine.c.contact).all()
3056 session.close()
3057 return ret
3058
3059 def getMachineByContact(self, ctx, contact):
3060 """
3061 @return: all machines that have this contact
3062 """
3063 # TODO use the ctx...
3064 session = create_session()
3065 query = session.query(Machine)
3066 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3067 query = self.__filter_on(query)
3068 query = self.__filter_on_entity(query, ctx)
3069 query = query.filter(self.machine.c.contact == contact)
3070 ret = query.all()
3071 session.close()
3072 return ret
3073
3074 def getAllContactNums(self, ctx, filt=''):
3075 """
3076 @return: all hostnames defined in the GLPI database
3077 """
3078 session = create_session()
3079 query = session.query(Machine)
3080 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3081 query = self.__filter_on(query)
3082 query = self.__filter_on_entity(query, ctx)
3083 if filter != '':
3084 query = query.filter(self.machine.c.contact_num.like('%' + filt + '%'))
3085 ret = query.group_by(self.machine.c.contact_num).all()
3086 session.close()
3087 return ret
3088
3089 def getMachineByContactNum(self, ctx, contact_num):
3090 """
3091 @return: all machines that have this contact number
3092 """
3093 # TODO use the ctx...
3094 session = create_session()
3095 query = session.query(Machine)
3096 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3097 query = self.__filter_on(query)
3098 query = self.__filter_on_entity(query, ctx)
3099 query = query.filter(self.machine.c.contact_num == contact_num)
3100 ret = query.all()
3101 session.close()
3102 return ret
3103
3104 def getAllComments(self, ctx, filt=''):
3105 """
3106 @return: all hostnames defined in the GLPI database
3107 """
3108 session = create_session()
3109 query = session.query(Machine)
3110 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3111 query = self.__filter_on(query)
3112 query = self.__filter_on_entity(query, ctx)
3113 if filter != '':
3114 query = query.filter(self.machine.c.comment.like('%' + filt + '%'))
3115 ret = query.group_by(self.machine.c.comment).all()
3116 session.close()
3117 return ret
3118
3119 def getMachineByComment(self, ctx, comment):
3120 """
3121 @return: all machines that have this contact number
3122 """
3123 # TODO use the ctx...
3124 session = create_session()
3125 query = session.query(Machine)
3126 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3127 query = self.__filter_on(query)
3128 query = self.__filter_on_entity(query, ctx)
3129 query = query.filter(self.machine.c.comment == comment)
3130 ret = query.all()
3131 session.close()
3132 return ret
3133
3134 def getAllModels(self, ctx, filt=''):
3135 """ @return: all machine models defined in the GLPI database """
3136 session = create_session()
3137 query = session.query(Model).select_from(self.model.join(self.machine))
3138 query = self.__filter_on(query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0))
3139 query = self.__filter_on_entity(query, ctx)
3140 if filter != '':
3141 query = query.filter(self.model.c.name.like('%' + filt + '%'))
3142 ret = query.group_by(self.model.c.name).all()
3143 session.close()
3144 return ret
3145
3146 def getAllManufacturers(self, ctx, filt=''):
3147 """ @return: all machine manufacturers defined in the GLPI database """
3148 session = create_session()
3149 query = session.query(Manufacturers).select_from(self.manufacturers.join(self.machine))
3150 query = self.__filter_on(query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0))
3151 query = self.__filter_on_entity(query, ctx)
3152 if filter != '':
3153 query = query.filter(self.manufacturers.c.name.like('%' + filt + '%'))
3154 ret = query.group_by(self.manufacturers.c.name).all()
3155 session.close()
3156 return ret
3157
3158 @DatabaseHelper._session
3159 def getAllSoftwareVendors(self, session, ctx, filt='', limit=20):
3160 """ @return: all software vendors defined in the GPLI database"""
3161 query = session.query(Manufacturers).select_from(self.manufacturers
3162 .join(self.software))
3163 query = query.filter(Software.is_deleted == 0)
3164 query = query.filter(Software.is_template == 0)
3165 if filt != '':
3166 query = query.filter(Manufacturers.name.like('%' + filt + '%'))
3167 query = query.group_by(Manufacturers.name)
3168 ret = query.order_by(asc(Manufacturers.name)).limit(limit)
3169 return ret
3170
3171 @DatabaseHelper._session
3172 def getAllSoftwareVersions(self, session, ctx, software=None, filt=''):
3173 """ @return: all software versions defined in the GPLI database"""
3174 query = session.query(SoftwareVersion)
3175 query = query.select_from(self.softwareversions
3176 .join(self.software))
3177 if software is not None:
3178 query = query.filter(Software.name.like(software))
3179 if filt != '':
3180 query = query.filter(SoftwareVersion.name.like('%' + filt + '%'))
3181 ret = query.group_by(SoftwareVersion.name).all()
3182 return ret
3183
3184 @DatabaseHelper._session
3185 def getAllRegistries(self, session, ctx, criterion, filt=""):
3186
3187 print "________%s_______" % criterion
3188 print "________%s_______" % filt
3189 print criterion
3190 print filt
3191 #query = session.query(RegContents).filter(RegContents.value.like('%' + filt + '%')).filter_by(key=criterion)
3192 query = session.query(RegContents).filter(RegContents.key.like('%' + criterion + '%')).order_by(RegContents.value)
3193 print "________%s_______" % query
3194 ret = []
3195 for r in query:
3196 ret.append(r.value)
3197 return ret
3198
3199 def getAllStates(self, ctx, filt=''):
3200 """ @return: all machine models defined in the GLPI database """
3201 session = create_session()
3202 query = session.query(State).select_from(self.state.join(self.machine))
3203 query = self.__filter_on(query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0))
3204 query = self.__filter_on_entity(query, ctx)
3205 if filter != '':
3206 query = query.filter(self.state.c.name.like('%' + filt + '%'))
3207 ret = query.group_by(self.state.c.name).all()
3208 session.close()
3209 return ret
3210
3211 def getAllTypes(self, ctx, filt=''):
3212 """ @return: all machine types defined in the GLPI database """
3213 session = create_session()
3214 query = session.query(self.klass['glpi_computertypes']).select_from(self.glpi_computertypes.join(self.machine))
3215 query = self.__filter_on(query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0))
3216 query = self.__filter_on_entity(query, ctx)
3217 if filter != '':
3218 query = query.filter(self.glpi_computertypes.c.name.like('%' + filt + '%'))
3219 ret = query.group_by(self.glpi_computertypes.c.name).all()
3220 session.close()
3221 return ret
3222
3223 def getAllInventoryNumbers(self, ctx, filt=''):
3224 """ @return: all machine inventory numbers defined in the GLPI database """
3225 ret = []
3226 return ret
3227
3228 def getMachineByModel(self, ctx, filt):
3229 """ @return: all machines that have this model """
3230 session = create_session()
3231 query = session.query(Machine).select_from(self.machine.join(self.model))
3232 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3233 query = self.__filter_on(query)
3234 query = self.__filter_on_entity(query, ctx)
3235 query = query.filter(self.model.c.name == filt)
3236 ret = query.all()
3237 session.close()
3238 return ret
3239
3240 @DatabaseHelper._session
3241 def getMachineByType(self, session, ctx, types, count=0):
3242 """ @return: all machines that have this type """
3243 if isinstance(types, basestring):
3244 types = [types]
3245
3246 if int(count) == 1:
3247 query = session.query(func.count(Machine.id)).select_from(self.machine.join(self.glpi_computertypes))
3248 else:
3249 query = session.query(Machine).select_from(self.machine.join(self.glpi_computertypes))
3250 query = query.filter(Machine.is_deleted == 0).filter(Machine.is_template == 0)
3251 query = self.__filter_on(query)
3252 query = self.__filter_on_entity(query, ctx)
3253
3254 type_filter = [self.klass['glpi_computertypes'].name.like(type) for type in types]
3255 query = query.filter(or_(*type_filter))
3256
3257 if int(count) == 1:
3258 ret = int(query.scalar())
3259 else:
3260 ret = query.all()
3261 return ret
3262
3263 def getMachineByInventoryNumber(self, ctx, filt):
3264 """ @return: all machines that have this type """
3265 session = create_session()
3266 query = session.query(Machine).select_from(self.machine)
3267 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3268 query = self.__filter_on(query)
3269 query = self.__filter_on_entity(query, ctx)
3270 query = query.filter(self.machine.c.otherserial == filt)
3271 ret = query.all()
3272 session.close()
3273 return ret
3274
3275 def getMachineByManufacturer(self, ctx, filt):
3276 """ @return: all machines that have this manufacturer """
3277 session = create_session()
3278 query = session.query(Manufacturers).select_from(self.machine.join(self.manufacturers))
3279 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3280 query = self.__filter_on(query)
3281 query = self.__filter_on_entity(query, ctx)
3282 query = query.filter(self.manufacturers.c.name == filt)
3283 ret = query.all()
3284 session.close()
3285 return ret
3286
3287 def getMachineByState(self, ctx, filt, count=0):
3288 """ @return: all machines that have this state """
3289 session = create_session()
3290 if int(count) == 1:
3291 query = session.query(func.count(Machine)).select_from(self.machine.join(self.state))
3292 else:
3293 query = session.query(Machine).select_from(self.machine.join(self.state))
3294 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3295 query = self.__filter_on(query)
3296 query = self.__filter_on_entity(query, ctx)
3297 if '%' in filt:
3298 query = query.filter(self.state.c.name.like(filt))
3299 else:
3300 query = query.filter(self.state.c.name == filt)
3301 if int(count) == 1:
3302 ret = int(query.scalar())
3303 else:
3304 ret = query.all()
3305 session.close()
3306 return ret
3307
3308 def getAllLocations(self, ctx, filt=''):
3309 """ @return: all hostnames defined in the GLPI database """
3310 if not hasattr(ctx, 'locationsid'):
3311 complete_ctx(ctx)
3312 session = create_session()
3313 query = session.query(Locations).select_from(self.locations.join(self.machine))
3314 query = self.__filter_on(query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0))
3315 my_parents_ids = self.getEntitiesParentsAsList(ctx.locationsid)
3316 query = self.__filter_on_entity(query, ctx, my_parents_ids)
3317 query = query.filter(or_(self.locations.c.entities_id.in_(ctx.locationsid),
3318 and_(self.locations.c.is_recursive == 1,
3319 self.locations.c.entities_id.in_(my_parents_ids))))
3320 if filter != '':
3321 query = query.filter(self.locations.c.completename.like('%' + filt + '%'))
3322 ret = query.group_by(self.locations.c.completename).all()
3323 session.close()
3324 return ret
3325
3326 def getMachineByLocation(self, ctx, filt):
3327 """ @return: all machines that have this contact number """
3328 session = create_session()
3329 query = session.query(Machine).select_from(self.machine.join(self.locations))
3330 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3331 query = self.__filter_on(query)
3332 query = self.__filter_on_entity(query, ctx)
3333 query = query.filter(self.locations.c.completename == filt)
3334 ret = query.all()
3335 session.close()
3336 return ret
3337
3338 def getAllOsSps(self, ctx, filt=''):
3339 """ @return: all hostnames defined in the GLPI database """
3340 session = create_session()
3341 query = session.query(OsSp).select_from(self.os_sp.join(self.machine))
3342 query = self.__filter_on(query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0))
3343 query = self.__filter_on_entity(query, ctx)
3344 if filter != '':
3345 query = query.filter(self.os_sp.c.name.like('%' + filt + '%'))
3346 ret = query.group_by(self.os_sp.c.name).all()
3347 session.close()
3348 return ret
3349
3350 def getMachineByOsSp(self, ctx, filt):
3351 """ @return: all machines that have this contact number """
3352 session = create_session()
3353 query = session.query(Machine).select_from(self.machine.join(self.os_sp))
3354 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3355 query = self.__filter_on(query)
3356 query = self.__filter_on_entity(query, ctx)
3357 query = query.filter(self.os_sp.c.name == filt)
3358 ret = query.all()
3359 session.close()
3360 return ret
3361
3362 def getAllGroups(self, ctx, filt=''):
3363 """ @return: all hostnames defined in the GLPI database """
3364 if not hasattr(ctx, 'locationsid'):
3365 complete_ctx(ctx)
3366 session = create_session()
3367 query = session.query(Group).select_from(self.group.join(self.machine))
3368 query = self.__filter_on(query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0))
3369 my_parents_ids = self.getEntitiesParentsAsList(ctx.locationsid)
3370 query = self.__filter_on_entity(query, ctx, my_parents_ids)
3371 query = query.filter(or_(self.group.c.entities_id.in_(ctx.locationsid),
3372 and_(self.group.c.is_recursive == 1, self.group.c.entities_id.in_(my_parents_ids))))
3373 if filter != '':
3374 query = query.filter(self.group.c.name.like('%' + filt + '%'))
3375 ret = query.group_by(self.group.c.name).all()
3376 session.close()
3377 return ret
3378
3379 def getMachineByGroup(self, ctx, filt): # Entity!
3380 """ @return: all machines that have this contact number """
3381 session = create_session()
3382 query = session.query(Machine).select_from(self.machine.join(self.group))
3383 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3384 query = self.__filter_on(query)
3385 query = self.__filter_on_entity(query, ctx)
3386 query = query.filter(self.group.c.entities_id.in_(ctx.locationsid))
3387 query = query.filter(self.group.c.name == filt)
3388 ret = query.all()
3389 session.close()
3390 return ret
3391
3392 def getAllNetworks(self, ctx, filt=''):
3393 """ @return: all hostnames defined in the GLPI database """
3394 session = create_session()
3395 query = session.query(Net).select_from(self.net.join(self.machine))
3396 query = self.__filter_on(query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0))
3397 query = self.__filter_on_entity(query, ctx)
3398 if filter != '':
3399 query = query.filter(self.net.c.name.like('%' + filt + '%'))
3400 ret = query.group_by(self.net.c.name).all()
3401 session.close()
3402 return ret
3403
3404 def getMachineByNetwork(self, ctx, filt):
3405 """ @return: all machines that have this contact number """
3406 session = create_session()
3407 query = session.query(Machine).select_from(self.machine.join(self.net))
3408 query = query.filter(self.machine.c.is_deleted == 0).filter(self.machine.c.is_template == 0)
3409 query = self.__filter_on(query)
3410 query = self.__filter_on_entity(query, ctx)
3411 query = query.filter(self.net.c.name == filt)
3412 ret = query.all()
3413 session.close()
3414 return ret
3415
3416 def getMachineByMacAddress(self, ctx, filt):
3417 """ @return: all computers that have this mac address """
3418 session = create_session()
3419 query = session.query(Machine).join(NetworkPorts, and_(Machine.id == NetworkPorts.items_id,
3420 NetworkPorts.itemtype == 'Computer'))
3421 query = query.filter(Machine.is_deleted == 0).filter(Machine.is_template == 0)
3422 query = query.filter(NetworkPorts.mac == filt)
3423 query = self.__filter_on(query)
3424 if ctx != 'imaging_module':
3425 query = self.__filter_on_entity(query, ctx)
3426 ret = query.all()
3427 session.close()
3428 return ret
3429
3430 @DatabaseHelper._session
3431 def getMachineByHostnameAndMacs(self, session, ctx, hostname, macs):
3432 """
3433 Get machine who match given hostname and at least one of macs
3434
3435 @param ctx: context
3436 @type ctx: dict
3437
3438 @param hostname: hostname of wanted machine
3439 @type hostname: str
3440
3441 @param macs: list of macs
3442 @type macs: list
3443
3444 @return: UUID of wanted machine or False
3445 @rtype: str or None
3446 """
3447 query = session.query(Machine).join(NetworkPorts, and_(Machine.id == NetworkPorts.items_id,
3448 NetworkPorts.itemtype == 'Computer'))
3449 query = query.filter(Machine.is_deleted == 0).filter(Machine.is_template == 0)
3450 query = query.filter(NetworkPorts.mac.in_(macs))
3451 query = query.filter(self.machine.c.name == hostname)
3452 query = self.__filter_on(query)
3453 if ctx != 'imaging_module':
3454 query = self.__filter_on_entity(query, ctx)
3455 try:
3456 ret = query.one()
3457 except (MultipleResultsFound, NoResultFound) as e:
3458 self.logger.warn('I can\'t get any UUID for machine %s and macs %s: %s' % (hostname, macs, e))
3459 return None
3460 return toUUID(ret.id)
3461
3462 def getComputersOS(self, uuids):
3463 if isinstance(uuids, str):
3464 uuids = [uuids]
3465 session = create_session()
3466 query = session.query(Machine) \
3467 .add_column(self.os.c.name) \
3468 .select_from(self.machine.join(self.os))
3469 query = query.filter(self.machine.c.id.in_([fromUUID(uuid) for uuid in uuids]))
3470 session.close()
3471 res = []
3472 for machine, OSName in query:
3473 res.append({
3474 'uuid': toUUID(machine.id),
3475 'OSName': OSName,
3476 })
3477 return res
3478
3479 def getComputersCountByOS(self, osname):
3480 session = create_session()
3481 query = session.query(func.count(Machine.id)) \
3482 .select_from(self.machine.join(self.os))
3483 query = query.filter(self.os.c.name.like('%' + osname + '%'))
3484 count = query.scalar()
3485 session.close()
3486 return count
3487
3488 def getMachineUUIDByMacAddress(self, mac):
3489 """
3490 Return a machine's UUID by MAC address.
3491 @param mac: MAC address of machine
3492 @type mac: str
3493
3494 @return: machine UUID
3495 @rtype: str
3496 """
3497 ret = self.getMachineByMacAddress('imaging_module', mac)
3498 if type(ret) == list:
3499 if len(ret) != 0:
3500 return str(toUUID(ret[0].id))
3501 return None
3502
3503 ##################### for msc
3504 def getMachinesNetwork(self, uuids):
3505 """
3506 Get for each machine a list of its networkports
3507
3508 return {
3509 computer_uuid1: {
3510 'domain': 'xxx',
3511 'gateway': 'xxx',
3512 'ifaddr': 'xxx',
3513 'ifmac': 'xxx',
3514 'name': 'xxx',
3515 'netmask': 'xxx',
3516 'subnet': 'xxx',
3517 'uuid': 'xxx', <= UUID of networkport
3518 },
3519 computer_uuid2: {},
3520 etc.,
3521 }
3522 """
3523
3524 def getComputerNetwork(machine, domain):
3525 result = []
3526 for networkport in machine.networkports:
3527 if networkport.networknames is not None:
3528 if networkport.networknames.ipaddresses:
3529 # If there is multiple adresses per interface, we
3530 # create the same number of interfaces
3531 for ipaddress in networkport.networknames.ipaddresses:
3532 d = {
3533 'uuid': toUUID(networkport.id),
3534 'domain': domain,
3535 'ifmac': networkport.mac,
3536 'name': networkport.name,
3537 'netmask': '',
3538 'subnet': '',
3539 'gateway': '',
3540 'ifaddr': '',
3541 }
3542
3543 # IP Address
3544 d['ifaddr'] = ipaddress.name
3545
3546 # Init old iface dict
3547 z = {}
3548
3549 for ipnetwork in ipaddress.ipnetworks:
3550 oz = z
3551
3552 z = d.copy()
3553 z['netmask'] = ipnetwork.netmask
3554 z['gateway'] = ipnetwork.gateway
3555 z['subnet'] = ipnetwork.address
3556
3557 # Add this (network/ip/interface) to result
3558 # and if its not duplicated
3559 if z != oz:
3560 result.append(z)
3561 if not ipaddress.ipnetworks:
3562 result.append(d)
3563 return result
3564
3565 session = create_session()
3566 query = self.filterOnUUID(session.query(Machine), uuids)
3567 ret = {}
3568 for machine in query:
3569 uuid = toUUID(machine.id)
3570 domain = ''
3571 if machine.domains is not None:
3572 domain = machine.domains.name
3573 ret[uuid] = getComputerNetwork(machine, domain)
3574 session.close()
3575 return ret
3576
3577 def getMachineNetwork(self, uuid):
3578 """
3579 Get a machine network
3580 @see getMachinesNetwork()
3581 """
3582 return self.getMachinesNetwork(uuid)[uuid]
3583
3584 def getMachinesMac(self, uuids):
3585 """
3586 Get several machines mac addresses
3587 """
3588 session = create_session()
3589 query = self.filterOnUUID(session.query(Machine), uuids)
3590 ret = {}
3591 for machine in query:
3592 cuuid = toUUID(machine.id)
3593 ret[cuuid] = [networkport.mac for networkport in machine.networkports]
3594 return ret
3595
3596 def getMachineMac(self, uuid):
3597 """
3598 Get a machine mac addresses
3599 """
3600 return self.getMachinesMac(uuid)[uuid]
3601
3602 def orderIpAdresses(self, uuid, hostname, netiface, empty_macs=False):
3603 ret_ifmac = []
3604 ret_ifaddr = []
3605 ret_netmask = []
3606 ret_domain = []
3607 ret_networkUuids = []
3608 idx_good = 0
3609 failure = [True, True]
3610 for iface in netiface:
3611 if not empty_macs:
3612 if not ('ifmac' in iface or iface['ifmac']):
3613 continue
3614 if 'ifaddr' in iface and iface['ifaddr']:
3615 if iface['gateway'] == None:
3616 ret_ifmac.append(iface['ifmac'])
3617 ret_ifaddr.append(iface['ifaddr'])
3618 ret_netmask.append(iface['netmask'])
3619 ret_networkUuids.append(iface['uuid'])
3620 if 'domain' in iface:
3621 ret_domain.append(iface['domain'])
3622 else:
3623 ret_domain.append('')
3624 else:
3625 if same_network(iface['ifaddr'], iface['gateway'], iface['netmask']):
3626 idx_good += 1
3627 ret_ifmac.insert(0, iface['ifmac'])
3628 ret_ifaddr.insert(0, iface['ifaddr'])
3629 ret_netmask.insert(0, iface['netmask'])
3630 ret_networkUuids.insert(0, iface['uuid'])
3631 if 'domain' in iface:
3632 ret_domain.insert(0, iface['domain'])
3633 else:
3634 ret_domain.insert(0, '')
3635 failure[0] = False
3636 else:
3637 ret_ifmac.insert(idx_good, iface['ifmac'])
3638 ret_ifaddr.insert(idx_good, iface['ifaddr'])
3639 ret_netmask.insert(idx_good, iface['netmask'])
3640 ret_networkUuids.insert(idx_good, iface['uuid'])
3641 if 'domain' in iface:
3642 ret_domain.insert(idx_good, iface['domain'])
3643 else:
3644 ret_domain.insert(idx_good, '')
3645 failure[1] = False
3646
3647 return (ret_ifmac, ret_ifaddr, ret_netmask, ret_domain, ret_networkUuids)
3648
3649 def dict2obj(d):
3650 """
3651 Get a dictionnary and return an object
3652 """
3653 from collections import namedtuple
3654 o = namedtuple('dict2obj', ' '.join(d.keys()))
3655 return o(**d)
3656
3657 def getMachineIp(self, uuid):
3658 """
3659 Get a machine ip addresses
3660 """
3661 machine_network = self.getMachineNetwork(uuid)
3662 ret_gw = []
3663 ret_nogw = []
3664 for m in machine_network:
3665 m = self.dict2obj(m)
3666 if same_network(m.ifaddr, m.gateway, m.netmask):
3667 ret_gw.append(m.ifaddr)
3668 else:
3669 ret_nogw.append(m.ifaddr)
3670 ret_gw = unique(ret_gw)
3671 ret_gw.extend(unique(ret_nogw))
3672
3673 return ret_gw
3674
3675 def getMachineListByState(self, ctx, groupName):
3676 """
3677 """
3678
3679 # Read config from ini file
3680 orange = self.config.orange
3681 red = self.config.red
3682
3683 complete_ctx(ctx)
3684 filt = {'ctxlocation': ctx.locations}
3685
3686 session = create_session()
3687 now = datetime.datetime.now()
3688 orange = now - datetime.timedelta(orange)
3689 red = now - datetime.timedelta(red)
3690
3691 date_mod = self.machine.c.date_mod
3692 if self.fusionagents is not None:
3693 date_mod = FusionAgents.last_contact
3694
3695 query = self.__getRestrictedComputersListQuery(ctx, filt, session)
3696
3697 # Limit list according to max_elements_for_static_list param in dyngroup.ini
3698 limit = DGConfig().maxElementsForStaticList
3699
3700 if groupName == "green":
3701 result = query.filter(date_mod > orange).limit(limit)
3702 elif groupName == "orange":
3703 result = query.filter(and_(date_mod < orange, date_mod > red)).limit(limit)
3704 elif groupName == "red":
3705 result = query.filter(date_mod < red).limit(limit)
3706
3707 ret = {}
3708 for machine in result.all():
3709 if machine.name is not None:
3710 ret[toUUID(machine.id) + '##' + machine.name] = {"hostname": machine.name, "uuid": toUUID(machine.id)}
3711
3712 session.close()
3713 return ret
3714
3715 def getMachineNumberByState(self, ctx):
3716 """
3717 return number of machines sorted by state
3718 default states are:
3719 * green: less than 10 days
3720 * orange: more than 10 days and less than 35 days
3721 * red: more than 35 days
3722
3723 @return: dictionnary with state as key, number as value
3724 @rtype: dict
3725 """
3726
3727 # Read config from ini file
3728 orange = self.config.orange
3729 red = self.config.red
3730
3731 complete_ctx(ctx)
3732 filt = {'ctxlocation': ctx.locations}
3733
3734 ret = {
3735 "days": {
3736 "orange": orange,
3737 "red": red,
3738 },
3739 "count": self.getRestrictedComputersListStatesLen(ctx, filt, orange, red),
3740 }
3741
3742 return ret
3743
3744 def getAntivirusStatus(self, ctx):
3745 """
3746 Return number of machine by antivirus status:
3747 * green: Antivirus OK
3748 * orange: Antivirus not running or not up-to-date
3749 * red: No antivirus or unknown status
3750 """
3751 session = create_session()
3752
3753 __computersListQ = self.__getRestrictedComputersListQuery
3754
3755 complete_ctx(ctx)
3756 filt = {
3757 'ctxlocation': ctx.locations
3758 }
3759
3760 ret = {
3761 'green': int(__computersListQ(ctx, dict(filt, **{'antivirus': 'green'}), session, count=True)),
3762 'orange': int(__computersListQ(ctx, dict(filt, **{'antivirus': 'orange'}), session, count=True)),
3763 'red': int(__computersListQ(ctx, dict(filt, **{'antivirus': 'red'}), session, count=True)),
3764 }
3765
3766 session.close()
3767
3768 return ret
3769
3770 def getMachineIdsNotInAntivirusRed(self, ctx):
3771 """
3772 return ids list of machines who are not in antivirus red status
3773 """
3774 session = create_session()
3775 __computersListQ = self.__getRestrictedComputersListQuery
3776
3777 complete_ctx(ctx)
3778
3779 filt = {
3780 'ctxlocation': ctx.locations
3781 }
3782
3783 query1 = __computersListQ(ctx, dict(filt, **{'antivirus': 'green'}), session)
3784 query2 = __computersListQ(ctx, dict(filt, **{'antivirus': 'orange'}), session)
3785
3786 session.close()
3787
3788 return [machine.id for machine in query1.all()] + [machine.id for machine in query2.all()]
3789
3790 def getMachineListByAntivirusState(self, ctx, groupName):
3791 session = create_session()
3792
3793 __computersListQ = self.__getRestrictedComputersListQuery
3794
3795 complete_ctx(ctx)
3796 filt = {
3797 'ctxlocation': ctx.locations
3798 }
3799 query = __computersListQ(ctx, dict(filt, **{'antivirus': groupName}), session)
3800
3801 # Limit list according to max_elements_for_static_list param in dyngroup.ini
3802 limit = DGConfig().maxElementsForStaticList
3803
3804 query = query.limit(limit)
3805
3806 ret = {}
3807 for machine in query.all():
3808 if machine.name is not None:
3809 ret[toUUID(machine.id) + '##' + machine.name] = {"hostname": machine.name, "uuid": toUUID(machine.id)}
3810
3811 session.close()
3812 return ret
3813
3814 def getIpFromMac(self, mac):
3815 """
3816 Get an ip address when a mac address is given
3817 """
3818 session = create_session()
3819 query = session.query(NetworkPorts).filter(NetworkPorts.mac == mac)
3820 # Get first IP address found
3821 ret = query.first().networknames.ipaddresses[0]
3822 session.close()
3823 return ret
3824
3825 def getIpFromMachine(self, uuid):
3826 """
3827 Same as getMachineIp
3828 TODO: check where it is used
3829 """
3830 return self.getMachineIp(uuid)
3831
3832 def getMachineDomain(self, uuid):
3833 """
3834 Get a machine domain name
3835 """
3836 session = create_session()
3837 machine = self.filterOnUUID(session.query(Machine), uuid).first()
3838 domain = ''
3839 if machine.domains is not None:
3840 domain = machine.domains.name
3841 return domain
3842
3843 def isComputerNameAvailable(self, ctx, locationUUID, name):
3844 raise Exception("need to be implemented when we would be able to add computers")
3845
3846 def _killsession(self, sessionwebservice):
3847 """
3848 Destroy a session identified by a session token.
3849
3850 @param sessionwebservice: session var provided by initSession endpoint.
3851 @type sessionwebservice: str
3852
3853 """
3854 headers = {'content-type': 'application/json',
3855 'Session-Token': sessionwebservice
3856 }
3857 url = GlpiConfig.webservices['glpi_base_url'] + "killSession"
3858 r = requests.get(url, headers=headers)
3859 if r.status_code == 200:
3860 self.logger.debug("Kill session REST: %s" % sessionwebservice)
3861
3862 def delMachine(self, uuid):
3863 """
3864 Deleting a machine in GLPI (only the flag 'is_deleted' updated)
3865
3866 @param uuid: UUID of machine
3867 @type uuid: str
3868
3869 @return: True if the machine successfully deleted
3870 @rtype: bool
3871 """
3872 authtoken = base64.b64encode(
3873 GlpiConfig.webservices['glpi_username'] + ":" + GlpiConfig.webservices['glpi_password'])
3874 headers = {'content-type': 'application/json',
3875 'Authorization': "Basic " + authtoken
3876 }
3877 url = GlpiConfig.webservices['glpi_base_url'] + "initSession"
3878 self.logger.debug("Create session REST")
3879 r = requests.get(url, headers=headers)
3880 if r.status_code == 200:
3881 sessionwebservice = str(json.loads(r.text)['session_token'])
3882 self.logger.debug("session %s" % sessionwebservice)
3883 url = GlpiConfig.webservices['glpi_base_url'] + "Computer/" + str(fromUUID(uuid))
3884 headers = {'content-type': 'application/json',
3885 'Session-Token': sessionwebservice
3886 }
3887 parameters = {'force_purge': '1'}
3888 r = requests.delete(url, headers=headers, params=parameters)
3889 if r.status_code == 200:
3890 self.logger.debug("Machine %s deleted" % str(fromUUID(uuid)))
3891 self._killsession(sessionwebservice)
3892 return True
3893 self._killsession(sessionwebservice)
3894 return False
3895
3896 @DatabaseHelper._session
3897 def addUser(self, session, username, password, entity_rights=None):
3898 # Check if the user exits or not
3899 try:
3900 user = session.query(User).filter_by(name=username).one()
3901 except NoResultFound:
3902 user = User()
3903 user.name = username
3904 user.password = hashlib.sha1(password).hexdigest()
3905 user.firstname = ''
3906 user.realname = ''
3907 user.auths_id = 0
3908 user.is_deleted = 0
3909 user.is_active = 1
3910 session.add(user)
3911 session.commit()
3912 session.flush()
3913
3914 # Setting entity rights
3915 if entity_rights is not None:
3916 self.setLocationsForUser(username, entity_rights)
3917 return True
3918
3919 @DatabaseHelper._session
3920 def setUserPassword(self, session, username, password):
3921 try:
3922 user = session.query(User).filter_by(name=username).one()
3923 except NoResultFound:
3924 self.addUser(username, password)
3925 return
3926 user.password = hashlib.sha1(password).hexdigest()
3927 session.commit()
3928 session.flush()
3929
3930 def removeUser(self, session, username):
3931 # Too complicated, affects many tables
3932 return True
3933
3934 @DatabaseHelper._session
3935 def addEntity(self, session, entity_name, parent_id, comment):
3936 entity = Entities()
3937 entity.id = session.query(func.max(Entities.id)).scalar() + 1
3938 entity.entities_id = parent_id # parent
3939 entity.name = entity_name
3940 entity.comment = comment
3941 # Get parent entity object
3942 parent_entity = session.query(Entities).filter_by(id=parent_id, ).one()
3943 completename = parent_entity.completename + ' > ' + entity_name
3944 entity.completename = completename
3945 entity.level = parent_entity.level + 1
3946 session.add(entity)
3947 session.commit()
3948 session.flush()
3949 return True
3950
3951 @DatabaseHelper._session
3952 def editEntity(self, session, id, entity_name, parent_id, comment):
3953 entity = session.query(Entities).filter_by(id=id).one()
3954 entity.entities_id = parent_id # parent
3955 entity.name = entity_name
3956 entity.comment = comment
3957 # entity.level = parent_id
3958 entity = self.updateEntityCompleteName(entity)
3959 session.commit()
3960 session.flush()
3961 return True
3962
3963 @DatabaseHelper._session
3964 def updateEntityCompleteName(self, session, entity):
3965 # Get parent entity object
3966 parent_entity = session.query(Entities).filter_by(id=entity.entities_id).one()
3967 completename = parent_entity.completename + ' > ' + entity.name
3968 entity.completename = completename
3969 entity.level = parent_entity.level + 1
3970 # Update all children complete names
3971 children = session.query(Entities).filter_by(entities_id=entity.id).all()
3972 for item in children:
3973 self.updateEntityCompleteName(item)
3974 return entity
3975
3976 def removeEntity(self, entity_id):
3977 # Too complicated, affects many tables
3978 pass
3979
3980 @DatabaseHelper._listinfo
3981 @DatabaseHelper._session
3982 def getAllEntitiesPowered(self, session, params):
3983 return session.query(Entities).order_by(Entities.completename)
3984
3985 @DatabaseHelper._session
3986 def addLocation(self, session, name, parent_id, comment):
3987 location = Locations()
3988 location.entities_id = 0 # entity is root
3989 location.name = name
3990 location.locations_id = parent_id
3991
3992 location.comment = comment
3993 location.level = parent_id
3994 location.building = ''
3995 location.room = ''
3996
3997 # Get parent location object
3998 parent_location = session.query(Locations).filter_by(id=parent_id, ).one()
3999 completename = parent_location.completename + ' > ' + name
4000 location.completename = completename
4001
4002 session.add(location)
4003 session.commit()
4004 session.flush()
4005 return True
4006
4007 @DatabaseHelper._session
4008 def editLocation(self, session, id, name, parent_id, comment):
4009 location = session.query(Locations).filter_by(id=id).one()
4010 location.locations_id = parent_id # parent
4011 location.name = name
4012 location.comment = comment
4013 location.level = parent_id
4014
4015 location = self.updateLocationCompleteName(location)
4016
4017 session.commit()
4018 session.flush()
4019 return True
4020
4021 @DatabaseHelper._session
4022 def updateLocationCompleteName(self, session, location):
4023 # Get parent location object
4024 parent_location = session.query(Locations).filter_by(id=location.locations_id).one()
4025 completename = parent_location.completename + ' > ' + location.name
4026 location.completename = completename
4027
4028 # Update all children complete names
4029 children = session.query(Locations).filter_by(locations_id=location.id).all()
4030
4031 for item in children:
4032 self.updateLocationCompleteName(item)
4033
4034 return location
4035
4036 @DatabaseHelper._listinfo
4037 @DatabaseHelper._session
4038 def getAllLocationsPowered(self, session, params):
4039 return session.query(Locations).order_by(Locations.completename)
4040
4041 @DatabaseHelper._listinfo
4042 @DatabaseHelper._session
4043 def getAllEntityRules(self, session, params):
4044 # TODO: Filter this by user context entities
4045 return session.query(self.rules).filter_by(sub_type='PluginFusioninventoryInventoryRuleEntity') \
4046 .filter(self.rules.c.name != 'Root') \
4047 .order_by(self.rules.c.ranking)
4048
4049 @DatabaseHelper._session
4050 def addEntityRule(self, session, rule_data):
4051 rule = Rule()
4052 # root entity (this means that rule is appliable on root entity and all subentities)
4053 rule.entities_id = 0
4054 rule.sub_type = 'PluginFusioninventoryInventoryRuleEntity'
4055 # Get the last ranking for this class +1
4056 rank = session.query(func.max(self.rules.c.ranking)) \
4057 .filter(self.rules.c.sub_type == 'PluginFusioninventoryInventoryRuleEntity') \
4058 .filter(self.rules.c.name != 'Root') \
4059 .scalar()
4060 if rank is None:
4061 rank = 0
4062 rule.ranking = rank + 1
4063 rule.name = rule_data['name']
4064 rule.description = rule_data['description']
4065 rule.match = rule_data['aggregator']
4066 if rule_data['active'] == 'on':
4067 rule.is_active = 1
4068 else:
4069 rule.is_active = 0
4070
4071 session.add(rule)
4072 session.commit()
4073 session.flush()
4074
4075 # Make sure "Root" entity rule ranking is very high
4076 session.query(Rule).filter_by(sub_type='PluginFusioninventoryInventoryRuleEntity', \
4077 name='Root').update({'ranking': rule.ranking + 1}, synchronize_session=False)
4078
4079 # Adding rule criteria
4080
4081 for i in xrange(len(rule_data['criteria'])):
4082 cr = RuleCriterion()
4083 cr.rules_id = rule.id
4084 cr.criteria = rule_data['criteria'][i]
4085 cr.condition = rule_data['operators'][i]
4086 cr.pattern = rule_data['patterns'][i]
4087 session.add(cr)
4088 session.commit()
4089
4090 # Adding rule actions
4091
4092 # If a target entity is specified, add it
4093 if rule_data['target_entity'] != '-1':
4094 action = RuleAction()
4095 action.rules_id = rule.id
4096 action.action_type = 'assign'
4097 action.field = 'entities_id'
4098 action.value = rule_data['target_entity']
4099 session.add(action)
4100
4101 # If a target location is specified, add it
4102 if rule_data['target_location'] != '-1':
4103 action = RuleAction()
4104 action.rules_id = rule.id
4105 action.action_type = 'assign'
4106 action.field = 'locations_id'
4107 action.value = rule_data['target_location']
4108 session.add(action)
4109
4110 session.commit()
4111 return True
4112
4113
4114 # it s shit do it from dict directly
4115 # {'ranking' : 2, 'sub_type': 'PluginFusioninventoryInventoryRuleEntity',
4116 # date_mod: NOW(),
4117
4118 # criteria
4119 # {'criteria': 'ip', // 'name' => hostanme, 'domain', 'serial', 'subnet', 'tag',
4120 # 'condition': 0=is, 1=is_not, 2=contains, 3=doesnt contain, 4=start with, 5= finishes by
4121 # 6=regex_check, 7=not_regex, 8=exists, 9=doesnt eixts
4122 # 'pattern' : 192.168.44.,
4123 # 'rules_id' : rule_id
4124
4125 # rule actions
4126 # { 'rules_id', rid
4127 # action_type = assign,
4128 # field = entities_id
4129 # value = ENTITY_ID
4130 #
4131 # action_type=regex_result,field=_affect_entity_by_tag, value=?
4132 # action_type=assign, field=locations_id, value=id
4133
4134 @DatabaseHelper._session
4135 def moveEntityRuleUp(self, session, id):
4136
4137 rule = session.query(Rule).filter_by(id=id).one()
4138 # get previous rule
4139 previous = session.query(Rule).filter(Rule.ranking < rule.ranking) \
4140 .filter(Rule.name != 'Root') \
4141 .filter(Rule.sub_type == 'PluginFusioninventoryInventoryRuleEntity') \
4142 .order_by(Rule.ranking.desc()).first()
4143 if previous:
4144 previous_ranking = previous.ranking
4145 rule_ranking = rule.ranking
4146 previous.ranking = rule_ranking
4147 session.commit()
4148 rule.ranking = previous_ranking
4149 session.commit()
4150
4151 return True
4152
4153 @DatabaseHelper._session
4154 def moveEntityRuleDown(self, session, id):
4155
4156 rule = session.query(Rule).filter_by(id=id).one()
4157 # get next rule
4158 next_ = session.query(Rule).filter(Rule.ranking > rule.ranking) \
4159 .filter(Rule.name != 'Root') \
4160 .filter(Rule.sub_type == 'PluginFusioninventoryInventoryRuleEntity') \
4161 .order_by(Rule.ranking.asc()).first()
4162 if next_:
4163 next_ranking = next_.ranking
4164 rule_ranking = rule.ranking
4165 next_.ranking = rule_ranking
4166 session.commit()
4167 rule.ranking = next_ranking
4168 session.commit()
4169
4170 return True
4171
4172 @DatabaseHelper._session
4173 def editEntityRule(self, session, id, rule_data):
4174
4175 rule = session.query(Rule).filter_by(id=id).one()
4176 # Delete associated criteria and actions
4177 session.query(RuleCriterion).filter_by(rules_id=id).delete()
4178 session.query(RuleAction).filter_by(rules_id=id).delete()
4179
4180 rule.name = rule_data['name']
4181 rule.description = rule_data['description']
4182 rule.match = rule_data['aggregator']
4183 if rule_data['active'] == 'on':
4184 rule.is_active = 1
4185 else:
4186 rule.is_active = 0
4187
4188 session.commit()
4189 session.flush()
4190
4191 # Adding rule criteria
4192
4193 for i in xrange(len(rule_data['criteria'])):
4194 cr = RuleCriterion()
4195 cr.rules_id = rule.id
4196 cr.criteria = rule_data['criteria'][i]
4197 cr.condition = rule_data['operators'][i]
4198 cr.pattern = rule_data['patterns'][i]
4199 session.add(cr)
4200 session.commit()
4201
4202 # Adding rule actions
4203
4204 # If a target entity is specified, add it
4205 if rule_data['target_entity'] != '-1':
4206 action = RuleAction()
4207 action.rules_id = rule.id
4208 action.action_type = 'assign'
4209 action.field = 'entities_id'
4210 action.value = rule_data['target_entity']
4211 session.add(action)
4212
4213 # If a target location is specified, add it
4214 if rule_data['target_location'] != '-1':
4215 action = RuleAction()
4216 action.rules_id = rule.id
4217 action.action_type = 'assign'
4218 action.field = 'locations_id'
4219 action.value = rule_data['target_location']
4220 session.add(action)
4221
4222 session.commit()
4223 return True
4224
4225 @DatabaseHelper._session
4226 def getEntityRule(self, session, id):
4227
4228 rule = session.query(Rule).filter_by(id=id).one()
4229 criteria = session.query(RuleCriterion).filter_by(rules_id=id).all()
4230 actions = session.query(RuleAction).filter_by(rules_id=id).all()
4231
4232 result = {}
4233 result['active'] = rule.is_active
4234 result['name'] = rule.name
4235 result['description'] = rule.description
4236 result['aggregator'] = rule.match
4237
4238 result['criteria'] = []
4239 result['operators'] = []
4240 result['patterns'] = []
4241
4242 for cr in criteria:
4243 result['criteria'].append(cr.criteria)
4244 result['operators'].append(cr.condition)
4245 result['patterns'].append(cr.pattern)
4246
4247 # By default, don't assign entity nor location
4248 result['target_entity'] = -1
4249 result['target_location'] = -1
4250
4251 for action in actions:
4252 if action.field == 'entities_id' and action.action_type == 'assign':
4253 result['target_entity'] = action.value
4254 if action.field == 'locations_id' and action.action_type == 'assign':
4255 result['target_entity'] = action.value
4256
4257 return result
4258
4259 @DatabaseHelper._session
4260 def deleteEntityRule(self, session, id):
4261
4262 # Delete rule
4263 session.query(Rule).filter_by(id=id).delete()
4264 # Delete associated criteria and actions
4265 session.query(RuleCriterion).filter_by(rules_id=id).delete()
4266 session.query(RuleAction).filter_by(rules_id=id).delete()
4267 return True
4268
4269 def moveComputerToEntity(self, uuid, entity_id):
4270 pass
4271 # UPDATE `glpi_computers`
4272 # SET `entities_id` = '5' WHERE `id` ='3'
4273
4274 @DatabaseHelper._session
4275 def getLocationsForUser(self, session, username):
4276 try:
4277 user_id = session.query(User).filter_by(name=username).one().id
4278 except NoResultFound:
4279 return []
4280 entities = []
4281 for profile in session.query(UserProfile).filter_by(users_id=user_id):
4282 entities += [{
4283 'entity_id': profile.entities_id,
4284 'profile': profile.profiles_id,
4285 'is_recursive': profile.is_recursive,
4286 'is_dynamic': profile.is_dynamic
4287 }]
4288 return entities
4289
4290 @DatabaseHelper._session
4291 def setLocationsForUser(self, session, username, profiles):
4292
4293 user_id = session.query(User).filter_by(name=username).one().id
4294 # Delete all user entity profiles
4295 session.query(UserProfile).filter_by(users_id=user_id).delete()
4296
4297 for attr in profiles:
4298 p = UserProfile()
4299 p.users_id = user_id
4300 p.profiles_id = attr['profile']
4301 p.entities_id = attr['entity_id']
4302 p.is_recursive = attr['is_recursive']
4303 p.is_dynamic = attr['is_dynamic']
4304 session.add(p)
4305 session.commit()
4306
4307 session.flush()
4308 return True
4309
4310 @DatabaseHelper._session
4311 def getAllRegistryCollect(self, session,filter=''):
4312
4313 query = session.query(Registries).all()
4314 if filter == 'key' :
4315 ret = [x.key for x in query]
4316 else:
4317 ret = [[x.key, " key %s from Register Base" % x.name] for x in query]
4318 return ret
4319
4320# Class for SQLalchemy mapping
4321class Machine(object):
4322 __tablename__ = 'glpi_computers'
4323
4324 def getUUID(self):
4325 return toUUID(self.id)
4326
4327 def toH(self):
4328 return {'hostname': self.name, 'uuid': toUUID(self.id)}
4329
4330 def to_a(self):
4331 owner_login, owner_firstname, owner_realname = Glpi91().getMachineOwner(self)
4332 return [
4333 ['name', self.name],
4334 ['comments', self.comment],
4335 ['serial', self.serial],
4336 ['otherserial', self.otherserial],
4337 ['contact', self.contact],
4338 ['contact_num', self.contact_num],
4339 ['owner', owner_login],
4340 ['owner_firstname', owner_firstname],
4341 ['owner_realname', owner_realname],
4342 # ['tech_num',self.tech_num],
4343 ['os', self.operatingsystems_id],
4344 ['os_version', self.operatingsystemversions_id],
4345 ['os_sp', self.operatingsystemservicepacks_id],
4346 ['os_license_number', self.os_license_number],
4347 ['os_license_id', self.os_licenseid],
4348 ['location', self.locations_id],
4349 ['domain', self.domains_id],
4350 ['network', self.networks_id],
4351 ['model', self.computermodels_id],
4352 ['type', self.computertypes_id],
4353 ['entity', self.entities_id],
4354 ['uuid', Glpi91().getMachineUUID(self)]
4355 ]
4356
4357
4358class Entities(object):
4359 def toH(self):
4360 return {
4361 'uuid': toUUID(self.id),
4362 'name': self.name,
4363 'completename': self.completename,
4364 'comments': self.comment,
4365 'level': self.level
4366 }
4367
4368
4369class State(object):
4370 pass
4371
4372
4373class DiskFs(object):
4374 pass
4375
4376
4377class FusionAntivirus(object):
4378 pass
4379
4380
4381class FusionLocks(object):
4382 pass
4383
4384
4385class FusionAgents(object):
4386 to_be_exported = ['last_contact']
4387
4388
4389class Disk(object):
4390 pass
4391
4392
4393class Suppliers(object):
4394 pass
4395
4396
4397class Infocoms(object):
4398 pass
4399
4400
4401class Processor(object):
4402 pass
4403
4404
4405class ComputerProcessor(object):
4406 pass
4407
4408
4409class Memory(object):
4410 pass
4411
4412
4413class MemoryType(object):
4414 pass
4415
4416
4417class ComputerMemory(object):
4418 pass
4419
4420
4421class Logs(object):
4422 pass
4423
4424
4425class User(object):
4426 pass
4427
4428
4429class Profile(object):
4430 pass
4431
4432
4433class UserProfile(object):
4434 pass
4435
4436
4437class NetworkPorts(object):
4438 def toH(self):
4439 return {
4440 'uuid': toUUID(self.id),
4441 'name': self.name,
4442 'ifaddr': self.ip,
4443 'ifmac': self.mac,
4444 'netmask': noNone(self.netmask),
4445 'gateway': self.gateway,
4446 'subnet': self.subnet
4447 }
4448
4449
4450class OS(object):
4451 pass
4452
4453
4454class ComputerDevice(object):
4455 pass
4456
4457
4458class Domain(object):
4459 pass
4460
4461
4462class Manufacturers(object):
4463 pass
4464
4465
4466class Software(object):
4467 pass
4468
4469
4470class InstSoftware(object):
4471 pass
4472
4473
4474class Licenses(object):
4475 pass
4476
4477
4478class SoftwareVersion(object):
4479 pass
4480
4481
4482class Group(object):
4483 pass
4484
4485
4486class OsSp(object):
4487 pass
4488
4489
4490class Model(object):
4491 pass
4492
4493
4494class Locations(object):
4495 pass
4496
4497
4498class Net(object):
4499 pass
4500
4501
4502class NetworkInterfaces(object):
4503 pass
4504
4505
4506class IPAddresses(object):
4507 pass
4508
4509
4510class IPNetworks(object):
4511 pass
4512
4513
4514class NetworkNames(object):
4515 pass
4516
4517
4518class IPAddresses_IPNetworks(object):
4519 pass
4520
4521
4522class Collects(object):
4523 pass
4524
4525
4526class Rule(DbTOA):
4527 pass
4528
4529
4530class RuleCriterion(DbTOA):
4531 pass
4532
4533
4534class RuleAction(DbTOA):
4535 pass
4536
4537
4538class Registries(object):
4539 pass
4540
4541
4542class RegContents(object):
4543 pass