I am using the googleapiclient
python api to start a vm, and then paramiko
to connect to it via ssh.
I use googleapiclient.discovery
to get the GCE
api
compute = googleapiclient.discovery.build('compute', 'v1')
I start my vm using the start
api call
req = compute.instances().start(project, zone, instance)
resp = request.execute()
while resp['status'] != 'DONE':
time.sleep(1)
resp = req.execute()
I then perform a get
request to find the vm details, and in turn the ephemeral external ip address
req = compute.instances().get(project, zone, instance)
info = req.execute()
ip_address = info['networkInterfaces'][0]['accessConfigs'][0]['natIP']
Finally, I use paramiko
to connect to this ip address.
ssh_client = paramiko.SSHClient()
ssh_client.connect(ip_address)
Non-deterministically, the connect
call fails:
.../lib/python3.6/site-packages/paramiko/client.py", line 362, in connect raise NoValidConnectionsError(errors) paramiko.ssh_exception.NoValidConnections Error: [Errno None] Unable to connect to port 22 on xxx.xxx.xxx.xxx
It seems to be timing related, as putting in a time.sleep(5)
before the ssh_client.connect
call has preventing this error.
I'm assuming this allows sufficient time for sshd
to start accepting connections, but I'm not certain.
Putting sleeps in my code is uber hacky, so I'd much prefer to find a way to deterministically wait until the ssh daemon is running and available for me to connect to it (if that is indeed the cause of the NoValidConnections
exception)
- Is there a way to instruct the GCE api to only return from
start
when the VM is running andsshd
is available for me to connect to? - Is there a way to request this information using the GCE api?
Alternately I see paramiko
has a timeout
option in the connect
call - should I just change my 5 second sleep to a 5 second timeout?