1784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi# Copyright 2014 The Chromium OS Authors. All rights reserved. 2784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi# Use of this source code is governed by a BSD-style license that can be 3784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi# found in the LICENSE file. 4784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 5784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi""" 6784df0c730f522dc4de83fa81c0f6fe211247673Dan ShiThe server module contains the objects and methods used to manage servers in 7784df0c730f522dc4de83fa81c0f6fe211247673Dan ShiAutotest. 8784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 9784df0c730f522dc4de83fa81c0f6fe211247673Dan ShiThe valid actions are: 10784df0c730f522dc4de83fa81c0f6fe211247673Dan Shilist: list all servers in the database 11784df0c730f522dc4de83fa81c0f6fe211247673Dan Shicreate: create a server 12784df0c730f522dc4de83fa81c0f6fe211247673Dan Shidelete: deletes a server 13784df0c730f522dc4de83fa81c0f6fe211247673Dan Shimodify: modify a server's role or status. 14784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 15784df0c730f522dc4de83fa81c0f6fe211247673Dan ShiThe common options are: 16784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi--role / -r: role that's related to server actions. 17784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 18784df0c730f522dc4de83fa81c0f6fe211247673Dan ShiSee topic_common.py for a High Level Design and Algorithm. 19784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi""" 20784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 21784df0c730f522dc4de83fa81c0f6fe211247673Dan Shiimport common 22784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 23784df0c730f522dc4de83fa81c0f6fe211247673Dan Shifrom autotest_lib.cli import action_common 24784df0c730f522dc4de83fa81c0f6fe211247673Dan Shifrom autotest_lib.cli import topic_common 25784df0c730f522dc4de83fa81c0f6fe211247673Dan Shifrom autotest_lib.client.common_lib import error 26b9144a457ac2be505eac18f61e75d68751b3cea0Dan Shi# The django setup is moved here as test_that uses sqlite setup. If this line 27b9144a457ac2be505eac18f61e75d68751b3cea0Dan Shi# is in server_manager, test_that unittest will fail. 2856f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shifrom autotest_lib.frontend import setup_django_environment 29784df0c730f522dc4de83fa81c0f6fe211247673Dan Shifrom autotest_lib.site_utils import server_manager 3056f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shifrom autotest_lib.site_utils import server_manager_utils 31784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 32784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 33784df0c730f522dc4de83fa81c0f6fe211247673Dan Shiclass server(topic_common.atest): 34784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Server class 35784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 36784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi atest server [list|create|delete|modify] <options> 37784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 38784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi usage_action = '[list|create|delete|modify]' 39784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi topic = msg_topic = 'server' 40784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi msg_items = '<server>' 41784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 42784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def __init__(self, hostname_required=True): 43784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Add to the parser the options common to all the server actions. 44784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 45784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi @param hostname_required: True to require the command has hostname 46784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi specified. Default is True. 47784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 48784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi super(server, self).__init__() 49784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 50784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.parser.add_option('-r', '--role', 51784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi help='Name of a role', 52784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi type='string', 53784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi default=None, 54784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi metavar='ROLE') 5556f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi self.parser.add_option('-x', '--action', 5656f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi help=('Set to True to apply actions when role ' 5756f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi 'or status is changed, e.g., restart ' 5856f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi 'scheduler when a drone is removed.'), 5956f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi action='store_true', 6056f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi default=False, 6156f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi metavar='ACTION') 62784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 63784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.topic_parse_info = topic_common.item_parse_info( 64784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi attribute_name='hostname', use_leftover=True) 65784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 66784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.hostname_required = hostname_required 67784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 68784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 69784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def parse(self): 70784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Parse command arguments. 71784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 72784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi role_info = topic_common.item_parse_info(attribute_name='role') 73784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi kwargs = {} 74784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if self.hostname_required: 75784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi kwargs['req_items'] = 'hostname' 76784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi (options, leftover) = super(server, self).parse([role_info], **kwargs) 77784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if options.web_server: 78784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.invalid_syntax('Server actions will access server database ' 79784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'defined in your local global config. It does ' 80784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'not rely on RPC, no autotest server needs to ' 81784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'be specified.') 82784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 83784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi # self.hostname is a list. Action on server only needs one hostname at 84784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi # most. 85784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if ((not self.hostname and self.hostname_required) or 86784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi len(self.hostname) > 1): 87784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.invalid_syntax('`server` topic can only manipulate 1 server. ' 88784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'Use -h to see available options.') 89784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if self.hostname: 90784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi # Override self.hostname with the first hostname in the list. 91784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.hostname = self.hostname[0] 92784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.role = options.role 93784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi return (options, leftover) 94784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 95784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 96784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def output(self, results): 97784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Display output. 98784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 99784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi For most actions, the return is a string message, no formating needed. 100784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 101784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi @param results: return of the execute call. 102784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 103784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi print results 104784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 105784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 106784df0c730f522dc4de83fa81c0f6fe211247673Dan Shiclass server_help(server): 107784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Just here to get the atest logic working. Usage is set by its parent. 108784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 109784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi pass 110784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 111784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 112784df0c730f522dc4de83fa81c0f6fe211247673Dan Shiclass server_list(action_common.atest_list, server): 113784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """atest server list [--role <role>]""" 114784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 115784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def __init__(self): 116784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Initializer. 117784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 118784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi super(server_list, self).__init__(hostname_required=False) 119784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.parser.add_option('-t', '--table', 120784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi help=('List details of all servers in a table, ' 121784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'e.g., \tHostname | Status | Roles | ' 122784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'note\t\tserver1 | primary | scheduler | ' 123784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'lab'), 124784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi action='store_true', 125784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi default=False, 126784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi metavar='TABLE') 127784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.parser.add_option('-s', '--status', 128784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi help='Only show servers with given status', 129784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi type='string', 130784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi default=None, 131784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi metavar='STATUS') 132784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.parser.add_option('-u', '--summary', 133784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi help=('Show the summary of roles and status ' 134784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'only, e.g.,\tscheduler: server1(primary) ' 135784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'server2(backup)\t\tdrone: server3(primary' 136784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi ') server4(backup)'), 137784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi action='store_true', 138784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi default=False, 139784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi metavar='SUMMARY') 140784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 141784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 142784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def parse(self): 143784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Parse command arguments. 144784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 145784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi (options, leftover) = super(server_list, self).parse() 146784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.table = options.table 147784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.status = options.status 148784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.summary = options.summary 149784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if self.table and self.summary: 150784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.invalid_syntax('Option --table and --summary cannot be both ' 151784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'specified.') 152784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi return (options, leftover) 153784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 154784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 155784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def execute(self): 156784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Execute the command. 157784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 158784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi @return: A list of servers matched given hostname and role. 159784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 160784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi try: 16156f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi return server_manager_utils.get_servers(hostname=self.hostname, 16256f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi role=self.role, 16356f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi status=self.status) 16456f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi except (server_manager_utils.ServerActionError, 165784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi error.InvalidDataError) as e: 166784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.failure(e, what_failed='Failed to find servers', 167784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi item=self.hostname, fatal=True) 168784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 169784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 170784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def output(self, results): 171784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Display output. 172784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 173784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi @param results: return of the execute call, a list of server object that 174784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi contains server information. 175784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 176784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if not results: 177784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.failure('No server is found.', 178784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi what_failed='Failed to find servers', 179784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi item=self.hostname, fatal=True) 180784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi else: 18156f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi print server_manager_utils.get_server_details(results, self.table, 18256f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi self.summary) 183784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 184784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 185784df0c730f522dc4de83fa81c0f6fe211247673Dan Shiclass server_create(server): 186784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """atest server create hostname --role <role> --note <note> 187784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 188784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 189784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def __init__(self): 190784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Initializer. 191784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 192784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi super(server_create, self).__init__() 193784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.parser.add_option('-n', '--note', 194784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi help='note of the server', 195784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi type='string', 196784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi default=None, 197784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi metavar='NOTE') 198784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 199784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 200784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def parse(self): 201784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Parse command arguments. 202784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 203784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi (options, leftover) = super(server_create, self).parse() 204784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.note = options.note 205784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 206784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if not self.role: 207784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.invalid_syntax('--role is required to create a server.') 208784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 209784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi return (options, leftover) 210784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 211784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 212784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def execute(self): 213784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Execute the command. 214784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 215784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi @return: A Server object if it is created successfully. 216784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 217784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi try: 218784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi return server_manager.create(hostname=self.hostname, role=self.role, 219784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi note=self.note) 22056f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi except (server_manager_utils.ServerActionError, 221784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi error.InvalidDataError) as e: 222784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.failure(e, what_failed='Failed to create server', 223784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi item=self.hostname, fatal=True) 224784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 225784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 226784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def output(self, results): 227784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Display output. 228784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 229784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi @param results: return of the execute call, a server object that 230784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi contains server information. 231784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 232784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if results: 233784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi print 'Server %s is added to server database:\n' % self.hostname 234784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi print results 235784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 236784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 237784df0c730f522dc4de83fa81c0f6fe211247673Dan Shiclass server_delete(server): 238784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """atest server delete hostname""" 239784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 240784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def execute(self): 241784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Execute the command. 242784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 243784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi @return: True if server is deleted successfully. 244784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 245784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi try: 246784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi server_manager.delete(hostname=self.hostname) 247784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi return True 24856f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi except (server_manager_utils.ServerActionError, 249784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi error.InvalidDataError) as e: 250784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.failure(e, what_failed='Failed to delete server', 251784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi item=self.hostname, fatal=True) 252784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 253784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 254784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def output(self, results): 255784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Display output. 256784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 257784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi @param results: return of the execute call. 258784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 259784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if results: 260784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi print ('Server %s is deleted from server database successfully.' % 261784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.hostname) 262784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 263784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 264784df0c730f522dc4de83fa81c0f6fe211247673Dan Shiclass server_modify(server): 265784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """atest server modify hostname 266784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 267784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi modify action can only change one input at a time. Available inputs are: 268784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi --status: Status of the server. 269784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi --note: Note of the server. 270784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi --role: New role to be added to the server. 271784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi --delete_role: Existing role to be deleted from the server. 272784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 273784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 274784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def __init__(self): 275784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Initializer. 276784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 277784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi super(server_modify, self).__init__() 278784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.parser.add_option('-s', '--status', 279784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi help='Status of the server', 280784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi type='string', 281784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi metavar='STATUS') 282784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.parser.add_option('-n', '--note', 283784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi help='Note of the server', 284784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi type='string', 285784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi default=None, 286784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi metavar='NOTE') 287784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.parser.add_option('-d', '--delete', 288784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi help=('Set to True to delete given role.'), 289784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi action='store_true', 290784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi default=False, 291784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi metavar='DELETE') 292784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.parser.add_option('-a', '--attribute', 293784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi help='Name of the attribute of the server', 294784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi type='string', 295784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi default=None, 296784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi metavar='ATTRIBUTE') 297784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.parser.add_option('-e', '--value', 298784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi help='Value for the attribute of the server', 299784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi type='string', 300784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi default=None, 301784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi metavar='VALUE') 302784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 303784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 304784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def parse(self): 305784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Parse command arguments. 306784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 307784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi (options, leftover) = super(server_modify, self).parse() 308784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.status = options.status 309784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.note = options.note 310784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.delete = options.delete 311784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.attribute = options.attribute 312784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.value = options.value 31356f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi self.action = options.action 314784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 315784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi # modify supports various options. However, it's safer to limit one 316784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi # option at a time so no complicated role-dependent logic is needed 317784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi # to handle scenario that both role and status are changed. 318784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi # self.parser is optparse, which does not have function in argparse like 319784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi # add_mutually_exclusive_group. That's why the count is used here. 320784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi flags = [self.status is not None, self.role is not None, 321784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.attribute is not None, self.note is not None] 322784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if flags.count(True) != 1: 323784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi msg = ('Action modify only support one option at a time. You can ' 324784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'try one of following 5 options:\n' 325784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi '1. --status: Change server\'s status.\n' 326784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi '2. --note: Change server\'s note.\n' 327784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi '3. --role with optional -d: Add/delete role from server.\n' 328784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi '4. --attribute --value: Set/change the value of a ' 329784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'server\'s attribute.\n' 330784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi '5. --attribute -d: Delete the attribute from the ' 331784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'server.\n' 332784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi '\nUse option -h to see a complete list of options.') 333784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.invalid_syntax(msg) 334784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if (self.status != None or self.note != None) and self.delete: 335784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.invalid_syntax('--delete does not apply to status or note.') 336784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if self.attribute != None and not self.delete and self.value == None: 337784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.invalid_syntax('--attribute must be used with option --value ' 338784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 'or --delete.') 339784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi return (options, leftover) 340784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 341784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 342784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def execute(self): 343784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Execute the command. 344784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 345784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi @return: The updated server object if it is modified successfully. 346784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 347784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi try: 348784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi return server_manager.modify(hostname=self.hostname, role=self.role, 349784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi status=self.status, delete=self.delete, 350784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi note=self.note, 351784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi attribute=self.attribute, 35256f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi value=self.value, action=self.action) 35356f1ba77e4b8b4c13d5bc72b0ebaeabda9f9d0bcDan Shi except (server_manager_utils.ServerActionError, 354784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi error.InvalidDataError) as e: 355784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi self.failure(e, what_failed='Failed to modify server', 356784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi item=self.hostname, fatal=True) 357784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 358784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 359784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi def output(self, results): 360784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """Display output. 361784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi 362784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi @param results: return of the execute call, which is the updated server 363784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi object. 364784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi """ 365784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi if results: 366784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi print 'Server %s is modified successfully.' % self.hostname 367784df0c730f522dc4de83fa81c0f6fe211247673Dan Shi print results 368