Home | History | Annotate | Download | only in build
      1 #
      2 # Copyright (C) 2017 The Android Open Source Project
      3 #
      4 # Licensed under the Apache License, Version 2.0 (the "License");
      5 # you may not use this file except in compliance with the License.
      6 # You may obtain a copy of the License at
      7 #
      8 #      http://www.apache.org/licenses/LICENSE-2.0
      9 #
     10 # Unless required by applicable law or agreed to in writing, software
     11 # distributed under the License is distributed on an "AS IS" BASIS,
     12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 # See the License for the specific language governing permissions and
     14 # limitations under the License.
     15 #
     16 
     17 import logging
     18 import os
     19 import re
     20 import zipfile
     21 
     22 from host_controller.build import build_provider
     23 from vts.utils.python.common import cmd_utils
     24 
     25 _GCLOUD_AUTH_ENV_KEY = "run_gcs_key"
     26 
     27 
     28 class BuildProviderGCS(build_provider.BuildProvider):
     29     """A build provider for GCS (Google Cloud Storage)."""
     30 
     31     def __init__(self):
     32         super(BuildProviderGCS, self).__init__()
     33         if _GCLOUD_AUTH_ENV_KEY in os.environ:
     34             gcloud_path = BuildProviderGCS.GetGcloudPath()
     35             if gcloud_path is not None:
     36                 auth_cmd = "%s auth activate-service-account --key-file=%s" % (
     37                     gcloud_path, os.environ[_GCLOUD_AUTH_ENV_KEY])
     38                 _, stderr, ret_code = cmd_utils.ExecuteOneShellCommand(
     39                     auth_cmd)
     40                 if ret_code == 0:
     41                     logging.info(stderr)
     42                 else:
     43                     print(stderr)
     44                     logging.error(stderr)
     45 
     46     @staticmethod
     47     def GetGcloudPath():
     48         """Returns the gcloud file path if found; None otherwise."""
     49         sh_stdout, _, ret_code = cmd_utils.ExecuteOneShellCommand(
     50             "which gcloud")
     51         if ret_code == 0:
     52             return sh_stdout.strip()
     53         else:
     54             logging.error("`gcloud` doesn't exist on the host; "
     55                           "please install Google Cloud SDK before retrying.")
     56             return None
     57 
     58     @staticmethod
     59     def GetGsutilPath():
     60         """Returns the gsutil file path if found; None otherwise."""
     61         sh_stdout, sh_stderr, ret_code = cmd_utils.ExecuteOneShellCommand(
     62             "which gsutil")
     63         if ret_code == 0:
     64             return sh_stdout.strip()
     65         else:
     66             logging.fatal("`gsutil` doesn't exist on the host; "
     67                           "please install Google Cloud SDK before retrying.")
     68             return None
     69 
     70     @staticmethod
     71     def IsGcsFile(gsutil_path, gs_path):
     72         """Checks whether a given path is for a GCS file.
     73 
     74         Args:
     75             gsutil_path: string, the path of a gsutil binary.
     76             gs_path: string, the GCS file path (e.g., gs://<bucket>/<file>.
     77 
     78         Returns:
     79             True if gs_path is a file, False otherwise.
     80         """
     81         check_command = "%s stat %s" % (gsutil_path, gs_path)
     82         _, _, ret_code = cmd_utils.ExecuteOneShellCommand(check_command)
     83         return ret_code == 0
     84 
     85     def Fetch(self, path):
     86         """Fetches Android device artifact file(s) from GCS.
     87 
     88         Args:
     89             path: string, the path of a directory which keeps artifacts.
     90 
     91         Returns:
     92             a dict containing the device image info.
     93             a dict containing the test suite package info.
     94             a dict containing the info about custom tool files.
     95         """
     96         if not path.startswith("gs://"):
     97             path = "gs://" + re.sub("^/*", "", path)
     98         path = re.sub("/*$", "", path)
     99         # make sure gsutil is available. Instead of a Python library,
    100         # gsutil binary is used that is to avoid packaging GCS PIP package
    101         # as part of VTS HC (Host Controller).
    102         gsutil_path = BuildProviderGCS.GetGsutilPath()
    103         if gsutil_path:
    104             temp_dir_path = self.CreateNewTmpDir()
    105             # IsGcsFile returns False if path is directory or doesn't exist.
    106             # cp command returns non-zero if path doesn't exist.
    107             if not BuildProviderGCS.IsGcsFile(gsutil_path, path):
    108                 dest_path = temp_dir_path
    109                 copy_command = "%s cp -r %s/* %s" % (gsutil_path, path,
    110                                                      temp_dir_path)
    111             else:
    112                 dest_path = os.path.join(temp_dir_path, os.path.basename(path))
    113                 copy_command = "%s cp %s %s" % (gsutil_path, path,
    114                                                 temp_dir_path)
    115 
    116             _, _, ret_code = cmd_utils.ExecuteOneShellCommand(copy_command)
    117             if ret_code == 0:
    118                 self.SetFetchedFile(dest_path, temp_dir_path)
    119             else:
    120                 logging.error("Error in copy file from GCS (code %s)." %
    121                               ret_code)
    122         return (self.GetDeviceImage(),
    123                 self.GetTestSuitePackage(),
    124                 self.GetAdditionalFile())
    125