def create_snapshot(self, volume_id, snapshot_id, timestamp=None, type_='backup', clone_id=None): snapshot = self._get_snapshot(volume_id) if snapshot: if type_ == 'backup': if snapshot['id'] == snapshot_id: return snapshot elif type_ == 'clone': if snapshot.get('clone_id') == clone_id: return snapshot raise AlreadyExists( "Volume %s already has a snapshot." % volume_id) origin = self.get(volume_id) # TODO: support size as kwarg or % of origin.size? sizestr = '%sB' % self._max_snapshot_size(origin['size']) if type_ == 'backup': # TODO: should we prevent create snapshot if timestamp is too old? timestamp = int(timestamp or time()) tag = encode_tag(backup_id=snapshot_id, timestamp=timestamp) elif type_ == 'clone': tag = encode_tag(clone_id=clone_id) else: raise ValueError("Invalid snapshot type: %s" % type_) try: # Create an lvm snapshot execute('lvcreate', origin['path'], name=snapshot_id, size=sizestr, snapshot=None, addtag=tag) return self.get(snapshot_id) except ProcessError, e: if e.errcode != 5 or 'already exists' not in e.err: raise raise AlreadyExists("snapshot id '%s' already in use" % id)
def _do_create(self, volume_id, size_str, tag, backup_source_volume_id=None): try: out = execute('lvcreate', self.volume_group, name=volume_id, size=size_str, addtag=tag) except ProcessError, e: if not e.errcode == 5 and 'already exists' not in e.err: raise # We ran out of space on the storage node! if "Insufficient free extents" in e.err \ or "insufficient free space" in e.err: logger.error(e.err) raise ServiceUnavailable("LVM reports insufficient " "free space on drive") # If we are requesting a restore, and the existing volume is this # same failed restore, it's not an error. if backup_source_volume_id and backup_source_volume_id == \ self.get(volume_id).get('backup_source_volume_id', False): logger.info("Restarting failed restore on '%s'" % volume_id) else: raise AlreadyExists("Unable to create a new volume named " "'%s' because one already exists." % volume_id)
def create(self, id, ip=None): with lock.ResourceFile(self._build_lock_path(id)): try: # see if an export was created while we were locking self.get(id) except NotFound: pass else: raise AlreadyExists("An export already exists for " "volume '%s'" % id) # create target params = {'Name': self._generate_target_name(id)} try: out = self.ietadm(op='new', tid='auto', params=params) except InvalidArgument: logger.exception("Unable to create target for '%s'" % id) raise ServiceUnavailable("Invalid argument while trying to " "create export for '%s'" % id) # lookup tid tid = self._get_tid(id) # add lun path = self._lun_path(id) params = {'Path': path, 'Type': 'blockio'} try: out += self.ietadm(op='new', tid=tid, lun=0, params=params) except (NoSuchFile, NotPermitted): # clean up the target self.delete(id) if not os.path.exists(path): raise NotFound("No volume named '%s'" % id) logger.exception('Unable to create export for %s' % id) raise ServiceUnavailable("Invalid param trying to create " "export for '%s'" % id) # Write the new exports to the iet config exports = self.rewrite_config() if ip: self.add_initiator_allow(id, ip) return self.get(id, exports=exports)