# Copyright 2015 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.

"""GNU/Linux specific utility functions."""

import ctypes
import ctypes.util
import logging
import multiprocessing
import os
import pipes
import platform
import re
import shlex
import subprocess

from utils import tools

import common
import gpu


## Private stuff.


libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))

cpu_mask_t = ctypes.c_ulong

CPU_SETSIZE = 1024
NCPUBITS = 8 * ctypes.sizeof(cpu_mask_t)

pid_t = ctypes.c_uint64

class cpu_set_t(ctypes.Structure):
  _fields_ = [('__bits', cpu_mask_t * (CPU_SETSIZE / NCPUBITS))]

  def get_cpus(self):
    """Convert bits in list len == CPU_SETSIZE
    Use 1 / 0 per cpu
    """
    cpus = []
    for bitmask in getattr(self, '__bits'):
      for i in range(NCPUBITS):
        if bitmask & 1:
          cpus.append(i)
        bitmask >>= 1
        if not bitmask:
          break
    return cpus


@tools.cached
def get_num_processors():
  # Multiprocessing cpu_count() returns number of processors on the system,
  # not the number of processors process can actually use. These numbers
  # may differ for example in Docker containers. Use sched_getaffinity to
  # find out the number of usable processors instead.
  cpu_set = cpu_set_t()
  err = libc.sched_getaffinity(
      pid_t(os.getpid()),
      ctypes.sizeof(cpu_set_t),
      ctypes.pointer(cpu_set))
  if err != 0:
    # This is not a big deal, fallback onto multiprocessing. This happens on
    # MIPS.
    return multiprocessing.cpu_count()
  return len(cpu_set.get_cpus())


def _lspci():
  """Returns list of PCI devices found.

  list(Bus, Type, Vendor [ID], Device [ID], extra...)
  """
  try:
    lines = subprocess.check_output(
        ['lspci', '-mm', '-nn'], stderr=subprocess.PIPE).splitlines()
  except (OSError, subprocess.CalledProcessError):
    # It normally happens on Google Compute Engine as lspci is not installed by
    # default and on ARM since they do not have a PCI bus.
    return None
  return [shlex.split(l) for l in lines]


@tools.cached
def _get_nvidia_version():
  try:
    with open('/sys/module/nvidia/version', 'rb') as f:
      # Looks like '367.27'.
      return f.read().strip()
  except (IOError, OSError):
    return None


@tools.cached
def _get_intel_version():
  """Retrieves the Mesa DRI driver version, which is usable as the Intel GPU
  driver version.
  """
  try:
    out = subprocess.check_output(['dpkg', '-s', 'libgl1-mesa-dri'])
    # Looks like 'Version: 17.2.8-0ubuntu0~17.10.1', and we need '17.2.8'.
    for line in out.splitlines():
      match = re.match(r'^Version: (\d+.\d+.\d+)', line)
      if match:
        return match.group(1)
    return None
  except (OSError, subprocess.CalledProcessError):
    return None


def _read_cpuinfo():
  with open('/proc/cpuinfo', 'rb') as f:
    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.


@tools.cached
def get_os_version_number():
  """Returns the normalized OS version number as a string.

  Returns:
    - 12.04, 10.04, etc.
  """
  # On Ubuntu it will return a string like '12.04'. On Raspbian, it will look
  # like '7.6'.
  return unicode(platform.linux_distribution()[1])


def get_temperatures():
  """Returns the temperatures measured via thermal_zones

  Returns:
    - dict of temperatures found on device in degrees C
      (e.g. {'thermal_zone0': 43.0, 'thermal_zone1': 46.117})
  """
  temps = {}
  path = '/sys/class/thermal'
  if os.path.isdir(path):
    for filename in os.listdir(path):
      if re.match(r'^thermal_zone\d+', filename):
        try:
          with open(os.path.join(path, filename, 'temp'), 'rb') as f:
            # Convert from milli-C to Celsius
            temps[filename] = int(f.read()) / 1000.0
        except (IOError, OSError):
          pass
  return temps


@tools.cached
def get_audio():
  """Returns information about the audio."""
  pci_devices = _lspci()
  if not pci_devices:
    return None
  # Join columns 'Vendor' and 'Device'. 'man lspci' for more details.
  return [
    u': '.join(l[2:4]) for l in pci_devices if l[1] == 'Audio device [0403]'
  ]


@tools.cached
def get_cpuinfo():
  values = common._safe_parse(_read_cpuinfo())
  cpu_info = {}
  if u'vendor_id' in values:
    # Intel.
    cpu_info[u'flags'] = values[u'flags']
    cpu_info[u'model'] = [
      int(values[u'cpu family']), int(values[u'model']),
      int(values[u'stepping']), int(values[u'microcode'], 0),
    ]
    cpu_info[u'name'] = values[u'model name']
    cpu_info[u'vendor'] = values[u'vendor_id']
  elif u'mips' in values.get('isa', ''):
    # MIPS.
    cpu_info[u'flags'] = values[u'isa']
    cpu_info[u'name'] = values[u'cpu model']
  else:
    # CPU implementer == 0x41 means ARM.
    cpu_info[u'flags'] = values[u'Features']
    cpu_info[u'model'] = (
      int(values[u'CPU variant'], 0), int(values[u'CPU part'], 0),
      int(values[u'CPU revision']),
    )
    # ARM CPUs have a serial number embedded. Intel did try on the Pentium III
    # but gave up after backlash;
    # http://www.wired.com/1999/01/intel-on-privacy-whoops/
    # http://www.theregister.co.uk/2000/05/04/intel_processor_serial_number_q/
    # It is very ironic that ARM based manufacturers are getting away with.
    if u'Serial' in values:
      cpu_info[u'serial'] = values[u'Serial'].lstrip(u'0')
    if u'Revision' in values:
      cpu_info[u'revision'] = values[u'Revision']

    # 'Hardware' field has better content so use it instead of 'model name' /
    # 'Processor' field.
    if u'Hardware' in values:
      cpu_info[u'name'] = values[u'Hardware']
      # Samsung felt this was useful information. Strip that.
      suffix = ' (Flattened Device Tree)'
      if cpu_info[u'name'].endswith(suffix):
        cpu_info[u'name'] = cpu_info[u'name'][:-len(suffix)]
    # SAMSUNG EXYNOS5 uses 'Processor' instead of 'model name' as the key for
    # its name <insert exasperation meme here>.
    cpu_info[u'vendor'] = (
        values.get(u'model name') or values.get(u'Processor') or u'N/A')

  # http://unix.stackexchange.com/questions/43539/what-do-the-flags-in-proc-cpuinfo-mean
  cpu_info[u'flags'] = sorted(i for i in cpu_info[u'flags'].split())
  return cpu_info


def get_gpu():
  """Returns video device as listed by 'lspci'. See get_gpu().

  Not cached as the GPU driver may change underneat.
  """
  pci_devices = _lspci()
  if not pci_devices:
    # It normally happens on Google Compute Engine as lspci is not installed by
    # default and on ARM since they do not have a PCI bus. In either case, we
    # don't care about the GPU.
    return None, None

  dimensions = set()
  state = set()
  re_id = re.compile(r'^(.+?) \[([0-9a-f]{4})\]$')
  for line in pci_devices:
    # Look for display class as noted at http://wiki.osdev.org/PCI
    dev_type = re_id.match(line[1]).group(2)
    if not dev_type or not dev_type.startswith('03'):
      continue
    vendor = re_id.match(line[2])
    device = re_id.match(line[3])
    if not vendor or not device:
      continue
    ven_name = vendor.group(1)
    ven_id = vendor.group(2)
    dev_name = device.group(1)
    dev_id = device.group(2)

    # TODO(maruel): Implement for AMD once needed.
    version = u''
    if ven_id == gpu.NVIDIA:
      version = _get_nvidia_version()
    elif ven_id == gpu.INTEL:
      version = _get_intel_version()
    ven_name, dev_name = gpu.ids_to_names(ven_id, ven_name, dev_id, dev_name)

    dimensions.add(unicode(ven_id))
    dimensions.add(u'%s:%s' % (ven_id, dev_id))
    if version:
      dimensions.add(u'%s:%s-%s' % (ven_id, dev_id, version))
      state.add(u'%s %s %s' % (ven_name, dev_name, version))
    else:
      state.add(u'%s %s' % (ven_name, dev_name))
  return sorted(dimensions), sorted(state)


def get_uptime():
  """Returns uptime in seconds since system startup.

  Includes sleep time.
  """
  try:
    with open('/proc/uptime', 'rb') as f:
      return float(f.read().split()[0])
  except (IOError, OSError, ValueError):
    return 0.


def get_reboot_required():
  """Returns True if the system should be rebooted to apply updates.

  This only checks /var/run/reboot-required, which not all distros support and
  which is not set for all conditions requiring reboot.
  """
  return os.path.exists('/var/run/reboot-required')


@tools.cached
def get_ssd():
  """Returns a list of SSD disks."""
  try:
    out = subprocess.check_output(
        ['lsblk', '-d', '-o', 'name,rota']).splitlines()
    ssd = []
    for line in out:
      match = re.match(r'(\w+)\s+(0|1)', line)
      if match and match.group(2) == '0':
        ssd.append(match.group(1).decode('utf-8'))
    return tuple(sorted(ssd))
  except (OSError, subprocess.CalledProcessError) as e:
    logging.error('Failed to read disk info: %s', e)
    return ()


@tools.cached
def get_kvm():
  """Check whether KVM is available."""
  # We only check the file existence, not whether we can access it. This avoids
  # the race condition between swarming_bot and udev which is responsible for
  # setting the correct ACL of /dev/kvm.
  return os.path.exists('/dev/kvm')


@tools.cached
def get_inside_docker():
  """Returns a strings representing if running inside docker, and which type.

  Returns:
    - None if not run in docker.
    - u'stock' if running in standard docker.
    - u'nvidia' if running in nvidia-docker.
  """
  if not os.path.isfile('/.docker_env') and not os.path.isfile('/.dockerenv'):
    return None
  # TODO(maruel): Detect nvidia-docker.
  return u'stock'


@tools.cached
def get_device_tree_compatible():
  """Returns the devicetree/compatible data, if available.

  This is generally used on ARM based hardware.
  """
  try:
    with open('/sys/firmware/devicetree/base/compatible', 'rb') as f:
      items = f.read().strip().split(',')
  except IOError:
    return None
  # The data could contain nul byte or other invalid data, we've observed this
  # on ODROID-C2.
  for i, item in enumerate(items):
    if '\x00' in item:
      items[i] = None
    else:
      try:
        items[i] = item.decode('utf-8', 'replace')
      except UnicodeDecodeError:
        items[i] = None
  return sorted(i for i in items if i)


def get_cpu_scaling_governor(cpu_num):
  """Returns the current CPU scaling governor, if available."""
  files = [
      '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor' % cpu_num,
      '/sys/devices/system/cpu/cpufreq/policy%d/scaling_governor' % cpu_num,
  ]
  for p in files:
    try:
      with open(p, 'rb') as f:
        return [unicode(f.read().strip())]
    except IOError:
      continue
  return None


## Mutating code.


def generate_initd(command, cwd, user):
  """Returns a valid init.d script for use for Swarming.

  Author is lazy so he copy-pasted.
  Source: https://github.com/fhd/init-script-template

  Copyright (C) 2012-2014 Felix H. Dahlke
  This is open source software, licensed under the MIT License. See the file
  LICENSE for details.

  LICENSE is at https://github.com/fhd/init-script-template/blob/master/LICENSE
  """
  return """#!/bin/sh
### BEGIN INIT INFO
# Provides:          swarming
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO

dir='%(cwd)s'
user='%(user)s'
cmd='%(cmd)s'

name=`basename $0`
pid_file="/var/run/$name.pid"
stdout_log="/var/log/$name.log"
stderr_log="/var/log/$name.err"

get_pid() {
  cat "$pid_file"
}

is_running() {
  [ -f "$pid_file" ] && ps `get_pid` > /dev/null 2>&1
}

case "$1" in
  start)
  if is_running; then
    echo "Already started"
  else
    echo "Starting $name"
    cd "$dir"
    sudo -u "$user" $cmd >> "$stdout_log" 2>> "$stderr_log" &
    echo $! > "$pid_file"
    if ! is_running; then
      echo "Unable to start, see $stdout_log and $stderr_log"
      exit 1
    fi
  fi
  ;;
  stop)
  if is_running; then
    echo -n "Stopping $name.."
    kill `get_pid`
    for i in {1..10}
    do
      if ! is_running; then
        break
      fi

      echo -n "."
      sleep 1
    done
    echo

    if is_running; then
      echo "Not stopped; may still be shutting down or shutdown may have failed"
      exit 1
    else
      echo "Stopped"
      if [ -f "$pid_file" ]; then
        rm "$pid_file"
      fi
    fi
  else
    echo "Not running"
  fi
  ;;
  restart)
  $0 stop
  if is_running; then
    echo "Unable to stop, will not attempt to start"
    exit 1
  fi
  $0 start
  ;;
  status)
  if is_running; then
    echo "Running"
  else
    echo "Stopped"
    exit 1
  fi
  ;;
  *)
  echo "Usage: $0 {start|stop|restart|status}"
  exit 1
  ;;
esac

exit 0
""" % {
      'cmd': ' '.join(pipes.quote(c) for c in command),
      'cwd': pipes.quote(cwd),
      'user': pipes.quote(user),
    }


def generate_autostart_desktop(command, name):
  """Returns a valid .desktop for use with Swarming bot.

  http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
  """
  return (
    '[Desktop Entry]\n'
    'Type=Application\n'
    'Name=%(name)s\n'
    'Exec=%(cmd)s\n'
    'Hidden=false\n'
    'NoDisplay=false\n'
    'Comment=Created by os_utilities.py in swarming_bot.zip\n'
    'X-GNOME-Autostart-enabled=true\n') % {
      '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'))
