Example #1
0
    def subclass_init(self):
        """Complete init for this subclass."""

        # -- modify options

        # add --cache-size if it is not specified
        if not "--cache-size" in self.options and not any([x.startswith("--cache-size=") for x in self.options]):
            self.options += ["--cache-size", "512"]

        # add --directory
        for i, option in enumerate(self.options):
            if option == "--directory" or option.startswith("--directory="):
                raise ValueError("The --directory should not be provided in extra_options")

        # add 'serve' before the rest of the options
        self.options.insert(0, "serve")

        # -- create the data folder if it does not already exists

        # get --server-tag entries
        server_tags = []
        for tag in self.server_tags:
            server_tags += ["--server-tag", tag]

        if not os.path.exists(os.path.join(self.data_path, "metadata")):
            self._console_file.write(
                "Creating data directory at %s (%s)\n" % (self.data_path, datetime.datetime.now().isoformat())
            )
            self._console_file.flush()
            command = (
                self.command_prefix
                + [self.executable_path]
                + [
                    "create",
                    "--server-name",
                    self._desired_name,
                    "--directory",
                    utils.translatePath(self.data_path),
                    "--log-file",
                    utils.translatePath(self.logfile_path),
                ]
                + server_tags
            )
            subprocess.check_call(command, stdout=self._console_file, stderr=subprocess.STDOUT)
Example #2
0
    def subclass_init(self):
        '''Complete init for this subclass.'''

        # -- modify options

        # add --cache-size if it is not specified
        if not '--cache-size' in self.options and not any(
            [x.startswith('--cache-size=') for x in self.options]):
            self.options += ['--cache-size', '512']

        # add --directory
        for i, option in enumerate(self.options):
            if option == '--directory' or option.startswith('--directory='):
                raise ValueError(
                    'The --directory should not be provided in extra_options')

        # add 'serve' before the rest of the options
        self.options.insert(0, 'serve')

        # -- create the data folder if it does not already exists

        # get --server-tag entries
        server_tags = []
        for tag in self.server_tags:
            server_tags += ['--server-tag', tag]

        if not os.path.exists(os.path.join(self.data_path, 'metadata')):
            self._console_file.write(
                "Creating data directory at %s (%s)\n" %
                (self.data_path, datetime.datetime.now().isoformat()))
            self._console_file.flush()
            command = self.command_prefix + [self.executable_path] + [
                'create', '--server-name', self._desired_name, '--directory',
                utils.translatePath(self.data_path), '--log-file',
                utils.translatePath(self.logfile_path)
            ] + server_tags
            subprocess.check_call(command,
                                  stdout=self._console_file,
                                  stderr=subprocess.STDOUT)
Example #3
0
    def start(self, wait_until_ready=True):
        '''Start up the server'''
        global runningServers

        assert not self.running, 'Trying to start a server where running = %r' % self.running
        self.returncode = None
        self.killed = False

        # -- setup options

        # - copy the options

        options = copy.copy(self.args)

        # - set the local_cluster_port

        if not '--client-port' in options and not any(
            [x.startswith('--client-port=') for x in options]):
            # allows resunder to know what port to block
            options += ['--client-port', str(self.local_cluster_port)]

        # - tls options

        if self.cluster.tlsKeyPath and self.cluster.tlsCertPath:
            options += [
                '--http-tls-key',
                utils.translatePath(self.cluster.tlsKeyPath),
                '--http-tls-cert',
                utils.translatePath(self.cluster.tlsCertPath),
                '--driver-tls-key',
                utils.translatePath(self.cluster.tlsKeyPath),
                '--driver-tls-cert',
                utils.translatePath(self.cluster.tlsCertPath),
                '--cluster-tls-key',
                utils.translatePath(self.cluster.tlsKeyPath),
                '--cluster-tls-cert',
                utils.translatePath(self.cluster.tlsCertPath),
                '--cluster-tls-ca',
                utils.translatePath(self.cluster.tlsCertPath)
            ]
            if platform.system() == 'Darwin':
                # because the driver will probably be using the system version of OpenSSL (old), enable TLSv1
                options += [
                    '--tls-min-protocol', 'TLSv1', '--tls-ciphers',
                    'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:AES256-SHA'
                ]

        # - log file

        options += ['--log-file', utils.translatePath(str(self.logfile_path))]

        # -- get the length of an exiting log file

        if os.path.isfile(self.logfile_path):
            self._existing_log_len = os.path.getsize(self.logfile_path)

        # -- set to join the cluster

        try:
            self.cluster._startLock.acquire()
            self.cluster._hasStartLock = self
            for peer in self.cluster.processes:
                if peer != self and peer.ready:
                    options += [
                        "--join", peer.host + ":" + str(peer.cluster_port)
                    ]
                    break
        finally:
            # release the lock if we are joining a running cluster
            if "--join" in options and self.cluster._hasStartLock is self:
                self.cluster._hasStartLock = None
                self.cluster._startLock.release()

        # -- allow subclasses to modify the options array

        self.subclass_options(options)  # in-place edit

        # -- start the process

        try:
            self._console_file.write(
                "Launching at %s:\n\t%s\n" %
                (datetime.datetime.now().isoformat(), " ".join(options)))
            self._console_file.flush()
            self.process = subprocess.Popen(options,
                                            stdout=self._console_file,
                                            stderr=subprocess.STDOUT,
                                            preexec_fn=os.setpgrp)

            if not self in runningServers:
                runningServers.append(self)

            # - start thread to tail output for needed info
            thread.start_new_thread(self.read_ports_from_log, ())

        except Exception:
            self.stop()
            raise

        finally:
            # - move console file if necessary
            if self._console_file_path and not os.path.exists(
                    self._console_file_path):
                os.rename(self._console_file.name, self._console_file_path)

        # -- wait until ready (if requested)
        if wait_until_ready:
            self.wait_until_ready()
Example #4
0
    def __init__(self,
                 cluster=None,
                 name=None,
                 console_output=None,
                 executable_path=None,
                 server_tags=None,
                 command_prefix=None,
                 extra_options=None,
                 wait_until_ready=True,
                 tls=None):
        global runningServers

        # -- validate/default input

        # - cluster
        assert tls in (None, False,
                       True), 'tls must be True, False, or None (False)'
        if cluster is None:
            cluster = Cluster(tls=tls is True)
        else:
            assert tls is None or tls is (
                cluster.tlsCertPath is None
            ), 'A server added to a cluster must have the same tls setting (cluster: %s vs %s)' % (
                cluster.tlsCertPath is None, tls)
        assert isinstance(
            cluster,
            Cluster), 'cluster must be a Cluster or None, got: %r' % cluster
        self.cluster = cluster
        self.cluster.processes.append(self)

        # - name/data_path
        assert isinstance(
            name,
            (str, unicode,
             None.__class__)), 'name was not an expected value: %r' % name
        if name is None:
            # default name and data_path
            name = '%s_%s' % (self.server_type,
                              self.cluster.metacluster.get_new_unique_id(
                                  server_type=self.server_type))
            data_path = self.genPath(name, self.cluster.output_folder)
        elif name == '.':
            # random name in the current directory
            name = '%s_%s' % (self.server_type,
                              self.cluster.metacluster.get_new_unique_id(
                                  server_type=self.server_type))
            data_path = self.genPath(name, os.path.realpath('.'))
        elif os.sep in name:  # if it looks like a path, it is one, possibly relative
            data_path = os.path.abspath(
                os.path.join(self.cluster.output_folder,
                             name))  # note: an absolute path survives this
            name = os.path.basename(name)
            if os.path.exists(data_path):
                assert os.path.isdir(
                    data_path
                ), 'The data_path was something other than a directory: %s' % data_path
                if os.path.isfile(os.path.join(data_path, 'log_file')):
                    # existing data folder, record server log file path
                    self.logfile_path = os.path.join(data_path, 'log_file')
                elif os.path.isfile(os.path.join(data_path, 'log_file.txt')):
                    # existing data folder, record server log file path
                    self.logfile_path = os.path.join(data_path, 'log_file.txt')
                else:
                    # folder for holding multiple server data folders
                    data_path = self.genPath(name, data_path)
            else:
                # specified path, use it exactly
                assert os.path.isdir(
                    os.path.dirname(data_path)
                ), 'The enclosing directory did not exist or was not a directory: %s' % data_path
        else:
            # just a name
            data_path = self.genPath(name, self.cluster.output_folder)
        self.data_path = data_path
        self._desired_name = name.replace('-', '_')

        # - console_output/console_file - can be: path, file-object, True/False
        if console_output is None:
            # default to stdout
            self._console_file_path = None
            self._console_file = sys.stdout
        elif console_output is False:
            # throw away file
            self._console_file_path = None
            self._console_file = tempfile.NamedTemporaryFile(mode='w+')
        elif console_output is True:
            # keep it with the data, but create it in the encosing folder until we are running
            self._console_file_path = os.path.join(self.data_path,
                                                   self._console_file_name)
            self._console_file = tempfile.NamedTemporaryFile(
                mode='w+', dir=os.path.dirname(self.data_path), delete=False)
        elif hasattr(console_output, 'write'):
            # file-like object:
            self._console_file_path = None
            self._console_file = console_output
        else:
            # a path
            assert isinstance(
                console_output,
                (str, unicode)), 'Unknown console_output: %r' % console_output
            console_output = os.path.realpath(console_output)
            assert os.path.isdir(
                os.path.dirname(console_output)
            ), 'console_output parent directory was not a folder: %r' % console_output
            assert os.path.isfile(console_output) or not os.path.exists(
                console_output
            ), 'console_output location was not useable: %r' % console_output
            self._console_file_path = console_output
            self._console_file = open(console_output, 'a')

        # - server_tags
        if server_tags is None:
            self.server_tags = []
        elif hasattr(server_tags,
                     '__iter__') and not hasattr(server_tags, 'capitalize'):
            self.server_tags = [str(x) for x in server_tags]
        else:
            self.server_tags = [str(server_tags)]

        # - executable_path
        if executable_path is None:
            executable_path = utils.find_rethinkdb_executable()
        assert os.access(executable_path,
                         os.X_OK), "no such executable: %r" % executable_path
        self.executable_path = executable_path

        # - command_prefix
        if command_prefix is None:
            self.command_prefix = []
        elif not hasattr(command_prefix, '__iter__'):
            raise ValueError(
                'command_prefix must be an array of command line options, got: %r'
                % command_prefix)
        else:
            self.command_prefix = command_prefix

        # - extra_options
        self.options = []
        if extra_options is None:
            extra_options = []
        elif not hasattr(extra_options, '__iter__'):
            raise ValueError(
                'extra_options must be an array of command line options, got: %r'
                % extra_options)
        else:
            extra_options = [str(x) for x in extra_options]

        # -- defaults

        if not '--bind' in extra_options and not any(
            [x.startswith('--bind=') for x in extra_options]):
            self.options += ['--bind', 'all']

        if not '--cluster-port' in extra_options and not any(
            [x.startswith('--cluster-port=') for x in extra_options]):
            self.options += ['--cluster-port', '0']

        if not '--driver-port' in extra_options and not any(
            [x.startswith('--driver-port=') for x in extra_options]):
            self.options += ['--driver-port', '0']

        if not '--http-port' in extra_options and not any(
            [x.startswith('--http-port=') for x in extra_options]):
            self.options += ['--http-port', '0']

        for i, option in enumerate(extra_options or []):
            if option == '--log-file':
                assert len(
                    self.options
                ) > i + 1, '--log-file specified in options without a path'
                self.logfile_path = utils.translatePath(
                    os.path.realpath(extra_options[i + 1]))
                del extra_options[i + 1]
                del extra_options[i]
                break
            elif option.startswith('--log-file='):
                self.logfile_path = utils.translatePath(
                    os.path.realpath(option[len('--log-file='):].strip('\'"')))
                del extra_options[i]
                break
        else:
            self.logfile_path = os.path.join(self.data_path, "log_file.txt")

        if not '--no-update-check' in extra_options:
            self.options += ['--no-update-check'
                             ]  # supress update checks/reporting in

        self.options += extra_options

        # - subclass modifications

        self.subclass_init()

        # - save the args

        self.args = self.command_prefix + [self.executable_path] + self.options

        # -- start the server process

        self.start(wait_until_ready=wait_until_ready)
Example #5
0
 def subclass_options(self, options):
     options += ['--directory', utils.translatePath(self.data_path)]
Example #6
0
    def start(self, wait_until_ready=True):
        """Start up the server"""
        global runningServers

        assert not self.running, "Trying to start a server where running = %r" % self.running
        self.returncode = None
        self.killed = False

        # -- setup options

        # - copy the options

        options = copy.copy(self.args)

        # - set the local_cluster_port

        if not "--client-port" in options and not any([x.startswith("--client-port=") for x in options]):
            # allows resunder to know what port to block
            options += ["--client-port", str(self.local_cluster_port)]

        # - tls options

        if self.cluster.tlsKeyPath and self.cluster.tlsCertPath:
            options += [
                "--http-tls-key",
                utils.translatePath(self.cluster.tlsKeyPath),
                "--http-tls-cert",
                utils.translatePath(self.cluster.tlsCertPath),
                "--driver-tls-key",
                utils.translatePath(self.cluster.tlsKeyPath),
                "--driver-tls-cert",
                utils.translatePath(self.cluster.tlsCertPath),
                "--cluster-tls-key",
                utils.translatePath(self.cluster.tlsKeyPath),
                "--cluster-tls-cert",
                utils.translatePath(self.cluster.tlsCertPath),
                "--cluster-tls-ca",
                utils.translatePath(self.cluster.tlsCertPath),
            ]
            if platform.system() == "Darwin":
                # because the driver will probably be using the system version of OpenSSL (old), enable TLSv1
                options += [
                    "--tls-min-protocol",
                    "TLSv1",
                    "--tls-ciphers",
                    "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:AES256-SHA",
                ]

        # - log file

        options += ["--log-file", utils.translatePath(str(self.logfile_path))]

        # -- get the length of an exiting log file

        if os.path.isfile(self.logfile_path):
            self._existing_log_len = os.path.getsize(self.logfile_path)

        # -- set to join the cluster

        try:
            self.cluster._startLock.acquire()
            self.cluster._hasStartLock = self
            for peer in self.cluster.processes:
                if peer != self and peer.ready:
                    options += ["--join", peer.host + ":" + str(peer.cluster_port)]
                    break
        finally:
            # release the lock if we are joining a running cluster
            if "--join" in options and self.cluster._hasStartLock is self:
                self.cluster._hasStartLock = None
                self.cluster._startLock.release()

        # -- allow subclasses to modify the options array

        self.subclass_options(options)  # in-place edit

        # -- start the process

        try:
            self._console_file.write(
                "Launching at %s:\n\t%s\n" % (datetime.datetime.now().isoformat(), " ".join(options))
            )
            self._console_file.flush()
            self.process = subprocess.Popen(
                options, stdout=self._console_file, stderr=subprocess.STDOUT, preexec_fn=os.setpgrp
            )

            if not self in runningServers:
                runningServers.append(self)

            # - start thread to tail output for needed info
            thread.start_new_thread(self.read_ports_from_log, ())

        except Exception:
            self.stop()
            raise

        finally:
            # - move console file if necessary
            if self._console_file_path and not os.path.exists(self._console_file_path):
                os.rename(self._console_file.name, self._console_file_path)

        # -- wait until ready (if requested)
        if wait_until_ready:
            self.wait_until_ready()
Example #7
0
    def __init__(
        self,
        cluster=None,
        name=None,
        console_output=None,
        executable_path=None,
        server_tags=None,
        command_prefix=None,
        extra_options=None,
        wait_until_ready=True,
        tls=None,
    ):
        global runningServers

        # -- validate/default input

        # - cluster
        assert tls in (None, False, True), "tls must be True, False, or None (False)"
        if cluster is None:
            cluster = Cluster(tls=tls is True)
        else:
            assert tls is None or tls is (cluster.tlsCertPath is None), (
                "A server added to a cluster must have the same tls setting (cluster: %s vs %s)"
                % (cluster.tlsCertPath is None, tls)
            )
        assert isinstance(cluster, Cluster), "cluster must be a Cluster or None, got: %r" % cluster
        self.cluster = cluster
        self.cluster.processes.append(self)

        # - name/data_path
        assert isinstance(name, (str, unicode, None.__class__)), "name was not an expected value: %r" % name
        if name is None:
            # default name and data_path
            name = "%s_%s" % (
                self.server_type,
                self.cluster.metacluster.get_new_unique_id(server_type=self.server_type),
            )
            data_path = self.genPath(name, self.cluster.output_folder)
        elif name == ".":
            # random name in the current directory
            name = "%s_%s" % (
                self.server_type,
                self.cluster.metacluster.get_new_unique_id(server_type=self.server_type),
            )
            data_path = self.genPath(name, os.path.realpath("."))
        elif os.sep in name:  # if it looks like a path, it is one, possibly relative
            data_path = os.path.abspath(
                os.path.join(self.cluster.output_folder, name)
            )  # note: an absolute path survives this
            name = os.path.basename(name)
            if os.path.exists(data_path):
                assert os.path.isdir(data_path), "The data_path was something other than a directory: %s" % data_path
                if os.path.isfile(os.path.join(data_path, "log_file")):
                    # existing data folder, record server log file path
                    self.logfile_path = os.path.join(data_path, "log_file")
                elif os.path.isfile(os.path.join(data_path, "log_file.txt")):
                    # existing data folder, record server log file path
                    self.logfile_path = os.path.join(data_path, "log_file.txt")
                else:
                    # folder for holding multiple server data folders
                    data_path = self.genPath(name, data_path)
            else:
                # specified path, use it exactly
                assert os.path.isdir(os.path.dirname(data_path)), (
                    "The enclosing directory did not exist or was not a directory: %s" % data_path
                )
        else:
            # just a name
            data_path = self.genPath(name, self.cluster.output_folder)
        self.data_path = data_path
        self._desired_name = name.replace("-", "_")

        # - console_output/console_file - can be: path, file-object, True/False
        if console_output is None:
            # default to stdout
            self._console_file_path = None
            self._console_file = sys.stdout
        elif console_output is False:
            # throw away file
            self._console_file_path = None
            self._console_file = tempfile.NamedTemporaryFile(mode="w+")
        elif console_output is True:
            # keep it with the data, but create it in the encosing folder until we are running
            self._console_file_path = os.path.join(self.data_path, self._console_file_name)
            self._console_file = tempfile.NamedTemporaryFile(
                mode="w+", dir=os.path.dirname(self.data_path), delete=False
            )
        elif hasattr(console_output, "write"):
            # file-like object:
            self._console_file_path = None
            self._console_file = console_output
        else:
            # a path
            assert isinstance(console_output, (str, unicode)), "Unknown console_output: %r" % console_output
            console_output = os.path.realpath(console_output)
            assert os.path.isdir(os.path.dirname(console_output)), (
                "console_output parent directory was not a folder: %r" % console_output
            )
            assert os.path.isfile(console_output) or not os.path.exists(console_output), (
                "console_output location was not useable: %r" % console_output
            )
            self._console_file_path = console_output
            self._console_file = open(console_output, "a")

        # - server_tags
        if server_tags is None:
            self.server_tags = []
        elif hasattr(server_tags, "__iter__") and not hasattr(server_tags, "capitalize"):
            self.server_tags = [str(x) for x in server_tags]
        else:
            self.server_tags = [str(server_tags)]

        # - executable_path
        if executable_path is None:
            executable_path = utils.find_rethinkdb_executable()
        assert os.access(executable_path, os.X_OK), "no such executable: %r" % executable_path
        self.executable_path = executable_path

        # - command_prefix
        if command_prefix is None:
            self.command_prefix = []
        elif not hasattr(command_prefix, "__iter__"):
            raise ValueError("command_prefix must be an array of command line options, got: %r" % command_prefix)
        else:
            self.command_prefix = command_prefix

        # - extra_options
        self.options = []
        if extra_options is None:
            extra_options = []
        elif not hasattr(extra_options, "__iter__"):
            raise ValueError("extra_options must be an array of command line options, got: %r" % extra_options)
        else:
            extra_options = [str(x) for x in extra_options]

        # -- defaults

        if not "--bind" in extra_options and not any([x.startswith("--bind=") for x in extra_options]):
            self.options += ["--bind", "all"]

        if not "--cluster-port" in extra_options and not any([x.startswith("--cluster-port=") for x in extra_options]):
            self.options += ["--cluster-port", "0"]

        if not "--driver-port" in extra_options and not any([x.startswith("--driver-port=") for x in extra_options]):
            self.options += ["--driver-port", "0"]

        if not "--http-port" in extra_options and not any([x.startswith("--http-port=") for x in extra_options]):
            self.options += ["--http-port", "0"]

        for i, option in enumerate(extra_options or []):
            if option == "--log-file":
                assert len(self.options) > i + 1, "--log-file specified in options without a path"
                self.logfile_path = utils.translatePath(os.path.realpath(extra_options[i + 1]))
                del extra_options[i + 1]
                del extra_options[i]
                break
            elif option.startswith("--log-file="):
                self.logfile_path = utils.translatePath(os.path.realpath(option[len("--log-file=") :].strip("'\"")))
                del extra_options[i]
                break
        else:
            self.logfile_path = os.path.join(self.data_path, "log_file.txt")

        if not "--no-update-check" in extra_options:
            self.options += ["--no-update-check"]  # supress update checks/reporting in

        self.options += extra_options

        # - subclass modifications

        self.subclass_init()

        # - save the args

        self.args = self.command_prefix + [self.executable_path] + self.options

        # -- start the server process

        self.start(wait_until_ready=wait_until_ready)
Example #8
0
 def subclass_options(self, options):
     options += ["--directory", utils.translatePath(self.data_path)]