Initial Kingbird framework code base ( part1:rest )

Fisrt patch to implement the framework of Kingbird, this is
the part1 for web service with keystone authentication
integrated, and API part with helloworld rest quest example.

Blueprint: https://blueprints.launchpad.net/kingbird/+spec/kingbird-framework

Change-Id: Ia33247132c6a4945f76f0819cf90acf6e8d2154d
Signed-off-by: Chaoyi Huang <joehuang@huawei.com>
This commit is contained in:
Chaoyi Huang 2015-11-09 11:31:19 +08:00
parent 811a157a29
commit 72fffc65fe
19 changed files with 1081 additions and 15 deletions

View File

@ -1,19 +1,24 @@
=============================== ===============================
kingbird Kingbird
=============================== ===============================
Kingbird is a centralised synchronization service for multi-region OpenStack deployments. Centralized service for multi-region OpenStack deployments.
Kingbird is an centralized OpenStack service that provides resource operation
and management across multiple OpenStack instances in a multi-region OpenStack
deployments. This service is part of the OPNFV Multisite project that intends
to address the use cases related to distributed cloud environments.
Kingbird provides features like centralized quota management, centralized view
for distributed virtual resources, global view for tenant level IP/MAC address
space management, synchronisation of ssh keys, images, flavors, security
groups, etc. across regions.
Please feel here a long description which must be at least 3 lines wrapped on
80 cols, so that distribution package maintainers can use it in their packages.
Note that this is a hard requirement.
* Free software: Apache license * Free software: Apache license
* Wiki:https://wiki.openstack.org/wiki/kingbird
* Documentation: http://docs.openstack.org/developer/kingbird * Documentation: http://docs.openstack.org/developer/kingbird
* Source: http://git.openstack.org/cgit/openstack/kingbird * Source: https://github.com/openstack/kingbird
* Bugs: http://bugs.launchpad.net/kingbird * Bugs: http://bugs.launchpad.net/kingbird
* Blueprints: https://launchpad.net/kingbird
Features
--------
* TODO

64
cmd/api.py Executable file
View File

@ -0,0 +1,64 @@
# Copyright 2015 Huawei Technologies Co., Ltd.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# Much of this module is based on the work of the Ironic team
# see http://git.openstack.org/cgit/openstack/ironic/tree/ironic/cmd/api.py
import sys
from oslo_config import cfg
from oslo_log import log as logging
import logging as std_logging
from werkzeug import serving
from kingbird.api import apicfg
from kingbird.api import app
from kingbird.common.i18n import _LI
from kingbird.common.i18n import _LW
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
def main():
apicfg.init(sys.argv[1:])
apicfg.setup_logging()
application = app.setup_app()
host = CONF.bind_host
port = CONF.bind_port
workers = CONF.api_workers
if workers < 1:
LOG.warning(_LW("Wrong worker number, worker = %(workers)s"), workers)
workers = 1
LOG.info(_LI("Server on http://%(host)s:%(port)s with %(workers)s"),
{'host': host, 'port': port, 'workers': workers})
serving.run_simple(host, port,
application,
processes=workers)
LOG.info(_LI("Configuration:"))
CONF.log_opt_values(LOG, std_logging.INFO)
if __name__ == '__main__':
main()

370
etc/api.conf Executable file
View File

@ -0,0 +1,370 @@
[DEFAULT]
# Print more verbose output (set logging level to INFO instead of default WARNING level).
# verbose = True
# Print debugging output (set logging level to DEBUG instead of default WARNING level).
# debug = False
# Where to store Kingbird state files. This directory must be writable by the
# user executing the agent.
# state_path = /var/lib/kingbird
# log_format = %(asctime)s %(levelname)8s [%(name)s] %(message)s
# log_date_format = %Y-%m-%d %H:%M:%S
# use_syslog -> syslog
# log_file and log_dir -> log_dir/log_file
# (not log_file) and log_dir -> log_dir/{binary_name}.log
# use_stderr -> stderr
# (not user_stderr) and (not log_file) -> stdout
# publish_errors -> notification system
# use_syslog = False
# syslog_log_facility = LOG_USER
# use_stderr = True
# log_file =
# log_dir =
# publish_errors = False
# Address to bind the API server to
# bind_host = 127.0.0.1
# Port the bind the API server to
# bind_port = 8118
# Paste configuration file
# api_paste_config = api-paste.ini
# (StrOpt) Hostname to be used by the kingbird server, agents and services
# running on this machine. All the agents and services running on this machine
# must use the same host value.
# The default value is hostname of the machine.
#
# host =
# admin_tenant_name = %SERVICE_TENANT_NAME%
# admin_user = %SERVICE_USER%
# admin_password = %SERVICE_PASSWORD%
# Enable or disable bulk create/update/delete operations
# allow_bulk = True
# Enable or disable pagination
# allow_pagination = False
# Enable or disable sorting
# allow_sorting = False
# Default maximum number of items returned in a single response,
# value == infinite and value < 0 means no max limit, and value must
# be greater than 0. If the number of items requested is greater than
# pagination_max_limit, server will just return pagination_max_limit
# of number of items.
# pagination_max_limit = -1
# =========== WSGI parameters related to the API server ==============
# Number of separate worker processes to spawn. The default, 0, runs the
# worker thread in the current process. Greater than 0 launches that number of
# child processes as workers. The parent process manages them.
# api_workers = 3
# Number of separate RPC worker processes to spawn. The default, 0, runs the
# worker thread in the current process. Greater than 0 launches that number of
# child processes as RPC workers. The parent process manages them.
# This feature is experimental until issues are addressed and testing has been
# enabled for various plugins for compatibility.
# rpc_workers = 0
# Timeout for client connections socket operations. If an
# incoming connection is idle for this number of seconds it
# will be closed. A value of '0' means wait forever. (integer
# value)
# client_socket_timeout = 900
# wsgi keepalive option. Determines if connections are allowed to be held open
# by clients after a request is fulfilled. A value of False will ensure that
# the socket connection will be explicitly closed once a response has been
# sent to the client.
# wsgi_keep_alive = True
# Sets the value of TCP_KEEPIDLE in seconds to use for each server socket when
# starting API server. Not supported on OS X.
# tcp_keepidle = 600
# Number of seconds to keep retrying to listen
# retry_until_window = 30
# Number of backlog requests to configure the socket with.
# backlog = 4096
# Max header line to accommodate large tokens
# max_header_line = 16384
# Enable SSL on the API server
# use_ssl = False
# Certificate file to use when starting API server securely
# ssl_cert_file = /path/to/certfile
# Private key file to use when starting API server securely
# ssl_key_file = /path/to/keyfile
# CA certificate file to use when starting API server securely to
# verify connecting clients. This is an optional parameter only required if
# API clients need to authenticate to the API server using SSL certificates
# signed by a trusted CA
# ssl_ca_file = /path/to/cafile
# ======== end of WSGI parameters related to the API server ==========
# The strategy to be used for auth.
# Supported values are 'keystone'(default), 'noauth'.
auth_strategy = noauth
[keystone_authtoken]
# auth_uri = http://162.3.111.227:35357/v3
# identity_uri = http://162.3.111.227:35357
# admin_tenant_name = service
# admin_user = kingbird
# admin_password = 1234
# auth_version = 3
[database]
# This line MUST be changed to actually run the plugin.
# Example:
# connection = mysql://root:pass@127.0.0.1:3306/neutron
# Replace 127.0.0.1 above with the IP address of the database used by the
# main neutron server. (Leave it as is if the database runs on this host.)
# connection = sqlite://
# NOTE: In deployment the [database] section and its connection attribute may
# be set in the corresponding core plugin '.ini' file. However, it is suggested
# to put the [database] section and its connection attribute in this
# configuration file.
# Database engine for which script will be generated when using offline
# migration
# engine =
# The SQLAlchemy connection string used to connect to the slave database
# slave_connection =
# Database reconnection retry times - in event connectivity is lost
# set to -1 implies an infinite retry count
# max_retries = 10
# Database reconnection interval in seconds - if the initial connection to the
# database fails
# retry_interval = 10
# Minimum number of SQL connections to keep open in a pool
# min_pool_size = 1
# Maximum number of SQL connections to keep open in a pool
# max_pool_size = 10
# Timeout in seconds before idle sql connections are reaped
# idle_timeout = 3600
# If set, use this value for max_overflow with sqlalchemy
# max_overflow = 20
# Verbosity of SQL debugging information. 0=None, 100=Everything
# connection_debug = 0
# Add python stack traces to SQL as comment strings
# connection_trace = False
# If set, use this value for pool_timeout with sqlalchemy
# pool_timeout = 10
[oslo_concurrency]
# Directory to use for lock files. For security, the specified directory should
# only be writable by the user running the processes that need locking.
# Defaults to environment variable OSLO_LOCK_PATH. If external locks are used,
# a lock path must be set.
lock_path = $state_path/lock
# Enables or disables inter-process locks.
# disable_process_locking = False
[oslo_policy]
# The JSON file that defines policies.
# policy_file = policy.json
# Default rule. Enforced when a requested rule is not found.
# policy_default_rule = default
# Directories where policy configuration files are stored.
# They can be relative to any directory in the search path defined by the
# config_dir option, or absolute paths. The file defined by policy_file
# must exist for these directories to be searched. Missing or empty
# directories are ignored.
# policy_dirs = policy.d
[oslo_messaging_amqp]
#
# From oslo.messaging
#
# Address prefix used when sending to a specific server (string value)
# server_request_prefix = exclusive
# Address prefix used when broadcasting to all servers (string value)
# broadcast_prefix = broadcast
# Address prefix when sending to any server in group (string value)
# group_request_prefix = unicast
# Name for the AMQP container (string value)
# container_name =
# Timeout for inactive connections (in seconds) (integer value)
# idle_timeout = 0
# Debug: dump AMQP frames to stdout (boolean value)
# trace = false
# CA certificate PEM file for verifing server certificate (string value)
# ssl_ca_file =
# Identifying certificate PEM file to present to clients (string value)
# ssl_cert_file =
# Private key PEM file used to sign cert_file certificate (string value)
# ssl_key_file =
# Password for decrypting ssl_key_file (if encrypted) (string value)
# ssl_key_password =
# Accept clients using either SSL or plain TCP (boolean value)
# allow_insecure_clients = false
[oslo_messaging_qpid]
#
# From oslo.messaging
#
# Use durable queues in AMQP. (boolean value)
# amqp_durable_queues = false
# Auto-delete queues in AMQP. (boolean value)
# amqp_auto_delete = false
# Size of RPC connection pool. (integer value)
# rpc_conn_pool_size = 30
# Qpid broker hostname. (string value)
# qpid_hostname = localhost
# Qpid broker port. (integer value)
# qpid_port = 5672
# Qpid HA cluster host:port pairs. (list value)
# qpid_hosts = $qpid_hostname:$qpid_port
# Username for Qpid connection. (string value)
# qpid_username =
# Password for Qpid connection. (string value)
# qpid_password =
# Space separated list of SASL mechanisms to use for auth. (string value)
# qpid_sasl_mechanisms =
# Seconds between connection keepalive heartbeats. (integer value)
# qpid_heartbeat = 60
# Transport to use, either 'tcp' or 'ssl'. (string value)
# qpid_protocol = tcp
# Whether to disable the Nagle algorithm. (boolean value)
# qpid_tcp_nodelay = true
# The number of prefetched messages held by receiver. (integer value)
# qpid_receiver_capacity = 1
# The qpid topology version to use. Version 1 is what was originally used by
# impl_qpid. Version 2 includes some backwards-incompatible changes that allow
# broker federation to work. Users should update to version 2 when they are
# able to take everything down, as it requires a clean break. (integer value)
# qpid_topology_version = 1
[oslo_messaging_rabbit]
#
# From oslo.messaging
#
# Use durable queues in AMQP. (boolean value)
# amqp_durable_queues = false
# Auto-delete queues in AMQP. (boolean value)
# amqp_auto_delete = false
# Size of RPC connection pool. (integer value)
# rpc_conn_pool_size = 30
# SSL version to use (valid only if SSL enabled). Valid values are TLSv1 and
# SSLv23. SSLv2, SSLv3, TLSv1_1, and TLSv1_2 may be available on some
# distributions. (string value)
# kombu_ssl_version =
# SSL key file (valid only if SSL enabled). (string value)
# kombu_ssl_keyfile =
# SSL cert file (valid only if SSL enabled). (string value)
# kombu_ssl_certfile =
# SSL certification authority file (valid only if SSL enabled). (string value)
# kombu_ssl_ca_certs =
# How long to wait before reconnecting in response to an AMQP consumer cancel
# notification. (floating point value)
# kombu_reconnect_delay = 1.0
# The RabbitMQ broker address where a single node is used. (string value)
# rabbit_host = localhost
# The RabbitMQ broker port where a single node is used. (integer value)
# rabbit_port = 5672
# RabbitMQ HA cluster host:port pairs. (list value)
# rabbit_hosts = $rabbit_host:$rabbit_port
# Connect over SSL for RabbitMQ. (boolean value)
# rabbit_use_ssl = false
# The RabbitMQ userid. (string value)
# rabbit_userid = guest
# The RabbitMQ password. (string value)
# rabbit_password = guest
# The RabbitMQ login method. (string value)
# rabbit_login_method = AMQPLAIN
# The RabbitMQ virtual host. (string value)
# rabbit_virtual_host = /
# How frequently to retry connecting with RabbitMQ. (integer value)
# rabbit_retry_interval = 1
# How long to backoff for between retries when connecting to RabbitMQ. (integer
# value)
# rabbit_retry_backoff = 2
# Maximum number of RabbitMQ connection retries. Default is 0 (infinite retry
# count). (integer value)
# rabbit_max_retries = 0
# Use HA queues in RabbitMQ (x-ha-policy: all). If you change this option, you
# must wipe the RabbitMQ database. (boolean value)
# rabbit_ha_queues = false
# Deprecated, use rpc_backend=kombu+memory or rpc_backend=fake (boolean value)
# fake_rabbit = false

8
etc/policy.json Executable file
View File

@ -0,0 +1,8 @@
{
"context_is_admin": "role:admin",
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
"default": "rule:admin_or_owner",
"kingbird:create_quota": "rule:admin_or_owner",
"kingbird:update_quota": "rule:admin_or_owner"
}

0
kingbird/api/__init__.py Executable file
View File

95
kingbird/api/apicfg.py Executable file
View File

@ -0,0 +1,95 @@
# Copyright 2015 Huawei Technologies Co., Ltd.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Routines for configuring kingbird, largely copy from Neutron
"""
import sys
from oslo_config import cfg
from oslo_log import log as logging
from kingbird.common.i18n import _
from kingbird.common.i18n import _LI
# from kingbird import policy
# from kingbird.common import rpc
from kingbird.common import version
LOG = logging.getLogger(__name__)
common_opts = [
cfg.StrOpt('bind_host', default='0.0.0.0',
help=_("The host IP to bind to")),
cfg.IntOpt('bind_port', default=8118,
help=_("The port to bind to")),
cfg.IntOpt('api_workers', default=2,
help=_("number of api workers")),
cfg.StrOpt('api_paste_config', default="api-paste.ini",
help=_("The API paste config file to use")),
cfg.StrOpt('api_extensions_path', default="",
help=_("The path for API extensions")),
cfg.StrOpt('auth_strategy', default='keystone',
help=_("The type of authentication to use")),
cfg.BoolOpt('allow_bulk', default=True,
help=_("Allow the usage of the bulk API")),
cfg.BoolOpt('allow_pagination', default=False,
help=_("Allow the usage of the pagination")),
cfg.BoolOpt('allow_sorting', default=False,
help=_("Allow the usage of the sorting")),
cfg.StrOpt('pagination_max_limit', default="-1",
help=_("The maximum number of items returned in a single "
"response, value was 'infinite' or negative integer "
"means no limit")),
]
def init(args, **kwargs):
# Register the configuration options
cfg.CONF.register_opts(common_opts)
# ks_session.Session.register_conf_options(cfg.CONF)
# auth.register_conf_options(cfg.CONF)
logging.register_options(cfg.CONF)
cfg.CONF(args=args, project='kingbird',
version='%%(prog)s %s' % version.version_info.release_string(),
**kwargs)
# rpc.init(cfg.CONF)
def setup_logging():
"""Sets up the logging options for a log with supplied name."""
product_name = "kingbird"
logging.setup(cfg.CONF, product_name)
LOG.info(_LI("Logging enabled!"))
LOG.info(_LI("%(prog)s version %(version)s"),
{'prog': sys.argv[0],
'version': version.version_info.release_string()})
LOG.debug("command line: %s", " ".join(sys.argv))
def reset_service():
# Reset worker in case SIGHUP is called.
# Note that this is called only in case a service is running in
# daemon mode.
setup_logging()
# TODO(joehuang) enforce policy later
# policy.refresh()

66
kingbird/api/app.py Executable file
View File

@ -0,0 +1,66 @@
# Copyright (c) 2015 Huawei, Tech. Co,. Ltd.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from keystonemiddleware import auth_token
from oslo_config import cfg
from oslo_middleware import request_id
import pecan
from kingbird.common import exceptions as k_exc
def setup_app(*args, **kwargs):
config = {
'server': {
'port': cfg.CONF.bind_port,
'host': cfg.CONF.bind_host
},
'app': {
'root': 'kingbird.api.controllers.root.RootController',
'modules': ['kingbird.api'],
'errors': {
400: '/error',
'__force_dict__': True
}
}
}
pecan_config = pecan.configuration.conf_from_dict(config)
# app_hooks = [], hook collection will be put here later
app = pecan.make_app(
pecan_config.app.root,
debug=False,
wrap_app=_wrap_app,
force_canonical=False,
hooks=[],
guess_content_type_from_ext=True
)
return app
def _wrap_app(app):
app = request_id.RequestId(app)
if cfg.CONF.auth_strategy == 'noauth':
pass
elif cfg.CONF.auth_strategy == 'keystone':
app = auth_token.AuthProtocol(app, {})
else:
raise k_exc.InvalidConfigurationOption(
opt_name='auth_strategy', opt_value=cfg.CONF.auth_strategy)
return app

View File

View File

@ -0,0 +1,63 @@
# Copyright (c) 2015 Huawei Tech. Co., Ltd.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# from kingbird.jobdaemon import jdrpcapi
import pecan
from pecan import expose
from pecan import rest
import restcomm
class HelloWorldController(rest.RestController):
def __init__(self, *args, **kwargs):
super(HelloWorldController, self).__init__(*args, **kwargs)
# self.jd_api = jdrpcapi.JobDaemonAPI()
@expose(generic=True, template='json')
def index(self):
if pecan.request.method != 'GET':
pecan.abort(405)
context = restcomm.extract_context_from_environ()
if context.is_admin:
return {'hello world message for admin': 'GET'}
else:
return {'hello world message for non-admin': 'GET'}
@index.when(method='PUT', template='json')
def put(self, **kw):
context = restcomm.extract_context_from_environ()
if context.is_admin:
return {'hello world message for admin': 'PUT'}
else:
return {'hello world message for non-admin': 'PUT'}
@index.when(method='POST', template='json')
def post(self, **kw):
context = restcomm.extract_context_from_environ()
if context.is_admin:
return {'hello world message for admin': 'POST'}
else:
return {'hello world message for non-admin': 'POST'}
@index.when(method='delete', template='json')
def delete(self):
context = restcomm.extract_context_from_environ()
if context.is_admin:
return {'hello world message for admin': 'delete'}
else:
return {'hello world message for non-admin': 'delete'}

View File

@ -0,0 +1,40 @@
# Copyright (c) 2015 Huawei Tech. Co., Ltd.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from pecan import request
import kingbird.common.context as k_context
def extract_context_from_environ():
context_paras = {'auth_token': 'HTTP_X_AUTH_TOKEN',
'user': 'HTTP_X_USER_ID',
'tenant': 'HTTP_X_TENANT_ID',
'user_name': 'HTTP_X_USER_NAME',
'tenant_name': 'HTTP_X_PROJECT_NAME',
'domain': 'HTTP_X_DOMAIN_ID',
'user_domain': 'HTTP_X_USER_DOMAIN_ID',
'project_domain': 'HTTP_X_PROJECT_DOMAIN_ID',
'request_id': 'openstack.request_id'}
environ = request.environ
for key in context_paras:
context_paras[key] = environ.get(context_paras[key])
role = environ.get('HTTP_X_ROLE')
context_paras['is_admin'] = role == 'admin'
return k_context.Context(**context_paras)

View File

@ -0,0 +1,69 @@
# Copyright (c) 2015 Huawei Tech. Co., Ltd.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import helloworld
import pecan
class RootController(object):
@pecan.expose('json')
def _lookup(self, version, *remainder):
if version == 'v1.0':
return V1Controller(), remainder
@pecan.expose('json')
def index(self):
return {
"versions": [
{
"status": "CURRENT",
"links": [
{
"rel": "self",
"href": pecan.request.application_url + "/v1.0/"
}
],
"id": "v1.0",
"updated": "2015-09-09"
}
]
}
class V1Controller(object):
def __init__(self):
self.sub_controllers = {
"helloworld": helloworld.HelloWorldController()
}
for name, ctrl in self.sub_controllers.items():
setattr(self, name, ctrl)
@pecan.expose('json')
def index(self):
return {
"version": "1.0",
"links": [
{"rel": "self",
"href": pecan.request.application_url + "/v1.0"}
] + [
{"rel": name,
"href": pecan.request.application_url + "/v1.0/" + name}
for name in sorted(self.sub_controllers)
]
}

0
kingbird/common/__init__.py Executable file
View File

70
kingbird/common/context.py Executable file
View File

@ -0,0 +1,70 @@
# Copyright 2015 Huawei Technologies Co., Ltd.
# All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_context import context as oslo_ctx
class ContextBase(oslo_ctx.RequestContext):
def __init__(self, auth_token=None, user_id=None, tenant_id=None,
is_admin=False, request_id=None, overwrite=True,
user_name=None, tenant_name=None, **kwargs):
super(ContextBase, self).__init__(
auth_token=auth_token,
user=user_id or kwargs.get('user', None),
tenant=tenant_id or kwargs.get('tenant', None),
domain=kwargs.get('domain', None),
user_domain=kwargs.get('user_domain', None),
project_domain=kwargs.get('project_domain', None),
is_admin=is_admin,
read_only=kwargs.get('read_only', False),
show_deleted=kwargs.get('show_deleted', False),
request_id=request_id,
resource_uuid=kwargs.get('resource_uuid', None),
overwrite=overwrite)
self.user_name = user_name
self.tenant_name = tenant_name
def to_dict(self):
ctx_dict = super(ContextBase, self).to_dict()
ctx_dict.update({
'user_name': self.user_name,
'tenant_name': self.tenant_name
})
return ctx_dict
@classmethod
def from_dict(cls, ctx):
return cls(**ctx)
class Context(ContextBase):
def __init__(self, **kwargs):
super(Context, self).__init__(**kwargs)
self._session = None
@property
def session(self):
# todo get db session in the context
# if not self._session:
# self._session = dal.get_session()
return self._session
def get_admin_context(read_only=True):
return ContextBase(user_id=None,
project_id=None,
is_admin=True,
overwrite=False,
read_only=read_only)

84
kingbird/common/exceptions.py Executable file
View File

@ -0,0 +1,84 @@
# Copyright 2015 Huawei Technologies Co., Ltd.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Kingbird base exception handling.
"""
from oslo_utils import excutils
import six
from kingbird.common.i18n import _
class KingbirdException(Exception):
"""Base Kingbird Exception.
To correctly use this class, inherit from it and define
a 'message' property. That message will get printf'd
with the keyword arguments provided to the constructor.
"""
message = _("An unknown exception occurred.")
def __init__(self, **kwargs):
try:
super(KingbirdException, self).__init__(self.message % kwargs)
self.msg = self.message % kwargs
except Exception:
with excutils.save_and_reraise_exception() as ctxt:
if not self.use_fatal_exceptions():
ctxt.reraise = False
# at least get the core message out if something happened
super(KingbirdException, self).__init__(self.message)
if six.PY2:
def __unicode__(self):
return unicode(self.msg)
def use_fatal_exceptions(self):
return False
class BadRequest(KingbirdException):
message = _('Bad %(resource)s request: %(msg)s')
class NotFound(KingbirdException):
pass
class Conflict(KingbirdException):
pass
class NotAuthorized(KingbirdException):
message = _("Not authorized.")
class ServiceUnavailable(KingbirdException):
message = _("The service is unavailable")
class AdminRequired(NotAuthorized):
message = _("User does not have admin privileges: %(reason)s")
class InUse(KingbirdException):
message = _("The resource is inuse")
class InvalidConfigurationOption(KingbirdException):
message = _("An invalid value was provided for %(opt_name)s: "
"%(opt_value)s")

30
kingbird/common/i18n.py Executable file
View File

@ -0,0 +1,30 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import oslo_i18n
_translators = oslo_i18n.TranslatorFactory(domain='kingbird')
# The primary translation function using the well-known name "_"
_ = _translators.primary
# Translators for log levels.
#
# The abbreviated names are meant to reflect the usual use of a short
# name like '_'. The "L" is for "log" and the other letter comes from
# the level.
_LI = _translators.log_info
_LW = _translators.log_warning
_LE = _translators.log_error
_LC = _translators.log_critical

18
kingbird/common/utils.py Executable file
View File

@ -0,0 +1,18 @@
# Copyright 2015 Huawei Technologies Co., Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
def get_import_path(cls):
return cls.__module__ + "." + cls.__name__

41
kingbird/common/version.py Executable file
View File

@ -0,0 +1,41 @@
# Copyright 2011 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import pbr.version
KINGBIRD_VENDOR = "OpenStack Foundation"
KINGBIRD_PRODUCT = "OpenStack Kingbird"
KINGBIRD_PACKAGE = None # OS distro package version suffix
version_info = pbr.version.VersionInfo('kingbird')
version_string = version_info.version_string
def vendor_string():
return KINGBIRD_VENDOR
def product_string():
return KINGBIRD_PRODUCT
def package_string():
return KINGBIRD_PACKAGE
def version_string_with_package():
if package_string() is None:
return version_info.version_string()
else:
return "%s-%s" % (version_info.version_string(), package_string())

View File

@ -1,6 +1,41 @@
# The order of packages is significant, because pip processes them in the order # The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration # of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
pbr>=1.6 pbr>=1.6
Babel>=1.3 Babel>=1.3
Paste
PasteDeploy>=1.5.0
Routes!=2.0,!=2.1,>=1.12.3;python_version=='2.7'
Routes!=2.0,>=1.12.3;python_version!='2.7'
debtcollector>=0.3.0 # Apache-2.0
eventlet>=0.17.4
pecan>=1.0.0
greenlet>=0.3.2
httplib2>=0.7.5
requests!=2.8.0,>=2.5.2
Werkzeug>=0.7 # BSD License
Jinja2>=2.8 # BSD License (3 clause)
keystonemiddleware!=2.4.0,>=2.0.0
netaddr!=0.7.16,>=0.7.12
retrying!=1.3.0,>=1.2.3 # Apache-2.0
SQLAlchemy<1.1.0,>=0.9.9
WebOb>=1.2.3
python-keystoneclient!=1.8.0,>=1.6.0
alembic>=0.8.0
six>=1.9.0
stevedore>=1.5.0 # Apache-2.0
oslo.concurrency>=2.3.0 # Apache-2.0
oslo.config>=2.6.0 # Apache-2.0
oslo.context>=0.2.0 # Apache-2.0
oslo.db>=3.0.0 # Apache-2.0
oslo.i18n>=1.5.0 # Apache-2.0
oslo.log>=1.12.0 # Apache-2.0
oslo.messaging!=2.8.0,>2.6.1 # Apache-2.0
oslo.middleware>=2.9.0 # Apache-2.0
oslo.policy>=0.5.0 # Apache-2.0
oslo.rootwrap>=2.0.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
oslo.service>=0.12.0 # Apache-2.0
oslo.utils!=2.6.0,>=2.4.0 # Apache-2.0
oslo.versionedobjects>=0.9.0

View File

@ -1,15 +1,23 @@
# The order of packages is significant, because pip processes them in the order # The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration # of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
hacking<0.11,>=0.10.2 hacking<0.11,>=0.10.2
cliff>=1.14.0 # Apache-2.0
coverage>=3.6 coverage>=3.6
discover fixtures>=1.3.1
mock>=1.2
python-subunit>=0.0.18 python-subunit>=0.0.18
requests-mock>=0.6.0 # Apache-2.0
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
oslosphinx>=2.5.0 # Apache-2.0 oslosphinx>=2.5.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
testrepository>=0.0.18 testrepository>=0.0.18
testscenarios>=0.4
testtools>=1.4.0 testtools>=1.4.0
testresources>=0.2.4
testscenarios>=0.4
WebTest>=2.0
oslotest>=1.10.0 # Apache-2.0
os-testr>=0.4.1
tempest-lib>=0.10.0
ddt>=0.7.0
pylint==1.4.4 # GNU GPL v2