# -*- coding: utf-8 -*- def _hashValuesNoneToEmptyString(self, hash): for (key, value) in hash.items(): if value is None: hash[key] = '' return hash def exit(self): self.backend_exit() def deleteOpsiBase(self): self.backend_deleteBase() def createOpsiBase(self): self.backend_createBase() def writeLog(self, type, data, objectId=None, append=True): self.log_write(logType = type, data = data, objectId = objectId, append = append) def readLog(self, type, objectId=None, maxSize=0): return self.log_read(logType = type, objectId = objectId, maxSize = maxSize) def getOpsiInformation_hash(self): return self.backend_info() def getBackendInfos_listOfHashes(self): return [{config[0]: config[1]} for config in self.dispatcher_getConfig()] def getDomain(self): from OPSI.Backend.Backend import OPSI_GLOBAL_CONF return forceUnicodeLower('.'.join(getfqdn(conf=OPSI_GLOBAL_CONF).split('.')[1:])) def getPossibleMethods_listOfHashes(self): possibleMethods = [] for method in self.backend_getInterface(): compatible = True for param in method["params"]: if param.startswith('**'): compatible = False break if compatible: possibleMethods.append({"name": method["name"], "params": method["params"]}) return possibleMethods def authenticated(self): if self.accessControl_authenticated(): return True raise Exception(u"Not authenticated") def getGeneralConfig_hash(self, objectId=None): if objectId: objectId = forceFqdn(objectId) if objectId in self.host_getIdents(type='OpsiDepotserver', returnType='unicode'): objectId = None result = {} if objectId: addConfigStateDefaults = self._backend.backend_getOptions().get('addConfigStateDefaults', False) try: self._backend.backend_setOptions({'addConfigStateDefaults': True}) for configState in self.configState_getObjects(objectId=objectId): result[configState.configId] = u','.join(forceUnicodeList(configState.getValues())) finally: self._backend.backend_setOptions({'addConfigStateDefaults': addConfigStateDefaults}) else: for config in self.config_getObjects(): result[config.id] = u','.join(forceUnicodeList(config.defaultValues)) return result def getGeneralConfigValue(self, key, objectId=None): return self.getGeneralConfig_hash(objectId=objectId).get(key) def setGeneralConfig(self, config, objectId=None): if objectId: objectId = forceFqdn(objectId) if objectId in self.host_getIdents(type='OpsiDepotserver', returnType='unicode'): objectId = None else: objectId = None knownConfigIds = frozenset(self.config_getIdents(returnType='unicode')) for configId in knownConfigIds: if configId not in config: self.config_delete(id=configId) boolvalues = frozenset(['yes', 'no', 'on', 'off', '1', '0', 'true', 'false']) def getNewConfigs(): hasNoObjectId = bool(objectId is None) for configId, value in config.iteritems(): if hasNoObjectId or configId not in knownConfigIds: if value.lower() in boolvalues: value = forceBool(value) yield BoolConfig(id=configId, defaultValues=[value]) else: yield UnicodeConfig( id=configId, defaultValues=[value], possibleValues=[value], editable=True, multiValue=False ) def getNewConfigStates(): if objectId is not None: for configId, value in config.iteritems(): if value.lower() in boolvalues: value = forceBool(value) yield ConfigState( configId=configId, objectId=objectId, values=[value] ) self.config_createObjects(getNewConfigs()) self.configState_createObjects(getNewConfigStates()) def setGeneralConfigValue(self, key, value, objectId=None): generalConfig = self.getGeneralConfig_hash(objectId=objectId) generalConfig[key] = value return self.setGeneralConfig(generalConfig, objectId=objectId) def deleteGeneralConfig(self, objectId): return self.configState_delete(configId=[], objectId=forceObjectId(objectId)) def setNetworkConfig(self, config, objectId=None): if objectId and 'depotId' in config.keys(): return self.setGeneralConfigValue('clientconfig.depot.id', config['depotId'], objectId) raise NotImplementedError("Please use general config to change values") def setNetworkConfigValue(self, key, value, objectId=None): raise NotImplementedError("Please use general config to change values") def getNetworkConfig_hash(self, objectId=None): configServerIdents = self.host_getIdents(type='OpsiConfigserver', returnType='unicode') if not configServerIdents: raise BackendMissingDataError(u"No configserver found") depotId = self.getGeneralConfigValue('clientconfig.depot.id', objectId=objectId) depots = self.host_getObjects(type='OpsiDepotserver', id=depotId) if not depots: raise BackendMissingDataError(u"Depotserver '%s' not found" % depotId) depotDrive = self.getGeneralConfigValue('clientconfig.depot.drive', objectId=objectId) depotUrl = depots[0].getDepotRemoteUrl() return { 'opsiServer': configServerIdents[0], 'nextBootServiceURL': self.getGeneralConfigValue('clientconfig.configserver.url', objectId=objectId), 'nextBootServerType': u'service', 'depotId': depotId, 'depotUrl': depotUrl, 'depotDrive': depotDrive, 'configUrl': depotUrl.replace('/install', '/pcpatch'), 'configDrive': depotDrive, 'utilsUrl': depotUrl.replace('/install', '/utils'), 'utilsDrive': depotDrive, 'winDomain': self.getGeneralConfigValue('clientconfig.windows.domain', objectId=objectId), } def getNetworkConfigValue(self, key, objectId=None): return self.getNetworkConfig_hash(objectId).get(key) def deleteNetworkConfig(self, objectId): raise NotImplementedError("Please use general config to change values") def getGroupIds_list(self): return self.group_getIdents(returnType='unicode') def getHostGroupTree_hash(self): groups = {} childs = {} for group in self.group_getObjects(attributes=['id', 'parentGroupId']): if group.getParentGroupId(): if not childs.has_key(group.getParentGroupId()): childs[group.getParentGroupId()] = {} childs[group.getParentGroupId()][group.getId()] = {} else: groups[group.getId()] = {} def insertGroup(gid, g, gs): if gid in gs.keys(): gs[gid] = g return True for ng in gs.keys(): if insertGroup(gid, g, gs[ng]): return True return False while childs.keys(): left = len(childs.keys()) for groupId in childs.keys(): if insertGroup(groupId, childs[groupId], groups): del childs[groupId] if (left == len(childs.keys())): raise BackendIOError("Error in host groups") return groups def createGroup(self, groupId, members=[], description="", parentGroupId=""): if not members: members = [] if not parentGroupId: parentGroupId = None self.group_createHostGroup(id=groupId, description=description, notes=u'', parentGroupId=parentGroupId) objects = [ObjectToGroup(groupType='HostGroup', groupId=groupId, objectId=member) for member in members] self.objectToGroup_createObjects(objects) def deleteGroup(self, groupId): self.group_delete(id=groupId) def getHostId(self, hostname=None): if not hostname: raise NotImplementedError(u"Hostname not given") return '%s.%s' % (forceUnicode(hostname), self.getDomain()) def setPXEBootConfiguration(self, hostId, args={}): raise NotImplementedError(u"Not Implemented") def unsetPXEBootConfiguration(self, hostId): raise NotImplementedError(u"Not Implemented") def powerOnHost(self, hostId): return self.hostControl_start(hostId) def getIpAddress(self, hostId): hostId = forceHostId(hostId) hosts = self.host_getObjects(attributes=['ipAddress'], id=hostId) if not hosts: raise BackendMissingDataError(u"Host '%s' not found" % hostId) return hosts[0].getIpAddress() or u'' def createServer(self, serverName, domain, description=None, notes=None): id = forceHostId(u'.'.join((forceHostname(serverName), forceDomain(domain)))) self.host_createOpsiConfigserver(id=id, description=description, notes=notes) return id def createClient(self, clientName, domain, description=None, notes=None, ipAddress=None, hardwareAddress=None): if not ipAddress: ipAddress = None if not hardwareAddress: hardwareAddress = None id = forceHostId(u'.'.join((forceHostname(clientName), forceDomain(domain)))) self.host_createOpsiClient(id=id, description=description, notes=notes, ipAddress=ipAddress, hardwareAddress=hardwareAddress) return id def deleteServer(self, serverId): self.host_delete(id=forceHostId(serverId)) def deleteClient(self, clientId): self.host_delete(id=forceHostId(clientId)) def setHostLastSeen(self, hostId, timestamp): hostId = forceHostId(hostId) hosts = self.host_getObjects(id=hostId) if not hosts: raise BackendMissingDataError(u"Host '%s' not found" % hostId) hosts[0].setLastSeen(timestamp) self.host_updateObject(hosts[0]) def setHostDescription(self, hostId, description): hostId = forceHostId(hostId) hosts = self.host_getObjects(id=hostId) if not hosts: raise BackendMissingDataError(u"Host '%s' not found" % hostId) hosts[0].setDescription(description) self.host_updateObject(hosts[0]) def setHostNotes(self, hostId, notes): hostId = forceHostId(hostId) hosts = self.host_getObjects(id=hostId) if not hosts: raise BackendMissingDataError(u"Host '%s' not found" % hostId) hosts[0].setNotes(notes) self.host_updateObject(hosts[0]) def getSoftwareInformation_hash(self, hostId): import time auditSoftwares = {} for aus in self.auditSoftware_getObjects(): try: auditSoftwares[aus.name][aus.version][aus.subVersion][aus.language][aus.architecture] = aus except KeyError: try: auditSoftwares[aus.name][aus.version][aus.subVersion][aus.language] = {aus.architecture: aus} except KeyError: try: auditSoftwares[aus.name][aus.version][aus.subVersion] = {aus.language: {aus.architecture: aus}} except KeyError: try: auditSoftwares[aus.name][aus.version] = {aus.subVersion: {aus.language: {aus.architecture: aus}}} except KeyError: auditSoftwares[aus.name] = {aus.version: {aus.subVersion: {aus.language: {aus.architecture: aus}}}} keysToRemove = ( "clientId", "name", "version", "subVersion", "language", "architecture", "state", "firstseen", "lastseen" ) result = {} scantime = time.strptime("2000-01-01 00:00:00", "%Y-%m-%d %H:%M:%S") for auditSoftwareOnClient in self.auditSoftwareOnClient_getObjects(clientId=hostId): lastseen = time.strptime(auditSoftwareOnClient.getLastseen(), "%Y-%m-%d %H:%M:%S") if scantime < lastseen: scantime = lastseen try: aus = (auditSoftwares [auditSoftwareOnClient.name] [auditSoftwareOnClient.version] [auditSoftwareOnClient.subVersion] [auditSoftwareOnClient.language] [auditSoftwareOnClient.architecture] ) except KeyError: logger.error( u'No auditSoftwares found with filter: {"name": {0}, ' u'"version": {1}, "subVersion": {2}, "language": {3}, ' u'"architecture": {4}}'.format( auditSoftwareOnClient.getName(), auditSoftwareOnClient.getVersion(), auditSoftwareOnClient.getSubVersion(), auditSoftwareOnClient.getLanguage(), auditSoftwareOnClient.getArchitecture() ) ) continue hash = auditSoftwareOnClient.toHash() hash["softwareId"] = aus.getWindowsSoftwareId() hash["displayName"] = aus.getWindowsDisplayName() hash["displayVersion"] = aus.getWindowsDisplayVersion() hash["installSize"] = aus.getInstallSize() for keyToRemove in keysToRemove: del hash[keyToRemove] if aus.getWindowsSoftwareId(): result[aus.getWindowsSoftwareId()] = self._hashValuesNoneToEmptyString(hash) result['SCANPROPERTIES'] = {'scantime': time.strftime("%Y-%m-%d %H:%M:%S", scantime)} return result def getSoftwareInformation_listOfHashes(self): result = [] for auditSoftware in self.auditSoftware_getObjects(): hash = auditSoftware.toHash() hash['displayName'] = hash['windowsDisplayName'] del hash['windowsDisplayName'] hash['displayVersion'] = hash['windowsDisplayVersion'] del hash['windowsDisplayVersion'] del hash['type'] del hash['name'] del hash['architecture'] del hash['language'] del hash['version'] del hash['subVersion'] if not hash['installSize']: hash['installSize'] = 0 hash['uninstallString'] = u'' hash['binaryName'] = u'' hash['installedOn'] = [] for auditSoftwareOnClient in self.auditSoftwareOnClient_getObjects( name=auditSoftware.getName(), version=auditSoftware.getVersion(), subVersion=auditSoftware.getSubVersion(), language=auditSoftware.getLanguage(), architecture=auditSoftware.getArchitecture()): if auditSoftwareOnClient.getUninstallString(): hash['uninstallString'] = auditSoftwareOnClient.getUninstallString() if auditSoftwareOnClient.getBinaryName(): hash['binaryName'] = auditSoftwareOnClient.getBinaryName() hash['installedOn'].append(auditSoftwareOnClient.getClientId()) hash['installationCount'] = len(hash['installedOn']) result.append(hash) return result def setSoftwareInformation(self, hostId, info): hostId = forceHostId(hostId) self.auditSoftwareOnClient_delete(name=[], version=[], subVersion=[], language=[], architecture=[], clientId=hostId) for (windowsSoftwareId, value) in info.items(): if (windowsSoftwareId == 'SCANPROPERTIES'): continue auditSoftwareHash = { 'name': u'', 'version': u'', 'subVersion': u'', 'language': u'', 'architecture': u'x86', 'windowsSoftwareId': windowsSoftwareId, 'windowsDisplayName': u'', 'windowsDisplayVersion': u'', 'installSize': -1, } auditSoftwareOnClientHash = { 'clientId': hostId, 'uninstallString': u'', 'binaryName': u'', 'usageFrequency': -1, 'lastUsed': None, } for (k, v) in value.items(): if k.lower() == 'displayname': auditSoftwareHash['name'] = auditSoftwareHash['windowsDisplayName'] = v elif k.lower() == 'displayversion': auditSoftwareHash['version'] = auditSoftwareHash['windowsDisplayVersion'] = v elif k.lower() == 'installsize': auditSoftwareHash['installSize'] = v else: for kk in auditSoftwareOnClientHash.keys(): if k.lower() == kk.lower(): auditSoftwareOnClientHash[k] = v break if not auditSoftwareHash['name']: auditSoftwareHash['name'] = auditSoftwareHash['windowsSoftwareId'] auditSoftwareOnClientHash['name'] = auditSoftwareHash['name'] auditSoftwareOnClientHash['version'] = auditSoftwareHash['version'] auditSoftwareOnClientHash['subVersion'] = auditSoftwareHash['subVersion'] auditSoftwareOnClientHash['language'] = auditSoftwareHash['language'] auditSoftwareOnClientHash['architecture'] = auditSoftwareHash['architecture'] self.auditSoftware_createObjects( AuditSoftware.fromHash(auditSoftwareHash) ) self.auditSoftwareOnClient_createObjects( AuditSoftwareOnClient.fromHash(auditSoftwareOnClientHash) ) def deleteSoftwareInformation(self, hostId): hostId = forceHostId(hostId) self.auditSoftwareOnClient_delete(clientId = hostId) def softwareInformationToProductInstallationStatus(self, hostIds=[]): raise NotImplementedError("Not Implemented") ''' This method sets product installation states based on software inventory results. ''' if not isinstance(hostIds, (list, tuple)): hostIds = [hostIds] if not hostIds: hostIds = self.getClientIds_list() windowsSoftwareIds = {} for product in self.getProducts_listOfHashes(): if product.get("windowsSoftwareIds", []): for swid in product["windowsSoftwareIds"]: windowsSoftwareIds[swid] = product['productId'] errors = [] for hostId in hostIds: try: sw = self.getSoftwareInformation_hash(hostId) for (softwareId, info) in sw.items(): if windowsSoftwareIds.has_key(softwareId): status = self.getProductInstallationStatus_hash(windowsSoftwareIds[softwareId], hostId) if (status.get("installationStatus") == "installed"): continue self.setProductState(windowsSoftwareIds[softwareId], hostId, installationStatus="installed", packageVersion="0") except Exception, e: logger.error("softwareInformationToProductInstallationStatus error: %s" % e) errors.append(e) if errors: raise Exception("Error occurred: %s" % errors) def getOpsiHWAuditConf(self, locale=None): return self.auditHardware_getConfig(locale) def getHardwareInformation_hash(self, hostId): import time hostId = forceHostId(hostId) info = {} scantime = time.strptime("2000-01-01 00:00:00", "%Y-%m-%d %H:%M:%S") for auditHardwareOnHost in self.auditHardwareOnHost_getObjects(hostId=hostId, state=1): hardwareClass = auditHardwareOnHost.getHardwareClass() if hardwareClass not in info: info[hardwareClass] = [] data = auditHardwareOnHost.toHash() lastseen = time.strptime(str(data['lastseen']), "%Y-%m-%d %H:%M:%S") if scantime < lastseen: scantime = lastseen for key in ('hardwareClass', 'hostId', 'firstseen', 'state', 'lastseen'): del data[key] info[hardwareClass].append(data) info['SCANPROPERTIES'] = [ {'scantime': time.strftime("%Y-%m-%d %H:%M:%S", scantime) } ] return info def getHardwareInformation_listOfHashes(self, hostId): return [] def setHardwareInformation(self, hostId, info): hostId = forceHostId(hostId) self.auditHardwareOnHost_setObsolete(hostId) auditHardwareOnHosts = [] for (hardwareClass, devices) in info.items(): if (hardwareClass == 'SCANPROPERTIES'): continue for device in devices: data = {'hardwareClass': hardwareClass} for (attribute, value) in device.items(): data[str(attribute)] = value data['hostId'] = hostId auditHardwareOnHosts.append(AuditHardwareOnHost.fromHash(data)) self.auditHardwareOnHost_updateObjects(auditHardwareOnHosts) def deleteHardwareInformation(self, hostId): hostId = forceHostId(hostId) self.auditHardwareOnHost_delete(hostId = hostId, hardwareClass = []) def filterHostsByHardwareInformation(self, hostIds, hwFilter): raise NotImplementedError("Not Implemented") def getHost_hash(self, hostId): import re hostId = forceHostId(hostId) hosts = self.host_getObjects(id = hostId) if not hosts: raise BackendMissingDataError(u"Host '%s' not found" % hostId) hash = hosts[0].toHash() hash['hostId'] = hash['id'] match = re.search('^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$', hash.get('created', '')) if match: hash['created'] = u'%s%s%s%s%s%s' % ( match.group(1), match.group(2), match.group(3), match.group(4), match.group(5), match.group(6) ) match = re.search('^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$', hash.get('lastSeen', '')) if match: hash['lastSeen'] = u'%s%s%s%s%s%s' % ( match.group(1), match.group(2), match.group(3), match.group(4), match.group(5), match.group(6) ) del hash['type'] del hash['id'] return self._hashValuesNoneToEmptyString(hash) def getClients_listOfHashes(self, serverId=None, depotIds=[], groupId=None, productId=None, installationStatus=None, actionRequest=None, productVersion=None, packageVersion=None, hwFilter=None): if not serverId: serverId = [] if not depotIds: depotIds = [] if not groupId: groupId = [] if not productId: productId = [] if not installationStatus: installationStatus = [] if not actionRequest: actionRequest = [] if not productVersion: productVersion = [] if not packageVersion: packageVersion = [] if not hwFilter: hwFilter = [] clientToDepotservers = self.configState_getClientToDepotserver(depotIds=forceHostIdList(depotIds)) if depotIds: clientIds = [clientToDepotserver['clientId'] for clientToDepotserver in clientToDepotservers] if not clientIds: return [] else: clientIds = [] if groupId: filteredClientIds = [ident['objectId'] for ident in self.objectToGroup_getIdents(groupType='HostGroup', objectId=clientIds, groupId=groupId, returnType='dict')] if not filteredClientIds: return [] clientIds = filteredClientIds if productId or productVersion or packageVersion or installationStatus or actionRequest: clientIds = self.backend_searchIdents(u'(&(&(objectClass=OpsiClient)(id=%s))(&(objectClass=ProductOnClient)(productId=%s)(productVersion=%s)(packageVersion=%s)(installationStatus=%s)(actionRequest=%s)))' % \ (clientIds, productId, productVersion, packageVersion, installationStatus, actionRequest)) if not clientIds: return [] if hwFilter: filter = [u'(&(&(objectClass=OpsiClient)(id=%s))' % clientIds, ] for (k, v) in hwFilter.items(): (hwClass, attr) = k.split('.') match = re.search('^([<=>]=?)(\d+.*)$', v) if match: operator = match.group(1) v = match.group(2) if operator == '==': operator = '=' elif operator == '<': operator = '<=' try: v = forceInt(v) + 1 except Exception: pass elif operator == '>': operator = '>=' try: v = forceInt(v) - 1 except Exception: pass v = u'%s%s' % (operator, v) else: v = u'=%s' % v filter.append(u'(&(objectClass=AuditHardwareOnHost)(hardwareClass=%s)(%s%s))' % (hwClass, attr, v)) filter.append(u')') filter = ''.join(filter) clientIds = self.backend_searchIdents(filter) if not clientIds: return [] result = [] for client in self.host_getObjects(type='OpsiClient', id=clientIds): hash = client.toHash() hash['hostId'] = hash['id'] if hash.get('created') is None: hash['created'] = u'' else: match = re.search('^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$', hash.get('created', '')) if match: hash['created'] = u'%s%s%s%s%s%s' % ( match.group(1), match.group(2), match.group(3), match.group(4), match.group(5), match.group(6) ) if hash.get('lastSeen') is None: hash['lastSeen'] = u'' else: match = re.search('^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$', hash.get('lastSeen', '')) if match: hash['lastSeen'] = u'%s%s%s%s%s%s' % ( match.group(1), match.group(2), match.group(3), match.group(4), match.group(5), match.group(6) ) del hash['type'] del hash['id'] hash['depotId'] = u'' for clientToDepotserver in clientToDepotservers: if client.getId() == clientToDepotserver['clientId']: hash['depotId'] = clientToDepotserver['depotId'] break result.append(self._hashValuesNoneToEmptyString(hash)) return result def getClientIds_list(self, serverId=None, depotIds=[], groupId=None, productId=None, installationStatus=None, actionRequest=None, productVersion=None, packageVersion=None, hwFilter=None): return [client['hostId'] for client in self.getClients_listOfHashes(serverId, depotIds, groupId, productId, installationStatus, actionRequest, productVersion, packageVersion, hwFilter)] def getClientIdByMac(self, mac): hosts = self.host_getObjects(attributes=['id'], type='OpsiClient', hardwareAddress=forceHardwareAddress(mac)) if not hosts: return u'' return hosts[0].id def getServerIds_list(self): return self.host_getIdents(type = 'OpsiConfigserver') def getServerId(self, clientId): return self.host_getIdents(type = 'OpsiConfigserver')[0] def createDepot(self, depotName, domain, depotLocalUrl, depotRemoteUrl, repositoryLocalUrl, repositoryRemoteUrl, network, description=None, notes=None, maxBandwidth=0): id = forceHostId(forceHostname(depotName) + u'.' + forceDomain(domain)) self.host_createOpsiDepotserver( id = id, depotLocalUrl = depotLocalUrl, depotRemoteUrl = depotRemoteUrl, repositoryLocalUrl = repositoryLocalUrl, repositoryRemoteUrl = repositoryRemoteUrl, description = description, notes = notes, hardwareAddress = None, ipAddress = None, networkAddress = network, maxBandwidth = maxBandwidth, ) return id def getDepotIds_list(self): return self.host_getIdents(type = 'OpsiDepotserver', isMasterDepot = True) def getDepot_hash(self, depotId): depotId = forceHostId(depotId) depots = self.host_getObjects(id = depotId) if not depots: raise BackendMissingDataError(u"Depot '%s' not found" % depotId) hash = depots[0].toHash() del hash['type'] if not hash['ipAddress']: try: hash['ipAddress'] = socket.gethostbyname(depotId) except Exception, e: logger.debug(u"Failed to get host by name (%s): %s" % (depotId, e)) hash['ip'] = hash['ipAddress'] return self._hashValuesNoneToEmptyString(hash) def getDepotId(self, clientId=None): if not clientId: clientId = None for clientToDepotserver in self.configState_getClientToDepotserver(clientIds=clientId): if clientToDepotserver['clientId'] == clientId: return clientToDepotserver['depotId'] raise BackendConfigurationError(u"Failed to get depot server for client '%s'" % clientId) def deleteDepot(self, depotId): self.host_delete(id = forceHostId(depotId)) def generateOpsiHostKey(self): raise NotImplementedError("Not Implemented") def getOpsiHostKey(self, hostId): if not hostId: raise NotImplementedError("No host id given") hostId = forceHostId(hostId) hosts = self.host_getObjects(attributes = ['opsiHostKey'], id = hostId) if not hosts: raise BackendMissingDataError(u"Host '%s' not found" % hostId) return hosts[0].opsiHostKey def setOpsiHostKey(self, hostId, opsiHostKey): hostId = forceHostId(hostId) hosts = self.host_getObjects(id = hostId) if not hosts: raise BackendMissingDataError(u"Host '%s' not found" % hostId) hosts[0].setOpsiHostKey(opsiHostKey) self.host_updateObject(hosts[0]) def getMacAddresses_list(self, hostId): hostId = forceHostId(hostId) hosts = self.host_getObjects(id = hostId) if not hosts: raise BackendMissingDataError(u"Host '%s' not found" % hostId) if not hosts[0].hardwareAddress: return [''] return [ hosts[0].hardwareAddress ] def setMacAddresses(self, hostId, macs=()): hostId = forceHostId(hostId) hosts = self.host_getObjects(id = hostId) if not hosts: raise BackendMissingDataError(u"Host '%s' not found" % hostId) hosts[0].setHardwareAddress(macs[0]) self.host_updateObject(hosts[0]) def getMacAddress(self, hostId): return self.getMacAddresses_list(hostId)[0] def setMacAddress(self, hostId, mac): self.setMacAddresses(hostId, macs = [ mac ] ) def lockProduct(self, productId, depotIds=[]): productOnDepots = self.productOnDepot_getObjects(productId = productId, depotId = depotIds) if not productOnDepots: raise BackendMissingDataError(u"Product '%s' not found on given depots" % productId) for productOnDepot in productOnDepots: productOnDepot.setLocked(True) self.productOnDepot_updateObjects(productOnDepots) def unlockProduct(self, productId, depotIds=[]): productOnDepots = self.productOnDepot_getObjects(productId = productId, depotId = depotIds) if not productOnDepots: raise BackendMissingDataError(u"Product '%s' not found on given depots" % productId) for productOnDepot in productOnDepots: productOnDepot.setLocked(False) self.productOnDepot_updateObjects(productOnDepots) def getProductLocks_hash(self, depotIds=[]): result = {} for productOnDepot in self.productOnDepot_getObjects(depotId = depotIds, locked = True): if not result.has_key(productOnDepot.productId): result[productOnDepot.productId] = [] result[productOnDepot.productId].append(productOnDepot.depotId) return result def createProduct(self, productType, productId, name, productVersion, packageVersion, licenseRequired=0, setupScript="", uninstallScript="", updateScript="", alwaysScript="", onceScript="", priority=0, description="", advice="", productClassNames=(), pxeConfigTemplate='', windowsSoftwareIds=[], depotIds=[]): type = forceProductType(productType) hash = locals() del hash['productType'] del hash['depotIds'] del hash['self'] hash['id'] = hash['productId'] del hash['productId'] product = Product.fromHash(hash) self.product_createObjects(product) productOnDepots = [] if not depotIds: depotIds = self.host_getIdents(type = 'OpsiDepotserver') for depotId in depotIds: productOnDepots.append( ProductOnDepot( productId = product.id, productType = product.getType(), productVersion = product.productVersion, packageVersion = product.packageVersion, depotId = depotId )) self.productOnDepot_createObjects(productOnDepots) def createLocalBootProduct(self, productId, name, productVersion, packageVersion, licenseRequired=0, setupScript="", uninstallScript="", updateScript="", alwaysScript="", onceScript="", priority=0, description="", advice="", productClassNames=('localBoot'), windowsSoftwareIds=[], depotIds=[]): self.createProduct('localboot', productId, name, productVersion, packageVersion, licenseRequired, setupScript, uninstallScript, updateScript, alwaysScript, onceScript, priority, description, advice, productClassNames, '', windowsSoftwareIds, depotIds) def createNetBootProduct(self, productId, name, productVersion, packageVersion, licenseRequired=0, setupScript="", uninstallScript="", updateScript="", alwaysScript="", onceScript="", priority=0, description="", advice="", productClassNames=('netboot'), pxeConfigTemplate='', windowsSoftwareIds=[], depotIds=[]): self.createProduct('netboot', productId, name, productVersion, packageVersion, licenseRequired, setupScript, uninstallScript, updateScript, alwaysScript, onceScript, priority, description, advice, productClassNames, pxeConfigTemplate, windowsSoftwareIds, depotIds) def createServerProduct(self, productId, name, productVersion, packageVersion, licenseRequired=0, setupScript="", uninstallScript="", updateScript="", alwaysScript="", onceScript="", priority=10, description="", advice="", productClassNames=('server'), windowsSoftwareIds=[], depotIds=[]): raise NotImplementedError("Not Implemented") def deleteProduct(self, productId, depotIds=[]): self.productOnDepot_delete(productId = productId, depotId = depotIds) def _productToHash(self, product): result = product.toHash() result['productId'] = result['id'] del result['id'] if (result['type'] == 'LocalbootProduct'): result['productType'] = 'localboot' elif (result['type'] == 'NetbootProduct'): result['productType'] = 'netboot' else: raise BackendBadValueError(u"Unknown product type '%s'" % result['type']) del result['type'] return self._hashValuesNoneToEmptyString(result) def getProduct_hash(self, productId, depotId=None): if not depotId: products = self.product_getObjects(id=productId) if not products: raise BackendMissingDataError(u"No product with id '%s' found" % productId) return self._productToHash(products[0]) else: productOnDepot = self.productOnDepot_getObjects(productId=productId, depotId=depotId) if not productOnDepot: raise BackendMissingDataError(u"No product with id '%s' on depot '%s' found" % (productId, depotId)) productOnDepot = productOnDepot[0] products = self.product_getObjects( id=productOnDepot.productId, productVersion=productOnDepot.productVersion, packageVersion=productOnDepot.packageVersion ) if not products: raise BackendMissingDataError(u"Product with id '%s', productVersion '%s', packageVersion '%s' not found" \ % (productOnDepot.productId, productOnDepot.productVersion, productOnDepot.packageVersion)) return self._productToHash(products[0]) def getProducts_hash(self, depotIds=[]): from collections import defaultdict if not depotIds: depotIds = self.getDepotIds_list() products = defaultdict(lambda: defaultdict(lambda: defaultdict(dict))) for product in self.product_getObjects(): products[product.id][product.productVersion][product.packageVersion] = product result = defaultdict(dict) for productOnDepot in self.productOnDepot_getObjects(depotId=depotIds): product = products[productOnDepot.productId][productOnDepot.productVersion][productOnDepot.packageVersion] if not product: raise BackendMissingDataError(u"Product with id '%s', productVersion '%s', packageVersion '%s' not found" \ % (productOnDepot.productId, productOnDepot.productVersion, productOnDepot.packageVersion)) result[productOnDepot.depotId][productOnDepot.productId] = self._productToHash(product) return result def getProducts_listOfHashes(self, depotId=None): if not depotId: return [self._productToHash(product) for product in self.product_getObjects()] result = [] for (depId, products) in self.getProducts_hash(depotIds=[depotId]).items(): for (productId, productHash) in products.items(): result.append(productHash) return result def getProductIds_list(self, productType=None, objectId=None, installationStatus=None): if not productType: productType = None if not objectId: objectId = None if not installationStatus: installationStatus = None type = None if (productType == 'localboot'): type = 'LocalbootProduct' elif (productType == 'netboot'): type = 'NetbootProduct' productIds = [] if objectId: objectId = forceHostId(objectId) hosts = self.host_getObjects(id = objectId) if not hosts: raise BackendMissingDataError(u"Host '%s' not found" % objectId) if isinstance(hosts[0], OpsiDepotserver): for ident in self.productOnDepot_getIdents(productType = type, depotId = hosts[0].getId(), returnType = 'dict'): productIds.append(ident['productId']) return productIds if not installationStatus: installationStatus = [] for ident in self.productOnClient_getIdents(productType = type, clientId = hosts[0].getId(), installationStatus = installationStatus, returnType = 'dict'): productIds.append(ident['productId']) return productIds else: for ident in self.product_getIdents(type = type, returnType = 'dict'): if not ident['id'] in productIds: productIds.append(ident['id']) return productIds def getLocalBootProductIds_list(self, objectId=None, installationStatus=None): return self.getProductIds_list('localboot', objectId, installationStatus) def getNetBootProductIds_list(self, objectId=None, installationStatus=None): return self.getProductIds_list('netboot', objectId, installationStatus) def getServerProductIds_list(self, objectId=None, installationStatus=None): raise NotImplementedError("Not Implemented") def getInstallableProductIds_list(self, clientId): depotId = self.getDepotId(clientId = clientId) result = [] for productOnDepot in self.productOnDepot_getObjects(depotId = depotId): result.append(productOnDepot.productId) return result def getInstallableLocalBootProductIds_list(self, clientId): depotId = self.getDepotId(clientId = clientId) result = [] for productOnDepot in self.productOnDepot_getObjects(depotId = depotId, productType = 'LocalbootProduct'): result.append(productOnDepot.productId) return result def getInstallableNetBootProductIds_list(self, clientId): depotId = self.getDepotId(clientId = clientId) result = [] for productOnDepot in self.productOnDepot_getObjects(depotId = depotId, productType = 'NetbootProduct'): result.append(productOnDepot.productId) return result def getInstalledProductIds_list(self, objectId): result = [] for productOnClient in self.productOnClient_getObjects(attributes = ['productId'], clientId = objectId, installationStatus = 'installed'): result.append(productOnClient.productId) return result def getUninstalledProductIds_list(self, objectId): raise NotImplementedError("Not Implemented") def getInstalledLocalBootProductIds_list(self, objectId): result = [] for productOnClient in self.productOnClient_getObjects(clientId = objectId, productType = 'LocalbootProduct', installationStatus = 'installed'): result.append(productOnClient.productId) return result def getInstalledNetBootProductIds_list(self, objectId): result = [] for productOnClient in self.productOnClient_getObjects(clientId = objectId, productType = 'NetbootProduct', installationStatus = 'installed'): result.append(productOnClient.productId) return result def getProvidedLocalBootProductIds_list(self, depotId): result = [] for productOnDepot in self.productOnDepot_getObjects(depotId = depotId, productType = 'LocalbootProduct'): result.append(productOnDepot.productId) return result def getProvidedNetBootProductIds_list(self, depotId): result = [] for productOnDepot in self.productOnDepot_getObjects(depotId = depotId, productType = 'NetbootProduct'): result.append(productOnDepot.productId) return result def getProductInstallationStatus_hash(self, productId, objectId): import re productId = forceProductId(productId) productOnClients = self.productOnClient_getObjects(productId = productId, clientId = objectId) if not productOnClients: return { u"installationStatus": u"not_installed", u"productId": productId } hash = productOnClients[0].toHash() match = re.search('^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$', hash.get('modificationTime', '')) if match: hash['lastStateChange'] = u'%s%s%s%s%s%s' % ( match.group(1), match.group(2), match.group(3), match.group(4), match.group(5), match.group(6) ) return hash def getProductInstallationStatus_listOfHashes(self, objectId): import re depotId = self.getDepotId(clientId = objectId) products = {} for productOnDepot in self.productOnDepot_getObjects(depotId=depotId): products[productOnDepot.productId] = { u"lastStateChange": u"", u"productVersion": productOnDepot.productVersion, u"packageVersion": productOnDepot.packageVersion, u"installationStatus": u"not_installed", u"productId": productOnDepot.productId } for productOnClient in self.productOnClient_getObjects(clientId=objectId): lastStateChange = u"" match = re.search('^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$', forceUnicode(productOnClient.modificationTime)) if match: lastStateChange = u'%s%s%s%s%s%s' % ( match.group(1), match.group(2), match.group(3), match.group(4), match.group(5), match.group(6) ) installationStatus = productOnClient.installationStatus if productOnClient.actionResult == "failed": installationStatus = u"failed" elif installationStatus == "unknown": installationStatus = u"not_installed" products[productOnClient.productId] = { u"lastStateChange": lastStateChange, u"productVersion": productOnClient.productVersion, u"packageVersion": productOnClient.packageVersion, u"installationStatus": installationStatus, u"productId": productOnClient.productId } return products.values() def setProductState(self, productId, objectId, installationStatus="", actionRequest="", productVersion="", packageVersion="", lastStateChange="", productActionProgress={}): if not installationStatus: installationStatus = None if not actionRequest: actionRequest = None if not productVersion: productVersion = None if not packageVersion: packageVersion = None if not lastStateChange: lastStateChange = None if not productActionProgress: productActionProgress = None actionResult = None if actionRequest: productActionProgress = u"" if actionRequest != 'none': actionResult = "none" if installationStatus: productActionProgress = u"" if installationStatus == 'failed': actionResult = "failed" installationStatus = None elif installationStatus == 'installed': actionResult = "successful" elif installationStatus == 'installing': productActionProgress = installationStatus actionResult = "none" installationStatus = "unknown" depotId = self.getDepotId(clientId=objectId) productType = None for productOnDepot in self.productOnDepot_getObjects(depotId=depotId, productId=productId): productType = productOnDepot.productType if not productType: raise BackendMissingDataError("Product '%s' not found on depot '%s'" % (productId, depotId)) self.productOnClient_updateObjects( ProductOnClient( productId=productId, productType=productType, clientId=objectId, installationStatus=installationStatus, actionRequest=actionRequest, actionProgress=productActionProgress, actionResult=actionResult, productVersion=productVersion, packageVersion=packageVersion, modificationTime=lastStateChange ) ) def setProductInstallationStatus(self, productId, objectId, installationStatus): self.setProductState( productId=productId, objectId=objectId, installationStatus=installationStatus ) def setProductActionProgress(self, productId, hostId, productActionProgress): self.setProductState( productId=productId, objectId=hostId, productActionProgress=productActionProgress ) def getPossibleProductActions_list(self, productId=None, depotId=None): if not depotId: depotId = None result = [ u'none' ] if not productId: return [ u'none', u'setup', u'uninstall', u'update', u'always', u'once', u'custom' ] product = self.getProduct_hash(productId = productId, depotId = depotId) if product['setupScript']: result.append(u'setup') if product['uninstallScript']: result.append(u'uninstall') if product['updateScript']: result.append(u'update') if product['alwaysScript']: result.append(u'always') if product['onceScript']: result.append(u'once') if product['customScript']: result.append(u'custom') return result def getPossibleProductActions_hash(self, depotId=None): result = {} if not depotId or not depotId in self.getDepotIds_list(): depotId = None for product in self.getProducts_listOfHashes(depotId = depotId): result[product['productId']] = [ u'none' ] if product['setupScript']: result[product['productId']].append(u'setup') if product['uninstallScript']: result[product['productId']].append(u'uninstall') if product['updateScript']: result[product['productId']].append(u'update') if product['alwaysScript']: result[product['productId']].append(u'always') if product['onceScript']: result[product['productId']].append(u'once') if product['customScript']: result[product['productId']].append(u'custom') return result def getProductActionRequests_listOfHashes(self, clientId, options=None): result = [] for productOnClient in self.productOnClient_getObjects(clientId = clientId): result.append({ u"productId": productOnClient.productId, u"actionRequest": productOnClient.actionRequest }) return result def getDefaultNetBootProductId(self, clientId): raise NotImplementedError(u"Not Implemented") def setProductActionRequest(self, productId, clientId, actionRequest): self.setProductState( productId = productId, objectId = clientId, actionRequest = actionRequest ) def unsetProductActionRequest(self, productId, clientId): self.setProductActionRequest(productId = productId, clientId = clientId, actionRequest = "none") def _getProductStates_hash(self, objectIds=[], options={}, productType=None): import re from collections import defaultdict if not productType: productType = None result = defaultdict(list) modificationtimeRegex = re.compile('^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$') addProductOnClientDefaults = self._backend.backend_getOptions().get('addProductOnClientDefaults', False) try: self._backend.backend_setOptions({'addProductOnClientDefaults': True}) for productOnClient in self.productOnClient_getObjects(clientId=objectIds, productType=productType): lastStateChange = productOnClient.modificationTime or u'' match = modificationtimeRegex.search(lastStateChange) if match: lastStateChange = u'%s%s%s%s%s%s' % (match.group(1), match.group(2), match.group(3), match.group(4), match.group(5), match.group(6)) installationStatus = productOnClient.installationStatus if productOnClient.actionResult == "failed": installationStatus = u"failed" elif installationStatus == "unknown": installationStatus = u"not_installed" result[productOnClient.clientId].append({ u"lastStateChange": lastStateChange, u"productVersion": productOnClient.productVersion or u'', u"packageVersion": productOnClient.packageVersion or u'', u"installationStatus": installationStatus, u"actionRequest": productOnClient.actionRequest, u"productActionProgress": productOnClient.actionProgress or u'', u"productId": productOnClient.productId }) finally: self._backend.backend_setOptions({'addProductOnClientDefaults': addProductOnClientDefaults}) return result def getLocalBootProductStates_hash(self, objectIds=[], options={}): return self._getProductStates_hash(objectIds=objectIds, options=options, productType='LocalbootProduct') def getNetBootProductStates_hash(self, objectIds=[], options={}): return self._getProductStates_hash(objectIds=objectIds, options=options, productType='NetbootProduct') def getProductStates_hash(self, objectIds=[], options={}): return self._getProductStates_hash(objectIds=objectIds, options=options) def getProductPropertyDefinitions_hash(self, depotId=None): if not depotId: depotId = None result = {} propertyNames = {} productProperties = {} for productProperty in self.productProperty_getObjects(): if not productProperties.has_key(productProperty.productId): productProperties[productProperty.productId] = {} if not productProperties[productProperty.productId].has_key(productProperty.productVersion): productProperties[productProperty.productId][productProperty.productVersion] = {} if not productProperties[productProperty.productId][productProperty.productVersion].has_key(productProperty.packageVersion): productProperties[productProperty.productId][productProperty.productVersion][productProperty.packageVersion] = [] productProperties[productProperty.productId][productProperty.productVersion][productProperty.packageVersion].append(productProperty) depotProperties = {} if depotId: for productPropertyState in self.productPropertyState_getObjects(objectId = depotId): if not depotProperties.has_key(productPropertyState.productId): depotProperties[productPropertyState.productId] = {} depotProperties[productPropertyState.productId][productPropertyState.propertyId] = productPropertyState.values for productOnDepot in self.productOnDepot_getIdents(depotId = depotId, returnType = 'dict'): for productProperty in productProperties.get(productOnDepot['productId'], {}).get(productOnDepot['productVersion'], {}).get(productOnDepot['packageVersion'], []): productId = productProperty.getProductId() if not result.has_key(productId): result[productId] = [] if not propertyNames.has_key(productId): propertyNames[productId] = {} if propertyNames[productId].has_key(productProperty.getPropertyId()): continue propertyNames[productId][productProperty.getPropertyId()] = 1 defaults = productProperty.getDefaultValues() if depotId: defaults = depotProperties.get(productId, {}).get(productProperty.getPropertyId(), defaults) values = [] if not productProperty.getEditable() or (productProperty.getPossibleValues() and len(productProperty.getPossibleValues()) > 1): values = forceUnicodeList(productProperty.getPossibleValues()) result[productId].append({ 'name': productProperty.getPropertyId(), 'description': productProperty.getDescription(), 'values': values, 'default': u','.join(forceUnicodeList(defaults)) }) return result def getProductPropertyDefinitions_listOfHashes(self, productId, depotId=None): result = [] propertyNames = {} for productOnDepot in self.productOnDepot_getIdents(depotId = depotId, productId = productId, returnType = 'dict'): for productProperty in self.productProperty_getObjects( productId = productOnDepot['productId'], productVersion = productOnDepot['productVersion'], packageVersion = productOnDepot['packageVersion']): if propertyNames.has_key(productProperty.getPropertyId()): continue propertyNames[productProperty.getPropertyId()] = 1 defaults = productProperty.getDefaultValues() if depotId: productPropertyState = self.productPropertyState_getObjects( productId = productId, propertyId = productProperty.getPropertyId(), objectId = depotId) if productPropertyState: defaults = productPropertyState[0].values values = [] if not productProperty.getEditable() or (productProperty.getPossibleValues() and len(productProperty.getPossibleValues()) > 1): values = forceUnicodeList(productProperty.getPossibleValues()) result.append({ 'name': productProperty.getPropertyId(), 'description': productProperty.getDescription(), 'values': values, 'default': u','.join(forceUnicodeList(defaults)) }) return result def deleteProductPropertyDefinition(self, productId, name, depotIds=[]): productProperties = [] for productOnDepot in self.productOnDepot_getObjects(productId = productId, depotId = depotIds): productProperties.extend( self.productProperty_getObjects( productId = productOnDepot.productId, productVersion = productOnDepot.productVersion, packageVersion = productOnDepot.packageVersion, propertyId = name ) ) if productProperties: self.productProperty_deleteObjects(productProperties) def deleteProductPropertyDefinitions(self, productId, depotIds=[]): productProperties = [] for productOnDepot in self.productOnDepot_getObjects(productId = productId, depotId = depotIds): productProperties.extend( self.productProperty_getObjects( productId = productOnDepot.productId, productVersion = productOnDepot.productVersion, packageVersion = productOnDepot.packageVersion ) ) if productProperties: self.productProperty_deleteObjects(productProperties) def createProductPropertyDefinition(self, productId, name, description=None, defaultValue=None, possibleValues=[], depotIds=[]): productProperties = [] productPropertyStates = [] created = {} depotIds = self.host_getIdents(type = 'OpsiDepotserver', id = depotIds, returnType = 'unicode') for productOnDepot in self.productOnDepot_getObjects(productId = productId, depotId = depotIds): if productOnDepot.packageVersion in created.get(productOnDepot.productVersion, []): continue defaultValues = [] if defaultValue: defaultValues = [ defaultValue ] editable = True if possibleValues: editable = False productProperties.append( UnicodeProductProperty( productId = productOnDepot.productId, productVersion = productOnDepot.productVersion, packageVersion = productOnDepot.packageVersion, propertyId = name, description = description, possibleValues = possibleValues, defaultValues = defaultValues, editable = editable, multiValue = False ) ) for depotId in depotIds: productPropertyStates.append( ProductPropertyState( productId = productOnDepot.productId, propertyId = name, objectId = depotId, values = defaultValues ) ) if not created.has_key(productOnDepot.productVersion): created[productOnDepot.productVersion] = [] created[productOnDepot.productVersion].append(productOnDepot.packageVersion) if productProperties: self.productProperty_createObjects(productProperties) if productPropertyStates: self.productPropertyState_createObjects(productPropertyStates) def getProductProperties_hash(self, productId, objectId=None): result = {} if not objectId: for ppd in self.getProductPropertyDefinitions_listOfHashes(productId=productId): result[ppd['name']] = ppd['default'] return result addProductPropertyStateDefaults = self._backend.backend_getOptions().get('addProductPropertyStateDefaults', False) try: self._backend.backend_setOptions({'addProductPropertyStateDefaults': True}) for productPropertyState in self.productPropertyState_getObjects(productId=productId, objectId=objectId): result[productPropertyState.getPropertyId()] = u','.join(forceUnicodeList(productPropertyState.getValues())) finally: self._backend.backend_setOptions({'addProductPropertyStateDefaults': addProductPropertyStateDefaults}) return result def setProductProperties(self, productId, properties, objectId=None): newProperties = {} for (propertyId, value) in properties.items(): newProperties[forceProductPropertyId(propertyId)] = forceUnicode(value) properties = newProperties productPropertyStates = [] if not objectId: depotIds = self.host_getIdents(type = 'OpsiDepotserver', returnType = 'unicode') for productPropertyState in self.productPropertyState_getObjects( productId = productId, objectId = depotIds): if not properties.has_key(productPropertyState.propertyId): continue productPropertyState.setValues(properties[productPropertyState.propertyId]) productPropertyStates.append(productPropertyState) else: for (propertyId, value) in properties.items(): productPropertyStates.append( ProductPropertyState( productId = productId, propertyId = propertyId, objectId = objectId, values = [ value ] ) ) self.productPropertyState_createObjects(productPropertyStates) def setProductProperty(self, productId, property, value, objectId=None): properties = self.getProductProperties_hash(productId, objectId) properties[property] = value self.setProductProperties(productId, properties, objectId) def deleteProductProperty(self, productId, property, objectId=None): raise NotImplementedError(u"Not implemented") def deleteProductProperties(self, productId, objectId=None): raise NotImplementedError(u"Not implemented") def getProductDependencies_listOfHashes(self, productId=None, depotId=None): if not productId: productId = None if not depotId: depotId = None result = [] if depotId: productDependencies = {} for productDependency in self.productDependency_getObjects(): if productId and productDependency.productId != productId: continue if not productDependencies.has_key(productDependency.productId): productDependencies[productDependency.productId] = {} if not productDependencies[productDependency.productId].has_key(productDependency.productVersion): productDependencies[productDependency.productId][productDependency.productVersion] = {} if not productDependencies[productDependency.productId][productDependency.productVersion].has_key(productDependency.packageVersion): productDependencies[productDependency.productId][productDependency.productVersion][productDependency.packageVersion] = [] productDependencies[productDependency.productId][productDependency.productVersion][productDependency.packageVersion].append(productDependency) for productOnDepot in self.productOnDepot_getIdents(depotId = depotId, returnType = 'dict'): for productDependency in productDependencies.get(productOnDepot['productId'], {}).get(productOnDepot['productVersion'], {}).get(productOnDepot['packageVersion'], []): result.append({ 'productId': productDependency.getProductId(), 'action': productDependency.getProductAction(), 'requiredProductId': productDependency.getRequiredProductId(), 'requiredProductClassId': u'', 'requiredAction': productDependency.getRequiredAction() or u'', 'requiredInstallationStatus': productDependency.getRequiredInstallationStatus() or u'', 'requirementType': productDependency.getRequirementType() or u'' }) else: for productDependency in self.productDependency_getObjects(productId = productId): result.append({ 'productId': productDependency.getProductId(), 'action': productDependency.getProductAction(), 'requiredProductId': productDependency.getRequiredProductId(), 'requiredProductClassId': u'', 'requiredAction': productDependency.getRequiredAction() or u'', 'requiredInstallationStatus': productDependency.getRequiredInstallationStatus() or u'', 'requirementType': productDependency.getRequirementType() or u'' }) return result def createProductDependency(self, productId, action, requiredProductId="", requiredProductClassId="", requiredAction="", requiredInstallationStatus="", requirementType="", depotIds=[]): if not requiredProductId: requiredProductId = None if not requiredProductClassId: requiredProductClassId = None if not requiredAction: requiredAction = None if not requiredInstallationStatus: requiredInstallationStatus = None if not requirementType: requirementType = None if not depotIds: depotIds = [] for productOnDepot in self.productOnDepot_getObjects(productId = productId, depotId = depotIds): self.productDependency_create( productId = productOnDepot.productId, productVersion = productOnDepot.productVersion, packageVersion = productOnDepot.packageVersion, productAction = action, requiredProductId = requiredProductId, requiredProductVersion = None, requiredPackageVersion = None, requiredAction = requiredAction, requiredInstallationStatus = requiredInstallationStatus, requirementType = requirementType) def deleteProductDependency(self, productId, action="", requiredProductId="", requiredProductClassId="", requirementType="", depotIds=[]): if not action: action = None if not requiredProductId: requiredProductId = None if not requiredProductClassId: requiredProductClassId = None if not requirementType: requirementType = None if not depotIds: depotIds = [] for productOnDepot in self.productOnDepot_getObjects(productId = productId, depotId = depotIds): self.productDependency_delete( productId = productOnDepot.productId, productVersion = productOnDepot.productVersion, packageVersion = productOnDepot.packageVersion, productAction = action, requiredProductId = requiredProductId, requirementType = requirementType) def createLicenseContract(self, licenseContractId="", partner="", conclusionDate="", notificationDate="", expirationDate="", notes=""): if not licenseContractId: # Generate license pool id import time knownLicenseContractIds = self.licenseContract_getIdents(returnType='unicode') t = time.strftime('%Y-%m-%d_%H:%M:%S', time.localtime()) i = 0 while True: licenseContractId = u'c_{time}_{index}'.format(time=t, index=i) if licenseContractId not in knownLicenseContractIds: break i += 1 self.licenseContract_create( id=licenseContractId, description=None, notes=notes, partner=partner, conclusionDate=conclusionDate, notificationDate=notificationDate, expirationDate=expirationDate ) return self.licenseContract_getIdents(id=licenseContractId, returnType='unicode')[0] def getLicenseContractIds_list(self): return self.licenseContract_getIdents(returnType = 'unicode') def getLicenseContract_hash(self, licenseContractId): licenseContracts = self.licenseContract_getObjects(id=licenseContractId) if not licenseContracts: raise BackendMissingDataError(u"License contract '%s' does not exist" % licenseContractId) hash = licenseContracts[0].toHash() # Cut time part, date only if hash['conclusionDate']: hash['conclusionDate'] = hash['conclusionDate'].split(' ')[0] else: hash['conclusionDate'] = u'' if hash['notificationDate']: hash['notificationDate'] = hash['notificationDate'].split(' ')[0] else: hash['notificationDate'] = u'' if hash['expirationDate']: hash['expirationDate'] = hash['expirationDate'].split(' ')[0] else: hash['expirationDate'] = u'' hash['licenseContractId'] = hash['id'] del hash['id'] del hash['type'] return hash def getLicenseContracts_listOfHashes(self): licenseContracts = [] for licenseContract in self.licenseContract_getObjects(): hash = licenseContract.toHash() # Cut time part, date only if hash['conclusionDate']: hash['conclusionDate'] = hash['conclusionDate'].split(' ')[0] else: hash['conclusionDate'] = u'' if hash['notificationDate']: hash['notificationDate'] = hash['notificationDate'].split(' ')[0] else: hash['notificationDate'] = u'' if hash['expirationDate']: hash['expirationDate'] = hash['expirationDate'].split(' ')[0] else: hash['expirationDate'] = u'' hash['licenseContractId'] = hash['id'] del hash['id'] del hash['type'] licenseContracts.append(hash) return licenseContracts def deleteLicenseContract(self, licenseContractId): self.licenseContract_delete(id = licenseContractId) def createSoftwareLicense(self, softwareLicenseId="", licenseContractId="", licenseType="", maxInstallations="", boundToHost="", expirationDate=""): if not boundToHost: boundToHost = None if not expirationDate: expirationDate = None if not licenseType: licenseType = 'volume' if not softwareLicenseId: # Generate software license id import time knownSoftwareLicenseIds = self.softwareLicense_getIdents(returnType = 'unicode') t = time.strftime('%Y-%m-%d_%H:%M:%S', time.localtime()) i=0 while True: softwareLicenseId = u'l_%s_%d' % (t, i) if not softwareLicenseId in knownSoftwareLicenseIds: break i+=1 method = None if (str(licenseType).lower() == 'oem'): method = self.softwareLicense_createOEM elif (str(licenseType).lower() == 'retail'): method = self.softwareLicense_createRetail elif (str(licenseType).lower() == 'volume'): method = self.softwareLicense_createVolume elif (str(licenseType).lower() == 'concurrent'): method = self.softwareLicense_createConcurrent else: raise BackendBadValueError(u"Unknown license type '%s'" % licenseType) method( id = softwareLicenseId, licenseContractId = licenseContractId, maxInstallations = maxInstallations, boundToHost = boundToHost, expirationDate = expirationDate) return self.softwareLicense_getIdents(id = softwareLicenseId, returnType = 'tuple')[0][0] def getSoftwareLicenseIds_list(self): ids = [] for ident in self.softwareLicense_getIdents(returnType = 'unicode'): ids.append(ident[0]) return ids def getSoftwareLicense_hash(self, softwareLicenseId): softwareLicenses = self.softwareLicense_getObjects(id = softwareLicenseId) if not softwareLicenses: raise BackendMissingDataError(u"Software license '%s' does not exist" % softwareLicenseId) hash = softwareLicenses[0].toHash() if isinstance(softwareLicenses[0], OEMSoftwareLicense): hash['licenseType'] = 'OEM' elif isinstance(softwareLicenses[0], RetailSoftwareLicense): hash['licenseType'] = 'RETAIL' elif isinstance(softwareLicenses[0], VolumeSoftwareLicense): hash['licenseType'] = 'VOLUME' elif isinstance(softwareLicenses[0], ConcurrentSoftwareLicense): hash['licenseType'] = 'CONCURRENT' # Cut time part, date only if hash['expirationDate']: hash['expirationDate'] = hash['expirationDate'].split(' ')[0] else: hash['expirationDate'] = u'' if not hash['boundToHost']: hash['boundToHost'] = u'' hash['softwareLicenseId'] = hash['id'] del hash['id'] del hash['type'] hash['licenseKeys'] = {} hash['licensePoolIds'] = [] for softwareLicenseToLicensePool in self.softwareLicenseToLicensePool_getObjects(softwareLicenseId = softwareLicenseId): hash['licensePoolIds'].append(softwareLicenseToLicensePool.getLicensePoolId()) if softwareLicenseToLicensePool.getLicenseKey(): hash['licenseKeys'][softwareLicenseToLicensePool.getLicensePoolId()] = softwareLicenseToLicensePool.getLicenseKey() return hash def getSoftwareLicenses_listOfHashes(self): softwareLicenses = [] for softwareLicense in self.softwareLicense_getObjects(): hash = softwareLicense.toHash() if isinstance(softwareLicense, OEMSoftwareLicense): hash['licenseType'] = 'OEM' elif isinstance(softwareLicense, RetailSoftwareLicense): hash['licenseType'] = 'RETAIL' elif isinstance(softwareLicense, VolumeSoftwareLicense): hash['licenseType'] = 'VOLUME' elif isinstance(softwareLicense, ConcurrentSoftwareLicense): hash['licenseType'] = 'CONCURRENT' # Cut time part, date only if hash['expirationDate']: hash['expirationDate'] = hash['expirationDate'].split(' ')[0] else: hash['expirationDate'] = u'' if not hash['boundToHost']: hash['boundToHost'] = u'' hash['softwareLicenseId'] = hash['id'] del hash['id'] del hash['type'] hash['licenseKeys'] = {} hash['licensePoolIds'] = [] for softwareLicenseToLicensePool in self.softwareLicenseToLicensePool_getObjects(softwareLicenseId = softwareLicense.getId()): hash['licensePoolIds'].append(softwareLicenseToLicensePool.getLicensePoolId()) if softwareLicenseToLicensePool.getLicenseKey(): hash['licenseKeys'][softwareLicenseToLicensePool.getLicensePoolId()] = softwareLicenseToLicensePool.getLicenseKey() softwareLicenses.append(hash) return softwareLicenses def deleteSoftwareLicense(self, softwareLicenseId, removeFromPools=False): if removeFromPools: self.softwareLicenseToLicensePool_delete(softwareLicenseId = softwareLicenseId) self.softwareLicense_delete(id = softwareLicenseId) def createLicensePool(self, licensePoolId="", description="", productIds=[], windowsSoftwareIds=[]): if not licensePoolId: # Generate license pool id import time knownLicensePoolIds = self.licensePool_getIdents(returnType = 'unicode') t = time.strftime('%Y-%m-%d_%H:%M:%S', time.localtime()) i=0 while True: licensePoolId = u'p_%s_%d' % (t, i) if not licensePoolId in knownLicensePoolIds: break i+=1 self.licensePool_create( id = licensePoolId, description = description, productIds = productIds) if windowsSoftwareIds: auditSoftwareToLicensePools = [] for auditSoftware in self.auditSoftware_getObjects(windowsSoftwareId = forceUnicodeList(windowsSoftwareIds)): auditSoftwareToLicensePools.append( AuditSoftwareToLicensePool( name = self.auditSoftware.name, version = self.auditSoftware.version, subVersion = self.auditSoftware.subVersion, language = self.auditSoftware.language, architecture = self.auditSoftware.architecture, licensePoolId = licensePoolId ) ) self.auditSoftwareToLicensePool_createObjects(auditSoftwareToLicensePools) poolIdents = self.licensePool_getIdents(id = licensePoolId, returnType = 'tuple') if not poolIdents: raise Exception(u"Failed to create license pool") return poolIdents[0][0] def getLicensePoolIds_list(self): return self.licensePool_getIdents(returnType = 'unicode') def getLicensePool_hash(self, licensePoolId): licensePools = self.licensePool_getObjects(id = licensePoolId) if not licensePools: raise BackendMissingDataError(u"License pool '%s' does not exist" % licensePoolId) hash = licensePools[0].toHash() hash['licensePoolId'] = hash['id'] del hash['id'] del hash['type'] hash['windowsSoftwareIds'] = [] for auditSoftwareToLicensePool in self.auditSoftwareToLicensePool_getObjects(licensePoolId = licensePools[0].id): auditSoftwares = self.auditSoftware_getObjects( ['windowsSoftwareId'], name = auditSoftwareToLicensePool.name, version = auditSoftwareToLicensePool.version, subVersion = auditSoftwareToLicensePool.subVersion, language = auditSoftwareToLicensePool.language, architecture = auditSoftwareToLicensePool.architecture, ) if not auditSoftwares: continue if not auditSoftwares[0].windowsSoftwareId: continue hash['windowsSoftwareIds'].append(auditSoftwares[0].windowsSoftwareId) return hash def getLicensePools_listOfHashes(self): licensePools = [] auditSoftwareToLicensePoolsByLicensePoolId = {} for auditSoftwareToLicensePool in self.auditSoftwareToLicensePool_getObjects(): if not auditSoftwareToLicensePoolsByLicensePoolId.has_key(auditSoftwareToLicensePool.licensePoolId): auditSoftwareToLicensePoolsByLicensePoolId[auditSoftwareToLicensePool.licensePoolId] = [] auditSoftwareToLicensePoolsByLicensePoolId[auditSoftwareToLicensePool.licensePoolId].append(auditSoftwareToLicensePool) for licensePool in self.licensePool_getObjects(): hash = licensePool.toHash() hash['licensePoolId'] = hash['id'] del hash['id'] del hash['type'] hash['windowsSoftwareIds'] = [] for auditSoftwareToLicensePool in auditSoftwareToLicensePoolsByLicensePoolId.get(licensePool.id, []): auditSoftwares = self.auditSoftware_getObjects( ['windowsSoftwareId'], name = auditSoftwareToLicensePool.name, version = auditSoftwareToLicensePool.version, subVersion = auditSoftwareToLicensePool.subVersion, language = auditSoftwareToLicensePool.language, architecture = auditSoftwareToLicensePool.architecture, ) if not auditSoftwares: continue if not auditSoftwares[0].windowsSoftwareId: continue hash['windowsSoftwareIds'].append(auditSoftwares[0].windowsSoftwareId) licensePools.append(hash) return licensePools def deleteLicensePool(self, licensePoolId, deleteLicenses=False): if deleteLicenses: for ident in self.softwareLicenseToLicensePool_getIdents(licensePoolId = licensePoolId, returnType = 'dict'): self.licenseOnClient_delete(softwareLicenseId = ident['softwareLicenseId'], licensePoolId = licensePoolId, clientId = []) self.softwareLicense_delete(ident['softwareLicenseId']) self.licensePool_delete(id = licensePoolId) def addSoftwareLicenseToLicensePool(self, softwareLicenseId, licensePoolId, licenseKey=""): self.softwareLicenseToLicensePool_create( softwareLicenseId = softwareLicenseId, licensePoolId = licensePoolId, licenseKey = licenseKey) def removeSoftwareLicenseFromLicensePool(self, softwareLicenseId, licensePoolId): self.softwareLicenseToLicensePool_delete( softwareLicenseId = softwareLicenseId, licensePoolId = licensePoolId) def addProductIdsToLicensePool(self, productIds, licensePoolId): productIds = forceUnicodeList(productIds) licensePools = self.licensePool_getObjects(id = licensePoolId) if not licensePools: raise BackendMissingDataError(u"License pool '%s' does not exist" % licensePoolId) productIds.extend(licensePools[0].getProductIds()) licensePools[0].setProductIds(productIds) self.licensePool_updateObject(licensePools[0]) def removeProductIdsFromLicensePool(self, productIds, licensePoolId): productIds = forceUnicodeList(productIds) licensePools = self.licensePool_getObjects(id = licensePoolId) if not licensePools: raise BackendMissingDataError(u"License pool '%s' does not exist" % licensePoolId) newProductIds = [] for productId in licensePools[0].getProductIds(): if not productId in productIds: newProductIds.append(productId) licensePools[0].setProductIds(newProductIds) self.licensePool_updateObject(licensePools[0]) def setWindowsSoftwareIdsToLicensePool(self, windowsSoftwareIds, licensePoolId): windowsSoftwareIds = forceUnicodeList(windowsSoftwareIds) licensePoolIds = self.licensePool_getIdents(id = licensePoolId, returnType = 'unicode') if not licensePoolIds: raise BackendMissingDataError(u"License pool '%s' does not exist" % licensePoolId) self.auditSoftwareToLicensePool_delete( name = [], version = [], subVersion = [], language = [], architecture = [], licensePoolId = licensePoolIds) auditSoftwareToLicensePools = [] for auditSoftware in self.auditSoftware_getObjects(windowsSoftwareId = forceUnicodeList(windowsSoftwareIds)): auditSoftwareToLicensePools.append( AuditSoftwareToLicensePool( name = auditSoftware.name, version = auditSoftware.version, subVersion = auditSoftware.subVersion, language = auditSoftware.language, architecture = auditSoftware.architecture, licensePoolId = licensePoolId ) ) self.auditSoftwareToLicensePool_createObjects(auditSoftwareToLicensePools) def getLicensePoolId(self, productId="", windowsSoftwareId=""): if not productId and not windowsSoftwareId: raise BackendBadValueError(u"Neither product id nor windows software id given.") idents = [] if productId: productId = forceProductId(productId) idents = self.licensePool_getIdents(productIds = productId, returnType = 'unicode') elif windowsSoftwareId: windowsSoftwareId = forceUnicode(windowsSoftwareId) auditSoftwares = self.auditSoftware_getObjects(windowsSoftwareId = windowsSoftwareId) for auditSoftware in auditSoftwares: auditSoftwareToLicensePools = self.auditSoftwareToLicensePool_getObjects( name = auditSoftware.name, version = auditSoftware.version, subVersion = auditSoftware.subVersion, language = auditSoftware.language, architecture = auditSoftware.architecture ) if auditSoftwareToLicensePools: idents.append(auditSoftwareToLicensePools[0].licensePoolId) if (len(idents) < 1): raise LicenseConfigurationError(u"No license pool for product id '%s', windowsSoftwareId '%s' found" % (productId, windowsSoftwareId)) elif (len(idents) > 1): raise LicenseConfigurationError(u"Multiple license pools for product id '%s', windowsSoftwareId '%s' found" % (productId, windowsSoftwareId)) return idents[0] def getOrCreateSoftwareLicenseUsage_hash(self, hostId, licensePoolId="", productId="", windowsSoftwareId=""): return self.licenseOnClient_getOrCreateObject( clientId = hostId, licensePoolId = licensePoolId, productId = productId, windowsSoftwareId = windowsSoftwareId).toHash() def getAndAssignSoftwareLicenseKey(self, hostId, licensePoolId="", productId="", windowsSoftwareId=""): licenseKey = '' try: if not licensePoolId: licensePoolId = self.getLicensePoolId(productId=productId, windowsSoftwareId=windowsSoftwareId) return self.getOrCreateSoftwareLicenseUsage_hash(hostId, licensePoolId, productId, windowsSoftwareId).get('licenseKey', '') except Exception as exception: logger.warning(u"Failed to get license key from license management for host '%s', pool '%s', product '%s', softwareid '%s': %s" \ % (hostId, licensePoolId, productId, windowsSoftwareId, exception)) # Trying the old way - product keys as product property if productId: properties = self.getProductProperties_hash(productId=productId, objectId=hostId) try: licenseKey = properties['productkey'] except KeyError: # No productkey found - we continue. pass if not licenseKey: raise exception return licenseKey def getLicenseKey(self, productId, clientId): ''' Returns an unused licensekey if available or the license key assigend to a specific client ! do not use ! deprecated ! ''' return self.getAndAssignSoftwareLicenseKey(hostId = clientId, productId = productId) def getSoftwareLicenseUsages_listOfHashes(self, hostIds=[], licensePoolIds=[]): if not hostIds: hostIds = [] if not licensePoolIds: licensePoolIds = [] licenseOnClients = [] for licenseOnClient in self.licenseOnClient_getObjects(licensePoolId = licensePoolIds, clientId = hostIds): hash = licenseOnClient.toHash() hash['hostId'] = hash['clientId'] if hash['licenseKey'] is None: hash['licenseKey'] = u'' if hash['notes'] is None: hash['notes'] = u'' del hash['clientId'] licenseOnClients.append(hash) return licenseOnClients def setSoftwareLicenseUsage(self, hostId, licensePoolId, softwareLicenseId, licenseKey="", notes=""): self.licenseOnClient_create( softwareLicenseId = softwareLicenseId, licensePoolId = licensePoolId, clientId = hostId, licenseKey = licenseKey, notes = notes) return { 'hostId' : hostId, 'softwareLicenseId': softwareLicenseId, 'licensePoolId' : licensePoolId } def deleteSoftwareLicenseUsage(self, hostId, softwareLicenseId="", licensePoolId="", productId="", windowsSoftwareId=""): if not softwareLicenseId: softwareLicenseId = None if not licensePoolId: licensePoolId = self.getLicensePoolId(productId = productId, windowsSoftwareId = windowsSoftwareId) self.licenseOnClient_delete( softwareLicenseId = softwareLicenseId, licensePoolId = licensePoolId, clientId = hostId) def deleteAllSoftwareLicenseUsages(self, hostIds): self.licenseOnClient_delete(clientId = hostIds) def getLicenseStatistics_hash(self): result = {} for licensePool in self.licensePool_getObjects(): poolId = licensePool.getId() licenses = 0 maxInstallations = 0 remainingInstallations = 0 additionalLicensePoolIds = set() for softwareLicenseToLicensePool in self.softwareLicenseToLicensePool_getObjects(licensePoolId=poolId): for softwareLicenseToLicensePool2 in self.softwareLicenseToLicensePool_getObjects(softwareLicenseId=softwareLicenseToLicensePool.getSoftwareLicenseId()): if softwareLicenseToLicensePool2.getLicensePoolId() == poolId: continue additionalLicensePoolIds.add(softwareLicenseToLicensePool2.getLicensePoolId()) licenses += 1 allowedInstallations = self.softwareLicense_getObjects(attributes=['maxInstallations'], id=softwareLicenseToLicensePool.getSoftwareLicenseId())[0].getMaxInstallations() if allowedInstallations == 0: maxInstallations = 'infinite' elif maxInstallations != 'infinite': maxInstallations += allowedInstallations usedBy = [licenseOnClient.getClientId() for licenseOnClient in self.licenseOnClient_getObjects(attributes=['clientId'], licensePoolId=poolId)] if maxInstallations == 'infinite': remainingInstallations = 'infinite' else: remainingInstallations = maxInstallations - len(usedBy) if additionalLicensePoolIds: poolIds = [additionalPoolId for additionalPoolId in additionalLicensePoolIds] licensesUsedByClientsInAdditionalPools = self.licenseOnClient_getIdents(licensePoolId=poolIds) remainingInstallations = remainingInstallations - len(licensesUsedByClientsInAdditionalPools) if remainingInstallations < 1: remainingInstallations = 0 result[poolId] = { 'licenses': licenses, 'usedBy': usedBy, 'usageCount': len(usedBy), 'maxInstallations': maxInstallations, 'remainingInstallations': remainingInstallations } return result def getMD5Sum(self, filename): return self.depot_getMD5Sum(filename) def librsyncSignature(self, filename): return self.depot_librsyncSignature(filename) def getDiskSpaceUsage(self, path): return self.depot_getDiskSpaceUsage(path) def getHostRSAPublicKey(self): return self.depot_getHostRSAPublicKey() def getPcpatchRSAPrivateKey(self): rsaPrivateKey = self.user_getCredentials(username = 'pcpatch')['rsaPrivateKey'] if not rsaPrivateKey: raise BackendMissingDataError(u"RSA private key not found") return rsaPrivateKey def getPcpatchPassword(self, hostId): return self.user_getCredentials(username = 'pcpatch', hostId = hostId)['password'] def setPcpatchPassword(self, hostId, password): if not hostId in self.getDepotIds_list(): return return self.user_setCredentials(username = 'pcpatch', password = password) def userIsAdmin(self): if self.accessControl_userIsAdmin(): return True raise Exception(u"User not admin") def areDepotsSynchronous(self, depotIds=[]): depotIds = self.host_getIdents(type = 'OpsiDepotserver', id = depotIds, returnType = 'unicode') if not depotIds: raise Excpetion(u"No depots found") if (len(depotIds) == 1): return True lastIdent = '' for i, currentDepot in enumerate(depotIds): idents = [] for ident in self.productOnDepot_getIdents(depotId=currentDepot, returnType='dict'): idents.append(u'%s;%s;%s' % (ident['productId'], ident['productVersion'], ident['packageVersion'])) idents.sort() ident = u'|'.join(idents) if (i > 0) and (ident != lastIdent): return False lastIdent = ident return True def setHostInventoryNumber(self, hostId, inventoryNumber): hostId = forceHostId(hostId) hosts = self.host_getObjects(id=hostId) if not hosts: raise BackendMissingDataError(u"Host {0!r} not found".format(hostId)) host = hosts[0] host.setInventoryNumber(inventoryNumber) self.host_updateObject(host)