# Path: lib/python/asterisk/pluggable_registry.py
# PLUGGABLE_EVENT_REGISTRY = PluggableRegistry()
# 
# PLUGGABLE_ACTION_REGISTRY = PluggableRegistry()
# 
# def var_replace(text, values):
#     """ perform variable replacement on text
# 
#     This allows a parameters to be written to include variables from the
#     arbitrarily structured object provided by an ARI or AMI event like so:
#     from ARI to ARI: Uri: 'playbacks/{playback.id}/control'
#     from AMI to AMI: Channel: '{channel}'
#     from AMI to ARI: Uri: 'channels/{uniqueid}/play'
#     from ARI to AMI: Channel: '{channel.name}'
# 
#     :param text: text with optional {var} entries
#     :param values: nested dict of values to get replacement values from
#     """
#     if not isinstance(text, str):
#         return text
# 
#     for match in re.findall(r'(?<!\\){[^}]*(?<!\\)}', text):
#         value = values
#         for var in match[1:-1].split('.'):
#             if not var in value:
#                 LOGGER.error('Unable to replace variables in %s from %s',
#                              text, values)
#                 return None
#             value = value[var]
#         text = text.replace(match, value)
# 
#     return text


import sys
import os
import time
import shutil
import logging
import fileinput
import polyfill
from . import test_suite_utils
from .config import ConfigFile
from twisted.internet import reactor, protocol, defer, utils, error
from twisted.python.failure import Failure
    from twisted.python.filepath import FilePath
    from twisted.internet.endpoints import UNIXClientEndpoint
    from twisted.conch.ssh.keys import Key
    from twisted.conch.client.knownhosts import KnownHostsFile
    from twisted.conch.endpoints import SSHCommandClientEndpoint
    from twisted.internet.error import ProcessTerminated
from .pluggable_registry import PLUGGABLE_EVENT_REGISTRY,\
    PLUGGABLE_ACTION_REGISTRY, var_replace
                # connection - it may already be gone however.
                self.process.loseConnection()
            except:
                pass
            try:
                if not self._stop_deferred.called:
                    self._stop_deferred.callback("Asterisk %s KILLED" % self.host)
            except defer.AlreadyCalledError:
                LOGGER.warning("Asterisk %s stop deferred already called" % self.host)

        def __process_stopped(reason):
            """Generic callback that raises the stopped deferred subscribers
            use to know that the process has exited"""
            self._stop_deferred.callback(reason)
            return reason

        def __actual_stop():
            # Schedule a kill. If we don't gracefully shut down Asterisk, this
            # will ensure that the test is stopped.
            sched_time = 200 if self.valgrind_enabled else 45

            self._stop_cancel_tokens.append(reactor.callLater(sched_time,
                                            __send_kill))

            # Start by asking to stop gracefully.
            __send_stop_gracefully()

            self._stop_deferred.addCallback(__cancel_stops)

        if not self.process:

# Path: lib/python/asterisk/pluggable_registry.py
# PLUGGABLE_EVENT_REGISTRY = PluggableRegistry()
# 
# PLUGGABLE_ACTION_REGISTRY = PluggableRegistry()
# 
# def var_replace(text, values):
#     """ perform variable replacement on text
# 
#     This allows a parameters to be written to include variables from the
#     arbitrarily structured object provided by an ARI or AMI event like so:
#     from ARI to ARI: Uri: 'playbacks/{playback.id}/control'
#     from AMI to AMI: Channel: '{channel}'
#     from AMI to ARI: Uri: 'channels/{uniqueid}/play'
#     from ARI to AMI: Channel: '{channel.name}'
# 
#     :param text: text with optional {var} entries
#     :param values: nested dict of values to get replacement values from
#     """
#     if not isinstance(text, str):
#         return text
# 
#     for match in re.findall(r'(?<!\\){[^}]*(?<!\\)}', text):
#         value = values
#         for var in match[1:-1].split('.'):
#             if not var in value:
#                 LOGGER.error('Unable to replace variables in %s from %s',
#                              text, values)
#                 return None
#             value = value[var]
#         text = text.replace(match, value)
# 
#     return text


# Path: lib/python/asterisk/asterisk.py
import sys
import os
import time
import shutil
import logging
import fileinput
import polyfill
from . import test_suite_utils
from .config import ConfigFile
from twisted.internet import reactor, protocol, defer, utils, error
from twisted.python.failure import Failure
    from twisted.python.filepath import FilePath
    from twisted.internet.endpoints import UNIXClientEndpoint
    from twisted.conch.ssh.keys import Key
    from twisted.conch.client.knownhosts import KnownHostsFile
    from twisted.conch.endpoints import SSHCommandClientEndpoint
    from twisted.internet.error import ProcessTerminated
from .pluggable_registry import PLUGGABLE_EVENT_REGISTRY,\
    PLUGGABLE_ACTION_REGISTRY, var_replace

                # connection - it may already be gone however.
                self.process.loseConnection()
            except:
                pass
            try:
                if not self._stop_deferred.called:
                    self._stop_deferred.callback("Asterisk %s KILLED" % self.host)
            except defer.AlreadyCalledError:
                LOGGER.warning("Asterisk %s stop deferred already called" % self.host)

        def __process_stopped(reason):
            """Generic callback that raises the stopped deferred subscribers
            use to know that the process has exited"""
            self._stop_deferred.callback(reason)
            return reason

        def __actual_stop():
            # Schedule a kill. If we don't gracefully shut down Asterisk, this
            # will ensure that the test is stopped.
            sched_time = 200 if self.valgrind_enabled else 45

            self._stop_cancel_tokens.append(reactor.callLater(sched_time,
                                            __send_kill))

            # Start by asking to stop gracefully.
            __send_stop_gracefully()

            self._stop_deferred.addCallback(__cancel_stops)

        if not self.process:

            reactor.callLater(0, __process_stopped, None)