running ansible playbook from python with subprocess.run doesnt pass extra vars - python

so i'm trying to run an ansible playbook from python with subprocess.run, the line im using is :
dns = "10.10.10.10"
subprocess.run(["ansible-playbook", f"{playbook_path}", f'-e "os_type=linux"', f'-i {dns},'])
and i'm getting
fatal: [10.10.10.10]: FAILED! => {"msg": "The conditional check 'os_type == 'linux'' failed. The error was: error while evaluating conditional (os_type == 'linux'): 'os_type' is undefined\n\nThe error appears to be in '/home/chaos_project/playbook': line 7, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n block:\n - name: Create a directory if it does not exist\n ^ here\n"}
as if os_type isnt defined, but when i just run it as a terminal command it works just fine :
ansible-playbook playbook -e 'os_type=linux' -i 10.10.10.10,

eventually im using ansible-runner, but for an easy fix :
subprocess.run(["ansible-playbook", f"{playbook_path}", f'-e os_type=linux', f'-i {dns},'])
worked fine.

Related

Python Subprocess [Errno 2] No such file or directory when calling subprocess.run()

I have a simple python web application made with flask. It compiles and runs the given c++ files on given input. Upon receiving the inputs from front-end, I use this function to compile and run the given file.
exec_id = get_unique_identifier(data["user_id"])
code = data["code"]
input_data = data["input"]
code_path = file_ops.write_code(code, data["lang"], exec_id)
logging.info("Code written to "+code_path)
#compile the code
logging.info("Compiling the code")
cmd = ['g++',code_path,'-o',exec_id]
logging.info("Command is : "+" ".join(cmd))
try:
compile_code=subprocess.run(cmd, stderr=PIPE)
has_compiled = compile_code.returncode
except Exception as e:
return {"status": "server Error", "output" : e}
compiled_file_path = './'+exec_id
file_ops.write_code is a utility function which takes input code, extension as input and writes the code in a file in the same directory. The code runs alright in local environment, However, In production server with nginx, The code never gets compiled and I get the following error(After a big traceback)
[Errno 2] No such file or directory: 'g++'
I tried the following things
Giving Absolute Path in code
passing shell=True in subprocess.run
Does this have something to do with Configuration with Nginx ? I'm running this application with gunicorn and nginx on Ubuntu VPS. If I run the code in development environment on vps, it runs without any error.

Run Python app (script on PATH) from Java

I'm facing quite simple problem, yet still not able to figure out what in particular causes that, and - more importantly - how to solve it.
I'm currently on Linux, and I would like to run an python app (script) from a Java application. The script is on PATH, thus I really would like to utilise that (avoid using absolute path to the script), if possible.
However, all I tried resulted in various forms of "File does not exist".
Sample
As a demonstration, I've tried to run one python3-based app (meld)
and one binary-built app (ls) for comparison:
$ which ls
/usr/bin/ls
$ file /usr/bin/ls
/usr/bin/ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=[...], for GNU/Linux 3.2.0, stripped
$ which meld
/usr/bin/meld
$ file /usr/bin/meld
/usr/bin/meld: Python script, UTF-8 Unicode text executable
$ head -n1 /usr/bin/meld
#!/usr/bin/python3
Nextly, I've created simple Java main, which tries several ways how to start theese:
package cz.martlin.processes;
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.util.List;
import java.util.stream.Collectors;
public class ProcessPlaying {
public static void main(String[] args) {
List<List<String>> commands = List.of(
List.of("ls"),
List.of("/usr/bin/ls"),
List.of("meld"),
List.of("/usr/bin/meld"),
List.of("python3", "/usr/bin/meld"),
List.of("/usr/bin/python3", "/usr/bin/meld"),
List.of("sh", "-c", "meld"),
List.of("sh", "-c", "/usr/bin/meld"),
List.of("sh", "-c", "python3 /usr/bin/meld")
);
for (List<String> command : commands) {
run(command);
}
}
private static void run(List<String> command) {
System.out.println("Running: " + command);
//String executable = command.get(0);
//boolean exists = new File(executable).exists();
//System.out.println("Exists the " + executable + " ? " + exists);
try {
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectError(Redirect.INHERIT);
Process proc = pb.start();
// Process proc = Runtime.getRuntime().exec(command.stream().collect(Collectors.joining(" ")));
int code = proc.waitFor();
System.out.println("OK, return code: " + code);
} catch (IOException e) {
System.out.println("Failed to start: " + e.toString());
} catch (InterruptedException e) {
System.out.println("Failed to await: " + e.toString());
}
System.out.println();
}
}
Here are the results:
Running: [ls]
OK, return code: 0
Running: [/usr/bin/ls]
OK, return code: 0
Running: [meld]
Failed to start: java.io.IOException: Cannot run program "meld": error=2, Directory or file doesn't exist
Running: [/usr/bin/meld]
Failed to start: java.io.IOException: Cannot run program "/usr/bin/meld": error=2, Directory or file doesn't exist
Running: [python3, /usr/bin/meld]
python3: can't open file '/usr/bin/meld': [Errno 2] No such file or directory
OK, return code: 2
Running: [/usr/bin/python3, /usr/bin/meld]
/usr/bin/python3: can't open file '/usr/bin/meld': [Errno 2] No such file or directory
OK, return code: 2
Running: [sh, -c, meld]
sh: line 1: meld: command not found
OK, return code: 127
Running: [sh, -c, /usr/bin/meld]
sh: line 1: /usr/bin/meld: Directory or file doesn't exist
OK, return code: 127
Running: [sh, -c, python3 /usr/bin/meld]
python3: can't open file '/usr/bin/meld': [Errno 2] No such file or directory
OK, return code: 2
To sum it up:
all of the commands tried works when executed directly from the shell (either sh or bash)
executing the binary works either by the full path (/usr/bin/ls) or by just the name (ls)
executing the python script the same way doesn't work neither way
when trying to run the python3 interpreter and populate the script path as an argument to the python, now the python yields the script file doesn't exist
trying to populate it as a command to the brand new shell didn't help either
I've tried to use the Runtime#exec (based on this comment: https://stackoverflow.com/a/36783743/3797793) to start the process (both the exec(String) and exec(String[] forms), but no sucess (none of the listed commands did actually execute).
Thus, my question is/are:
What do I understand wrong?
How to start the Python script from Java?
Would some small (ba)sh script wrapper do the job?
Since it's python3-based, Jython wouldn't help here (because the latest one is 2.7.*), would it?
Further requirements:
As mentioned, I would like to be able to avoid using full path to the Python script
Also, I would like to have platform independant solution (at least Linux and Windows compatible)
Thanks in advance

Fabric sudo call - Cannot hide fatal error

Running Fabric 1.10, Python 2.7 on RHEL6.5. We have a cloud environment where we provide OS layer support and there is no central LDAP so everything is done via scripting, OS level accounts and RSA keys. One thing you have to do is keep an eye on your account to ensure that your key is working but also that your password on each system is correct so you can sudo. I devised a small test specifically for this....
def sudotest(cmd="echo TEST"):
with hide('status','warnings','stderr', 'stdout','running','everything','status'), settings(warn_only=True):
env.abort_on_prompts = True
try:
result=sudo(cmd)
if (result.succeeded):
print(env.host + ":SUCCESS")
else:
print(env.host + ":FAIL")
except SystemExit:
print(env.host + ":FAIL")
except:
print(env.host + ":FAIL - catchall")
You'll notice I've been trying all kinds of settings and even doubling up as I've seen odd behavior with hiding output. For example without the double 'status' I still see 'disconnecting' messages. So I've tried throwing 'everything' and 'stderr' all over with no change in output. I added the inclusive except: just to see if it would help, no change. Also no change when trying an else:
In a good run I see this output:
[host1] Executing task 'sudotest'
host1 :SUCCESS
host2 :SUCCESS
So first observation is I'm still getting that first running message. Otherwise it's exactly what I want.
On an intentionally failed run of the same host list I get:
[host1] Executing task 'sudotest'
[host1] out: Sorry, try again.
[host1] out: sudo password:
Fatal error: Needed to prompt for a connection or sudo password (host: host1), but abort-on-prompts was set to True
Aborting.
host1 :FAIL
[host2] out: Sorry, try again.
[host2] out: sudo password:
Fatal error: Needed to prompt for a connection or sudo password (host: host2), but abort-on-prompts was set to True
Aborting.
host2 :FAIL
I've got the following env settings:
env.disable_known_hosts = True
env.skip_bad_hosts = True
env.remote_interupt = True
env.warn_only = True
env.eagerly_disconnect = True
I'm running it through fab, not python, i.e.: fab sudotest
Usually with me it's because I'm missing something simple. I can live with the first running message, it's the fatal error and the extra stderr output that turns a nice clean output into a wreck.
So what's missing? Thanks.
You can try with quiet=True:
output = sudo(cmd, quiet=True):
try with:
import fabric.api as fab
fab.output['aborts'] = False
I looked at fabric abort function and there is a check on "output.aborts"
more info here output_controls

My Python script hosted on OpenShift inside the .openshift/cron/minutely directory doesn't run. What's wrong?

I wrote the following script, which sends an email to a specific email address, and saved it inside the .openshift/cron/minutely directory:
import smtplib
g = smtplib.SMTP('smtp.gmail.com:587')
g.ehlo()
g.starttls()
g.ehlo()
g.login('myusername','mypassword')
g.sendmail('myemail','otheremail','message')
I then pushed the script to the server.
I expected the program to run once every minute, and receive an email every minute. However, there is no evidence indicating that my code is being run. Any idea what might be causing the problem? Did I forget a step while setting up my application?
Note: I've checked that the email address and password I provided were correct, and that cron is installed.
EDIT: It seems that the problem is originating from the server:
I deleted the original contents of the file, created 'testfile.txt', and wrote this code instead:
a = open('testfile.txt','r+')
if not a.read():
a.write('Test writing')
a.close()
after waiting for the code to run and ssh-ing into the server, I changed to the directory named app-root/logs and displayed the contents of cron.log, which looked something like this:
Sat Nov 8 11:01:11 EST 2014: START minutely cron run
__________________________________________________________________________
/var/lib/openshift/545a6ac550044652510001d3/app-root/runtime/repo//.openshift/cron/minutely/test_openshift.py:
/var/lib/openshift/545a6ac550044652510001d3/app-root/runtime/repo//.openshift/cron/minutely/test_openshift.py: line 1: syntax error near unexpected token `('
/var/lib/openshift/545a6ac550044652510001d3/app-root/runtime/repo//.openshift/cron/minutely/test_openshift.py: line 1: `a = open('testfile.txt','r+')'
__________________________________________________________________________
Sat Nov 8 11:01:11 EST 2014: END minutely cron run - status=0
__________________________________________________________________________
Could it be that the server is not interpreting the code in my file as python code? Any suggestions welcome.
connect to openshift console
rhc ssh app_name
Change to a directory to have permission to create script:
cd $OPENSHIFT_DATA_DIR
create test01.py script
touch test01.py
Give executing permission to test01.py
chmod +x test01.py
Edit script
nano test01.py
Add a simple code like
print("Hello")
run script:
./test01.py
Error:
./test01.py: line 1: syntax error near unexpected token `"Hello"'
./test01.py: line 1: `print("Hello")'
Now check python path
which python
Output
/var/lib/openshift/your-sesseion-id/python/virtenv/venv/bin/python
Now add a she bang to test01.py
#!/var/lib/openshift/your-sesseion-id/python/virtenv/venv/bin/python
print("Hello")
Now Execute it
./test01.py
Output:
Hello
Conclusion:
Your script should know how to run and where is python path, so add it at the first line of your script

Python Psphere Issue

Looking at using psphere. I've successfully installed it via pip but run into an issue when I execute the following code (taken from the psphere documentation site):
from psphere.client import Client
from psphere.managedobjects import HostSystem
Client = Client("server", "username", "password")
hs_list = HostSystem.all(Client)
len(hs_list)
After running that command I get the following:
"could not found expected ':'", self.get_mark())
yaml.scanner.ScannerError: while scanning a simple key
in "C:\Users\thor/.psphere/config.yaml", line 5, column 1
could not found expected ':'
in "C:\Users\thor/.psphere/config.yaml", line 6, column 1
There was no .psphere directory or config.yaml. I created both and no joy (although I must be honest - I don't really know what should be in the yaml file.)
There are no : in my file so I don't know why it's raising an exception.
Help would be appreciated. Thanks.
in the distribution's examples/ directory there is a sample_config.yaml file you can use.
# Copy this file into ~/.psphree/config.yaml and edit to your liking
general:
server: your.esxserver.com
username: Administrator
password: strongpassword
template_dir: ~/.psphere/templates/
logging:
destination: ~/.psphere/psphere.log
level: INFO # DEBUG, INFO, etc

Categories