Esempio n. 1
0
 def read(self, param):
     try:
         with open(os.path.join(self.path, param)) as f:
             for line in f.readlines():
                 yield line.split()
     except IOError, e:
         msg = "Cgroup read error: %s/%s: %s" % (self.path, param, e)
         logger.error(msg)
Esempio n. 2
0
 def write(self, param, value):
     try:
         with open(os.path.join(self.path, param), 'w') as f:
             f.write(value)
             logger.info("Writing cgroup: %s: %s" % (param, value))
     except IOError, e:
         msg = "Cgroup write error: %s/%s: %s" % (self.path, param, e)
         logger.error(msg)
Esempio n. 3
0
 def remove(self, path):
     for i in range(0, 10):
         try:
             return execute('lvremove', path, force=None)
         except ProcessError:
             sleep(1)
             continue
     logger.error("Failed to delete volume '%s' after 10 tries" % path)
     raise
Esempio n. 4
0
File: volume.py Progetto: audip/lunr
    def _assign_node(self, volume, backup, source, nodes):
        """
        Assigns the new volume to a node.

        :returns: dict, node response on successful placement

        :raises: HTTPError
        """
        request_params = {
            'account': self.account_id,
            'size': volume.size,
            'read_iops': volume.volume_type.read_iops,
            'write_iops': volume.volume_type.write_iops,
        }
        if volume.image_id:
            request_params['image_id'] = volume.image_id
        if backup:
            request_params['backup_source_volume_id'] = backup.volume.name
            request_params['backup_id'] = backup.id
            volume.restore_of = backup.id
        if source:
            request_params['source_volume_id'] = source.name
            request_params['source_host'] = source.node.hostname
            request_params['source_port'] = source.node.port

        last_node_error = None
        for node in nodes:
            volume.node = node
            self.db.commit()  # prevent duplicate/lost volumes
            try:
                path = '/volumes/%s' % volume.name
                return self.node_request(node, 'PUT', path, **request_params)
            except NodeError, e:
                last_node_error = e
                # log server errors and continue
                if (e.code // 100) == 5:
                    logger.error(str(e))
                    continue
                # pass client error up to user, immediately
                break
Esempio n. 5
0
File: base.py Progetto: audip/lunr
def get_registration_exceptions(local_info, node_info):
    exceptions = {}
    for k, v in local_info.items():
        if 'hostname' in k and node_info[k] != v:
            try:
                node_value = socket.gethostbyname(node_info[k])
            except socket.error:
                # skip hostname translation on failure
                pass
        else:
            try:
                node_value = node_info[k]
            except KeyError, e:
                logger.error("During registration; missing '%s' key in api "
                             "server response" % k)
                continue
        if node_value != v:
            logger.warning("Invalid '%s' registered "
                           "as %r != %r" % (k, node_value, v))
            exceptions[k] = v
        else:
            logger.info("Verified '%s' registered as '%s'" % (k, v))
Esempio n. 6
0
    def create_clone(self, volume_id, clone_id, iqn, iscsi_ip, iscsi_port,
                     callback=None, lock=None, cinder=None):
        volume = self.get(volume_id)
        size = volume['size'] / 1024 / 1024 / 1024
        logger.info("Cloning source '%s' to volume '%s'" %
                    (volume_id, clone_id))
        snapshot_name = uuid.uuid4()
        snapshot = self.create_snapshot(volume_id, snapshot_name,
                                        clone_id=clone_id, type_='clone')
        logger.info("Snapshot to clone id: '%s'" % snapshot['id'])
        try:
            new_volume = ISCSIDevice(iqn, iscsi_ip, iscsi_port)
            new_volume.connect()
        except (ISCSILoginFailed, ISCSINotConnected):
            msg = "Unable to open iscsi connection to %s:%s - %s" % \
                  (iscsi_ip, iscsi_port, iqn)
            logger.error(msg)
            self.delete(snapshot['id'])
            raise ServiceUnavailable(msg)

        spawn(lock, self._copy_clone, snapshot, clone_id, size, new_volume,
              cinder, callback=callback, skip_fork=self.skip_fork)
Esempio n. 7
0
File: wsgi.py Progetto: audip/lunr
 def __call__(self, request):
     """Handle WSGI request."""
     try:
         try:
             # Call the implementation to handle the action
             return self.encode_response(self.call(request))
         except HTTPException:
             raise
         except Exception, e:
             logger.exception("Caught unknown exception, traceback dumped")
             raise HTTPInternalServerError("Internal controller error")
     except HTTPException, e:
         # Avoid logging HTTPOk Exceptions
         if isinstance(e, HTTPError):
             logger.error("%s" % e)
         # (thrawn01) returning a HTTPError exception to WSGI
         # container would result in a text/html content type
         # provided by webob, this is not desired
         body = {
             'reason': e.detail,
             'request-id': request.headers.get('x-request-id', '-')
         }
         return self.encode_response(Response(body=body, status=e.status))
Esempio n. 8
0
 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)
Esempio n. 9
0
            path = '/volumes/%s/clones/%s' % (source['id'], volume['id'])
            node_params = {
                'account': req.params.get('account', ''),
                'iqn': export['name'],
                'iscsi_ip': self.helper.storage_host,
                'iscsi_port': self.helper.storage_port,
                # First dirty method to close the export.
                'mgmt_host': self.helper.management_host,
                'mgmt_port': self.helper.management_port,
                'cinder_host': self.helper.cinder_host,
            }
            try:
                self.helper.node_request(source['host'], source['port'], 'PUT',
                                         path, **node_params)
            except NodeError, e:
                logger.error('Clone node request failed: %s' % e)
                self.helper.exports.delete(volume['id'])
                self.helper.volumes.delete(volume['id'], lock=lock)
                raise

            volume['status'] = 'CLONING'
        # Create from image
        elif req.params.get('image_id'):
            image_id = params['image_id'] = req.params['image_id']
            account = params['account'] = req.params.get('account')

            params['callback'] = self._create_from_image_cb(req, iops)
            params['scrub_callback'] = self._post_scrub_cb()
            try:
                self.helper.volumes.create(self.id, **params)
            except InvalidImage, e:
Esempio n. 10
0
File: volume.py Progetto: audip/lunr
            path = '/volumes/%s/clones/%s' % (source['id'], volume['id'])
            node_params = {
                'account': req.params.get('account', ''),
                'iqn': export['name'],
                'iscsi_ip': self.helper.storage_host,
                'iscsi_port': self.helper.storage_port,
                # First dirty method to close the export.
                'mgmt_host': self.helper.management_host,
                'mgmt_port': self.helper.management_port,
                'cinder_host': self.helper.cinder_host,
            }
            try:
                self.helper.node_request(source['host'], source['port'],
                                         'PUT', path, **node_params)
            except NodeError, e:
                logger.error('Clone node request failed: %s' % e)
                self.helper.exports.delete(volume['id'])
                self.helper.volumes.delete(volume['id'], lock=lock)
                raise

            volume['status'] = 'CLONING'
        # Create from image
        elif req.params.get('image_id'):
            image_id = params['image_id'] = req.params['image_id']
            account = params['account'] = req.params.get('account')

            params['callback'] = self._create_from_image_cb(req, iops)
            params['scrub_callback'] = self._post_scrub_cb()
            try:
                self.helper.volumes.create(self.id, **params)
            except InvalidImage, e:
Esempio n. 11
0
                else:
                    convert_gbs = self.convert_gbs
                tmp_vol = self.create_convert_scratch(image, convert_gbs)
            except GlanceError, e:
                logger.warning("Error fetching glance image: %s" % e)
                raise InvalidImage("Error fetching image: %s" % image_id)

        # Create a tag to apply to the lvm volume
        tag = encode_tag(backup_source_volume_id=backup_source_volume_id,
                         backup_id=backup_id)

        try:
            self._do_create(volume_id, size_str, tag, backup_source_volume_id)
        except Exception, e:
            # If we ran out of space due to the tmp_vol
            logger.error('Failed to create volume: %s' % e)
            # Update cinder immediately.
            if callback:
                callback()
            if tmp_vol:
                spawn(NullResource(), self.remove_lvm_volume, tmp_vol,
                      callback=scrub_callback, skip_fork=self.skip_fork)
            raise

        def log_duration():
            duration = time() - op_start

            parts = ['STAT: Create Volume']
            if volume_id:
                parts.append('Volume_ID: %s' % (volume_id,))
            if backup_id:
Esempio n. 12
0
class CgroupHelper(object):
    cgroup_parameters = [
        'blkio.throttle.read_iops_device',
        'blkio.throttle.write_iops_device',
    ]

    def __init__(self, conf):
        sys_fs_path = conf.string('cgroup', 'cgroup_path',
                                  '/sys/fs/cgroup/blkio/sysdefault')
        self.cgroup_fs = CgroupFs(sys_fs_path)
        run_dir = conf.string('storage', 'run_dir', conf.path('run'))
        self.cgroups_path = os.path.join(run_dir, 'cgroups')

    def _updates_path(self):
        return os.path.join(self.cgroups_path, 'updates')

    def all_cgroups(self):
        data = defaultdict(dict)
        for name in self.cgroup_parameters:
            for device, throttle in self.cgroup_fs.read(name):
                data[name][device] = throttle
        return data

    def get(self, volume):
        device = volume['device_number']
        data = {}
        cgroups = self.all_cgroups()
        for name, device_map in cgroups.items():
            if device in device_map:
                data[name] = device_map[device]
        return data

    def set_read_iops(self, volume, throttle):
        self.set(volume, throttle, 'blkio.throttle.read_iops_device')

    def set_write_iops(self, volume, throttle):
        self.set(volume, throttle, 'blkio.throttle.write_iops_device')

    def set(self, volume, throttle, param=None):
        if not param:
            params = self.cgroup_parameters
        else:
            params = [param]
        throttle = int(throttle)
        if throttle < 0:
            raise ValueError("Throttle cannot be negative")
        device = volume['device_number']
        for name in params:
            value = "%s %s" % (device, throttle)
            self.cgroup_fs.write(name, value)
            self.save_update(volume, name, throttle)

    def save_update(self, volume, name, throttle):
        try:
            os.makedirs(self.cgroups_path)
        except OSError, e:
            if e.errno != errno.EEXIST:
                raise
        try:
            with open(self._updates_path(), 'a') as f:
                fcntl.lockf(f.fileno(), fcntl.LOCK_EX)
                entry = '%s %s %s\n' % (volume['id'], name, throttle)
                f.write(entry)
        except IOError, e:
            logger.error('Failed writing cgroup update: %s' % e)
Esempio n. 13
0
                else:
                    convert_gbs = self.convert_gbs
                tmp_vol = self.create_convert_scratch(image, convert_gbs)
            except GlanceError, e:
                logger.warning("Error fetching glance image: %s" % e)
                raise InvalidImage("Error fetching image: %s" % image_id)

        # Create a tag to apply to the lvm volume
        tag = encode_tag(backup_source_volume_id=backup_source_volume_id,
                         backup_id=backup_id)

        try:
            self._do_create(volume_id, size_str, tag, backup_source_volume_id)
        except Exception, e:
            # If we ran out of space due to the tmp_vol
            logger.error('Failed to create volume: %s' % e)
            # Update cinder immediately.
            if callback:
                callback()
            if tmp_vol:
                spawn(NullResource(),
                      self.remove_lvm_volume,
                      tmp_vol,
                      callback=scrub_callback,
                      skip_fork=self.skip_fork)
            raise

        def log_duration():
            duration = time() - op_start

            parts = ['STAT: Create Volume']