[autotest] Refactor atest server list
This is prep work for adding a JSON output format to atest so various
scripts can use atest to access server_db.
BUG=None
TEST=Run atest server list
Change-Id: If037def77393f60bc87e2b855bb088c72e1c34ab
Reviewed-on: https://chromium-review.googlesource.com/404496
Commit-Ready: Allen Li <[email protected]>
Tested-by: Allen Li <[email protected]>
Reviewed-by: Allen Li <[email protected]>
diff --git a/cli/server.py b/cli/server.py
index e0c5717..f517046 100644
--- a/cli/server.py
+++ b/cli/server.py
@@ -173,13 +173,18 @@
@param results: return of the execute call, a list of server object that
contains server information.
"""
- if not results:
+ if results:
+ if self.table:
+ formatter = server_manager_utils.format_servers_table
+ elif self.summary:
+ formatter = server_manager_utils.format_servers_summary
+ else:
+ formatter = server_manager_utils.format_servers
+ print formatter(results)
+ else:
self.failure('No server is found.',
what_failed='Failed to find servers',
item=self.hostname, fatal=True)
- else:
- print server_manager_utils.get_server_details(results, self.table,
- self.summary)
class server_create(server):
diff --git a/site_utils/server_manager_utils.py b/site_utils/server_manager_utils.py
index cca4a3f..b9e6ea7 100644
--- a/site_utils/server_manager_utils.py
+++ b/site_utils/server_manager_utils.py
@@ -7,6 +7,7 @@
"""
+import collections
import socket
import subprocess
import sys
@@ -72,11 +73,11 @@
return list(server_models.Server.objects.filter(**filters))
-def get_server_details(servers, table=False, summary=False):
- """Get a string of given servers' details.
+def format_servers(servers):
+ """Format servers for printing.
- The method can return a string of server information in 3 different formats:
- A detail view:
+ Example output:
+
Hostname : server2
Status : primary
Roles : drone
@@ -84,11 +85,54 @@
Date Created : 2014-11-25 12:00:00
Date Modified: None
Note : Drone in lab1
- A table view:
+
+ @param servers: Sequence of Server instances.
+ @returns: Formatted output as string.
+ """
+ return '\n'.join(str(server) for server in servers)
+
+
+_SERVER_TABLE_FORMAT = ('%(hostname)-30s | %(status)-7s | %(roles)-20s |'
+ ' %(date_created)-19s | %(date_modified)-19s |'
+ ' %(note)s')
+
+
+def format_servers_table(servers):
+ """format servers for printing as a table.
+
+ Example output:
+
Hostname | Status | Roles | Date Created | Date Modified | Note
server1 | backup | scheduler | 2014-11-25 23:45:19 | |
server2 | primary | drone | 2014-11-25 12:00:00 | | Drone
- A summary view:
+
+ @param servers: Sequence of Server instances.
+ @returns: Formatted output as string.
+ """
+ result_lines = [(_SERVER_TABLE_FORMAT %
+ {'hostname': 'Hostname',
+ 'status': 'Status',
+ 'roles': 'Roles',
+ 'date_created': 'Date Created',
+ 'date_modified': 'Date Modified',
+ 'note': 'Note'})]
+ for server in servers:
+ roles = ','.join(server.get_role_names())
+ result_lines.append(_SERVER_TABLE_FORMAT %
+ {'hostname':server.hostname,
+ 'status': server.status or '',
+ 'roles': roles,
+ 'date_created': server.date_created,
+ 'date_modified': server.date_modified or '',
+ 'note': server.note or ''})
+ return '\n'.join(result_lines)
+
+
+def format_servers_summary(servers):
+ """format servers for printing a summary.
+
+ Example output:
+
scheduler : server1(backup), server3(primary),
host_scheduler :
drone : server2(primary),
@@ -98,55 +142,48 @@
crash_server :
No Role :
- The method returns detail view of each server and a summary view by default.
- If `table` is set to True, only table view will be returned.
- If `summary` is set to True, only summary view will be returned.
-
- @param servers: A list of servers to get details.
- @param table: True to return a table view instead of a detail view,
- default is set to False.
- @param summary: True to only show the summary of roles and status of
- given servers.
-
- @return: A string of the information of given servers.
+ @param servers: Sequence of Server instances.
+ @returns: Formatted output as string.
"""
- # Format string to display a table view.
- # Hostname, Status, Roles, Date Created, Date Modified, Note
- TABLEVIEW_FORMAT = ('%(hostname)-30s | %(status)-7s | %(roles)-20s | '
- '%(date_created)-19s | %(date_modified)-19s | %(note)s')
+ servers_by_role = _get_servers_by_role(servers)
+ servers_with_roles = {server for role_servers in servers_by_role.itervalues()
+ for server in role_servers}
+ servers_without_roles = [server for server in servers
+ if server not in servers_with_roles]
+ result_lines = ['Roles and status of servers:', '']
+ for role, role_servers in servers_by_role.iteritems():
+ result_lines.append(_format_role_servers_summary(role, role_servers))
+ if servers_without_roles:
+ result_lines.append(
+ _format_role_servers_summary('No Role', servers_without_roles))
+ return '\n'.join(result_lines)
- result = ''
- if not table and not summary:
- for server in servers:
- result += '\n' + str(server)
- elif table:
- result += (TABLEVIEW_FORMAT %
- {'hostname':'Hostname', 'status':'Status',
- 'roles':'Roles', 'date_created':'Date Created',
- 'date_modified':'Date Modified', 'note':'Note'})
- for server in servers:
- roles = ','.join(server.get_role_names())
- result += '\n' + (TABLEVIEW_FORMAT %
- {'hostname':server.hostname,
- 'status': server.status or '',
- 'roles': roles,
- 'date_created': server.date_created,
- 'date_modified': server.date_modified or '',
- 'note': server.note or ''})
- elif summary:
- result += 'Roles and status of servers:\n\n'
- for role, _ in server_models.ServerRole.ROLE.choices():
- servers_of_role = [s for s in servers if role in
- [r.role for r in s.roles.all()]]
- result += '%-15s: ' % role
- for server in servers_of_role:
- result += '%s(%s), ' % (server.hostname, server.status)
- result += '\n'
- servers_without_role = [s.hostname for s in servers
- if not s.roles.all()]
- result += '%-15s: %s' % ('No Role', ', '.join(servers_without_role))
- return result
+def _get_servers_by_role(servers):
+ """Return a mapping from roles to servers.
+
+ @param servers: Iterable of servers.
+ @returns: Mapping of role strings to lists of servers.
+ """
+ roles = [role for role, _ in server_models.ServerRole.ROLE.choices()]
+ servers_by_role = collections.defaultdict(list)
+ for server in servers:
+ for role in server.get_role_names():
+ servers_by_role[role].append(server)
+ return servers_by_role
+
+
+def _format_role_servers_summary(role, servers):
+ """Format one line of servers for a role in a server list summary.
+
+ @param role: Role string.
+ @param servers: Iterable of Server instances.
+ @returns: String.
+ """
+ servers_part = ', '.join(
+ '%s(%s)' % (server.hostname, server.status)
+ for server in servers)
+ return '%-15s: %s' % (role, servers_part)
def check_server(hostname, role):