Guest User

Untitled

a guest
Apr 6th, 2017
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 180.65 KB | None | 0 0
  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. """
  24. This module declare all the necessary stuff to connect to a glpi database in it's
  25. version 9.1
  26. """
  27. import os
  28. import logging
  29. import re
  30. from sets import Set
  31. import datetime
  32. import calendar, hashlib
  33. import time
  34. from configobj import ConfigObj
  35. from xmlrpclib import ProtocolError
  36.  
  37. from sqlalchemy import and_, create_engine, MetaData, Table, Column, String, \
  38.     Integer, Date, ForeignKey, asc, or_, not_, desc, func, distinct
  39. from sqlalchemy.orm import create_session, mapper, relationship
  40.  
  41. try:
  42.     from sqlalchemy.sql.expression import ColumnOperators
  43. except ImportError:
  44.     from sqlalchemy.sql.operators import ColumnOperators
  45. from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
  46. from sqlalchemy.exc import OperationalError
  47. from mmc.support.mmctools import shlaunch
  48. import base64
  49. import json
  50. import requests
  51. from mmc.site import mmcconfdir
  52. from mmc.database.database_helper import DatabaseHelper
  53. # TODO rename location into entity (and locations in location)
  54. from pulse2.utils import same_network, unique, noNone
  55. from pulse2.database.dyngroup.dyngroup_database_helper import DyngroupDatabaseHelper
  56. from pulse2.managers.group import ComputerGroupManager
  57. from mmc.plugins.glpi.config import GlpiConfig
  58. from mmc.plugins.glpi.GLPIClient import XMLRPCClient
  59. from mmc.plugins.glpi.utilities import complete_ctx
  60. from mmc.plugins.glpi.database_utils import decode_latin1, encode_latin1, decode_utf8, encode_utf8, fromUUID, toUUID, \
  61.     setUUID
  62. from mmc.plugins.glpi.database_utils import DbTOA  # pyflakes.ignore
  63. from mmc.plugins.dyngroup.config import DGConfig
  64. from distutils.version import LooseVersion, StrictVersion
  65.  
  66.  
  67. class 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
  4321. class 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.  
  4358. class 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.  
  4369. class State(object):
  4370.     pass
  4371.  
  4372.  
  4373. class DiskFs(object):
  4374.     pass
  4375.  
  4376.  
  4377. class FusionAntivirus(object):
  4378.     pass
  4379.  
  4380.  
  4381. class FusionLocks(object):
  4382.     pass
  4383.  
  4384.  
  4385. class FusionAgents(object):
  4386.     to_be_exported = ['last_contact']
  4387.  
  4388.  
  4389. class Disk(object):
  4390.     pass
  4391.  
  4392.  
  4393. class Suppliers(object):
  4394.     pass
  4395.  
  4396.  
  4397. class Infocoms(object):
  4398.     pass
  4399.  
  4400.  
  4401. class Processor(object):
  4402.     pass
  4403.  
  4404.  
  4405. class ComputerProcessor(object):
  4406.     pass
  4407.  
  4408.  
  4409. class Memory(object):
  4410.     pass
  4411.  
  4412.  
  4413. class MemoryType(object):
  4414.     pass
  4415.  
  4416.  
  4417. class ComputerMemory(object):
  4418.     pass
  4419.  
  4420.  
  4421. class Logs(object):
  4422.     pass
  4423.  
  4424.  
  4425. class User(object):
  4426.     pass
  4427.  
  4428.  
  4429. class Profile(object):
  4430.     pass
  4431.  
  4432.  
  4433. class UserProfile(object):
  4434.     pass
  4435.  
  4436.  
  4437. class 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.  
  4450. class OS(object):
  4451.     pass
  4452.  
  4453.  
  4454. class ComputerDevice(object):
  4455.     pass
  4456.  
  4457.  
  4458. class Domain(object):
  4459.     pass
  4460.  
  4461.  
  4462. class Manufacturers(object):
  4463.     pass
  4464.  
  4465.  
  4466. class Software(object):
  4467.     pass
  4468.  
  4469.  
  4470. class InstSoftware(object):
  4471.     pass
  4472.  
  4473.  
  4474. class Licenses(object):
  4475.     pass
  4476.  
  4477.  
  4478. class SoftwareVersion(object):
  4479.     pass
  4480.  
  4481.  
  4482. class Group(object):
  4483.     pass
  4484.  
  4485.  
  4486. class OsSp(object):
  4487.     pass
  4488.  
  4489.  
  4490. class Model(object):
  4491.     pass
  4492.  
  4493.  
  4494. class Locations(object):
  4495.     pass
  4496.  
  4497.  
  4498. class Net(object):
  4499.     pass
  4500.  
  4501.  
  4502. class NetworkInterfaces(object):
  4503.     pass
  4504.  
  4505.  
  4506. class IPAddresses(object):
  4507.     pass
  4508.  
  4509.  
  4510. class IPNetworks(object):
  4511.     pass
  4512.  
  4513.  
  4514. class NetworkNames(object):
  4515.     pass
  4516.  
  4517.  
  4518. class IPAddresses_IPNetworks(object):
  4519.     pass
  4520.  
  4521.  
  4522. class Collects(object):
  4523.     pass
  4524.  
  4525.  
  4526. class Rule(DbTOA):
  4527.     pass
  4528.  
  4529.  
  4530. class RuleCriterion(DbTOA):
  4531.     pass
  4532.  
  4533.  
  4534. class RuleAction(DbTOA):
  4535.     pass
  4536.  
  4537.  
  4538. class Registries(object):
  4539.     pass
  4540.  
  4541.  
  4542. class RegContents(object):
  4543.     pass
Add Comment
Please, Sign In to add comment