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