Package starcluster :: Module volume
[hide private]
[frames] | no frames]

Source Code for Module starcluster.volume

  1  import time 
  2  import string 
  3  from starcluster.logger import log 
  4  from starcluster.node import Node 
  5  from starcluster.spinner import Spinner 
  6  from starcluster import static 
  7  from starcluster import utils 
  8  from starcluster import exception 
9 10 -class VolumeCreator(object):
11 - def __init__(self, cfg, add_to_cfg=False, keypair=None, device='/dev/sdz', 12 image_id=static.BASE_AMI_32, shutdown_instance=True):
13 self._cfg = cfg 14 self._ec2 = cfg.get_easy_ec2() 15 self._keypair = keypair 16 self._key_location = None 17 self._add_to_cfg = add_to_cfg 18 self._resv = None 19 self._instance = None 20 self._volume = None 21 self._device = device or '/dev/sdz' 22 self._node = None 23 self._image_id = image_id or BASE_AMI_32 24 self._shutdown = shutdown_instance
25 26 @property
27 - def security_group(self):
31
32 - def _request_instance(self, zone):
33 for i in self.security_group.instances(): 34 if i.state in ['pending','running'] and i.placement == zone: 35 log.info("Using existing instance %s in group %s" % \ 36 (i.id,self.security_group.name)) 37 self._instance = Node(i, self._key_location, 'vol_host') 38 break 39 if not self._instance: 40 log.info("No instance in group %s for zone %s, launching one now." % \ 41 (self.security_group.name, zone)) 42 self._resv = self._ec2.run_instances(image_id=self._image_id, 43 instance_type='m1.small', 44 min_count=1, max_count=1, 45 security_groups=[self.security_group.name], 46 key_name=self._keypair, 47 placement=zone) 48 instance = self._resv.instances[0] 49 self._instance = Node(instance, self._key_location, 'vol_host') 50 s = Spinner() 51 log.info("Waiting for instance %s to come up..." % self._instance.id) 52 s.start() 53 while not self._instance.is_up(): 54 time.sleep(15) 55 s.stop() 56 return self._instance
57
58 - def _create_volume(self, size, zone):
59 vol = self._ec2.conn.create_volume(size, zone) 60 while True: 61 vol.update() 62 if vol.status == 'available': 63 self._volume = vol 64 break 65 time.sleep(5) 66 return self._volume
67
68 - def _determine_device(self):
69 block_dev_map = self._instance.block_device_mapping 70 for char in string.lowercase[::-1]: 71 dev = '/dev/sd%s' % char 72 if not block_dev_map.get(dev): 73 self._device = dev 74 return self._device
75
76 - def _attach_volume(self, instance_id, device):
77 vol = self._volume 78 vol.attach(instance_id, device) 79 while True: 80 vol.update() 81 if vol.attachment_state() == 'attached': 82 break 83 time.sleep(5) 84 return self._volume
85
86 - def _validate_image(self, image):
87 i = self._ec2.get_image(image) 88 if not i or i.id != image: 89 raise exception.ValidationError( 90 'image %s does not exist' % image 91 )
92
93 - def _validate_zone(self, zone):
94 z = self._ec2.get_zone(zone) 95 if not z: 96 raise exception.ValidationError( 97 'zone %s does not exist' % zone 98 ) 99 if z.state != 'available': 100 log.warn('zone %s is not available at this time' % zone) 101 return True
102
103 - def _validate_size(self, size):
104 try: 105 volume_size = int(size) 106 if volume_size < 1: 107 raise exception.ValidationError( 108 "volume_size must be an integer >= 1") 109 except ValueError: 110 raise exception.ValidationError("volume_size must be an integer")
111
112 - def _validate_device(self, device):
113 if not utils.is_valid_device(device): 114 raise exception.ValidationError("volume device %s is not valid" % \ 115 device)
116
117 - def validate(self, size, zone, device, image):
118 self._validate_size(size) 119 self._validate_zone(zone) 120 self._validate_device(device) 121 self._validate_image(image)
122
123 - def is_valid(self, size, zone, device, image):
124 try: 125 self.validate(size, zone, device, image) 126 return True 127 except exception.ValidationError,e: 128 log.error(e.msg) 129 return False
130
131 - def _partition_volume(self):
132 self._instance.ssh.execute('echo ",,L" | sfdisk %s' % self._device, 133 silent=False)
134
136 self._instance.ssh.execute('mkfs.ext3 %s' % (self._device + '1'), 137 silent=False)
138
139 - def _load_keypair(self):
140 kps = self._ec2.keypairs; cfg = self._cfg 141 if self._keypair: 142 for kp in kps: 143 if kp.name == self._keypair and cfg.keys.get(kp.name): 144 log.info('Using keypair %s' % kp.name) 145 self._keypair = kp.name 146 self._key_location = cfg.keys.get(kp.name).get('key_location') 147 return 148 for kp in kps: 149 if self._cfg.keys.has_key(kp.name): 150 log.info('Using keypair %s' % kp.name) 151 self._keypair = kp.name 152 self._key_location = cfg.keys.get(kp.name).get('key_location') 153 return
154
155 - def create(self, volume_size, volume_zone):
156 self.validate(volume_size, volume_zone, self._device, self._image_id) 157 try: 158 self._load_keypair() 159 log.info(("Requesting host instance in zone %s to attach volume" + \ 160 " to...") % volume_zone) 161 instance = self._request_instance(volume_zone) 162 self._determine_device() 163 log.info("Creating %sGB volume in zone %s" % (volume_size, 164 volume_zone)) 165 vol = self._create_volume(volume_size, volume_zone) 166 log.info("New volume id: %s" % vol.id) 167 log.info("Attaching volume to instance %s" % instance.id) 168 self._attach_volume(instance.id, self._device) 169 log.info("Partitioning the volume") 170 self._partition_volume() 171 log.info("Formatting volume") 172 self._format_volume_partitions() 173 if self._shutdown: 174 log.info("Detaching volume %s from instance %s" % \ 175 (vol.id,self._instance.id)) 176 vol.detach() 177 time.sleep(5) 178 for i in self.security_group.instances(): 179 log.info("Shutting down instance %s" % i.id) 180 i.stop() 181 log.info("Removing security group %s" % \ 182 self.security_group.name) 183 self.security_group.delete() 184 return vol.id 185 except Exception,e: 186 log.error("exception thrown: %s" % e) 187 if self._volume: 188 self._volume.detach() 189 time.sleep(5) 190 if self._instance: 191 self._instance.stop()
192