autotest: Make RPC 'get_hosts_by_attribute' respect static attributes. am: 91ecef5829 am: 8a15d7af76 am: 5d84275966
am: 53bcc0545e
Change-Id: Ia665f7ff8cc57038ca1e27b2997e04d5f68d0380
diff --git a/frontend/afe/rpc_interface.py b/frontend/afe/rpc_interface.py
index a8b4302..b4e1733 100644
--- a/frontend/afe/rpc_interface.py
+++ b/frontend/afe/rpc_interface.py
@@ -1773,9 +1773,43 @@
@returns List of hostnames that all have the same host attribute and
value.
"""
- hosts = models.HostAttribute.query_objects({'attribute': attribute,
- 'value': value})
- return [row.host.hostname for row in hosts if row.host.invalid == 0]
+ rows = models.HostAttribute.query_objects({'attribute': attribute,
+ 'value': value})
+ if RESPECT_STATIC_ATTRIBUTES:
+ returned_hosts = set()
+ # Add hosts:
+ # * Non-valid
+ # * Exist in afe_host_attribute with given attribute.
+ # * Don't exist in afe_static_host_attribute OR exist in
+ # afe_static_host_attribute with the same given value.
+ for row in rows:
+ if row.host.invalid != 0:
+ continue
+
+ static_hosts = models.StaticHostAttribute.query_objects(
+ {'host_id': row.host.id, 'attribute': attribute})
+ values = [static_host.value for static_host in static_hosts]
+ if len(values) == 0 or values[0] == value:
+ returned_hosts.add(row.host.hostname)
+
+ # Add hosts:
+ # * Non-valid
+ # * Exist in afe_static_host_attribute with given attribute
+ # and value
+ # * No need to check whether each static attribute has its
+ # corresponding entry in afe_host_attribute since it is ensured
+ # in inventory sync.
+ static_rows = models.StaticHostAttribute.query_objects(
+ {'attribute': attribute, 'value': value})
+ for row in static_rows:
+ if row.host.invalid != 0:
+ continue
+
+ returned_hosts.add(row.host.hostname)
+
+ return list(returned_hosts)
+ else:
+ return [row.host.hostname for row in rows if row.host.invalid == 0]
def canonicalize_suite_name(suite_name):
diff --git a/frontend/afe/rpc_interface_unittest.py b/frontend/afe/rpc_interface_unittest.py
index 017b122..bf31ccb 100755
--- a/frontend/afe/rpc_interface_unittest.py
+++ b/frontend/afe/rpc_interface_unittest.py
@@ -307,6 +307,48 @@
'test_attribute2': 'test_value2',
'static_attribute1': 'static_value2'})
+ def test_get_hosts_by_attribute_without_static(self):
+ host1 = models.Host.objects.create(hostname='test_host1')
+ host1.set_attribute('test_attribute1', 'test_value1')
+ host2 = models.Host.objects.create(hostname='test_host2')
+ host2.set_attribute('test_attribute1', 'test_value1')
+
+ hosts = rpc_interface.get_hosts_by_attribute(
+ 'test_attribute1', 'test_value1')
+ self.assertEquals(set(hosts),
+ set(['test_host1', 'test_host2']))
+
+
+ def test_get_hosts_by_attribute_with_static(self):
+ host1 = models.Host.objects.create(hostname='test_host1')
+ host1.set_attribute('test_attribute1', 'test_value1')
+ self._set_static_attribute(host1, 'test_attribute1', 'test_value1')
+ host2 = models.Host.objects.create(hostname='test_host2')
+ host2.set_attribute('test_attribute1', 'test_value1')
+ self._set_static_attribute(host2, 'test_attribute1', 'static_value1')
+ host3 = models.Host.objects.create(hostname='test_host3')
+ self._set_static_attribute(host3, 'test_attribute1', 'test_value1')
+ host4 = models.Host.objects.create(hostname='test_host4')
+ host4.set_attribute('test_attribute1', 'test_value1')
+ host5 = models.Host.objects.create(hostname='test_host5')
+ host5.set_attribute('test_attribute1', 'temp_value1')
+ self._set_static_attribute(host5, 'test_attribute1', 'test_value1')
+
+ hosts = rpc_interface.get_hosts_by_attribute(
+ 'test_attribute1', 'test_value1')
+ # host1: matched, it has the same value for test_attribute1.
+ # host2: not matched, it has a new value in
+ # afe_static_host_attributes for test_attribute1.
+ # host3: matched, it has a corresponding entry in
+ # afe_host_attributes for test_attribute1.
+ # host4: matched, test_attribute1 is not replaced by static
+ # attribute.
+ # host5: matched, it has an updated & matched value for
+ # test_attribute1 in afe_static_host_attributes.
+ self.assertEquals(set(hosts),
+ set(['test_host1', 'test_host3',
+ 'test_host4', 'test_host5']))
+
class RpcInterfaceTestWithStaticLabel(ShardHeartbeatTest,
frontend_test_utils.FrontendTestMixin):
@@ -690,6 +732,18 @@
self.assertEquals(rpc_interface.ping_db(), [True])
+ def test_get_hosts_by_attribute(self):
+ host1 = models.Host.objects.create(hostname='test_host1')
+ host1.set_attribute('test_attribute1', 'test_value1')
+ host2 = models.Host.objects.create(hostname='test_host2')
+ host2.set_attribute('test_attribute1', 'test_value1')
+
+ hosts = rpc_interface.get_hosts_by_attribute(
+ 'test_attribute1', 'test_value1')
+ self.assertEquals(set(hosts),
+ set(['test_host1', 'test_host2']))
+
+
def test_get_hosts(self):
hosts = rpc_interface.get_hosts()
self._check_hostnames(hosts, [host.hostname for host in self.hosts])