|
126 |
# Create the logfile |
126 |
# Create the logfile |
127 |
if self.logfile: |
127 |
if self.logfile: |
128 |
log = open(self.logfile, 'a+') |
128 |
log = open(self.logfile, 'a+') |
129 |
log.write('Created instance %s at %s\n' % (section, time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()))) |
129 |
log.write('Creating instance %s at %s\n' % (section, time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()))) |
130 |
log.close() |
130 |
log.close() |
131 |
self.logfile_fd = None |
131 |
self.logfile_fd = None |
132 |
|
132 |
|
|
144 |
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) |
144 |
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) |
145 |
start = now = time.time() |
145 |
start = now = time.time() |
146 |
# TODO: make the timeout configurable |
146 |
# TODO: make the timeout configurable |
147 |
timeout = 1200 |
147 |
timeout = 600 |
148 |
while now - start < timeout: |
148 |
while now - start < timeout: |
149 |
try: |
149 |
try: |
150 |
self._connect_vm() |
150 |
self._connect_vm() |
151 |
break |
151 |
break |
152 |
except socket_error: |
152 |
except socket_error: |
153 |
self._log('Pending %d...' % (timeout - now + start)) |
153 |
self._log('Connecting %d...' % (timeout - now + start)) |
154 |
time.sleep(5) |
154 |
time.sleep(5) |
155 |
now = time.time() |
155 |
now = time.time() |
156 |
except paramiko.AuthenticationException: |
156 |
except paramiko.AuthenticationException: |
|
159 |
now = time.time() |
159 |
now = time.time() |
160 |
except Exception, ex: |
160 |
except Exception, ex: |
161 |
self._log('Unknown error "%s"...' % (ex,)) |
161 |
self._log('Unknown error "%s"...' % (ex,)) |
162 |
self._log('Pending %d...' % (timeout - now + start)) |
162 |
self._log('Connecting %d...' % (timeout - now + start)) |
163 |
time.sleep(5) |
163 |
time.sleep(5) |
164 |
now = time.time() |
164 |
now = time.time() |
165 |
else: |
165 |
else: |
|
552 |
'ec2_ami', |
552 |
'ec2_ami', |
553 |
'ec2_security_group', |
553 |
'ec2_security_group', |
554 |
'ec2_instance_type', |
554 |
'ec2_instance_type', |
|
|
555 |
'ec2_instance_ebsOptimized', |
555 |
'ec2_keypair', |
556 |
'ec2_keypair', |
556 |
'ec2_region', |
557 |
'ec2_region', |
557 |
'ec2_subnet_id', |
558 |
'ec2_subnet_id', |
558 |
'ec2_partition_size', |
559 |
'ec2_partition_size', |
|
|
560 |
'ec2_instance_store', |
561 |
'ec2_volume_type', |
562 |
'ec2_volume_iops', |
559 |
] |
563 |
] |
560 |
for key in params: |
564 |
for key in params: |
561 |
if not config.has_option(section, key): |
565 |
if not config.has_option(section, key): |
|
575 |
Create explicit block device with given size. |
579 |
Create explicit block device with given size. |
576 |
""" |
580 |
""" |
577 |
bdm = None |
581 |
bdm = None |
|
|
582 |
#self._log('Mapping volumes...') |
578 |
if self.aws_cfg.get('ec2_partition_size'): |
583 |
if self.aws_cfg.get('ec2_partition_size'): |
|
|
584 |
opt_volume_type = 'standard' |
585 |
opt_iops = None |
586 |
if self.aws_cfg.get('ec2_volume_type'): |
587 |
#self._log('Adding IOPS volumes...') |
588 |
#TODO: make sure ebsOptimized is also active |
589 |
opt_volume_type = self.aws_cfg.get('ec2_volume_type') |
590 |
# IOPS - up to partition_size * 30 (See AWS docs) |
591 |
opt_iops = self.aws_cfg.get('ec2_volume_iops') |
579 |
dev_sda1 = blockdevicemapping.EBSBlockDeviceType( |
592 |
dev_sda1 = blockdevicemapping.EBSBlockDeviceType( |
580 |
size = self.aws_cfg.get('ec2_partition_size'), |
593 |
size = self.aws_cfg.get('ec2_partition_size'), |
581 |
delete_on_termination=True, |
594 |
volume_type = opt_volume_type, |
582 |
) |
595 |
iops = opt_iops, |
|
|
596 |
delete_on_termination = True) |
583 |
bdm = blockdevicemapping.BlockDeviceMapping() |
597 |
bdm = blockdevicemapping.BlockDeviceMapping() |
584 |
bdm['/dev/sda1'] = dev_sda1 |
598 |
bdm['/dev/sda1'] = dev_sda1 |
|
|
599 |
#self._log('instance stores %s' % self.aws_cfg.get('ec2_instance_store')) |
600 |
#assumming 2 - TODO: cycle for given-number-of-devices |
601 |
if self.aws_cfg.get('ec2_instance_store'): |
602 |
#self._log('Adding instance store volumes...') |
603 |
dev_xvdb = blockdevicemapping.BlockDeviceType() |
604 |
dev_xvdc = blockdevicemapping.BlockDeviceType() |
605 |
dev_xvdb.ephemeral_name = 'ephemeral0' |
606 |
dev_xvdc.ephemeral_name = 'ephemeral1' |
607 |
bdm = blockdevicemapping.BlockDeviceMapping() |
608 |
bdm['/dev/sdb'] = dev_xvdb |
609 |
bdm['/dev/sdc'] = dev_xvdc |
610 |
#self._log('...done. MappedDevices: %s' % bdm) |
585 |
return bdm |
611 |
return bdm |
586 |
|
612 |
|
587 |
def _connect_vm(self): |
613 |
def _connect_vm(self): |
|
605 |
user_data = '\n'.join(['%s=%s' % (v, os.getenv(v, '')) for v in env_vars]) |
631 |
user_data = '\n'.join(['%s=%s' % (v, os.getenv(v, '')) for v in env_vars]) |
606 |
|
632 |
|
607 |
self.ec2 = boto.connect_ec2(**aws_cfg) |
633 |
self.ec2 = boto.connect_ec2(**aws_cfg) |
|
|
634 |
|
608 |
reuse = self.aws_cfg.get('ec2_reuse') |
635 |
reuse = self.aws_cfg.get('ec2_reuse') |
609 |
if reuse: |
636 |
if reuse: |
610 |
reservation = self.ec2.get_all_instances(instance_ids=[reuse])[0] |
637 |
reservation = self.ec2.get_all_instances(instance_ids=[reuse])[0] |
|
617 |
user_data=user_data, |
644 |
user_data=user_data, |
618 |
security_group_ids=[self.aws_cfg['ec2_security_group']], |
645 |
security_group_ids=[self.aws_cfg['ec2_security_group']], |
619 |
instance_type=self.aws_cfg['ec2_instance_type'], |
646 |
instance_type=self.aws_cfg['ec2_instance_type'], |
620 |
instance_initiated_shutdown_behavior='terminate', # 'save' |
647 |
instance_initiated_shutdown_behavior='terminate', |
621 |
block_device_map=self._get_blockdevicemapping() |
648 |
block_device_map=self._get_blockdevicemapping() |
622 |
) |
649 |
) |
623 |
else: |
650 |
else: |
|
628 |
user_data=user_data, |
655 |
user_data=user_data, |
629 |
security_groups=[self.aws_cfg['ec2_security_group']], |
656 |
security_groups=[self.aws_cfg['ec2_security_group']], |
630 |
instance_type=self.aws_cfg['ec2_instance_type'], |
657 |
instance_type=self.aws_cfg['ec2_instance_type'], |
631 |
instance_initiated_shutdown_behavior='terminate', # 'save' |
658 |
instance_initiated_shutdown_behavior='terminate', |
632 |
block_device_map=self._get_blockdevicemapping() |
659 |
block_device_map=self._get_blockdevicemapping() |
633 |
) |
660 |
) |
|
|
661 |
|
662 |
self.instance = reservation.instances[0] |
663 |
self._log('Instance %s reserved. ->%s' % (self.instance.id, self.instance.state)) |
634 |
|
664 |
|
635 |
self.instance = reservation.instances[0] |
|
|
636 |
|
637 |
self._wait_instance() |
665 |
self._wait_instance() |
638 |
|
666 |
|
639 |
self.instance.add_tag('Name', 'Test-%s-%s' % (os.getenv('USER'), self.section)) |
667 |
self.instance.add_tag('Name', 'Test-%s-%s' % (os.getenv('USER'), self.section)) |
640 |
self.instance.add_tag('class', 'ucs-test') |
668 |
self.instance.add_tag('class', 'ucs-test') |
641 |
for var in env_vars: |
669 |
for var in env_vars: |
642 |
self.instance.add_tag(var.lower(), os.getenv(var, '')) |
670 |
self.instance.add_tag(var.lower(), os.getenv(var, '')) |
|
|
671 |
#Need ebsOptimized if volume_type is io1 |
672 |
#NOTE:launching an instance with image.run does not support ebsOptimized |
673 |
#modifying instance attribute: |
674 |
#self._log('EBS status: %s' % (self.instance.ebs_optimized)) |
675 |
if self.aws_cfg.get('ec2_instance_ebsOptimized') == 'True': |
676 |
self._log('Changing EBS status: stopping instance first.') |
677 |
# stop VM (make sure it will only be stopped, not terminated) |
678 |
self.instance.modify_attribute('instanceInitiatedShutdownBehavior', 'stop') |
679 |
self.instance.stop() |
680 |
self._wait_instance(desiredState='stopped') |
681 |
self.instance.modify_attribute('ebsOptimized', True) |
682 |
self.instance.modify_attribute('instanceInitiatedShutdownBehavior', 'terminate') |
683 |
self.instance.start() |
684 |
self._wait_instance() |
643 |
|
685 |
|
644 |
def _wait_instance(self, timeout=600): |
686 |
def _wait_instance(self, timeout=600, desiredState='running'): |
645 |
""" |
687 |
""" |
646 |
Wait until instance is created. |
688 |
Wait until instance is created. |
647 |
""" |
689 |
""" |
648 |
start = now = time.time() |
690 |
start = now = time.time() |
649 |
while now - start < timeout: |
691 |
while now - start < timeout: |
650 |
if self.instance.state == 'running': |
692 |
if self.instance.state == desiredState: |
651 |
break |
693 |
break |
652 |
if self.instance.state == 'pending': |
694 |
if self.instance.state != desiredState: |
653 |
self._log('Pending %d...' % (timeout - now + start)) |
695 |
self._log('State: %s, waiting %d...' % (self.instance.state, timeout - now + start)) |
654 |
time.sleep(10) |
696 |
time.sleep(10) |
655 |
|
697 |
|
656 |
try: |
698 |
try: |
|
661 |
if error.error_code == 'InvalidInstanceID.NotFound': |
703 |
if error.error_code == 'InvalidInstanceID.NotFound': |
662 |
break |
704 |
break |
663 |
else: |
705 |
else: |
664 |
self._log('Unexcpected error waiting for instance: %s', ex) |
706 |
self._log('Unexpected error waiting for instance: %s', ex) |
665 |
raise |
707 |
raise |
666 |
now = time.time() |
708 |
now = time.time() |
667 |
else: |
709 |
else: |
668 |
self._log('Timeout waiting for instance') |
710 |
self._log('Timeout waiting for instance') |
669 |
raise |
711 |
raise |
|
|
712 |
self._log('OK ->%s' % (self.instance.state)) |
670 |
|
713 |
|
671 |
|
|
|
672 |
def _print_process(msg): |
714 |
def _print_process(msg): |
673 |
''' Print s status line ''' |
715 |
''' Print s status line ''' |
674 |
if len(msg) > 64: |
716 |
if len(msg) > 64: |