Пример #1
0
    def __init__(self, dep):
        """Construct a new dependency

        Keyword arguments:
        dep A tuple containing the dependency type name and its subinformation.
        """

        self.name = ""
        self.version = ""
        self.met = False
        if "app" in dep:
            self.name = dep["app"]
            self.met = test_suite_utils.which(self.name) is not None
        elif "python" in dep:
            self.name = dep["python"]
            try:
                __import__(self.name)
                self.met = True
            except ImportError:
                pass
        elif "sipp" in dep:
            self.name = "SIPp"
            version = None
            feature = None
            if 'version' in dep['sipp']:
                version = dep['sipp']['version']
            if 'feature' in dep['sipp']:
                feature = dep['sipp']['feature']
            self.sipp_version = SIPpVersion()
            self.version = SIPpVersion(version, feature)
            if self.sipp_version >= self.version:
                self.met = True
            if self.version.tls and not self.sipp_version.tls:
                self.met = False
            if self.version.pcap and not self.sipp_version.pcap:
                self.met = False
        elif "custom" in dep:
            self.name = dep["custom"]
            method = "depend_%s" % self.name
            found = False
            for dir_method in dir(self):
                if dir_method == method:
                    self.met = getattr(self, dir_method)()
                    found = True
            if not found:
                print "Unknown custom dependency - '%s'" % self.name
        elif "asterisk" in dep:
            self.name = dep["asterisk"]
            self.met = self._find_asterisk_module(self.name)
        elif "buildoption" in dep:
            self.name = dep["buildoption"]
            self.met = self._find_build_flag(self.name)
        elif "pcap" in dep:
            self.name = "pcap"
            from test_case import PCAP_AVAILABLE
            self.met = PCAP_AVAILABLE
        else:
            print "Unknown dependency type specified:"
            for key in dep.keys():
                print key
Пример #2
0
    def get_version_from_binary(cls):
        """Obtain the version from the installed instance of Asterisk

        This method will invoke Asterisk, get the version, parse the
        result, and cache it. Once cached, the cached version will
        always be returned.

        Returns: The installed Asterisk version
        """
        if not hasattr(cls, "_asterisk_version_from_binary"):
            version = ""
            ast_binary = (test_suite_utils.which("asterisk") or
                          "/usr/sbin/asterisk")
            cmd = [
                ast_binary,
                "-V",
            ]

            try:
                process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                                           stderr=None)
                version = process.stdout.read()
            except OSError as o_excep:
                LOGGER.error("OSError [%d]: %s" % (o_excep.errno,
                                                   o_excep.strerror))
                raise
            process.wait()
            cls._asterisk_version_from_binary = version.replace(
                "Asterisk ", "")
        return cls._asterisk_version_from_binary
Пример #3
0
    def get_version_from_binary(cls):
        """Obtain the version from the installed instance of Asterisk

        This method will invoke Asterisk, get the version, parse the
        result, and cache it. Once cached, the cached version will
        always be returned.

        Returns: The installed Asterisk version
        """
        if not hasattr(cls, "_asterisk_version_from_binary"):
            version = ""
            ast_binary = (test_suite_utils.which("asterisk") or
                          "/usr/sbin/asterisk")
            cmd = [
                ast_binary,
                "-V",
            ]

            try:
                process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                                           stderr=None)
                version = process.stdout.read()
            except OSError as o_excep:
                LOGGER.error("OSError [%d]: %s" % (o_excep.errno,
                                                   o_excep.strerror))
                raise
            process.wait()
            cls._asterisk_version_from_binary = version.replace(
                "Asterisk ", "")
        return cls._asterisk_version_from_binary
Пример #4
0
    def __init__(self,
                 test_dir,
                 scenario,
                 positional_args=(),
                 target='127.0.0.1'):
        """
        Keyword Arguments:
        test_dir        The path to the directory containing the run-test file.

        scenario        A SIPp scenario to execute. The scenario should
                        be a dictionary with the key 'scenario' being the
                        filename of the SIPp scenario. Any other key-value pairs
                        are treated as arguments to SIPp. For example, specify
                        '-timeout' : '60s' to set the timeout option to SIPp to
                        60 seconds. If a parameter specified is also one
                        specified by default, the value provided will be used.

                        The default SIPp parameters include:
            -p <port>    - Unless otherwise specified, the port number will
                           be 5060 + <scenario list index, starting at 1>.
                           So, the first SIPp sceario will use port 5061.
            -m 1         - Stop the test after 1 'call' is processed.
            -i 127.0.0.1 - Use this as the local IP address for the Contact
                           headers, Via headers, etc.
            -timeout 20s - Set a global test timeout of 20 seconds.

        positional_args Certain SIPp parameters can be specified multiple
                        times, or take multiple arguments. Supply those through
                        this iterable.

                        The canonical example being -key:
                            ('-key', 'extra_via_param', ';rport',
                             '-key', 'user_addr', 'sip:myname@myhost')
        target          Overrides the default target address (127.0.0.1) of the
                        SIPp scenario. Be sure to specify IPv6 addresses in
                        brackets ([::1])
        """
        self.scenario = scenario
        self.name = scenario['scenario']
        # don't allow caller to mangle his own list
        self.positional_args = tuple(positional_args)
        self.test_dir = test_dir
        self.default_port = 5061
        self.sipp = test_suite_utils.which("sipp")
        self.passed = False
        self.exited = False
        self._process = None
        self.target = target
        self._our_exit_deferred = None
        self._test_case = None
        if not self.sipp:
            raise ValueError("SIPpTestObject requires that sipp is installed")
Пример #5
0
    def depend_pjsuav6(self):
        """This tests if pjsua was compiled with IPv6 support.

        To do this, we run pjsua --help and parse the output to determine if
        --ipv6 is a valid option
        """
        if test_suite_utils.which('pjsua') is None:
            return False

        help_output = subprocess.Popen(['pjsua', '--help'],
                                       stdout=subprocess.PIPE).communicate()[0]
        if help_output.find('--ipv6') == -1:
            return False
        return True
Пример #6
0
    def depend_pjsuav6(self):
        """This tests if pjsua was compiled with IPv6 support.

        To do this, we run pjsua --help and parse the output to determine if
        --ipv6 is a valid option
        """
        if test_suite_utils.which('pjsua') is None:
            return False

        help_output = subprocess.Popen(['pjsua', '--help'],
                                       stdout=subprocess.PIPE).communicate()[0]
        if help_output.find('--ipv6') == -1:
            return False
        return True
    def __init__(self, test_dir, scenario, positional_args=(),
                 target='127.0.0.1'):
        """
        Keyword Arguments:
        test_dir        The path to the directory containing the run-test file.

        scenario        A SIPp scenario to execute. The scenario should
                        be a dictionary with the key 'scenario' being the
                        filename of the SIPp scenario. Any other key-value pairs
                        are treated as arguments to SIPp. For example, specify
                        '-timeout' : '60s' to set the timeout option to SIPp to
                        60 seconds. If a parameter specified is also one
                        specified by default, the value provided will be used.

                        The default SIPp parameters include:
            -p <port>    - Unless otherwise specified, the port number will
                           be 5060 + <scenario list index, starting at 1>.
                           So, the first SIPp sceario will use port 5061.
            -m 1         - Stop the test after 1 'call' is processed.
            -i 127.0.0.1 - Use this as the local IP address for the Contact
                           headers, Via headers, etc.
            -timeout 20s - Set a global test timeout of 20 seconds.

        positional_args Certain SIPp parameters can be specified multiple
                        times, or take multiple arguments. Supply those through
                        this iterable.

                        The canonical example being -key:
                            ('-key', 'extra_via_param', ';rport',
                             '-key', 'user_addr', 'sip:myname@myhost')
        target          Overrides the default target address (127.0.0.1) of the
                        SIPp scenario. Be sure to specify IPv6 addresses in
                        brackets ([::1])
        """
        self.scenario = scenario
        self.name = scenario['scenario']
        # don't allow caller to mangle his own list
        self.positional_args = tuple(positional_args)
        self.test_dir = test_dir
        self.default_port = 5061
        self.sipp = test_suite_utils.which("sipp")
        self.passed = False
        self.exited = False
        self._process = None
        self.target = target
        self._our_exit_deferred = None
        self._test_case = None
        if not self.sipp:
            raise ValueError("SIPpTestObject requires that sipp is installed")
Пример #8
0
    def __init__(self, version=None, feature=None):
        """Construct a SIPp Version parser.

        Keyword Arguments:
        version The SIPp version string to parse.
        """
        self.version_str = None
        self.feature_str = None
        self.concept = None
        self.major = None
        self.minor = None
        self.tls = False
        self.pcap = False

        if version is None and feature is None:
            sipp = test_suite_utils.which("sipp")
            if sipp is None:
                return

            cmd = [
                sipp, "-v"
            ]
            try:
                sipp_process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                                                stderr=subprocess.STDOUT)
            except OSError:
                return
            for line in sipp_process.stdout:
                if line.strip().startswith('SIPp '):
                    sipp = line.strip()[5:]
                    sipp = sipp.split(',', 1)
                    sipp = sipp[0].split('-', 1)
                    version = sipp[0]
                    if len(sipp) > 1:
                        feature = sipp[1]
            sipp_process.wait()

        if version is not None:
            self.__parse_version(version)
        if feature is not None:
            self.__parse_feature(feature)
Пример #9
0
    def __init__(self, version=None, feature=None):
        """Construct a SIPp Version parser.

        Keyword Arguments:
        version The SIPp version string to parse.
        """
        self.version_str = None
        self.feature_str = None
        self.concept = None
        self.major = None
        self.minor = None
        self.tls = False
        self.pcap = False

        if version is None and feature is None:
            sipp = test_suite_utils.which("sipp")
            if sipp is None:
               return

            cmd = [
                sipp, "-v"
            ]
            try:
                sipp_process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                    stderr=subprocess.STDOUT)
            except OSError:
                return
            for line in sipp_process.stdout:
                if line.strip().startswith('SIPp'):
                    sipp = line.strip().lstrip('SIPp ')
                    sipp = sipp.split(',', 1)
                    sipp = sipp[0].split('-', 1)
                    version = sipp[0]
                    if len(sipp) > 1:
                        feature = sipp[1]
            sipp_process.wait()

        if version is not None:
            self.__parse_version(version)
        if feature is not None:
            self.__parse_feature(feature)
    def get_version_from_binary(cls):
        """Obtain the version from Asterisk and return a cached version of it"""
        if not hasattr(cls, "_asterisk_version_from_binary"):
            version = ""
            ast_binary = (test_suite_utils.which("asterisk")
                          or "/usr/sbin/asterisk")
            cmd = [
                ast_binary,
                "-V",
            ]

            try:
                process = subprocess.Popen(cmd,
                                           stdout=subprocess.PIPE,
                                           stderr=None)
                version = process.stdout.read()
            except OSError as o_excep:
                LOGGER.error("OSError [%d]: %s" %
                             (o_excep.errno, o_excep.strerror))
                raise
            process.wait()
            cls._asterisk_version_from_binary = version.replace(
                "Asterisk ", "")
        return cls._asterisk_version_from_binary
Пример #11
0
    def start(self, deps=None):
        """Start this instance of Asterisk.

        Returns:
        A deferred object that will be called when Asterisk is fully booted.

        Example Usage:
        asterisk.start()

        Note that calling this will install the default testsuite
        config files, if they have not already been installed
        """

        def __start_asterisk_callback(cmd):
            """Begin the Asterisk startup cycle"""

            self.process_protocol = AsteriskProtocol(self.host,
                                                     self._stop_deferred)
            self.process = reactor.spawnProcess(self.process_protocol,
                                                cmd[0],
                                                cmd, env=os.environ)
            # Begin the wait fully booted cycle
            self.__start_asterisk_time = time.time()
            reactor.callLater(1, __execute_wait_fully_booted)

        def __execute_wait_fully_booted():
            """Send the CLI command waitfullybooted"""

            cli_deferred = self.cli_exec("core waitfullybooted")
            cli_deferred.addCallbacks(__wait_fully_booted_callback,
                                      __wait_fully_booted_error)

        def __wait_fully_booted_callback(cli_command):
            """Callback for CLI command waitfullybooted"""

            if "Asterisk has fully booted" in cli_command.output:
                msg = "Successfully started Asterisk %s" % self.host
                self._start_deferred.callback(msg)
            else:
                LOGGER.debug("Asterisk core waitfullybooted failed " +
                             "with output '%s', attempting again..." %
                             cli_command.output)
                reactor.callLater(1, __execute_wait_fully_booted)
            return cli_command

        def __wait_fully_booted_error(cli_command):
            """Errback for CLI command waitfullybooted"""

            timeout = 90 if self.valgrind_enabled else 5
            if time.time() - self.__start_asterisk_time > timeout:
                msg = "Asterisk core waitfullybooted for %s failed" % self.host
                LOGGER.error(msg)
                self._start_deferred.errback(Exception(msg))
            else:
                msg = "Asterisk core waitfullybooted failed, attempting again"
                LOGGER.debug(msg)
                reactor.callLater(1, __execute_wait_fully_booted)
            return cli_command

        self.install_configs(os.getcwd() + "/configs", deps)
        self._setup_configs()

        cmd_prefix = []

        if os.getenv("VALGRIND_ENABLE") == "true":
            valgrind_path = test_suite_utils.which('valgrind')
            if valgrind_path:
                cmd_prefix = [
                    valgrind_path,
                    '--xml=yes',
                    '--xml-file=%s' % self.get_path("astlogdir", 'valgrind.xml'),
                    '--xml-user-comment=%s (%s)' % (
                        os.environ['TESTSUITE_ACTIVE_TEST'], self.host)]
                suppression_file = 'contrib/valgrind/suppressions.txt'
                if os.path.exists(suppression_file):
                    cmd_prefix.append('--suppressions=%s' % suppression_file)
            else:
                LOGGER.error('Valgrind not found')

        cmd = cmd_prefix + [
            self.ast_binary,
            "-f", "-g", "-q", "-m", "-n",
            "-C", "%s" % os.path.join(self.astetcdir, "asterisk.conf")
        ]

        # Make the start/stop deferreds - this method will return
        # the start deferred, and pass the stop deferred to the AsteriskProtocol
        # object.  The stop deferred will be raised when the Asterisk process
        # exits
        self._start_deferred = defer.Deferred()
        self._stop_deferred = defer.Deferred()

        # Asterisk will attempt to use built in configuration information if
        # it can't find the configuration files that are being installed - which
        # can happen due to the files being created due to a copy operation.
        # If that happens, the test will fail - wait a second to give
        # Asterisk time to come up fully
        reactor.callLater(0, __start_asterisk_callback, cmd)

        return self._start_deferred
Пример #12
0
    def __init__(self, base=None, ast_conf_options=None, host="127.0.0.1"):
        """Construct an Asterisk instance.

        Keyword Arguments:
        base -- This is the root of the files associated with this instance of
        Asterisk.  By default, the base is "/tmp/asterisk-testsuite" directory.
        Given a base, it will be appended to the default base directory.

        Example Usage:
        self.asterisk = Asterisk(base="manager/login")
        """
        self._start_deferred = None
        self._stop_deferred = None
        self._stop_cancel_tokens = []
        self.directories = {}
        self.ast_version = AsteriskVersion()
        self.process_protocol = None
        self.process = None
        self.astetcdir = ""
        self.original_astmoddir = ""

        valgrind_env = os.getenv("VALGRIND_ENABLE") or ""
        self.valgrind_enabled = True if "true" in valgrind_env else False

        if base is not None:
            self.base = base
        else:
            self.base = Asterisk.test_suite_root
        if self.localtest_root:
            self.ast_binary = self.localtest_root + "/usr/sbin/asterisk"
        else:
            ast_binary = test_suite_utils.which("asterisk")
            self.ast_binary = ast_binary or "/usr/sbin/asterisk"
        self.host = host

        self._ast_conf_options = ast_conf_options
        self._directory_structure_made = False
        self._configs_installed = False
        self._configs_set_up = False

        # Find the system installed asterisk.conf
        ast_confs = [
            os.path.join(self.default_etc_directory, "asterisk.conf"),
            "/usr/local/etc/asterisk/asterisk.conf",
        ]
        self._ast_conf = None
        for config in ast_confs:
            if os.path.exists(config):
                self._ast_conf = ConfigFile(config)
                break
        if self._ast_conf is None:
            msg = "Unable to locate asterisk.conf in any known location"
            LOGGER.error(msg)
            raise Exception(msg)

        # Set which astxxx this instance will be
        i = 1
        while True:
            if not os.path.isdir("%s/ast%d" % (self.base, i)):
                self.base = "%s/ast%d" % (self.base, i)
                break
            i += 1

        # Get the Asterisk directories from the Asterisk config file
        for cat in self._ast_conf.categories:
            if cat.name == "directories":
                for (var, val) in cat.options:
                    self.directories[var] = val

        # self.original_astmoddir is for dependency checking only
        if "astmoddir" in self.directories:
            if self.localtest_root:
                self.original_astmoddir = "%s%s" % (
                    self.localtest_root, self.directories["astmoddir"])
            else:
                self.original_astmoddir = self.directories["astmoddir"]
Пример #13
0
    def start(self, deps=None):
        """Start this instance of Asterisk.

        Returns:
        A deferred object that will be called when Asterisk is fully booted.

        Example Usage:
        asterisk.start()

        Note that calling this will install the default testsuite
        config files, if they have not already been installed
        """

        def __start_asterisk_callback(cmd):
            """Begin the Asterisk startup cycle"""

            self.__start_asterisk_time = time.time()

            if self.remote_config:
                reactor.callLater(0, __execute_wait_fully_booted)
                return

            self.protocol = AsteriskProtocol(self.host, self._stop_deferred)
            self.process = reactor.spawnProcess(self.protocol,
                                                cmd[0],
                                                cmd, env=os.environ)
            # Begin the wait fully booted cycle
            reactor.callLater(1, __execute_wait_fully_booted)

        def __execute_wait_fully_booted():
            """Send the CLI command waitfullybooted"""

            cli_deferred = self.cli_exec("core waitfullybooted")
            cli_deferred.addCallbacks(__wait_fully_booted_callback,
                                      __wait_fully_booted_error)

        def __wait_fully_booted_callback(cli_command):
            """Callback for CLI command waitfullybooted"""

            if "Asterisk has fully booted" in cli_command.output:
                msg = "Successfully started Asterisk %s" % self.host
                self._start_deferred.callback(msg)
            else:
                LOGGER.debug("Asterisk core waitfullybooted failed " +
                             "with output '%s', attempting again..." %
                             cli_command.output)
                reactor.callLater(1, __execute_wait_fully_booted)
            return cli_command

        def __wait_fully_booted_error(cli_command):
            """Errback for CLI command waitfullybooted"""

            timeout = 90 if self.valgrind_enabled else 45
            if time.time() - self.__start_asterisk_time > timeout:
                msg = "Asterisk core waitfullybooted for %s failed" % self.host
                LOGGER.error(msg)
                self._start_deferred.errback(Exception(msg))
            else:
                msg = "Asterisk core waitfullybooted failed, attempting again"
                LOGGER.debug(msg)
                reactor.callLater(1, __execute_wait_fully_booted)
            return cli_command

        self.install_configs(os.getcwd() + "/configs", deps)
        self._setup_configs()

        cmd_prefix = []

        if os.getenv("VALGRIND_ENABLE") == "true":
            valgrind_path = test_suite_utils.which('valgrind')
            if valgrind_path:
                cmd_prefix = [
                    valgrind_path,
                    '--xml=yes',
                    '--xml-file=%s' % self.get_path("astlogdir", 'valgrind.xml'),
                    '--xml-user-comment=%s (%s)' % (
                        os.environ['TESTSUITE_ACTIVE_TEST'], self.host)]
                suppression_file = 'contrib/valgrind/suppressions.txt'
                if os.path.exists(suppression_file):
                    cmd_prefix.append('--suppressions=%s' % suppression_file)
            else:
                LOGGER.error('Valgrind not found')

        cmd = cmd_prefix + [
            self.ast_binary,
            "-f", "-g", "-q", "-m", "-n",
            "-C", "%s" % os.path.join(self.astetcdir, "asterisk.conf")
        ]

        # Make the start/stop deferreds - this method will return
        # the start deferred, and pass the stop deferred to the AsteriskProtocol
        # object.  The stop deferred will be raised when the Asterisk process
        # exits
        self._start_deferred = defer.Deferred()
        self._stop_deferred = defer.Deferred()

        # Asterisk will attempt to use built in configuration information if
        # it can't find the configuration files that are being installed - which
        # can happen due to the files being created due to a copy operation.
        # If that happens, the test will fail - wait a second to give
        # Asterisk time to come up fully
        reactor.callLater(0, __start_asterisk_callback, cmd)

        return self._start_deferred
Пример #14
0
    def __init__(self, base=None, ast_conf_options=None, host="127.0.0.1",
                 remote_config=None):
        """Construct an Asterisk instance.

        Keyword Arguments:
        base -- This is the root of the files associated with this instance of
                Asterisk. By default, the base is "/tmp/asterisk-testsuite"
                directory. Given a base, it will be appended to the default base
                directory.
        ast_conf_options -- Configuration overrides for asterisk.conf.
        host -- The IP address the Asterisk instance runs on
        remote_config -- Configuration section that defines this as a remote
                         Asterisk instance. If provided, base and
                         ast_conf_options are generally ignored, and the
                         Asterisk instance's configuration is treated as
                         immutable on some remote machine defined by 'host'

        Example Usage:
        self.asterisk = Asterisk(base="manager/login")
        """
        self._start_deferred = None
        self._stop_deferred = None
        self._stop_cancel_tokens = []
        self.directories = {}
        self.protocol = None
        self.process = None
        self.astetcdir = ""
        self.original_astmoddir = ""
        self.ast_version = None
        self.remote_config = remote_config

        # If the process is remote, don't bother
        if not self.remote_config:
            self.ast_version = AsteriskVersion()

        valgrind_env = os.getenv("VALGRIND_ENABLE") or ""
        self.valgrind_enabled = True if "true" in valgrind_env else False

        if base is not None:
            self.base = base
        else:
            self.base = Asterisk.test_suite_root
        if self.localtest_root:
            self.ast_binary = self.localtest_root + "/usr/sbin/asterisk"
        else:
            ast_binary = test_suite_utils.which("asterisk")
            self.ast_binary = ast_binary or "/usr/sbin/asterisk"
        self.host = host

        self._ast_conf_options = ast_conf_options

        if self.remote_config:
            # Pretend as if we made the structure
            self._directory_structure_made = True
            self._configs_installed = True
            self._configs_set_up = True

            # And assume we've got /etc/asterisk/ where we expect it to be
            self.astetcdir = "/etc/asterisk"
        else:
            self._directory_structure_made = False
            self._configs_installed = False
            self._configs_set_up = False

            # Find the system installed asterisk.conf
            ast_confs = [
                os.path.join(self.default_etc_directory, "asterisk.conf"),
                "/usr/local/etc/asterisk/asterisk.conf",
            ]
            self._ast_conf = None
            for config in ast_confs:
                if os.path.exists(config):
                    self._ast_conf = ConfigFile(config)
                    break
            if self._ast_conf is None:
                msg = "Unable to locate asterisk.conf in any known location"
                LOGGER.error(msg)
                raise Exception(msg)

            # Set which astxxx this instance will be
            i = 1
            while True:
                if not os.path.isdir("%s/ast%d" % (self.base, i)):
                    self.base = "%s/ast%d" % (self.base, i)
                    break
                i += 1

            # Get the Asterisk directories from the Asterisk config file
            for cat in self._ast_conf.categories:
                if cat.name == "directories":
                    for (var, val) in cat.options:
                        self.directories[var] = val

            # self.original_astmoddir is for dependency checking only
            if "astmoddir" in self.directories:
                if self.localtest_root:
                    self.original_astmoddir = "%s%s" % (
                        self.localtest_root, self.directories["astmoddir"])
                else:
                    self.original_astmoddir = self.directories["astmoddir"]
Пример #15
0
    def __init__(self, base=None, ast_conf_options=None, host="127.0.0.1"):
        """Construct an Asterisk instance.

        Keyword Arguments:
        base -- This is the root of the files associated with this instance of
        Asterisk.  By default, the base is "/tmp/asterisk-testsuite" directory.
        Given a base, it will be appended to the default base directory.

        Example Usage:
        self.asterisk = Asterisk(base="manager/login")
        """
        self._start_deferred = None
        self._stop_deferred = None
        self._stop_cancel_tokens = []
        self.directories = {}
        self.ast_version = AsteriskVersion()
        self.process_protocol = None
        self.process = None
        self.astetcdir = ""
        self.original_astmoddir = ""

        if base is not None:
            self.base = base
        else:
            self.base = Asterisk.test_suite_root
        if self.localtest_root:
            self.ast_binary = self.localtest_root + "/usr/sbin/asterisk"
        else:
            ast_binary = test_suite_utils.which("asterisk")
            self.ast_binary = ast_binary or "/usr/sbin/asterisk"
        self.host = host

        self._ast_conf_options = ast_conf_options
        self._directory_structure_made = False
        self._configs_installed = False
        self._configs_set_up = False

        # Find the system installed asterisk.conf
        ast_confs = [
            os.path.join(self.default_etc_directory, "asterisk.conf"),
            "/usr/local/etc/asterisk/asterisk.conf",
        ]
        self._ast_conf = None
        for config in ast_confs:
            if os.path.exists(config):
                self._ast_conf = ConfigFile(config)
                break
        if self._ast_conf is None:
            msg = "Unable to locate asterisk.conf in any known location"
            LOGGER.error(msg)
            raise Exception(msg)

        # Set which astxxx this instance will be
        i = 1
        while True:
            if not os.path.isdir("%s/ast%d" % (self.base, i)):
                self.base = "%s/ast%d" % (self.base, i)
                break
            i += 1

        # Get the Asterisk directories from the Asterisk config file
        for cat in self._ast_conf.categories:
            if cat.name == "directories":
                for (var, val) in cat.options:
                    self.directories[var] = val

        # self.original_astmoddir is for dependency checking only
        if "astmoddir" in self.directories:
            if self.localtest_root:
                self.original_astmoddir = "%s%s" % (
                    self.localtest_root, self.directories["astmoddir"])
            else:
                self.original_astmoddir = self.directories["astmoddir"]