1#!/usr/bin/python2 2# 3# Copyright 2008 Google Inc. All Rights Reserved. 4 5"""Test for host.""" 6 7# pylint: disable=missing-docstring 8 9import sys 10import unittest 11 12import mock 13 14import common 15from autotest_lib.cli import cli_mock, host 16from autotest_lib.client.common_lib import control_data 17from autotest_lib.server import hosts 18CLIENT = control_data.CONTROL_TYPE_NAMES.CLIENT 19SERVER = control_data.CONTROL_TYPE_NAMES.SERVER 20 21class host_ut(cli_mock.cli_unittest): 22 def test_parse_lock_options_both_set(self): 23 hh = host.host() 24 class opt(object): 25 lock = True 26 unlock = True 27 options = opt() 28 self.usage = "unused" 29 sys.exit.expect_call(1).and_raises(cli_mock.ExitException) 30 self.god.mock_io() 31 self.assertRaises(cli_mock.ExitException, 32 hh._parse_lock_options, options) 33 self.god.unmock_io() 34 35 36 def test_cleanup_labels_with_platform(self): 37 labels = ['l0', 'l1', 'l2', 'p0', 'l3'] 38 hh = host.host() 39 self.assertEqual(['l0', 'l1', 'l2', 'l3'], 40 hh._cleanup_labels(labels, 'p0')) 41 42 43 def test_cleanup_labels_no_platform(self): 44 labels = ['l0', 'l1', 'l2', 'l3'] 45 hh = host.host() 46 self.assertEqual(['l0', 'l1', 'l2', 'l3'], 47 hh._cleanup_labels(labels)) 48 49 50 def test_cleanup_labels_with_non_avail_platform(self): 51 labels = ['l0', 'l1', 'l2', 'l3'] 52 hh = host.host() 53 self.assertEqual(['l0', 'l1', 'l2', 'l3'], 54 hh._cleanup_labels(labels, 'p0')) 55 56 57class host_list_unittest(cli_mock.cli_unittest): 58 def test_parse_host_not_required(self): 59 hl = host.host_list() 60 sys.argv = ['atest'] 61 (options, leftover) = hl.parse() 62 self.assertEqual([], hl.hosts) 63 self.assertEqual([], leftover) 64 65 66 def test_parse_with_hosts(self): 67 hl = host.host_list() 68 mfile = cli_mock.create_file('host0\nhost3\nhost4\n') 69 sys.argv = ['atest', 'host1', '--mlist', mfile.name, 'host3'] 70 (options, leftover) = hl.parse() 71 self.assertEqualNoOrder(['host0', 'host1','host3', 'host4'], 72 hl.hosts) 73 self.assertEqual(leftover, []) 74 mfile.clean() 75 76 77 def test_parse_with_labels(self): 78 hl = host.host_list() 79 sys.argv = ['atest', '--label', 'label0'] 80 (options, leftover) = hl.parse() 81 self.assertEqual(['label0'], hl.labels) 82 self.assertEqual(leftover, []) 83 84 85 def test_parse_with_multi_labels(self): 86 hl = host.host_list() 87 sys.argv = ['atest', '--label', 'label0,label2'] 88 (options, leftover) = hl.parse() 89 self.assertEqualNoOrder(['label0', 'label2'], hl.labels) 90 self.assertEqual(leftover, []) 91 92 93 def test_parse_with_escaped_commas_label(self): 94 hl = host.host_list() 95 sys.argv = ['atest', '--label', 'label\\,0'] 96 (options, leftover) = hl.parse() 97 self.assertEqual(['label,0'], hl.labels) 98 self.assertEqual(leftover, []) 99 100 101 def test_parse_with_escaped_commas_multi_labels(self): 102 hl = host.host_list() 103 sys.argv = ['atest', '--label', 'label\\,0,label\\,2'] 104 (options, leftover) = hl.parse() 105 self.assertEqualNoOrder(['label,0', 'label,2'], hl.labels) 106 self.assertEqual(leftover, []) 107 108 109 def test_parse_with_both(self): 110 hl = host.host_list() 111 mfile = cli_mock.create_file('host0\nhost3\nhost4\n') 112 sys.argv = ['atest', 'host1', '--mlist', mfile.name, 'host3', 113 '--label', 'label0'] 114 (options, leftover) = hl.parse() 115 self.assertEqualNoOrder(['host0', 'host1','host3', 'host4'], 116 hl.hosts) 117 self.assertEqual(['label0'], hl.labels) 118 self.assertEqual(leftover, []) 119 mfile.clean() 120 121 122 def test_execute_list_all_no_labels(self): 123 self.run_cmd(argv=['atest', 'host', 'list'], 124 rpcs=[('get_hosts', {}, 125 True, 126 [{u'status': u'Ready', 127 u'hostname': u'host0', 128 u'locked': False, 129 u'locked_by': 'user0', 130 u'lock_time': u'2008-07-23 12:54:15', 131 u'lock_reason': u'', 132 u'labels': [], 133 u'invalid': False, 134 u'platform': None, 135 u'shard': None, 136 u'id': 1}, 137 {u'status': u'Ready', 138 u'hostname': u'host1', 139 u'locked': True, 140 u'locked_by': 'user0', 141 u'lock_time': u'2008-07-23 12:54:15', 142 u'lock_reason': u'', 143 u'labels': [u'plat1'], 144 u'invalid': False, 145 u'platform': u'plat1', 146 u'shard': None, 147 u'id': 2}])], 148 out_words_ok=['host0', 'host1', 'Ready', 149 'plat1', 'False', 'True', 'None']) 150 151 152 def test_execute_list_all_with_labels(self): 153 self.run_cmd(argv=['atest', 'host', 'list'], 154 rpcs=[('get_hosts', {}, 155 True, 156 [{u'status': u'Ready', 157 u'hostname': u'host0', 158 u'locked': False, 159 u'locked_by': 'user0', 160 u'lock_time': u'2008-07-23 12:54:15', 161 u'lock_reason': u'', 162 u'labels': [u'label0', u'label1'], 163 u'invalid': False, 164 u'platform': None, 165 u'shard': None, 166 u'id': 1}, 167 {u'status': u'Ready', 168 u'hostname': u'host1', 169 u'locked': True, 170 u'locked_by': 'user0', 171 u'lock_time': u'2008-07-23 12:54:15', 172 u'lock_reason': u'', 173 u'labels': [u'label2', u'label3', u'plat1'], 174 u'invalid': False, 175 u'shard': None, 176 u'platform': u'plat1', 177 u'id': 2}])], 178 out_words_ok=['host0', 'host1', 'Ready', 'plat1', 179 'label0', 'label1', 'label2', 'label3', 180 'False', 'True', 'None']) 181 182 183 def test_execute_list_filter_one_host(self): 184 self.run_cmd(argv=['atest', 'host', 'list', 'host1'], 185 rpcs=[('get_hosts', {'hostname__in': ['host1']}, 186 True, 187 [{u'status': u'Ready', 188 u'hostname': u'host1', 189 u'locked': True, 190 u'locked_by': 'user0', 191 u'lock_time': u'2008-07-23 12:54:15', 192 u'lock_reason': u'', 193 u'labels': [u'label2', u'label3', u'plat1'], 194 u'invalid': False, 195 u'platform': u'plat1', 196 u'shard': None, 197 u'id': 2}])], 198 out_words_ok=['host1', 'Ready', 'plat1', 199 'label2', 'label3', 'True', 'None'], 200 out_words_no=['host0', 'host2', 201 'label1', 'False']) 202 203 204 def test_execute_list_filter_two_hosts(self): 205 mfile = cli_mock.create_file('host2') 206 self.run_cmd(argv=['atest', 'host', 'list', 'host1', 207 '--mlist', mfile.name], 208 # This is a bit fragile as the list order may change... 209 rpcs=[('get_hosts', {'hostname__in': ['host2', 'host1']}, 210 True, 211 [{u'status': u'Ready', 212 u'hostname': u'host1', 213 u'locked': True, 214 u'locked_by': 'user0', 215 u'lock_time': u'2008-07-23 12:54:15', 216 u'lock_reason': u'', 217 u'labels': [u'label2', u'label3', u'plat1'], 218 u'invalid': False, 219 u'platform': u'plat1', 220 u'shard': None, 221 u'id': 2}, 222 {u'status': u'Ready', 223 u'hostname': u'host2', 224 u'locked': True, 225 u'locked_by': 'user0', 226 u'lock_time': u'2008-07-23 12:54:15', 227 u'lock_reason': u'', 228 u'labels': [u'label3', u'plat1'], 229 u'invalid': False, 230 u'shard': None, 231 u'platform': u'plat1', 232 u'id': 3}])], 233 out_words_ok=['host1', 'Ready', 'plat1', 234 'label2', 'label3', 'True', 235 'host2', 'None'], 236 out_words_no=['host0', 'label1', 'False']) 237 mfile.clean() 238 239 240 def test_execute_list_filter_two_hosts_one_not_found(self): 241 mfile = cli_mock.create_file('host2') 242 self.run_cmd(argv=['atest', 'host', 'list', 'host1', 243 '--mlist', mfile.name], 244 # This is a bit fragile as the list order may change... 245 rpcs=[('get_hosts', {'hostname__in': ['host2', 'host1']}, 246 True, 247 [{u'status': u'Ready', 248 u'hostname': u'host2', 249 u'locked': True, 250 u'locked_by': 'user0', 251 u'lock_time': u'2008-07-23 12:54:15', 252 u'lock_reason': u'', 253 u'labels': [u'label3', u'plat1'], 254 u'invalid': False, 255 u'shard': None, 256 u'platform': u'plat1', 257 u'id': 3}])], 258 out_words_ok=['Ready', 'plat1', 259 'label3', 'True', 'None'], 260 out_words_no=['host1', 'False'], 261 err_words_ok=['host1']) 262 mfile.clean() 263 264 265 def test_execute_list_filter_two_hosts_none_found(self): 266 self.run_cmd(argv=['atest', 'host', 'list', 267 'host1', 'host2'], 268 # This is a bit fragile as the list order may change... 269 rpcs=[('get_hosts', {'hostname__in': ['host2', 'host1']}, 270 True, 271 [])], 272 out_words_ok=[], 273 out_words_no=['Hostname', 'Status'], 274 err_words_ok=['Unknown', 'host1', 'host2']) 275 276 277 def test_execute_list_filter_label(self): 278 self.run_cmd(argv=['atest', 'host', 'list', 279 '-b', 'label3'], 280 rpcs=[('get_hosts', {'labels__name__in': ['label3']}, 281 True, 282 [{u'status': u'Ready', 283 u'hostname': u'host1', 284 u'locked': True, 285 u'locked_by': 'user0', 286 u'lock_time': u'2008-07-23 12:54:15', 287 u'lock_reason': u'', 288 u'labels': [u'label2', u'label3', u'plat1'], 289 u'invalid': False, 290 u'platform': u'plat1', 291 u'shard': None, 292 u'id': 2}, 293 {u'status': u'Ready', 294 u'hostname': u'host2', 295 u'locked': True, 296 u'locked_by': 'user0', 297 u'lock_time': u'2008-07-23 12:54:15', 298 u'lock_reason': u'', 299 u'labels': [u'label3', u'plat1'], 300 u'invalid': False, 301 u'shard': None, 302 u'platform': u'plat1', 303 u'id': 3}])], 304 out_words_ok=['host1', 'Ready', 'plat1', 305 'label2', 'label3', 'True', 306 'host2', 'None'], 307 out_words_no=['host0', 'label1', 'False']) 308 309 310 def test_execute_list_filter_multi_labels(self): 311 self.run_cmd(argv=['atest', 'host', 'list', 312 '-b', 'label3,label2'], 313 rpcs=[('get_hosts', {'multiple_labels': ['label2', 314 'label3']}, 315 True, 316 [{u'status': u'Ready', 317 u'hostname': u'host1', 318 u'locked': True, 319 u'locked_by': 'user0', 320 u'lock_time': u'2008-07-23 12:54:15', 321 u'lock_reason': u'', 322 u'labels': [u'label2', u'label3', u'plat0'], 323 u'invalid': False, 324 u'shard': None, 325 u'platform': u'plat0', 326 u'id': 2}, 327 {u'status': u'Ready', 328 u'hostname': u'host3', 329 u'locked': True, 330 u'locked_by': 'user0', 331 u'lock_time': u'2008-07-23 12:54:15', 332 u'lock_reason': u'', 333 u'labels': [u'label3', u'label2', u'plat2'], 334 u'invalid': False, 335 u'shard': None, 336 u'platform': u'plat2', 337 u'id': 4}])], 338 out_words_ok=['host1', 'host3', 'Ready', 'plat0', 339 'label2', 'label3', 'plat2', 'None'], 340 out_words_no=['host2', 'False', 'plat1']) 341 342 343 def test_execute_list_filter_three_labels(self): 344 self.run_cmd(argv=['atest', 'host', 'list', 345 '-b', 'label3,label2'], 346 rpcs=[('get_hosts', {'multiple_labels': ['label2', 347 'label3']}, 348 True, 349 [{u'status': u'Ready', 350 u'hostname': u'host2', 351 u'locked': True, 352 u'locked_by': 'user0', 353 u'lock_time': u'2008-07-23 12:54:15', 354 u'lock_reason': u'', 355 u'labels': [u'label3', u'label2', u'plat1'], 356 u'invalid': False, 357 u'platform': u'plat1', 358 u'shard': None, 359 u'id': 3}])], 360 out_words_ok=['host2', 'plat1', 361 'label2', 'label3', 'None'], 362 out_words_no=['host1', 'host3']) 363 364 365 def test_execute_list_filter_wild_labels(self): 366 self.run_cmd(argv=['atest', 'host', 'list', 367 '-b', 'label*'], 368 rpcs=[('get_hosts', 369 {'labels__name__startswith': 'label'}, 370 True, 371 [{u'status': u'Ready', 372 u'hostname': u'host2', 373 u'locked': 1, 374 u'shard': None, 375 u'locked_by': 'user0', 376 u'lock_time': u'2008-07-23 12:54:15', 377 u'lock_reason': u'', 378 u'labels': [u'label3', u'label2', u'plat1'], 379 u'invalid': 0, 380 u'platform': u'plat1', 381 u'id': 3}])], 382 out_words_ok=['host2', 'plat1', 383 'label2', 'label3', 'None'], 384 out_words_no=['host1', 'host3']) 385 386 387 def test_execute_list_filter_multi_labels_no_results(self): 388 self.run_cmd(argv=['atest', 'host', 'list', 389 '-b', 'label3,label2, '], 390 rpcs=[('get_hosts', {'multiple_labels': ['label2', 391 'label3']}, 392 True, 393 [])], 394 out_words_ok=[], 395 out_words_no=['host1', 'host2', 'host3', 396 'label2', 'label3']) 397 398 399 def test_execute_list_filter_label_and_hosts(self): 400 self.run_cmd(argv=['atest', 'host', 'list', 'host1', 401 '-b', 'label3', 'host2'], 402 rpcs=[('get_hosts', {'labels__name__in': ['label3'], 403 'hostname__in': ['host2', 'host1']}, 404 True, 405 [{u'status': u'Ready', 406 u'hostname': u'host1', 407 u'locked': True, 408 u'locked_by': 'user0', 409 u'lock_time': u'2008-07-23 12:54:15', 410 u'labels': [u'label2', u'label3', u'plat1'], 411 u'lock_reason': u'', 412 u'invalid': False, 413 u'platform': u'plat1', 414 u'shard': None, 415 u'id': 2}, 416 {u'status': u'Ready', 417 u'hostname': u'host2', 418 u'locked': True, 419 u'locked_by': 'user0', 420 u'lock_time': u'2008-07-23 12:54:15', 421 u'lock_reason': u'', 422 u'labels': [u'label3', u'plat1'], 423 u'invalid': False, 424 u'shard': None, 425 u'platform': u'plat1', 426 u'id': 3}])], 427 out_words_ok=['host1', 'Ready', 'plat1', 428 'label2', 'label3', 'True', 429 'host2', 'None'], 430 out_words_no=['host0', 'label1', 'False']) 431 432 433 def test_execute_list_filter_label_and_hosts_none(self): 434 self.run_cmd(argv=['atest', 'host', 'list', 'host1', 435 '-b', 'label3', 'host2'], 436 rpcs=[('get_hosts', {'labels__name__in': ['label3'], 437 'hostname__in': ['host2', 'host1']}, 438 True, 439 [])], 440 out_words_ok=[], 441 out_words_no=['Hostname', 'Status'], 442 err_words_ok=['Unknown', 'host1', 'host2']) 443 444 445 def test_execute_list_filter_status(self): 446 self.run_cmd(argv=['atest', 'host', 'list', 447 '-s', 'Ready'], 448 rpcs=[('get_hosts', {'status__in': ['Ready']}, 449 True, 450 [{u'status': u'Ready', 451 u'hostname': u'host1', 452 u'locked': True, 453 u'locked_by': 'user0', 454 u'lock_time': u'2008-07-23 12:54:15', 455 u'lock_reason': u'', 456 u'labels': [u'label2', u'label3', u'plat1'], 457 u'invalid': False, 458 u'platform': u'plat1', 459 u'shard': None, 460 u'id': 2}, 461 {u'status': u'Ready', 462 u'hostname': u'host2', 463 u'locked': True, 464 u'locked_by': 'user0', 465 u'lock_time': u'2008-07-23 12:54:15', 466 u'lock_reason': u'', 467 u'labels': [u'label3', u'plat1'], 468 u'invalid': False, 469 u'shard': None, 470 u'platform': u'plat1', 471 u'id': 3}])], 472 out_words_ok=['host1', 'Ready', 'plat1', 473 'label2', 'label3', 'True', 474 'host2', 'None'], 475 out_words_no=['host0', 'label1', 'False']) 476 477 478 479 def test_execute_list_filter_status_and_hosts(self): 480 self.run_cmd(argv=['atest', 'host', 'list', 'host1', 481 '-s', 'Ready', 'host2'], 482 rpcs=[('get_hosts', {'status__in': ['Ready'], 483 'hostname__in': ['host2', 'host1']}, 484 True, 485 [{u'status': u'Ready', 486 u'hostname': u'host1', 487 u'locked': True, 488 u'locked_by': 'user0', 489 u'lock_time': u'2008-07-23 12:54:15', 490 u'lock_reason': u'', 491 u'labels': [u'label2', u'label3', u'plat1'], 492 u'invalid': False, 493 u'platform': u'plat1', 494 u'shard': None, 495 u'id': 2}, 496 {u'status': u'Ready', 497 u'hostname': u'host2', 498 u'locked': True, 499 u'locked_by': 'user0', 500 u'lock_time': u'2008-07-23 12:54:15', 501 u'lock_reason': u'', 502 u'labels': [u'label3', u'plat1'], 503 u'invalid': False, 504 u'shard': None, 505 u'platform': u'plat1', 506 u'id': 3}])], 507 out_words_ok=['host1', 'Ready', 'plat1', 508 'label2', 'label3', 'True', 509 'host2', 'None'], 510 out_words_no=['host0', 'label1', 'False']) 511 512 513 def test_execute_list_filter_status_and_hosts_none(self): 514 self.run_cmd(argv=['atest', 'host', 'list', 'host1', 515 '--status', 'Repair', 516 'host2'], 517 rpcs=[('get_hosts', {'status__in': ['Repair'], 518 'hostname__in': ['host2', 'host1']}, 519 True, 520 [])], 521 out_words_ok=[], 522 out_words_no=['Hostname', 'Status'], 523 err_words_ok=['Unknown', 'host2']) 524 525 526 def test_execute_list_filter_statuses_and_hosts_none(self): 527 self.run_cmd(argv=['atest', 'host', 'list', 'host1', 528 '--status', 'Repair', 529 'host2'], 530 rpcs=[('get_hosts', {'status__in': ['Repair'], 531 'hostname__in': ['host2', 'host1']}, 532 True, 533 [])], 534 out_words_ok=[], 535 out_words_no=['Hostname', 'Status'], 536 err_words_ok=['Unknown', 'host2']) 537 538 539 def test_execute_list_filter_locked(self): 540 self.run_cmd(argv=['atest', 'host', 'list', 'host1', 541 '--locked', 'host2'], 542 rpcs=[('get_hosts', {'locked': True, 543 'hostname__in': ['host2', 'host1']}, 544 True, 545 [{u'status': u'Ready', 546 u'hostname': u'host1', 547 u'locked': True, 548 u'locked_by': 'user0', 549 u'lock_reason': u'', 550 u'lock_time': u'2008-07-23 12:54:15', 551 u'labels': [u'label2', u'label3', u'plat1'], 552 u'invalid': False, 553 u'platform': u'plat1', 554 u'shard': None, 555 u'id': 2}, 556 {u'status': u'Ready', 557 u'hostname': u'host2', 558 u'locked': True, 559 u'locked_by': 'user0', 560 u'lock_reason': u'', 561 u'lock_time': u'2008-07-23 12:54:15', 562 u'labels': [u'label3', u'plat1'], 563 u'invalid': False, 564 u'shard': None, 565 u'platform': u'plat1', 566 u'id': 3}])], 567 out_words_ok=['host1', 'Ready', 'plat1', 568 'label2', 'label3', 'True', 569 'host2', 'None'], 570 out_words_no=['host0', 'label1', 'False']) 571 572 573 def test_execute_list_filter_unlocked(self): 574 self.run_cmd(argv=['atest', 'host', 'list', 575 '--unlocked'], 576 rpcs=[('get_hosts', {'locked': False}, 577 True, 578 [{u'status': u'Ready', 579 u'hostname': u'host1', 580 u'locked': False, 581 u'locked_by': 'user0', 582 u'lock_time': u'2008-07-23 12:54:15', 583 u'lock_reason': u'', 584 u'labels': [u'label2', u'label3', u'plat1'], 585 u'invalid': False, 586 u'shard': None, 587 u'platform': u'plat1', 588 u'id': 2}, 589 {u'status': u'Ready', 590 u'hostname': u'host2', 591 u'locked': False, 592 u'locked_by': 'user0', 593 u'lock_time': u'2008-07-23 12:54:15', 594 u'lock_reason': u'', 595 u'labels': [u'label3', u'plat1'], 596 u'invalid': False, 597 u'shard': None, 598 u'platform': u'plat1', 599 u'id': 3}])], 600 out_words_ok=['host1', 'Ready', 'plat1', 601 'label2', 'label3', 'False', 602 'host2', 'None'], 603 out_words_no=['host0', 'label1', 'True']) 604 605 606class host_stat_unittest(cli_mock.cli_unittest): 607 def test_execute_stat_two_hosts(self): 608 # The order of RPCs between host1 and host0 could change... 609 self.run_cmd(argv=['atest', 'host', 'stat', 'host0', 'host1'], 610 rpcs=[('get_hosts', {'hostname': 'host1'}, 611 True, 612 [{u'status': u'Ready', 613 u'hostname': u'host1', 614 u'locked': True, 615 u'lock_time': u'2008-07-23 12:54:15', 616 u'locked_by': 'user0', 617 u'lock_reason': u'', 618 u'protection': 'No protection', 619 u'labels': [u'label3', u'plat1'], 620 u'invalid': False, 621 u'shard': None, 622 u'platform': u'plat1', 623 u'id': 3, 624 u'attributes': {}}]), 625 ('get_hosts', {'hostname': 'host0'}, 626 True, 627 [{u'status': u'Ready', 628 u'hostname': u'host0', 629 u'locked': False, 630 u'locked_by': 'user0', 631 u'lock_time': u'2008-07-23 12:54:15', 632 u'lock_reason': u'', 633 u'protection': u'No protection', 634 u'labels': [u'label0', u'plat0'], 635 u'invalid': False, 636 u'shard': None, 637 u'platform': u'plat0', 638 u'id': 2, 639 u'attributes': {}}]), 640 ('get_acl_groups', {'hosts__hostname': 'host1'}, 641 True, 642 [{u'description': u'', 643 u'hosts': [u'host0', u'host1'], 644 u'id': 1, 645 u'name': u'Everyone', 646 u'users': [u'user2', u'debug_user', u'user0']}]), 647 ('get_labels', {'host__hostname': 'host1'}, 648 True, 649 [{u'id': 2, 650 u'platform': 1, 651 u'name': u'jme', 652 u'invalid': False, 653 u'kernel_config': u''}]), 654 ('get_acl_groups', {'hosts__hostname': 'host0'}, 655 True, 656 [{u'description': u'', 657 u'hosts': [u'host0', u'host1'], 658 u'id': 1, 659 u'name': u'Everyone', 660 u'users': [u'user0', u'debug_user']}, 661 {u'description': u'myacl0', 662 u'hosts': [u'host0'], 663 u'id': 2, 664 u'name': u'acl0', 665 u'users': [u'user0']}]), 666 ('get_labels', {'host__hostname': 'host0'}, 667 True, 668 [{u'id': 4, 669 u'platform': 0, 670 u'name': u'label0', 671 u'invalid': False, 672 u'kernel_config': u''}, 673 {u'id': 5, 674 u'platform': 1, 675 u'name': u'plat0', 676 u'invalid': False, 677 u'kernel_config': u''}])], 678 out_words_ok=['host0', 'host1', 'plat0', 'plat1', 679 'Everyone', 'acl0', 'label0']) 680 681 682 def test_execute_stat_one_bad_host_verbose(self): 683 self.run_cmd(argv=['atest', 'host', 'stat', 'host0', 684 'host1', '-v'], 685 rpcs=[('get_hosts', {'hostname': 'host1'}, 686 True, 687 []), 688 ('get_hosts', {'hostname': 'host0'}, 689 True, 690 [{u'status': u'Ready', 691 u'hostname': u'host0', 692 u'locked': False, 693 u'locked_by': 'user0', 694 u'lock_time': u'2008-07-23 12:54:15', 695 u'lock_reason': u'', 696 u'protection': u'No protection', 697 u'labels': [u'label0', u'plat0'], 698 u'invalid': False, 699 u'platform': u'plat0', 700 u'id': 2, 701 u'attributes': {}}]), 702 ('get_acl_groups', {'hosts__hostname': 'host0'}, 703 True, 704 [{u'description': u'', 705 u'hosts': [u'host0', u'host1'], 706 u'id': 1, 707 u'name': u'Everyone', 708 u'users': [u'user0', u'debug_user']}, 709 {u'description': u'myacl0', 710 u'hosts': [u'host0'], 711 u'id': 2, 712 u'name': u'acl0', 713 u'users': [u'user0']}]), 714 ('get_labels', {'host__hostname': 'host0'}, 715 True, 716 [{u'id': 4, 717 u'platform': 0, 718 u'name': u'label0', 719 u'invalid': False, 720 u'kernel_config': u''}, 721 {u'id': 5, 722 u'platform': 1, 723 u'name': u'plat0', 724 u'invalid': False, 725 u'kernel_config': u''}])], 726 out_words_ok=['host0', 'plat0', 727 'Everyone', 'acl0', 'label0'], 728 out_words_no=['host1'], 729 err_words_ok=['host1', 'Unknown host'], 730 err_words_no=['host0']) 731 732 733 def test_execute_stat_one_bad_host(self): 734 self.run_cmd(argv=['atest', 'host', 'stat', 'host0', 'host1'], 735 rpcs=[('get_hosts', {'hostname': 'host1'}, 736 True, 737 []), 738 ('get_hosts', {'hostname': 'host0'}, 739 True, 740 [{u'status': u'Ready', 741 u'hostname': u'host0', 742 u'locked': False, 743 u'locked_by': 'user0', 744 u'lock_time': u'2008-07-23 12:54:15', 745 u'lock_reason': u'', 746 u'protection': u'No protection', 747 u'labels': [u'label0', u'plat0'], 748 u'invalid': False, 749 u'platform': u'plat0', 750 u'id': 2, 751 u'attributes': {}}]), 752 ('get_acl_groups', {'hosts__hostname': 'host0'}, 753 True, 754 [{u'description': u'', 755 u'hosts': [u'host0', u'host1'], 756 u'id': 1, 757 u'name': u'Everyone', 758 u'users': [u'user0', u'debug_user']}, 759 {u'description': u'myacl0', 760 u'hosts': [u'host0'], 761 u'id': 2, 762 u'name': u'acl0', 763 u'users': [u'user0']}]), 764 ('get_labels', {'host__hostname': 'host0'}, 765 True, 766 [{u'id': 4, 767 u'platform': 0, 768 u'name': u'label0', 769 u'invalid': False, 770 u'kernel_config': u''}, 771 {u'id': 5, 772 u'platform': 1, 773 u'name': u'plat0', 774 u'invalid': False, 775 u'kernel_config': u''}])], 776 out_words_ok=['host0', 'plat0', 777 'Everyone', 'acl0', 'label0'], 778 out_words_no=['host1'], 779 err_words_ok=['host1', 'Unknown host'], 780 err_words_no=['host0']) 781 782 783 def test_execute_stat_wildcard(self): 784 # The order of RPCs between host1 and host0 could change... 785 self.run_cmd(argv=['atest', 'host', 'stat', 'ho*'], 786 rpcs=[('get_hosts', {'hostname__startswith': 'ho'}, 787 True, 788 [{u'status': u'Ready', 789 u'hostname': u'host1', 790 u'locked': True, 791 u'lock_time': u'2008-07-23 12:54:15', 792 u'locked_by': 'user0', 793 u'lock_reason': u'', 794 u'protection': 'No protection', 795 u'labels': [u'label3', u'plat1'], 796 u'invalid': False, 797 u'platform': u'plat1', 798 u'id': 3, 799 u'attributes': {}}, 800 {u'status': u'Ready', 801 u'hostname': u'host0', 802 u'locked': False, 803 u'locked_by': 'user0', 804 u'lock_time': u'2008-07-23 12:54:15', 805 u'lock_reason': u'', 806 u'protection': u'No protection', 807 u'labels': [u'label0', u'plat0'], 808 u'invalid': False, 809 u'platform': u'plat0', 810 u'id': 2, 811 u'attributes': {}}]), 812 ('get_acl_groups', {'hosts__hostname': 'host1'}, 813 True, 814 [{u'description': u'', 815 u'hosts': [u'host0', u'host1'], 816 u'id': 1, 817 u'name': u'Everyone', 818 u'users': [u'user2', u'debug_user', u'user0']}]), 819 ('get_labels', {'host__hostname': 'host1'}, 820 True, 821 [{u'id': 2, 822 u'platform': 1, 823 u'name': u'jme', 824 u'invalid': False, 825 u'kernel_config': u''}]), 826 ('get_acl_groups', {'hosts__hostname': 'host0'}, 827 True, 828 [{u'description': u'', 829 u'hosts': [u'host0', u'host1'], 830 u'id': 1, 831 u'name': u'Everyone', 832 u'users': [u'user0', u'debug_user']}, 833 {u'description': u'myacl0', 834 u'hosts': [u'host0'], 835 u'id': 2, 836 u'name': u'acl0', 837 u'users': [u'user0']}]), 838 ('get_labels', {'host__hostname': 'host0'}, 839 True, 840 [{u'id': 4, 841 u'platform': 0, 842 u'name': u'label0', 843 u'invalid': False, 844 u'kernel_config': u''}, 845 {u'id': 5, 846 u'platform': 1, 847 u'name': u'plat0', 848 u'invalid': False, 849 u'kernel_config': u''}])], 850 out_words_ok=['host0', 'host1', 'plat0', 'plat1', 851 'Everyone', 'acl0', 'label0']) 852 853 854 def test_execute_stat_wildcard_and_host(self): 855 # The order of RPCs between host1 and host0 could change... 856 self.run_cmd(argv=['atest', 'host', 'stat', 'ho*', 'newhost0'], 857 rpcs=[('get_hosts', {'hostname': 'newhost0'}, 858 True, 859 [{u'status': u'Ready', 860 u'hostname': u'newhost0', 861 u'locked': False, 862 u'locked_by': 'user0', 863 u'lock_time': u'2008-07-23 12:54:15', 864 u'lock_reason': u'', 865 u'protection': u'No protection', 866 u'labels': [u'label0', u'plat0'], 867 u'invalid': False, 868 u'platform': u'plat0', 869 u'id': 5, 870 u'attributes': {}}]), 871 ('get_hosts', {'hostname__startswith': 'ho'}, 872 True, 873 [{u'status': u'Ready', 874 u'hostname': u'host1', 875 u'locked': True, 876 u'lock_time': u'2008-07-23 12:54:15', 877 u'locked_by': 'user0', 878 u'lock_reason': u'', 879 u'protection': 'No protection', 880 u'labels': [u'label3', u'plat1'], 881 u'invalid': False, 882 u'platform': u'plat1', 883 u'id': 3, 884 u'attributes': {}}, 885 {u'status': u'Ready', 886 u'hostname': u'host0', 887 u'locked': False, 888 u'locked_by': 'user0', 889 u'lock_reason': u'', 890 u'protection': 'No protection', 891 u'lock_time': u'2008-07-23 12:54:15', 892 u'labels': [u'label0', u'plat0'], 893 u'invalid': False, 894 u'platform': u'plat0', 895 u'id': 2, 896 u'attributes': {}}]), 897 ('get_acl_groups', {'hosts__hostname': 'newhost0'}, 898 True, 899 [{u'description': u'', 900 u'hosts': [u'newhost0', 'host1'], 901 u'id': 42, 902 u'name': u'my_acl', 903 u'users': [u'user0', u'debug_user']}, 904 {u'description': u'my favorite acl', 905 u'hosts': [u'newhost0'], 906 u'id': 2, 907 u'name': u'acl10', 908 u'users': [u'user0']}]), 909 ('get_labels', {'host__hostname': 'newhost0'}, 910 True, 911 [{u'id': 4, 912 u'platform': 0, 913 u'name': u'label0', 914 u'invalid': False, 915 u'kernel_config': u''}, 916 {u'id': 5, 917 u'platform': 1, 918 u'name': u'plat0', 919 u'invalid': False, 920 u'kernel_config': u''}]), 921 ('get_acl_groups', {'hosts__hostname': 'host1'}, 922 True, 923 [{u'description': u'', 924 u'hosts': [u'host0', u'host1'], 925 u'id': 1, 926 u'name': u'Everyone', 927 u'users': [u'user2', u'debug_user', u'user0']}]), 928 ('get_labels', {'host__hostname': 'host1'}, 929 True, 930 [{u'id': 2, 931 u'platform': 1, 932 u'name': u'jme', 933 u'invalid': False, 934 u'kernel_config': u''}]), 935 ('get_acl_groups', {'hosts__hostname': 'host0'}, 936 True, 937 [{u'description': u'', 938 u'hosts': [u'host0', u'host1'], 939 u'id': 1, 940 u'name': u'Everyone', 941 u'users': [u'user0', u'debug_user']}, 942 {u'description': u'myacl0', 943 u'hosts': [u'host0'], 944 u'id': 2, 945 u'name': u'acl0', 946 u'users': [u'user0']}]), 947 ('get_labels', {'host__hostname': 'host0'}, 948 True, 949 [{u'id': 4, 950 u'platform': 0, 951 u'name': u'label0', 952 u'invalid': False, 953 u'kernel_config': u''}, 954 {u'id': 5, 955 u'platform': 1, 956 u'name': u'plat0', 957 u'invalid': False, 958 u'kernel_config': u''}])], 959 out_words_ok=['host0', 'host1', 'newhost0', 960 'plat0', 'plat1', 961 'Everyone', 'acl10', 'label0']) 962 963 964class host_jobs_unittest(cli_mock.cli_unittest): 965 def test_execute_jobs_one_host(self): 966 self.run_cmd(argv=['atest', 'host', 'jobs', 'host0'], 967 rpcs=[('get_host_queue_entries', 968 {'host__hostname': 'host0', 'query_limit': 20, 969 'sort_by': ['-job__id']}, 970 True, 971 [{u'status': u'Failed', 972 u'complete': 1, 973 u'host': {u'status': u'Ready', 974 u'locked': True, 975 u'locked_by': 'user0', 976 u'hostname': u'host0', 977 u'invalid': False, 978 u'id': 3232}, 979 u'priority': 0, 980 u'meta_host': u'meta0', 981 u'job': {u'control_file': 982 (u"def step_init():\n" 983 "\tjob.next_step([step_test])\n" 984 "def step_test():\n" 985 "\tjob.run_test('kernbench')\n\n"), 986 u'name': u'kernel-smp-2.6.xyz.x86_64', 987 u'control_type': CLIENT, 988 u'synchronizing': None, 989 u'priority': u'Low', 990 u'owner': u'user0', 991 u'created_on': u'2008-01-09 10:45:12', 992 u'synch_count': None, 993 u'id': 216}, 994 u'active': 0, 995 u'id': 2981}, 996 {u'status': u'Aborted', 997 u'complete': 1, 998 u'host': {u'status': u'Ready', 999 u'locked': True, 1000 u'locked_by': 'user0', 1001 u'hostname': u'host0', 1002 u'invalid': False, 1003 u'id': 3232}, 1004 u'priority': 0, 1005 u'meta_host': None, 1006 u'job': {u'control_file': 1007 u"job.run_test('sleeptest')\n\n", 1008 u'name': u'testjob', 1009 u'control_type': CLIENT, 1010 u'synchronizing': 0, 1011 u'priority': u'Low', 1012 u'owner': u'user1', 1013 u'created_on': u'2008-01-17 15:04:53', 1014 u'synch_count': None, 1015 u'id': 289}, 1016 u'active': 0, 1017 u'id': 3167}])], 1018 out_words_ok=['216', 'user0', 'Failed', 1019 'kernel-smp-2.6.xyz.x86_64', 'Aborted', 1020 '289', 'user1', 'Aborted', 1021 'testjob']) 1022 1023 1024 def test_execute_jobs_wildcard(self): 1025 self.run_cmd(argv=['atest', 'host', 'jobs', 'ho*'], 1026 rpcs=[('get_hosts', {'hostname__startswith': 'ho'}, 1027 True, 1028 [{u'status': u'Ready', 1029 u'hostname': u'host1', 1030 u'locked': True, 1031 u'lock_time': u'2008-07-23 12:54:15', 1032 u'locked_by': 'user0', 1033 u'labels': [u'label3', u'plat1'], 1034 u'invalid': False, 1035 u'platform': u'plat1', 1036 u'id': 3}, 1037 {u'status': u'Ready', 1038 u'hostname': u'host0', 1039 u'locked': False, 1040 u'locked_by': 'user0', 1041 u'lock_time': u'2008-07-23 12:54:15', 1042 u'labels': [u'label0', u'plat0'], 1043 u'invalid': False, 1044 u'platform': u'plat0', 1045 u'id': 2}]), 1046 ('get_host_queue_entries', 1047 {'host__hostname': 'host1', 'query_limit': 20, 1048 'sort_by': ['-job__id']}, 1049 True, 1050 [{u'status': u'Failed', 1051 u'complete': 1, 1052 u'host': {u'status': u'Ready', 1053 u'locked': True, 1054 u'locked_by': 'user0', 1055 u'hostname': u'host1', 1056 u'invalid': False, 1057 u'id': 3232}, 1058 u'priority': 0, 1059 u'meta_host': u'meta0', 1060 u'job': {u'control_file': 1061 (u"def step_init():\n" 1062 "\tjob.next_step([step_test])\n" 1063 "def step_test():\n" 1064 "\tjob.run_test('kernbench')\n\n"), 1065 u'name': u'kernel-smp-2.6.xyz.x86_64', 1066 u'control_type': CLIENT, 1067 u'synchronizing': None, 1068 u'priority': u'Low', 1069 u'owner': u'user0', 1070 u'created_on': u'2008-01-09 10:45:12', 1071 u'synch_count': None, 1072 u'id': 216}, 1073 u'active': 0, 1074 u'id': 2981}, 1075 {u'status': u'Aborted', 1076 u'complete': 1, 1077 u'host': {u'status': u'Ready', 1078 u'locked': True, 1079 u'locked_by': 'user0', 1080 u'hostname': u'host1', 1081 u'invalid': False, 1082 u'id': 3232}, 1083 u'priority': 0, 1084 u'meta_host': None, 1085 u'job': {u'control_file': 1086 u"job.run_test('sleeptest')\n\n", 1087 u'name': u'testjob', 1088 u'control_type': CLIENT, 1089 u'synchronizing': 0, 1090 u'priority': u'Low', 1091 u'owner': u'user1', 1092 u'created_on': u'2008-01-17 15:04:53', 1093 u'synch_count': None, 1094 u'id': 289}, 1095 u'active': 0, 1096 u'id': 3167}]), 1097 ('get_host_queue_entries', 1098 {'host__hostname': 'host0', 'query_limit': 20, 1099 'sort_by': ['-job__id']}, 1100 True, 1101 [{u'status': u'Failed', 1102 u'complete': 1, 1103 u'host': {u'status': u'Ready', 1104 u'locked': True, 1105 u'locked_by': 'user0', 1106 u'hostname': u'host0', 1107 u'invalid': False, 1108 u'id': 3232}, 1109 u'priority': 0, 1110 u'meta_host': u'meta0', 1111 u'job': {u'control_file': 1112 (u"def step_init():\n" 1113 "\tjob.next_step([step_test])\n" 1114 "def step_test():\n" 1115 "\tjob.run_test('kernbench')\n\n"), 1116 u'name': u'kernel-smp-2.6.xyz.x86_64', 1117 u'control_type': CLIENT, 1118 u'synchronizing': None, 1119 u'priority': u'Low', 1120 u'owner': u'user0', 1121 u'created_on': u'2008-01-09 10:45:12', 1122 u'synch_count': None, 1123 u'id': 216}, 1124 u'active': 0, 1125 u'id': 2981}, 1126 {u'status': u'Aborted', 1127 u'complete': 1, 1128 u'host': {u'status': u'Ready', 1129 u'locked': True, 1130 u'locked_by': 'user0', 1131 u'hostname': u'host0', 1132 u'invalid': False, 1133 u'id': 3232}, 1134 u'priority': 0, 1135 u'meta_host': None, 1136 u'job': {u'control_file': 1137 u"job.run_test('sleeptest')\n\n", 1138 u'name': u'testjob', 1139 u'control_type': CLIENT, 1140 u'synchronizing': 0, 1141 u'priority': u'Low', 1142 u'owner': u'user1', 1143 u'created_on': u'2008-01-17 15:04:53', 1144 u'synch_count': None, 1145 u'id': 289}, 1146 u'active': 0, 1147 u'id': 3167}])], 1148 out_words_ok=['216', 'user0', 'Failed', 1149 'kernel-smp-2.6.xyz.x86_64', 'Aborted', 1150 '289', 'user1', 'Aborted', 1151 'testjob']) 1152 1153 1154 def test_execute_jobs_one_host_limit(self): 1155 self.run_cmd(argv=['atest', 'host', 'jobs', 'host0', '-q', '10'], 1156 rpcs=[('get_host_queue_entries', 1157 {'host__hostname': 'host0', 'query_limit': 10, 1158 'sort_by': ['-job__id']}, 1159 True, 1160 [{u'status': u'Failed', 1161 u'complete': 1, 1162 u'host': {u'status': u'Ready', 1163 u'locked': True, 1164 u'locked_by': 'user0', 1165 u'hostname': u'host0', 1166 u'invalid': False, 1167 u'id': 3232}, 1168 u'priority': 0, 1169 u'meta_host': u'meta0', 1170 u'job': {u'control_file': 1171 (u"def step_init():\n" 1172 "\tjob.next_step([step_test])\n" 1173 "def step_test():\n" 1174 "\tjob.run_test('kernbench')\n\n"), 1175 u'name': u'kernel-smp-2.6.xyz.x86_64', 1176 u'control_type': CLIENT, 1177 u'synchronizing': None, 1178 u'priority': u'Low', 1179 u'owner': u'user0', 1180 u'created_on': u'2008-01-09 10:45:12', 1181 u'synch_count': None, 1182 u'id': 216}, 1183 u'active': 0, 1184 u'id': 2981}, 1185 {u'status': u'Aborted', 1186 u'complete': 1, 1187 u'host': {u'status': u'Ready', 1188 u'locked': True, 1189 u'locked_by': 'user0', 1190 u'hostname': u'host0', 1191 u'invalid': False, 1192 u'id': 3232}, 1193 u'priority': 0, 1194 u'meta_host': None, 1195 u'job': {u'control_file': 1196 u"job.run_test('sleeptest')\n\n", 1197 u'name': u'testjob', 1198 u'control_type': CLIENT, 1199 u'synchronizing': 0, 1200 u'priority': u'Low', 1201 u'owner': u'user1', 1202 u'created_on': u'2008-01-17 15:04:53', 1203 u'synch_count': None, 1204 u'id': 289}, 1205 u'active': 0, 1206 u'id': 3167}])], 1207 out_words_ok=['216', 'user0', 'Failed', 1208 'kernel-smp-2.6.xyz.x86_64', 'Aborted', 1209 '289', 'user1', 'Aborted', 1210 'testjob']) 1211 1212 1213class host_mod_create_tests(object): 1214 1215 def _gen_attributes_rpcs(self, host, attributes): 1216 """Generate RPCs expected to add attributes to host. 1217 1218 @param host: hostname 1219 @param attributes: dict of attributes 1220 1221 @return: list of rpcs to expect 1222 """ 1223 rpcs = [] 1224 for attr, val in attributes.iteritems(): 1225 rpcs.append(('set_host_attribute', 1226 { 1227 'hostname': host, 1228 'attribute': attr, 1229 'value': val, 1230 }, 1231 True, None)) 1232 return rpcs 1233 1234 1235 def _gen_labels_rpcs(self, labels, platform=False, host_id=None): 1236 """Generate RPCS expected to add labels. 1237 1238 @param labels: list of label names 1239 @param platform: labels are platform labels 1240 @param host_id: Host id old labels will be deleted from (if host exists) 1241 """ 1242 rpcs = [] 1243 if host_id: 1244 rpcs.append(('get_labels', {'host': host_id}, True, [])) 1245 for label in labels: 1246 rpcs += [ 1247 ('get_labels', {'name': label}, True, []), 1248 ('add_label', {'name': label}, True, None) 1249 ] 1250 if platform: 1251 rpcs[-1][1]['platform'] = True 1252 return rpcs 1253 1254 1255 def _gen_acls_rpcs(self, hosts, acls, host_ids=[]): 1256 """Generate RPCs expected to add acls. 1257 1258 @param hosts: list of hostnames 1259 @param acls: list of acl names 1260 @param host_ids: List of host_ids if hosts already exist 1261 """ 1262 rpcs = [] 1263 for host_id in host_ids: 1264 rpcs.append(('get_acl_groups', {'hosts': host_id}, True, [])) 1265 for acl in acls: 1266 rpcs.append(('get_acl_groups', {'name': acl}, True, [])) 1267 rpcs.append(('add_acl_group', {'name': acl}, True, None)) 1268 for acl in acls: 1269 rpcs.append(( 1270 'acl_group_add_hosts', 1271 { 1272 'hosts': hosts, 1273 'id': acl, 1274 }, 1275 True, 1276 None, 1277 )) 1278 return rpcs 1279 1280 1281 def test_lock_one_host(self): 1282 """Test locking host / creating host locked.""" 1283 lock_reason = 'Because' 1284 rpcs, out = self._gen_expectations(locked=True, lock_reason=lock_reason) 1285 self.run_cmd(argv=self._command_single + ['--lock', '--lock_reason', 1286 lock_reason], 1287 rpcs=rpcs, out_words_ok=out) 1288 1289 1290 def test_unlock_multiple_hosts(self): 1291 """Test unlocking host / creating host unlocked.""" 1292 rpcs, out = self._gen_expectations(hosts=self._hosts, locked=False) 1293 self.run_cmd(argv=self._command_multiple + ['--unlock'], rpcs=rpcs, 1294 out_words_ok=out) 1295 1296 1297 def test_machine_list(self): 1298 """Test action an machines from machine list file.""" 1299 mfile = cli_mock.create_file(','.join(self._hosts)) 1300 rpcs, out = self._gen_expectations(hosts=self._hosts, locked=False) 1301 try: 1302 self.run_cmd(argv=self._command_multiple + ['--unlock'], rpcs=rpcs, 1303 out_words_ok=out) 1304 finally: 1305 mfile.clean() 1306 1307 1308 def test_single_attributes(self): 1309 """Test applying one attribute to one host.""" 1310 attrs = {'foo': 'bar'} 1311 rpcs, out = self._gen_expectations(attributes=attrs) 1312 self.run_cmd(self._command_single + ['--attribute', 'foo=bar'], 1313 rpcs=rpcs, out_words_ok=out) 1314 1315 1316 def test_attributes_comma(self): 1317 """Test setting an attribute with a comma in the value.""" 1318 attrs = {'foo': 'bar,zip'} 1319 rpcs, out = self._gen_expectations(attributes=attrs) 1320 self.run_cmd(self._command_single + ['--attribute', 'foo=bar,zip'], 1321 rpcs=rpcs, out_words_ok=out) 1322 1323 1324 def test_multiple_attributes_comma(self): 1325 """Test setting attributes when one of the values contains a comma.""" 1326 attrs = {'foo': 'bar,zip', 'zang': 'poodle'} 1327 rpcs, out = self._gen_expectations(attributes=attrs) 1328 self.run_cmd(self._command_single + ['--attribute', 'foo=bar,zip', 1329 '--attribute', 'zang=poodle'], 1330 rpcs=rpcs, out_words_ok=out) 1331 1332 1333 def test_multiple_attributes_multiple_hosts(self): 1334 """Test applying multiple attributes to multiple hosts.""" 1335 attrs = {'foo': 'bar', 'baz': 'zip'} 1336 rpcs, out = self._gen_expectations(hosts=self._hosts, attributes=attrs) 1337 self.run_cmd(self._command_multiple + ['--attribute', 'foo=bar', 1338 '--attribute', 'baz=zip'], 1339 rpcs=rpcs, out_words_ok=out) 1340 1341 1342 def test_platform(self): 1343 """Test applying platform label.""" 1344 rpcs, out = self._gen_expectations(platform='some_platform') 1345 self.run_cmd(argv=self._command_single + ['--platform', 1346 'some_platform'], 1347 rpcs=rpcs, out_words_ok=out) 1348 1349 1350 def test_labels(self): 1351 """Test applying labels.""" 1352 labels = ['label0', 'label1'] 1353 rpcs, out = self._gen_expectations(labels=labels) 1354 self.run_cmd(argv=self._command_single + ['--labels', ','.join(labels)], 1355 rpcs=rpcs, out_words_ok=out) 1356 1357 1358 def test_labels_from_file(self): 1359 """Test applying labels from file.""" 1360 labels = ['label0', 'label1'] 1361 rpcs, out = self._gen_expectations(labels=labels) 1362 labelsf = cli_mock.create_file(','.join(labels)) 1363 try: 1364 self.run_cmd(argv=self._command_single + ['--blist', labelsf.name], 1365 rpcs=rpcs, out_words_ok=out) 1366 finally: 1367 labelsf.clean() 1368 1369 1370 def test_acls(self): 1371 """Test applying acls.""" 1372 acls = ['acl0', 'acl1'] 1373 rpcs, out = self._gen_expectations(acls=acls) 1374 self.run_cmd(argv=self._command_single + ['--acls', ','.join(acls)], 1375 rpcs=rpcs, out_words_ok=out) 1376 1377 1378 def test_acls_from_file(self): 1379 """Test applying acls from file.""" 1380 acls = ['acl0', 'acl1'] 1381 rpcs, out = self._gen_expectations(acls=acls) 1382 aclsf = cli_mock.create_file(','.join(acls)) 1383 try: 1384 self.run_cmd(argv=self._command_single + ['-A', aclsf.name], 1385 rpcs=rpcs, out_words_ok=out) 1386 finally: 1387 aclsf.clean() 1388 1389 1390 def test_protection(self): 1391 """Test applying host protection.""" 1392 protection = 'Do not repair' 1393 rpcs, out = self._gen_expectations(protection=protection) 1394 self.run_cmd(argv=self._command_single + ['--protection', protection], 1395 rpcs=rpcs,out_words_ok=out) 1396 1397 1398 def test_protection_invalid(self): 1399 """Test invalid protection causes failure.""" 1400 protection = 'Invalid protection' 1401 rpcs, out = self._gen_expectations(hosts=[]) 1402 self.run_cmd(argv=self._command_single + ['--protection', protection], 1403 exit_code=2, err_words_ok=['invalid', 'choice'] + 1404 protection.split()) 1405 1406 1407 def test_complex(self): 1408 """Test applying multiple modifications / creating a complex host.""" 1409 lock_reason = 'Because I said so.' 1410 platform = 'some_platform' 1411 labels = ['label0', 'label1'] 1412 acls = ['acl0', 'acl1'] 1413 protection = 'Do not verify' 1414 labelsf = cli_mock.create_file(labels[1]) 1415 aclsf = cli_mock.create_file(acls[1]) 1416 cmd_args = ['-l', '-r', lock_reason, '-t', platform, '-b', labels[0], 1417 '-B', labelsf.name, '-a', acls[0], '-A', aclsf.name, '-p', 1418 protection] 1419 rpcs, out = self._gen_expectations(locked=True, lock_reason=lock_reason, 1420 acls=acls, labels=labels, 1421 platform=platform, 1422 protection=protection) 1423 1424 try: 1425 self.run_cmd(argv=self._command_single + cmd_args, rpcs=rpcs, 1426 out_words_ok=out) 1427 finally: 1428 labelsf.clean() 1429 aclsf.clean() 1430 1431 1432class host_mod_unittest(host_mod_create_tests, cli_mock.cli_unittest): 1433 """Tests specific to the mod action and expectation generator for shared 1434 tests. 1435 """ 1436 _hosts = ['localhost', '127.0.0.1'] 1437 _host_ids = [1, 2] 1438 _command_base = ['atest', 'host', 'mod'] 1439 _command_single = _command_base + [_hosts[0]] 1440 _command_multiple = _command_base + _hosts 1441 1442 def _gen_expectations(self, hosts=['localhost'], locked=None, 1443 lock_reason='', force_lock=False, protection=None, 1444 acls=[], labels=[], platform=None, attributes={}): 1445 rpcs = [] 1446 out = set() 1447 hosts = hosts[:] 1448 hosts.reverse() 1449 1450 # Genarate result for get_hosts command to include all known hosts 1451 host_dicts = [] 1452 for h, h_id in zip(self._hosts, self._host_ids): 1453 host_dicts.append({'hostname': h, 'id': h_id}) 1454 rpcs.append(('get_hosts', {'hostname__in': hosts}, True, host_dicts)) 1455 1456 # Expect actions only for known hosts 1457 host_ids = [] 1458 for host in hosts: 1459 if host not in self._hosts: 1460 continue 1461 host_id = self._host_ids[self._hosts.index(host)] 1462 host_ids.append(host_id) 1463 modify_args = {'id': host} 1464 1465 if locked is not None: 1466 out.add('Locked' if locked else 'Unlocked') 1467 modify_args['locked'] = locked 1468 modify_args['lock_reason'] = lock_reason 1469 if force_lock: 1470 modify_args['force_modify_locking'] = True 1471 if protection: 1472 modify_args['protection'] = protection 1473 1474 if len(modify_args.keys()) > 1: 1475 out.add(host) 1476 rpcs.append(('modify_host', modify_args, True, None)) 1477 1478 if labels: 1479 rpcs += self._gen_labels_rpcs(labels, host_id=host_id) 1480 rpcs.append(('host_add_labels', {'id': host, 'labels': labels}, 1481 True, None)) 1482 1483 if platform: 1484 rpcs += self._gen_labels_rpcs([platform], platform=True, 1485 host_id=host_id) 1486 rpcs.append(('host_add_labels', {'id': host, 1487 'labels': [platform]}, 1488 True, None)) 1489 1490 rpcs += self._gen_attributes_rpcs(host, attributes) 1491 1492 if acls: 1493 rpcs += self._gen_acls_rpcs(hosts, acls, host_ids=host_ids) 1494 1495 return rpcs, list(out) 1496 1497 1498 def test_mod_force_lock_one_host(self): 1499 """Test mod with forced locking.""" 1500 lock_reason = 'Because' 1501 rpcs, out = self._gen_expectations(locked=True, force_lock=True, 1502 lock_reason=lock_reason) 1503 self.run_cmd(argv=self._command_single + [ 1504 '--lock', '--force_modify_locking', '--lock_reason', 1505 lock_reason], 1506 rpcs=rpcs, out_words_ok=out) 1507 1508 def test_mod_force_unlock_one_host(self): 1509 """Test mod forced unlocking.""" 1510 rpcs, out = self._gen_expectations(locked=False, force_lock=True) 1511 self.run_cmd(argv=self._command_single + ['--unlock', 1512 '--force_modify_locking'], 1513 rpcs=rpcs, out_words_ok=out) 1514 1515 def test_mod_fail_unknown_host(self): 1516 """Test mod fails with unknown host.""" 1517 rpcs, out = self._gen_expectations(hosts=['nope'], locked=True) 1518 self.run_cmd(argv=self._command_base + ['nope', '--lock'], 1519 rpcs=rpcs, err_words_ok=['Cannot', 'modify', 'nope']) 1520 1521 1522class host_create_unittest(host_mod_create_tests, cli_mock.cli_unittest): 1523 """Test specific to create action and expectation generator for shared 1524 tests. 1525 """ 1526 _hosts = ['localhost', '127.0.0.1'] 1527 _command_base = ['atest', 'host', 'create'] 1528 _command_single = _command_base + [_hosts[0]] 1529 _command_multiple = _command_base + _hosts 1530 1531 1532 def setUp(self): 1533 """Mock out the create_host method. 1534 """ 1535 super(host_create_unittest, self).setUp() 1536 self._orig_create_host = hosts.create_host 1537 1538 1539 def tearDown(self): 1540 """Undo mock. 1541 """ 1542 super(host_create_unittest, self).tearDown() 1543 hosts.create_host = self._orig_create_host 1544 1545 1546 def _mock_host(self, platform=None, labels=[]): 1547 """Update the return values of the mocked host object. 1548 1549 @param platform: return value of Host.get_platform() 1550 @param labels: return value of Host.get_labels() 1551 """ 1552 mock_host = mock.MagicMock() 1553 mock_host.get_platform.return_value = platform 1554 mock_host.get_labels.return_value = labels 1555 hosts.create_host = mock.MagicMock() 1556 hosts.create_host.return_value = mock_host 1557 1558 1559 def _gen_expectations(self, hosts=['localhost'], locked=False, 1560 lock_reason=None, platform=None, 1561 discovered_platform=None, labels=[], 1562 discovered_labels=[], acls=[], protection=None, 1563 attributes={}): 1564 """Build a list of expected RPC calls based on values to host command. 1565 1566 @param hosts: list of hostname being created (default ['localhost']) 1567 @param locked: end state of host (bool) 1568 @param lock_reason: reason for host to be locked 1569 @param platform: platform label 1570 @param discovered_platform: platform discovered automatically by host 1571 @param labels: list of host labels (excluding platform) 1572 @param discovered_labels: list of labels discovered automatically 1573 @param acls: list of host acls 1574 @param protection: host protection level 1575 1576 @return: list of expect rpc calls (each call is (op, args, success, 1577 result)) 1578 """ 1579 hosts = hosts[:] 1580 hosts.reverse() # No idea why 1581 lock_reason = lock_reason or 'Forced lock on device creation' 1582 acls = acls or [] 1583 1584 rpcs = [] 1585 out = ['Added', 'host'] + hosts 1586 1587 # Mock platform and label detection results 1588 self._mock_host(discovered_platform, discovered_labels) 1589 1590 for host in hosts: 1591 add_args = { 1592 'hostname': host, 1593 'status': 'Ready', 1594 'locked': True, 1595 'lock_reason': lock_reason, 1596 } 1597 if protection: 1598 add_args['protection'] = protection 1599 rpcs.append(('add_host', add_args, True, None)) 1600 1601 rpcs += self._gen_labels_rpcs(labels) 1602 if labels: 1603 rpcs.append(('host_add_labels', {'id': host, 'labels': labels}, 1604 True, None)) 1605 1606 if platform: 1607 rpcs += self._gen_labels_rpcs([platform], platform=True) 1608 rpcs.append(('host_add_labels', {'id': host, 1609 'labels': [platform]}, 1610 True, None)) 1611 1612 rpcs += self._gen_attributes_rpcs(host, attributes) 1613 1614 rpcs += self._gen_acls_rpcs(hosts, acls) 1615 1616 if not locked: 1617 for host in hosts: 1618 rpcs.append(( 1619 'modify_host', 1620 { 1621 'id': host, 1622 'locked': False, 1623 'lock_reason': '', 1624 }, 1625 True, 1626 None, 1627 )) 1628 return rpcs, out 1629 1630 def test_create_no_args(self): 1631 """Test simple creation with to arguments.""" 1632 rpcs, out = self._gen_expectations() 1633 self.run_cmd(argv=self._command_single, rpcs=rpcs, out_words_ok=out) 1634 1635 1636 def test_create_with_discovered_platform(self): 1637 """Test discovered platform is used when platform isn't specified.""" 1638 rpcs, out = self._gen_expectations(platform='some_platform', 1639 discovered_platform='some_platform') 1640 self.run_cmd(argv=self._command_single, rpcs=rpcs, out_words_ok=out) 1641 1642 1643 def test_create_specified_platform_overrides_discovered_platform(self): 1644 """Test that the specified platform overrides the discovered platform. 1645 """ 1646 rpcs, out = self._gen_expectations(platform='some_platform', 1647 discovered_platform='wrong_platform') 1648 self.run_cmd(argv=self._command_single + ['--platform', 1649 'some_platform'], 1650 rpcs=rpcs, out_words_ok=out) 1651 1652 1653 def test_create_discovered_labels(self): 1654 """Test applying automatically discovered labels.""" 1655 labels = ['label0', 'label1'] 1656 rpcs, out = self._gen_expectations(labels=labels, 1657 discovered_labels=labels) 1658 self.run_cmd(argv=self._command_single, rpcs=rpcs, out_words_ok=out) 1659 1660 1661 def test_create_specified_discovered_labels_combine(self): 1662 """Test applying both discovered and specified labels.""" 1663 labels = ['label0', 'label1'] 1664 rpcs, out = self._gen_expectations(labels=labels, 1665 discovered_labels=[labels[0]]) 1666 self.run_cmd(argv=self._command_single + ['--labels', labels[1]], 1667 rpcs=rpcs, out_words_ok=out) 1668 1669 def test_remove_hostname_suffix(self): 1670 self.assertEqual( 1671 host._remove_hostname_suffix_if_present( \ 1672 "a", host.MIGRATED_HOST_SUFFIX), "a") 1673 self.assertEqual( \ 1674 host._remove_hostname_suffix_if_present( \ 1675 "b" + host.MIGRATED_HOST_SUFFIX, \ 1676 host.MIGRATED_HOST_SUFFIX), "b") 1677 1678 1679if __name__ == '__main__': 1680 unittest.main() 1681