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