Basic example of AMI connection to Asterisk from Python script w/Starpy - python

I have some years of solid experience working with asterisk but am new to python.
I want to connect from a python script and receive some events. I have created a manager user with AMIUSERNAME and AMIPASSWORD as credentials and tested working OK. I have also installed StarPy.
Then I run with the command python ami.py USERNAME PASSWORD the following script:
import sys
from starpy import manager
f = manager.AMIFactory(sys.argv[1], sys.argv[2])
df = f.login('127.0.0.1',5038)
While monitoring the asterisk console and nothing happens.
Does anyone know what I am missing?
I would like to send a Ping action and wait for a Pong response.

I suppose that f.login() returns you an AMIProtocol instance that has a ping() method.
I don't know anything about starpy, so some vague advice:
Start Python as an interactive shell. Execute code and examine results on the spot. help function is your friend; try help(df) after the last line of your script.
Look at the examples directory in starpy distribution. Maybe 90% of the code you need is already there.

The following is pulled from the ami module (and a few other places) in the Asterisk Test Suite. We use starpy extensively throughout the Test Suite, so you may want to check it out for some examples. Assume that the following code resides in some class with member method login.
def login(self):
def on_login_success(self, ami):
self.ami_factory.ping().addCallback(ping_response)
return ami
def on_login_error(self, reason):
print "Failed to log into AMI"
return reason
def ping_response(self, ami)
print "Got a ping response!"
return ami
self.ami_factory = manager.AMIFactory("user", "mysecret")
self.ami_factory.login("127.0.0.1", 5038).addCallbacks(on_login_success, on_login_error)
Make sure as well that your manager.conf is configured properly. For the Asterisk Test Suite, we use the following:
[general]
enabled = yes
webenabled = yes
port = 5038
bindaddr = 127.0.0.1
[user]
secret = mysecret
read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan,test
write = system,call,agent,user,config,command,reporting,originate

Related

Environment Variables in Fabric2

I’m using Python 3.6 and Fabric 2.4. I’m using Fabric to SSH into a server and run some commands. I need to set an environment variable for the commands being run on the remote server. The documentation indicates that something like this should work:
from fabric import task
#task(hosts=["servername"])
def do_things(c):
c.run("command_to_execute", env={"KEY": "VALUE"})
But that doesn’t work. Something like this should also be possible:
from fabric import task
#task(hosts=["servername"])
def do_things(c):
c.config.run.env = {"KEY": "VALUE"}
c.run("command_to_execute")
But that doesn’t work either. I feel like I’m missing something. Can anyone help?
I was able to do it by setting inline_ssh_env=True, and then explicitly setting the env variable, ex:
with Connection(host=hostname, user=username, inline_ssh_env=True) as c:
c.config.run.env = {"MY_VAR": "this worked"}
c.run('echo $MY_VAR')
As stated on the site of Fabric:
The root cause of this is typically because the SSH server runs non-interactive commands via a very limited shell call: /path/to/shell -c "command" (for example, OpenSSH). Most shells, when run this way, are not considered to be either interactive or login shells; and this then impacts which startup files get loaded.
You read more on this page link
So what you try to do won't work, and the solution is to pass the environment variable you want to set explicitly:
from fabric import task
#task(hosts=["servername"])
def do_things(c):
c.config.run.env = {"KEY": "VALUE"}
c.run('echo export %s >> ~/.bashrc ' % 'ENV_VAR=VALUE' )
c.run('source ~/.bashrc' )
c.run('echo $ENV_VAR') # to verify if it's set or not!
c.run("command_to_execute")
You can try that:
#task
def qa(ctx):
ctx.config.run.env['counter'] = 22
ctx.config.run.env['conn'] = Connection('qa_host')
#task
def sign(ctx):
print(ctx.config.run.env['counter'])
conn = ctx.config.run.env['conn']
conn.run('touch mike_was_here.txt')
And run:
fab2 qa sign
When creating the Connection object, try adding inline_ssh_env=True.
Quoting the documentation:
Whether to send environment variables “inline” as prefixes in front of command strings (export VARNAME=value && mycommand here), instead of trying to submit them through the SSH protocol itself (which is the default behavior). This is necessary if the remote server has a restricted AcceptEnv setting (which is the common default).
According to that part of the official doc, the connect_kwargs attribute of the Connection object is intended to replace the env dict. I use it, and it works as expected.

Python 2.6 pxssh Password GUI spawned on login failure

Before I get into the details, I have already attempted the solution from this question with no success.
I am trying to use the pxssh module within pexpect to SSH to a remote system and collect the uptime data. However, whenever I enter the incorrect password, the script generates a GUI password prompt for openSSH.
The script will query a large number of systems and write the output to a log, so I want it to just write a note in the log whenever the SSH connection fails; I don't want it to ever pop up a window.
Here is the current code of the function:
def getUptime(ipAddr, passwd):
try:
os.unsetenv('SSH_ASKPASS')
ssh = px.pxssh.pxssh()
ssh.options={"NumberOfPasswordPrompts":"1"}
ssh.force_password=True
ssh.options = {'RequestTTY':'Force'}
ssh.login(ipAddr,"root",passwd,auto_prompt_reset=False)
ssh.sendline("uptime")
ssh.prompt()
uptime = ssh.before.split()
ssh.logout()
uptime = ' '.join(uptime[uptime.index('up'):]).split(',')[0].strip('up')
return(uptime)
except(px.pxssh.ExceptionPxssh):
return("SSH connection failed; double-check the password")
I apologize if there are typos in that code, I had to re-type it by hand since Virtualbox is not letting me copy and paste from my development environment (SLES 11 x64, if that matters), even with bidirectional clipboard enabled.
I have tried the following steps (some of which are visible above):
Set ssh.force_password=True
Set ssh.options = {'RequestTTY':'Force'} (This should be equivalent to using "-t" in the SSH CLI argument, if I understand the openSSH documentation)
Set auto_prompt_reset=False
Edit pxssh.py to set "ssh_options" from '' to '-t -x' (I tried each option separately, then both together).
Manually unset SSH_ASKPASS in the shell before running the script.
Unset SSH_ASKPASS with os.unsetenv() immediately before invoking pxssh within the script.
Set the "NumberOfPasswordPrompts" option to "1".
The observed behavior when it gets an incorrect password is that it will print "SSH connection failed..." as expected, but it will also popup the openSSH password window.
None of those listed steps has had any noticeable effect on the script's performance whatsoever, and most of my Google searches on this issue point back to that linked question. If anyone has any idea of how I can possibly 100% suppress that password window, I would very much appreciate the assistance.
Thank you all in advance for your advice.
Potential Solution
I've found that I can keep the window from popping up by taking the following steps:
In pxssh.py change ssh_options from '' to "-o 'NumberOfPasswordPrompts=1'"
In my script, catch pexpect.EOF along with pexpect.pxssh.ExceptionPxssh to determine when a password has failed.
I'm not accepting this as an answer just yet because it seems like a very poor solution to me, particularly editing pxssh.py. I attempted to set the NumberOfPasswordPrompts option within my script, but it has no effect, so I must have the incorrect syntax.
You don't need to update pxssh.py at all. Instead:
ssh = px.pxssh.pxssh()
ssh.force_password = True
ssh.SSH_OPTS = "-o 'NumberOfPasswordPrompts=1'"
I had this problem quite a while ago, see if this helps. Python PXSSH GUI spawn on login failure
If not then trying opening the pxsssh module in you python library. If I remember correctly theres an issue that's explained in the __init__ where all you need to do is comment a line and uncomment a line.
Edit:
In the pexpect package theres the pxssh.py file, open it up and look at line 115 there should be your fix. Heres what your looking for
path: /usr/lib/python2.7/dist-packages/pexpect/pxssh.py
# Comment this line
self.SSH_OPTS = ("-o'RSAAuthentication=no'"
+ " -o 'PubkeyAuthentication=no'")
# Disabling host key checking, makes you vulnerable to MITM attacks.
# + " -o 'StrictHostKeyChecking=no'"
# + " -o 'UserKnownHostsFile /dev/null' ")
# Disabling X11 forwarding gets rid of the annoying SSH_ASKPASS from
# displaying a GUI password dialog. I have not figured out how to
# disable only SSH_ASKPASS without also disabling X11 forwarding.
# Unsetting SSH_ASKPASS on the remote side doesn't disable it! Annoying!
# UNCOMMENT THE LINE BELOW
#self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'"
self.force_password = False
self.auto_prompt_reset = True
I haven't used the pxssh module in quite sometime. But I think you can find away to override the SSH_OPTS so that you don't need to physically modify the module.

Creating an outgoing call using Asterisk Manager and "pyst"

I am trying to write some automation tests which make a phone call to my local Asterisk instance and then check that a receiving SIP client has received the call.
It is my understanding that I can create an outgoing call event using the Asterisk Manager. To do this I have been trying to use the Python 'pyst' library.
I have not been able to find any working examples of how to implement this scenario. From the information I have managed to gather, I have come up with this script:
from asterisk import manager
HOST = 'localhost'
PORT = 5068
m = manager.Manager()
m.connect( HOST )
m.login( 'admin', 'temp123' )
targetURL = '441610000001'
response = m.originate(
targetURL ,
's',
context='outgoing',
priority='1'
)
print m.status()
m.logoff()
m.close()
This script reports a 'success' response from Asterisk Manager but does not actually create an outgoing call.
Has anyone written a script to do this in python?
I am only familiar with the Python language so solutions in other languages wouldn't be very helpful for me!
Please read again documentation
"Targeturl" in your program actually have be channel, so in your code it have no channel type and host(if that sip).
Valid examples are:
targetURL = 'SIP/441610000001#myprovider_name'
targetURL = 'Local/441610000001#outbound_context'
Context "outbound" have be valid and have deliver call.
PYST is opensource framework. If you are realy "familar" with python, i recommend you read source of originate method and check what it send with asterisk doc
http://www.voip-info.org/wiki/view/Asterisk+Manager+API+Action+Originate
Note: it is very bad idea program for asterisk using framework like PYST if you have no general knowledge about asterisk itself. First you need read asterisk book.

python define replica set configuration

I'm writing the script to setup the replaset for mongo in python.
The first part of the script starts the processes and the second should configure the replicaset.
From the command line I ussually do:
config={_id:"aaa",members:[{_id:0,host:"localhost:27017"},{_id:1,host:"localhost:27018"},{_id:2,host:"localhost:27019",arbiterOnly:true}]}
rs.initiate(config)
rs.status();
And then I'm looking from rs.status() that all members are initialized
I want to do the same in python script.
In general i'm looking for a good reference of setup scripts for mongodb (also sharding). I saw the python script in their site, it is a good start point (but it only for single machine and sinle node in replSet). I need to setup all on different machines.
Thanks
If you run rs.initiate (without the (config)) the shell tells you which command it would run. In this case, it would be:
function (c) {
return db._adminCommand({replSetInitiate:c});
}
In python this should be something like:
>>> from pymongo import Connection
>>> c = Connection("morton.local:27017", slave_okay=True)
>>> d.command( "replSetInitiate", c );
With c being your replicaset configuration. http://api.mongodb.org/python/current/api/pymongo/database.html#pymongo.database.Database.command has some more information on calling commands.
Thanks Derick. Here are some remarks to your answer. 'replSetInitiate' is DBA command. Run it agains 'admin' database. As here:
conn = Connection("localhost:27017", slave_okay=True)
conn.admin.command( "replSetInitiate" );
To get the output of rs.status in pymongo we can use like this
def __init__(self):
'''Constructor'''
self.mdb=ReplicaSetConnection('localhost:27017',replicaSet='rs0')
def statusofcluster(self):
'''Check the status of Cluster and gives the output as true'''
print "We are Inside Status of Cluster"
output=self.mdb.admin.command('replSetGetStatus')

Dispatching an external script from Trace32's PRACTICE II script?

Is it possible to dispatch an external (python) script from Trace32 using its PRACTICE II scripting language?
For future googlers, like me, here is how to use the Lauterbach c-API to execute PRACTICE commands from Python. The TRACE32 application has to be open before you run your script. You also have to add 5 lines (including two blank lines) to your config.t32 file:
#You must have an empty line before
RCL=NETASSIST
PACKLEN=1024
PORT=20010
#and after these three parameters
At least the PORT parameter value is arbitary, but it has to match in your config and script. It defines the UDP port over which the API will be available.
This code demonstrates how you can use the the API in Python:
from ctypes import *
node = (c_char_p('NODE='),c_char_p('localhost'))
port = (c_char_p('PORT='),c_char_p('20010'))
plen = (c_char_p('PACKLEN='),c_char_p('1024'))
mydll = cdll.LoadLibrary(r'C:\T32\demo\api\capi\dll\T32api.dll')
error = mydll.T32_Config(*node)
error = mydll.T32_Config(*port)
error = mydll.T32_Config(*plen)
error = mydll.T32_Init()
error = mydll.T32_Attach(1)
#Try a PRACTICE command
cmd = c_char_p('DATA.DUMP 0xFF800000')
mydll.T32_Cmd(cmd)
Check that the T32api.dll is in the directory specified in the script.
Lauterbach provides more documentation for this api. Take a look in the demo\api\capi folder and this document http://www2.lauterbach.com/pdf/api_remote.pdf
Use OS.Screen to make a command prompt session.

Categories