Browse code

cloudstack: cs_host: revamp fixes several issues

(cherry picked from commit 1f5839777b28c479783c9a9316c702ee3b6f96bf)

Rene Moser authored on 2017/06/19 16:18:19
Showing 1 changed files
... ...
@@ -36,7 +36,14 @@ options:
36 36
     description:
37 37
       - Name of the host.
38 38
     required: true
39
-    aliases: [ 'url', 'ip_address' ]
39
+    aliases: [ 'ip_address' ]
40
+  url:
41
+    description:
42
+      - Url of the host used to create a host.
43
+      - If not provided, C(http://) and param C(name) is used as url.
44
+      - Only considered if C(state=present) and host does not yet exist.
45
+    required: false
46
+    default: null
40 47
   username:
41 48
     description:
42 49
       - Username for the host.
... ...
@@ -301,6 +308,11 @@ resource_state:
301 301
   returned: success
302 302
   type: string
303 303
   sample: Enabled
304
+allocation_state::
305
+  description: Allocation state of the host.
306
+  returned: success
307
+  type: string
308
+  sample: enabled
304 309
 state:
305 310
   description: State of the host.
306 311
   returned: success
... ...
@@ -334,7 +346,14 @@ zone:
334 334
 '''
335 335
 
336 336
 from ansible.module_utils.basic import AnsibleModule
337
-from ansible.module_utils.cloudstack import AnsibleCloudStack, CloudStackException, cs_argument_spec, cs_required_together, CS_HYPERVISORS
337
+from ansible.module_utils.cloudstack import (
338
+    AnsibleCloudStack,
339
+    CloudStackException,
340
+    cs_argument_spec,
341
+    cs_required_together,
342
+    CS_HYPERVISORS
343
+)
344
+import time
338 345
 
339 346
 
340 347
 class AnsibleCloudStackHost(AnsibleCloudStack):
... ...
@@ -359,7 +378,6 @@ class AnsibleCloudStackHost(AnsibleCloudStack):
359 359
             'events': 'events',
360 360
             'hahost': 'ha_host',
361 361
             'hasenoughcapacity': 'has_enough_capacity',
362
-            'hosttags': 'host_tags',
363 362
             'hypervisor': 'hypervisor',
364 363
             'hypervisorversion': 'hypervisor_version',
365 364
             'ipaddress': 'ip_address',
... ...
@@ -380,12 +398,12 @@ class AnsibleCloudStackHost(AnsibleCloudStack):
380 380
             'type': 'host_type',
381 381
             'version': 'host_version',
382 382
             'gpugroup': 'gpu_group',
383
-
384 383
         }
385 384
         self.allocation_states = {
386
-            'enabled': 'enable',
387
-            'disabled': 'disable',
385
+            'enabled': 'Enable',
386
+            'disabled': 'Disable',
388 387
         }
388
+        self.host = None
389 389
 
390 390
     def get_pod(self, key=None):
391 391
         pod_name = self.module.params.get('pod')
... ...
@@ -425,8 +443,10 @@ class AnsibleCloudStackHost(AnsibleCloudStack):
425 425
             return None
426 426
         return self.allocation_states[allocation_state]
427 427
 
428
-    def get_host(self):
429
-        host = None
428
+    def get_host(self, refresh=False):
429
+        if self.host is not None and not refresh:
430
+            return self.host
431
+
430 432
         name = self.module.params.get('name')
431 433
         args = {
432 434
             'zoneid': self.get_zone(key='id'),
... ...
@@ -435,8 +455,8 @@ class AnsibleCloudStackHost(AnsibleCloudStack):
435 435
         if res:
436 436
             for h in res['host']:
437 437
                 if name in [h['ipaddress'], h['name']]:
438
-                    host = h
439
-        return host
438
+                    self.host = h
439
+        return self.host
440 440
 
441 441
     def present_host(self):
442 442
         host = self.get_host()
... ...
@@ -446,6 +466,13 @@ class AnsibleCloudStackHost(AnsibleCloudStack):
446 446
             host = self._update_host(host)
447 447
         return host
448 448
 
449
+    def _get_url(self):
450
+        url = self.module.params.get('url')
451
+        if url:
452
+            return url
453
+        else:
454
+            return "http://%s" % self.module.params.get('name')
455
+
449 456
     def _create_host(self, host):
450 457
         required_params = [
451 458
             'password',
... ...
@@ -457,7 +484,7 @@ class AnsibleCloudStackHost(AnsibleCloudStack):
457 457
         self.result['changed'] = True
458 458
         args = {
459 459
             'hypervisor': self.module.params.get('hypervisor'),
460
-            'url': self.module.params.get('name'),
460
+            'url': self._get_url(),
461 461
             'username': self.module.params.get('username'),
462 462
             'password': self.module.params.get('password'),
463 463
             'podid': self.get_pod(key='id'),
... ...
@@ -470,24 +497,24 @@ class AnsibleCloudStackHost(AnsibleCloudStack):
470 470
             host = self.cs.addHost(**args)
471 471
             if 'errortext' in host:
472 472
                 self.module.fail_json(msg="Failed: '%s'" % host['errortext'])
473
-            host = host['host']
473
+            host = host['host'][0]
474 474
         return host
475 475
 
476 476
     def _update_host(self, host):
477 477
         args = {
478 478
             'id': host['id'],
479 479
             'hosttags': self.get_host_tags(),
480
-            'allocationstate': self.module.params.get('allocation_state'),
480
+            'allocationstate': self.get_allocation_state()
481 481
         }
482
-        host['allocationstate'] = host['resourcestate'].lower()
482
+        host['allocationstate'] = self.allocation_states[host['resourcestate'].lower()]
483 483
         if self.has_changed(args, host):
484
-            args['allocationstate'] = self.get_allocation_state()
485 484
             self.result['changed'] = True
486 485
             if not self.module.check_mode:
487 486
                 host = self.cs.updateHost(**args)
488 487
                 if 'errortext' in host:
489 488
                     self.module.fail_json(msg="Failed: '%s'" % host['errortext'])
490 489
                 host = host['host']
490
+
491 491
         return host
492 492
 
493 493
     def absent_host(self):
... ...
@@ -498,16 +525,51 @@ class AnsibleCloudStackHost(AnsibleCloudStack):
498 498
                 'id': host['id'],
499 499
             }
500 500
             if not self.module.check_mode:
501
-                res = self.cs.deleteHost(**args)
501
+                res = self.enable_maintenance()
502
+                if res:
503
+                    res = self.cs.deleteHost(**args)
504
+                    if 'errortext' in res:
505
+                        self.module.fail_json(msg="Failed: '%s'" % res['errortext'])
506
+        return host
507
+
508
+    def enable_maintenance(self):
509
+        host = self.get_host()
510
+        if host['resourcestate'] not in ['PrepareForMaintenance', 'Maintenance']:
511
+            self.result['changed'] = True
512
+            args = {
513
+                'id': host['id'],
514
+            }
515
+            if not self.module.check_mode:
516
+                res = self.cs.prepareHostForMaintenance(**args)
502 517
                 if 'errortext' in res:
503 518
                     self.module.fail_json(msg="Failed: '%s'" % res['errortext'])
519
+                host = self.poll_job(res, 'host')
520
+                self._poll_for_maintenance()
504 521
         return host
505 522
 
523
+    def _poll_for_maintenance(self):
524
+        for i in range(0, 300):
525
+            time.sleep(2)
526
+            host = self.get_host(refresh=True)
527
+            if not host:
528
+                return None
529
+            elif host['resourcestate'] != 'PrepareForMaintenance':
530
+                return host
531
+        self.fail_json("Polling for maintenance timed out")
532
+
533
+    def get_result(self, host):
534
+        super(AnsibleCloudStackHost, self).get_result(host)
535
+        if host:
536
+            self.result['allocation_state'] = host['resourcestate'].lower()
537
+            self.result['host_tags'] = host['hosttags'].split(',') if host.get('hosttags') else []
538
+        return self.result
539
+
506 540
 
507 541
 def main():
508 542
     argument_spec = cs_argument_spec()
509 543
     argument_spec.update(dict(
510
-        name=dict(required=True, aliases=['url', 'ip_address']),
544
+        name=dict(required=True, aliases=['ip_address']),
545
+        url=dict(),
511 546
         password=dict(default=None, no_log=True),
512 547
         username=dict(default=None),
513 548
         hypervisor=dict(choices=CS_HYPERVISORS, default=None),