Allow tests run for IPv6 only BMC

Changed:
  Replaced gethostbyname with getaddrinfo. gethostbyname only returns
  IPv4 addresses, so, if target has only IPv6 address, socket.gaierror
  is thrown. getaddrinfo returns all IPv4 and IPv6. The code still
  prefers IPv4.

Tested:
  Ran against IPv6 only BMC, it worked.

Change-Id: I47b59e05506dda14cdd8d60c8b1db98e86c1bd39
Signed-off-by: Igor Kanyuka <ifelmail@gmail.com>
diff --git a/lib/bmc_network_utils.py b/lib/bmc_network_utils.py
index 82b10fd..84410f9 100644
--- a/lib/bmc_network_utils.py
+++ b/lib/bmc_network_utils.py
@@ -31,7 +31,7 @@
     ip_list = list()
     stdout = subprocess.check_output(["hostname", "--all-fqdns"], shell=True)
     host_fqdns = stdout.decode("utf-8").strip()
-    ip_address = socket.gethostbyname(str(host_fqdns))
+    ip_address = gm.get_first_host_addr(host_fqdns)
     ip_list.append(ip_address)
 
     return ip_list
diff --git a/lib/gen_misc.py b/lib/gen_misc.py
index cc82034..e2136c2 100755
--- a/lib/gen_misc.py
+++ b/lib/gen_misc.py
@@ -448,10 +448,11 @@
                                     and short_host.
     """
 
-    host = dft(host, socket.gethostname())
+    if not host:
+        host = socket.gethostname()
     host_name = socket.getfqdn(host)
     try:
-        host_ip = socket.gethostbyname(host)
+        host_ip = get_first_host_addr(host)
     except socket.gaierror as my_gaierror:
         message = (
             "Unable to obtain the host name for the following host:"
@@ -468,6 +469,22 @@
         return host_name, host_ip
 
 
+def get_first_host_addr(host):
+    # Prefer IPv4
+    addr_infos = sorted(
+        socket.getaddrinfo(host, 443, proto=socket.IPPROTO_TCP),
+        key=lambda x: x[0],
+    )
+    # socket.getaddrinfo returns a list of 5-tuples with the
+    # following structure:
+    # (family, type, proto, canonname, sockaddr)
+    # sockaddr structure is (ip, port)
+    # See: https://docs.python.org/3/library/socket.html#socket.getaddrinfo
+    # Take the first tuple for the first IP,
+    # then its 4th element - sockaddr and IP from it
+    return addr_infos[0][4][0]
+
+
 def pid_active(pid):
     r"""
     Return true if pid represents an active pid and false otherwise.