def testChangeStatusSuccess_PrimaryToRepairFailed(self): """Test manager can change the status of a primary server to repair_required. """ server_models.validate( status=server_models.Server.STATUS.REPAIR_REQUIRED) self.mox.StubOutWithMock(self.PRIMARY_DRONE.roles, 'filter') self.mox.StubOutWithMock(self.PRIMARY_DRONE, 'get_role_names') self.PRIMARY_DRONE.get_role_names().MultipleTimes().AndReturn( [server_models.ServerRole.ROLE.DRONE]) self.PRIMARY_DRONE.roles.filter( role__in=server_models.ServerRole.ROLES_REQUIRE_UNIQUE_INSTANCE ).AndReturn(None) server_manager_utils.use_server_db().MultipleTimes().AndReturn(True) server_manager_utils.warn_missing_role( server_models.ServerRole.ROLE.DRONE, self.PRIMARY_DRONE) server_models.Server.objects.filter( roles__role=server_models.ServerRole.ROLE.SCHEDULER, status=server_models.Server.STATUS.PRIMARY).AndReturn( [self.PRIMARY_SCHEDULER]) infra.execute_command(mox.IgnoreArg(), mox.IgnoreArg()) self.mox.ReplayAll() server_manager._change_status( server=self.PRIMARY_DRONE, status=server_models.Server.STATUS.REPAIR_REQUIRED, action=True)
def testAddRoleToPrimarySuccess(self): """Test manager can add a role to a primary server successfully. Confirm that actions needs to be taken, e.g., restart scheduler for new drone to be added. """ server_models.validate(role=server_models.ServerRole.ROLE.DRONE) server_manager_utils.check_server(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(True) server_manager_utils.use_server_db().MultipleTimes().AndReturn(True) self.mox.StubOutWithMock(self.PRIMARY_SCHEDULER, 'get_role_names') self.PRIMARY_SCHEDULER.get_role_names().AndReturn( [server_models.ServerRole.ROLE.SCHEDULER]) server_models.ServerRole.objects.create( server=self.PRIMARY_SCHEDULER, role=server_models.ServerRole.ROLE.DRONE).AndReturn( self.DRONE_ROLE) server_models.Server.objects.filter( roles__role=server_models.ServerRole.ROLE.SCHEDULER, status=server_models.Server.STATUS.PRIMARY).AndReturn( [self.PRIMARY_SCHEDULER]) infra.execute_command(mox.IgnoreArg(), mox.IgnoreArg()) self.mox.ReplayAll() server_manager._add_role(self.PRIMARY_SCHEDULER, server_models.ServerRole.ROLE.DRONE, action=True)
def testDeleteRoleFromPrimarySuccess(self): """Test manager can delete a role from a primary server successfully. Confirm that database call is made, and actions are taken, e.g., restart scheduler to delete an existing drone. """ server_manager_utils.use_server_db().MultipleTimes().AndReturn(True) server_models.validate(role=server_models.ServerRole.ROLE.DRONE) self.mox.StubOutWithMock(self.PRIMARY_DRONE, 'get_role_names') self.PRIMARY_DRONE.get_role_names().MultipleTimes().AndReturn( [server_models.ServerRole.ROLE.DRONE]) self.mox.StubOutWithMock(self.PRIMARY_DRONE.roles, 'get') self.PRIMARY_DRONE.roles.get( role=server_models.ServerRole.ROLE.DRONE).AndReturn( self.DRONE_ROLE) server_models.Server.objects.filter( roles__role=server_models.ServerRole.ROLE.SCHEDULER, status=server_models.Server.STATUS.PRIMARY).AndReturn( [self.PRIMARY_SCHEDULER]) server_manager.server_manager_utils.warn_missing_role( server_models.ServerRole.ROLE.DRONE, self.PRIMARY_DRONE) infra.execute_command(mox.IgnoreArg(), mox.IgnoreArg()) self.mox.ReplayAll() server_manager._delete_role(self.PRIMARY_DRONE, server_models.ServerRole.ROLE.DRONE, action=True)
def testChangeStatusFail_StatusNoChange(self): """Test manager cannot change the status of a server with the same status. """ server_models.validate(status=server_models.Server.STATUS.BACKUP) self.mox.ReplayAll() self.assertRaises(server_manager_utils.ServerActionError, server_manager._change_status, server=self.BACKUP_DRONE, status=server_models.Server.STATUS.BACKUP, action=True)
def testAddRoleToBackupFail_RoleAlreadyExists(self): """Test manager fails to add a role to a backup server if server already has the given role. """ server_models.validate(role=server_models.ServerRole.ROLE.DRONE) self.mox.StubOutWithMock(self.BACKUP_DRONE, 'get_role_names') self.BACKUP_DRONE.get_role_names().AndReturn( [server_models.ServerRole.ROLE.DRONE]) self.mox.ReplayAll() self.assertRaises(server_manager_utils.ServerActionError, server_manager._add_role, server=self.BACKUP_DRONE, role=server_models.ServerRole.ROLE.DRONE, action=True)
def testDeleteRoleFromBackupFail_RoleNotExist(self): """Test manager fails to delete a role from a backup server if the server does not have the given role. """ server_models.validate(role=server_models.ServerRole.ROLE.DEVSERVER) self.mox.StubOutWithMock(self.BACKUP_DRONE, 'get_role_names') self.BACKUP_DRONE.get_role_names().AndReturn( [server_models.ServerRole.ROLE.DRONE]) self.mox.ReplayAll() self.assertRaises(server_manager_utils.ServerActionError, server_manager._delete_role, server=self.BACKUP_DRONE, role=server_models.ServerRole.ROLE.DEVSERVER, action=True)
def testAddRoleToBackupFail_CheckServerFail(self): """Test manager fails to add a role to a backup server if check_server is failed. """ server_manager_utils.check_server(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(False) server_models.validate(role=server_models.ServerRole.ROLE.DRONE) self.mox.StubOutWithMock(self.BACKUP_DRONE, 'get_role_names') self.BACKUP_DRONE.get_role_names().MultipleTimes().AndReturn( [server_models.ServerRole.ROLE.DRONE]) self.mox.ReplayAll() self.assertRaises(server_manager_utils.ServerActionError, server_manager._add_role, server=self.BACKUP_DRONE, role=server_models.ServerRole.ROLE.SCHEDULER, action=True)
def _delete_role(server, role, action=False): """Delete a role from the server. @param server: An object of server_models.Server. @param role: Role to be deleted from the server. @param action: Execute actions after role or status is changed. Default to False. @raise ServerActionError: If role is failed to be deleted. """ server_models.validate(role=role) if role not in server.get_role_names(): raise server_manager_utils.ServerActionError( 'Server %s does not have role %s.' % (server.hostname, role)) if server.status == server_models.Server.STATUS.PRIMARY: server_manager_utils.warn_missing_role(role, server) # Apply actions to disable the role for the server before the role is # removed from the server. server_manager_actions.try_execute(server, [role], enable=False, post_change=False, do_action=action) print 'Deleting role %s from server %s...' % (role, server.hostname) server.roles.get(role=role).delete() # Apply actions to disable the role for the server after the role is # removed from the server. server_manager_actions.try_execute(server, [role], enable=False, post_change=True, do_action=action) # If the server is in status primary and has no role, change its status to # backup. if (not server.get_role_names() and server.status == server_models.Server.STATUS.PRIMARY): print( 'Server %s has no role, change its status from primary to backup' % server.hostname) server.status = server_models.Server.STATUS.BACKUP server.save() print 'Role %s is deleted from server %s.' % (role, server.hostname)
def create(hostname, role=None, note=None): """Create a new server. The status of new server will always be primary. @param hostname: hostname of the server. @param role: role of the new server, default to None. @param note: notes about the server, default to None. @return: A Server object that contains the server information. """ server_models.validate(hostname=hostname, role=role) server = server_models.Server.objects.create( hostname=hostname, status=server_models.Server.STATUS.PRIMARY, note=note, date_created=datetime.datetime.now()) server_models.ServerRole.objects.create(server=server, role=role) return server
def testDeleteRoleFromBackupSuccess(self): """Test manager can delete a role from a backup server successfully. Confirm that database call is made, and no action is taken, e.g., restart scheduler to delete an existing devserver. """ server_models.validate(role=server_models.ServerRole.ROLE.DRONE) server_manager_utils.use_server_db().MultipleTimes().AndReturn(True) self.mox.StubOutWithMock(self.BACKUP_DRONE, 'get_role_names') self.BACKUP_DRONE.get_role_names().MultipleTimes().AndReturn( [server_models.ServerRole.ROLE.DRONE]) self.mox.StubOutWithMock(self.BACKUP_DRONE.roles, 'get') self.BACKUP_DRONE.roles.get( role=server_models.ServerRole.ROLE.DRONE).AndReturn( self.DRONE_ROLE) self.mox.ReplayAll() server_manager._delete_role(server=self.BACKUP_DRONE, role=server_models.ServerRole.ROLE.DRONE, action=True)
def testChangeStatusFail_UniqueInstance(self): """Test manager cannot change the status of a server from backup to primary if there is already a primary exists for role doesn't allow multiple instances. """ server_models.validate(status=server_models.Server.STATUS.PRIMARY) self.mox.StubOutWithMock(self.BACKUP_SCHEDULER.roles, 'filter') self.BACKUP_SCHEDULER.roles.filter( role__in=server_models.ServerRole.ROLES_REQUIRE_UNIQUE_INSTANCE ).AndReturn(QueriableList([self.SCHEDULER_ROLE])) server_models.Server.objects.filter( roles__role=self.SCHEDULER_ROLE.role, status=server_models.Server.STATUS.PRIMARY).AndReturn( QueriableList([self.PRIMARY_SCHEDULER])) self.mox.ReplayAll() self.assertRaises(server_manager_utils.ServerActionError, server_manager._change_status, server=self.BACKUP_SCHEDULER, status=server_models.Server.STATUS.PRIMARY, action=True)
def create(hostname, role=None, note=None): """Create a new server. The status of new server will always be backup, user need to call atest server modify hostname --status primary to set the server's status to primary. @param hostname: hostname of the server. @param role: role of the new server, default to None. @param note: notes about the server, default to None. @return: A Server object that contains the server information. """ server_models.validate(hostname=hostname, role=role) server = server_models.Server.objects.create( hostname=hostname, status=server_models.Server.STATUS.BACKUP, note=note, date_created=datetime.datetime.now()) server_models.ServerRole.objects.create(server=server, role=role) return server
def testAddRoleToBackupSuccess(self): """Test manager can add a role to a backup server successfully. Confirm that database call is made, and no action is taken, e.g., restart scheduler to activate a new devserver. """ server_models.validate(role=server_models.ServerRole.ROLE.DEVSERVER) server_manager_utils.check_server(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(True) server_manager_utils.use_server_db().MultipleTimes().AndReturn(True) self.mox.StubOutWithMock(self.BACKUP_DRONE, 'get_role_names') self.BACKUP_DRONE.get_role_names().AndReturn( [server_models.ServerRole.ROLE.DRONE]) server_models.ServerRole.objects.create( server=mox.IgnoreArg(), role=server_models.ServerRole.ROLE.DEVSERVER).AndReturn( self.DRONE_ROLE) self.mox.ReplayAll() server_manager._add_role(server=self.BACKUP_DRONE, role=server_models.ServerRole.ROLE.DEVSERVER, action=True)
def testChangeStatusSuccess_BackupToPrimary(self): """Test manager can change the status of a backup server to primary. """ server_models.validate(status=server_models.Server.STATUS.PRIMARY) server_manager_utils.use_server_db().MultipleTimes().AndReturn(True) self.mox.StubOutWithMock(self.BACKUP_DRONE, 'get_role_names') self.BACKUP_DRONE.get_role_names().MultipleTimes().AndReturn( [server_models.ServerRole.ROLE.DRONE]) self.mox.StubOutWithMock(self.BACKUP_DRONE.roles, 'filter') self.BACKUP_DRONE.roles.filter( role__in=server_models.ServerRole.ROLES_REQUIRE_UNIQUE_INSTANCE ).AndReturn(None) server_models.Server.objects.filter( roles__role=server_models.ServerRole.ROLE.SCHEDULER, status=server_models.Server.STATUS.PRIMARY).AndReturn( [self.PRIMARY_SCHEDULER]) infra.execute_command(mox.IgnoreArg(), mox.IgnoreArg()) self.mox.ReplayAll() server_manager._change_status( server=self.BACKUP_DRONE, status=server_models.Server.STATUS.PRIMARY, action=True)
def _add_role(server, role, action): """Add a role to the server. @param server: An object of server_models.Server. @param role: Role to be added to the server. @param action: Execute actions after role or status is changed. Default to False. @raise ServerActionError: If role is failed to be added. """ server_models.validate(role=role) if role in server.get_role_names(): raise server_manager_utils.ServerActionError( 'Server %s already has role %s.' % (server.hostname, role)) # Verify server if not server_manager_utils.check_server(server.hostname, role): raise server_manager_utils.ServerActionError( 'Server %s is not ready for role %s.' % (server.hostname, role)) if (role in server_models.ServerRole.ROLES_REQUIRE_UNIQUE_INSTANCE and server.status == server_models.Server.STATUS.PRIMARY): servers = server_models.Server.objects.filter( roles__role=role, status=server_models.Server.STATUS.PRIMARY) if len(servers) >= 1: raise server_manager_utils.ServerActionError( 'Role %s must be unique. Server %s already has role %s.' % (role, servers[0].hostname, role)) server_models.ServerRole.objects.create(server=server, role=role) # If needed, apply actions to enable the role for the server. server_manager_actions.try_execute(server, [role], enable=True, post_change=True, do_action=action) print 'Role %s is added to server %s.' % (role, server.hostname)
def testDeleteRoleFromPrimarySuccess_NoAction(self): """Test manager can delete a role from a primary server successfully. Confirm that database call is made, and no action is taken as action is set to False. """ server_manager_utils.use_server_db().MultipleTimes().AndReturn(True) server_models.validate(role=server_models.ServerRole.ROLE.DRONE) self.mox.StubOutWithMock(self.PRIMARY_DRONE, 'get_role_names') self.PRIMARY_DRONE.get_role_names().MultipleTimes().AndReturn( [server_models.ServerRole.ROLE.DRONE]) self.mox.StubOutWithMock(self.PRIMARY_DRONE.roles, 'get') self.PRIMARY_DRONE.roles.get( role=server_models.ServerRole.ROLE.DRONE).AndReturn( self.DRONE_ROLE) server_manager.server_manager_utils.warn_missing_role( server_models.ServerRole.ROLE.DRONE, self.PRIMARY_DRONE) self.mox.ReplayAll() server_manager._delete_role(self.PRIMARY_DRONE, server_models.ServerRole.ROLE.DRONE, action=False)
def _change_status(server, status, action): """Change the status of the server. @param server: An object of server_models.Server. @param status: New status of the server. @param action: Execute actions after role or status is changed. Default to False. @raise ServerActionError: If status is failed to be changed. """ server_models.validate(status=status) if server.status == status: raise server_manager_utils.ServerActionError( 'Server %s already has status of %s.' % (server.hostname, status)) if (not server.roles.all() and status == server_models.Server.STATUS.PRIMARY): raise server_manager_utils.ServerActionError( 'Server %s has no role associated. Server must have a role to ' 'be in status primary.' % server.hostname) # Abort the action if the server's status will be changed to primary and # the Autotest instance already has another server running an unique role. # For example, a scheduler server is already running, and a backup server # with role scheduler should not be changed to status primary. unique_roles = server.roles.filter( role__in=server_models.ServerRole.ROLES_REQUIRE_UNIQUE_INSTANCE) if unique_roles and status == server_models.Server.STATUS.PRIMARY: for role in unique_roles: servers = server_models.Server.objects.filter( roles__role=role.role, status=server_models.Server.STATUS.PRIMARY) if len(servers) == 1: raise server_manager_utils.ServerActionError( 'Role %s must be unique. Server %s already has the ' 'role.' % (role.role, servers[0].hostname)) # Post a warning if the server's status will be changed from primary to # other value and the server is running a unique role across database, e.g. # scheduler. if server.status == server_models.Server.STATUS.PRIMARY: for role in server.get_role_names(): server_manager_utils.warn_missing_role(role, server) enable = status == server_models.Server.STATUS.PRIMARY server_manager_actions.try_execute(server, server.get_role_names(), enable=enable, post_change=False, do_action=action) prev_status = server.status server.status = status server.save() # Apply actions to enable/disable roles of the server after the status is # changed. server_manager_actions.try_execute(server, server.get_role_names(), enable=enable, post_change=True, prev_status=prev_status, do_action=action) print('Status of server %s is changed from %s to %s. Affected roles: %s' % (server.hostname, prev_status, status, ', '.join( server.get_role_names())))