0

I am a complete newb to Python and development and i'm stuck on a project.

I have a function that gets me a list of servers from our Salt Master. I am then trying to use that list inside of a for loop to connect to that server and copy my public keys to them. When I hardcode the servers it runs without issue. It looks like my variable in my for loop isnt returning anything.

Here is my For loop.

def deploy_key(key, server, username, password):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(server, username=username, password=password)
    transport = ssh.get_transport()
    session = transport.open_session()
    session.set_combine_stderr(True)
    session.get_pty()
    session = transport.open_session()
    session.set_combine_stderr(True)
    session.get_pty()
    for commands in l_commands:
        session = transport.open_session()
        session.set_combine_stderr(True)
        session.get_pty()
        session.exec_command(commands)
        stdin = session.makefile('wb', -1)
        stdout = session.makefile('rb', -1)
        stdin.write(password + '\n')
        stdin.flush()

username = "myUserName"
password = "myPassword"
server = hosts()
user = getUser()
key = getKey()
l_commands = ['sudo mkdir -p /home/%s/.ssh/' % user,'sudo chmod -R 777 /home/%s' %user,
          'sudo echo "%s" >> /home/%s/.ssh/authorized_keys' %(key, user),
          'sudo chmod 644 /home/%s/.ssh/authorized_keys' % user,
          'sudo chmod 700 /home/%s/.ssh/' % user, 'sudo chmod 755 /home/%s' %user]

for host in server:
    deploy_key(key, host, username, password)

Here is my function to get the variables

import paramiko

l_password = "myPassword"
l_host = "saltMaster.salt.com"
l_commands = "sudo salt-key -L"
l_user = "myUser"

def hosts():
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(l_host, username=l_user, password=l_password)
    transport = ssh.get_transport()
    session = transport.open_session()
    session.set_combine_stderr(True)
    session.get_pty()
    session = transport.open_session()
    session.set_combine_stderr(True)
    session.get_pty()
    session.exec_command(l_commands)
    stdin = session.makefile('wb', -1)
    stdout = session.makefile('rb', -1)
    stdin.write(l_password + '\n')
    stdin.flush()

    for line in stdout.read().splitlines():
        input_line = line
        input_line = input_line.replace(b"\x1b[0;32m", b'')  # remove \x1b[1;32m
        input_line = input_line.replace(b"\x1b[0;0m", b'')  # remove \x1b[1;35m
        input_line = input_line.replace(b"\x1b[0;1;34mRejected Keys:", b'')  # remove \x1b[1;36m
        input_line = input_line.replace(b"\x1b[0;1;31mUnaccepted Keys:", b'')  # remove \x1b[1m
        input_line = input_line.replace(b"\x1b[0;1;35mDenied Keys:", b'')  # remove \x07 (BEL)
        input_line = input_line.replace(b"\x1b[0;1;32mAccepted Keys:", b'')  # remove \x07 (BEL)
        input_line = input_line.replace(b"Freedom1", b'')  # remove \x07 (BEL)

        hostsIndividual = str(input_line,"utf-8")
        return(hostsIndividual)
2
  • Before your for loop what does l_commands hold, can you print it out to make sure it's what you want ? Also for your host function why are you returning after the first for loop iteration? If it's just one iteration why need a for loop in the first place? Commented Dec 28, 2016 at 18:35
  • The hosts() function only ever returns a single hostsIndividual value because you have a return statement inside the for loop within it. Commented Dec 28, 2016 at 18:45

2 Answers 2

1

The problem is in the return statement of hosts() method.

def hosts():
    // your code goes here

    for line in stdout.read().splitlines():
        // your code goes here
        hostsIndividual = str(input_line,"utf-8")
        return(hostsIndividual)

Here loop will run only once as function will return a single String in the very first iteration of the loop. You should place the return statement outside the loop first.

def hosts():
    // your code goes here

    for line in stdout.read().splitlines():
        // your code goes here
        hostsIndividual = str(input_line,"utf-8")

    return(hostsIndividual) // returning only one host name

You also need to use a list of server names (strings) and return it from hosts() method rather returning only hostIndividual (a single String) as follows.

def hosts():
    // your code goes here

    hosts = []
    for line in stdout.read().splitlines():
        // your code goes here
        hostsIndividual = str(input_line,"utf-8")
        hosts.append(hostsIndividual) 

    return(hosts) // now returning a list of host name

Now you can iterate through the list of servers (list of Strings) returned by hosts().

for host in server:
    deploy_key(key, host, username, password)
Sign up to request clarification or add additional context in comments.

Comments

1

Your loop returns a single string, the first input line you find. Thus, in your main program, server is a that single string, and your loop

for host in server:

iterates through the characters of that string. Try making this change to your function's loop ... instead of

for line in ...
    ...
    hostsIndividual = str(input_line,"utf-8")
    return(hostsIndividual)

Use

server_list = []
for line in ...
    ...
    hostsIndividual = str(input_line,"utf-8")
    server_list.append(hostsIndividual)

return(server_list)

This builds a list of strings, each of which is one server; after the loop is done, it returns the entire list to the main program.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.