Examples of crl.interactivesessions usage¶
Running Commands In Background¶
This example demonstrates simple background execution of Linux Shell
commands. The implementation uses the transparent proxies which
are created by
crl.interactivesessions.autorunnerterminal.AutoRunnerTerminal
.
Please see the code from BackgroundRunner Code.
By the default Remoteproxies proxies are blocking until the timeout expires.
However, in this example the proxy of subprocess.Popen.communicate()
is
set to asynchronous mode:
@staticmethod
def _communicate(pro):
communicate = pro.communicate
communicate.remote_proxy_use_asynchronous_response()
return ResponseHandle(pro=pro, handle=communicate())
The example usage of the BackgroundRunner Code class BackgroundRunner is here:
>>> from crl.interactivesessions.InteractiveSession import SshShell
>>> runner = BackgroundRunner(SshShell(
... '10.7.20.22', username='ncioadmin', password='admin_pass'))
>>> handle = runner.run_in_background('echo Hello World!;sleep 100')
>>> runner.terminate_and_get_response(handle)
RunResponse(ret=-15, out='Hello World!\n', err='')
Copying Files To/From Remote Targets¶
This example demonstrates binary file copying to and from the remote targets
using
crl.interactivesessions.autorunnerterminal
provided proxies.
In more detail a simple file handle like contextmanager is created which opens the remote file is created. This is done in the following fashion.
class _RemoteFile(object):
def __init__(self, terminal, filename, options='r'):
self.terminal = terminal
self.filename = filename
self.options = options
self.handle = None
def __enter__(self):
self.terminal.initialize_if_needed()
self.handle = self.terminal.get_proxy_object_from_call(
'open', self.filename, self.options)
self.handle.set_proxy_spec(file)
return self.handle
def __exit__(self, *args, **kwargs):
if self.handle is not None:
self.handle.close()
self.handle = None
The call self.terminal.initialize_if_needed will open a new terminal session in case it is either never opened or for some reason broken.
A simple roundtrip example is here:
>>> with open('hello.txt', 'w') as f:
... f.write('Hello World!')
...
>>> from crl.interactivesessions.InteractiveSession import SshShell
>>> copier = FileCopier(SshShell(
... '10.7.20.22', username='ncioadmin', password='admin_pass'))
>>> copier.copy_file_to_remote('hello.txt', 'hello_remote.txt')
>>> copier.copy_file_from_remote('hello_remote.txt', 'hello_local.txt')
>>> with open('hello_local.txt') as f:
... f.read()
...
'Hello World!'
>>>
Please see the full source from FileCopier Code.
Lazy Initialization of Remote Proxies¶
There is no need to initialize the session for the
crl.interactivesessions.remoteproxies._RemoteProxy
proxies
before the actual usage of the proxy. This can be achieved by calling
either
crl.interactivesessions.autorunnerterminal.RunnerTerminal.create_empty_remote_proxy()
or
crl.interactivesessions.autorunnerterminal.RunnerTerminal.create_empty_recursive_proxy()
.
The access to proxies of this type will automatically tricker the initialization
process. In this case, it is recommended that the prepare method copies the
new proxy content over the old proxies so that the references to the proxies
can be still used. This can be achieved by using the
crl.interactivesessions.remoteproxies._RemoteProxy.set_remote_proxy_from_proxy()
.
Please see the details from BackgroundRunner Code.
BackgroundRunner Code¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | import logging
import signal
import errno
from collections import namedtuple
from crl.interactivesessions.InteractiveSession import BashShell
from crl.interactivesessions.autorunnerterminal import AutoRunnerTerminal
from crl.interactivesessions.autorecoveringterminal import (
AutoRecoveringTerminal)
__copyright__ = 'Copyright (C) 2019, Nokia'
logger = logging.getLogger(__name__)
class _OsProxies(object):
def __init__(self, terminal):
self.killpg = terminal.create_empty_remote_proxy()
self.getpgid = terminal.create_empty_remote_proxy()
self.setsid = terminal.create_empty_remote_proxy()
ResponseHandle = namedtuple('ResponseHandle', ['pro', 'handle'])
RunResponse = namedtuple('RunResponse', ['ret', 'out', 'err'])
class BackgroundRunner(object):
def __init__(self, shells=None):
self.terminal = None
self.popen = None
self.pipe = None
self.os = None
self._initialize(BashShell() if shells is None else shells)
def _initialize(self, shells):
self.terminal = AutoRunnerTerminal()
self.terminal.initialize_with_shells(shells=shells,
prepare=self._prepare)
self._setup_with_empty_proxies()
def _setup_with_empty_proxies(self):
self.os = _OsProxies(self.terminal)
self.popen = self.terminal.create_empty_recursive_proxy()
self.pipe = self.terminal.create_empty_remote_proxy()
def _prepare(self):
self._import_libraries()
self._setup_proxies()
def _import_libraries(self):
self.terminal.import_libraries('os', 'subprocess')
def _setup_proxies(self):
self._setup_subprocess_proxies()
self._setup_os_proxies()
def _setup_subprocess_proxies(self):
self.popen.set_from_remote_proxy(
self.terminal.get_recursive_proxy('subprocess.Popen'))
self.pipe.set_from_remote_proxy(
self.terminal.get_proxy_object('subprocess.PIPE', None))
def _setup_os_proxies(self):
self.os.killpg.set_from_remote_proxy(
self.terminal.get_proxy_object('os.killpg', None))
self.os.getpgid.set_from_remote_proxy(
self.terminal.get_proxy_object('os.getpgid', None))
self.os.setsid.set_from_remote_proxy(
self.terminal.get_proxy_object('os.setsid', None))
def run_in_background(self, cmd):
pro = self.popen(cmd,
stdout=self.pipe,
stderr=self.pipe,
shell=True,
preexec_fn=self.os.setsid)
return self._communicate(pro)
@staticmethod
def _communicate(pro):
communicate = pro.communicate
communicate.remote_proxy_use_asynchronous_response()
return ResponseHandle(pro=pro, handle=communicate())
def terminate_and_get_response(self, handle):
self._terminate_if_needed(handle.pro)
out, err = handle.pro.get_remote_proxy_response(handle.handle,
timeout=10)
return RunResponse(ret=handle.pro.returncode, out=out, err=err)
def _terminate_if_needed(self, pro):
try:
self.os.killpg(self.os.getpgid(pro.pid), signal.SIGTERM)
except OSError as e:
if e.errno == errno.ESRCH:
logger.debug('Not terminating: process already terminated')
else:
raise
|
FileCopier Code¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | from crl.interactivesessions.InteractiveSession import BashShell
from crl.interactivesessions.autorunnerterminal import AutoRunnerTerminal
from crl.interactivesessions.autorecoveringterminal import (
AutoRecoveringTerminal)
__copyright__ = 'Copyright (C) 2019, Nokia'
class _RemoteFile(object):
def __init__(self, terminal, filename, options='r'):
self.terminal = terminal
self.filename = filename
self.options = options
self.handle = None
def __enter__(self):
self.terminal.initialize_if_needed()
self.handle = self.terminal.get_proxy_object_from_call(
'open', self.filename, self.options)
self.handle.set_proxy_spec(file)
return self.handle
def __exit__(self, *args, **kwargs):
if self.handle is not None:
self.handle.close()
self.handle = None
class FileCopier(object):
def __init__(self, shells=None):
self.terminal = None
self.buffersize = 32768
self._initialize(BashShell() if shells is None else shells)
self._buf = None
def set_buffersize(self, buffersize):
self.buffersize = buffersize
def _initialize(self, shells):
self.terminal = AutoRunnerTerminal()
self.terminal.initialize_with_shells(shells=shells)
def copy_file_to_remote(self, source, dest):
self._copy_file_from_ropen_to_wopen(
lambda: open(source, 'rb'),
lambda: _RemoteFile(self.terminal, dest, 'wb'))
def copy_file_from_remote(self, source, dest):
self._copy_file_from_ropen_to_wopen(
lambda: _RemoteFile(self.terminal, source, 'rb'),
lambda: open(dest, 'wb'))
def _copy_file_from_ropen_to_wopen(self, ropen, wopen):
with ropen() as readf:
with wopen() as writef:
self._copy_file_from_readf_to_writef(readf, writef)
def _copy_file_from_readf_to_writef(self, readf, writef):
while self._read(readf):
writef.write(self._buf)
def _read(self, readf):
self._buf = readf.read(self.buffersize)
return self._buf
|