• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 #pragma once
18 
19 #include <sys/socket.h>  // for ucred
20 
21 #include <memory>
22 #include <optional>
23 #include <string>
24 #include <unordered_map>
25 #include <vector>
26 
27 #include "common/libs/utils/result.h"
28 #include "common/libs/utils/unique_resource_allocator.h"
29 #include "host/commands/cvd/instance_lock.h"
30 #include "host/commands/cvd/selector/instance_database.h"
31 #include "host/commands/cvd/selector/start_selector_parser.h"
32 
33 namespace cuttlefish {
34 namespace selector {
35 
36 struct PerInstanceInfo {
37   // for the sake of std::vector::emplace_back
PerInstanceInfoPerInstanceInfo38   PerInstanceInfo(const unsigned id, const std::string& per_instance_name,
39                   InstanceLockFile&& instance_file_lock)
40       : instance_id_(id),
41         per_instance_name_(per_instance_name),
42         instance_file_lock_(std::move(instance_file_lock)) {}
43 
PerInstanceInfoPerInstanceInfo44   PerInstanceInfo(const unsigned id, const std::string& per_instance_name)
45       : instance_id_(id), per_instance_name_(per_instance_name) {}
46 
47   const unsigned instance_id_;
48   const std::string per_instance_name_;
49   std::optional<InstanceLockFile> instance_file_lock_;
50 };
51 
52 /**
53  * Creation is currently group by group
54  *
55  * If you want one instance, you should create a group with one instance.
56  */
57 struct GroupCreationInfo {
58   std::string home;
59   std::string host_artifacts_path;  ///< e.g. out/host/linux-x86
60   // set to host_artifacts_path if no ANDROID_PRODUCT_OUT
61   std::string product_out_path;
62   std::string group_name;
63   std::vector<PerInstanceInfo> instances;
64   std::vector<std::string> args;
65   std::unordered_map<std::string, std::string> envs;
66 };
67 
68 /**
69  * Instance IDs:
70  *  Use the InstanceNumCalculator's logic
71  *
72  * HOME directory:
73  *  If given in envs and is different from the system-wide home, use it
74  *  If not, try ParentOfAutogeneratedHomes()/uid/${group_name}
75  *
76  * host_artifacts_path:
77  *  ANDROID_HOST_OUT must be given.
78  *
79  * Group name:
80  *  if a group name is not given, automatically generate:
81  *   default_prefix + "_" + one_of_ids
82  *
83  * Per-instance name:
84  *  When not given, use std::string(id) as the per instance name of each
85  *
86  * Number of instances:
87  *  Controlled by --instance_nums, --num_instances, etc.
88  *  Also controlled by --instance_name
89  *
90  * p.s.
91  *  dependency: (a-->b means b depends on a)
92  *    group_name --> HOME
93  *    instance ids --> per_instance_name
94  *
95  */
96 class CreationAnalyzer {
97  public:
98   struct CreationAnalyzerParam {
99     const std::vector<std::string>& cmd_args;
100     const std::unordered_map<std::string, std::string>& envs;
101     const std::vector<std::string>& selector_args;
102   };
103 
104   static Result<GroupCreationInfo> Analyze(
105       const std::string& cmd, const CreationAnalyzerParam& param,
106       const ucred& credential, const InstanceDatabase& instance_database,
107       InstanceLockFileManager& instance_lock_file_manager);
108 
109  private:
110   using IdAllocator = UniqueResourceAllocator<unsigned>;
111 
112   CreationAnalyzer(const CreationAnalyzerParam& param, const ucred& credential,
113                    StartSelectorParser&& selector_options_parser,
114                    const InstanceDatabase& instance_database,
115                    InstanceLockFileManager& instance_lock_file_manager);
116 
117   Result<GroupCreationInfo> Analyze();
118 
119   /**
120    * calculate n_instances_ and instance_ids_
121    */
122   Result<std::vector<PerInstanceInfo>> AnalyzeInstanceIds();
123 
124   /*
125    * When group name is nil, it is auto-generated using instance ids
126    *
127    * If the instanc group is the default one, the group name is cvd. Otherwise,
128    * for given instance ids, {i}, the group name will be cvd_i.
129    */
130   Result<std::string> AnalyzeGroupName(
131       const std::vector<PerInstanceInfo>&) const;
132 
133   /**
134    * Figures out the HOME directory
135    *
136    * The issue is that many times, HOME is anyway implicitly given. Thus, only
137    * if the HOME value is not equal to the HOME directory recognized by the
138    * system, it can be safely regarded as overridden by the user.
139    *
140    * If that is not the case, we use a automatically generated value as HOME.
141    * If the group instance is the default one, we still use the user's system-
142    * widely recognized home. If not, we populate them user /tmp/.cf/<uid>/
143    *
144    */
145   Result<std::string> AnalyzeHome() const;
146 
147   Result<std::vector<PerInstanceInfo>> AnalyzeInstanceIdsInternal();
148   Result<std::vector<PerInstanceInfo>> AnalyzeInstanceIdsInternal(
149       const std::vector<unsigned>& requested_instance_ids);
150 
151   /*
152    * Adds --webrtc_device_id when necessary to cmd_args_
153    */
154   Result<std::vector<std::string>> UpdateWebrtcDeviceId(
155       std::vector<std::string>&& args,
156       const std::vector<PerInstanceInfo>& per_instance_info);
157 
158   // inputs
159   std::vector<std::string> cmd_args_;
160   std::unordered_map<std::string, std::string> envs_;
161   std::vector<std::string> selector_args_;
162   const ucred credential_;
163 
164   // information to return later
165   std::string home_;
166   std::string group_name_;
167 
168   // internal, temporary
169   StartSelectorParser selector_options_parser_;
170   const InstanceDatabase& instance_database_;
171   InstanceLockFileManager& instance_file_lock_manager_;
172 };
173 
174 }  // namespace selector
175 }  // namespace cuttlefish
176