• 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/types.h>
20 
21 #include <optional>
22 #include <string>
23 #include <unordered_map>
24 #include <unordered_set>
25 #include <vector>
26 
27 #include "common/libs/utils/result.h"
28 #include "host/commands/cvd/selector/selector_common_parser.h"
29 #include "host/commands/cvd/types.h"
30 
31 namespace cuttlefish {
32 namespace selector {
33 
34 /**
35  * This class parses the separated SelectorOptions defined in
36  * cvd_server.proto.
37  *
38  * Note that the parsing is from the perspective of syntax.
39  *
40  * In other words, this does not check the following, for example:
41  *  1. If the numeric instance id is duplicated
42  *  2. If the group name is already taken
43  *
44  * How it works is, it parses the selector options that are common
45  * across operations with SelectorCommonParser first. Following that,
46  * StartSelectorParser parses start-specific selector options.
47  */
48 class StartSelectorParser {
49  public:
50   static Result<StartSelectorParser> ConductSelectFlagsParser(
51       const uid_t uid, const cvd_common::Args& selector_args,
52       const cvd_common::Args& cmd_args, const cvd_common::Envs& envs);
53   std::optional<std::string> GroupName() const;
54   std::optional<std::vector<std::string>> PerInstanceNames() const;
InstanceIds()55   const std::optional<std::vector<unsigned>>& InstanceIds() const {
56     return instance_ids_;
57   }
RequestedNumInstances()58   unsigned RequestedNumInstances() const { return requested_num_instances_; }
IsMaybeDefaultGroup()59   bool IsMaybeDefaultGroup() const { return may_be_default_group_; }
MustAcquireFileLock()60   bool MustAcquireFileLock() const { return must_acquire_file_lock_; }
61 
62  private:
63   StartSelectorParser(const std::string& system_wide_user_home,
64                       const cvd_common::Args& selector_args,
65                       const cvd_common::Args& cmd_args,
66                       const cvd_common::Envs& envs,
67                       SelectorCommonParser&& common_parser);
68 
69   Result<void> ParseOptions();
70 
71   struct InstanceIdsParams {
72     std::optional<std::string> num_instances;
73     std::optional<std::string> instance_nums;
74     std::optional<std::string> base_instance_num;
75     std::optional<unsigned> cuttlefish_instance_env;
76     std::optional<unsigned> vsoc_suffix;
77   };
78 
79   class ParsedInstanceIdsOpt {
80     friend class StartSelectorParser;
81 
82    private:
ParsedInstanceIdsOpt(const std::vector<unsigned> & instance_ids)83     ParsedInstanceIdsOpt(const std::vector<unsigned>& instance_ids)
84         : instance_ids_{instance_ids},
85           n_instances_{static_cast<unsigned>(instance_ids.size())} {}
ParsedInstanceIdsOpt(const unsigned n_instances)86     ParsedInstanceIdsOpt(const unsigned n_instances)
87         : instance_ids_{std::nullopt}, n_instances_{n_instances} {}
GetInstanceIds()88     auto GetInstanceIds() { return std::move(instance_ids_); }
GetNumOfInstances()89     unsigned GetNumOfInstances() const { return n_instances_; }
90     std::optional<std::vector<unsigned>> instance_ids_;
91     const unsigned n_instances_;
92   };
93 
94   /*
95    * CF_ERR is meant to be an error:
96    *  For example, --num_instances != |--instance_nums|.
97    *
98    * On the contrary, std::nullopt inside Result is not necessary one.
99    * std::nullopt inside Result means that with the given information,
100    * the instance_ids_ cannot be yet figured out, so the task is deferred
101    * to CreationAnaylizer or so, which has more contexts. For example,
102    * if no option at all is given, it is not an error; however, the
103    * StartSelectorParser alone cannot figure out the list of instance ids. The
104    * InstanceDatabase, UniqueResourceAllocator, InstanceLockFileManager will be
105    * involved to automatically generate the valid, numeric instance ids.
106    * If that's the case, Result{std::nullopt} could be returned.
107    *
108    */
109   Result<ParsedInstanceIdsOpt> HandleInstanceIds(
110       const InstanceIdsParams& instance_id_params);
111 
112   struct InstanceFromEnvParam {
113     std::optional<unsigned> cuttlefish_instance_env;
114     std::optional<unsigned> vsoc_suffix;
115     std::optional<unsigned> num_instances;
116   };
117   std::optional<std::vector<unsigned>> InstanceFromEnvironment(
118       const InstanceFromEnvParam& params);
119 
120   struct VerifyNumOfInstancesParam {
121     std::optional<std::string> num_instances_flag;
122     std::optional<std::vector<std::string>> instance_names;
123     std::optional<std::string> instance_nums_flag;
124   };
125 
126   Result<unsigned> VerifyNumOfInstances(
127       const VerifyNumOfInstancesParam& params,
128       const unsigned default_n_instances = 1) const;
129   Result<bool> CalcMayBeDefaultGroup();
130   Result<bool> CalcAcquireFileLock();
131 
132   struct WebrtcCalculatedNames {
133     std::optional<std::string> group_name;
134     std::optional<std::vector<std::string>> per_instance_names;
135   };
136   Result<WebrtcCalculatedNames> CalcNamesUsingWebrtcDeviceId();
137 
138   /**
139    * The following are considered, and left empty if can't be figured out.
140    *
141    * --base_instance_num, --instance_nums, --num_instances,
142    * instance_names_.size(), CUTTLEFISH_INSTANCE, and vsoc-suffix if
143    * it is the user name.
144    *
145    * instance_names_.size() is effectively another --num_instances.
146    * CUTTLEFISH_INSTANCE and the suffix in order are considered as
147    * --base_instance_num if --base_instance_num is not given and
148    * --instance_nums is not given.
149    *
150    */
151   std::optional<std::vector<unsigned>> instance_ids_;
152   unsigned requested_num_instances_;
153   bool may_be_default_group_;
154   bool must_acquire_file_lock_;
155   std::optional<std::string> group_name_;
156   std::optional<std::vector<std::string>> per_instance_names_;
157 
158   // temporarily keeps the leftover of the input cmd_args
159   const std::string client_user_home_;
160   cvd_common::Args selector_args_;
161   cvd_common::Args cmd_args_;
162   cvd_common::Envs envs_;
163   SelectorCommonParser common_parser_;
164 };
165 
166 }  // namespace selector
167 }  // namespace cuttlefish
168