• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 package com.android.tradefed.host;
18 
19 import com.android.tradefed.config.ConfigurationException;
20 import com.android.tradefed.config.Option;
21 import com.android.tradefed.config.OptionClass;
22 import com.android.tradefed.error.HarnessRuntimeException;
23 import com.android.tradefed.log.LogUtil.CLog;
24 import com.android.tradefed.result.error.InfraErrorIdentifier;
25 import com.android.tradefed.util.RunInterruptedException;
26 
27 import java.io.File;
28 import java.net.InetAddress;
29 import java.net.NetworkInterface;
30 import java.net.SocketException;
31 import java.util.ArrayList;
32 import java.util.Enumeration;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import java.util.Set;
39 import java.util.concurrent.Semaphore;
40 
41 /**
42  * Host options holder class.
43  * This class is used to store host-wide options.
44  */
45 @OptionClass(alias = "host_options", global_namespace = false)
46 public class HostOptions implements IHostOptions {
47 
48     @Option(name = "concurrent-flasher-limit", description =
49             "The maximum number of concurrent flashers (may be useful to avoid memory constraints)")
50     private Integer mConcurrentFlasherLimit = 1;
51 
52     @Option(
53         name = "concurrent-download-limit",
54         description =
55                 "The maximum number of concurrent downloads (may be useful to avoid network "
56                         + "constraints)"
57     )
58     private Integer mConcurrentDownloadLimit = null;
59 
60     @Option(
61             name = "concurrent-virtual-device-startup-limit",
62             description =
63                     "The maximum number of concurrent virtual device startup to avoid resource"
64                             + " contentions depending on factors such as network, CPU, I/O etc.")
65     private Integer mConcurrentVirtualDeviceStartupLimit = null;
66 
67     @Option(name = "concurrent-limits", description =
68             "The maximum number of concurrent actions of a given type.")
69     private Map<PermitLimitType, Integer> mConcurrentLimit = new HashMap<>();
70 
71     @Option(
72         name = "fastboot-tmpdir",
73         description = "The location of temporary directory used by fastboot"
74     )
75     private File mFastbootTmpDir = null;
76 
77     @Option(
78             name = "enable-fastbootd-mode",
79             description = "Feature flag to enable the support for fastbootd.")
80     private boolean mEnableFastbootdMode = true;
81 
82     @Option(name = "download-cache-dir", description = "the directory for caching downloaded "
83             + "flashing files. Should be on the same filesystem as java.io.tmpdir.  Consider "
84             + "changing the java.io.tmpdir property if you want to move downloads to a different "
85             + "filesystem.")
86     private File mDownloadCacheDir = new File(System.getProperty("java.io.tmpdir"), "lc_cache");
87 
88     @Option(name = "use-sso-client", description = "Use a SingleSignOn client for HTTP requests.")
89     private Boolean mUseSsoClient = true;
90 
91     @Option(
92         name = "service-account-json-key-file",
93         description =
94                 "Specify a service account json key file, and a String key name to identify it."
95     )
96     private Map<String, File> mJsonServiceAccountMap = new HashMap<>();
97 
98     @Option(name = "label", description = "Labels to describe the host.")
99     private List<String> mLabels = new ArrayList<>();
100 
101     @Option(
102             name = "known-gce-device-ip-pool",
103             description =
104                     "known remote device available via ip associated with the "
105                             + "gce-device placeholder.")
106     private Set<String> mKnownGceDeviceIpPool = new HashSet<>();
107 
108     @Option(
109             name = "known-remote-device-ip-pool",
110             description =
111                     "known remote device available via ip associated with the "
112                             + "remote-device placeholder.")
113     private Set<String> mKnownRemoteDeviceIpPool = new HashSet<>();
114 
115     @Option(
116             name = "use-zip64-in-partial-download",
117             description = "Whether to use zip64 format in partial download.")
118     private boolean mUseZip64InPartialDownload = true;
119 
120     @Option(
121             name = "use-network-interface",
122             description = "The network interface used to connect to test devices.")
123     private String mNetworkInterface = null;
124 
125     @Option(
126             name = "preconfigured-virtual-device-pool",
127             description = "Preconfigured virtual device pool. (Value format: $hostname:$user.)")
128     private List<String> mPreconfiguredVirtualDevicePool = new ArrayList<>();
129 
130     @Option(
131             name = "preconfigured-native-device-pool",
132             description = "Preconfigured Native virtual device pool. (Value format: $hostname.)")
133     private List<String> mPreconfiguredNativeDevicePool = new ArrayList<>();
134 
135     @Option(
136             name = "flash-with-fuse-zip",
137             description = "Use `fastboot flashall` on a folder of fuse mounted device image zip "
138                     + "instead of `fastboot update` with zip")
139     private boolean mFlashWithFuseZip = false;
140 
141     @Option(
142             name = "cache-size-limit",
143             description =
144                     "The maximum allowed size(bytes) of the local file cache. (default: 15GB)")
145     private Long mCacheSizeLimit = 15L * 1024L * 1024L * 1024L;
146 
147     @Option(
148             name = "test-phase-timeout",
149             description =
150                     "the maximum time to wait for test phase to finish before attempting to force"
151                             + "stop it. A value of zero will indicate no timeout.",
152             isTimeVal = true)
153     private long mTestPhaseTimeout = 0;
154 
155     @Option(
156             name = "enable-incremental-flashing",
157             description = "Feature flag to enable incremental flashing on one host.")
158     private boolean mEnableIncrementalFlashing = false;
159 
160     @Option(
161             name = "opt-out-incremental-flashing",
162             description = "Allows an host to fully opt-out of incremental flashing.")
163     private boolean mOptOutFromIncrementalFlashing = false;
164 
165     @Option(
166             name = "disable-host-metric-reporting",
167             description = "Feature flag to disable the support for host metric reporting.")
168     private boolean mDisableHostMetricReporting = false;
169 
170     private Map<PermitLimitType, Semaphore> mConcurrentLocks = new HashMap<>();
171     private Map<PermitLimitType, Integer> mInternalConcurrentLimits = new HashMap<>();
172 
173     /** {@inheritDoc} */
174     @Override
getCacheSizeLimit()175     public Long getCacheSizeLimit() {
176         return mCacheSizeLimit;
177     }
178 
179     /** {@inheritDoc} */
180     @Override
getConcurrentFlasherLimit()181     public Integer getConcurrentFlasherLimit() {
182         return mConcurrentFlasherLimit;
183     }
184 
185     /** {@inheritDoc} */
186     @Override
getConcurrentDownloadLimit()187     public Integer getConcurrentDownloadLimit() {
188         return mConcurrentDownloadLimit;
189     }
190 
191     @Override
getConcurrentVirtualDeviceStartupLimit()192     public Integer getConcurrentVirtualDeviceStartupLimit() {
193         return mConcurrentVirtualDeviceStartupLimit;
194     }
195 
196     /** {@inheritDoc} */
197     @Override
getFastbootTmpDir()198     public File getFastbootTmpDir() {
199         if (mFastbootTmpDir != null) {
200             if (!mFastbootTmpDir.exists() || !mFastbootTmpDir.isDirectory()) {
201                 throw new HarnessRuntimeException(
202                         String.format(
203                                 "Fastboot tmp dir '%s' is missing and was expected.",
204                                 mFastbootTmpDir),
205                         InfraErrorIdentifier.LAB_HOST_FILESYSTEM_ERROR);
206             }
207             return mFastbootTmpDir;
208         }
209         return null;
210     }
211 
212     /** {@inheritDoc} */
213     @Override
isFastbootdEnable()214     public boolean isFastbootdEnable() {
215         return mEnableFastbootdMode;
216     }
217 
218     /** {@inheritDoc} */
219     @Override
getDownloadCacheDir()220     public File getDownloadCacheDir() {
221         return mDownloadCacheDir;
222     }
223 
224     /** {@inheritDoc} */
225     @Override
shouldUseSsoClient()226     public Boolean shouldUseSsoClient() {
227         return mUseSsoClient;
228     }
229 
230     /** {@inheritDoc} */
231     @Override
getServiceAccountJsonKeyFiles()232     public Map<String, File> getServiceAccountJsonKeyFiles() {
233         return new HashMap<>(mJsonServiceAccountMap);
234     }
235 
236     /** {@inheritDoc} */
237     @Override
validateOptions()238     public void validateOptions() throws ConfigurationException {
239         // Validation of host options
240     }
241 
242     /** {@inheritDoc} */
243     @Override
getLabels()244     public List<String> getLabels() {
245         return new ArrayList<>(mLabels);
246     }
247 
248     /** {@inheritDoc} */
249     @Override
getKnownGceDeviceIpPool()250     public Set<String> getKnownGceDeviceIpPool() {
251         return new HashSet<>(mKnownGceDeviceIpPool);
252     }
253 
254     /** {@inheritDoc} */
255     @Override
getKnownRemoteDeviceIpPool()256     public Set<String> getKnownRemoteDeviceIpPool() {
257         return new HashSet<>(mKnownRemoteDeviceIpPool);
258     }
259 
260     /** {@inheritDoc} */
261     @Override
getKnownPreconfigureVirtualDevicePool()262     public List<String> getKnownPreconfigureVirtualDevicePool() {
263         return new ArrayList<>(mPreconfiguredVirtualDevicePool);
264     }
265 
266     /** {@inheritDoc} */
267     @Override
getKnownPreconfigureNativeDevicePool()268     public List<String> getKnownPreconfigureNativeDevicePool() {
269         return new ArrayList<>(mPreconfiguredNativeDevicePool);
270     }
271 
272     /** {@inheritDoc} */
273     @Override
getUseZip64InPartialDownload()274     public boolean getUseZip64InPartialDownload() {
275         return mUseZip64InPartialDownload;
276     }
277 
278     /** {@inheritDoc} */
279     @Override
getNetworkInterface()280     public String getNetworkInterface() {
281         if (mNetworkInterface != null) {
282             return mNetworkInterface;
283         }
284 
285         try {
286             for (Enumeration<NetworkInterface> enNetI = NetworkInterface.getNetworkInterfaces();
287                     enNetI.hasMoreElements(); ) {
288                 NetworkInterface netI = enNetI.nextElement();
289                 if (!netI.isUp()) {
290                     continue;
291                 }
292                 for (Enumeration<InetAddress> enumIpAddr = netI.getInetAddresses();
293                         enumIpAddr.hasMoreElements(); ) {
294                     InetAddress inetAddress = enumIpAddr.nextElement();
295                     if (!inetAddress.isAnyLocalAddress()
296                             && !inetAddress.isLinkLocalAddress()
297                             && !inetAddress.isLoopbackAddress()
298                             && !inetAddress.isMulticastAddress()) {
299                         mNetworkInterface = netI.getName();
300                         return mNetworkInterface;
301                     }
302                 }
303             }
304         } catch (SocketException e) {
305             CLog.w("Failed to get host's active interface");
306             CLog.w(e);
307         }
308         return null;
309     }
310 
311     @Override
getTestPhaseTimeout()312     public long getTestPhaseTimeout() {
313         return mTestPhaseTimeout;
314     }
315 
316     @Override
initConcurrentLocks()317     public void initConcurrentLocks() {
318         // Do not reinit if it has been called before
319         if (!mConcurrentLocks.isEmpty()) {
320             return;
321         }
322         mInternalConcurrentLimits.putAll(mConcurrentLimit);
323         // Backfill flasher & download limit from their dedicated option
324         if (!mInternalConcurrentLimits.containsKey(PermitLimitType.CONCURRENT_FLASHER)) {
325             mInternalConcurrentLimits.put(
326                     PermitLimitType.CONCURRENT_FLASHER, mConcurrentFlasherLimit);
327         }
328         if (!mInternalConcurrentLimits.containsKey(PermitLimitType.CONCURRENT_DOWNLOAD)) {
329             mInternalConcurrentLimits.put(
330                     PermitLimitType.CONCURRENT_DOWNLOAD, mConcurrentDownloadLimit);
331         }
332 
333         if (!mInternalConcurrentLimits.containsKey(
334                 PermitLimitType.CONCURRENT_VIRTUAL_DEVICE_STARTUP)) {
335             mInternalConcurrentLimits.put(
336                     PermitLimitType.CONCURRENT_VIRTUAL_DEVICE_STARTUP,
337                     mConcurrentVirtualDeviceStartupLimit);
338         }
339 
340         for (Entry<PermitLimitType, Integer> limits : mInternalConcurrentLimits.entrySet()) {
341             if (limits.getValue() == null) {
342                 continue;
343             }
344             mConcurrentLocks.put(limits.getKey(),
345                     new Semaphore(limits.getValue(), true /* fair */));
346         }
347     }
348 
349     @Override
takePermit(PermitLimitType type)350     public void takePermit(PermitLimitType type) {
351         if (!mConcurrentLocks.containsKey(type)) {
352             return;
353         }
354         CLog.i(
355                 "Requesting a '%s' permit out of the max limit of %s. Current queue "
356                         + "length: %s",
357                 type,
358                 mInternalConcurrentLimits.get(type),
359                 mConcurrentLocks.get(type).getQueueLength());
360         try {
361             mConcurrentLocks.get(type).acquire();
362         } catch (InterruptedException e) {
363             throw new RunInterruptedException(e.getMessage(), e, InfraErrorIdentifier.UNDETERMINED);
364         }
365     }
366 
367     @Override
returnPermit(PermitLimitType type)368     public void returnPermit(PermitLimitType type) {
369         if (!mConcurrentLocks.containsKey(type)) {
370             return;
371         }
372         mConcurrentLocks.get(type).release();
373     }
374 
375     @Override
getAvailablePermits(PermitLimitType type)376     public Integer getAvailablePermits(PermitLimitType type) {
377         if (!mConcurrentLocks.containsKey(type)) {
378             return Integer.MAX_VALUE;
379         }
380         return mConcurrentLocks.get(type).availablePermits();
381     }
382 
383     @Override
getInUsePermits(PermitLimitType type)384     public int getInUsePermits(PermitLimitType type) {
385         if (!mConcurrentLocks.containsKey(type)) {
386             return 0;
387         }
388         return mInternalConcurrentLimits.get(type) - mConcurrentLocks.get(type).availablePermits();
389     }
390 
391     @Override
shouldFlashWithFuseZip()392     public boolean shouldFlashWithFuseZip() {
393         return mFlashWithFuseZip;
394     }
395 
396     /** {@inheritDoc} */
397     @Override
isIncrementalFlashingEnabled()398     public boolean isIncrementalFlashingEnabled() {
399         return mEnableIncrementalFlashing;
400     }
401 
402     /** {@inheritDoc} */
403     @Override
isOptOutOfIncrementalFlashing()404     public boolean isOptOutOfIncrementalFlashing() {
405         return mOptOutFromIncrementalFlashing;
406     }
407 
408     /** {@inheritDoc} */
409     @Override
isHostMetricReportingDisabled()410     public boolean isHostMetricReportingDisabled() {
411         return mDisableHostMetricReporting;
412     }
413 }
414