Change-Id: I4de4d2c2e8f9fe4462d3dc68e209c168fff2ce48
This commit is contained in:
Kanagaraj Manickam 2016-03-20 12:57:49 +05:30
parent b5f33280a1
commit 4e04023955
8 changed files with 411 additions and 4 deletions

View File

@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import pbr.version
from os_namos import sync
__version__ = pbr.version.VersionInfo(
'os-namos').version_string()
RegistrationInfo = sync.RegistrationInfo
Config = sync.Config
register_myself = sync.register_myself
collect_registration_info = sync.collect_registration_info

View File

36
os_namos/common/config.py Normal file
View File

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# 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_config import cfg
from oslo_log import log as logging
import os_namos # noqa
PROJECT_NAME = 'namos'
VERSION = '0.0.1'
MESSAGE_QUEUE_CONDUCTOR_TOPIC = '%s.conductor' % PROJECT_NAME
CONF = cfg.CONF
def init_conf(prog):
CONF(project=PROJECT_NAME,
version=VERSION,
prog=prog)
def init_log(project=PROJECT_NAME):
logging.register_options(cfg.CONF)
logging.setup(cfg.CONF,
project,
version=VERSION)

View File

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# 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.
class NamosException(Exception):
def __init__(self, **kwargs):
self.message = kwargs.get('message') or "UNKNOWN"
self.data = kwargs.get('data') or {}
self.error_code = kwargs.get('error_code') or -1
self.http_status_code = kwargs.get('http_status_code') or 500
def __str__(self):
return unicode(self.message).encode('UTF-8')
def __unicode__(self):
return unicode(self.message)
def __deepcopy__(self, memo):
return self.__class__(**self.kwargs)

View File

@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
# 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_config import cfg
import oslo_messaging
from oslo_serialization import jsonutils
from oslo_context import context
DEFAULT_URL = "__default__"
TRANSPORTS = {}
_ALIASES = {
'namos.openstack.common.rpc.impl_kombu': 'rabbit',
'namos.openstack.common.rpc.impl_qpid': 'qpid',
'namos.openstack.common.rpc.impl_zmq': 'zmq',
}
class RequestContextSerializer(oslo_messaging.Serializer):
def __init__(self, base):
self._base = base
def serialize_entity(self, ctxt, entity):
if not self._base:
return entity
return self._base.serialize_entity(ctxt, entity)
def deserialize_entity(self, ctxt, entity):
if not self._base:
return entity
return self._base.deserialize_entity(ctxt, entity)
@staticmethod
def serialize_context(ctxt):
return ctxt.to_dict()
@staticmethod
def deserialize_context(ctxt):
return context.RequestContext(ctxt)
class JsonPayloadSerializer(oslo_messaging.NoOpSerializer):
@classmethod
def serialize_entity(cls, context, entity):
return jsonutils.to_primitive(entity, convert_instances=True)
def get_transport(url=None, optional=False, cache=True):
"""Initialise the olso.messaging layer."""
global TRANSPORTS, DEFAULT_URL
cache_key = url or DEFAULT_URL
transport = TRANSPORTS.get(cache_key)
if not transport or not cache:
try:
transport = oslo_messaging.get_transport(cfg.CONF, url,
aliases=_ALIASES)
except oslo_messaging.InvalidTransportURL as e:
if not optional or e.url:
# NOTE(sileht): olso.messaging is configured but unloadable
# so reraise the exception
raise
return None
else:
if cache:
TRANSPORTS[cache_key] = transport
return transport
def get_rpc_server(host, topic, version, endpoint):
"""Return a configured olso.messaging rpc server."""
target = oslo_messaging.Target(server=host, topic=topic, version=version)
serializer = RequestContextSerializer(JsonPayloadSerializer())
transport = get_transport(optional=True)
return oslo_messaging.get_rpc_server(transport, target,
[endpoint], executor='eventlet',
serializer=serializer)
def get_rpc_client(topic, version, retry=None, **kwargs):
"""Return a configured olso.messaging RPCClient."""
target = oslo_messaging.Target(version=version,
topic=topic, **kwargs)
serializer = RequestContextSerializer(JsonPayloadSerializer())
transport = get_transport(optional=True)
return oslo_messaging.RPCClient(transport, target,
serializer=serializer,
retry=retry,
version_cap=version)
def cleanup():
"""Cleanup the olso.messaging layer."""
global TRANSPORTS
for url in TRANSPORTS:
TRANSPORTS[url].cleanup()
del TRANSPORTS[url]

67
os_namos/common/rpcapi.py Normal file
View File

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
# 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.
"""
Client side of the OSLO CONFIG NAMOS
"""
import functools
import json
import oslo_messaging
from oslo_messaging import RemoteError
from os_namos.common import config # noqa
from os_namos.common import exception as namos_exception
from os_namos.common import messaging as rpc
def wrapper_function(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
try:
return func(*args, **kwargs)
except RemoteError as e:
kwargs = json.loads(e.value)
raise namos_exception.NamosException(**kwargs)
return wrapped
class ConductorAPI(object):
RPC_API_VERSION = '1.0'
def __init__(self, project):
super(ConductorAPI, self).__init__()
self.topic = 'namos.conductor'
# Setup the messaging tweaks ! here
rpc._ALIASES.update(
{
'%s.openstack.common.rpc.impl_kombu' % project: 'rabbit',
'%s.openstack.common.rpc.impl_qpid' % project: 'qpid',
'%s.openstack.common.rpc.impl_zmq' % project: 'zmq',
}
)
oslo_messaging.set_transport_defaults(project)
self.client = rpc.get_rpc_client(version=self.RPC_API_VERSION,
topic=self.topic)
@wrapper_function
def register_myself(self, context, registration_info):
# TODO(mrkanag): is to be call instead of cast
return self.client.cast(context,
'register_myself',
registration_info=registration_info)

158
os_namos/sync.py Normal file
View File

@ -0,0 +1,158 @@
# -*- coding: utf-8 -*-
# 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 os
import socket
from oslo_context import context
from os_namos.common import rpcapi
NAMOS_RPCAPI = None
class RegistrationInfo(object):
def __init__(self,
host,
project_name,
prog_name,
fqdn=socket.gethostname(),
pid=os.getpid(),
config_file_list=None,
config_dict=None):
self.host = host
self.project_name = project_name
self.fqdn = fqdn
self.prog_name = prog_name
self.pid = pid
self.config_file_list = config_file_list or list()
# List of configuration which CONF is already updated with
self.config_dict = config_dict or dict()
class Config(object):
def __init__(self,
name,
type,
value,
help=None,
default_value=None,
required=False,
secret=False,
file=None):
self.name = name
self.default_value = default_value
self.help = help
self.type = type
self.value = value
self.required = required
self.secret = secret
self.file = file
def collect_registration_info():
from oslo_config import cfg
self = cfg.CONF
def normalize_type(type):
if str(type).find('function'):
return 'String'
return type
def get_host():
try:
return getattr(self, 'host')
except: # noqa
import socket
return socket.gethostname()
reg_info = RegistrationInfo(host=get_host(),
project_name=self.project,
prog_name=self.prog,
config_file_list=self.default_config_files)
config_dict = dict()
for opt_name in sorted(self._opts):
opt = self._get_opt_info(opt_name)['opt']
cfg = Config(name='%s' % opt_name,
type='%s' % normalize_type(opt.type),
value='%s' % getattr(self, opt_name),
help='%s' % opt.help,
required=opt.required,
secret=opt.secret,
default_value='%s' % opt.default)
config_dict[cfg.name] = cfg
for group_name in self._groups:
group_attr = self.GroupAttr(self, self._get_group(group_name))
for opt_name in sorted(self._groups[group_name]._opts):
opt = self._get_opt_info(opt_name, group_name)['opt']
cfg = Config(name="%s.%s" % (group_name, opt_name),
type='%s' % normalize_type(opt.type),
value='%s' % getattr(group_attr, opt_name),
help='%s' % opt.help,
required=opt.required,
secret=opt.secret,
default_value='%s' % opt.default)
config_dict[cfg.name] = cfg
reg_info.config_dict = config_dict
return reg_info
def register_myself(registration_info=None):
global NAMOS_RPCAPI
if registration_info is None:
registration_info = collect_registration_info()
if NAMOS_RPCAPI is None:
NAMOS_RPCAPI = rpcapi.ConductorAPI(
project=registration_info.project_name)
ctx = context.RequestContext()
return NAMOS_RPCAPI.register_myself(ctx, registration_info)
def add_config(config):
pass
def remove_config(config):
pass
def update_config(config):
pass
if __name__ == '__main__':
# TODO(mrkanag) Remove this before production !
from os_namos.common import config
config.init_log()
config.init_conf('test-run')
reg_info = RegistrationInfo(
host='namos_development',
project_name=config.PROJECT_NAME,
prog_name='sync',
config_file_list=['/etc/namos/namos.conf'],
config_dict={})
print (reg_info.__dict__)
print (register_myself(reg_info))

View File

@ -3,3 +3,7 @@
# process, which may cause wedges in the gate later.
pbr>=1.6
oslo.context>=0.2.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
oslo.messaging>=4.0.0 # Apache-2.0
oslo.utils>=3.5.0 # Apache-2.0