| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 1 | # | 
 | 2 | # Copyright 2008 Google Inc. All Rights Reserved. | 
 | 3 |  | 
 | 4 | """ | 
 | 5 | The host module contains the objects and method used to | 
 | 6 | manage a host in Autotest. | 
 | 7 |  | 
 | 8 | The valid actions are: | 
 | 9 | create:  adds host(s) | 
 | 10 | delete:  deletes host(s) | 
 | 11 | list:    lists host(s) | 
 | 12 | stat:    displays host(s) information | 
 | 13 | mod:     modifies host(s) | 
 | 14 | jobs:    lists all jobs that ran on host(s) | 
 | 15 |  | 
 | 16 | The common options are: | 
 | 17 | -M|--mlist:   file containing a list of machines | 
 | 18 |  | 
 | 19 |  | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 20 | See topic_common.py for a High Level Design and Algorithm. | 
 | 21 |  | 
 | 22 | """ | 
 | 23 |  | 
| mbligh | 6996fe8 | 2008-08-13 00:32:27 +0000 | [diff] [blame] | 24 | import os, sys, socket | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 25 | from autotest_lib.cli import topic_common, action_common | 
 | 26 |  | 
 | 27 |  | 
 | 28 | class host(topic_common.atest): | 
 | 29 |     """Host class | 
 | 30 |     atest host [create|delete|list|stat|mod|jobs] <options>""" | 
 | 31 |     usage_action = '[create|delete|list|stat|mod|jobs]' | 
 | 32 |     topic = msg_topic = 'host' | 
 | 33 |     msg_items = '<hosts>' | 
 | 34 |  | 
 | 35 |  | 
 | 36 |     def __init__(self): | 
 | 37 |         """Add to the parser the options common to all the | 
 | 38 |         host actions""" | 
 | 39 |         super(host, self).__init__() | 
 | 40 |  | 
 | 41 |         self.parser.add_option('-M', '--mlist', | 
 | 42 |                                help='File listing the machines', | 
 | 43 |                                type='string', | 
 | 44 |                                default=None, | 
 | 45 |                                metavar='MACHINE_FLIST') | 
 | 46 |  | 
 | 47 |  | 
 | 48 |     def parse(self, flists=None, req_items='hosts'): | 
 | 49 |         """Consume the common host options""" | 
 | 50 |         if flists: | 
 | 51 |             flists.append(('hosts', 'mlist', '', True)) | 
 | 52 |         else: | 
 | 53 |             flists = [('hosts', 'mlist', '', True)] | 
 | 54 |         return self.parse_with_flist(flists, req_items) | 
 | 55 |  | 
 | 56 |  | 
 | 57 |     def _parse_lock_options(self, options): | 
 | 58 |         if options.lock and options.unlock: | 
 | 59 |             self.invalid_syntax('Only specify one of ' | 
 | 60 |                                 '--lock and --unlock.') | 
 | 61 |  | 
 | 62 |         if options.lock: | 
 | 63 |             self.data['locked'] = True | 
 | 64 |             self.messages.append('Locked host') | 
 | 65 |         elif options.unlock: | 
 | 66 |             self.data['locked'] = False | 
 | 67 |             self.messages.append('Unlocked host') | 
 | 68 |  | 
 | 69 |  | 
 | 70 |     def _cleanup_labels(self, labels, platform=None): | 
 | 71 |         """Removes the platform label from the overall labels""" | 
 | 72 |         if platform: | 
 | 73 |             return [label for label in labels | 
 | 74 |                     if label != platform] | 
 | 75 |         else: | 
 | 76 |             try: | 
 | 77 |                 return [label for label in labels | 
 | 78 |                         if not label['platform']] | 
 | 79 |             except TypeError: | 
 | 80 |                 # This is a hack - the server will soon | 
 | 81 |                 # do this, so all this code should be removed. | 
 | 82 |                 return labels | 
 | 83 |  | 
 | 84 |  | 
 | 85 |     def get_items(self): | 
 | 86 |         return self.hosts | 
 | 87 |  | 
 | 88 |  | 
 | 89 | class host_help(host): | 
 | 90 |     """Just here to get the atest logic working. | 
 | 91 |     Usage is set by its parent""" | 
 | 92 |     pass | 
 | 93 |  | 
 | 94 |  | 
 | 95 | class host_list(action_common.atest_list, host): | 
 | 96 |     """atest host list [--mlist <file>|<hosts>] [--label <label>] | 
| mbligh | 536a524 | 2008-10-18 14:35:54 +0000 | [diff] [blame] | 97 |        [--status <status1,status2>] [--acl <ACL>] [--user <user>]""" | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 98 |  | 
 | 99 |     def __init__(self): | 
 | 100 |         super(host_list, self).__init__() | 
 | 101 |  | 
 | 102 |         self.parser.add_option('-b', '--label', | 
| mbligh | 6444c6b | 2008-10-27 20:55:13 +0000 | [diff] [blame] | 103 |                                default='', | 
 | 104 |                                help='Only list hosts with all these labels ' | 
 | 105 |                                '(comma separated)') | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 106 |         self.parser.add_option('-s', '--status', | 
| mbligh | 6444c6b | 2008-10-27 20:55:13 +0000 | [diff] [blame] | 107 |                                default='', | 
 | 108 |                                help='Only list hosts with any of these ' | 
 | 109 |                                'statuses (comma separated)') | 
| mbligh | 536a524 | 2008-10-18 14:35:54 +0000 | [diff] [blame] | 110 |         self.parser.add_option('-a', '--acl', | 
| mbligh | 6444c6b | 2008-10-27 20:55:13 +0000 | [diff] [blame] | 111 |                                default='', | 
| mbligh | 536a524 | 2008-10-18 14:35:54 +0000 | [diff] [blame] | 112 |                                help='Only list hosts within this ACL') | 
 | 113 |         self.parser.add_option('-u', '--user', | 
| mbligh | 6444c6b | 2008-10-27 20:55:13 +0000 | [diff] [blame] | 114 |                                default='', | 
| mbligh | 536a524 | 2008-10-18 14:35:54 +0000 | [diff] [blame] | 115 |                                help='Only list hosts available to this user') | 
| mbligh | 70b9bf4 | 2008-11-18 15:00:46 +0000 | [diff] [blame] | 116 |         self.parser.add_option('-N', '--hostnames-only', help='Only return ' | 
 | 117 |                                'hostnames for the machines queried.', | 
 | 118 |                                action='store_true') | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 119 |  | 
 | 120 |  | 
 | 121 |     def parse(self): | 
 | 122 |         """Consume the specific options""" | 
 | 123 |         (options, leftover) = super(host_list, self).parse(req_items=None) | 
| mbligh | 6444c6b | 2008-10-27 20:55:13 +0000 | [diff] [blame] | 124 |         self.labels = options.label | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 125 |         self.status = options.status | 
| mbligh | 536a524 | 2008-10-18 14:35:54 +0000 | [diff] [blame] | 126 |         self.acl = options.acl | 
 | 127 |         self.user = options.user | 
| mbligh | 70b9bf4 | 2008-11-18 15:00:46 +0000 | [diff] [blame] | 128 |         self.hostnames_only = options.hostnames_only | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 129 |         return (options, leftover) | 
 | 130 |  | 
 | 131 |  | 
 | 132 |     def execute(self): | 
 | 133 |         filters = {} | 
 | 134 |         check_results = {} | 
 | 135 |         if self.hosts: | 
 | 136 |             filters['hostname__in'] = self.hosts | 
 | 137 |             check_results['hostname__in'] = 'hostname' | 
| mbligh | 6444c6b | 2008-10-27 20:55:13 +0000 | [diff] [blame] | 138 |  | 
 | 139 |         if self.labels: | 
 | 140 |             labels = self.labels.split(',') | 
 | 141 |             labels = [label.strip() for label in labels if label.strip()] | 
 | 142 |  | 
| mbligh | f703fb4 | 2009-01-30 00:35:05 +0000 | [diff] [blame^] | 143 |             if len(labels) == 1: | 
 | 144 |                 # This is needed for labels with wildcards (x86*) | 
 | 145 |                 filters['labels__name__in'] = labels | 
 | 146 |                 check_results['labels__name__in'] = None | 
 | 147 |             else: | 
 | 148 |                 filters['multiple_labels'] = labels | 
 | 149 |                 check_results['multiple_labels'] = None | 
| mbligh | 6444c6b | 2008-10-27 20:55:13 +0000 | [diff] [blame] | 150 |  | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 151 |         if self.status: | 
| mbligh | 6444c6b | 2008-10-27 20:55:13 +0000 | [diff] [blame] | 152 |             statuses = self.status.split(',') | 
 | 153 |             statuses = [status.strip() for status in statuses | 
 | 154 |                         if status.strip()] | 
 | 155 |  | 
 | 156 |             filters['status__in'] = statuses | 
| mbligh | cd8eb97 | 2008-08-25 19:20:39 +0000 | [diff] [blame] | 157 |             check_results['status__in'] = None | 
| mbligh | 6444c6b | 2008-10-27 20:55:13 +0000 | [diff] [blame] | 158 |  | 
| mbligh | 536a524 | 2008-10-18 14:35:54 +0000 | [diff] [blame] | 159 |         if self.acl: | 
 | 160 |             filters['acl_group__name'] = self.acl | 
 | 161 |             check_results['acl_group__name'] = None | 
 | 162 |         if self.user: | 
 | 163 |             filters['acl_group__users__login'] = self.user | 
 | 164 |             check_results['acl_group__users__login'] = None | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 165 |         return super(host_list, self).execute(op='get_hosts', | 
 | 166 |                                               filters=filters, | 
 | 167 |                                               check_results=check_results) | 
 | 168 |  | 
 | 169 |  | 
 | 170 |     def output(self, results): | 
 | 171 |         if results: | 
 | 172 |             # Remove the platform from the labels. | 
 | 173 |             for result in results: | 
 | 174 |                 result['labels'] = self._cleanup_labels(result['labels'], | 
 | 175 |                                                         result['platform']) | 
| mbligh | 70b9bf4 | 2008-11-18 15:00:46 +0000 | [diff] [blame] | 176 |         if self.hostnames_only: | 
| mbligh | df75f8b | 2008-11-18 19:07:42 +0000 | [diff] [blame] | 177 |             self.print_list(results, key='hostname') | 
| mbligh | 70b9bf4 | 2008-11-18 15:00:46 +0000 | [diff] [blame] | 178 |         else: | 
 | 179 |             super(host_list, self).output(results, keys=['hostname', 'status', | 
 | 180 |                                           'locked', 'platform', 'labels']) | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 181 |  | 
 | 182 |  | 
 | 183 | class host_stat(host): | 
 | 184 |     """atest host stat --mlist <file>|<hosts>""" | 
 | 185 |     usage_action = 'stat' | 
 | 186 |  | 
 | 187 |     def execute(self): | 
| mbligh | 6996fe8 | 2008-08-13 00:32:27 +0000 | [diff] [blame] | 188 |         socket.setdefaulttimeout(topic_common.LIST_SOCKET_TIMEOUT) | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 189 |         results = [] | 
 | 190 |         # Convert wildcards into real host stats. | 
 | 191 |         existing_hosts = [] | 
 | 192 |         for host in self.hosts: | 
 | 193 |             if host.endswith('*'): | 
 | 194 |                 stats = self.execute_rpc('get_hosts', | 
 | 195 |                                          hostname__startswith=host.rstrip('*')) | 
 | 196 |                 if len(stats) == 0: | 
 | 197 |                     self.failure('No hosts matching %s' % host, item=host, | 
 | 198 |                                  what_failed='Failed to stat') | 
 | 199 |                     continue | 
 | 200 |             else: | 
 | 201 |                 stats = self.execute_rpc('get_hosts', hostname=host) | 
 | 202 |                 if len(stats) == 0: | 
 | 203 |                     self.failure('Unknown host %s' % host, item=host, | 
 | 204 |                                  what_failed='Failed to stat') | 
 | 205 |                     continue | 
 | 206 |             existing_hosts.extend(stats) | 
 | 207 |  | 
 | 208 |         for stat in existing_hosts: | 
 | 209 |             host = stat['hostname'] | 
 | 210 |             # The host exists, these should succeed | 
 | 211 |             acls = self.execute_rpc('get_acl_groups', hosts__hostname=host) | 
 | 212 |  | 
 | 213 |             labels = self.execute_rpc('get_labels', host__hostname=host) | 
 | 214 |             results.append ([[stat], acls, labels]) | 
 | 215 |         return results | 
 | 216 |  | 
 | 217 |  | 
 | 218 |     def output(self, results): | 
 | 219 |         for stats, acls, labels in results: | 
 | 220 |             print '-'*5 | 
 | 221 |             self.print_fields(stats, | 
 | 222 |                               keys=['hostname', 'platform', | 
| mbligh | e163b03 | 2008-10-18 14:30:27 +0000 | [diff] [blame] | 223 |                                     'status', 'locked', 'locked_by', | 
 | 224 |                                     'lock_time', 'protection',]) | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 225 |             self.print_by_ids(acls, 'ACLs', line_before=True) | 
 | 226 |             labels = self._cleanup_labels(labels) | 
 | 227 |             self.print_by_ids(labels, 'Labels', line_before=True) | 
 | 228 |  | 
 | 229 |  | 
 | 230 | class host_jobs(host): | 
| mbligh | 1494eca | 2008-08-13 21:24:22 +0000 | [diff] [blame] | 231 |     """atest host jobs [--max-query] --mlist <file>|<hosts>""" | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 232 |     usage_action = 'jobs' | 
 | 233 |  | 
| mbligh | 6996fe8 | 2008-08-13 00:32:27 +0000 | [diff] [blame] | 234 |     def __init__(self): | 
 | 235 |         super(host_jobs, self).__init__() | 
 | 236 |         self.parser.add_option('-q', '--max-query', | 
 | 237 |                                help='Limits the number of results ' | 
 | 238 |                                '(20 by default)', | 
 | 239 |                                type='int', default=20) | 
 | 240 |  | 
 | 241 |  | 
 | 242 |     def parse(self): | 
 | 243 |         """Consume the specific options""" | 
 | 244 |         (options, leftover) = super(host_jobs, self).parse(req_items=None) | 
 | 245 |         self.max_queries = options.max_query | 
 | 246 |         return (options, leftover) | 
 | 247 |  | 
 | 248 |  | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 249 |     def execute(self): | 
| mbligh | 6996fe8 | 2008-08-13 00:32:27 +0000 | [diff] [blame] | 250 |         socket.setdefaulttimeout(topic_common.LIST_SOCKET_TIMEOUT) | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 251 |         results = [] | 
 | 252 |         real_hosts = [] | 
 | 253 |         for host in self.hosts: | 
 | 254 |             if host.endswith('*'): | 
 | 255 |                 stats = self.execute_rpc('get_hosts', | 
 | 256 |                                          hostname__startswith=host.rstrip('*')) | 
 | 257 |                 if len(stats) == 0: | 
 | 258 |                     self.failure('No host matching %s' % host, item=host, | 
 | 259 |                                  what_failed='Failed to stat') | 
 | 260 |                 [real_hosts.append(stat['hostname']) for stat in stats] | 
 | 261 |             else: | 
 | 262 |                 real_hosts.append(host) | 
 | 263 |  | 
 | 264 |         for host in real_hosts: | 
 | 265 |             queue_entries = self.execute_rpc('get_host_queue_entries', | 
| mbligh | 6996fe8 | 2008-08-13 00:32:27 +0000 | [diff] [blame] | 266 |                                              host__hostname=host, | 
| mbligh | 1494eca | 2008-08-13 21:24:22 +0000 | [diff] [blame] | 267 |                                              query_limit=self.max_queries, | 
 | 268 |                                              sort_by=['-job_id']) | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 269 |             jobs = [] | 
 | 270 |             for entry in queue_entries: | 
 | 271 |                 job = {'job_id': entry['job']['id'], | 
 | 272 |                        'job_owner': entry['job']['owner'], | 
 | 273 |                        'job_name': entry['job']['name'], | 
 | 274 |                        'status': entry['status']} | 
 | 275 |                 jobs.append(job) | 
 | 276 |             results.append((host, jobs)) | 
 | 277 |         return results | 
 | 278 |  | 
 | 279 |  | 
 | 280 |     def output(self, results): | 
 | 281 |         for host, jobs in results: | 
 | 282 |             print '-'*5 | 
 | 283 |             print 'Hostname: %s' % host | 
 | 284 |             self.print_table(jobs, keys_header=['job_id', | 
 | 285 |                                                  'job_owner', | 
 | 286 |                                                  'job_name', | 
 | 287 |                                                  'status']) | 
 | 288 |  | 
 | 289 |  | 
 | 290 | class host_mod(host): | 
 | 291 |     """atest host mod --lock|--unlock|--ready|--dead | 
 | 292 |     --mlist <file>|<hosts>""" | 
 | 293 |     usage_action = 'mod' | 
 | 294 |  | 
 | 295 |     def __init__(self): | 
 | 296 |         """Add the options specific to the mod action""" | 
 | 297 |         self.data = {} | 
 | 298 |         self.messages = [] | 
 | 299 |         super(host_mod, self).__init__() | 
 | 300 |         self.parser.add_option('-y', '--ready', | 
 | 301 |                                help='Mark this host ready', | 
 | 302 |                                action='store_true') | 
 | 303 |         self.parser.add_option('-d', '--dead', | 
 | 304 |                                help='Mark this host dead', | 
 | 305 |                                action='store_true') | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 306 |         self.parser.add_option('-l', '--lock', | 
 | 307 |                                help='Lock hosts', | 
 | 308 |                                action='store_true') | 
 | 309 |         self.parser.add_option('-u', '--unlock', | 
 | 310 |                                help='Unlock hosts', | 
 | 311 |                                action='store_true') | 
| mbligh | e163b03 | 2008-10-18 14:30:27 +0000 | [diff] [blame] | 312 |         self.parser.add_option('-p', '--protection', type='choice', | 
 | 313 |                                help='Set the protection level on a host.  Must ' | 
 | 314 |                                'be one of: "Repair filesystem only", ' | 
 | 315 |                                '"No protection", or "Do not repair"', | 
 | 316 |                                choices=('No protection', 'Do not repair', | 
 | 317 |                                         'Repair filesystem only')) | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 318 |  | 
 | 319 |  | 
 | 320 |     def parse(self): | 
 | 321 |         """Consume the specific options""" | 
 | 322 |         (options, leftover) = super(host_mod, self).parse() | 
 | 323 |  | 
 | 324 |         self._parse_lock_options(options) | 
 | 325 |  | 
 | 326 |         if options.ready and options.dead: | 
 | 327 |             self.invalid_syntax('Only specify one of ' | 
 | 328 |                                 '--ready and --dead') | 
 | 329 |  | 
 | 330 |         if options.ready: | 
 | 331 |             self.data['status'] = 'Ready' | 
 | 332 |             self.messages.append('Set status to Ready for host') | 
 | 333 |         elif options.dead: | 
 | 334 |             self.data['status'] = 'Dead' | 
 | 335 |             self.messages.append('Set status to Dead for host') | 
 | 336 |  | 
| mbligh | e163b03 | 2008-10-18 14:30:27 +0000 | [diff] [blame] | 337 |         if options.protection: | 
 | 338 |             self.data['protection'] = options.protection | 
 | 339 |  | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 340 |         if len(self.data) == 0: | 
 | 341 |             self.invalid_syntax('No modification requested') | 
 | 342 |         return (options, leftover) | 
 | 343 |  | 
 | 344 |  | 
 | 345 |     def execute(self): | 
 | 346 |         successes = [] | 
 | 347 |         for host in self.hosts: | 
| mbligh | 6eca460 | 2009-01-07 16:48:50 +0000 | [diff] [blame] | 348 |             try: | 
 | 349 |                 res = self.execute_rpc('modify_host', item=host, | 
 | 350 |                                        id=host, **self.data) | 
 | 351 |                 # TODO: Make the AFE return True or False, | 
 | 352 |                 # especially for lock | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 353 |                 successes.append(host) | 
| mbligh | 6eca460 | 2009-01-07 16:48:50 +0000 | [diff] [blame] | 354 |             except topic_common.CliError, full_error: | 
 | 355 |                 # Already logged by execute_rpc() | 
 | 356 |                 pass | 
 | 357 |  | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 358 |         return successes | 
 | 359 |  | 
 | 360 |  | 
 | 361 |     def output(self, hosts): | 
 | 362 |         for msg in self.messages: | 
 | 363 |             self.print_wrapped(msg, hosts) | 
 | 364 |  | 
 | 365 |  | 
 | 366 |  | 
 | 367 | class host_create(host): | 
 | 368 |     """atest host create [--lock|--unlock --platform <arch> | 
 | 369 |     --labels <labels>|--blist <label_file> | 
 | 370 |     --acls <acls>|--alist <acl_file> | 
 | 371 |     --mlist <mach_file>] <hosts>""" | 
 | 372 |     usage_action = 'create' | 
 | 373 |  | 
 | 374 |     def __init__(self): | 
 | 375 |         self.messages = [] | 
 | 376 |         super(host_create, self).__init__() | 
 | 377 |         self.parser.add_option('-l', '--lock', | 
 | 378 |                                help='Create the hosts as locked', | 
| mbligh | 719e14a | 2008-12-04 01:17:08 +0000 | [diff] [blame] | 379 |                                action='store_true', default=False) | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 380 |         self.parser.add_option('-u', '--unlock', | 
 | 381 |                                help='Create the hosts as ' | 
 | 382 |                                'unlocked (default)', | 
 | 383 |                                action='store_true') | 
 | 384 |         self.parser.add_option('-t', '--platform', | 
 | 385 |                                help='Sets the platform label') | 
 | 386 |         self.parser.add_option('-b', '--labels', | 
 | 387 |                                help='Comma separated list of labels') | 
 | 388 |         self.parser.add_option('-B', '--blist', | 
 | 389 |                                help='File listing the labels', | 
 | 390 |                                type='string', | 
 | 391 |                                metavar='LABEL_FLIST') | 
 | 392 |         self.parser.add_option('-a', '--acls', | 
 | 393 |                                help='Comma separated list of ACLs') | 
 | 394 |         self.parser.add_option('-A', '--alist', | 
 | 395 |                                help='File listing the acls', | 
 | 396 |                                type='string', | 
 | 397 |                                metavar='ACL_FLIST') | 
 | 398 |  | 
 | 399 |  | 
 | 400 |     def parse(self): | 
 | 401 |         flists = [('labels', 'blist', 'labels', False), | 
 | 402 |                   ('acls', 'alist', 'acls', False)] | 
 | 403 |         (options, leftover) = super(host_create, self).parse(flists) | 
 | 404 |  | 
 | 405 |         self._parse_lock_options(options) | 
| mbligh | 719e14a | 2008-12-04 01:17:08 +0000 | [diff] [blame] | 406 |         self.locked = options.lock | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 407 |         self.platform = getattr(options, 'platform', None) | 
 | 408 |         return (options, leftover) | 
 | 409 |  | 
 | 410 |  | 
 | 411 |     def _execute_add_one_host(self, host): | 
| mbligh | 719e14a | 2008-12-04 01:17:08 +0000 | [diff] [blame] | 412 |         # Always add the hosts as locked to avoid the host | 
 | 413 |         # being picked up by the scheduler before it's ACL'ed  | 
 | 414 |         self.data['locked'] = True | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 415 |         self.execute_rpc('add_host', hostname=host, | 
 | 416 |                          status="Ready", **self.data) | 
 | 417 |  | 
 | 418 |         # Now add the platform label | 
 | 419 |         labels = self.labels[:] | 
 | 420 |         if self.platform: | 
 | 421 |             labels.append(self.platform) | 
 | 422 |         if len (labels): | 
 | 423 |             self.execute_rpc('host_add_labels', id=host, labels=labels) | 
 | 424 |  | 
 | 425 |  | 
 | 426 |     def execute(self): | 
 | 427 |         # We need to check if these labels & ACLs exist, | 
 | 428 |         # and create them if not. | 
 | 429 |         if self.platform: | 
 | 430 |             self.check_and_create_items('get_labels', 'add_label', | 
 | 431 |                                         [self.platform], | 
 | 432 |                                         platform=True) | 
 | 433 |  | 
 | 434 |         if self.labels: | 
 | 435 |             self.check_and_create_items('get_labels', 'add_label', | 
 | 436 |                                         self.labels, | 
 | 437 |                                         platform=False) | 
 | 438 |  | 
 | 439 |         if self.acls: | 
 | 440 |             self.check_and_create_items('get_acl_groups', | 
 | 441 |                                         'add_acl_group', | 
 | 442 |                                         self.acls) | 
 | 443 |  | 
 | 444 |         success = self.site_create_hosts_hook() | 
 | 445 |  | 
 | 446 |         if len(success): | 
 | 447 |             for acl in self.acls: | 
 | 448 |                 self.execute_rpc('acl_group_add_hosts', id=acl, hosts=success) | 
| mbligh | 719e14a | 2008-12-04 01:17:08 +0000 | [diff] [blame] | 449 |  | 
 | 450 |             if not self.locked: | 
 | 451 |                 for host in success: | 
 | 452 |                     self.execute_rpc('modify_host', id=host, locked=False) | 
| mbligh | be630eb | 2008-08-01 16:41:48 +0000 | [diff] [blame] | 453 |         return success | 
 | 454 |  | 
 | 455 |  | 
 | 456 |     def site_create_hosts_hook(self): | 
 | 457 |         success = [] | 
 | 458 |         for host in self.hosts: | 
 | 459 |             try: | 
 | 460 |                 self._execute_add_one_host(host) | 
 | 461 |                 success.append(host) | 
 | 462 |             except topic_common.CliError: | 
 | 463 |                 pass | 
 | 464 |  | 
 | 465 |         return success | 
 | 466 |  | 
 | 467 |  | 
 | 468 |     def output(self, hosts): | 
 | 469 |         self.print_wrapped('Added host', hosts) | 
 | 470 |  | 
 | 471 |  | 
 | 472 | class host_delete(action_common.atest_delete, host): | 
 | 473 |     """atest host delete [--mlist <mach_file>] <hosts>""" | 
 | 474 |     pass |