acloud: Add in AVDSpec class and basic arg parsing.
Add in a very barebones implementation of AVDSpec. The real meat of the
class will come later once we add in the new options (e.g. --local_instance)
and we do the magic for our users.
I intentionally did not do any of the remote image arg inferring logic
as that will require a new arg and some google api calls (to Android
Build) so that deserves its own cl.
Bug: 112598956
Test: m acloud && acloud create
m acloud_test && acloud_test
$ acloud create --build_id 1234 --branch rand_branch
We will (but not yet) create an AVD with these details:
- avd type: cuttlefish
- num of instances requested: 1
- remote image details: {'build_id': '1234', 'build_branch':
'git_rand_branch'}.
Change-Id: Ia27bf86e55f3a171ba39663bb2c1db407119a54f
diff --git a/create/avd_spec.py b/create/avd_spec.py
new file mode 100644
index 0000000..c9566ac
--- /dev/null
+++ b/create/avd_spec.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+#
+# Copyright 2018 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+r"""AVDSpec class.
+
+AVDSpec will take in args from the user and be the main data type that will
+get passed into the create classes. The inferring magic will happen within
+initialization of AVDSpec (like LKGB build id, image branch, etc).
+"""
+
+_BUILD_TARGET = "build_target"
+_BUILD_BRANCH = "build_branch"
+_BUILD_ID = "build_id"
+
+
+class AVDSpec(object):
+ """Class to store data on the type of AVD to create."""
+
+ def __init__(self, args):
+ """Process the args into class vars.
+
+ Args:
+ args: Namespace object from argparse.parse_args.
+ """
+ # Let's define the private class vars here and then process the user
+ # args afterwards.
+ self._avd_type = None
+ self._remote_image = None
+ self._num_of_instances = None
+
+ self._ProcessArgs(args)
+
+ def __repr__(self):
+ """Let's make it easy to see what this class is holding."""
+ # TODO: I'm pretty sure there's a better way to do this, but I'm not
+ # quite sure what that would be.
+ representation = []
+ representation.append("")
+ representation.append(" - avd type: %s" % self._avd_type)
+ representation.append(" - num of instances requested: %s" %
+ self._num_of_instances)
+ representation.append(" - remote image details: %s" %
+ self._remote_image)
+ return "\n".join(representation)
+
+ def _ProcessArgs(self, args):
+ """Main entry point to process args for the different type of args.
+
+ Split up the arg processing into related areas (image, instance type,
+ etc) so that we don't have one huge monolilthic method that does
+ everything. It makes it easier to review, write tests, and maintain.
+
+ Args:
+ args: Namespace object from argparse.parse_args.
+ """
+ self._ProcessMiscArgs(args)
+ self._ProcessRemoteBuildArgs(args)
+
+ def _ProcessMiscArgs(self, args):
+ """These args we can take as and don't belong to a group of args.
+
+ Args:
+ args: Namespace object from argparse.parse_args.
+ """
+ self._avd_type = args.avd_type
+ self._num_of_instances = args.num
+
+ def _ProcessRemoteBuildArgs(self, args):
+ """Get the remote build args.
+
+ Some of the acloud magic happens here, we will infer some of these
+ values if the user hasn't specified them.
+
+ Args:
+ args: Namespace object from argparse.parse_args.
+ """
+ # TODO: We need some logic here to determine if we should infer remote
+ # build info or not.
+ self._remote_image = {}
+ if args.build_target:
+ self._remote_image[_BUILD_TARGET] = args.build_target
+ else:
+ # TODO: actually figure out what we want here.
+ pass
+
+ if args.branch:
+ self._remote_image[_BUILD_BRANCH] = args.branch
+ else:
+ # TODO: infer from user workspace
+ pass
+
+ if args.build_id:
+ self._remote_image[_BUILD_ID] = args.build_id
+ else:
+ # TODO: extract this info from Android Build.
+ pass
diff --git a/create/base_avd_create.py b/create/base_avd_create.py
index 54a78dd..937e622 100644
--- a/create/base_avd_create.py
+++ b/create/base_avd_create.py
@@ -25,6 +25,13 @@
"""Base class for all AVD intance creation classes."""
# pylint: disable=no-self-use
- def Create(self):
- """Create the AVD."""
- print("Feature coming soon.")
+ def Create(self, avd_spec):
+ """Create the AVD.
+
+ Args:
+ avd_spec: AVDSpec object that tells us what we're going to create.
+ """
+ # TODO: rewrite this function to raise NotImplemented once actual device
+ # classes are here.
+ print("We will (but not yet) create an AVD with these details: %s." %
+ avd_spec)
diff --git a/create/create.py b/create/create.py
index 0d6e6d7..88c0ac7 100644
--- a/create/create.py
+++ b/create/create.py
@@ -20,14 +20,16 @@
image artifacts.
"""
+from acloud.create import avd_spec
from acloud.create import base_avd_create
-def Run():
+def Run(args):
"""Run create.
Args:
args: Namespace object from argparse.parse_args.
"""
+ spec = avd_spec.AVDSpec(args)
avd_creator = base_avd_create.BaseAVDCreate()
- avd_creator.Create()
+ avd_creator.Create(spec)
diff --git a/public/acloud_main.py b/public/acloud_main.py
index 88727e3..196d404 100644
--- a/public/acloud_main.py
+++ b/public/acloud_main.py
@@ -393,7 +393,7 @@
logcat_file=args.logcat_file,
autoconnect=args.autoconnect)
elif args.which == create_args.CMD_CREATE:
- create.Run()
+ create.Run(args)
elif args.which == CMD_CREATE_CUTTLEFISH:
report = create_cuttlefish_action.CreateDevices(
cfg=cfg,