blob: 2209383ce8bcccecb212a8d1e42d29d57fb04419 [file] [log] [blame]
Dan Shi54682e72014-10-08 19:10:56 +00001#!/usr/bin/env python
2
3# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""
8This script provides functions to:
91. collect: Collect all hosts and their labels to metaDB, can be scheduled
10 run daily, e.g.,
Dan Shi17ecbbf2014-10-06 13:56:34 -070011 ./site_utils/host_label_utils.py collect
Dan Shi54682e72014-10-08 19:10:56 +0000122. query: Query for hosts and their labels information at a given day, e.g.,
Dan Shi17ecbbf2014-10-06 13:56:34 -070013 ./site_utils/host_label_utils.py query -n 172.27.213.193 -l peppy
Dan Shi54682e72014-10-08 19:10:56 +000014"""
15
16import argparse
17import logging
18import pprint
19import time
20
21import common
22from autotest_lib.client.common_lib import time_utils
23from autotest_lib.client.common_lib.cros.graphite import es_utils
24from autotest_lib.frontend import setup_django_environment
25from autotest_lib.frontend.afe import models
26
27
28# _type used for ES
29_HOST_LABEL_TYPE = 'host_labels'
30_HOST_LABEL_TIME_INDEX_TYPE = 'host_labels_time_index'
31
32
33def get_host_labels(days_back=0, hostname=None, labels=None):
34 """Get the labels for a given host or all hosts.
35
36 @param days_back: Get the label info around that number of days back. The
37 default is 0, i.e., the latest label information.
38 @param hostname: Name of the host, if set to None, return labels for all
39 hosts. Default is None.
40 @param labels: A list of labels to filter hosts.
41 @return: A dictionary of host labels, key is the hostname, and value is a
42 list of labels, e.g.,
43 {'host1': ['board:daisy', 'pool:bvt']}
44 """
45 # Search for the latest logged labels before the given days_back.
46 # Default is 0, which means the last time host labels were logged.
47 t_end = time.time() - days_back*24*3600
48 query_time_index = es_utils.create_range_eq_query_multiple(
49 fields_returned=['time_index'],
50 equality_constraints=[('_type', _HOST_LABEL_TIME_INDEX_TYPE),],
51 range_constraints=[('time_index', None, t_end)],
52 size=1,
53 sort_specs=[{'time_index': 'desc'}])
54 results = es_utils.execute_query(query_time_index)
55 count = int(results['hits']['total'])
56 t_end_str = time_utils.epoch_time_to_date_string(t_end)
57 if count == 0:
58 logging.error('No label information was logged before %s.', t_end_str)
59 return
60 time_index = results['hits']['hits'][0]['fields']['time_index'][0]
61 logging.info('Host labels were recorded at %s',
62 time_utils.epoch_time_to_date_string(time_index))
63
64 # Search for labels for a given host or all hosts, at time_index.
65 equality_constraints=[('_type', _HOST_LABEL_TYPE),
66 ('time_index', time_index),]
67 if hostname:
68 equality_constraints.append(('hostname', hostname))
69 if labels:
70 for label in labels:
71 equality_constraints.append(('labels', label))
72 query_labels = es_utils.create_range_eq_query_multiple(
73 fields_returned=['hostname', 'labels'],
74 equality_constraints=equality_constraints)
75 results = es_utils.execute_query(query_labels)
76
77 host_labels = {}
78 for hit in results['hits']['hits']:
79 hit = es_utils.convert_hit(hit['fields'])
80 host_labels[hit['hostname']] = hit['labels']
81
82 return host_labels
83
84
85def collect_info():
86 """Collect label info and report to metaDB.
87 """
88 # time_index is to index all host labels collected together. It's
89 # converted to int to make search faster.
90 time_index = int(time.time())
91 hosts = models.Host.objects.filter(invalid=False)
92 for host in hosts:
93 info = {'hostname': host.hostname,
94 'labels': [label.name for label in host.labels.all()],
95 'time_index': time_index}
96 es_utils.ESMetadata().post(type_str=_HOST_LABEL_TYPE, metadata=info,
97 log_time_recorded=False)
98
99 # After all host label information is logged, save the time stamp.
100 es_utils.ESMetadata().post(type_str=_HOST_LABEL_TIME_INDEX_TYPE,
101 metadata={'time_index': time_index},
102 log_time_recorded=False)
103 logging.info('Finished collecting host labels for %d hosts.', len(hosts))
104
105
106def main():
107 """Main script.
108 """
109 parser = argparse.ArgumentParser()
110 parser.add_argument('action',
111 help=('collect or query. Action collect will collect '
112 'all hosts and their labels to metaDB. Action '
113 'query will query for hosts and their labels '
114 'information at a given day'))
115 parser.add_argument('-d', '--days_back', type=int, dest='days_back',
116 help=('Number of days before current time. Query will '
117 'get host label information collected before that'
118 ' time. The option is applicable to query only. '
119 'Default to 0, i.e., get the latest label info.'),
120 default=0)
121 parser.add_argument('-n', '--hostname', type=str, dest='hostname',
122 help=('Name of the host to query label information for.'
123 'The option is applicable to query only. '
124 'Default to None, i.e., return label info for all'
125 ' hosts.'),
126 default=None)
127 parser.add_argument('-l', '--labels', nargs='+', dest='labels',
128 help=('A list of labels to filter hosts. The option is '
129 'applicable to query only. Default to None.'),
130 default=None)
131 parser.add_argument('-v', '--verbose', action="store_true", dest='verbose',
132 help='Allow more detail information to be shown.')
133 options = parser.parse_args()
134
135 logging.getLogger().setLevel(logging.INFO if options.verbose
136 else logging.WARN)
137 if options.action == 'collect':
138 collect_info()
139 elif options.action == 'query':
140 host_labels = get_host_labels(options.days_back, options.hostname,
141 options.labels)
142 pprint.pprint(host_labels)
143 else:
144 logging.error('action %s is not supported, can only be collect or '
145 'query!', options.action)
146
147
148if __name__ == '__main__':
149 main()