调试CloudKitty

本地PyCharm调试

1.配置文件

主要包含三个配置 api_paste.ini policy.json cloudkitty.conf,复制到/etc/cloudkitty目录下

  • api_paste.ini
#可在源码etc/cloudkitty目录中找到

[pipeline:main]
pipeline = cors http_proxy_to_wsgi request_id authtoken ck_api_v1

[app:ck_api_v1]
paste.app_factory = cloudkitty.api.app:app_factory

[filter:authtoken]
acl_public_routes = /, /v1
paste.filter_factory = cloudkitty.api.middleware:AuthTokenMiddleware.factory

[filter:request_id]
paste.filter_factory = oslo_middleware:RequestId.factory

[filter:cors]
paste.filter_factory =  oslo_middleware.cors:filter_factory
oslo_config_project = cloudkitty

[filter:http_proxy_to_wsgi]
paste.filter_factory = oslo_middleware.http_proxy_to_wsgi:HTTPProxyToWSGI.factory
oslo_config_project = cloudkitty
  • policy.json
#可在源码etc/cloudkitty目录中找到

{
    "context_is_admin":  "role:admin",
    "default": "",

    "rating:list_modules": "role:admin",
    "rating:get_module": "role:admin",
    "rating:update_module": "role:admin",
    "rating:quote": "",

    "report:list_tenants": "role:admin",
    "report:get_total": "",

    "collector:list_mappings": "role:admin",
    "collector:get_mapping": "role:admin",
    "collector:manage_mappings": "role:admin",
    "collector:get_state": "role:admin",
    "collector:update_state": "role:admin",

    "storage:list_data_frames": "",

    "rating:module_config": "role:admin"
}
  • cloudkitty.conf
[authinfos]
#权限认证配置,可以使用服务器的keystone进行验证
username = cloudkitty
password = t2cloud123
project_name = service
region_name = large
auth_uri = http://192.168.103.157:5000/v2.0
auth_url = http://192.168.103.157:35357
auth_type = password


[DEFAULT]
verbose = True
log_dir = .
rpc_backend = rabbit
debug = True
[api]
host_ip = 0.0.0.0

[oslo_messaging_rabbit]
#消息队列地址
rabbit_hosts = 127.0.0.1:5672
rabbit_userid = test
rabbit_password = test

kombu_reconnect_delay = 5
rabbit_ha_queues = True
heartbeat_timeout_threshold = 0
heartbeat_rate = 2

[keystone_authtoken]
auth_section = authinfos

[database]
#数据库地址
connection = mysql+pymysql://cloudkitty:password@127.0.0.1:3306/cloudkitty

[keystone_fetcher]
auth_section = authinfos

[ceilometer_collector]
auth_section = authinfos
region_name = large
use_session = False

[orchestrator]
coordination_url='file:///tmp/cloudkitty/locks'

[collect]
#计费周期
period = 3600
#需要计费的服务
services = compute,image,volume,network.bw.in,network.bw.out,network.floating

2.准备cloudkitty运行所依赖的环境

  • 数据库

创建数据库

MariaDB [(none)]> CREATE DATABASE cloudkitty;
MariaDB [(none)]> GRANT ALL PRIVILEGES ON cloudkitty.* TO 'cloudkitty'@'localhost' IDENTIFIED BY 'password';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON cloudkitty.* TO 'cloudkitty'@'%' IDENTIFIED BY 'password';

初始化数据库

进入虚拟环境,安装好cloudkitty后,执行如下命令

(cloudkitty) [root@controller52 cloudkitty]# pip install pymysql
(cloudkitty) [root@controller52 cloudkitty]# cloudkitty-dbsync upgrade
(cloudkitty) [root@controller52 cloudkitty]# cloudkitty-storage-init
  • 在keystone中创建相应的用户和endpoint
[root@dev ~(keystone_admin)]# keystone user-create --name cloudkitty --pass password  --email cloudkitty@localhost
[root@dev ~(keystone_admin)]# keystone user-role-add --user cloudkitty --role admin --tenant services
[root@dev ~(keystone_admin)]# keystone service-create --name cloudKitty --type rating --description "OpenStack Rating Service"
[root@dev ~(keystone_admin)]# keystone endpoint-create --service-id %CLOUDKITTY_SERVICE_ID%  \
    --publicurl http://172.16.40.152:8889 \
    --adminurl http://172.16.40.152:8889 \
    --internalurl http://172.16.40.152:8889 \
    --region RegionOne
  • 新建rating角色,并对demo租户进行计费

cloudkitty只会查询包含rating角色的tenant进行计费处理

[root@dev ~(keystone_admin)]# keystone role-create --name rating
[root@dev ~(keystone_admin)]# keystone user-role-add --user cloudkitty --role rating --tenant demo

2.设置启动文件

  • processor

启动脚本: cloudkitty/cli/processor.py

启动参数: --config-file=/etc/cloudkitty/cloudkitty.conf

  • api

启动脚本: cloudkitty/cli/api.py

启动参数: --config-file=/etc/cloudkitty/cloudkitty.conf

3.命令行使用

#admin-openrc.sh
#配置环境变量

export OS_SERVICE_TOKEN=t2cloud123
export OS_SERVICE_ENDPOINT=http://127.0.0.1:35357/v2.0
export OS_USERNAME=admin
export OS_PASSWORD=t2cloud123
export OS_TENANT_NAME=admin
export OS_AUTH_URL=http://192.168.103.157:35357/v2.0
export OS_REGION_NAME=large

#配置api服务所在地址(如果不配置则会使用keystone中注册的地址),这里是本机
export CLOUDKITTY_URL=http://127.0.0.1:8889

远程ipdb

1.调整下eventlet的monkey patch

编辑 orchestrator.py

eventlet.monkey_patch(all=False, socket=True, time=True, thread=False)

2.设置断点

import ipdb ; ipdb.set_trace()

3.常用命令


ENTER(重复上次命令)
c(继续)
l(查找当前位于哪里)
s(进入子程序)
r(运行直到子程序结束)
!<python 命令>
h(帮助)
a(rgs) 打印当前函数的参数
j(ump) 让程序跳转到指定的行数
l(ist) 可以列出当前将要运行的代码块
n(ext) 让程序运行下一行,如果当前语句有一个函数调用,用 n 是不会进入被调用的函数体中的
p(rint) 最有用的命令之一,打印某个变量
q(uit) 退出调试
r(eturn) 继续执行,直到函数体返回
s(tep) 跟 n 相似,但是如果当前有一个函数调用,那么 s 会进入被调用的函数体中

简单调试脚本

# -*- coding: utf-8 -*-
import logging

from cloudkittyclient import client as ck_client
from keystoneclient.v2_0 import client as client_v2
from keystoneclient.v3 import client as client_v3

logging_config = dict(
    version=1,
    formatters={
        'f': {'format':
              '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'}
    },
    handlers={
        'h': {'class': 'logging.StreamHandler',
              'formatter': 'f',
              'level': logging.DEBUG}
    },
    loggers={
        '': {'handlers': ['h'],
             'level': logging.DEBUG}
    }
)
logging.basicConfig(**logging_config)

# keystone的配置
openstack_api_info = {
    'identity': 2.0,
    'admin_username': 'admin',
    'admin_password': 'aaaaaaaa',
    'auth_url': 'http://192.168.107.50:5000/v2.0',
    # api服务地址,如果不配置则使用keystone中注册的地址
    'endpoint': 'http://127.0.0.1:8889',
    # 'endpoint' : 'http://192.168.107.52:8889',
}


def get_keystone_version():
    return openstack_api_info.get('identity', 2.0)


def available_services_regions(service_type, keystone=None):
    """Returns list of unique region name values in service catalog."""

    if not keystone:
        keystone = keystone_admin_client()

    regions = []
    endpoints = keystone.service_catalog.get_endpoints()

    for endpoint in endpoints.get(service_type, []):
        region = endpoint.get('region_id') or endpoint.get('region')
        if region not in regions:
            regions.append(region)
    return regions


def get_keystone_client():
    if get_keystone_version() < 3:
        return client_v2
    else:
        return client_v3


def keystone_admin_client():
    # 获取admin权限的keystone
    keystone = get_keystone_client().Client(
        username=openstack_api_info['admin_username'],
        password=openstack_api_info['admin_password'],
        tenant_name=openstack_api_info.get('project', 'admin'),
        auth_url=openstack_api_info['auth_url']
    )
    return keystone


def cloudkitty_client(keystone=None, region_name=None):
    """Initialization of Cloudkitty client."""
    if not keystone:
        keystone = keystone_admin_client()
    token = keystone.auth_token

    endpoint = openstack_api_info.get('endpoint', None)
    insecure = openstack_api_info.get('openstack_ssl_no_verify', False)
    cacert = openstack_api_info.get('openstack_ssl_cacert', None)
    return ck_client.Client('1', endpoint, token=token, insecure=insecure, cacert=cacert)

if __name__ == '__main__':

    def query_quote():
        cloudkitty = cloudkitty_client()

        tenant_id = 'ce54dd999ef94bffa5d67b77f98cf117'
        resources = [{'volume': 50, 'service': 'volume', 'desc': {'size': 50}}]

        price_data = cloudkitty.quotations.quote(resources, tenant_id)
        return price_data

    print query_quote()