1#!/usr/bin/env python
2#
3# Copyright 2018 - The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16"""Common code used by acloud create methods/classes."""
17
18import logging
19import os
20
21from acloud import errors
22from acloud.internal import constants
23from acloud.internal.lib import android_build_client
24from acloud.internal.lib import auth
25from acloud.internal.lib import utils
26
27
28logger = logging.getLogger(__name__)
29
30
31def ParseHWPropertyArgs(dict_str, item_separator=",", key_value_separator=":"):
32    """Helper function to initialize a dict object from string.
33
34    e.g.
35    cpu:2,dpi:240,resolution:1280x800
36    -> {"cpu":"2", "dpi":"240", "resolution":"1280x800"}
37
38    Args:
39        dict_str: A String to be converted to dict object.
40        item_separator: String character to separate items.
41        key_value_separator: String character to separate key and value.
42
43    Returns:
44        Dict created from key:val pairs in dict_str.
45
46    Raises:
47        error.MalformedDictStringError: If dict_str is malformed.
48    """
49    hw_dict = {}
50    if not dict_str:
51        return hw_dict
52
53    for item in dict_str.split(item_separator):
54        if key_value_separator not in item:
55            raise errors.MalformedDictStringError(
56                "Expecting ':' in '%s' to make a key-val pair" % item)
57        key, value = item.split(key_value_separator)
58        if not value or not key:
59            raise errors.MalformedDictStringError(
60                "Missing key or value in %s, expecting form of 'a:b'" % item)
61        hw_dict[key.strip()] = value.strip()
62
63    return hw_dict
64
65
66def GetCvdHostPackage():
67    """Get cvd host package path.
68
69    Look for the host package in $ANDROID_HOST_OUT and dist dir then verify
70    existence and get cvd host package path.
71
72    Return:
73        A string, the path to the host package.
74
75    Raises:
76        errors.GetCvdLocalHostPackageError: Can't find cvd host package.
77    """
78    dirs_to_check = list(filter(None, [os.environ.get(constants.ENV_ANDROID_HOST_OUT)]))
79    dist_dir = utils.GetDistDir()
80    if dist_dir:
81        dirs_to_check.append(dist_dir)
82
83    for path in dirs_to_check:
84        cvd_host_package = os.path.join(path, constants.CVD_HOST_PACKAGE)
85        if os.path.exists(cvd_host_package):
86            logger.debug("cvd host package: %s", cvd_host_package)
87            return cvd_host_package
88    raise errors.GetCvdLocalHostPackageError(
89        "Can't find the cvd host package (Try lunching a cuttlefish target"
90        " like aosp_cf_x86_phone-userdebug and running 'm'): \n%s" %
91        '\n'.join(dirs_to_check))
92
93
94def DownloadRemoteArtifact(cfg, build_target, build_id, artifact, extract_path,
95                           decompress=False):
96    """Download remote artifact.
97
98    Args:
99        cfg: An AcloudConfig instance.
100        build_target: String, the build target, e.g. cf_x86_phone-userdebug.
101        build_id: String, Build id, e.g. "2263051", "P2804227"
102        artifact: String, zip image or cvd host package artifact.
103        extract_path: String, a path include extracted files.
104        decompress: Boolean, if true decompress the artifact.
105    """
106    build_client = android_build_client.AndroidBuildClient(
107        auth.CreateCredentials(cfg))
108    temp_file = os.path.join(extract_path, artifact)
109    build_client.DownloadArtifact(
110        build_target,
111        build_id,
112        artifact,
113        temp_file)
114    if decompress:
115        utils.Decompress(temp_file, extract_path)
116        try:
117            os.remove(temp_file)
118            logger.debug("Deleted temporary file %s", temp_file)
119        except OSError as e:
120            logger.error("Failed to delete temporary file: %s", str(e))
121