コード例 #1
0
    def uninstallPackage(self, productId, force=False, deleteFiles=True):
        depotId = self._depotBackend._depotId
        logger.info(
            u"================================================================================================="
        )
        logger.notice(u"Uninstalling product '%s' on depot '%s'" %
                      (productId, depotId))
        try:
            productId = forceProductIdFunc(productId)
            force = forceBool(force)
            deleteFiles = forceBool(deleteFiles)

            dataBackend = self._depotBackend._context
            depot = dataBackend.host_getObjects(type='OpsiDepotserver',
                                                id=depotId)[0]
            productOnDepots = dataBackend.productOnDepot_getObjects(
                depotId=depotId, productId=productId)
            try:
                productOnDepot = productOnDepots[0]
            except IndexError:
                raise BackendBadValueError(
                    "Product '%s' is not installed on depot '%s'" %
                    (productId, depotId))

            if productOnDepot.getLocked():
                logger.notice(u"Product '{}' currently locked on depot '{}'",
                              productId, depotId)
                if not force:
                    raise BackendTemporaryError(
                        u"Product '%s' currently locked on depot '%s'" %
                        (productId, depotId))
                logger.warning(u"Uninstallation of locked product forced")

            logger.notice(u"Locking product '%s' on depot '%s'" %
                          (productId, depotId))
            productOnDepot.setLocked(True)
            dataBackend.productOnDepot_updateObject(productOnDepot)

            logger.debug("Deleting product '{}'", productId)

            if deleteFiles:
                if not depot.depotLocalUrl.startswith('file:///'):
                    raise BackendBadValueError(
                        u"Value '%s' not allowed for depot local url (has to start with 'file:///')"
                        % depot.depotLocalUrl)

                for element in os.listdir(depot.depotLocalUrl[7:]):
                    if element.lower() == productId.lower():
                        clientDataDir = os.path.join(depot.depotLocalUrl[7:],
                                                     element)
                        logger.info("Deleting client data dir '{}'",
                                    clientDataDir)
                        removeDirectory(clientDataDir)

            dataBackend.productOnDepot_deleteObjects(productOnDepot)
        except Exception as uninstallError:
            logger.logException(uninstallError)
            raise BackendError(
                u"Failed to uninstall product '%s' on depot '%s': %s" %
                (productId, depotId, uninstallError))
コード例 #2
0
ファイル: __init__.py プロジェクト: mpice-mn/python-opsi
    def create(self, fileList, baseDir='.', dereference=False):
        try:
            fileList = forceUnicodeList(fileList)
            baseDir = os.path.abspath(forceFilename(baseDir))
            dereference = forceBool(dereference)

            if not os.path.isdir(baseDir):
                raise IOError(u"Base dir '%s' not found" % baseDir)

            command = u'%s --create --quiet --verbose --format crc' % System.which(
                'cpio')
            if dereference:
                command += ' --dereference'
            if self._compression == 'gzip':
                if self.pigz_detected:
                    command += ' | %s --rsyncable' % System.which('pigz')
                else:
                    command += ' | %s --rsyncable' % System.which('gzip')
            elif self._compression == 'bzip2':
                command += ' | %s' % System.which('bzip2')
            command += ' > "%s"' % self._filename

            self._create(fileList, baseDir, command)
        except Exception as e:
            raise RuntimeError(u"Failed to create archive '%s': %s" %
                               (self._filename, e))
コード例 #3
0
    def __init__(self, id, type=u'', title=u'', **args):
        MessageSubject.__init__(self, id, type, title, **args)
        self.reset()
        self._callbacks = []
        try:
            self._multiValue = forceBool(args['multiValue'])
        except KeyError:
            pass

        try:
            self._choices = forceUnicodeList(args['choices'])
        except KeyError:
            pass

        try:
            self._selectedIndexes = forceIntList(args['selectedIndexes'])
        except KeyError:
            pass

        try:
            self._callbacks = args['callbacks']
        except KeyError:
            pass

        logger.debug(u"ChoiceSubject '%s' created" % self._id)
コード例 #4
0
    def setBlockLogin(self, blockLogin, handleNotifier=True):  # pylint: disable=too-many-branches
        blockLogin = forceBool(blockLogin)
        changed = self._blockLogin != blockLogin
        self._blockLogin = blockLogin
        logger.notice("Block login now set to '%s'", self._blockLogin)

        if self._blockLogin:
            if not self._blockLoginEventId:
                self._blockLoginEventId = timeline.addEvent(
                    title="Blocking login",
                    description="User login blocked",
                    category="block_login",
                    durationEvent=True)

            if not self._blockLoginNotifierPid and config.get(
                    'global', 'block_login_notifier'):
                if handleNotifier and RUNNING_ON_WINDOWS:
                    logger.info("Starting block login notifier app")
                    # Start block login notifier on physical console
                    sessionId = System.getActiveConsoleSessionId()
                    while True:
                        try:
                            self._blockLoginNotifierPid = System.runCommandInSession(
                                command=config.get('global',
                                                   'block_login_notifier'),
                                sessionId=sessionId,
                                desktop='winlogon',
                                waitForProcessEnding=False)[2]
                            break
                        except Exception as err:  # pylint: disable=broad-except
                            logger.error(
                                "Failed to start block login notifier app: %s",
                                err)
                            break
        else:
            if self._blockLoginEventId:
                timeline.setEventEnd(eventId=self._blockLoginEventId)
                self._blockLoginEventId = None

            if handleNotifier and self._blockLoginNotifierPid:
                try:
                    logger.info(
                        "Terminating block login notifier app (pid %s)",
                        self._blockLoginNotifierPid)
                    System.terminateProcess(
                        processId=self._blockLoginNotifierPid)
                except Exception as err:  # pylint: disable=broad-except
                    logger.warning(
                        "Failed to terminate block login notifier app: %s",
                        err)
                self._blockLoginNotifierPid = None

        if changed and self._controlPipe:
            try:
                self._controlPipe.executeRpc("blockLogin", self._blockLogin)
            except Exception as rpc_error:  # pylint: disable=broad-except
                logger.debug(rpc_error)
コード例 #5
0
ファイル: Timeline.py プロジェクト: opsi-org/opsiclientd
    def addEvent(self,
                 title,
                 description='',
                 isError=False,
                 category=None,
                 durationEvent=False,
                 start=None,
                 end=None):  # pylint: disable=too-many-arguments
        if self._stopped:
            return -1

        with self._db_lock, self._sql.session() as session:
            try:
                if category:
                    category = forceUnicode(category)
                if not start:
                    start = timestamp()
                start = forceOpsiTimestamp(start)

                if end:
                    end = forceOpsiTimestamp(end)
                    durationEvent = True

                event = {
                    'title': forceUnicode(title),
                    'category': category,
                    'description': forceUnicode(description),
                    'isError': forceBool(isError),
                    'durationEvent': forceBool(durationEvent),
                    'start': start,
                    'end': end,
                }
                try:
                    return self._sql.insert(session, 'EVENT', event)
                except sqlite3.DatabaseError as db_error:
                    logger.error(
                        "Failed to add event '%s': %s, recreating database",
                        title, db_error)
                    self._sql.delete_db()
                    self._createDatabase(delete_existing=True)
                    return self._sql.insert(session, 'EVENT', event)
            except Exception as add_error:  # pylint: disable=broad-except
                logger.error("Failed to add event '%s': %s", title, add_error)
        return -1
コード例 #6
0
ファイル: JSONRPC.py プロジェクト: mpice-mn/python-opsi
    def setDeflate(self, deflate):
        if not self._connected:
            raise OpsiConnectionError(u'Not connected')

        logger.warning("Call to deprecated method 'setDeflate'. "
                       "This method will be removed in the future. "
                       "Please use the method 'setCompression' instead.")

        if forceBool(deflate):
            self.setCompression('deflate')
        else:
            self.setCompression(False)
コード例 #7
0
    def __init__(self, id, type=u'', title=u'', **args):
        MessageSubject.__init__(self, id, type, title, **args)
        self.reset()
        self._fireAlways = True
        self._endChangable = True
        try:
            self._end = forceInt(args['end'])
            if self._end < 0:
                self._end = 0
        except KeyError:
            pass

        try:
            self._percent = args['percent']
        except KeyError:
            pass

        try:
            self._state = args['state']
        except KeyError:
            pass

        try:
            self._timeStarted = args['timeStarted']
        except KeyError:
            pass

        try:
            self._timeSpend = args['timeSpend']
        except KeyError:
            pass

        try:
            self._timeLeft = args['timeLeft']
        except KeyError:
            pass

        try:
            self._timeFired = args['timeFired']
        except KeyError:
            pass

        try:
            self._speed = args['speed']
        except KeyError:
            pass

        try:
            self._fireAlways = forceBool(args['fireAlways'])
        except KeyError:
            pass

        logger.debug(u"ProgressSubject {0!r} created", self._id)
コード例 #8
0
    def isShutdownRequested(self):
        try:
            shutdownRequested = System.getRegistryValue(
                System.HKEY_LOCAL_MACHINE, "SOFTWARE\\opsi.org\\winst",
                "ShutdownRequested")
        except Exception as err:  # pylint: disable=broad-except
            logger.info("Failed to get shutdownRequested from registry: %s",
                        err)
            shutdownRequested = 0

        logger.notice("Shutdown request in Registry: %s", shutdownRequested)
        return forceBool(shutdownRequested)
コード例 #9
0
ファイル: DHCPD.py プロジェクト: mpice-mn/python-opsi
    def __init__(self, **kwargs):
        self._name = 'dhcpd'

        ConfigDataBackend.__init__(self, **kwargs)

        self._dhcpdConfigFile = System.Posix.locateDHCPDConfig(
            u'/etc/dhcp3/dhcpd.conf')
        self._reloadConfigCommand = '/usr/bin/sudo {command}'.format(
            command=System.Posix.getDHCPDRestartCommand(
                default='/etc/init.d/dhcp3-server restart'))

        self._fixedAddressFormat = u'IP'
        self._defaultClientParameters = {
            'next-server': socket.gethostbyname(getfqdn()),
            'filename': u'linux/pxelinux.0'
        }
        self._dhcpdOnDepot = False

        # Parse arguments
        for (option, value) in kwargs.items():
            option = option.lower()
            if option == 'dhcpdconfigfile':
                self._dhcpdConfigFile = value
            elif option == 'reloadconfigcommand':
                self._reloadConfigCommand = value
            elif option == 'defaultclientparameters':
                self._defaultClientParameters = forceDict(value)
            elif option == 'fixedaddressformat':
                if value not in (u'IP', u'FQDN'):
                    raise BackendBadValueError(
                        u"Bad value '%s' for fixedAddressFormat, possible values are %s"
                        % (value, u', '.join(('IP', 'FQDN'))))
                self._fixedAddressFormat = value
            elif option == 'dhcpdondepot':
                self._dhcpdOnDepot = forceBool(value)

        if self._defaultClientParameters.get(
                'next-server'
        ) and self._defaultClientParameters['next-server'].startswith(u'127'):
            raise BackendBadValueError(
                u"Refusing to use ip address '%s' as default next-server" %
                self._defaultClientParameters['next-server'])

        self._dhcpdConfFile = DHCPDConfFile(self._dhcpdConfigFile)
        self._reloadEvent = threading.Event()
        self._reloadEvent.set()
        self._reloadLock = threading.Lock()
        self._reloadThread = None
        self._depotId = forceHostId(getfqdn())
        self._opsiHostKey = None
        self._depotConnections = {}
コード例 #10
0
ファイル: HostControl.py プロジェクト: mpice-mn/python-opsi
def _configureHostcontrolBackend(backend, kwargs):
    """
	Configure `backend` to the values given in `kwargs`.

	Keys in `kwargs` will be treated as lowercase.
	Supported keys are 'broadcastaddresses', 'hostrpctimeout', \
'maxconnections' opsiclientdport' and 'resolvehostaddress'.
	Unrecognized options will be ignored.

	:type backend: HostControlBackend or HostControlSafeBackend
	:type kwargs: dict
	"""
    for option, value in kwargs.items():
        option = option.lower()
        if option == 'opsiclientdport':
            backend._opsiclientdPort = forceInt(value)
        elif option == 'hostrpctimeout':
            backend._hostRpcTimeout = forceInt(value)
        elif option == 'resolvehostaddress':
            backend._resolveHostAddress = forceBool(value)
        elif option == 'maxconnections':
            backend._maxConnections = forceInt(value)
        elif option == 'broadcastaddresses':
            try:
                backend._broadcastAddresses = forceDict(value)
            except ValueError:
                # This is an old-style configuraton. Old default
                # port was 12287 so we assume this as the default
                # and convert everything to the new format.
                backend._broadcastAddresses = {
                    bcAddress: (12287, )
                    for bcAddress in forceUnicodeList(value)
                }
                logger.warning(
                    "Your hostcontrol backend configuration uses the old "
                    "format for broadcast addresses. The new format "
                    "allows to also set a list of ports to send the "
                    "broadcast to.\nPlease use this new "
                    "value in the future: {0!r}", backend._broadcastAddresses)

            newAddresses = {
                bcAddress: tuple(forceInt(port) for port in ports)
                for bcAddress, ports in backend._broadcastAddresses.items()
            }
            backend._broadcastAddresses = newAddresses

    if backend._maxConnections < 1:
        backend._maxConnections = 1
コード例 #11
0
ファイル: JSONRPC.py プロジェクト: mpice-mn/python-opsi
    def _parseCompressionValue(compression):
        if isinstance(compression, bool):
            return compression
        else:
            value = forceUnicode(compression)
            value = value.strip()
            value = value.lower()

            if value in ('true', 'false'):
                return forceBool(value)
            elif value == 'gzip':
                return _GZIP_COMPRESSION
            elif value == 'deflate':
                return _DEFLATE_COMPRESSION
            else:
                return False
コード例 #12
0
    def __init__(self, **kwargs):
        self._database = ":memory:"
        self._synchronous = True
        self._databaseCharset = 'utf8'
        for (option, value) in kwargs.items():
            option = option.lower()
            if option == 'database':
                self._database = forceFilename(value)
            elif option == 'synchronous':
                self._synchronous = forceBool(value)
            elif option == 'databasecharset':
                self._databaseCharset = str(value)

        self._connection = None
        self._cursor = None
        logger.debug(u'SQLite created: %s' % self)
コード例 #13
0
    def isRebootRequested(self):
        try:
            rebootRequested = System.getRegistryValue(
                System.HKEY_LOCAL_MACHINE, "SOFTWARE\\opsi.org\\winst",
                "RebootRequested")
        except Exception as error:  # pylint: disable=broad-except
            logger.warning("Failed to get RebootRequested from registry: %s",
                           error)
            rebootRequested = 0

        logger.notice("Reboot request in Registry: %s", rebootRequested)
        if rebootRequested == 2:
            # Logout
            logger.info("Logout requested")
            self.clearRebootRequest()
            return False

        return forceBool(rebootRequested)
コード例 #14
0
    def depot_getMD5Sum(self, filename, forceCalculation=False):
        checksum = None
        try:
            if not forceBool(forceCalculation):
                hashFile = filename + '.md5'

                try:
                    with open(hashFile) as fileHandle:
                        checksum = fileHandle.read()

                    logger.info(u"Using pre-calculated MD5sum from '{0}'.",
                                hashFile)
                except (OSError, IOError):
                    pass

            if not checksum:
                checksum = md5sum(filename)

            logger.info(u"MD5sum of file '{0}' is '{1}'", filename, checksum)
            return checksum
        except Exception as error:
            raise BackendIOError(u"Failed to get md5sum: %s" % error)
コード例 #15
0
    def __init__(self,
                 name,
                 baseUrl,
                 dirs=[],
                 username=u"",
                 password=u"",
                 authcertfile=u"",
                 authkeyfile="",
                 opsiDepotId=None,
                 autoInstall=False,
                 autoUpdate=True,
                 autoSetup=False,
                 proxy=None,
                 excludes=[],
                 includes=[],
                 active=False):
        self.name = forceUnicode(name)
        self.baseUrl = forceUnicode(baseUrl)
        self.dirs = forceUnicodeList(dirs)
        self.excludes = excludes
        self.includes = includes
        self.username = forceUnicode(username)
        self.password = forceUnicode(password)
        self.authcertfile = forceUnicode(authcertfile)
        self.authkeyfile = forceUnicode(authkeyfile)
        self.autoInstall = autoInstall
        self.autoUpdate = autoUpdate
        self.autoSetup = autoSetup
        self.opsiDepotId = opsiDepotId
        self.onlyDownload = None
        self.inheritProductProperties = None
        self.description = ''
        self.active = forceBool(active)

        self.proxy = None
        if proxy:
            self.proxy = proxy
        if self.baseUrl.startswith('webdav'):
            self.baseUrl = u'http%s' % self.baseUrl[6:]
コード例 #16
0
ファイル: State.py プロジェクト: opsi-org/opsiclientd
    def get(self, name, default=None):  # pylint: disable=too-many-return-statements,too-many-branches
        name = forceUnicode(name)
        if name == 'user_logged_in':
            if RUNNING_ON_WINDOWS:
                for session in System.getActiveSessionInformation():
                    if session["UserName"] != OPSI_SETUP_USER_NAME:
                        return True
                return False
            if RUNNING_ON_LINUX:
                for proc in psutil.process_iter():
                    try:
                        env = proc.environ()
                        if env.get("DISPLAY") and proc.uids()[0] >= 1000:
                            return True
                    except psutil.AccessDenied:
                        pass
                return False
            if RUNNING_ON_DARWIN:
                # TODO
                return True
            return False
        if name == 'products_cached':
            return self._state.get('product_cache_service',
                                   {}).get('products_cached', default)
        if name == 'config_cached':
            return self._state.get('config_cache_service',
                                   {}).get('config_cached', default)
        if "cancel_counter" in name:
            return self._state.get(name, 0)
        if name == 'installation_pending':
            return forceBool(self._state.get('installation_pending', False))

        try:
            return self._state[name]
        except KeyError:
            logger.warning("Unknown state name '%s', returning default '%s'",
                           name, default)
            return default
コード例 #17
0
ファイル: Replicator.py プロジェクト: mpice-mn/python-opsi
    def __init__(self,
                 readBackend,
                 writeBackend,
                 newServerId=None,
                 oldServerId=None,
                 cleanupFirst=True):
        self.__readBackend = readBackend
        self.__writeBackend = writeBackend

        self._extendedReadBackend = ExtendedConfigDataBackend(
            self.__readBackend)
        self._extendedWriteBackend = ExtendedConfigDataBackend(
            self.__writeBackend)

        self.__newServerId = None
        self.__oldServerId = None

        self.__cleanupFirst = forceBool(cleanupFirst)
        self.__strict = False
        self.__serverIds = []
        self.__depotIds = []
        self.__clientIds = []
        self.__groupIds = []
        self.__productIds = []

        if newServerId:
            self.__newServerId = forceHostId(newServerId)
        if oldServerId:
            self.__oldServerId = forceHostId(oldServerId)

        self.__overallProgressSubject = ProgressSubject(
            id=u'overall_replication',
            title=u'Replicating',
            end=100,
            fireAlways=True)
        self.__currentProgressSubject = ProgressSubject(
            id=u'current_replication', fireAlways=True)
コード例 #18
0
ファイル: JSONRPC.py プロジェクト: mpice-mn/python-opsi
    def __init__(self, address, **kwargs):
        """
		Backend for JSON-RPC access to another opsi service.

		:param compression: Specify compression usage. Can be a boolean \
or the strings 'gzip' or 'deflate' in case a specific compression is desired.
		:type compression: bool or str
		:param deflate: Specify if deflate compression should be used for requests. \
Deprecated: Use keyword 'compression' instead.
		:type deflate: bool
		"""

        self._name = 'jsonrpc'

        Backend.__init__(self, **kwargs)

        self._application = 'opsi jsonrpc module version %s' % __version__
        self._sessionId = None
        self._compression = False
        self._connectOnInit = True
        self._connected = False
        self._retryTime = 5
        self._host = None
        self._port = None
        self._baseUrl = u'/rpc'
        self._protocol = 'https'
        self._socketTimeout = None
        self._connectTimeout = 30
        self._connectionPoolSize = 2
        self._interface = None
        self._rpcId = 0
        self._rpcIdLock = threading.Lock()
        self._async = False
        self._rpcQueue = None
        self._rpcQueuePollingTime = 0.01
        self._rpcQueueSize = 10
        self._serverCertFile = None
        self._caCertFile = None
        self._verifyServerCert = False
        self._verifyServerCertByCa = False
        self._verifyByCaCertsFile = None
        self._proxyURL = None

        if not self._username:
            self._username = u''
        if not self._password:
            self._password = u''

        retry = True
        for (option, value) in kwargs.items():
            option = option.lower()
            if option == 'application':
                self._application = str(value)
            elif option == 'sessionid':
                self._sessionId = str(value)
            elif option == 'deflate':
                if forceBool(value):
                    self.setCompression('deflate')
                else:
                    self.setCompression(False)
            elif option == 'compression':
                self._compression = self._parseCompressionValue(value)
            elif option == 'connectoninit':
                self._connectOnInit = forceBool(value)
            elif option == 'connecttimeout' and value is not None:
                self._connectTimeout = forceInt(value)
            elif option == 'connectionpoolsize' and value is not None:
                self._connectionPoolSize = forceInt(value)
            elif option in ('timeout', 'sockettimeout') and value is not None:
                self._socketTimeout = forceInt(value)
            elif option == 'retry':
                retry = forceBool(value)
            elif option == 'retrytime':
                self._retryTime = forceInt(value)
            elif option == 'rpcqueuepollingtime':
                self._rpcQueuePollingTime = forceFloat(value)
            elif option == 'rpcqueuesize':
                self._rpcQueueSize = forceInt(value)
            elif option == 'servercertfile' and value is not None:
                self._serverCertFile = forceFilename(value)
            elif option == 'verifyservercert':
                self._verifyServerCert = forceBool(value)
            elif option == 'cacertfile' and value is not None:
                self._caCertFile = forceFilename(value)
            elif option == 'verifyservercertbyca':
                self._verifyServerCertByCa = forceBool(value)
            elif option == 'proxyurl' and value is not None:
                logger.debug(u"ProxyURL detected: '%s'" % value)
                self._proxyURL = forceUnicode(value)

        if not retry:
            self._retryTime = 0

        if self._password:
            logger.addConfidentialString(self._password)

        self._processAddress(address)
        self._connectionPool = getSharedConnectionPool(
            scheme=self._protocol,
            host=self._host,
            port=self._port,
            socketTimeout=self._socketTimeout,
            connectTimeout=self._connectTimeout,
            retryTime=self._retryTime,
            maxsize=self._connectionPoolSize,
            block=True,
            verifyServerCert=self._verifyServerCert,
            serverCertFile=self._serverCertFile,
            caCertFile=self._caCertFile,
            verifyServerCertByCa=self._verifyServerCertByCa,
            proxyURL=self._proxyURL)

        if self._connectOnInit:
            self.connect()
コード例 #19
0
	def __init__(self, prior, posterior, fulfilled=False):
		self.prior = forceInt(prior)
		self.posterior = forceInt(posterior)
		self.fulfilled = forceBool(fulfilled)
コード例 #20
0
ファイル: Product.py プロジェクト: mpice-mn/python-opsi
    def __init__(self,
                 packageSourceDir,
                 tempDir=None,
                 customName=None,
                 customOnly=False,
                 packageFileDestDir=None,
                 format='cpio',
                 compression='gzip',
                 dereference=False):
        self.packageSourceDir = os.path.abspath(
            forceFilename(packageSourceDir))
        if not os.path.isdir(self.packageSourceDir):
            raise IOError(u"Package source directory '%s' not found" %
                          self.packageSourceDir)

        tempDir = tempDir or DEFAULT_TMP_DIR
        self.tempDir = os.path.abspath(forceFilename(tempDir))
        if not os.path.isdir(self.tempDir):
            raise IOError(u"Temporary directory '%s' not found" % self.tempDir)

        self.customName = None
        if customName:
            self.customName = forcePackageCustomName(customName)

        self.customOnly = forceBool(customOnly)

        if format:
            if format not in (u'cpio', u'tar'):
                raise ValueError(u"Format '%s' not supported" % format)
            self.format = format
        else:
            self.format = u'cpio'

        if not compression:
            self.compression = None
        else:
            if compression not in (u'gzip', u'bzip2'):
                raise ValueError(u"Compression '%s' not supported" %
                                 compression)
            self.compression = compression

        self.dereference = forceBool(dereference)

        if not packageFileDestDir:
            packageFileDestDir = self.packageSourceDir
        packageFileDestDir = os.path.abspath(forceFilename(packageFileDestDir))
        if not os.path.isdir(packageFileDestDir):
            raise IOError(u"Package destination directory '%s' not found" %
                          packageFileDestDir)

        packageControlFile = os.path.join(self.packageSourceDir, u'OPSI',
                                          u'control')
        if customName and os.path.exists(
                os.path.join(self.packageSourceDir, u'OPSI.%s' % customName,
                             u'control')):
            packageControlFile = os.path.join(self.packageSourceDir,
                                              u'OPSI.%s' % customName,
                                              u'control')
        self.packageControlFile = PackageControlFile(packageControlFile)
        self.packageControlFile.parse()

        customName = u''
        if self.customName:
            customName = u'~%s' % self.customName
        self.packageFile = os.path.join(
            packageFileDestDir, u"%s_%s-%s%s.opsi" %
            (self.packageControlFile.getProduct().id,
             self.packageControlFile.getProduct().productVersion,
             self.packageControlFile.getProduct().packageVersion, customName))

        self.tmpPackDir = os.path.join(self.tempDir,
                                       u'.opsi.pack.%s' % randomString(5))
コード例 #21
0
def findFiles(directory,
              prefix=u'',
              excludeDir=None,
              excludeFile=None,
              includeDir=None,
              includeFile=None,
              returnDirs=True,
              returnLinks=True,
              followLinks=False,
              repository=None):
    directory = forceFilename(directory)
    prefix = forceUnicode(prefix)

    if excludeDir:
        if not isRegularExpressionPattern(excludeDir):
            excludeDir = re.compile(forceUnicode(excludeDir))
    else:
        excludeDir = None

    if excludeFile:
        if not isRegularExpressionPattern(excludeFile):
            excludeFile = re.compile(forceUnicode(excludeFile))
    else:
        excludeFile = None

    if includeDir:
        if not isRegularExpressionPattern(includeDir):
            includeDir = re.compile(forceUnicode(includeDir))
    else:
        includeDir = None

    if includeFile:
        if not isRegularExpressionPattern(includeFile):
            includeFile = re.compile(forceUnicode(includeFile))
    else:
        includeFile = None

    returnDirs = forceBool(returnDirs)
    returnLinks = forceBool(returnLinks)
    followLinks = forceBool(followLinks)

    if repository:
        islink = repository.islink
        isdir = repository.isdir
        listdir = repository.listdir
    else:
        islink = os.path.islink
        isdir = os.path.isdir
        listdir = os.listdir

    files = []
    for entry in listdir(directory):
        if isinstance(entry, str):  # TODO how to handle this with Python 3?
            logger.error(
                u"Bad filename '%s' found in directory '%s', skipping entry!" %
                (unicode(entry, 'ascii', 'replace'), directory))
            continue
        pp = os.path.join(prefix, entry)
        dp = os.path.join(directory, entry)
        isLink = False
        if islink(dp):
            isLink = True
            if not returnLinks and not followLinks:
                continue
        if isdir(dp) and (not isLink or followLinks):
            if excludeDir and re.search(excludeDir, entry):
                logger.debug(u"Excluding dir '%s' and containing files" %
                             entry)
                continue
            if includeDir:
                if not re.search(includeDir, entry):
                    continue
                logger.debug(u"Including dir '%s' and containing files" %
                             entry)
            if returnDirs:
                files.append(pp)
            files.extend(
                findFiles(directory=dp,
                          prefix=pp,
                          excludeDir=excludeDir,
                          excludeFile=excludeFile,
                          includeDir=includeDir,
                          includeFile=includeFile,
                          returnDirs=returnDirs,
                          returnLinks=returnLinks,
                          followLinks=followLinks,
                          repository=repository))
            continue

        if excludeFile and re.search(excludeFile, entry):
            if isLink:
                logger.debug(u"Excluding link '%s'" % entry)
            else:
                logger.debug(u"Excluding file '%s'" % entry)
            continue

        if includeFile:
            if not re.search(includeFile, entry):
                continue
            if isLink:
                logger.debug(u"Including link '%s'" % entry)
            else:
                logger.debug(u"Including file '%s'" % entry)
        files.append(pp)
    return files
コード例 #22
0
    def __init__(self,
                 host,
                 port,
                 socketTimeout=None,
                 connectTimeout=None,
                 retryTime=0,
                 maxsize=1,
                 block=False,
                 reuseConnection=False,
                 verifyServerCert=False,
                 serverCertFile=None,
                 caCertFile=None,
                 verifyServerCertByCa=False,
                 proxyURL=None):

        self.host = forceUnicode(host)
        self.port = forceInt(port)
        self.socketTimeout = forceInt(socketTimeout or 0)
        self.connectTimeout = forceInt(connectTimeout or 0)
        self.retryTime = forceInt(retryTime)
        self.block = forceBool(block)
        self.reuseConnection = forceBool(reuseConnection)
        self.proxyURL = forceUnicode(proxyURL or u"")
        self.pool = None
        self.usageCount = 1
        self.num_connections = 0
        self.num_requests = 0
        self.httplibDebugLevel = 0
        self.peerCertificate = None
        self.serverVerified = False
        self.verifyServerCert = False
        self.serverCertFile = None
        self.caCertFile = None
        self.verifyServerCertByCa = False

        if isinstance(self, HTTPSConnectionPool):
            if self.host in ('localhost', '127.0.0.1'):
                self.serverVerified = True
                logger.debug(u"No host verification for localhost")
            else:
                if caCertFile:
                    self.caCertFile = forceFilename(caCertFile)
                self.verifyServerCertByCa = forceBool(verifyServerCertByCa)

                if self.verifyServerCertByCa:
                    if not self.caCertFile:
                        raise ValueError(
                            u"Server certificate verfication by CA enabled but no CA cert file given"
                        )
                    logger.info(
                        u"Server certificate verfication by CA file '%s' enabled for host '%s'"
                        % (self.caCertFile, self.host))
                else:
                    self.verifyServerCert = forceBool(verifyServerCert)
                    if serverCertFile:
                        self.serverCertFile = forceFilename(serverCertFile)
                    if self.verifyServerCert:
                        if not self.serverCertFile:
                            raise ValueError(
                                u"Server verfication enabled but no server cert file given"
                            )
                        logger.info(
                            u"Server verfication by server certificate enabled for host '%s'"
                            % self.host)
        self.adjustSize(maxsize)
コード例 #23
0
def testForceBoolWithTrueValues(value):
    assert forceBool(value) is True
コード例 #24
0
ファイル: Replicator.py プロジェクト: mpice-mn/python-opsi
    def replicate(self,
                  serverIds=[],
                  depotIds=[],
                  clientIds=[],
                  groupIds=[],
                  productIds=[],
                  productTypes=[],
                  audit=True,
                  license=True):
        '''
		Replicate (a part) of a opsi configuration database
		An empty list passed as a param means: replicate all known
		None as the only element of a list means: replicate none
		'''
        serverIds = forceList(serverIds)
        depotIds = forceList(depotIds)
        clientIds = forceList(clientIds)
        groupIds = forceList(serverIds)
        productIds = forceList(productIds)
        productTypes = forceList(productTypes)
        audit = forceBool(audit)
        license = forceBool(license)

        logger.info(
            u"Replicating: serverIds={serverIds}, depotIds={depotIds}, "
            u"clientIds={clientIds}, groupIds={groupIds}, "
            u"productIds={productIds}, productTypes={productTypes}, "
            u"audit: {audit}, license: {license}".format(**locals()))

        rb = self._extendedReadBackend
        wb = self.__writeBackend
        aric = wb.backend_getOptions().get(
            'additionalReferentialIntegrityChecks', True)
        if self.__strict:
            wb = self._extendedWriteBackend
        else:
            wb.backend_setOptions(
                {'additionalReferentialIntegrityChecks': False})

        try:
            if serverIds or depotIds or clientIds:
                if not serverIds:
                    serverIds = rb.host_getIdents(type='OpsiConfigserver',
                                                  returnType=list)
                if not depotIds:
                    depotIds = rb.host_getIdents(type='OpsiDepotserver',
                                                 returnType=list)
                if not clientIds:
                    clientIds = rb.host_getIdents(type='OpsiClient',
                                                  returnType=list)

            hostIds = set()
            for serverId in serverIds:
                hostIds.add(serverId)

            for depotId in depotIds:
                hostIds.add(depotId)

            for clientId in clientIds:
                hostIds.add(clientId)

            self.__overallProgressSubject.reset()
            end = self._getNumberOfObjectClassesToProcess(audit, license)
            if self.__cleanupFirst:
                end += 1
            if self.__newServerId:
                end += 1
            self.__overallProgressSubject.setEnd(end)

            if self.__cleanupFirst:
                wb.backend_deleteBase()
                self.__overallProgressSubject.addToState(1)

            wb.backend_createBase()

            productOnDepots = []
            if depotIds:
                productOnDepots = rb.productOnDepot_getObjects(
                    depotId=depotIds,
                    productId=productIds,
                    productType=productTypes)
                productIdsOnDepot = set()
                for productOnDepot in productOnDepots:
                    productIdsOnDepot.add(productOnDepot.productId)

                if productIdsOnDepot:
                    if not productIds:
                        productIds = list(productIdsOnDepot)
                    else:
                        newProductIds = []
                        for productId in productIds:
                            if productId in productIdsOnDepot:
                                newProductIds.append(productId)
                        productIds = newProductIds

            auditClasses = set([
                'AuditHardware', 'AuditSoftware', 'AuditHardwareOnHost',
                'AuditSoftwareOnClient'
            ])
            licenseClasses = set([
                'LicenseContract', 'SoftwareLicense', 'LicensePool',
                'SoftwareLicenseToLicensePool', 'LicenseOnClient',
                'AuditSoftwareToLicensePool'
            ])

            configServer = None
            depotServers = []
            for objClass in self.OBJECT_CLASSES:
                if not audit and objClass in auditClasses:
                    continue
                if not license and objClass in licenseClasses:
                    continue

                subClasses = [None]
                if objClass == 'Host':
                    subClasses = [
                        'OpsiConfigserver', 'OpsiDepotserver', 'OpsiClient'
                    ]

                methodPrefix = eval("%s.backendMethodPrefix" % objClass)

                self.__overallProgressSubject.setMessage(u"Replicating %s" %
                                                         objClass)
                self.__currentProgressSubject.setTitle(u"Replicating %s" %
                                                       objClass)
                for subClass in subClasses:
                    filter = {}
                    if subClass == 'OpsiConfigserver':
                        filter = {'type': subClass, 'id': serverIds}
                    elif subClass == 'OpsiDepotserver':
                        filter = {'type': subClass, 'id': depotIds}
                    elif subClass == 'OpsiClient':
                        filter = {'type': subClass, 'id': clientIds}
                    elif objClass == 'Group':
                        filter = {'type': subClass, 'id': groupIds}
                    elif objClass == 'Product':
                        filter = {'type': subClass, 'id': productIds}
                    elif objClass == 'ProductOnClient':
                        filter = {
                            'productType': productTypes,
                            'productId': productIds,
                            'clientId': clientIds
                        }
                    elif objClass == 'ProductOnDepot':
                        filter = {
                            'productType': productTypes,
                            'productId': productIds,
                            'depotId': depotIds
                        }
                    elif objClass == 'ProductDependency':
                        filter = {'productId': productIds}
                    elif objClass == 'ProductProperty':
                        filter = {'productId': productIds}
                    elif objClass == 'ProductPropertyState':
                        filter = {
                            'productId': productIds,
                            'objectId': forceList(hostIds)
                        }
                    elif objClass == 'ConfigState':
                        filter = {'objectId': forceList(hostIds)}
                    elif objClass == 'ObjectToGroup':
                        if productIds and hostIds:
                            objectIds = productIds + forceList(hostIds)
                        else:
                            objectIds = []

                        filter = {'objectId': objectIds}
                    elif objClass == 'LicenseOnClient':
                        filter = {'clientId': clientIds}

                    logger.notice("Replicating class '%s', filter: %s" %
                                  (objClass, filter))
                    if not subClass:
                        subClass = objClass
                    Class = eval(subClass)

                    self.__currentProgressSubject.reset()
                    self.__currentProgressSubject.setMessage(
                        u"Reading objects")
                    self.__currentProgressSubject.setEnd(1)
                    objs = []

                    if objClass == 'ProductOnDepot' and productOnDepots:
                        objs = productOnDepots
                    else:
                        meth = '%s_getObjects' % Class.backendMethodPrefix
                        meth = getattr(rb, meth)
                        objs = meth(**filter)

                    self.__currentProgressSubject.addToState(1)
                    if objClass == 'Group':
                        # Sort groups
                        sortedObjs = []
                        groupIds = []
                        while True:
                            notAddedObjs = []
                            for obj in objs:
                                if not obj.getParentGroupId(
                                ) or obj.getParentGroupId() in groupIds:
                                    if not obj.getParentGroupId():
                                        logger.debug(
                                            u"Adding group '%s' without parent group set"
                                            % obj)
                                    else:
                                        logger.debug(
                                            u"Adding group '%s' with parent group '%s' already added"
                                            % (obj, obj.getParentGroupId()))
                                    sortedObjs.append(obj)
                                    groupIds.append(obj.getId())
                                else:
                                    logger.debug(
                                        u"Cannot add group '%s' parent group '%s' not added yet"
                                        % (obj, obj.getParentGroupId()))
                                    notAddedObjs.append(obj)
                            if not notAddedObjs:
                                break
                            if len(notAddedObjs) == len(objs):
                                for obj in notAddedObjs:
                                    logger.error(u"Failed to add group: %s" %
                                                 obj)
                                break
                            objs = notAddedObjs
                        objs = sortedObjs

                    self.__currentProgressSubject.reset()
                    self.__currentProgressSubject.setMessage(
                        u"Writing objects")
                    if subClass == 'OpsiConfigserver' and objs:
                        configServer = objs[0]
                        depotServers.extend(objs)
                    if subClass == 'OpsiDepotserver':
                        depotServers.extend(objs)

                    if self.__strict:
                        self.__currentProgressSubject.setEnd(1)
                        meth = '%s_createObjects' % Class.backendMethodPrefix
                        meth = getattr(wb, meth)
                        meth(objs)
                        self.__currentProgressSubject.addToState(1)
                    else:
                        self.__currentProgressSubject.setEnd(len(objs))
                        meth = '%s_insertObject' % Class.backendMethodPrefix
                        meth = getattr(wb, meth)

                        for obj in objs:
                            try:
                                meth(obj)
                            except Exception as e:
                                logger.logException(e, LOG_DEBUG)
                                logger.error(
                                    u"Failed to replicate object %s: %s" %
                                    (obj, e))
                            self.__currentProgressSubject.addToState(1)
                    self.__currentProgressSubject.setState(len(objs))

                self.__overallProgressSubject.addToState(1)

            if self.__newServerId:
                self.__currentProgressSubject.reset()
                self.__currentProgressSubject.setMessage(u"Renaming server")
                self.__currentProgressSubject.setTitle(u"Renaming server")
                self.__currentProgressSubject.setEnd(1)
                if not self.__oldServerId:
                    if configServer:
                        self.__oldServerId = configServer.id
                    elif depotServers:
                        self.__oldServerId = depotServers[0].id
                    else:
                        logger.error(u"No config/depot servers found")

                if self.__oldServerId and self.__oldServerId != self.__newServerId:
                    logger.notice(
                        u"Renaming config server {0!r} to {1!r}".format(
                            self.__oldServerId, self.__newServerId))
                    renamingBackend = wb
                    try:
                        renamingBackend.host_renameOpsiDepotserver()
                    except TypeError:
                        pass  # Missing arguments but method exists
                    except AttributeError:
                        # Missing the method - need to use extended backend
                        renamingBackend = self._extendedWriteBackend

                    renamingBackend.host_renameOpsiDepotserver(
                        oldId=self.__oldServerId, newId=self.__newServerId)

                    newDepots = []
                    for depot in renamingBackend.host_getObjects(
                            type='OpsiDepotserver'):
                        hash = depot.toHash()
                        del hash['type']
                        if depot.id == self.__newServerId:
                            newDepots.append(OpsiConfigserver.fromHash(hash))
                        else:
                            newDepots.append(OpsiDepotserver.fromHash(hash))
                    renamingBackend.host_createObjects(newDepots)

                self.__overallProgressSubject.addToState(1)
        finally:
            wb.backend_setOptions(
                {'additionalReferentialIntegrityChecks': aric})
コード例 #25
0
def cleanupBackend(backend=None):
    """
	Clean up data from your backends.

	This method uses different cleanup methods to ensure that no
	obsolete data is present in your backend.

	:param backend: the backend to check. If ``None`` this will create a \
BackendManager from default paths.
	:type backend: OPSI.Backend.Backend
	"""
    def usesMysqlBackend():
        LOGGER.notice(u"Parsing dispatch.conf")
        bdc = BackendDispatchConfigFile(
            u'/etc/opsi/backendManager/dispatch.conf')
        dispatchConfig = bdc.parse()
        for entry in dispatchConfig:
            (regex, backends) = entry
            if not re.search(regex, u'backend_createBase'):
                continue

            if 'mysql' in backends:
                return True

        return False

    LOGGER.debug("Cleaning backend chunk size: {0}".format(_CHUNK_SIZE))

    if backend is None:
        backend = BackendManager(
            dispatchConfigFile=u'/etc/opsi/backendManager/dispatch.conf',
            backendConfigDir=u'/etc/opsi/backends',
            extensionConfigDir=u'/etc/opsi/backendManager/extend.d',
            depotbackend=False)

        try:
            if usesMysqlBackend():
                LOGGER.notice(
                    u"Mysql-backend detected. Trying to cleanup mysql-backend first"
                )
                # ToDo: backendConfigFile should be as dynamic as possible
                # What if we have 2 mysql backends set up?
                cleanUpMySQL()
        except Exception as error:
            LOGGER.warning(error)

    LOGGER.notice(u"Cleaning up groups")
    cleanUpGroups(backend)

    LOGGER.notice(u"Cleaning up products")
    cleanUpProducts(backend)

    LOGGER.debug(u'Getting current depots...')
    depotIds = set(depot.id for depot in backend.host_getObjects(
        type=["OpsiConfigserver", "OpsiDepotserver"]))  # pylint: disable=maybe-no-member
    LOGGER.debug(u'Depots are: {0}'.format(depotIds))

    LOGGER.debug(u'Getting current products...')
    productIdents = set(
        product.getIdent(returnType='unicode')
        for product in backend.product_getObjects())
    LOGGER.debug(u'Product idents are: {0}'.format(productIdents))

    LOGGER.notice(u"Cleaning up product on depots")
    cleanUpProductOnDepots(backend, depotIds, productIdents)

    LOGGER.notice(u"Cleaning up product on clients")
    cleanUpProductOnClients(backend)

    LOGGER.notice(u"Cleaning up product properties")
    productPropertyIdents = set()
    deleteProductProperties = []
    productPropertiesToCleanup = {}
    for productProperty in backend.productProperty_getObjects():  # pylint: disable=maybe-no-member
        productIdent = u"%s;%s;%s" % (productProperty.productId,
                                      productProperty.productVersion,
                                      productProperty.packageVersion)
        if not productProperty.editable and productProperty.possibleValues:
            productPropertyIdent = u"%s;%s" % (productIdent,
                                               productProperty.propertyId)
            productPropertiesToCleanup[productPropertyIdent] = productProperty

        if productIdent not in productIdents:
            LOGGER.info(
                u"Marking productProperty %s of non existent product '%s' for deletion"
                % (productProperty, productIdent))
            deleteProductProperties.append(productProperty)
        else:
            productPropertyIdent = u'%s;%s' % (productProperty.productId,
                                               productProperty.propertyId)
            productPropertyIdents.add(productPropertyIdent)

    if deleteProductProperties:
        for productProperties in chunk(deleteProductProperties, _CHUNK_SIZE):
            LOGGER.debug(u"Deleting product properties: {0!r}".format(
                productProperties))
            backend.productProperty_deleteObjects(productProperties)  # pylint: disable=maybe-no-member

    LOGGER.notice(u"Cleaning up product property states")
    deleteProductPropertyStates = []
    for productPropertyState in backend.productPropertyState_getObjects():  # pylint: disable=maybe-no-member
        productPropertyIdent = u'%s;%s' % (productPropertyState.productId,
                                           productPropertyState.propertyId)
        if productPropertyIdent not in productPropertyIdents:
            LOGGER.info(
                u"Marking productPropertyState %s of non existent productProperty '%s' for deletion"
                % (productPropertyState, productPropertyIdent))
            deleteProductPropertyStates.append(productPropertyState)

    if deleteProductPropertyStates:
        for productPropertyStates in chunk(deleteProductPropertyStates,
                                           _CHUNK_SIZE):
            LOGGER.debug(u"Deleting product property states: {0!r}".format(
                productPropertyStates))
            backend.productPropertyState_deleteObjects(productPropertyStates)  # pylint: disable=maybe-no-member

    for depot in backend.host_getObjects(type='OpsiDepotserver'):  # pylint: disable=maybe-no-member
        objectIds = set(
            ClientToDepot['clientId']
            for ClientToDepot in backend.configState_getClientToDepotserver(
                depotIds=depot.id))
        objectIds.add(depot.id)

        productOnDepotIdents = {}
        for productOnDepot in backend.productOnDepot_getObjects(
                depotId=depot.id):  # pylint: disable=maybe-no-member
            productIdent = u"%s;%s;%s" % (productOnDepot.productId,
                                          productOnDepot.productVersion,
                                          productOnDepot.packageVersion)
            productOnDepotIdents[productOnDepot.productId] = productIdent

        if not productOnDepotIdents:
            continue

        deleteProductPropertyStates = []
        updateProductPropertyStates = []
        for productPropertyState in backend.productPropertyState_getObjects(  # pylint: disable=maybe-no-member
                objectId=objectIds,
                productId=productOnDepotIdents.keys(),
                propertyId=[]):
            productIdent = productOnDepotIdents.get(
                productPropertyState.productId)
            if not productIdent:
                continue
            productPropertyIdent = u"%s;%s" % (productIdent,
                                               productPropertyState.propertyId)
            productProperty = productPropertiesToCleanup.get(
                productPropertyIdent)
            if not productProperty:
                continue
            changed = False
            newValues = []
            removeValues = []
            changedValues = []
            for value in productPropertyState.values:
                if value in productProperty.possibleValues:
                    newValues.append(value)
                    continue
                if productProperty.getType(
                ) == u'BoolProductProperty' and forceBool(
                        value) in productProperty.possibleValues:
                    newValues.append(forceBool(value))
                    changedValues.append(value)
                    changed = True
                    continue
                if productProperty.getType() == u'UnicodeProductProperty':
                    newValue = None
                    for possibleValue in productProperty.possibleValues:
                        if forceUnicodeLower(
                                possibleValue) == forceUnicodeLower(value):
                            newValue = possibleValue
                            break
                    if newValue:
                        newValues.append(newValue)
                        changedValues.append(value)
                        changed = True
                        continue
                removeValues.append(value)
                changed = True
            if changed:
                if not newValues:
                    LOGGER.info(
                        u"Marking productPropertyState %s for deletion: no value in possible values (%s)"
                        % (productPropertyState, removeValues))
                    deleteProductPropertyStates.append(productPropertyState)
                else:
                    productPropertyState.setValues(newValues)
                    LOGGER.info(
                        u"Marking productPropertyState %s for update: values not in possible values: %s, values corrected: %s"
                        % (productPropertyState, removeValues, changedValues))
                    updateProductPropertyStates.append(productPropertyState)

        if deleteProductPropertyStates:
            for productPropertyStates in chunk(deleteProductPropertyStates,
                                               _CHUNK_SIZE):
                LOGGER.debug(u"Deleting product property states: {0!r}".format(
                    productPropertyStates))
                backend.productPropertyState_deleteObjects(
                    productPropertyStates)  # pylint: disable=maybe-no-member
            del deleteProductPropertyStates

        if updateProductPropertyStates:
            for productPropertyStates in chunk(updateProductPropertyStates,
                                               _CHUNK_SIZE):
                LOGGER.debug(u"Updating product property states: {0!r}".format(
                    productPropertyStates))
                backend.productPropertyState_updateObjects(
                    productPropertyStates)  # pylint: disable=maybe-no-member
            del updateProductPropertyStates

    LOGGER.notice(u"Cleaning up config states")
    cleanUpConfigStates(backend)

    LOGGER.notice(u"Cleaning up audit softwares")
    cleanUpAuditSoftwares(backend)

    LOGGER.notice(u"Cleaning up audit software on clients")
    cleanUpAuditSoftwareOnClients(backend)
コード例 #26
0
    def connectConfigService(self, allowTemporaryConfigServiceUrls=True):  # pylint: disable=too-many-locals,too-many-branches,too-many-statements
        try:  # pylint: disable=too-many-nested-blocks
            configServiceUrls = config.getConfigServiceUrls(
                allowTemporaryConfigServiceUrls=allowTemporaryConfigServiceUrls
            )
            if not configServiceUrls:
                raise Exception("No service url defined")

            if self._loadBalance and (len(configServiceUrls) > 1):
                random.shuffle(configServiceUrls)

            for urlIndex, configServiceURL in enumerate(configServiceUrls):
                self._configServiceUrl = configServiceURL

                kwargs = self.connectionThreadOptions()
                logger.debug("Creating ServiceConnectionThread (url: %s)",
                             self._configServiceUrl)
                serviceConnectionThread = ServiceConnectionThread(
                    configServiceUrl=self._configServiceUrl,
                    username=config.get('global', 'host_id'),
                    password=config.get('global', 'opsi_host_key'),
                    **kwargs)
                serviceConnectionThread.daemon = True

                self.connectionStart(self._configServiceUrl)

                cancellableAfter = forceInt(
                    config.get('config_service', 'user_cancelable_after'))
                timeout = forceInt(
                    config.get('config_service', 'connection_timeout'))
                logger.info(
                    "Starting ServiceConnectionThread, timeout is %d seconds",
                    timeout)
                serviceConnectionThread.start()
                for _unused in range(5):
                    if serviceConnectionThread.running:
                        break
                    time.sleep(1)

                logger.debug("ServiceConnectionThread started")
                while serviceConnectionThread.running and timeout > 0:
                    if self._should_stop:
                        return
                    logger.debug(
                        "Waiting for ServiceConnectionThread (timeout: %d, alive: %s, cancellable in: %d)",
                        timeout, serviceConnectionThread.is_alive(),
                        cancellableAfter)
                    self.connectionTimeoutChanged(timeout)
                    if cancellableAfter > 0:
                        cancellableAfter -= 1
                    if cancellableAfter == 0:
                        self.connectionCancelable(
                            serviceConnectionThread.stopConnectionCallback)
                    time.sleep(1)
                    timeout -= 1

                if serviceConnectionThread.cancelled:
                    self.connectionCanceled()
                elif serviceConnectionThread.running:
                    serviceConnectionThread.stop()
                    if urlIndex + 1 < len(configServiceUrls):
                        # Try next url
                        continue
                    self.connectionTimedOut()

                if not serviceConnectionThread.connected:
                    self.connectionFailed(
                        serviceConnectionThread.connectionError)

                if serviceConnectionThread.connected and (
                        serviceConnectionThread.getUsername() != config.get(
                            'global', 'host_id')):
                    config.set('global', 'host_id',
                               serviceConnectionThread.getUsername().lower())
                    logger.info("Updated host_id to '%s'",
                                config.get('global', 'host_id'))
                    config.updateConfigFile()

                if serviceConnectionThread.connected and forceBool(
                        config.get('config_service',
                                   'sync_time_from_service')):
                    logger.info("Syncing local system time from service")
                    try:
                        System.setLocalSystemTime(
                            serviceConnectionThread.configService.
                            getServiceTime(utctime=True))  # pylint: disable=no-member
                    except Exception as err:  # pylint: disable=broad-except
                        logger.error("Failed to sync time: '%s'", err)

                if ("localhost" not in configServiceURL
                        and "127.0.0.1" not in configServiceURL):
                    try:
                        config.set(
                            'depot_server',
                            'master_depot_id',
                            serviceConnectionThread.configService.getDepotId(
                                config.get('global', 'host_id'))  # pylint: disable=no-member
                        )
                        config.updateConfigFile()
                    except Exception as err:  # pylint: disable=broad-except
                        logger.warning(err)

                self._configService = serviceConnectionThread.configService
                self.connectionEstablished()
        except Exception:
            self.disconnectConfigService()
            raise
コード例 #27
0
    def getSelection(self,
                     entries,
                     radio=False,
                     width=-1,
                     height=-1,
                     title=_(u'Please select'),
                     text=u'',
                     okLabel=_(u'OK'),
                     cancelLabel=_(u'Cancel')):
        try:
            entries = forceList(entries)
            radio = forceBool(radio)
            width = forceInt(width)
            height = forceInt(height)
            title = forceUnicode(title)
            text = forceUnicode(text)
            okLabel = forceUnicode(okLabel)
            cancelLabel = forceUnicode(cancelLabel)

            for string in self.confidentialStrings:
                text = text.replace(string, u'*** confidential ***')

            if (width <= 0):
                width = self.getScreen().width - 15

            if (height <= 14):
                height = 13 + len(entries)
                if text:
                    height += len(text.split(u'\n')) + 1
                if (height > self.getScreen().height - 5):
                    height = self.getScreen().height - 5

            entriesHeight = len(entries)
            if (entriesHeight > height - 13):
                entriesHeight = height - 13

            # create text grid
            textGrid = Grid(1, 1)
            if text:
                textHeight = len(text.split(u'\n')) + 1
                diff = textHeight + entriesHeight + 13 - height
                if (diff > 0):
                    entriesHeight -= diff
                    if (entriesHeight < 3):
                        textHeight = textHeight - 3 + entriesHeight
                        entriesHeight = 3

                textBox = Textbox(width=width,
                                  height=textHeight,
                                  text=text.encode(encoding, 'replace'),
                                  scroll=1,
                                  wrap=1)
                textGrid.setField(textBox, col=0, row=0)

            # create widget for entries
            entriesWidget = None
            if radio:
                entriesWidget = Listbox(height=entriesHeight,
                                        scroll=1,
                                        returnExit=0,
                                        width=0,
                                        showCursor=0)
            else:
                entriesWidget = CheckboxTree(height=entriesHeight, scroll=1)

            row = 0
            numSelected = 0
            for i, entry in enumerate(entries):
                selected = forceBool(entry.get('selected', False))
                if radio and (numSelected >= 1):
                    selected = False
                if selected:
                    numSelected += 1
                if radio:
                    entriesWidget.append(text=forceUnicode(
                        entry.get('name', '???')).encode(encoding, 'replace'),
                                         item=i)
                    if selected:
                        entriesWidget.setCurrent(i)
                else:
                    entriesWidget.append(text=forceUnicode(
                        entry.get('name', '???')).encode(encoding, 'replace'),
                                         item=i,
                                         selected=selected)
                row += 1

            # create grid for buttons
            buttonsGrid = Grid(2, 1)

            cancelButton = Button(cancelLabel.encode(encoding, 'replace'))
            buttonsGrid.setField(cancelButton,
                                 col=0,
                                 row=0,
                                 padding=(0, 0, 10, 0))

            okButton = Button(okLabel.encode(encoding, 'replace'))
            buttonsGrid.setField(okButton, col=1, row=0, padding=(10, 0, 0, 0))

            gridForm = GridForm(self._screen,
                                title.encode(encoding, 'replace'), 1, 3)
            gridForm.add(textGrid, col=0, row=0, padding=(0, 0, 0, 1))
            gridForm.add(entriesWidget, col=0, row=1, padding=(0, 0, 0, 1))
            gridForm.add(buttonsGrid, col=0, row=2, padding=(0, 0, 0, 0))

            # help line
            helpLine = _(
                u"<ESC> %s | <F12> %s | <Tab> move cursor | <Space> select"
            ) % (cancelLabel, okLabel)
            if text:
                helpLine += _(u" | <Up/Down> scroll text")
            self.getScreen().pushHelpLine(
                forceUnicode(helpLine).encode(encoding, 'replace'))

            # run
            gridForm.addHotKey('ESC')
            gridForm.draw()
            buttonPressed = None
            while (buttonPressed not in [okButton, 'F12', cancelButton,
                                         'ESC']):
                buttonPressed = gridForm.run()
            self._screen.popWindow()
            if (buttonPressed not in [okButton, 'F12']):
                return None

            result = []
            if radio:
                result.append(entries[entriesWidget.current()]['name'])
            else:
                for sel in entriesWidget.getSelection():
                    result.append(entries[sel]['name'])
            return result
        except Exception as e:
            self.exit()
            logger.logException(e)
            raise
コード例 #28
0
    def getValue(self,
                 width=-1,
                 height=-1,
                 title=_(u'Please type text'),
                 default=u'',
                 password=False,
                 text=u'',
                 okLabel=_(u'OK'),
                 cancelLabel=_(u'Cancel')):
        try:
            width = forceInt(width)
            height = forceInt(height)
            title = forceUnicode(title)
            default = forceUnicode(default)
            password = forceBool(password)
            text = forceUnicode(text)
            okLabel = forceUnicode(okLabel)
            cancelLabel = forceUnicode(cancelLabel)

            for string in self.confidentialStrings:
                text = text.replace(string, u'*** confidential ***')

            if (width <= 0):
                width = self.getScreen().width - 15

            # create text grid
            textGrid = Grid(1, 1)
            if text:
                textHeight = 0
                if (height <= 0):
                    height = self.getScreen().height - 15
                    textHeight = height - 5
                    if (textHeight < 2):
                        textHeight = 2
                    elif (textHeight > len(text.split('\n')) + 1):
                        textHeight = len(text.split('\n')) + 1
                else:
                    textHeight = height - len(text.split('\n')) + 1

                textBox = Textbox(width=width,
                                  height=textHeight,
                                  text=text.encode(encoding, 'replace'),
                                  scroll=1,
                                  wrap=1)
                textGrid.setField(textBox, col=0, row=0)

            # create grid for input
            entryGrid = Grid(1, 1)
            entry = Entry(width=width,
                          text=default.encode(encoding, 'replace'),
                          hidden=False,
                          password=password,
                          scroll=1,
                          returnExit=0)
            entryGrid.setField(entry, col=0, row=0, padding=(0, 0, 0, 0))

            # create grid for buttons
            buttonsGrid = Grid(2, 1)

            cancelButton = Button(cancelLabel.encode(encoding, 'replace'))
            buttonsGrid.setField(cancelButton,
                                 col=0,
                                 row=0,
                                 padding=(0, 0, 10, 0))

            okButton = Button(okLabel.encode(encoding, 'replace'))
            buttonsGrid.setField(okButton, col=1, row=0, padding=(10, 0, 0, 0))

            gridForm = GridForm(self._screen,
                                title.encode(encoding, 'replace'), 1, 3)
            gridForm.add(textGrid, col=0, row=0, padding=(0, 0, 0, 1))
            gridForm.add(entryGrid, col=0, row=1, padding=(0, 0, 0, 1))
            gridForm.add(buttonsGrid, col=0, row=2, padding=(0, 0, 0, 0))
            gridForm.addHotKey('ESC')

            # help line
            helpLine = _(
                u"<ESC> %s | <F12> %s | <Tab> move cursor | <Space> select"
            ) % (cancelLabel, okLabel)
            if text:
                helpLine += _(u" | <Up/Down> scroll text")
            self.getScreen().pushHelpLine(
                forceUnicode(helpLine).encode(encoding, 'replace'))

            # run
            gridForm.addHotKey('ESC')
            gridForm.draw()
            buttonPressed = None
            while (buttonPressed not in [okButton, 'F12', cancelButton,
                                         'ESC']):
                buttonPressed = gridForm.run()
            self._screen.popWindow()
            if (buttonPressed not in [okButton, 'F12']):
                return None

            return unicode(entry.value(), encoding)
        except Exception as e:
            self.exit()
            logger.logException(e)
            raise
コード例 #29
0
def getEventConfigs(): # pylint: disable=too-many-locals,too-many-branches,too-many-statements
	preconditions = {}
	for (section, options) in config.getDict().items():
		section = section.lower()
		if section.startswith('precondition_'):
			preconditionId = section.split('_', 1)[1]
			preconditions[preconditionId] = {}
			try:
				for key in options.keys():
					if forceBool(options[key]):
						# Only check if value in precondition is true
						# false means: do not check state
						preconditions[preconditionId][key] = True
				logger.info("Precondition '%s' created: %s", preconditionId, preconditions[preconditionId])
			except Exception as err: # pylint: disable=broad-except
				logger.error("Failed to parse precondition '%s': %s", preconditionId, err)

	rawEventConfigs = {}
	for (section, options) in config.getDict().items(): # pylint: disable=too-many-nested-blocks
		section = section.lower()
		if section.startswith('event_'):
			eventConfigId = section.split('_', 1)[1]
			if not eventConfigId:
				logger.error("No event config id defined in section '%s'", section)
				continue

			rawEventConfigs[eventConfigId] = {
				'active': True,
				'args': {
					'name': eventConfigId.split("{")[0]
				},
				'super': None,
				'precondition': None
			}

			try:
				for key in options.keys():
					if key.lower() == 'active':
						rawEventConfigs[eventConfigId]['active'] = str(options[key]).lower() not in ('0', 'false', 'off', 'no')
					elif key.lower() == 'super':
						rawEventConfigs[eventConfigId]['super'] = options[key]
						if rawEventConfigs[eventConfigId]['super'].startswith('event_'):
							rawEventConfigs[eventConfigId]['super'] = rawEventConfigs[eventConfigId]['super'].split('_', 1)[1]
					else:
						rawEventConfigs[eventConfigId]['args'][key.lower()] = options[key]

				if '{' in eventConfigId:
					superEventName, precondition = eventConfigId.split('{', 1)
					if not rawEventConfigs[eventConfigId]['super']:
						rawEventConfigs[eventConfigId]['super'] = superEventName.strip()
					rawEventConfigs[eventConfigId]['precondition'] = precondition.replace('}', '').strip()
			except Exception as err: # pylint: disable=broad-except
				logger.error("Failed to parse event config '%s': %s", eventConfigId, err)

	# Process inheritance
	newRawEventConfigs = {}
	while rawEventConfigs:
		num_configs = len(rawEventConfigs)
		for eventConfigId in sorted(list(rawEventConfigs)):
			rawEventConfig = rawEventConfigs[eventConfigId]
			if rawEventConfig['super']:
				if rawEventConfig['super'] in newRawEventConfigs:
					super_args = pycopy.deepcopy(newRawEventConfigs[rawEventConfig['super']]['args'])
					# Do not overwrite values with emptystring or emptylist (behaves like no value given)
					cleaned_args = {
						key : value
						for key, value in rawEventConfig['args'].items()
						if not (
							key in ("include_product_group_ids", "exclude_product_group_ids")
							and value in ("", [])
						)
					}
					super_args.update(cleaned_args)
					rawEventConfig['args'] = super_args
					logger.debug("Inheritance for event '%s' processed", eventConfigId)
					newRawEventConfigs[eventConfigId] = rawEventConfig
					rawEventConfigs.pop(eventConfigId)
				elif rawEventConfig['super'] not in rawEventConfigs:
					logger.error("Super event '%s' not found", rawEventConfig['super'])
					rawEventConfigs.pop(eventConfigId)
			else:
				logger.debug("Inheritance for event '%s' processed", eventConfigId)
				newRawEventConfigs[eventConfigId] = rawEventConfig
				rawEventConfigs.pop(eventConfigId)
		if num_configs == len(rawEventConfigs):
			logger.error("Failed to process event inheritance: %s", rawEventConfigs)
			break

	rawEventConfigs = newRawEventConfigs

	eventConfigs = {}
	for (eventConfigId, rawEventConfig) in rawEventConfigs.items(): # pylint: disable=too-many-nested-blocks
		try:
			if rawEventConfig['args'].get('type', 'template').lower() == 'template':
				continue

			eventConfigs[eventConfigId] = {
				'active': rawEventConfig['active'],
				'preconditions': {}
			}

			if rawEventConfig.get('precondition'):
				precondition = preconditions.get(rawEventConfig['precondition'])
				if not precondition:
					logger.error(
						"Precondition '%s' referenced by event config '%s' not found, deactivating event",
						precondition, eventConfigId
					)
					eventConfigs[eventConfigId]['active'] = False
				else:
					eventConfigs[eventConfigId]['preconditions'] = precondition

			for (key, value) in rawEventConfig['args'].items():
				try:
					if key == 'type':
						eventConfigs[eventConfigId]['type'] = value
					elif key == 'wql':
						eventConfigs[eventConfigId]['wql'] = value
					elif key.startswith(('action_message', 'message')):
						try:
							mLanguage = key.split('[')[1].split(']')[0].strip().lower()
						except Exception: # pylint: disable=broad-except
							mLanguage = None

						if mLanguage:
							if mLanguage == getLanguage():
								eventConfigs[eventConfigId]['actionMessage'] = value
						elif not eventConfigs[eventConfigId].get('actionMessage'):
							eventConfigs[eventConfigId]['actionMessage'] = value
					elif key.startswith('shutdown_warning_message'):
						try:
							mLanguage = key.split('[')[1].split(']')[0].strip().lower()
						except Exception: # pylint: disable=broad-except
							mLanguage = None

						if mLanguage:
							if mLanguage == getLanguage():
								eventConfigs[eventConfigId]['shutdownWarningMessage'] = value
						elif not eventConfigs[eventConfigId].get('shutdownWarningMessage'):
							eventConfigs[eventConfigId]['shutdownWarningMessage'] = value
					elif key.startswith('name'):
						try:
							mLanguage = key.split('[')[1].split(']')[0].strip().lower()
						except Exception: # pylint: disable=broad-except
							mLanguage = None

						if mLanguage:
							if mLanguage == getLanguage():
								eventConfigs[eventConfigId]['name'] = value
						else:
							eventConfigs[eventConfigId]['name'] = value
					elif key == 'start_interval':
						eventConfigs[eventConfigId]['startInterval'] = int(value)
					elif key == 'interval':
						eventConfigs[eventConfigId]['interval'] = int(value)
					elif key == 'max_repetitions':
						eventConfigs[eventConfigId]['maxRepetitions'] = int(value)
					elif key == 'activation_delay':
						eventConfigs[eventConfigId]['activationDelay'] = int(value)
					elif key == 'notification_delay':
						eventConfigs[eventConfigId]['notificationDelay'] = int(value)
					elif key == 'action_warning_time':
						eventConfigs[eventConfigId]['actionWarningTime'] = int(value)
					elif key == 'action_user_cancelable':
						eventConfigs[eventConfigId]['actionUserCancelable'] = int(value)
					elif key == 'shutdown':
						eventConfigs[eventConfigId]['shutdown'] = forceBool(value)
					elif key == 'reboot':
						eventConfigs[eventConfigId]['reboot'] = forceBool(value)
					elif key == 'shutdown_warning_time':
						eventConfigs[eventConfigId]['shutdownWarningTime'] = int(value)
					elif key == 'shutdown_warning_repetition_time':
						eventConfigs[eventConfigId]['shutdownWarningRepetitionTime'] = int(value)
					elif key == 'shutdown_user_cancelable':
						eventConfigs[eventConfigId]['shutdownUserCancelable'] = int(value)
					elif key == 'shutdown_user_selectable_time':
						eventConfigs[eventConfigId]['shutdownUserSelectableTime'] = forceBool(value)
					elif key == 'shutdown_warning_time_after_time_select':
						eventConfigs[eventConfigId]['shutdownWarningTimeAfterTimeSelect'] = int(value)
					elif key == 'block_login':
						eventConfigs[eventConfigId]['blockLogin'] = forceBool(value)
					elif key == 'lock_workstation':
						eventConfigs[eventConfigId]['lockWorkstation'] = forceBool(value)
					elif key == 'logoff_current_user':
						eventConfigs[eventConfigId]['logoffCurrentUser'] = forceBool(value)
					elif key == 'process_shutdown_requests':
						eventConfigs[eventConfigId]['processShutdownRequests'] = forceBool(value)
					elif key == 'get_config_from_service':
						eventConfigs[eventConfigId]['getConfigFromService'] = forceBool(value)
					elif key == 'update_config_file':
						eventConfigs[eventConfigId]['updateConfigFile'] = forceBool(value)
					elif key == 'write_log_to_service':
						eventConfigs[eventConfigId]['writeLogToService'] = forceBool(value)
					elif key == 'cache_products':
						eventConfigs[eventConfigId]['cacheProducts'] = forceBool(value)
					elif key == 'cache_max_bandwidth':
						eventConfigs[eventConfigId]['cacheMaxBandwidth'] = int(value)
					elif key == 'cache_dynamic_bandwidth':
						eventConfigs[eventConfigId]['cacheDynamicBandwidth'] = forceBool(value)
					elif key == 'use_cached_products':
						eventConfigs[eventConfigId]['useCachedProducts'] = forceBool(value)
					elif key == 'sync_config_from_server':
						eventConfigs[eventConfigId]['syncConfigFromServer'] = forceBool(value)
					elif key == 'sync_config_to_server':
						eventConfigs[eventConfigId]['syncConfigToServer'] = forceBool(value)
					elif key == 'use_cached_config':
						eventConfigs[eventConfigId]['useCachedConfig'] = forceBool(value)
					elif key == 'update_action_processor':
						eventConfigs[eventConfigId]['updateActionProcessor'] = forceBool(value)
					elif key == 'action_type':
						eventConfigs[eventConfigId]['actionType'] = forceUnicodeLower(value)
					elif key == 'event_notifier_command':
						eventConfigs[eventConfigId]['eventNotifierCommand'] = config.replace(forceUnicodeLower(value), escaped=True)
					elif key == 'event_notifier_desktop':
						eventConfigs[eventConfigId]['eventNotifierDesktop'] = forceUnicodeLower(value)
					elif key == 'process_actions':
						eventConfigs[eventConfigId]['processActions'] = forceBool(value)
					elif key == 'action_notifier_command':
						eventConfigs[eventConfigId]['actionNotifierCommand'] = config.replace(forceUnicodeLower(value), escaped=True)
					elif key == 'action_notifier_desktop':
						eventConfigs[eventConfigId]['actionNotifierDesktop'] = forceUnicodeLower(value)
					elif key == 'action_processor_command':
						eventConfigs[eventConfigId]['actionProcessorCommand'] = forceUnicodeLower(value)
					elif key == 'action_processor_desktop':
						eventConfigs[eventConfigId]['actionProcessorDesktop'] = forceUnicodeLower(value)
					elif key == 'action_processor_timeout':
						eventConfigs[eventConfigId]['actionProcessorTimeout'] = int(value)
					elif key == 'trusted_installer_detection':
						eventConfigs[eventConfigId]['trustedInstallerDetection'] = forceBool(value)
					elif key == 'shutdown_notifier_command':
						eventConfigs[eventConfigId]['shutdownNotifierCommand'] = config.replace(forceUnicodeLower(value), escaped=True)
					elif key == 'shutdown_notifier_desktop':
						eventConfigs[eventConfigId]['shutdownNotifierDesktop'] = forceUnicodeLower(value)
					elif key == 'pre_action_processor_command':
						eventConfigs[eventConfigId]['preActionProcessorCommand'] = config.replace(forceUnicodeLower(value), escaped=True)
					elif key == 'post_action_processor_command':
						eventConfigs[eventConfigId]['postActionProcessorCommand'] = config.replace(forceUnicodeLower(value), escaped=True)
					elif key == 'post_event_command':
						eventConfigs[eventConfigId]['postEventCommand'] = config.replace(forceUnicodeLower(value), escaped=True)
					elif key == 'action_processor_productids':
						if not isinstance(value, list):
							value = [x.strip() for x in value.split(",") if x.strip()]
						eventConfigs[eventConfigId]['actionProcessorProductIds'] = forceList(value)
					elif key == 'depot_protocol':
						eventConfigs[eventConfigId]['depotProtocol'] = forceUnicodeLower(value)
					elif key == 'exclude_product_group_ids':
						if not isinstance(value, list):
							value = [x.strip() for x in value.split(",") if x.strip()]
						eventConfigs[eventConfigId]['excludeProductGroupIds'] = forceList(value)
					elif key == 'include_product_group_ids':
						if not isinstance(value, list):
							value = [x.strip() for x in value.split(",") if x.strip()]
						eventConfigs[eventConfigId]['includeProductGroupIds'] = forceList(value)
					elif key == 'working_window':
						eventConfigs[eventConfigId]['workingWindow'] = str(value)
					else:
						logger.error("Skipping unknown option '%s' in definition of event '%s'", key, eventConfigId)
						for section in list(config.getDict()):
							if section.startswith("event_") and config.has_option(section, key):
								logger.info("Removing config option %s.%s", section, key)
								config.del_option(section, key)

				except Exception as err: # pylint: disable=broad-except
					logger.debug(err, exc_info=True)
					logger.error("Failed to set event config argument '%s' to '%s': %s", key, value, err)

			logger.info(
				"Event config '%s' args:\n%s",
				eventConfigId,
				pprint.pformat(eventConfigs[eventConfigId], indent=4, width=300, compact=False)
			)
		except Exception as err: # pylint: disable=broad-except
			logger.error(err, exc_info=True)

	return eventConfigs
コード例 #30
0
def testForceBoolWithFalsyValues(value):
    assert forceBool(value) is False