コード例 #1
0
    def post(self, **kwargs):
        LOG.info("Creating function, params=%s", kwargs)

        if not POST_REQUIRED.issubset(set(kwargs.keys())):
            raise exc.InputException(
                'Required param is missing. Required: %s' % POST_REQUIRED)

        runtime = db_api.get_runtime(kwargs['runtime_id'])
        if runtime.status != 'available':
            raise exc.InputException('Runtime %s not available.' %
                                     kwargs['runtime_id'])

        values = {
            'name': kwargs['name'],
            'description': kwargs.get('description', None),
            'runtime_id': kwargs['runtime_id'],
            'code': json.loads(kwargs['code']),
            'entry': kwargs.get('entry', 'main'),
        }

        if values['code'].get('package', False):
            data = kwargs['package'].file.read()

        ctx = context.get_ctx()

        with db_api.transaction():
            func_db = db_api.create_function(values)

            self.storage_provider.store(ctx.projectid, func_db.id, data)

        pecan.response.status = 201
        return resources.Function.from_dict(func_db.to_dict()).to_dict()
コード例 #2
0
ファイル: default_engine.py プロジェクト: sampathP/qinling
    def create_execution(self,
                         ctx,
                         execution_id,
                         function_id,
                         runtime_id,
                         input=None):
        LOG.info(
            'Creating execution. execution_id=%s, function_id=%s, '
            'runtime_id=%s', execution_id, function_id, runtime_id)

        with db_api.transaction():
            execution = db_api.get_execution(execution_id)
            runtime = db_api.get_runtime(runtime_id)
            identifier = '%s-%s' % (runtime_id, runtime.name)
            labels = {'runtime_name': runtime.name, 'runtime_id': runtime_id}

            service_url = self.orchestrator.prepare_execution(
                function_id, identifier=identifier, labels=labels)

            output = self.orchestrator.run_execution(function_id,
                                                     input=input,
                                                     service_url=service_url)

            LOG.debug('Finished execution. execution_id=%s, output=%s',
                      execution_id, output)

            execution.output = output
            execution.status = 'success'

            mapping = {'function_id': function_id, 'service_url': service_url}
            db_api.create_function_service_mapping(mapping)
コード例 #3
0
    def post(self, **kwargs):
        LOG.info("Creating %s, params: %s", self.type, kwargs)

        # When using image to create function, runtime_id is not a required
        # param.
        if not POST_REQUIRED.issubset(set(kwargs.keys())):
            raise exc.InputException(
                'Required param is missing. Required: %s' % POST_REQUIRED)

        values = {
            'name': kwargs.get('name'),
            'description': kwargs.get('description'),
            'runtime_id': kwargs.get('runtime_id'),
            'code': json.loads(kwargs['code']),
            'entry': kwargs.get('entry', 'main.main'),
        }

        source = values['code'].get('source')
        if not source or source not in CODE_SOURCE:
            raise exc.InputException(
                'Invalid code source specified, available sources: %s' %
                ', '.join(CODE_SOURCE))

        if source != constants.IMAGE_FUNCTION:
            if not kwargs.get('runtime_id'):
                raise exc.InputException('"runtime_id" must be specified.')

            runtime = db_api.get_runtime(kwargs['runtime_id'])
            if runtime.status != 'available':
                raise exc.InputException('Runtime %s is not available.' %
                                         kwargs['runtime_id'])

        store = False
        if values['code']['source'] == constants.PACKAGE_FUNCTION:
            store = True
            data = kwargs['package'].file.read()
        elif values['code']['source'] == constants.SWIFT_FUNCTION:
            swift_info = values['code'].get('swift', {})
            self._check_swift(swift_info.get('container'),
                              swift_info.get('object'))

        if cfg.CONF.pecan.auth_enable:
            try:
                values['trust_id'] = keystone_util.create_trust().id
                LOG.debug('Trust %s created', values['trust_id'])
            except Exception:
                raise exc.TrustFailedException(
                    'Trust creation failed for function.')

        with db_api.transaction():
            func_db = db_api.create_function(values)

            if store:
                ctx = context.get_ctx()

                self.storage_provider.store(ctx.projectid, func_db.id, data)

        pecan.response.status = 201
        return resources.Function.from_dict(func_db.to_dict()).to_dict()
コード例 #4
0
    def post(self, **kwargs):
        LOG.info("Creating %s, params: %s", self.type, kwargs)

        # When using image to create function, runtime_id is not a required
        # param.
        if not POST_REQUIRED.issubset(set(kwargs.keys())):
            raise exc.InputException(
                'Required param is missing. Required: %s' % POST_REQUIRED)

        values = {
            'name': kwargs['name'],
            'description': kwargs.get('description'),
            'runtime_id': kwargs.get('runtime_id'),
            'code': json.loads(kwargs['code']),
            'entry': kwargs.get('entry', 'main.main'),
        }

        source = values['code'].get('source')
        if not source or source not in CODE_SOURCE:
            raise exc.InputException(
                'Invalid code source specified, available sources: %s' %
                ', '.join(CODE_SOURCE))

        if source != 'image':
            if not kwargs.get('runtime_id'):
                raise exc.InputException('"runtime_id" must be specified.')

            runtime = db_api.get_runtime(kwargs['runtime_id'])
            if runtime.status != 'available':
                raise exc.InputException('Runtime %s is not available.' %
                                         kwargs['runtime_id'])

        store = False
        if values['code']['source'] == 'package':
            store = True
            data = kwargs['package'].file.read()
        elif values['code']['source'] == 'swift':
            # Auth needs to be enabled because qinling needs to check swift
            # object using user's credential.
            if not CONF.pecan.auth_enable:
                raise exc.InputException('Swift object not supported.')

            container = values['code']['swift'].get('container')
            object = values['code']['swift'].get('object')

            if not swift_util.check_object(container, object):
                raise exc.InputException('Object does not exist in Swift.')

        with db_api.transaction():
            func_db = db_api.create_function(values)

            if store:
                ctx = context.get_ctx()

                self.storage_provider.store(ctx.projectid, func_db.id, data)

        pecan.response.status = 201
        return resources.Function.from_dict(func_db.to_dict()).to_dict()
コード例 #5
0
    def put(self, id, runtime):
        """Update runtime.

        Currently, we support update name, description, image. When
        updating image, send message to engine for asynchronous
        handling.
        """
        acl.enforce('runtime:update', context.get_ctx())

        values = {}
        for key in UPDATE_ALLOWED:
            if runtime.to_dict().get(key) is not None:
                values.update({key: runtime.to_dict()[key]})

        LOG.info('Update resource, params: %s',
                 values,
                 resource={
                     'type': self.type,
                     'id': id
                 })

        image = values.get('image')

        with db_api.transaction():
            if image is not None:
                pre_runtime = db_api.get_runtime(id)
                if pre_runtime.status != status.AVAILABLE:
                    raise exc.RuntimeNotAvailableException(
                        'Runtime %s is not available.' % id)

                pre_image = pre_runtime.image
                if pre_image != image:
                    # Ensure there is no function running in the runtime.
                    db_funcs = db_api.get_functions(insecure=True,
                                                    fields=['id'],
                                                    runtime_id=id)
                    func_ids = [func.id for func in db_funcs]

                    for id in func_ids:
                        if etcd_util.get_service_url(id):
                            raise exc.NotAllowedException(
                                'Runtime %s is still in use by functions.' %
                                id)

                    values['status'] = status.UPGRADING
                    self.engine_client.update_runtime(
                        id,
                        image=image,
                        pre_image=pre_image,
                    )

            runtime_db = db_api.update_runtime(id, values)

        return resources.Runtime.from_db_obj(runtime_db)
コード例 #6
0
    def test_create_runtime(self):
        runtime = self.create_runtime()
        runtime_id = runtime.id
        # Set status to verify it is changed during creation.
        db_api.update_runtime(runtime_id, {'status': status.CREATING})

        self.default_engine.create_runtime(mock.Mock(), runtime_id)

        self.orchestrator.create_pool.assert_called_once_with(
            runtime_id, runtime.image)
        runtime = db_api.get_runtime(runtime_id)
        self.assertEqual(status.AVAILABLE, runtime.status)
コード例 #7
0
ファイル: default_engine.py プロジェクト: sampathP/qinling
    def delete_runtime(self, ctx, runtime_id):
        LOG.info('Start to delete runtime, id=%s', runtime_id)

        with db_api.transaction():
            runtime = db_api.get_runtime(runtime_id)
            identifier = '%s-%s' % (runtime_id, runtime.name)
            labels = {'runtime_name': runtime.name, 'runtime_id': runtime_id}

            self.orchestrator.delete_pool(identifier, labels=labels)

            db_api.delete_runtime(runtime_id)

            LOG.info('Runtime %s deleted.', runtime_id)
コード例 #8
0
    def test_create_runtime_failed(self):
        runtime = self.create_runtime()
        runtime_id = runtime.id
        # Set status to verify it is changed during creation.
        db_api.update_runtime(runtime_id, {'status': status.CREATING})
        self.orchestrator.create_pool.side_effect = RuntimeError

        self.default_engine.create_runtime(mock.Mock(), runtime_id)

        self.orchestrator.create_pool.assert_called_once_with(
            runtime_id, runtime.image, trusted=True)
        runtime = db_api.get_runtime(runtime_id)
        self.assertEqual(status.ERROR, runtime.status)
コード例 #9
0
ファイル: runtime.py プロジェクト: huzhengchuan/qinling
    def put(self, id, runtime):
        """Update runtime.

        Currently, we only support update name, description, image. When
        updating image, send message to engine for asynchronous handling.
        """
        values = {}
        for key in UPDATE_ALLOWED:
            if runtime.to_dict().get(key) is not None:
                values.update({key: runtime.to_dict()[key]})

        LOG.info('Update resource, params: %s',
                 values,
                 resource={
                     'type': self.type,
                     'id': id
                 })

        with db_api.transaction():
            if 'image' in values:
                pre_runtime = db_api.get_runtime(id)
                if pre_runtime.status != status.AVAILABLE:
                    raise exc.RuntimeNotAvailableException(
                        'Runtime %s is not available.' % id)

                pre_image = pre_runtime.image
                if pre_image != values['image']:
                    # Ensure there is no function running in the runtime.
                    db_funcs = db_api.get_functions(insecure=True,
                                                    fields=['id'],
                                                    runtime_id=id)
                    func_ids = [func.id for func in db_funcs]

                    mappings = db_api.get_function_service_mappings(
                        insecure=True, function_id={'in': func_ids})
                    if mappings:
                        raise exc.NotAllowedException(
                            'Runtime %s is still in use by functions.' % id)

                    values['status'] = status.UPGRADING

                    self.engine_client.update_runtime(id,
                                                      image=values['image'],
                                                      pre_image=pre_image)
                else:
                    values.pop('image')

            runtime_db = db_api.update_runtime(id, values)

        return resources.Runtime.from_dict(runtime_db.to_dict())
コード例 #10
0
ファイル: default_engine.py プロジェクト: baikai/qinling
    def create_runtime(self, ctx, runtime_id):
        LOG.info('Start to create runtime %s.', runtime_id)

        with db_api.transaction():
            runtime = db_api.get_runtime(runtime_id)

            try:
                self.orchestrator.create_pool(runtime_id, runtime.image)
                runtime.status = status.AVAILABLE
                LOG.info('Runtime %s created.', runtime_id)
            except Exception as e:
                LOG.exception(
                    'Failed to create pool for runtime %s. Error: %s',
                    runtime_id, str(e))
                runtime.status = status.ERROR
コード例 #11
0
    def test_update_runtime(self):
        runtime = self.create_runtime()
        runtime_id = runtime.id
        # Set status to verify it is changed during update.
        db_api.update_runtime(runtime_id, {'status': status.UPGRADING})
        image = self.rand_name('new_image', prefix=self.prefix)
        pre_image = self.rand_name('pre_image', prefix=self.prefix)
        self.orchestrator.update_pool.return_value = True

        self.default_engine.update_runtime(mock.Mock(), runtime_id, image,
                                           pre_image)

        self.orchestrator.update_pool.assert_called_once_with(runtime_id,
                                                              image=image)
        runtime = db_api.get_runtime(runtime_id)
        self.assertEqual(runtime.status, status.AVAILABLE)
コード例 #12
0
ファイル: runtime.py プロジェクト: huzhengchuan/qinling
    def delete(self, id):
        LOG.info("Delete resource.", resource={'type': self.type, 'id': id})

        with db_api.transaction():
            runtime_db = db_api.get_runtime(id)

            # Runtime can not be deleted if still associate with functions.
            funcs = db_api.get_functions(runtime_id={'eq': id})
            if len(funcs):
                raise exc.NotAllowedException('Runtime %s is still in use.' %
                                              id)

            runtime_db.status = status.DELETING

        # Clean related resources asynchronously
        self.engine_client.delete_runtime(id)
コード例 #13
0
ファイル: runtime.py プロジェクト: sampathP/qinling
    def delete(self, id):
        """Delete runtime."""

        LOG.info("Delete runtime [id=%s]", id)

        with db_api.transaction():
            runtime_db = db_api.get_runtime(id)

            # Runtime can not be deleted if still associate with functions.
            funcs = db_api.get_functions(runtime_id={'eq': id})
            if len(funcs):
                raise exc.NotAllowedException(
                    'Runtime %s is still in use.' % id
                )

            runtime_db.status = 'deleting'

        # Clean related resources asynchronously
        self.engine_client.delete_runtime(id)
コード例 #14
0
ファイル: default_engine.py プロジェクト: sampathP/qinling
    def create_runtime(self, ctx, runtime_id):
        LOG.info('Start to create runtime, id=%s', runtime_id)

        with db_api.transaction():
            runtime = db_api.get_runtime(runtime_id)
            identifier = '%s-%s' % (runtime_id, runtime.name)
            labels = {'runtime_name': runtime.name, 'runtime_id': runtime_id}

            try:
                self.orchestrator.create_pool(
                    identifier,
                    runtime.image,
                    labels=labels,
                )

                runtime.status = 'available'
            except Exception as e:
                LOG.exception(
                    'Failed to create pool for runtime %s. Error: %s',
                    runtime_id, str(e))

                runtime.status = 'error'
コード例 #15
0
    def create_runtime(self, ctx, runtime_id):
        LOG.info('Start to create.',
                 resource={
                     'type': 'runtime',
                     'id': runtime_id
                 })

        with db_api.transaction():
            runtime = db_api.get_runtime(runtime_id)
            labels = {'runtime_id': runtime_id}

            try:
                self.orchestrator.create_pool(
                    runtime_id,
                    runtime.image,
                    labels=labels,
                )
                runtime.status = status.AVAILABLE
            except Exception as e:
                LOG.exception(
                    'Failed to create pool for runtime %s. Error: %s',
                    runtime_id, str(e))
                runtime.status = status.ERROR
コード例 #16
0
ファイル: runtime.py プロジェクト: baikai/qinling
    def get(self, id):
        LOG.info("Get resource.", resource={'type': self.type, 'id': id})

        runtime_db = db_api.get_runtime(id)

        return resources.Runtime.from_db_obj(runtime_db)
コード例 #17
0
ファイル: runtime.py プロジェクト: sampathP/qinling
    def get(self, id):
        LOG.info("Fetch runtime [id=%s]", id)

        runtime_db = db_api.get_runtime(id)

        return resources.Runtime.from_dict(runtime_db.to_dict())
コード例 #18
0
    def post(self, **kwargs):
        # When using image to create function, runtime_id is not a required
        # param.
        if not POST_REQUIRED.issubset(set(kwargs.keys())):
            raise exc.InputException(
                'Required param is missing. Required: %s' % POST_REQUIRED)
        LOG.info("Creating function, params: %s", kwargs)

        values = {
            'name':
            kwargs.get('name'),
            'description':
            kwargs.get('description'),
            'runtime_id':
            kwargs.get('runtime_id'),
            'code':
            json.loads(kwargs['code']),
            'entry':
            kwargs.get('entry', 'main.main'),
            'cpu':
            kwargs.get('cpu', CONF.resource_limits.default_cpu),
            'memory_size':
            kwargs.get('memory_size', CONF.resource_limits.default_memory),
            'timeout':
            kwargs.get('timeout', CONF.resource_limits.default_timeout),
        }

        common.validate_int_in_range('timeout', values['timeout'],
                                     CONF.resource_limits.min_timeout,
                                     CONF.resource_limits.max_timeout)
        common.validate_int_in_range('cpu', values['cpu'],
                                     CONF.resource_limits.min_cpu,
                                     CONF.resource_limits.max_cpu)
        common.validate_int_in_range('memory', values['memory_size'],
                                     CONF.resource_limits.min_memory,
                                     CONF.resource_limits.max_memory)

        source = values['code'].get('source')
        if not source or source not in CODE_SOURCE:
            raise exc.InputException(
                'Invalid code source specified, available sources: %s' %
                ', '.join(CODE_SOURCE))

        if source != constants.IMAGE_FUNCTION:
            if not kwargs.get('runtime_id'):
                raise exc.InputException('"runtime_id" must be specified.')

            runtime = db_api.get_runtime(kwargs['runtime_id'])
            if runtime.status != 'available':
                raise exc.InputException('Runtime %s is not available.' %
                                         kwargs['runtime_id'])

        store = False
        create_trust = True
        if source == constants.PACKAGE_FUNCTION:
            store = True
            md5sum = values['code'].get('md5sum')
            data = kwargs['package'].file.read()
        elif source == constants.SWIFT_FUNCTION:
            swift_info = values['code'].get('swift', {})

            if not (swift_info.get('container') and swift_info.get('object')):
                raise exc.InputException("Both container and object must be "
                                         "provided for swift type function.")

            self._check_swift(swift_info.get('container'),
                              swift_info.get('object'))
        else:
            create_trust = False
            values['entry'] = None

        if cfg.CONF.pecan.auth_enable and create_trust:
            try:
                values['trust_id'] = keystone_util.create_trust().id
                LOG.debug('Trust %s created', values['trust_id'])
            except Exception:
                raise exc.TrustFailedException(
                    'Trust creation failed for function.')

        # Create function and store the package data inside a db transaction so
        # that the function won't be created if any error happened during
        # package store.
        with db_api.transaction():
            func_db = db_api.create_function(values)
            if store:
                try:
                    ctx = context.get_ctx()
                    _, actual_md5 = self.storage_provider.store(ctx.projectid,
                                                                func_db.id,
                                                                data,
                                                                md5sum=md5sum)
                    values['code'].update({"md5sum": actual_md5})
                    func_db = db_api.update_function(func_db.id, values)
                except Exception as e:
                    LOG.exception("Failed to store function package.")
                    keystone_util.delete_trust(values['trust_id'])
                    raise e

        pecan.response.status = 201
        return resources.Function.from_db_obj(func_db).to_dict()
コード例 #19
0
ファイル: runtime.py プロジェクト: huzhengchuan/qinling
    def get(self, id):
        LOG.info("Fetch resource.", resource={'type': self.type, 'id': id})

        runtime_db = db_api.get_runtime(id)

        return resources.Runtime.from_dict(runtime_db.to_dict())
コード例 #20
0
ファイル: executions.py プロジェクト: baikai/qinling
def create_execution(engine_client, params):
    function_id = params['function_id']
    is_sync = params.get('sync', True)
    input = params.get('input')
    version = params.get('function_version', 0)

    func_db = db_api.get_function(function_id)
    runtime_id = func_db.runtime_id

    # Image type function does not need runtime
    if runtime_id:
        runtime_db = db_api.get_runtime(runtime_id)
        if runtime_db and runtime_db.status != status.AVAILABLE:
            raise exc.RuntimeNotAvailableException(
                'Runtime %s is not available.' % func_db.runtime_id)

    if version > 0:
        if func_db.code['source'] != constants.PACKAGE_FUNCTION:
            raise exc.InputException(
                "Can not specify version for %s type function." %
                constants.PACKAGE_FUNCTION)

        # update version count
        version_db = db_api.get_function_version(function_id, version)
        pre_version_count = version_db.count
        _update_function_version_db(version_db.id, pre_version_count)
    else:
        pre_count = func_db.count
        _update_function_db(function_id, pre_count)

    # input in params should be a string.
    if input:
        try:
            params['input'] = json.loads(input)
        except ValueError:
            params['input'] = {'__function_input': input}

    params.update({'status': status.RUNNING})
    db_model = db_api.create_execution(params)

    try:
        engine_client.create_execution(db_model.id,
                                       function_id,
                                       version,
                                       runtime_id,
                                       input=params.get('input'),
                                       is_sync=is_sync)
    except exc.QinlingException:
        # Catch RPC errors for executions:
        #   - for RemoteError in an RPC call, the execution status would be
        #     handled in the engine side;
        #   - for other exceptions in an RPC call or cast, the execution status
        #     would remain RUNNING so we should update it.
        db_model = db_api.get_execution(db_model.id)
        if db_model.status == status.RUNNING:
            db_model = db_api.update_execution(db_model.id,
                                               {'status': status.ERROR})
        return db_model

    if is_sync:
        # The execution should already be updated by engine service for sync
        # execution.
        db_model = db_api.get_execution(db_model.id)

    return db_model