diff options
author | showard <showard@592f7852-d20e-0410-864c-8624ca9c26a4> | 2008-11-12 18:17:05 +0000 |
---|---|---|
committer | showard <showard@592f7852-d20e-0410-864c-8624ca9c26a4> | 2008-11-12 18:17:05 +0000 |
commit | 8bad6ed905449c8190f8c8e37826b738c0cdd842 (patch) | |
tree | 326531059c7fcf6dd657abb1dcb8661bd17a567f /frontend | |
parent | d6f2a1a31f4f1d1c13f078ebcf568fd68195b9e3 (diff) |
Add a checkbox 'exclude "only if needed" labels' to host lists in AFE, checked by default in the create job view.
-add exclude_only_if_needed_labels argument to get_hosts() and get_num_hosts() RPCs
-move some code from tko.models.TestViewManager up into model_logic, since AFE now needs it to create a custom join for doing many-valued exclusion
git-svn-id: svn://test.kernel.org/autotest/trunk@2405 592f7852-d20e-0410-864c-8624ca9c26a4
Diffstat (limited to 'frontend')
-rw-r--r-- | frontend/afe/model_logic.py | 47 | ||||
-rw-r--r-- | frontend/afe/rpc_interface.py | 34 | ||||
-rw-r--r-- | frontend/afe/rpc_utils.py | 16 | ||||
-rw-r--r-- | frontend/client/src/autotest/afe/HostSelector.java | 1 | ||||
-rw-r--r-- | frontend/client/src/autotest/afe/HostTableDecorator.java | 34 | ||||
-rw-r--r-- | frontend/client/src/autotest/common/table/CheckboxFilter.java | 35 |
6 files changed, 132 insertions, 35 deletions
diff --git a/frontend/afe/model_logic.py b/frontend/afe/model_logic.py index 3cf964e0..91558233 100644 --- a/frontend/afe/model_logic.py +++ b/frontend/afe/model_logic.py @@ -137,6 +137,53 @@ class ExtendedManager(dbmodels.Manager): return new_joins, new_where, params + class _CustomSqlQ(dbmodels.Q): + def __init__(self): + self._joins = datastructures.SortedDict() + self._where, self._params = [], [] + + + def add_join(self, table, condition, join_type, alias=None): + if alias is None: + alias = table + condition = ModelExtensions.escape_user_sql(condition) + self._joins[alias] = (table, join_type, condition) + + + def add_where(self, where, params=[]): + self._where.append(where) + self._params.extend(params) + + + def get_sql(self, opts): + return self._joins, self._where, self._params + + + def add_join(self, query_set, join_table, join_key, + local_join_key='id', join_condition='', suffix='', + exclude=False, force_left_join=False): + table_name = self.model._meta.db_table + join_alias = join_table + suffix + full_join_key = join_alias + '.' + join_key + full_join_condition = '%s = %s.%s' % (full_join_key, table_name, + local_join_key) + if join_condition: + full_join_condition += ' AND (' + join_condition + ')' + if exclude or force_left_join: + join_type = 'LEFT JOIN' + else: + join_type = 'INNER JOIN' + + filter_object = self._CustomSqlQ() + filter_object.add_join(join_table, + full_join_condition, + join_type, + alias=join_alias) + if exclude: + filter_object.add_where(full_join_key + ' IS NULL') + return query_set.filter(filter_object).distinct() + + def filter_custom_join(self, join_suffix, **kwargs): """ Just like Django filter(), but allows the user to specify a custom diff --git a/frontend/afe/rpc_interface.py b/frontend/afe/rpc_interface.py index 3b1f99c8..167f04d9 100644 --- a/frontend/afe/rpc_interface.py +++ b/frontend/afe/rpc_interface.py @@ -90,27 +90,33 @@ def delete_host(id): models.Host.smart_get(id).delete() -def get_hosts(multiple_labels=[], **filter_data): +def get_hosts(multiple_labels=[], exclude_only_if_needed_labels=False, + **filter_data): """\ multiple_labels: match hosts in all of the labels given. Should be a list of label names. + exclude_only_if_needed_labels: exclude hosts with at least one + "only_if_needed" label applied. """ - filter_data['extra_args'] = ( - rpc_utils.extra_host_filters(multiple_labels)) - hosts = models.Host.list_objects(filter_data) - for host in hosts: - host_obj = models.Host.objects.get(id=host['id']) - host['labels'] = [label.name - for label in host_obj.labels.all()] + hosts = rpc_utils.get_host_query(multiple_labels, + exclude_only_if_needed_labels, + filter_data) + host_dicts = [] + for host_obj in hosts: + host_dict = host_obj.get_object_dict() + host_dict['labels'] = [label.name for label in host_obj.labels.all()] platform = host_obj.platform() - host['platform'] = platform and platform.name or None - return rpc_utils.prepare_for_serialization(hosts) + host_dict['platform'] = platform and platform.name or None + host_dicts.append(host_dict) + return rpc_utils.prepare_for_serialization(host_dicts) -def get_num_hosts(multiple_labels=[], **filter_data): - filter_data['extra_args'] = ( - rpc_utils.extra_host_filters(multiple_labels)) - return models.Host.query_count(filter_data) +def get_num_hosts(multiple_labels=[], exclude_only_if_needed_labels=False, + **filter_data): + hosts = rpc_utils.get_host_query(multiple_labels, + exclude_only_if_needed_labels, + filter_data) + return hosts.count() # tests diff --git a/frontend/afe/rpc_utils.py b/frontend/afe/rpc_utils.py index 0e25d05c..014e3f3d 100644 --- a/frontend/afe/rpc_utils.py +++ b/frontend/afe/rpc_utils.py @@ -97,6 +97,22 @@ def extra_host_filters(multiple_labels=[]): return extra_args +def get_host_query(multiple_labels, exclude_only_if_needed_labels, filter_data): + query = models.Host.valid_objects.all() + if exclude_only_if_needed_labels: + only_if_needed_labels = models.Label.valid_objects.filter( + only_if_needed=True) + only_if_needed_ids = ','.join( + str(label['id']) for label in only_if_needed_labels.values('id')) + query = models.Host.objects.add_join( + query, 'hosts_labels', join_key='host_id', + join_condition='hosts_labels_exclude.label_id IN (%s)' + % only_if_needed_ids, + suffix='_exclude', exclude=True) + filter_data['extra_args'] = (extra_host_filters(multiple_labels)) + return models.Host.query_objects(filter_data, initial_query=query) + + class InconsistencyException(Exception): 'Raised when a list of objects does not have a consistent value' diff --git a/frontend/client/src/autotest/afe/HostSelector.java b/frontend/client/src/autotest/afe/HostSelector.java index 030d17ea..921f2e49 100644 --- a/frontend/client/src/autotest/afe/HostSelector.java +++ b/frontend/client/src/autotest/afe/HostSelector.java @@ -72,6 +72,7 @@ public class HostSelector { availableTable.setClickable(true); availableDecorator.lockedFilter.setSelectedChoice("No"); availableDecorator.aclFilter.setActive(true); + availableDecorator.excludeOnlyIfNeededFilter.setActive(true); availableSelection = availableDecorator.addSelectionManager(false); availableDecorator.addSelectionPanel(true); diff --git a/frontend/client/src/autotest/afe/HostTableDecorator.java b/frontend/client/src/autotest/afe/HostTableDecorator.java index 77df2cdd..fc5f1a97 100644 --- a/frontend/client/src/autotest/afe/HostTableDecorator.java +++ b/frontend/client/src/autotest/afe/HostTableDecorator.java @@ -3,17 +3,15 @@ package autotest.afe; import autotest.common.StaticDataRepository; import autotest.common.Utils; import autotest.common.table.BooleanFilter; -import autotest.common.table.FieldFilter; +import autotest.common.table.CheckboxFilter; import autotest.common.table.ListFilter; import autotest.common.table.SearchFilter; import autotest.common.table.TableDecorator; import com.google.gwt.json.client.JSONArray; +import com.google.gwt.json.client.JSONBoolean; import com.google.gwt.json.client.JSONString; import com.google.gwt.json.client.JSONValue; -import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.ClickListener; -import com.google.gwt.user.client.ui.Widget; class HostTableDecorator extends TableDecorator { SearchFilter hostnameFilter; @@ -21,38 +19,30 @@ class HostTableDecorator extends TableDecorator { ListFilter statusFilter; BooleanFilter lockedFilter; AclAccessibleFilter aclFilter; + OnlyIfNeededFilter excludeOnlyIfNeededFilter; - static class AclAccessibleFilter extends FieldFilter implements ClickListener { - private CheckBox checkBox = new CheckBox("ACL accessible only"); + static class AclAccessibleFilter extends CheckboxFilter { private JSONValue username; public AclAccessibleFilter() { super("acl_group__users__login"); username = new JSONString(StaticDataRepository.getRepository().getCurrentUserLogin()); - checkBox.addClickListener(this); - } - - public void onClick(Widget sender) { - notifyListeners(); } @Override public JSONValue getMatchValue() { return username; } - - @Override - public Widget getWidget() { - return checkBox; + } + + static class OnlyIfNeededFilter extends CheckboxFilter { + public OnlyIfNeededFilter() { + super("exclude_only_if_needed_labels"); } @Override - public boolean isActive() { - return checkBox.isChecked(); - } - - public void setActive(boolean active) { - checkBox.setChecked(active); + public JSONValue getMatchValue() { + return JSONBoolean.getInstance(true); } } @@ -73,6 +63,7 @@ class HostTableDecorator extends TableDecorator { statusFilter.setChoices(statusStrings); lockedFilter = new BooleanFilter("locked"); aclFilter = new AclAccessibleFilter(); + excludeOnlyIfNeededFilter = new OnlyIfNeededFilter(); addFilter("Hostname", hostnameFilter); addControl("Platform", labelFilter.getPlatformWidget()); @@ -80,5 +71,6 @@ class HostTableDecorator extends TableDecorator { addFilter("Status", statusFilter); addFilter("Locked", lockedFilter); addFilter("ACL accessible only", aclFilter); + addFilter("Exclude only_if_needed labels", excludeOnlyIfNeededFilter); } } diff --git a/frontend/client/src/autotest/common/table/CheckboxFilter.java b/frontend/client/src/autotest/common/table/CheckboxFilter.java new file mode 100644 index 00000000..1a92e044 --- /dev/null +++ b/frontend/client/src/autotest/common/table/CheckboxFilter.java @@ -0,0 +1,35 @@ +// Copyright 2008 Google Inc. All Rights Reserved. + +package autotest.common.table; + + +import com.google.gwt.user.client.ui.CheckBox; +import com.google.gwt.user.client.ui.ClickListener; +import com.google.gwt.user.client.ui.Widget; + +public abstract class CheckboxFilter extends FieldFilter implements ClickListener { + private CheckBox checkBox = new CheckBox(); + + public CheckboxFilter(String fieldName) { + super(fieldName); + checkBox.addClickListener(this); + } + + public void onClick(Widget sender) { + notifyListeners(); + } + + @Override + public Widget getWidget() { + return checkBox; + } + + @Override + public boolean isActive() { + return checkBox.isChecked(); + } + + public void setActive(boolean active) { + checkBox.setChecked(active); + } +}
\ No newline at end of file |