vitrage/tools/load_generator/load_generator.py

155 lines
5.0 KiB
Python

# Copyright 2017 - Nokia
#
# 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 copy
import sys
import cotyledon
from futurist import periodics
from futurist import ThreadPoolExecutor
from oslo_config import cfg
from oslo_log import log
import oslo_messaging
from tools.load_generator.notification_info import * # noqa
from vitrage.common import config
from vitrage.messaging import get_transport
CONF = cfg.CONF
LOG = log.getLogger(__name__)
EXISTING_COMPUTES_NUM = 64
VMS_PER_COMPUTE = 2
NET_ID = '59fec1a4-7ab2-4bc6-8792-0ddf54b15dfe'
RUN_EVERY_X_SECONDS = 600
"""
Stress Notifications Tool:
Following service runs a timed action every X seconds.
Action will send mock bus notifications, as configured in the constants above.
Sends mock notifications for:
VM create
Port create
volume create
volume attach
1. To use this, place computes.yaml at /etc/vitrage/static_datasources/
and restart vitrage-graph.
2. EXISTING_COMPUTES_NUM should match the computes defined in computes.yaml
3. Configure NET_ID to an existing network (this tool doesnt create networks)
4. Run 'python load_generator.py'
Number of vms = VMS_PER_COMPUTE * EXISTING_COMPUTES_NUM
Number of ports = VMS_PER_COMPUTE * EXISTING_COMPUTES_NUM
Number of volumes = VMS_PER_COMPUTE * EXISTING_COMPUTES_NUM
Notifications are sent repeatedly every RUN_EVERY_X_SECONDS, this is
to avoid Vitrage consistency deleting the created resources.
* Folder /templates also includes templates to create load on the evaluator
"""
class StressNotificationsService(cotyledon.Service):
def __init__(self, worker_id):
super(StressNotificationsService, self).__init__(worker_id)
self.oslo_notifier = None
topics = CONF.datasources.notification_topics
self.oslo_notifier = oslo_messaging.Notifier(
get_transport(),
driver='messagingv2',
publisher_id='vitrage.stress',
topics=topics)
self.periodic = periodics.PeriodicWorker.create(
[], executor_factory=lambda: ThreadPoolExecutor(max_workers=10))
def run(self):
LOG.info("StressNotificationsService - Started!")
self.periodic.add(self.stress_notifications)
self.periodic.start()
def terminate(self):
self.periodic.stop()
LOG.info("StressNotificationsService - Stopped!")
@periodics.periodic(spacing=RUN_EVERY_X_SECONDS)
def stress_notifications(self):
notifications = []
for i in range(EXISTING_COMPUTES_NUM * VMS_PER_COMPUTE):
vm = create_vm(i, i % EXISTING_COMPUTES_NUM)
port = create_port(i, vm[0][1]['instance_id'], vm[0][1]['host'],
NET_ID)
storage = create_storage(i, vm[0][1]['instance_id'])
notifications.extend(vm)
notifications.extend(port)
notifications.extend(storage)
LOG.info("Notifications Created - " + str(len(notifications)))
LOG.info("Sending...")
for n in notifications:
self._send(*n)
LOG.info("Sent!")
def _send(self, notification_type, payload):
try:
self.oslo_notifier.info(
{},
notification_type,
payload)
except Exception:
LOG.exception('Cannot notify - %s', notification_type)
def create_port(port_num, instance_id, host_id, net_id):
payload = copy.deepcopy(PORT_CREATE_END)
payload['port']['id'] = 'StressPort-' + str(port_num)
payload['port']['device_id'] = instance_id
payload['port']['binding:host_id'] = host_id
payload['port']['network_id'] = net_id
return [('port.create.end', payload)]
def create_storage(volume_num, instance_id):
payload_1 = copy.deepcopy(VOLUME_CREATE_END)
payload_1['volume_id'] = 'StressVolume-' + str(volume_num)
payload_2 = copy.deepcopy(VOLUME_ATTACH_END)
payload_2['volume_id'] = payload_1['volume_id']
payload_2['volume_attachment'][0]['volume']['id'] = payload_1['volume_id']
payload_2['volume_attachment'][0]['instance_uuid'] = instance_id
return [('volume.create.end', payload_1),
('volume.attach.end', payload_2)]
def create_vm(instance_num, compute_num):
payload = copy.deepcopy(COMPUTE_INSTANCE_CREATE_END)
payload['instance_id'] = 'StressVM-' + str(instance_num)
payload['node'] = payload['host'] = "compute-0-" + str(compute_num)
return [('compute.instance.create.end', payload)]
def main():
config.parse_config(sys.argv)
sm = cotyledon.ServiceManager()
sm.add(StressNotificationsService)
sm.run()
if __name__ == "__main__":
sys.exit(main())