예제 #1
0
    def test_volume_put_minimal_body(self, etcd_client, volume_raw_ok_ready,
                                     volume_raw_requested_ok, flask_app):
        volume = etcd_client.write(VolumeManager.KEY, volume_raw_ok_ready, append=True)
        id = flask_app.volume_manager.get_id_from_key(volume.key)

        volume = flask_app.volume_manager._load_from_etcd([volume])[0]
        expected, errors = VolumeSchema().dump(volume)
        assert errors == {}

        expected['state'] = 'pending'
        expected['requested'], errors = VolumeAttributeSchema().loads(
            volume_raw_requested_ok)
        assert errors == {}

        with flask_app.test_client() as c:
            response = c.put('/volumes/{}'.format(id),
                             data=volume_raw_requested_ok,
                             content_type='application/json')

            result, errors = VolumeSchema().loads(response.data.decode())

            assert errors == {}
            assert result['id'] == id
            assert response.status_code == 202
            assert expected == result
            assert response.headers[
                       'Location'] == 'http://localhost/volumes/{}'.format(id)
예제 #2
0
    def post():
        """It will create a volume with the given input as a starting point.

        Returns:
             tuple: payload, http status code, headers
        """
        manager = app.volume_manager
        request_json = request.get_json(force=True)

        request_id = request_json.get('id', '')

        fields = (
            'name',
            'meta',
            'requested',
        )
        data, errors = VolumeSchema(only=fields).load(request_json)
        if errors:
            return {'message': errors}, 400

        data['node'] = ''
        data['state'] = 'scheduling'
        data['actual'] = {}
        data['control'] = {
            'error': '',
            'error_count': 0,
            'parent_id': request_id
        }

        lock = manager.get_lock(request_id, 'clone')

        if request_id:
            lock.acquire(timeout=0, lock_ttl=10)

            data['state'] = 'pending'
            parent = manager.by_id(request_id)
            if not parent:
                lock.release()
                return {
                    'message': 'Parent does not exist. Clone not created'
                }, 400

            parent_state = parent.value['state']
            if parent_state in ['deleting', 'scheduling']:
                lock.release()
                return {
                    'message':
                    'Parent can\'t have state {} '
                    'in order to clone'.format(parent_state)
                }, 400

        volume = manager.create(data)
        if request_id:
            lock.release()

        result, _ = VolumeSchema().dump(volume)
        return result, 202, {
            'Location': app.api.url_for(Volume, volume_id=result['id'])
        }
예제 #3
0
    def get():
        """It will return a list of all the volumes

        Returns:
             tuple: payload, http status code
        """
        result, _ = VolumeSchema().dump(app.volume_manager.all()[1], many=True)
        return result
예제 #4
0
    def test_volume_get(self, etcd_client, volume_raw_ok_ready, flask_app):
        volume = etcd_client.write(VolumeManager.KEY, volume_raw_ok_ready, append=True)
        id = flask_app.volume_manager.get_id_from_key(volume.key)

        volume = flask_app.volume_manager._load_from_etcd([volume])[0]
        expected, errors = VolumeSchema().dump(volume)
        assert errors == {}

        with flask_app.test_client() as c:
            response = c.get('/volumes/{}'.format(id))

            actual = json.loads(response.data.decode())

            assert actual == expected
            assert response.status_code == 200
예제 #5
0
    def delete(volume_id):
        """Deletes the volume pointed by the id.

        Args:
            volume_id (str): The id parsed from the URL

        Returns:
            tuple: payload, http status code, headers
        """
        manager = app.volume_manager

        target_volume = manager.by_id(volume_id)
        if target_volume is None:
            return {'message': 'Not Found'}, 404

        if target_volume.value['state'] != 'ready':
            return {
                'message': 'Resource not in ready state, can\'t delete.'
            }, 409

        lock = manager.get_lock(volume_id, 'clone')
        lock.acquire(timeout=0, lock_ttl=10)

        pending_clones = []
        for volume in manager.all()[1]:
            if volume.value['control']['parent_id'] == volume_id:
                pending_clones.append(manager.get_id_from_key(volume.key))

        if pending_clones:
            lock.release()
            return {
                'message': 'Resource has pending clones, can\'t delete.',
                'clones': pending_clones
            }, 409

        target_volume.value['state'] = 'deleting'
        target_volume = manager.update(target_volume)
        lock.release()

        if not target_volume:
            return {'message': 'Resource changed during transition.'}, 409

        result, _ = VolumeSchema().dump(target_volume)
        return result, 202, {
            'Location': app.api.url_for(Volume, volume_id=result['id'])
        }
예제 #6
0
    def get(volume_id):
        """Returns a volume dict as a json response or 404 if not found.

        Args:
            volume_id (str): The id parsed from the URL

        Returns:
            tuple: payload, http status code
        """
        manager = app.volume_manager
        volume = manager.by_id(volume_id)

        if volume is None:
            return {'message': 'Not Found'}, 404

        result, _ = VolumeSchema().dump(volume)
        return result, 200
예제 #7
0
    def put(volume_id):
        """Edits a volume dict based on the given representation.

        Expects to receive a json payload with a complete new version of the volume to be edited

        Args:
            volume_id (str): The id parsed from the URL

        Returns:
             tuple: payload, http status code, headers
        """
        manager = app.volume_manager

        volume = manager.by_id(volume_id)
        if volume is None:
            return {'message': 'Not Found'}, 404

        if volume.value['state'] != 'ready':
            return {
                'message': 'Resource not in ready state, can\'t update.'
            }, 409

        new_volume, errors = VolumeAttributeSchema().load(
            request.get_json(force=True))
        if errors:
            return {'message': errors}, 400

        if volume.value['requested'] == new_volume:
            return '', 304

        volume.value['requested'] = new_volume
        volume.value['state'] = 'pending'

        volume = manager.update(volume)
        if not volume:
            return {'message': 'Resource changed during transition.'}, 409

        result, _ = VolumeSchema().dump(volume)
        return result, 202, {
            'Location': app.api.url_for(Volume, volume_id=result['id'])
        }
예제 #8
0
    def test_volume_list_get(self, etcd_client, volume_raw_ok_ready,
                             flask_app):
        generators = [volume_raw_ok_ready, volume_raw_ok_ready]

        volume_writes = []
        for generator in generators:
            volume_writes.append(
                etcd_client.write(VolumeManager.KEY, generator, append=True))
        volume_writes = flask_app.volume_manager._load_from_etcd(volume_writes)

        expected, errors = VolumeSchema().dump(volume_writes, many=True)
        assert errors == {}

        with flask_app.test_client() as c:
            response = c.get('/volumes')
            assert response.status_code == 200

            actual = json.loads(response.data.decode())

        assert len(actual) == len(expected)
        assert actual == expected