blob: ec33b4a16a320f9c4da8342108d7552b3f041fea [file] [log] [blame]
Alex Miller0516e4c2013-06-03 18:07:48 -07001# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5
6import logging
7
8import common
9from autotest_lib.frontend.afe.json_rpc import proxy
10from autotest_lib.server import frontend
11
12
13### Constants for label prefixes
14CROS_VERSION_PREFIX = 'cros-version'
Fang Dengdbc86322013-08-09 16:17:30 -070015FW_VERSION_PREFIX = 'fw-version'
Alex Miller0516e4c2013-06-03 18:07:48 -070016
17
18### Helpers to convert value to label
19def cros_version_to_label(image):
20 """
21 Returns the proper label name for a ChromeOS build of |image|.
22
23 @param image: A string of the form 'lumpy-release/R28-3993.0.0'
24 @returns: A string that is the appropriate label name.
25
26 """
27 return CROS_VERSION_PREFIX + ':' + image
28
29
30# TODO(milleral): http://crbug.com/249555
31# Create some way to discover and register provisioning tests so that we don't
32# need to hand-maintain a list of all of them.
33_provision_types = {
34 CROS_VERSION_PREFIX:'provision_AutoUpdate',
Fang Dengdbc86322013-08-09 16:17:30 -070035 FW_VERSION_PREFIX:'provision_FirmwareUpdate',
Alex Miller0516e4c2013-06-03 18:07:48 -070036}
37
38
39def can_provision(label):
40 """
41 Returns True if the label is a label that we recognize as something we
42 know how to provision.
43
44 @param label: The label as a string.
45 @returns: True if there exists a test to provision the label.
46
47 """
48 return label.split(':')[0] in _provision_types
49
50
51def provisioner_for(name):
52 """
53 Returns the provisioning class associated with the given (string) name.
54
55 @param name: The name of the provision type being requested.
56 @returns: The subclass of Provisioner that was requested.
57 @raises KeyError: If the name was not recognized as a provision type.
58
59 """
60 return _provision_types[name]
61
62
63def filter_labels(labels):
64 """
65 Filter a list of labels into two sets: those labels that we know how to
66 change and those that we don't. For the ones we know how to change, split
67 them apart into the name of configuration type and its value.
68
69 @param labels: A list of strings of labels.
70 @returns: A tuple where the first element is a set of unprovisionable
71 labels, and the second element is a set of the provisionable
72 labels.
73
74 >>> filter_labels(['bluetooth', 'cros-version:lumpy-release/R28-3993.0.0'])
75 (set(['bluetooth']), set(['cros-version:lumpy-release/R28-3993.0.0']))
76
77 """
78 capabilities = set()
79 configurations = set()
80
81 for label in labels:
82 if can_provision(label):
83 configurations.add(label)
84 else:
85 capabilities.add(label)
86
87 return capabilities, configurations
88
89
90def split_labels(labels):
91 """
92 Split a list of labels into a dict mapping name to value. All labels must
93 be provisionable labels, or else a ValueError
94
95 @param labels: list of strings of label names
96 @returns: A dict of where the key is the configuration name, and the value
97 is the configuration value.
98 @raises: ValueError if a label is not a provisionable label.
99
100 >>> split_labels(['cros-version:lumpy-release/R28-3993.0.0'])
101 {'cros-version': 'lumpy-release/R28-3993.0.0'}
102 >>> split_labels(['bluetooth'])
103 Traceback (most recent call last):
104 ...
105 ValueError: Unprovisionable label bluetooth
106
107 """
108 configurations = dict()
109
110 for label in labels:
111 if can_provision(label):
112 name, value = label.split(':', 1)
113 configurations[name] = value
114 else:
115 raise ValueError('Unprovisionable label %s' % label)
116
117 return configurations
118
119
120# This has been copied out of dynamic_suite's reimager.py, which will be killed
121# off in a future CL. I'd prefer if this would go away by doing
122# http://crbug.com/249424, so that labels are just automatically made when we
123# try to add them to a host.
124def ensure_label_exists(name):
125 """
126 Ensure that a label called |name| exists in the autotest DB.
127
128 @param name: the label to check for/create.
129 @raises ValidationError: There was an error in the response that was
130 not because the label already existed.
131
132 """
133 afe = frontend.AFE()
134 try:
135 afe.create_label(name=name)
136 except proxy.ValidationError as ve:
137 if ('name' in ve.problem_keys and
138 'This value must be unique' in ve.problem_keys['name']):
139 logging.debug('Version label %s already exists', name)
140 else:
141 raise ve