Add test data generator via oslo messaging

This script is helpful for emulate real workflow.
Generate and send sample batches with different resources and
configurable counter_name.

Change-Id: I3ab6472c99abfe28e8c200ada2da91e97abed1d2
This commit is contained in:
Ilya Tyaptin 2014-12-03 20:54:37 +04:00
parent 86d84a6dbd
commit 2ea548f10f
2 changed files with 169 additions and 31 deletions

View File

@ -23,7 +23,8 @@ Usage:
Generate testing data for e.g. for default time span Generate testing data for e.g. for default time span
source .tox/py27/bin/activate source .tox/py27/bin/activate
./tools/make_test_data.py --user 1 --project 1 1 cpu_util 20 ./tools/make_test_data.py --user 1 --project 1 --resource 1 --counter cpu_util
--volume 20
""" """
from __future__ import print_function from __future__ import print_function
@ -32,6 +33,7 @@ import datetime
import logging import logging
import random import random
import sys import sys
import uuid
from oslo.config import cfg from oslo.config import cfg
from oslo.utils import timeutils from oslo.utils import timeutils
@ -41,10 +43,10 @@ from ceilometer import sample
from ceilometer import storage from ceilometer import storage
def make_test_data(conn, name, meter_type, unit, volume, random_min, def make_test_data(name, meter_type, unit, volume, random_min,
random_max, user_id, project_id, resource_id, start, random_max, user_id, project_id, resource_id, start,
end, interval, resource_metadata={}, source='artificial',): end, interval, resource_metadata=None, source='artificial'):
resource_metadata = resource_metadata or {}
# Compute start and end timestamps for the new data. # Compute start and end timestamps for the new data.
if isinstance(start, datetime.datetime): if isinstance(start, datetime.datetime):
timestamp = start timestamp = start
@ -83,7 +85,8 @@ def make_test_data(conn, name, meter_type, unit, volume, random_min,
data = utils.meter_message_from_counter( data = utils.meter_message_from_counter(
c, c,
cfg.CONF.publisher.metering_secret) cfg.CONF.publisher.metering_secret)
conn.record_metering_data(data)
yield data
n += 1 n += 1
timestamp = timestamp + increment timestamp = timestamp + increment
@ -96,9 +99,12 @@ def make_test_data(conn, name, meter_type, unit, volume, random_min,
print('Added %d new events for meter %s.' % (n, name)) print('Added %d new events for meter %s.' % (n, name))
def main(): def record_test_data(conn, *args, **kwargs):
cfg.CONF([], project='ceilometer') for data in make_test_data(*args, **kwargs):
conn.record_metering_data(data)
def get_parser():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='generate metering data', description='generate metering data',
) )
@ -116,6 +122,7 @@ def main():
) )
parser.add_argument( parser.add_argument(
'--end', '--end',
type=int,
default=2, default=2,
help='Number of days to be stepped forward from now or date in the ' help='Number of days to be stepped forward from now or date in the '
'future ("YYYY-MM-DDTHH:MM:SS" format) to define timestamps end ' 'future ("YYYY-MM-DDTHH:MM:SS" format) to define timestamps end '
@ -125,6 +132,7 @@ def main():
'--type', '--type',
choices=('gauge', 'cumulative'), choices=('gauge', 'cumulative'),
default='gauge', default='gauge',
dest='meter_type',
help='Counter type.', help='Counter type.',
) )
parser.add_argument( parser.add_argument(
@ -134,10 +142,12 @@ def main():
) )
parser.add_argument( parser.add_argument(
'--project', '--project',
dest='project_id',
help='Project id of owner.', help='Project id of owner.',
) )
parser.add_argument( parser.add_argument(
'--user', '--user',
dest='user_id',
help='User id of owner.', help='User id of owner.',
) )
parser.add_argument( parser.add_argument(
@ -153,20 +163,30 @@ def main():
default=0, default=0,
) )
parser.add_argument( parser.add_argument(
'resource', '--resource',
dest='resource_id',
default=str(uuid.uuid4()),
help='The resource id for the meter data.', help='The resource id for the meter data.',
) )
parser.add_argument( parser.add_argument(
'counter', '--counter',
default='instance',
dest='name',
help='The counter name for the meter data.', help='The counter name for the meter data.',
) )
parser.add_argument( parser.add_argument(
'volume', '--volume',
help='The amount to attach to the meter.', help='The amount to attach to the meter.',
type=int, type=int,
default=1, default=1,
) )
args = parser.parse_args() return parser
def main():
cfg.CONF([], project='ceilometer')
args = get_parser().parse_args()
# Set up logging to use the console # Set up logging to use the console
console = logging.StreamHandler(sys.stderr) console = logging.StreamHandler(sys.stderr)
@ -181,11 +201,11 @@ def main():
conn = storage.get_connection_from_config(cfg.CONF) conn = storage.get_connection_from_config(cfg.CONF)
# Find the user and/or project for a real resource # Find the user and/or project for a real resource
if not (args.user or args.project): if not (args.user_id or args.project_id):
for r in conn.get_resources(): for r in conn.get_resources():
if r.resource_id == args.resource: if r.resource_id == args.resource_id:
args.user = r.user_id args.user_id = r.user_id
args.project = r.project_id args.project_id = r.project_id
break break
# Compute the correct time span # Compute the correct time span
@ -208,24 +228,12 @@ def main():
end = datetime.datetime.strptime(args.end, format) end = datetime.datetime.strptime(args.end, format)
except ValueError: except ValueError:
raise raise
args.start = start
make_test_data(conn=conn, args.end = end
name=args.counter, record_test_data(conn=conn, **args.__dict__)
meter_type=args.type,
unit=args.unit,
volume=args.volume,
random_min=args.random_min,
random_max=args.random_max,
user_id=args.user,
project_id=args.project,
resource_id=args.resource,
start=start,
end=end,
interval=args.interval,
resource_metadata={},
source='artificial',)
return 0 return 0
if __name__ == '__main__': if __name__ == '__main__':
main() main()

130
tools/send_test_data.py Normal file
View File

@ -0,0 +1,130 @@
# 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.
"""Command line tool for sending test data for Ceilometer via oslo.messaging.
Usage:
Send messages with samples generated by make_test_data
source .tox/py27/bin/activate
./tools/send_test_data.py --count 1000 --resources_count 10 --topic metering
"""
import argparse
import datetime
import json
import random
import uuid
import make_test_data
from oslo_context import context
from ceilometer import messaging
from ceilometer import service
def send_batch(rpc_client, topic, batch):
rpc_client.prepare(topic=topic).cast(context.RequestContext(),
'record_metering_data', data=batch)
def get_rpc_client(config_file):
service.prepare_service(argv=['/', '--config-file', config_file])
transport = messaging.get_transport()
rpc_client = messaging.get_rpc_client(transport, version='1.0')
return rpc_client
def generate_data(rpc_client, make_data_args, samples_count,
batch_size, resources_count, topic):
make_data_args.interval = 1
make_data_args.start = (datetime.datetime.utcnow() -
datetime.timedelta(minutes=samples_count))
make_data_args.end = datetime.datetime.utcnow()
make_data_args.resource_id = None
resources_list = [str(uuid.uuid4())
for _ in xrange(resources_count)]
resource_samples = {resource: 0 for resource in resources_list}
batch = []
count = 0
for sample in make_test_data.make_test_data(**make_data_args.__dict__):
count += 1
resource = resources_list[random.randint(0, len(resources_list) - 1)]
resource_samples[resource] += 1
sample['resource_id'] = resource
batch.append(sample)
if len(batch) == batch_size:
send_batch(rpc_client, topic, batch)
batch = []
if count == samples_count:
send_batch(rpc_client, topic, batch)
return resource_samples
send_batch(rpc_client, topic, batch)
return resource_samples
def get_parser():
parser = argparse.ArgumentParser()
parser.add_argument(
'--batch-size',
dest='batch_size',
type=int,
default=100
)
parser.add_argument(
'--config-file',
default='/etc/ceilometer/ceilometer.conf'
)
parser.add_argument(
'--topic',
default='perfmetering'
)
parser.add_argument(
'--samples-count',
dest='samples_count',
type=int,
default=1000
)
parser.add_argument(
'--resources-count',
dest='resources_count',
type=int,
default=100
)
parser.add_argument(
'--result-directory',
dest='result_dir',
default='/tmp'
)
return parser
def main():
args = get_parser().parse_known_args()[0]
make_data_args = make_test_data.get_parser().parse_known_args()[0]
rpc_client = get_rpc_client(args.config_file)
result_dir = args.result_dir
del args.config_file
del args.result_dir
resource_writes = generate_data(rpc_client, make_data_args,
**args.__dict__)
result_file = "%s/sample-by-resource-%s" % (result_dir,
random.getrandbits(32))
with open(result_file, 'w') as f:
f.write(json.dumps(resource_writes))
return result_file
if __name__ == '__main__':
main()