blob: 5a7d183ecd36cba7c2a4c9820413518021267f16 [file] [log] [blame]
Dan Shi784df0c2014-11-26 10:11:15 -08001# Copyright 2014 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
5"""This module provides functions to manage servers in server database
Dan Shi56f1ba72014-12-03 19:16:53 -08006(defined in global config section AUTOTEST_SERVER_DB).
Dan Shi784df0c2014-11-26 10:11:15 -08007
8create(hostname, role=None, note=None)
Xixuan Wu91f58e12017-11-29 11:38:13 -08009 Create a server with given role, with status primary.
Dan Shi784df0c2014-11-26 10:11:15 -080010
11delete(hostname)
Xixuan Wu91f58e12017-11-29 11:38:13 -080012 Delete a server from the database.
Dan Shi784df0c2014-11-26 10:11:15 -080013
14modify(hostname, role=None, status=None, note=None, delete=False,
15 attribute=None, value=None)
16 Modify a server's role, status, note, or attribute:
17 1. Add role to a server. If the server is in primary status, proper actions
18 like service restart will be executed to enable the role.
19 2. Delete a role from a server. If the server is in primary status, proper
20 actions like service restart will be executed to disable the role.
21 3. Change status of a server. If the server is changed from or to primary
22 status, proper actions like service restart will be executed to enable
23 or disable each role of the server.
24 4. Change note of a server. Note is a field you can add description about
25 the server.
26 5. Change/delete attribute of a server. Attribute can be used to store
27 information about a server. For example, the max_processes count for a
28 drone.
29
30"""
31
Dan Shi784df0c2014-11-26 10:11:15 -080032
33import datetime
34
35import common
36
Dan Shi784df0c2014-11-26 10:11:15 -080037from autotest_lib.frontend.server import models as server_models
Dan Shi56f1ba72014-12-03 19:16:53 -080038from autotest_lib.site_utils import server_manager_actions
39from autotest_lib.site_utils import server_manager_utils
Dan Shi784df0c2014-11-26 10:11:15 -080040
41
Dan Shi56f1ba72014-12-03 19:16:53 -080042def _add_role(server, role, action):
Dan Shi784df0c2014-11-26 10:11:15 -080043 """Add a role to the server.
44
45 @param server: An object of server_models.Server.
46 @param role: Role to be added to the server.
Dan Shi56f1ba72014-12-03 19:16:53 -080047 @param action: Execute actions after role or status is changed. Default to
48 False.
Dan Shi784df0c2014-11-26 10:11:15 -080049
50 @raise ServerActionError: If role is failed to be added.
51 """
52 server_models.validate(role=role)
Dan Shi56f1ba72014-12-03 19:16:53 -080053 if role in server.get_role_names():
54 raise server_manager_utils.ServerActionError(
55 'Server %s already has role %s.' % (server.hostname, role))
56
57 # Verify server
58 if not server_manager_utils.check_server(server.hostname, role):
59 raise server_manager_utils.ServerActionError(
60 'Server %s is not ready for role %s.' % (server.hostname, role))
Dan Shi784df0c2014-11-26 10:11:15 -080061
62 if (role in server_models.ServerRole.ROLES_REQUIRE_UNIQUE_INSTANCE and
63 server.status == server_models.Server.STATUS.PRIMARY):
64 servers = server_models.Server.objects.filter(
65 roles__role=role, status=server_models.Server.STATUS.PRIMARY)
66 if len(servers) >= 1:
Dan Shi56f1ba72014-12-03 19:16:53 -080067 raise server_manager_utils.ServerActionError(
68 'Role %s must be unique. Server %s already has role %s.' %
69 (role, servers[0].hostname, role))
70
Dan Shi784df0c2014-11-26 10:11:15 -080071 server_models.ServerRole.objects.create(server=server, role=role)
72
Dan Shi56f1ba72014-12-03 19:16:53 -080073 # If needed, apply actions to enable the role for the server.
74 server_manager_actions.try_execute(server, [role], enable=True,
75 post_change=True, do_action=action)
76
Dan Shi784df0c2014-11-26 10:11:15 -080077 print 'Role %s is added to server %s.' % (role, server.hostname)
78
79
Dan Shi60cf6a92015-01-29 17:22:49 -080080def _delete_role(server, role, action=False):
Dan Shi784df0c2014-11-26 10:11:15 -080081 """Delete a role from the server.
82
83 @param server: An object of server_models.Server.
84 @param role: Role to be deleted from the server.
Dan Shi56f1ba72014-12-03 19:16:53 -080085 @param action: Execute actions after role or status is changed. Default to
86 False.
Dan Shi784df0c2014-11-26 10:11:15 -080087
88 @raise ServerActionError: If role is failed to be deleted.
89 """
90 server_models.validate(role=role)
Dan Shi56f1ba72014-12-03 19:16:53 -080091 if role not in server.get_role_names():
92 raise server_manager_utils.ServerActionError(
93 'Server %s does not have role %s.' % (server.hostname, role))
Dan Shi784df0c2014-11-26 10:11:15 -080094
95 if server.status == server_models.Server.STATUS.PRIMARY:
Dan Shi56f1ba72014-12-03 19:16:53 -080096 server_manager_utils.warn_missing_role(role, server)
97
98 # Apply actions to disable the role for the server before the role is
99 # removed from the server.
100 server_manager_actions.try_execute(server, [role], enable=False,
101 post_change=False, do_action=action)
102
103 print 'Deleting role %s from server %s...' % (role, server.hostname)
104 server.roles.get(role=role).delete()
105
106 # Apply actions to disable the role for the server after the role is
107 # removed from the server.
108 server_manager_actions.try_execute(server, [role], enable=False,
109 post_change=True, do_action=action)
110
Dan Shi56f1ba72014-12-03 19:16:53 -0800111 if (not server.get_role_names() and
112 server.status == server_models.Server.STATUS.PRIMARY):
Xixuan Wu91f58e12017-11-29 11:38:13 -0800113 print ('Server %s has no role.')
Dan Shi784df0c2014-11-26 10:11:15 -0800114
115 print 'Role %s is deleted from server %s.' % (role, server.hostname)
116
117
Dan Shi56f1ba72014-12-03 19:16:53 -0800118def _change_status(server, status, action):
Dan Shi784df0c2014-11-26 10:11:15 -0800119 """Change the status of the server.
120
121 @param server: An object of server_models.Server.
122 @param status: New status of the server.
Dan Shi56f1ba72014-12-03 19:16:53 -0800123 @param action: Execute actions after role or status is changed. Default to
124 False.
Dan Shi784df0c2014-11-26 10:11:15 -0800125
126 @raise ServerActionError: If status is failed to be changed.
127 """
128 server_models.validate(status=status)
129 if server.status == status:
Dan Shi56f1ba72014-12-03 19:16:53 -0800130 raise server_manager_utils.ServerActionError(
131 'Server %s already has status of %s.' %
132 (server.hostname, status))
Dan Shi784df0c2014-11-26 10:11:15 -0800133 if (not server.roles.all() and
Dan Shi56f1ba72014-12-03 19:16:53 -0800134 status == server_models.Server.STATUS.PRIMARY):
135 raise server_manager_utils.ServerActionError(
136 'Server %s has no role associated. Server must have a role to '
137 'be in status primary.' % server.hostname)
Dan Shi784df0c2014-11-26 10:11:15 -0800138
Dan Shi56f1ba72014-12-03 19:16:53 -0800139 # Abort the action if the server's status will be changed to primary and
140 # the Autotest instance already has another server running an unique role.
Xixuan Wu91f58e12017-11-29 11:38:13 -0800141 # For example, a scheduler server is already running, and a repair_required
142 # server with role scheduler should not be changed to status primary.
Dan Shi784df0c2014-11-26 10:11:15 -0800143 unique_roles = server.roles.filter(
144 role__in=server_models.ServerRole.ROLES_REQUIRE_UNIQUE_INSTANCE)
145 if unique_roles and status == server_models.Server.STATUS.PRIMARY:
146 for role in unique_roles:
147 servers = server_models.Server.objects.filter(
148 roles__role=role.role,
149 status=server_models.Server.STATUS.PRIMARY)
150 if len(servers) == 1:
Dan Shi56f1ba72014-12-03 19:16:53 -0800151 raise server_manager_utils.ServerActionError(
152 'Role %s must be unique. Server %s already has the '
153 'role.' % (role.role, servers[0].hostname))
154
155 # Post a warning if the server's status will be changed from primary to
156 # other value and the server is running a unique role across database, e.g.
157 # scheduler.
158 if server.status == server_models.Server.STATUS.PRIMARY:
159 for role in server.get_role_names():
160 server_manager_utils.warn_missing_role(role, server)
161
162 enable = status == server_models.Server.STATUS.PRIMARY
163 server_manager_actions.try_execute(server, server.get_role_names(),
164 enable=enable, post_change=False,
165 do_action=action)
166
167 prev_status = server.status
Dan Shi784df0c2014-11-26 10:11:15 -0800168 server.status = status
169 server.save()
170
Dan Shi56f1ba72014-12-03 19:16:53 -0800171 # Apply actions to enable/disable roles of the server after the status is
172 # changed.
173 server_manager_actions.try_execute(server, server.get_role_names(),
174 enable=enable, post_change=True,
175 prev_status=prev_status,
176 do_action=action)
177
Dan Shi784df0c2014-11-26 10:11:15 -0800178 print ('Status of server %s is changed from %s to %s. Affected roles: %s' %
Dan Shi56f1ba72014-12-03 19:16:53 -0800179 (server.hostname, prev_status, status,
180 ', '.join(server.get_role_names())))
Dan Shi784df0c2014-11-26 10:11:15 -0800181
182
Dan Shi56f1ba72014-12-03 19:16:53 -0800183@server_manager_utils.verify_server(exist=False)
Dan Shi784df0c2014-11-26 10:11:15 -0800184def create(hostname, role=None, note=None):
185 """Create a new server.
186
Xixuan Wu91f58e12017-11-29 11:38:13 -0800187 The status of new server will always be primary.
Dan Shi784df0c2014-11-26 10:11:15 -0800188
189 @param hostname: hostname of the server.
190 @param role: role of the new server, default to None.
191 @param note: notes about the server, default to None.
192
193 @return: A Server object that contains the server information.
194 """
195 server_models.validate(hostname=hostname, role=role)
196 server = server_models.Server.objects.create(
Xixuan Wu91f58e12017-11-29 11:38:13 -0800197 hostname=hostname, status=server_models.Server.STATUS.PRIMARY,
Dan Shi784df0c2014-11-26 10:11:15 -0800198 note=note, date_created=datetime.datetime.now())
199 server_models.ServerRole.objects.create(server=server, role=role)
200 return server
201
202
Dan Shi56f1ba72014-12-03 19:16:53 -0800203@server_manager_utils.verify_server()
Dan Shi784df0c2014-11-26 10:11:15 -0800204def delete(hostname, server=None):
205 """Delete given server from server database.
206
207 @param hostname: hostname of the server to be deleted.
208 @param server: Server object from database query, this argument should be
209 injected by the verify_server_exists decorator.
210
211 @raise ServerActionError: If delete server action failed, e.g., server is
Xixuan Wu91f58e12017-11-29 11:38:13 -0800212 not found in database.
Dan Shi784df0c2014-11-26 10:11:15 -0800213 """
214 print 'Deleting server %s from server database.' % hostname
215
Dan Shi56f1ba72014-12-03 19:16:53 -0800216 if (server_manager_utils.use_server_db() and
217 server.status == server_models.Server.STATUS.PRIMARY):
Dan Shi784df0c2014-11-26 10:11:15 -0800218 print ('Server %s is in status primary, need to disable its '
219 'current roles first.' % hostname)
220 for role in server.roles.all():
221 _delete_role(server, role.role)
222
223 server.delete()
224 print 'Server %s is deleted from server database.' % hostname
225
226
Dan Shi56f1ba72014-12-03 19:16:53 -0800227@server_manager_utils.verify_server()
Dan Shi784df0c2014-11-26 10:11:15 -0800228def modify(hostname, role=None, status=None, delete=False, note=None,
Dan Shi56f1ba72014-12-03 19:16:53 -0800229 attribute=None, value=None, action=False, server=None):
Dan Shi784df0c2014-11-26 10:11:15 -0800230 """Modify given server with specified actions.
231
232 @param hostname: hostname of the server to be modified.
233 @param role: Role to be added to the server.
234 @param status: Modify server status.
235 @param delete: True to delete given role from the server, default to False.
236 @param note: Note of the server.
237 @param attribute: Name of an attribute of the server.
238 @param value: Value of an attribute of the server.
Dan Shi56f1ba72014-12-03 19:16:53 -0800239 @param action: Execute actions after role or status is changed. Default to
240 False.
Dan Shi784df0c2014-11-26 10:11:15 -0800241 @param server: Server object from database query, this argument should be
242 injected by the verify_server_exists decorator.
243
244 @raise InvalidDataError: If the operation failed with any wrong value of
245 the arguments.
246 @raise ServerActionError: If any operation failed.
247 """
248 if role:
249 if not delete:
Dan Shi56f1ba72014-12-03 19:16:53 -0800250 _add_role(server, role, action)
Dan Shi784df0c2014-11-26 10:11:15 -0800251 else:
Dan Shi56f1ba72014-12-03 19:16:53 -0800252 _delete_role(server, role, action)
Dan Shi784df0c2014-11-26 10:11:15 -0800253
254 if status:
Dan Shi56f1ba72014-12-03 19:16:53 -0800255 _change_status(server, status, action)
Dan Shi784df0c2014-11-26 10:11:15 -0800256
257 if note is not None:
258 server.note = note
259 server.save()
260
261 if attribute and value:
Dan Shi56f1ba72014-12-03 19:16:53 -0800262 server_manager_utils.change_attribute(server, attribute, value)
Dan Shi784df0c2014-11-26 10:11:15 -0800263 elif attribute and delete:
Dan Shi56f1ba72014-12-03 19:16:53 -0800264 server_manager_utils.delete_attribute(server, attribute)
Dan Shi784df0c2014-11-26 10:11:15 -0800265
266 return server