diff --git a/awx/main/management/commands/run_fact_cache_receiver.py b/awx/main/management/commands/run_fact_cache_receiver.py index 0ed5b1e921..1526062c47 100644 --- a/awx/main/management/commands/run_fact_cache_receiver.py +++ b/awx/main/management/commands/run_fact_cache_receiver.py @@ -4,13 +4,35 @@ import logging from django.core.management.base import NoArgsCommand +from django.utils.timezone import now from awx.main.models import * # noqa +from awx.main.socket import Socket + +from pymongo import MongoClient logger = logging.getLogger('awx.main.commands.run_fact_cache_receiver') class FactCacheReceiver(object): - pass + + def __init__(self): + self.client = MongoClient('localhost', 27017) + + def process_fact_message(self, message): + host = message['host'] + facts = message['facts'] + host_db = self.client.host_facts + host_collection = host_db[host] + facts.update(dict(tower_host=host, datetime=now())) + host_collection.insert(facts) + + def run_receiver(self): + with Socket('fact_cache', 'r') as facts: + for message in facts.listen(): + print("Message received: " + str(message)) + if 'host' not in message or 'facts' not in message: + continue + self.process_fact_message(message) class Command(NoArgsCommand): ''' diff --git a/awx/main/socket.py b/awx/main/socket.py index 679b5f5fd0..39b252ae26 100644 --- a/awx/main/socket.py +++ b/awx/main/socket.py @@ -63,6 +63,7 @@ class Socket(object): settings.CALLBACK_CONSUMER_PORT), 'task_commands': settings.TASK_COMMAND_PORT, 'websocket': settings.SOCKETIO_NOTIFICATION_PORT, + 'fact_cache': settings.FACT_CACHE_PORT, }[self._bucket] def connect(self): diff --git a/awx/playbooks/scan_facts.yml b/awx/playbooks/scan_facts.yml index 252c284631..8e12ba75a3 100644 --- a/awx/playbooks/scan_facts.yml +++ b/awx/playbooks/scan_facts.yml @@ -1,5 +1,4 @@ - hosts: all - gather_facts: no tasks: - scan_packages: diff --git a/awx/plugins/fact_caching/tower.py b/awx/plugins/fact_caching/tower.py old mode 100644 new mode 100755 index 1f4122d493..73a44b33a0 --- a/awx/plugins/fact_caching/tower.py +++ b/awx/plugins/fact_caching/tower.py @@ -1,21 +1,70 @@ +# Copyright (c) 2015 Ansible, Inc. +# This file is a utility Ansible plugin that is not part of the AWX or Ansible +# packages. It does not import any code from either package, nor does its +# license apply to Ansible or AWX. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import sys +from ansible import constants as C from ansible.cache.base import BaseCacheModule -class TowerCacheModule(BaseCacheModule): +try: + import zmq +except Import: + print("pyzmq is required") + sys.exit(1) + +class CacheModule(BaseCacheModule): def __init__(self, *args, **kwargs): - pass + + # This is the local tower zmq connection + self._tower_connection = C.CACHE_PLUGIN_CONNECTION + try: + self.context = zmq.Context() + self.socket = self.context.socket(zmq.REQ) + self.socket.connect(self._tower_connection) + except Exception, e: + print("Connection to zeromq failed at %s" % str(self._tower_connection)) + sys.exit(1) def get(self, key): - pass + return {} # Temporary until we have some tower retrieval endpoints def set(self, key, value): - pass + self.socket.send_json(dict(host=key, facts=value)) + self.socket.recv() def keys(self): - pass + return [] def contains(self, key): - pass + return False def delete(self, key): pass @@ -24,4 +73,4 @@ class TowerCacheModule(BaseCacheModule): pass def copy(self): - pass + return dict() diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index fed14e4fa5..9f8a3b923e 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -510,6 +510,8 @@ TASK_COMMAND_PORT = 6559 SOCKETIO_NOTIFICATION_PORT = 6557 SOCKETIO_LISTEN_PORT = 8080 +FACT_CACHE_PORT = 6564 + ORG_ADMINS_CAN_SEE_ALL_USERS = True # Logging configuration.