Add a new function "get_computer_system_info" in win and linux platform
It will be used to create a new dimension "synthetic_product_name"

The design doc for "synthetic_product_name" can be found on:
https://docs.google.com/document/d/1UAXCsF4R8NifgKAC_iDbaMl9gLITqhe02xJLix-_rLE/

Such dimension will only be shown for bots in pools chrome.tests.perf and chrome.tests.pinpoint
See related review https://crrev.com/i/1282559

Bug: 949662
Change-Id: Ibc03aeb943737dcce61395821124ef40b5ed11dd
Reviewed-on: https://chromium-review.googlesource.com/c/infra/luci/luci-py/+/1602879
Commit-Queue: Haiyang Pan <hypan@google.com>
Reviewed-by: Marc-Antoine Ruel <maruel@chromium.org>
Reviewed-by: Caleb Rouleau <crouleau@chromium.org>
diff --git a/appengine/swarming/swarming_bot/api/platforms/common.py b/appengine/swarming/swarming_bot/api/platforms/common.py
index d6c1b7b..819d55f 100644
--- a/appengine/swarming/swarming_bot/api/platforms/common.py
+++ b/appengine/swarming/swarming_bot/api/platforms/common.py
@@ -4,6 +4,8 @@
 
 """Common code for platforms."""
 
+from collections import namedtuple
+
 
 def _safe_parse(content, split=': '):
   """Safely parse a 'key: value' list of strings from a command."""
@@ -17,3 +19,7 @@
     values.setdefault(
         parts[0].strip().decode('utf-8'), parts[1].decode('utf-8'))
   return values
+
+
+ComputerSystemInfo = namedtuple('ComputerSystemInfo', [
+    'name', 'vendor', 'version', 'serial'])
diff --git a/appengine/swarming/swarming_bot/api/platforms/linux.py b/appengine/swarming/swarming_bot/api/platforms/linux.py
index c916c6b..72aa986 100644
--- a/appengine/swarming/swarming_bot/api/platforms/linux.py
+++ b/appengine/swarming/swarming_bot/api/platforms/linux.py
@@ -116,6 +116,14 @@
     return f.read()
 
 
+def _read_dmi_file(filename):
+  try:
+    with open('/sys/devices/virtual/dmi/id/' + filename, 'rb') as f:
+      return f.read().strip()
+  except (IOError, OSError):
+    return None
+
+
 ## Public API.
 
 
@@ -497,3 +505,16 @@
       'cmd': ' '.join(pipes.quote(c) for c in command),
       'name': name,
     }
+
+
+@tools.cached
+def get_computer_system_info():
+  """Return a named tuple, which lists the following params:
+
+  name, vendor, version, uuid
+  """
+  return common.ComputerSystemInfo(
+      name=_read_dmi_file('product_name'),
+      vendor=_read_dmi_file('sys_vendor'),
+      version=_read_dmi_file('product_version'),
+      serial=_read_dmi_file('product_serial'))
diff --git a/appengine/swarming/swarming_bot/api/platforms/win.py b/appengine/swarming/swarming_bot/api/platforms/win.py
index d21dc41..5b7358d 100644
--- a/appengine/swarming/swarming_bot/api/platforms/win.py
+++ b/appengine/swarming/swarming_bot/api/platforms/win.py
@@ -15,6 +15,7 @@
 
 from utils import tools
 
+import common
 import gpu
 
 
@@ -548,3 +549,25 @@
 
   ctypes.windll.user32.EnumWindows(window_enum_proc_prototype(on_window), None)
   return out
+
+
+@tools.cached
+def get_computer_system_info():
+  """Return a named tuple, which lists the following params from the WMI class
+  Win32_ComputerSystemProduct:
+
+  name, vendor, version, uuid
+  """
+  wbem = _get_wmi_wbem()
+  if not wbem:
+    return None
+
+  info = None
+  # https://msdn.microsoft.com/en-us/library/aa394105
+  for device in wbem.ExecQuery('SELECT * FROM Win32_ComputerSystemProduct'):
+    info = common.ComputerSystemInfo(
+        name=device.Name,
+        vendor=device.Vendor,
+        version=device.Version,
+        serial=device.IdentifyingNumber)
+  return info