Home | History | Annotate | Download | only in site_utils
      1 # Copyright 2016 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """Chrome OS Parnter Concole remote actions."""
      6 
      7 from __future__ import print_function
      8 
      9 import base64
     10 import logging
     11 
     12 import common
     13 
     14 from autotest_lib.client.common_lib import global_config
     15 from autotest_lib.client.common_lib import utils
     16 from autotest_lib.server.hosts import moblab_host
     17 from autotest_lib.site_utils import pubsub_utils
     18 
     19 
     20 _PUBSUB_TOPIC = global_config.global_config.get_config_value(
     21         'CROS', 'cloud_notification_topic', default=None)
     22 
     23 # Test upload pubsub notification attributes
     24 NOTIFICATION_ATTR_VERSION = 'version'
     25 NOTIFICATION_ATTR_GCS_URI = 'gcs_uri'
     26 NOTIFICATION_ATTR_MOBLAB_MAC = 'moblab_mac_address'
     27 NOTIFICATION_ATTR_MOBLAB_ID = 'moblab_id'
     28 NOTIFICATION_VERSION = '1'
     29 # the message data for new test result notification.
     30 NEW_TEST_RESULT_MESSAGE = 'NEW_TEST_RESULT'
     31 
     32 
     33 ALERT_CRITICAL = 'Critical'
     34 ALERT_MAJOR = 'Major'
     35 ALERT_MINOR = 'Minor'
     36 
     37 LOG_INFO = 'Info'
     38 LOG_WARNING = 'Warning'
     39 LOG_SEVERE = 'Severe'
     40 LOG_FATAL = 'Fatal'
     41 
     42 
     43 def is_cloud_notification_enabled():
     44     """Checks if cloud pubsub notification is enabled.
     45 
     46     @returns: True if cloud pubsub notification is enabled. Otherwise, False.
     47     """
     48     return  global_config.global_config.get_config_value(
     49         'CROS', 'cloud_notification_enabled', type=bool, default=False)
     50 
     51 
     52 class CloudConsoleClient(object):
     53     """The remote interface to the Cloud Console."""
     54     def send_heartbeat(self):
     55         """Sends a heartbeat.
     56 
     57         @returns True if the notification is successfully sent.
     58             Otherwise, False.
     59         """
     60         pass
     61 
     62     def send_event(self, event_type=None, event_data=None):
     63         """Sends an event notification to the remote console.
     64 
     65         @param event_type: The event type that is defined in the protobuffer
     66             file 'cloud_console.proto'.
     67         @param event_data: The event data.
     68 
     69         @returns True if the notification is successfully sent.
     70             Otherwise, False.
     71         """
     72         pass
     73 
     74     def send_log(self, msg, level=LOG_INFO, session_id=None):
     75         """Sends a log message to the remote console.
     76 
     77         @param msg: The log message.
     78         @param level: The logging level as string.
     79         @param session_id: The current session id.
     80 
     81         @returns True if the notification is successfully sent.
     82             Otherwise, False.
     83         """
     84         pass
     85 
     86     def send_alert(self, msg, level=ALERT_MINOR, session_id=None):
     87         """Sends an alert to the remote console.
     88 
     89         @param msg: The alert message.
     90         @param level: The logging level as string.
     91         @param session_id: The current session id.
     92 
     93         @returns True if the notification is successfully sent.
     94             Otherwise, False.
     95         """
     96         pass
     97 
     98     def send_test_job_offloaded_message(self, gcs_uri):
     99         """Sends a test job offloaded message to the remote console.
    100 
    101         @param gcs_uri: The test result Google Cloud Storage URI.
    102 
    103         @returns True if the notification is successfully sent.
    104             Otherwise, False.
    105         """
    106         pass
    107 
    108 
    109 # Make it easy to mock out
    110 def _create_pubsub_client(credential):
    111     return pubsub_utils.PubSubClient(credential)
    112 
    113 
    114 class PubSubBasedClient(CloudConsoleClient):
    115     """A Cloud PubSub based implementation of the CloudConsoleClient interface.
    116     """
    117     def __init__(
    118             self,
    119             credential=moblab_host.MOBLAB_SERVICE_ACCOUNT_LOCATION,
    120             pubsub_topic=_PUBSUB_TOPIC):
    121         """Constructor.
    122 
    123         @param credential: The service account credential filename. Default to
    124             '/home/moblab/.service_account.json'.
    125         @param pubsub_topic: The cloud pubsub topic name to use.
    126         """
    127         super(PubSubBasedClient, self).__init__()
    128         self._pubsub_client = _create_pubsub_client(credential)
    129         self._pubsub_topic = pubsub_topic
    130 
    131 
    132     def _create_notification_message(self, data, msg_attributes):
    133         """Creates a cloud pubsub notification object.
    134 
    135         @param data: The message data as a string.
    136         @param msg_attributes: The message attribute map.
    137 
    138         @returns: A pubsub message object with data and attributes.
    139         """
    140         message = {'data': data}
    141         message['attributes'] = msg_attributes
    142         return message
    143 
    144     def _create_notification_attributes(self):
    145         """Creates a cloud pubsub notification message attribute map.
    146 
    147         Fills in the version, moblab mac address, and moblab id information
    148         as attributes.
    149 
    150         @returns: A pubsub messsage attribute map.
    151         """
    152         msg_attributes = {}
    153         msg_attributes[NOTIFICATION_ATTR_VERSION] = NOTIFICATION_VERSION
    154         msg_attributes[NOTIFICATION_ATTR_MOBLAB_MAC] = (
    155                 utils.get_default_interface_mac_address())
    156         msg_attributes[NOTIFICATION_ATTR_MOBLAB_ID] = utils.get_moblab_id()
    157         return msg_attributes
    158 
    159     def _create_test_result_notification(self, gcs_uri):
    160         """Construct a test result notification.
    161 
    162         @param gcs_uri: The test result Google Cloud Storage URI.
    163 
    164         @returns The notification message.
    165         """
    166         data = base64.b64encode(NEW_TEST_RESULT_MESSAGE)
    167         msg_attributes = self._create_notification_attributes()
    168         msg_attributes[NOTIFICATION_ATTR_GCS_URI] = gcs_uri
    169 
    170         return self._create_notification_message(data, msg_attributes)
    171 
    172 
    173     def send_test_job_offloaded_message(self, gcs_uri):
    174         """Notify the cloud console a test job is offloaded.
    175 
    176         @param gcs_uri: The test result Google Cloud Storage URI.
    177 
    178         @returns True if the notification is successfully sent.
    179             Otherwise, False.
    180         """
    181         logging.info('Notification on gcs_uri %s', gcs_uri)
    182         message = self._create_test_result_notification(gcs_uri)
    183         msg_ids = self._pubsub_client.publish_notifications(
    184                 self._pubsub_topic, [message])
    185         if msg_ids:
    186             return True
    187         logging.warning('Failed to send notification on gcs_uri %s', gcs_uri)
    188         return False
    189 
    190