cros_vm: Handle SSH port clash better.
Prior to this change, the user saw a saw a cryptic QEMU networking error
whenever there was a ssh port conflict. We now make an effort to check
that the port is free before calling qemu.
BUG=None
TEST=Call cros_vm --start from within the chroot and within the simple
chrome SDK.
Change-Id: Ib1bec87a33ffa6b6131115fae2315dba9746cdcf
Reviewed-on: https://chromium-review.googlesource.com/1220627
Commit-Ready: Achuith Bhandarkar <achuith@chromium.org>
Tested-by: Achuith Bhandarkar <achuith@chromium.org>
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
diff --git a/scripts/cros_vm.py b/scripts/cros_vm.py
index 7543ae8..a33416e 100644
--- a/scripts/cros_vm.py
+++ b/scripts/cros_vm.py
@@ -9,9 +9,11 @@
import argparse
import distutils.version
+import errno
import multiprocessing
import os
import re
+import socket
from chromite.cli.cros import cros_chrome_sdk
from chromite.lib import cache
@@ -258,6 +260,31 @@
raise VMError('VM image does not exist: %s' % self.image_path)
logging.debug('VM image path: %s', self.image_path)
+ def _WaitForSSHPort(self):
+ """Wait for SSH port to become available."""
+ class _SSHPortInUseError(Exception):
+ """Exception for _CheckSSHPortBusy to throw."""
+
+ def _CheckSSHPortBusy(ssh_port):
+ """Check if the SSH port is in use."""
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ try:
+ sock.bind((remote_access.LOCALHOST_IP, ssh_port))
+ except socket.error as e:
+ if e.errno == errno.EADDRINUSE:
+ logging.info('SSH port %d in use...', self.ssh_port)
+ raise _SSHPortInUseError()
+ sock.close()
+
+ try:
+ retry_util.RetryException(
+ exception=_SSHPortInUseError,
+ max_retry=7,
+ functor=lambda: _CheckSSHPortBusy(self.ssh_port),
+ sleep=1)
+ except _SSHPortInUseError:
+ raise VMError('SSH port %d in use' % self.ssh_port)
+
def Run(self):
"""Performs an action, one of start, stop, or run a command in the VM."""
if not self.start and not self.stop and not self.cmd:
@@ -276,6 +303,7 @@
"""Start the VM."""
self.Stop()
+ self._WaitForSSHPort()
logging.debug('Start VM')
self._SetQemuPath()
@@ -305,8 +333,8 @@
# Append 'check' to warn if the requested CPU is not fully supported.
'-cpu', self.qemu_cpu + ',check',
'-device', 'virtio-net,netdev=eth0',
- '-netdev', 'user,id=eth0,net=10.0.2.0/27,hostfwd=tcp:127.0.0.1:%d-:22'
- % self.ssh_port,
+ '-netdev', 'user,id=eth0,net=10.0.2.0/27,hostfwd=tcp:%s:%d-:22'
+ % (remote_access.LOCALHOST_IP, self.ssh_port),
'-drive', 'file=%s,index=0,media=disk,cache=unsafe,format=%s'
% (self.image_path, self.image_format),
]
@@ -382,7 +410,7 @@
try:
retry_util.RetryException(
exception=_TooFewPidsException,
- max_retry=20,
+ max_retry=5,
functor=lambda: _GetRunningPids(exe, numpids),
sleep=2)
except _TooFewPidsException: