1# 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 5import logging 6import subprocess 7 8from autotest_lib.client.common_lib import error 9from autotest_lib.client.common_lib import utils 10from autotest_lib.server import test 11from autotest_lib.server import frontend 12 13class hardware_StorageQualCheckSetup(test.test): 14 """ 15 Verifies the moblab and DUT setup for storage qual 16 A correct setup consists of 17 At least one pool (the default "no pool" counts as a pool) 18 Each of the labels [retention, trim, suspend] is applied to exactly 19 one DUT in the pool. 20 No duplication of the labels, all labels are applied exactly once 21 per pool 22 23 The test will verify this set up. If any pool isn't configured correctly, 24 the test will fail. To pass the test, every DUT must be a part of a 25 correctly configured pool. This gives us confidence that the partners 26 will have a correct setup for storage qual no matter which pool they select 27 on RunSuite page. 28 """ 29 30 version = 1 31 32 REQUIRED_LABELS = ['retention', 'trim', 'suspend'] 33 34 def _group_hosts_into_pools(self, hosts): 35 pools = {} 36 for host in hosts: 37 labels = [label.name for label in host.get_labels()] 38 39 pool_name = 'none' 40 for label in labels: 41 if 'pool:' in label: 42 pool_name = label.replace('pool:', '') 43 44 if pool_name not in pools: 45 pools[pool_name] = [] 46 47 pools[pool_name].append({ 48 'host': host.hostname, 49 'labels': labels 50 }) 51 52 return pools 53 54 55 def run_once(self): 56 """ Tests the moblab's connected DUTs to see if the current 57 configuration is valid for storage qual 58 """ 59 60 afe = frontend.AFE(server='localhost', user='moblab') 61 62 # get autotest statuses that indicate a live host 63 live_statuses = afe.host_statuses(live=True) 64 65 # get the hosts connected to autotest, find the live ones 66 hosts = [] 67 for host in afe.get_hosts(): 68 if host.status in live_statuses: 69 logging.info('Host %s is live, status %s' % 70 (host.hostname, host.status)) 71 hosts.append(host) 72 else: 73 logging.info('Host %s is not live, status %s' % 74 (host.hostname, host.status)) 75 76 pools = self._group_hosts_into_pools(hosts) 77 78 # verify that each pool is set up to run storage qual 79 # err on the side of caution by requiring all pools to have the correct 80 # setup, so it is clear to partners that they could run storage qual 81 # with any configuration on RunSuite page 82 required_set = set(self.REQUIRED_LABELS) 83 for pool_name, pool_hosts in pools.iteritems(): 84 provided_set = set() 85 logging.info('Pool %s' % pool_name) 86 for host in pool_hosts: 87 host_provided_labels = set(host['labels']) & required_set 88 # check that each DUT has at most 1 storage qual label 89 if len(host_provided_labels) > 1: 90 raise error.TestFail( 91 ('Host %s is assigned more than ' 92 'one storage qual label %s') % 93 (host['host'], str(host_provided_labels))) 94 if len(host_provided_labels) == 0: 95 continue 96 97 # check that each label is only on one DUT in the pool 98 provided_label = host_provided_labels.pop() 99 if provided_label in provided_set: 100 raise error.TestFail( 101 ('Host %s is assigned label %s, which is already ' 102 'assigned to another DUT in pool %s') % 103 (host['host'], provided_label, pool_name) 104 ) 105 106 provided_set.add(provided_label) 107 logging.info(' - %s %s' % (host['host'], provided_label)) 108 109 # check that all storage qual labels are accounted for in the pool 110 missing_labels = required_set - provided_set 111 if len(missing_labels) > 0: 112 raise error.TestFail( 113 'Pool %s is missing required labels %s' % 114 (pool_name, str(missing_labels)) 115 ) 116 117 return 118