• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package autotest.afe;
2 
3 import autotest.afe.create.CreateJobViewPresenter.JobCreateListener;
4 import autotest.common.CustomHistory.HistoryToken;
5 import autotest.common.SimpleCallback;
6 import autotest.common.Utils;
7 import autotest.common.table.DataSource;
8 import autotest.common.table.DataSource.DataCallback;
9 import autotest.common.table.DataSource.Query;
10 import autotest.common.table.DataSource.SortDirection;
11 import autotest.common.table.DataTable;
12 import autotest.common.table.DatetimeSegmentFilter;
13 import autotest.common.table.DynamicTable;
14 import autotest.common.table.DynamicTable.DynamicTableListener;
15 import autotest.common.table.JSONObjectSet;
16 import autotest.common.table.RpcDataSource;
17 import autotest.common.table.SelectionManager;
18 import autotest.common.table.SimpleFilter;
19 import autotest.common.table.TableDecorator;
20 import autotest.common.ui.ContextMenu;
21 import autotest.common.ui.DetailView;
22 import autotest.common.ui.NotifyManager;
23 import autotest.common.ui.TableActionsPanel.TableActionsListener;
24 
25 import com.google.gwt.event.dom.client.ClickEvent;
26 import com.google.gwt.event.dom.client.ClickHandler;
27 import com.google.gwt.event.dom.client.KeyCodes;
28 import com.google.gwt.event.dom.client.KeyPressEvent;
29 import com.google.gwt.event.dom.client.KeyPressHandler;
30 import com.google.gwt.event.logical.shared.ValueChangeEvent;
31 import com.google.gwt.event.logical.shared.ValueChangeHandler;
32 import com.google.gwt.json.client.JSONArray;
33 import com.google.gwt.json.client.JSONBoolean;
34 import com.google.gwt.json.client.JSONNumber;
35 import com.google.gwt.json.client.JSONObject;
36 import com.google.gwt.json.client.JSONString;
37 import com.google.gwt.json.client.JSONValue;
38 import com.google.gwt.user.client.Command;
39 import com.google.gwt.user.client.ui.Button;
40 import com.google.gwt.user.client.ui.CheckBox;
41 import com.google.gwt.user.client.ui.TextBox;
42 
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Set;
46 
47 public class HostDetailView extends DetailView implements DataCallback, TableActionsListener {
48     private static final String[][] HOST_JOBS_COLUMNS = {
49             {DataTable.WIDGET_COLUMN, ""}, {"type", "Type"}, {"job__id", "Job ID"},
50             {"job_owner", "Job Owner"}, {"job_name", "Job Name"}, {"started_on", "Time started"},
51             {"status", "Status"}
52     };
53     public static final int JOBS_PER_PAGE = 20;
54 
55     public interface HostDetailListener {
onJobSelected(int jobId)56         public void onJobSelected(int jobId);
57     }
58 
59     private static class HostQueueEntryDataSource extends RpcDataSource {
HostQueueEntryDataSource()60         public HostQueueEntryDataSource() {
61             super("get_host_queue_entries", "get_num_host_queue_entries");
62         }
63 
64         @Override
handleJsonResult(JSONValue result)65         protected List<JSONObject> handleJsonResult(JSONValue result) {
66             List<JSONObject> resultArray = super.handleJsonResult(result);
67             for (JSONObject row : resultArray) {
68                 // get_host_queue_entries() doesn't return type, so fill it in for consistency with
69                 // get_host_queue_entries_and_special_tasks()
70                 row.put("type", new JSONString("Job"));
71             }
72             return resultArray;
73         }
74     }
75 
76     private static class HostJobsTable extends DynamicTable {
77         private static final DataSource normalDataSource = new HostQueueEntryDataSource();
78         private static final DataSource dataSourceWithSpecialTasks =
79             new RpcDataSource("get_host_queue_entries_and_special_tasks",
80                               "get_num_host_queue_entries_and_special_tasks");
81 
82         private SimpleFilter hostFilter = new SimpleFilter();
83         private String hostId;
84         private String startTime;
85         private String endTime;
86 
HostJobsTable()87         public HostJobsTable() {
88             super(HOST_JOBS_COLUMNS, normalDataSource);
89             addFilter(hostFilter);
90         }
91 
setHostId(String hostId)92         public void setHostId(String hostId) {
93             this.hostId = hostId;
94             updateFilter();
95         }
96 
setStartTime(String startTime)97         public void setStartTime(String startTime) {
98             this.startTime = startTime;
99             updateFilter();
100         }
101 
setEndTime(String endTime)102         public void setEndTime(String endTime) {
103             this.endTime = endTime;
104             updateFilter();
105         }
106 
updateFilter()107         private void updateFilter() {
108             if (getDataSource() == normalDataSource) {
109                 sortOnColumn("job__id", SortDirection.DESCENDING);
110             } else {
111                 clearSorts();
112             }
113 
114             hostFilter.clear();
115             hostFilter.setParameter("host",
116                                     new JSONNumber(Double.parseDouble(hostId)));
117             if (startTime != null && startTime != "")
118                 hostFilter.setParameter("start_time", new JSONString(startTime));
119             if (endTime != null && endTime != "")
120                 hostFilter.setParameter("end_time", new JSONString(endTime));
121         }
122 
setSpecialTasksEnabled(boolean enabled)123         public void setSpecialTasksEnabled(boolean enabled) {
124             if (enabled) {
125                 setDataSource(dataSourceWithSpecialTasks);
126             } else {
127                 setDataSource(normalDataSource);
128             }
129 
130             updateFilter();
131         }
132 
133         @Override
preprocessRow(JSONObject row)134         protected void preprocessRow(JSONObject row) {
135             JSONObject job = row.get("job").isObject();
136             JSONString blank = new JSONString("");
137             JSONString jobId = blank, owner = blank, name = blank;
138             if (job != null) {
139                 int id = (int) job.get("id").isNumber().doubleValue();
140                 jobId = new JSONString(Integer.toString(id));
141                 owner = job.get("owner").isString();
142                 name = job.get("name").isString();
143             }
144 
145             row.put("job__id", jobId);
146             row.put("job_owner", owner);
147             row.put("job_name", name);
148         }
149     }
150 
151     private String hostname = "";
152     private String hostId = "";
153     private DataSource hostDataSource = new HostDataSource();
154     private HostJobsTable jobsTable = new HostJobsTable();
155     private TableDecorator tableDecorator = new TableDecorator(jobsTable);
156     private HostDetailListener hostDetailListener = null;
157     private JobCreateListener jobCreateListener = null;
158     private SelectionManager selectionManager;
159 
160     private JSONObject currentHostObject;
161 
162     private Button lockButton = new Button();
163     private Button reverifyButton = new Button("Reverify");
164     private Button reinstallButton = new Button("Reinstall");
165     private Button repairButton = new Button("Repair");
166     private CheckBox showSpecialTasks = new CheckBox();
167     private DatetimeSegmentFilter startedTimeFilter = new DatetimeSegmentFilter();
168     private TextBox hostnameInput = new TextBox();
169     private Button hostnameFetchButton = new Button("Go");
170     private TextBox lockReasonInput = new TextBox();
171 
HostDetailView(HostDetailListener hostDetailListener, JobCreateListener jobCreateListener)172     public HostDetailView(HostDetailListener hostDetailListener,
173                           JobCreateListener jobCreateListener) {
174         this.hostDetailListener = hostDetailListener;
175         this.jobCreateListener = jobCreateListener;
176     }
177 
178     @Override
getElementId()179     public String getElementId() {
180         return "view_host";
181     }
182 
183     @Override
getFetchControlsElementId()184     protected String getFetchControlsElementId() {
185         return "view_host_fetch_controls";
186     }
187 
getFetchByHostnameControlsElementId()188     private String getFetchByHostnameControlsElementId() {
189         return "view_host_fetch_by_hostname_controls";
190     }
191 
192     @Override
getDataElementId()193     protected String getDataElementId() {
194         return "view_host_data";
195     }
196 
197     @Override
getTitleElementId()198     protected String getTitleElementId() {
199         return "view_host_title";
200     }
201 
202     @Override
getNoObjectText()203     protected String getNoObjectText() {
204         return "No host selected";
205     }
206 
207     @Override
getObjectId()208     protected String getObjectId() {
209         return hostId;
210     }
211 
getHostname()212     protected String getHostname() {
213         return hostname;
214     }
215 
216     @Override
setObjectId(String id)217     protected void setObjectId(String id) {
218         if (id.length() == 0) {
219             throw new IllegalArgumentException();
220         }
221         this.hostId = id;
222     }
223 
224     @Override
fetchData()225     protected void fetchData() {
226         JSONObject params = new JSONObject();
227         params.put("id", new JSONString(getObjectId()));
228         fetchDataCommmon(params);
229     }
230 
fetchDataByHostname(String hostname)231     private void fetchDataByHostname(String hostname) {
232         JSONObject params = new JSONObject();
233         params.put("hostname", new JSONString(hostname));
234         fetchDataCommmon(params);
235     }
236 
fetchDataCommmon(JSONObject params)237     private void fetchDataCommmon(JSONObject params) {
238         params.put("valid_only", JSONBoolean.getInstance(false));
239         hostDataSource.query(params, this);
240     }
241 
fetchByHostname(String hostname)242     private void fetchByHostname(String hostname) {
243         fetchDataByHostname(hostname);
244         updateHistory();
245     }
246 
247     @Override
handleTotalResultCount(int totalCount)248     public void handleTotalResultCount(int totalCount) {}
249 
250     @Override
onQueryReady(Query query)251     public void onQueryReady(Query query) {
252         query.getPage(null, null, null, this);
253     }
254 
handlePage(List<JSONObject> data)255     public void handlePage(List<JSONObject> data) {
256         try {
257             currentHostObject = Utils.getSingleObjectFromList(data);
258         }
259         catch (IllegalArgumentException exc) {
260             NotifyManager.getInstance().showError("No such host found");
261             resetPage();
262             return;
263         }
264 
265         setObjectId(currentHostObject.get("id").toString());
266 
267         String lockedText = Utils.jsonToString(currentHostObject.get(HostDataSource.LOCKED_TEXT));
268         if (currentHostObject.get("locked").isBoolean().booleanValue()) {
269             String lockedBy = Utils.jsonToString(currentHostObject.get("locked_by"));
270             String lockedTime = Utils.jsonToString(currentHostObject.get("lock_time"));
271             String lockReasonText = Utils.jsonToString(currentHostObject.get("lock_reason"));
272             lockedText += ", by " + lockedBy + " on " + lockedTime;
273             lockedText += ", reason: " + lockReasonText;
274         }
275 
276         showField(currentHostObject, "status", "view_host_status");
277         showField(currentHostObject, "platform", "view_host_platform");
278         showField(currentHostObject, HostDataSource.HOST_ACLS, "view_host_acls");
279         showField(currentHostObject, HostDataSource.OTHER_LABELS, "view_host_labels");
280         showText(lockedText, "view_host_locked");
281         String shard_url = Utils.jsonToString(currentHostObject.get("shard")).trim();
282         String host_id = Utils.jsonToString(currentHostObject.get("id")).trim();
283         if (shard_url.equals("<null>")){
284             shard_url = "";
285         } else {
286             shard_url = "http://" + shard_url;
287         }
288         shard_url = shard_url + "/afe/#tab_id=view_host&object_id=" + host_id;
289         showField(currentHostObject, "shard", "view_host_shard");
290         getElementById("view_host_shard").setAttribute("href", shard_url);
291 
292         String job_id = Utils.jsonToString(currentHostObject.get("current_job")).trim();
293         if (!job_id.equals("<null>")){
294             String job_url = "#tab_id=view_job&object_id=" + job_id;
295             showField(currentHostObject, "current_job", "view_host_current_job");
296             getElementById("view_host_current_job").setAttribute("href", job_url);
297         }
298         hostname = currentHostObject.get("hostname").isString().stringValue();
299 
300         String task = Utils.jsonToString(currentHostObject.get("current_special_task")).trim();
301         if (!task.equals("<null>")){
302             String task_url = Utils.getRetrieveLogsUrl("hosts/" + hostname + "/" + task);
303             showField(currentHostObject, "current_special_task", "view_host_current_special_task");
304             getElementById("view_host_current_special_task").setAttribute("href", task_url);
305         }
306 
307         showField(currentHostObject, "protection", "view_host_protection");
308         String pageTitle = "Host " + hostname;
309         hostnameInput.setText(hostname);
310         hostnameInput.setWidth("240px");
311         updateLockButton();
312         updateLockReasonInput();
313         displayObjectData(pageTitle);
314 
315         jobsTable.setHostId(getObjectId());
316         jobsTable.refresh();
317     }
318 
319     @Override
initialize()320     public void initialize() {
321         super.initialize();
322 
323         // Replace fetch by id with fetch by hostname
324         addWidget(hostnameInput, getFetchByHostnameControlsElementId());
325         addWidget(hostnameFetchButton, getFetchByHostnameControlsElementId());
326 
327         hostnameInput.addKeyPressHandler(new KeyPressHandler() {
328             public void onKeyPress (KeyPressEvent event) {
329                 if (event.getCharCode() == (char) KeyCodes.KEY_ENTER)
330                     fetchByHostname(hostnameInput.getText());
331             }
332         });
333         hostnameFetchButton.addClickHandler(new ClickHandler() {
334             public void onClick(ClickEvent event) {
335                 fetchByHostname(hostnameInput.getText());
336             }
337         });
338 
339         jobsTable.setRowsPerPage(JOBS_PER_PAGE);
340         jobsTable.setClickable(true);
341         jobsTable.addListener(new DynamicTableListener() {
342             public void onRowClicked(int rowIndex, JSONObject row, boolean isRightClick) {
343                 if (isJobRow(row)) {
344                     JSONObject job = row.get("job").isObject();
345                     int jobId = (int) job.get("id").isNumber().doubleValue();
346                     hostDetailListener.onJobSelected(jobId);
347                 } else {
348                     String resultsPath = Utils.jsonToString(row.get("execution_path"));
349                     Utils.openUrlInNewWindow(Utils.getRetrieveLogsUrl(resultsPath));
350                 }
351             }
352 
353             public void onTableRefreshed() {}
354         });
355         tableDecorator.addPaginators();
356         selectionManager = tableDecorator.addSelectionManager(false);
357         jobsTable.setWidgetFactory(selectionManager);
358         tableDecorator.addTableActionsPanel(this, true);
359         tableDecorator.addControl("Show verifies, repairs, cleanups and resets",
360                                   showSpecialTasks);
361         tableDecorator.addFilter("Filter by time started:",
362                                  startedTimeFilter);
363         addWidget(tableDecorator, "view_host_jobs_table");
364 
365         showSpecialTasks.addClickHandler(new ClickHandler() {
366             public void onClick(ClickEvent event) {
367                 selectionManager.deselectAll();
368                 jobsTable.setSpecialTasksEnabled(showSpecialTasks.getValue());
369                 jobsTable.refresh();
370             }
371         });
372 
373         startedTimeFilter.addValueChangeHandler(
374             new ValueChangeHandler() {
375                 public void onValueChange(ValueChangeEvent event) {
376                     String value = (String) event.getValue();
377                     jobsTable.setStartTime(value);
378                     if (value == "")
379                         startedTimeFilter.setStartTimeToPlaceHolderValue();
380                     jobsTable.refresh();
381                 }
382             },
383             new ValueChangeHandler() {
384                 public void onValueChange(ValueChangeEvent event) {
385                     String value = (String) event.getValue();
386                     jobsTable.setEndTime(value);
387                     if (value == "")
388                         startedTimeFilter.setEndTimeToPlaceHolderValue();
389                     jobsTable.refresh();
390                 }
391             }
392         );
393 
394         addWidget(lockButton, "view_host_lock_button");
395         addWidget(lockReasonInput, "view_host_lock_reason_input");
396 
397         lockButton.addClickHandler(new ClickHandler() {
398             public void onClick(ClickEvent event) {
399                boolean locked = currentHostObject.get("locked").isBoolean().booleanValue();
400                changeLock(!locked);
401             }
402         });
403         lockReasonInput.addKeyPressHandler(new KeyPressHandler() {
404             public void onKeyPress (KeyPressEvent event) {
405                 if (event.getCharCode() == (char) KeyCodes.KEY_ENTER) {
406                     boolean locked = currentHostObject.get("locked").isBoolean().booleanValue();
407                     changeLock(!locked);
408                 }
409             }
410         });
411 
412         reverifyButton.addClickHandler(new ClickHandler() {
413             public void onClick(ClickEvent event) {
414                 JSONObject params = new JSONObject();
415 
416                 params.put("id", currentHostObject.get("id"));
417                 AfeUtils.callReverify(params, new SimpleCallback() {
418                     public void doCallback(Object source) {
419                        refresh();
420                     }
421                 }, "Host " + hostname);
422             }
423         });
424         addWidget(reverifyButton, "view_host_reverify_button");
425 
426         reinstallButton.addClickHandler(new ClickHandler() {
427             public void onClick(ClickEvent event) {
428                 JSONArray array = new JSONArray();
429                 array.set(0, new JSONString(hostname));
430                 AfeUtils.scheduleReinstall(array, hostname, jobCreateListener);
431             }
432         });
433         addWidget(reinstallButton, "view_host_reinstall_button");
434 
435         repairButton.addClickHandler(new ClickHandler() {
436             public void onClick(ClickEvent event) {
437                 JSONObject params = new JSONObject();
438 
439                 params.put("id", currentHostObject.get("id"));
440                 AfeUtils.callRepair(params, new SimpleCallback() {
441                     public void doCallback(Object source) {
442                        refresh();
443                     }
444                 }, "Host " + hostname);
445             }
446         });
447         addWidget(repairButton, "view_host_repair_button");
448     }
449 
onError(JSONObject errorObject)450     public void onError(JSONObject errorObject) {
451         // RPC handler will display error
452     }
453 
getActionMenu()454     public ContextMenu getActionMenu() {
455         ContextMenu menu = new ContextMenu();
456         menu.addItem("Abort", new Command() {
457             public void execute() {
458                 abortSelectedQueueEntriesAndSpecialTasks();
459             }
460         });
461         if (selectionManager.isEmpty())
462             menu.setEnabled(false);
463         return menu;
464     }
465 
abortSelectedQueueEntriesAndSpecialTasks()466     private void abortSelectedQueueEntriesAndSpecialTasks() {
467         Set<JSONObject> selectedEntries = selectionManager.getSelectedObjects();
468         Set<JSONObject> selectedQueueEntries = new JSONObjectSet<JSONObject>();
469         JSONArray selectedSpecialTaskIds = new JSONArray();
470         for (JSONObject entry : selectedEntries) {
471             if (isJobRow(entry))
472                 selectedQueueEntries.add(entry);
473             else
474                 selectedSpecialTaskIds.set(selectedSpecialTaskIds.size(),
475                                            entry.get("oid"));
476         }
477         if (!selectedQueueEntries.isEmpty()) {
478             AfeUtils.abortHostQueueEntries(selectedQueueEntries, new SimpleCallback() {
479                 public void doCallback(Object source) {
480                     refresh();
481                 }
482             });
483         }
484         if (selectedSpecialTaskIds.size() > 0) {
485             AfeUtils.abortSpecialTasks(selectedSpecialTaskIds, new SimpleCallback() {
486                 public void doCallback(Object source) {
487                     refresh();
488                 }
489             });
490         }
491     }
492 
updateLockButton()493     private void updateLockButton() {
494         boolean locked = currentHostObject.get("locked").isBoolean().booleanValue();
495         if (locked) {
496             lockButton.setText("Unlock");
497         } else {
498             lockButton.setText("Lock");
499         }
500     }
501 
updateLockReasonInput()502     private void updateLockReasonInput() {
503         boolean locked = currentHostObject.get("locked").isBoolean().booleanValue();
504         if (locked) {
505             lockReasonInput.setText("");
506             lockReasonInput.setEnabled(false);
507         } else {
508             lockReasonInput.setEnabled(true);
509         }
510     }
511 
changeLock(final boolean lock)512     private void changeLock(final boolean lock) {
513         JSONArray hostIds = new JSONArray();
514         hostIds.set(0, currentHostObject.get("id"));
515 
516         AfeUtils.changeHostLocks(hostIds, lock, lockReasonInput.getText(),
517                                  "Host " + hostname, new SimpleCallback() {
518             public void doCallback(Object source) {
519                 refresh();
520             }
521         });
522     }
523 
isJobRow(JSONObject row)524     private boolean isJobRow(JSONObject row) {
525         String type = Utils.jsonToString(row.get("type"));
526         return type.equals("Job");
527     }
528 
isRowSelectable(JSONObject row)529     public boolean isRowSelectable(JSONObject row) {
530         return isJobRow(row);
531     }
532 
533     @Override
handleHistoryArguments(Map<String, String> arguments)534     public void handleHistoryArguments(Map<String, String> arguments) {
535         String hostname = arguments.get("hostname");
536         String objectId = arguments.get("object_id");
537 
538         if (objectId != null) {
539             try {
540                 updateObjectId(objectId);
541             }
542             catch (IllegalArgumentException exc) {
543                 return;
544             }
545         } else if (hostname != null) {
546             fetchDataByHostname(hostname);
547         } else {
548             resetPage();
549         }
550     }
551 }
552