Example #1
0
    def run_helper(self, helper, msg, data):
        """
        Run a helper to post-process result data

        Args:
            helper (str): Name of the helper to run
            msg   (dict): The original message request
            data  (dict): The data to be processed

        """
        logger.debug(
            'Invoking helper module %s for processing of data',
            helper
        )

        module = self.helper_modules[helper]
        h = module.HelperAgent(msg=msg, data=data)

        try:
            result = h.run()
        except Exception as e:
            logger.warning('Helper module raised an exception: %s', e)
            return data

        return result
Example #2
0
    def create_agents(self):
        """
        Prepares the vSphere Agents used by the vPoller Worker

        Raises:
            VPollerException

        """
        logger.debug('Creating vSphere Agents')

        db = VConnectorDatabase(self.config.get('db'))
        agents = db.get_agents(only_enabled=True)

        if not agents:
            logger.warning('No registered or enabled vSphere Agents found')
            raise VPollerException(
                'No registered or enabled vSphere Agents found'
            )

        for agent in agents:
            a = VConnector(
                user=agent['user'],
                pwd=agent['pwd'],
                host=agent['host'],
                cache_enabled=self.config.get('cache_enabled'),
                cache_maxsize=self.config.get('cache_maxsize'),
                cache_ttl=self.config.get('cache_ttl'),
                cache_housekeeping=self.config.get('cache_housekeeping')
            )
            self.agents[a.host] = a
            logger.info('Created vSphere Agent for %s', agent['host'])
Example #3
0
    def process_mgmt_task(self, msg):
        """
        Processes a message for the management interface

        Example client message to shutdown the vPoller Worker would be:

            {
                "method": "shutdown"
            }

        Args:
            msg (dict): The client message for processing

        """
        logger.debug('Processing management message: %s', msg)

        if 'method' not in msg:
            return {'success': 1, 'msg': 'Missing method name'}

        if msg['method'] not in self.mgmt_methods:
            return {'success': 1, 'msg': 'Unknown method name received'}

        method = msg['method']
        result = self.mgmt_methods[method]()

        return result
Example #4
0
    def status(self):
        """
        Get status information about the vPoller Worker

        """
        logger.debug('Getting Worker status')

        result = {
            'success': 0,
            'msg': 'vPoller Worker status',
            'result': {
                'status': 'running',
                'hostname': self.node,
                'proxy': self.config.get('proxy'),
                'mgmt': self.config.get('mgmt'),
                'db': self.config.get('db'),
                'concurrency': self.num_workers,
                'helpers': self.config.get('helpers'),
                'tasks': self.config.get('tasks'),
            }
        }

        logger.debug('Returning result to client: %s', result)

        return result
Example #5
0
    def process_mgmt_task(self, msg):
        """
        Processes a message for the management interface

        Example client message to shutdown the vPoller Worker would be:

            {
                "method": "shutdown"
            }

        Args:
            msg (dict): The client message for processing

        """
        logger.debug('Processing management message: %s', msg)

        if 'method' not in msg:
            return {'success': 1, 'msg': 'Missing method name'}

        if msg['method'] not in self.mgmt_methods:
            return {'success': 1, 'msg': 'Unknown method name received'}

        method = msg['method']
        result = self.mgmt_methods[method]()

        return result
Example #6
0
    def load_config(self):
        """
        Loads the vPoller Worker Manager configuration settings

        """
        logger.debug('Loading config file %s', self.config_file)

        parser = ConfigParser(self.config_defaults)
        parser.read(self.config_file)

        self.config['mgmt'] = parser.get('worker', 'mgmt')
        self.config['db'] = parser.get('worker', 'db')
        self.config['proxy'] = parser.get('worker', 'proxy')
        self.config['helpers'] = parser.get('worker', 'helpers')
        self.config['tasks'] = parser.get('worker', 'tasks')
        self.config['cache_enabled'] = parser.getboolean('cache', 'enabled')
        self.config['cache_maxsize'] = parser.getint('cache', 'maxsize')
        self.config['cache_ttl'] = parser.getint('cache', 'ttl')
        self.config['cache_housekeeping'] = parser.getint('cache', 'housekeeping')

        if self.config['helpers']:
            self.config['helpers'] = self.config['helpers'].split(',')

        if self.config['tasks']:
            self.config['tasks'] = self.config['tasks'].split(',')
        
        logger.debug(
            'Worker Manager configuration: %s',
            self.config
        )
Example #7
0
    def status(self):
        """
        Get status information about the vPoller Worker

        """
        logger.debug('Getting Worker status')

        result = {
            'success': 0,
            'msg': 'vPoller Worker status',
            'result': {
                'status': 'running',
                'hostname': self.node,
                'proxy': self.config.get('proxy'),
                'mgmt': self.config.get('mgmt'),
                'db': self.config.get('db'),
                'concurrency': self.num_workers,
                'helpers': self.config.get('helpers'),
                'tasks': self.config.get('tasks'),
            }
        }

        logger.debug('Returning result to client: %s', result)

        return result
Example #8
0
    def create_agents(self):
        """
        Prepares the vSphere Agents used by the vPoller Worker

        Raises:
            VPollerException

        """
        logger.debug('Creating vSphere Agents')

        db = VConnectorDatabase(self.config.get('db'))
        agents = db.get_agents(only_enabled=True)

        if not agents:
            logger.warning('No registered or enabled vSphere Agents found')
            raise VPollerException(
                'No registered or enabled vSphere Agents found')

        for agent in agents:
            a = VConnector(
                user=agent['user'],
                pwd=agent['pwd'],
                host=agent['host'],
                cache_enabled=self.config.get('cache_enabled'),
                cache_maxsize=self.config.get('cache_maxsize'),
                cache_ttl=self.config.get('cache_ttl'),
                cache_housekeeping=self.config.get('cache_housekeeping'))
            self.agents[a.host] = a
            logger.info('Created vSphere Agent for %s', agent['host'])
Example #9
0
    def load_config(self):
        """
        Loads the vPoller Worker Manager configuration settings

        """
        logger.debug('Loading config file %s', self.config_file)

        parser = ConfigParser(self.config_defaults)
        parser.read(self.config_file)

        self.config['mgmt'] = parser.get('worker', 'mgmt')
        self.config['db'] = parser.get('worker', 'db')
        self.config['proxy'] = parser.get('worker', 'proxy')
        self.config['helpers'] = parser.get('worker', 'helpers')
        self.config['tasks'] = parser.get('worker', 'tasks')
        self.config['cache_enabled'] = parser.getboolean('cache', 'enabled')
        self.config['cache_maxsize'] = parser.getint('cache', 'maxsize')
        self.config['cache_ttl'] = parser.getint('cache', 'ttl')
        self.config['cache_housekeeping'] = parser.getint(
            'cache', 'housekeeping')

        if self.config['helpers']:
            self.config['helpers'] = self.config['helpers'].split(',')

        if self.config['tasks']:
            self.config['tasks'] = self.config['tasks'].split(',')

        logger.debug('Worker Manager configuration: %s', self.config)
Example #10
0
    def stop_agents(self):
        """
        Disconnects all vPoller Agents

        """
        logger.debug('Shutting down vSphere Agents')

        for agent in self.agents:
            self.agents[agent].disconnect()
Example #11
0
    def stop_agents(self):
        """
        Disconnects all vPoller Agents

        """
        logger.debug('Shutting down vSphere Agents')

        for agent in self.agents:
            self.agents[agent].disconnect()
Example #12
0
    def close_sockets(self):
        """
        Closes the ZeroMQ sockets used by the Manager

        """
        logger.debug('Closing Worker Manager sockets')

        self.zpoller.unregister(self.mgmt_socket)
        self.mgmt_socket.close()
        self.zcontext.term()
Example #13
0
    def close_sockets(self):
        """
        Closes the ZeroMQ sockets used by the Manager

        """
        logger.debug('Closing Worker Manager sockets')

        self.zpoller.unregister(self.mgmt_socket)
        self.mgmt_socket.close()
        self.zcontext.term()
Example #14
0
 def wrapper(*args, **kwargs):
     logger.debug("Executing task %s", name)
     try:
         result = fn(*args, **kwargs)
     except Exception as e:
         tb = format_exc()
         result = {"success": 1, "msg": "Task {} failed".format(name), "traceback": tb}
         logger.warning("Task %s failed: %s", name, tb)
     finally:
         logger.debug("Returning result from task %s: %s", name, result)
         return result
Example #15
0
    def create_sockets(self):
        """
        Creates the ZeroMQ sockets used by the vPoller Worker Manager

        """
        logger.debug('Creating Worker Manager sockets')

        self.zcontext = zmq.Context()
        self.mgmt_socket = self.zcontext.socket(zmq.REP)
        self.mgmt_socket.bind(self.config.get('mgmt'))
        self.zpoller = zmq.Poller()
        self.zpoller.register(self.mgmt_socket, zmq.POLLIN)
Example #16
0
    def create_sockets(self):
        """
        Creates the ZeroMQ sockets used by the vPoller Worker Manager

        """
        logger.debug('Creating Worker Manager sockets')

        self.zcontext = zmq.Context()
        self.mgmt_socket = self.zcontext.socket(zmq.REP)
        self.mgmt_socket.bind(self.config.get('mgmt'))
        self.zpoller = zmq.Poller()
        self.zpoller.register(self.mgmt_socket, zmq.POLLIN)
Example #17
0
    def process_client_msg(self, msg):
        """
        Processes a client message received on the vPoller Worker socket

        The message is passed to the VSphereAgent object of the
        respective vSphere host in order to do the actual polling.

        Args:
            msg (dict): Client message for processing

        An example message for discovering the hosts could be:

            {
                "method":   "host.discover",
                "hostname": "vc01.example.org",
            }

        An example message for polling a datastore property could be:

            {
                "method":   "datastore.poll",
                "hostname": "vc01.example.org",
                "info.url": "ds:///vmfs/volumes/5190e2a7-d2b7c58e-b1e2/",
                "property": "summary.capacity"
            }

        """
        logger.debug('Processing client message: %s', msg)

        if not isinstance(msg, dict):
            return {
                'success': 1,
                'msg':
                'Expected a JSON message, received {}'.format(msg.__class__)
            }

        task = registry.get(msg.get('method'))
        agent = self.agents.get(msg.get('hostname'))

        if not task:
            return {'success': 1, 'msg': 'Unknown or missing task/method name'}

        if not agent:
            return {'success': 1, 'msg': 'Unknown or missing agent name'}

        if not validate_message(msg=msg, required=task.required):
            return {'success': 1, 'msg': 'Invalid task request'}

        result = task.function(agent, msg)

        return result
Example #18
0
    def distribute_tasks(self):
        """
        Distributes tasks from clients to workers for processing

        """
        socks = dict(self.zpoller.poll(1000))

        # Forward task from frontend to backend socket
        if socks.get(self.frontend) == zmq.POLLIN:
            logger.debug('Message received on frontend socket')
            task = self.frontend.recv()
            more = self.frontend.getsockopt(zmq.RCVMORE)
            if more:
                self.backend.send(task, zmq.SNDMORE)
            else:
                self.backend.send(task)
            logger.debug(
                'Sending message to backend socket: %s',
                task
            )

        # Forward result from backend to frontend socket
        if socks.get(self.backend) == zmq.POLLIN:
            logger.debug('Message received on backend socket')
            result = self.backend.recv()
            more = self.backend.getsockopt(zmq.RCVMORE)
            if more:
                self.frontend.send(result, zmq.SNDMORE)
            else:
                self.frontend.send(result)
            logger.debug(
                'Sending message to frontend socket: %s',
                result
            )
Example #19
0
    def distribute_tasks(self):
        """
        Distributes tasks from clients to workers for processing

        """
        socks = dict(self.zpoller.poll(1000))

        # Forward task from frontend to backend socket
        if socks.get(self.frontend) == zmq.POLLIN:
            logger.debug('Message received on frontend socket')
            task = self.frontend.recv()
            more = self.frontend.getsockopt(zmq.RCVMORE)
            if more:
                self.backend.send(task, zmq.SNDMORE)
            else:
                self.backend.send(task)
            logger.debug('Sending message to backend socket: %s', task)

        # Forward result from backend to frontend socket
        if socks.get(self.backend) == zmq.POLLIN:
            logger.debug('Message received on backend socket')
            result = self.backend.recv()
            more = self.backend.getsockopt(zmq.RCVMORE)
            if more:
                self.frontend.send(result, zmq.SNDMORE)
            else:
                self.frontend.send(result)
            logger.debug('Sending message to frontend socket: %s', result)
Example #20
0
    def process_client_msg(self, msg):
        """
        Processes a client message received on the vPoller Worker socket

        The message is passed to the VSphereAgent object of the
        respective vSphere host in order to do the actual polling.

        Args:
            msg (dict): Client message for processing

        An example message for discovering the hosts could be:

            {
                "method":   "host.discover",
                "hostname": "vc01.example.org",
            }

        An example message for polling a datastore property could be:

            {
                "method":   "datastore.poll",
                "hostname": "vc01.example.org",
                "info.url": "ds:///vmfs/volumes/5190e2a7-d2b7c58e-b1e2/",
                "property": "summary.capacity"
            }

        """
        logger.debug('Processing client message: %s', msg)

        if not isinstance(msg, dict):
            return {
                'success': 1,
                'msg': 'Expected a JSON message, received {}'.format(msg.__class__)
            }

        task = registry.get(msg.get('method'))
        agent = self.agents.get(msg.get('hostname'))

        if not task:
            return {'success': 1, 'msg': 'Unknown or missing task/method name'}

        if not agent:
            return {'success': 1, 'msg': 'Unknown or missing agent name'}

        if not validate_message(msg=msg, required=task.required):
            return {'success': 1, 'msg': 'Invalid task request'}

        result = task.function(agent, msg)

        return result
Example #21
0
 def wrapper(*args, **kwargs):
     logger.debug('Executing task %s', name)
     try:
         result = fn(*args, **kwargs)
     except Exception as e:
         tb = format_exc()
         result = {
             'success': 1,
             'msg': 'Task {} failed'.format(name),
             'traceback': tb
         }
         logger.warning('Task %s failed: %s', name, tb)
     finally:
         logger.debug('Returning result from task %s: %s', name, result)
         return result
Example #22
0
    def load_config(self):
        """
        Load the vPoller Proxy Manager configuration settings

        """
        logger.debug('Loading config file %s', self.config_file)

        parser = ConfigParser(self.config_defaults)
        parser.read(self.config_file)

        self.config['mgmt'] = parser.get('proxy', 'mgmt')
        self.config['frontend'] = parser.get('proxy', 'frontend')
        self.config['backend'] = parser.get('proxy', 'backend')

        logger.debug('Proxy Manager configuration: %s', self.config)
Example #23
0
    def load_config(self):
        """
        Load the vPoller Proxy Manager configuration settings

        """
        logger.debug('Loading config file %s', self.config_file)

        parser = ConfigParser(self.config_defaults)
        parser.read(self.config_file)

        self.config['mgmt'] = parser.get('proxy', 'mgmt')
        self.config['frontend'] = parser.get('proxy', 'frontend')
        self.config['backend'] = parser.get('proxy', 'backend')

        logger.debug(
            'Proxy Manager configuration: %s',
            self.config
        )
Example #24
0
def validate_message(msg, required):
    """
    Helper method for validating a client message

    Returns:
        bool: True if message has been successfully validated

    """
    if not required:
        return True

    logger.debug('Validating client message, required to have: %s', required)

    # Check if we have the required message attributes
    if not all(k in msg for k in required):
        logger.debug('Required message keys are missing')
        return False

    logger.debug('Client message successfully validated')

    return True
Example #25
0
def validate_message(msg, required):
    """
    Helper method for validating a client message

    Returns:
        bool: True if message has been successfully validated

    """
    if not required:
        return True

    logger.debug(
        'Validating client message, required to have: %s',
        required
    )

    # Check if we have the required message attributes
    if not all(k in msg for k in required):
        logger.debug('Required message keys are missing')
        return False

    logger.debug('Client message successfully validated')

    return True
Example #26
0
    def run(self, msg):
        """
        Main vPoller Client method

        Partially based on the Lazy Pirate Pattern:

        http://zguide.zeromq.org/py:all#Client-Side-Reliability-Lazy-Pirate-Pattern

        Args:
            msg (dict): The client message to send

        """
        logger.debug('Endpoint to connect to: %s', self.endpoint)
        logger.debug('Timeout of request: %s ms', self.timeout)
        logger.debug('Number of retries: %d', self.retries)
        logger.debug('Message to be sent: %s', msg)

        self.zcontext = zmq.Context()
        self.zclient = self.zcontext.socket(zmq.REQ)
        self.zclient.connect(self.endpoint)
        self.zclient.setsockopt(zmq.LINGER, 0)
        self.zpoller = zmq.Poller()
        self.zpoller.register(self.zclient, zmq.POLLIN)
        result = None

        while self.retries > 0:
            logger.debug('Sending client message...')

            # Send our message out
            self.zclient.send_json(msg)
            socks = dict(self.zpoller.poll(self.timeout))

            # Do we have a reply?
            if socks.get(self.zclient) == zmq.POLLIN:
                logger.debug('Received response on client socket')
                result = self.zclient.recv_unicode()
                logger.debug('Received message was: %s', result)
                break
            else:
                # We didn't get a reply back from the server, let's retry
                self.retries -= 1
                logger.warning('Did not receive response, retrying...')

                # Socket is confused. Close and remove it.
                logger.debug(
                    'Closing sockets and re-establishing connection...')
                self.zclient.close()
                self.zpoller.unregister(self.zclient)

                # Re-establish the connection
                logger.debug('Re-establishing connection to endpoint: %s',
                             self.endpoint)
                self.zclient = self.zcontext.socket(zmq.REQ)
                self.zclient.connect(self.endpoint)
                self.zclient.setsockopt(zmq.LINGER, 0)
                self.zpoller.register(self.zclient, zmq.POLLIN)

        # Close the socket and terminate the context
        logger.debug('Closing sockets and exiting')
        self.zclient.close()
        self.zpoller.unregister(self.zclient)
        self.zcontext.term()

        # Did we have any result reply at all?
        if result is None:
            logger.error('Did not receive response, aborting...')
            r = {'success': 1, 'msg': 'Did not receive response, aborting...'}
            return json.dumps(r, ensure_ascii=False)

        return result
Example #27
0
    def run(self, msg):
        """
        Main vPoller Client method

        Partially based on the Lazy Pirate Pattern:

        http://zguide.zeromq.org/py:all#Client-Side-Reliability-Lazy-Pirate-Pattern

        Args:
            msg (dict): The client message to send

        """
        logger.debug('Endpoint to connect to: %s', self.endpoint)
        logger.debug('Timeout of request: %s ms', self.timeout)
        logger.debug('Number of retries: %d', self.retries)
        logger.debug('Message to be sent: %s', msg)

        self.zcontext = zmq.Context()
        self.zclient = self.zcontext.socket(zmq.REQ)
        self.zclient.connect(self.endpoint)
        self.zclient.setsockopt(zmq.LINGER, 0)
        self.zpoller = zmq.Poller()
        self.zpoller.register(self.zclient, zmq.POLLIN)
        result = None

        while self.retries > 0:
            logger.debug('Sending client message...')

            # Send our message out
            self.zclient.send_json(msg)
            socks = dict(self.zpoller.poll(self.timeout))

            # Do we have a reply?
            if socks.get(self.zclient) == zmq.POLLIN:
                logger.debug('Received response on client socket')
                result = self.zclient.recv_unicode()
                logger.debug('Received message was: %s', result)
                break
            else:
                # We didn't get a reply back from the server, let's retry
                self.retries -= 1
                logger.warning(
                    'Did not receive response, retrying...'
                )

                # Socket is confused. Close and remove it.
                logger.debug('Closing sockets and re-establishing connection...')
                self.zclient.close()
                self.zpoller.unregister(self.zclient)

                # Re-establish the connection
                logger.debug(
                    'Re-establishing connection to endpoint: %s',
                    self.endpoint
                )
                self.zclient = self.zcontext.socket(zmq.REQ)
                self.zclient.connect(self.endpoint)
                self.zclient.setsockopt(zmq.LINGER, 0)
                self.zpoller.register(self.zclient, zmq.POLLIN)

        # Close the socket and terminate the context
        logger.debug('Closing sockets and exiting')
        self.zclient.close()
        self.zpoller.unregister(self.zclient)
        self.zcontext.term()

        # Did we have any result reply at all?
        if result is None:
            logger.error(
                'Did not receive response, aborting...'
            )
            r = {
                'success': 1,
                'msg': 'Did not receive response, aborting...'
            }
            return json.dumps(r, ensure_ascii=False)

        return result