Ejemplo n.º 1
0
class Launcher(object):
    """
    Connects to Redis instance, listens for jobs, and spawns new threads using defined
    launcher_adapter
    """

    adapter = None
    ip_address = None
    launcher = None
    tag = None
    pool = None

    def __init__(self, site, tag="", logger=None, overwatch_id=False):
        """
        Initialize the Launcher instance

        Keyword arguments:
        site -- site object with relevant information to run
        tag -- optional string describing launcher. Defined in site.LAUNCHER_REGISTER
        logger -- logger instance (default = None)
        overwatch_id -- id for optional overwatcher instance
        """
        # Get the logger Instance
        self.logger = logger

        # Save passed-in variables
        self.site = site
        self.tag = tag
        self.overwatch_id = overwatch_id

        # Retrieve settings for this Launcher
        self.get_settings()

        # Check if additional params in self.launcher
        self.check_settings()

        # Load the adapter
        self.load_adapter()

        # Connect to Redis for communications
        self.connect_to_redis()

        # For loop in self.run
        self.running = True

        self.run()

    def run(self):
        """The core process of the Launcher instance"""

        # Set up overwatcher
        if self.overwatch_id:
            self.ow_registrar = Registrar(site=self.site,
                                          ow_type="launcher",
                                          ow_id=self.overwatch_id)
            self.ow_registrar.register({
                "site_id":
                json.dumps(self.launcher.get('site_tag')),
                "job_list":
                self.job_list
            })

        try:
            timer = 0
            # This is the server portion of the code
            while self.running:
                # Have Registrar update status every second
                if round(timer % 1, 1) in (0.0, 1.0):
                    if self.overwatch_id:
                        #self.ow_registrar.update({"site_id":self.site.ID,
                        self.ow_registrar.update({
                            "site_id":
                            json.dumps(self.launcher.get('site_tag')),
                            "job_list":
                            self.job_list
                        })
                        #self.ow_registrar.update({"job_list":self.job_list})

                # Look for a new command
                # This will throw a redis.exceptions.ConnectionError if redis is unreachable
                #command = self.redis.brpop(["RAPD_JOBS",], 5)
                try:
                    while self.redis.llen(self.job_list) != 0:
                        command = self.redis.rpop(self.job_list)
                        # Handle the message
                        if command:
                            self.handle_command(json.loads(command))

                            # Only run 1 command
                            # self.running = False
                            # break
                    # sleep a little when jobs aren't coming in.
                    time.sleep(0.2)
                    timer += 0.2
                except redis.exceptions.ConnectionError:
                    if self.logger:
                        self.logger.exception(
                            "Remote Redis is not up. Waiting for Sentinal to switch to new host"
                        )
                    time.sleep(1)

        except KeyboardInterrupt:
            self.stop()

    def stop(self):
        """Stop everything smoothly."""
        self.running = False
        # Close the file lock handle
        close_lock_file()
        # Try to close the pool. Python bugs gives errors!
        if self.pool:
            self.pool.close()
            self.pool.join()
        # Tell overwatch it is closing
        if self.overwatch_id:
            self.ow_registrar.stop()

    def connect_to_redis(self):
        """Connect to the redis instance"""
        redis_database = importlib.import_module('database.redis_adapter')

        self.redis = redis_database.Database(
            settings=self.site.CONTROL_DATABASE_SETTINGS, logger=self.logger)

    def handle_command(self, command):
        """
        Handle an incoming command

        Keyword arguments:
        command -- command from redis
        """
        print "handle_command"
        pprint(command)

        # Split up the command
        message = command
        if self.logger:
            self.logger.debug("Command received channel:%s  message: %s",
                              self.job_list, message)

        # Use the adapter to launch
        #self.adapter(self.site, message, self.launcher)
        # If running thru a shell limit the number of running processes
        if self.pool:
            self.pool.apply_async(
                self.adapter(self.site, message, self.launcher))
        else:
            self.adapter(self.site, message, self.launcher)

    def get_settings(self):
        """
        Get the settings for this Launcher based on ip address and tag
        """

        # Get IP Address
        self.ip_address = utils.site.get_ip_address()
        #print self.ip_address
        if self.logger:
            self.logger.debug("Found ip address to be %s", self.ip_address)

        # Save typing
        launchers = self.site.LAUNCHER_SETTINGS["LAUNCHER_SPECIFICATIONS"]

        # Look for the launcher matching this ip_address and the input tag
        possible_tags = []
        for launcher in launchers:
            #print launcher
            if launcher.get('ip_address') == self.ip_address and launcher.get(
                    'tag') == self.tag:
                self.launcher = launcher
                break
            elif launcher.get('ip_address') == self.ip_address:
                possible_tags.append(launcher.get('tag'))

        # No launcher adapter
        if self.launcher is None:

            # No launchers for this IP address
            if len(possible_tags) == 0:
                print "  There are no launcher adapters registered for this ip address"
            # IP Address in launchers, but not the input tag
            else:
                print text.error + "There is a launcher adapter registered for thi\
s IP address (%s), but not for the input tag (%s)" % (self.ip_address,
                                                      self.tag)
                print "  Available tags for this IP address:"
                for tag in possible_tags:
                    print "    %s" % tag
                print text.stop

            # Exit in error state
            sys.exit(9)
        else:
            # Get the job_list to watch for this launcher
            self.job_list = self.launcher.get('job_list')

    def check_settings(self):
        """Check if additional params in self.launcher need setup."""
        # Check if a multiprocessing.Pool needs to be setup for launcher adapter.
        if self.tag == 'shell':
            if self.launcher.get('pool_size', False):
                size = self.launcher.get('pool_size')
            else:
                size = total_nproc() - 1
            # Make sure its an integer
            self.pool = mp_pool(int(size))

    def load_adapter(self):
        """Find and load the adapter"""

        # Import the database adapter as database module

        self.adapter = load_module(
            seek_module=self.launcher["adapter"],
            directories=self.site.LAUNCHER_SETTINGS[
                "RAPD_LAUNCHER_ADAPTER_DIRECTORIES"]).LauncherAdapter

        if self.logger:
            self.logger.debug(self.adapter)
Ejemplo n.º 2
0
class Launcher_Manager(Thread):
    """
    Listens to the 'RAPD_JOBS'list and sends jobs to proper
    launcher.
    """
    def __init__(self, site, logger=False, overwatch_id=False):
        """
        Initialize the Launcher instance

        Keyword arguments:
        site -- site object with relevant information to run
        redis -- Redis instance for communication
        logger -- logger instance (default = None)
        overwatch_id -- id for optional overwatcher instance
        """
        # If logger is passed in from main use that...
        if logger:
            self.logger = logger
        else:
            # Otherwise, get the rapd logger
            self.logger = logging.getLogger("RAPDLogger")

        # Initialize the thread
        Thread.__init__(self)

        # Save passed-in variables
        self.site = site
        self.overwatch_id = overwatch_id

        self.running = True
        self.timer = 0
        self.job_list = []

        self.connect_to_redis()

        self.start()

    def run(self):
        """The core process of the Launcher instance"""

        # Set up overwatcher
        if self.overwatch_id:
            self.ow_registrar = Registrar(site=self.site,
                                          ow_type="launch_manager",
                                          ow_id=self.overwatch_id)
            self.ow_registrar.register()

        # Get the initial possible jobs lists
        full_job_list = [
            x.get('job_list')
            for x in self.site.LAUNCHER_SETTINGS["LAUNCHER_SPECIFICATIONS"]
        ]

        try:
            # This is the server portion of the code
            while self.running:
                # Get updated job list by checking which launchers are running
                # Reassign jobs if launcher(s) status changes
                if round(self.timer % TIMER, 1) == 1.0:
                    try:
                        # Have Registrar update status
                        if self.overwatch_id:
                            self.ow_registrar.update()

                        # Check which launchers are running
                        temp = [
                            l for l in full_job_list
                            if self.redis.get("OW:" + l)
                        ]

                        # Determine which launcher(s) went offline
                        offline = [
                            line for line in self.job_list
                            if temp.count(line) == False
                        ]
                        if len(offline) > 0:
                            # Pop waiting jobs off their job_lists and push back in RAPD_JOBS for reassignment.
                            for _l in offline:
                                while self.redis.llen(_l) != 0:
                                    self.redis.rpoplpush(_l, 'RAPD_JOBS')

                        # Determine which launcher(s) came online (Also runs at startup!)
                        online = [
                            line for line in temp
                            if self.job_list.count(line) == False
                        ]
                        if len(online) > 0:
                            # Pop jobs off RAPD_JOBS_WAITING and push back onto RAPD_JOBS for reassignment.
                            while self.redis.llen('RAPD_JOBS_WAITING') != 0:
                                self.redis.rpoplpush('RAPD_JOBS_WAITING',
                                                     'RAPD_JOBS')

                        # Update the self.job_list
                        self.job_list = temp

                    except redis.exceptions.ConnectionError:
                        if self.logger:
                            self.logger.exception(
                                "Remote Redis is not up. Waiting for Sentinal to switch to new host"
                            )
                        time.sleep(1)

                # Look for a new command
                # This will throw a redis.exceptions.ConnectionError if redis is unreachable
                #command = self.redis.brpop(["RAPD_JOBS",], 5)
                try:
                    while self.redis.llen("RAPD_JOBS") != 0:
                        command = self.redis.rpop("RAPD_JOBS")
                        # Handle the message
                        if command:
                            self.push_command(json.loads(command))
                            # Only run 1 command
                            # self.running = False
                            # break
                    # sleep a little when jobs aren't coming in.
                    time.sleep(0.2)
                    self.timer += 0.2
                except redis.exceptions.ConnectionError:
                    if self.logger:
                        self.logger.exception(
                            "Remote Redis is not up. Waiting for Sentinal to switch to new host"
                        )
                    time.sleep(1)

        except KeyboardInterrupt:
            self.stop()

    def stop(self):
        if self.logger:
            self.logger.debug('shutting down launcher manager')
        self.running = False
        if self.overwatch_id:
            self.ow_registrar.stop()

    def set_launcher(self, command=False, site_tag=False):
        """Find the correct running launcher to launch a specific job COMMAND"""
        # list of commands to look for in the 'job_types'
        # If the highest prioity launcher is 'ALL', it is chosen.
        search = ['ALL']
        if command:
            search.append(command)

        # Search through launchers
        for x in self.site.LAUNCHER_SETTINGS["LAUNCHER_SPECIFICATIONS"]:
            # Is launcher running?
            if x.get('job_list') in self.job_list:
                # check if its job type matches the command
                for j in search:
                    if j in x.get('job_types'):
                        # Check if launcher is accepting jobs for this beamline
                        if site_tag:
                            if site_tag in x.get('site_tag'):
                                return (x.get('job_list'), x.get('launch_dir'))
                        else:
                            return (x.get('job_list'), x.get('launch_dir'))

        # Return False if no running launchers are appropriate
        return (False, False)

    def push_command(self, command):
        """
        Handle an incoming command

        Keyword arguments:
        command -- command from redis
        """
        print "push_command"
        #pprint(command)

        # Split up the command
        message = command
        if self.logger:
            self.logger.debug(
                "Command received channel:RAPD_JOBS  message: %s", message)

        # get the site_tag from the image header to determine beamline where is was collected.
        site_tag = launch_tools.get_site_tag(message)

        # get the correct running launcher and launch_dir
        launcher, launch_dir = self.set_launcher(message['command'], site_tag)

        if message['command'].startswith('INTEGRATE'):
            print 'type: %s...%s' % (message['preferences']['xdsinp'][:100],
                                     message['preferences']['xdsinp'][-100:])

        if launcher:
            # Update preferences to be in server run mode
            if not message.get("preferences"):
                message["preferences"] = {}
            message["preferences"]["run_mode"] = "server"

            # Pass along the Launch directory
            if not message.get("directories"):
                message["directories"] = {}
            message["directories"]["launch_dir"] = launch_dir

            # Push the job on the correct launcher job list
            self.redis.lpush(launcher, json.dumps(message))
            if self.logger:
                self.logger.debug("Command sent channel:%s  message: %s",
                                  launcher, message)
        else:
            self.redis.lpush('RAPD_JOBS_WAITING', json.dumps(message))
            if self.logger:
                self.logger.debug(
                    "Could not find a running launcher for this job. Putting job on RAPD_JOBS_WAITING list"
                )

    def connect_to_redis(self):
        """Connect to the redis instance"""
        redis_database = importlib.import_module('database.redis_adapter')

        #self.redis_db = redis_database.Database(settings=self.site.CONTROL_DATABASE_SETTINGS)
        #self.redis = self.redis_db.connect_to_redis()
        #self.redis = redis_database.Database(settings=self.site.CONTROL_DATABASE_SETTINGS)
        self.redis = redis_database.Database(
            settings=self.site.CONTROL_DATABASE_SETTINGS, logger=self.logger)
Ejemplo n.º 3
0
class Launcher(object):
    """
    Connects to Redis instance, listens for jobs, and spawns new threads using defined
    launcher_adapter
    """

    adapter = None
    #adapter_file = None
    #database = None
    # address = None
    ip_address = None
    #job_types = None
    launcher = None
    #port = None
    tag = None

    def __init__(self, site, tag="", logger=None, overwatch_id=False):
        """
        Initialize the Launcher instance

        Keyword arguments:
        site -- site object with relevant information to run
        tag -- optional string describing launcher. Defined in site.LAUNCHER_REGISTER
        logger -- logger instance (default = None)
        overwatch_id -- id for optional overwatcher instance
        """
        # Get the logger Instance
        self.logger = logger

        # Save passed-in variables
        self.site = site
        self.tag = tag
        self.overwatch_id = overwatch_id

        # Retrieve settings for this Launcher
        self.get_settings()

        # Load the adapter
        self.load_adapter()

        # Connect to Redis for communications
        self.connect_to_redis()

        # For loop in self.run
        self.running = True

        self.run()

    def run(self):
        """The core process of the Launcher instance"""

        # Set up overwatcher
        if self.overwatch_id:
            self.ow_registrar = Registrar(site=self.site,
                                          ow_type="launcher",
                                          ow_id=self.overwatch_id)
            self.ow_registrar.register({"site_id":self.site.ID,
                                        "job_list":self.job_list})

        try:
            # This is the server portion of the code
            while self.running:
                # Have Registrar update status
                if self.overwatch_id:
                    self.ow_registrar.update({"site_id":self.site.ID,
                                              "job_list":self.job_list})

                # Look for a new command
                # This will throw a redis.exceptions.ConnectionError if redis is unreachable
                #command = self.redis.brpop(["RAPD_JOBS",], 5)
                try:
                    while self.redis.llen(self.job_list) != 0:
                        command = self.redis.rpop(self.job_list)
                        # Handle the message
                        if command:
                            self.handle_command(json.loads(command))

                            # Only run 1 command
                            # self.running = False
                            # break
                    # sleep a little when jobs aren't coming in.
                    time.sleep(0.2)
                except redis.exceptions.ConnectionError:
                    if self.logger:
                        self.logger.exception("Remote Redis is not up. Waiting for Sentinal to switch to new host")
                    time.sleep(1)

        except KeyboardInterrupt:
            self.stop()

    def stop(self):
        """Stop everything smoothly."""
        self.running = False
        if self.overwatch_id:
            self.ow_registrar.stop()
        self.redis_database.stop()

    def connect_to_redis(self):
        """Connect to the redis instance"""
        redis_database = importlib.import_module('database.redis_adapter')

        #self.redis_database = redis_database.Database(settings=self.site.CONTROL_DATABASE_SETTINGS)
        #self.redis = self.redis_database.connect_to_redis()
        #self.redis = redis_database.Database(settings=self.site.CONTROL_DATABASE_SETTINGS)
        self.redis = redis_database.Database(settings=self.site.CONTROL_DATABASE_SETTINGS, 
                                             logger=self.logger)

    def handle_command(self, command):
        """
        Handle an incoming command

        Keyword arguments:
        command -- command from redis
        """
        print "handle_command"
        pprint(command)

        # Split up the command
        message = command
        if self.logger:
            self.logger.debug("Command received channel:%s  message: %s", self.job_list, message)

        # Use the adapter to launch
        self.adapter(self.site, message, self.launcher)
        #Thread(target=self.adapter, args=(self.site, message, self.launcher)).start()

    def get_settings(self):
        """
        Get the settings for this Launcher based on ip address and tag
        """

        # Save typing
        #launchers = self.site.LAUNCHER_SETTINGS["LAUNCHER_REGISTER"]

        # Get IP Address
        self.ip_address = utils.site.get_ip_address()
        #print self.ip_address
        if self.logger:
            self.logger.debug("Found ip address to be %s", self.ip_address)
        """
        # Look for the launcher matching this ip_address and the input tag
        possible_tags = []
        for launcher in launchers:
            if launcher[0] == self.ip_address and launcher[1] == self.tag:
                self.launcher = launcher
                break
            elif launcher[0] == self.ip_address:
                possible_tags.append(launcher[1])
        """

        # Save typing
        launchers = self.site.LAUNCHER_SETTINGS["LAUNCHER_SPECIFICATIONS"]

        # Look for the launcher matching this ip_address and the input tag
        possible_tags = []
        for launcher in launchers:
            #print launcher
            if launcher.get('ip_address') == self.ip_address and launcher.get('tag') == self.tag:
                self.launcher = launcher
                break
            elif launcher.get('ip_address') == self.ip_address:
                possible_tags.append(launcher.get('tag'))

        # No launcher adapter
        if self.launcher is None:

            # No launchers for this IP address
            if len(possible_tags) == 0:
                print "  There are no launcher adapters registered for this ip address"
            # IP Address in launchers, but not the input tag
            else:
                print text.error + "There is a launcher adapter registered for thi\
s IP address (%s), but not for the input tag (%s)" % (self.ip_address, self.tag)
                print "  Available tags for this IP address:"
                for tag in possible_tags:
                    print "    %s" % tag
                print text.stop

            # Exit in error state
            sys.exit(9)
        else:
            # Get the job_list to watch for this launcher
            self.job_list = self.launcher.get('job_list')

    def load_adapter(self):
        """Find and load the adapter"""

        # Import the database adapter as database module
        self.adapter = load_module(
            seek_module=self.launcher["adapter"],
            directories=self.site.LAUNCHER_SETTINGS["RAPD_LAUNCHER_ADAPTER_DIRECTORIES"]).LauncherAdapter
        if self.logger:
            self.logger.debug(self.adapter)
Ejemplo n.º 4
0
class Launcher_Manager(threading.Thread):
    """
    Listens to the 'RAPD_JOBS'list and sends jobs to proper
    launcher.
    """
    def __init__(self, site, logger=False, overwatch_id=False):
        """
        Initialize the Launcher instance

        Keyword arguments:
        site -- site object with relevant information to run
        redis -- Redis instance for communication
        logger -- logger instance (default = None)
        overwatch_id -- id for optional overwatcher instance
        """
        # If logger is passed in from main use that...
        if logger:
            self.logger = logger
        else:
            # Otherwise, get the rapd logger
            self.logger = logging.getLogger("RAPDLogger")

        # Initialize the thread
        threading.Thread.__init__(self)

        # Save passed-in variables
        self.site = site
        self.overwatch_id = overwatch_id

        self.running = True
        self.timer = 0
        self.job_list = []

        self.connect_to_redis()

        self.start()

    def run(self):
        """The core process of the Launcher instance"""

        # Set up overwatcher
        if self.overwatch_id:
            self.ow_registrar = Registrar(site=self.site,
                                          ow_type="launch_manager",
                                          ow_id=self.overwatch_id)
            self.ow_registrar.register()

        # Get the initial possible jobs lists
        full_job_list = [x.get('job_list') for x in self.site.LAUNCHER_SETTINGS["LAUNCHER_SPECIFICATIONS"]]

        try:
            # This is the server portion of the code
            while self.running:
                # Have Registrar update status
                #if self.overwatch_id:
                #    self.ow_registrar.update()

                # Get updated job list by checking which launchers are running
                # Reassign jobs if launcher(s) status changes
                if round(self.timer%TIMER,1) == 1.0:
                    try:
                        # Have Registrar update status
                        if self.overwatch_id:
                            self.ow_registrar.update()

                        # Check which launchers are running
                        temp = [l for l in full_job_list if self.redis.get("OW:"+l)]

                        # Determine which launcher(s) went offline
                        offline = [line for line in self.job_list if temp.count(line) == False]
                        if len(offline) > 0:
                            # Pop waiting jobs off their job_lists and push back in RAPD_JOBS for reassignment.
                            for _l in offline:
                                while self.redis.llen(_l) != 0:
                                    self.redis.rpoplpush(_l, 'RAPD_JOBS')

                        # Determine which launcher(s) came online (Also runs at startup!)
                        online = [line for line in temp if self.job_list.count(line) == False]
                        if len(online) > 0:
                            # Pop jobs off RAPD_JOBS_WAITING and push back onto RAPD_JOBS for reassignment.
                            while self.redis.llen('RAPD_JOBS_WAITING') != 0:
                                self.redis.rpoplpush('RAPD_JOBS_WAITING', 'RAPD_JOBS')

                        # Update the self.job_list
                        self.job_list = temp

                    except redis.exceptions.ConnectionError:
                        if self.logger:
                            self.logger.exception("Remote Redis is not up. Waiting for Sentinal to switch to new host")
                        time.sleep(1)

                # Look for a new command
                # This will throw a redis.exceptions.ConnectionError if redis is unreachable
                #command = self.redis.brpop(["RAPD_JOBS",], 5)
                try:
                    while self.redis.llen("RAPD_JOBS") != 0:
                        command = self.redis.rpop("RAPD_JOBS")
                        # Handle the message
                        if command:
                            #self.push_command(json.loads(command))
                            self.push_command(json.loads(command))
                            # Only run 1 command
                            # self.running = False
                            # break
                    # sleep a little when jobs aren't coming in.
                    time.sleep(0.2)
                    self.timer += 0.2
                except redis.exceptions.ConnectionError:
                    if self.logger:
                        self.logger.exception("Remote Redis is not up. Waiting for Sentinal to switch to new host")
                    time.sleep(1)

        except KeyboardInterrupt:
            self.stop()

    def stop(self):
        if self.logger:
            self.logger.debug('shutting down launcher manager')
        self.running = False
        if self.overwatch_id:
            self.ow_registrar.stop()
        self.redis_db.stop()

    def set_launcher(self, command=False, site_tag=False):
        """Find the correct running launcher to launch a specific job COMMAND"""
        # list of commands to look for in the 'job_types'
        # If the highest prioity launcher is 'ALL', it is chosen.
        search = ['ALL']
        if command:
            search.append(command)

        # Search through launchers
        for x in self.site.LAUNCHER_SETTINGS["LAUNCHER_SPECIFICATIONS"]:
            # Is launcher running?
            if x.get('job_list') in self.job_list:
                # check if its job type matches the command
                for j in search:
                    if j in x.get('job_types'):
                        # Check if launcher is accepting jobs for this beamline
                        if site_tag:
                            if site_tag in x.get('site_tag'):
                                return (x.get('job_list'), x.get('launch_dir'))
                        else:
                            return (x.get('job_list'), x.get('launch_dir'))

        # Return False if no running launchers are appropriate
        return (False, False)

    def push_command(self, command):
        """
        Handle an incoming command

        Keyword arguments:
        command -- command from redis
        """
        print "push_command"
        #pprint(command)

        # Split up the command
        message = command
        if self.logger:
            self.logger.debug("Command received channel:RAPD_JOBS  message: %s", message)

        # get the site_tag from the image header to determine beamline where is was collected.
        site_tag = launch_tools.get_site_tag(message)

        # get the correct running launcher and launch_dir
        launcher, launch_dir = self.set_launcher(message['command'], site_tag)

        if message['command'].startswith('INTEGRATE'):
            print 'type: %s'%message['preferences']['xdsinp']

        if launcher:
            # Update preferences to be in server run mode
            if not message.get("preferences"):
                message["preferences"] = {}
            message["preferences"]["run_mode"] = "server"

            # Pass along the Launch directory
            if not message.get("directories"):
                message["directories"] = {}
            message["directories"]["launch_dir"] = launch_dir

            # Push the job on the correct launcher job list
            self.redis.lpush(launcher, json.dumps(message))
            if self.logger:
                self.logger.debug("Command sent channel:%s  message: %s", launcher, message)
        else:
            self.redis.lpush('RAPD_JOBS_WAITING', json.dumps(message))
            if self.logger:
                self.logger.debug("Could not find a running launcher for this job. Putting job on RAPD_JOBS_WAITING list")

    def connect_to_redis(self):
        """Connect to the redis instance"""
        redis_database = importlib.import_module('database.redis_adapter')

        #self.redis_db = redis_database.Database(settings=self.site.CONTROL_DATABASE_SETTINGS)
        #self.redis = self.redis_db.connect_to_redis()
        #self.redis = redis_database.Database(settings=self.site.CONTROL_DATABASE_SETTINGS)
        self.redis = redis_database.Database(settings=self.site.CONTROL_DATABASE_SETTINGS, 
                                             logger=self.logger)