aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchenjiankun <chenjiankun1@huawei.com>2017-07-17 07:40:09 +0000
committerchenjiankun <chenjiankun1@huawei.com>2017-07-17 07:40:09 +0000
commit6444f136ec83856e7d9beabf765124d2a6d18466 (patch)
tree0d6a1bac0ba7346048d06121b8b5d56f29e98fb8
parent146e193c209fe654c4aeb88e9a2564df9960a8e4 (diff)
Add API(v2) to create grafana
JIRA: YARDSTICK-727 API: /api/v2/yardstick/containers/action METHOD: POST PARAMS: { 'action': 'create_influxdb', 'args': { 'environment_id': environment_id } } Change-Id: I12fc23261ba62df6f923a4d34455ad8b46c4aa8f Signed-off-by: chenjiankun <chenjiankun1@huawei.com>
-rw-r--r--api/database/v2/handlers.py6
-rw-r--r--api/resources/v2/containers.py159
2 files changed, 158 insertions, 7 deletions
diff --git a/api/database/v2/handlers.py b/api/database/v2/handlers.py
index 095ad724c..3474af2c1 100644
--- a/api/database/v2/handlers.py
+++ b/api/database/v2/handlers.py
@@ -122,6 +122,12 @@ class V2ContainerHandler(object):
raise ValueError
return container
+ def update_attr(self, uuid, attr):
+ container = self.get_by_uuid(uuid)
+ for k, v in attr.items():
+ setattr(container, k, v)
+ db_session.commit()
+
def delete_by_uuid(self, uuid):
container = self.get_by_uuid(uuid)
db_session.delete(container)
diff --git a/api/resources/v2/containers.py b/api/resources/v2/containers.py
index 9219c7cac..5042e0592 100644
--- a/api/resources/v2/containers.py
+++ b/api/resources/v2/containers.py
@@ -12,6 +12,8 @@ import logging
import threading
import time
import uuid
+import os
+import glob
from six.moves import configparser
from oslo_serialization import jsonutils
@@ -25,6 +27,7 @@ from yardstick.common import constants as consts
from yardstick.common import utils
from yardstick.common.utils import result_handler
from yardstick.common.utils import get_free_port
+from yardstick.common.httpClient import HttpClient
LOG = logging.getLogger(__name__)
@@ -114,16 +117,16 @@ class V2Containers(ApiResource):
LOG.debug('container ip is: %s', ip)
LOG.info('Changing output to influxdb')
- self._change_output_to_influxdb(ip, port)
+ self._change_output_to_influxdb(ip)
LOG.info('Config influxdb')
- self._config_influxdb(port)
+ self._config_influxdb()
- container_handler.update_attr(container_id, 'status', 1)
+ container_handler.update_attr(container_id, {'status': 1})
LOG.info('Finished')
except Exception:
- container_handler.update_attr(container_id, 'status', 2)
+ container_handler.update_attr(container_id, {'status': 2})
LOG.exception('Creating influxdb failed')
def _create_influxdb_container(self, client, name, port):
@@ -147,7 +150,7 @@ class V2Containers(ApiResource):
client.start(container)
return container
- def _config_influxdb(self, port):
+ def _config_influxdb(self):
try:
client = influx.get_data_db_client()
client.create_user(consts.INFLUXDB_USER,
@@ -158,7 +161,7 @@ class V2Containers(ApiResource):
except Exception:
LOG.exception('Config influxdb failed')
- def _change_output_to_influxdb(self, ip, port):
+ def _change_output_to_influxdb(self, ip):
utils.makedirs(consts.CONF_DIR)
parser = configparser.ConfigParser()
@@ -168,8 +171,150 @@ class V2Containers(ApiResource):
LOG.info('Set dispatcher to influxdb')
parser.set('DEFAULT', 'dispatcher', 'influxdb')
parser.set('dispatcher_influxdb', 'target',
- 'http://{}:{}'.format(ip, port))
+ 'http://{}:{}'.format(ip, 8086))
LOG.info('Writing to %s', consts.CONF_FILE)
with open(consts.CONF_FILE, 'w') as f:
parser.write(f)
+
+ def create_grafana(self, args):
+ try:
+ environment_id = args['environment_id']
+ except KeyError:
+ return result_handler(consts.API_ERROR, 'environment_id must be provided')
+
+ try:
+ uuid.UUID(environment_id)
+ except ValueError:
+ return result_handler(consts.API_ERROR, 'invalid environment id')
+
+ try:
+ environment = environment_handler.get_by_uuid(environment_id)
+ except ValueError:
+ return result_handler(consts.API_ERROR, 'no such environment id')
+
+ container_info = environment.container_id
+ container_info = jsonutils.loads(container_info) if container_info else {}
+
+ if not container_info.get('influxdb'):
+ return result_handler(consts.API_ERROR, 'influxdb not set')
+
+ if container_info.get('grafana'):
+ return result_handler(consts.API_ERROR, 'grafana container already exists')
+
+ name = 'grafana-{}'.format(environment_id[:8])
+ port = get_free_port(consts.SERVER_IP)
+ container_id = str(uuid.uuid4())
+
+ args = (name, port, container_id)
+ thread = threading.Thread(target=self._create_grafana, args=args)
+ thread.start()
+
+ container_init_data = {
+ 'uuid': container_id,
+ 'environment_id': environment_id,
+ 'name': name,
+ 'port': port,
+ 'status': 0
+ }
+ container_handler.insert(container_init_data)
+
+ container_info['grafana'] = container_id
+ environment_info = {'container_id': jsonutils.dumps(container_info)}
+ environment_handler.update_attr(environment_id, environment_info)
+
+ return result_handler(consts.API_SUCCESS, {'uuid': container_id})
+
+ def _create_grafana(self, name, port, container_id):
+ client = Client(base_url=consts.DOCKER_URL)
+
+ try:
+ LOG.info('Checking if grafana image exist')
+ image = '{}:{}'.format(consts.GRAFANA_IMAGE, consts.GRAFANA_TAG)
+ if not self._check_image_exist(client, image):
+ LOG.info('Grafana image not exist, start pulling')
+ client.pull(consts.GRAFANA_IMAGE, consts.GRAFANA_TAG)
+
+ LOG.info('Createing grafana container')
+ container = self._create_grafana_container(client, name, port)
+ LOG.info('Grafana container is created')
+
+ time.sleep(5)
+
+ container = client.inspect_container(container['Id'])
+ ip = container['NetworkSettings']['Networks']['bridge']['IPAddress']
+ LOG.debug('container ip is: %s', ip)
+
+ LOG.info('Creating data source for grafana')
+ self._create_data_source(ip)
+
+ LOG.info('Creating dashboard for grafana')
+ self._create_dashboard(ip)
+
+ container_handler.update_attr(container_id, {'status': 1})
+ LOG.info('Finished')
+ except Exception:
+ container_handler.update_attr(container_id, {'status': 2})
+ LOG.exception('Create grafana failed')
+
+ def _create_dashboard(self, ip):
+ url = 'http://admin:admin@{}:{}/api/dashboards/db'.format(ip, 3000)
+ path = os.path.join(consts.REPOS_DIR, 'dashboard', '*dashboard.json')
+
+ for i in sorted(glob.iglob(path)):
+ with open(i) as f:
+ data = jsonutils.load(f)
+ try:
+ HttpClient().post(url, data)
+ except Exception:
+ LOG.exception('Create dashboard %s failed', i)
+ raise
+
+ def _create_data_source(self, ip):
+ url = 'http://admin:admin@{}:{}/api/datasources'.format(ip, 3000)
+
+ influx_conf = utils.parse_ini_file(consts.CONF_FILE)
+ try:
+ influx_url = influx_conf['dispatcher_influxdb']['target']
+ except KeyError:
+ LOG.exception('influxdb url not set in yardstick.conf')
+ raise
+
+ data = {
+ "name": "yardstick",
+ "type": "influxdb",
+ "access": "proxy",
+ "url": influx_url,
+ "password": "root",
+ "user": "root",
+ "database": "yardstick",
+ "basicAuth": True,
+ "basicAuthUser": "admin",
+ "basicAuthPassword": "admin",
+ "isDefault": False,
+ }
+ try:
+ HttpClient().post(url, data)
+ except Exception:
+ LOG.exception('Create datasources failed')
+ raise
+
+ def _create_grafana_container(self, client, name, port):
+ ports = [3000]
+ port_bindings = {3000: port}
+ restart_policy = {"MaximumRetryCount": 0, "Name": "always"}
+ host_config = client.create_host_config(port_bindings=port_bindings,
+ restart_policy=restart_policy)
+
+ LOG.info('Creating container')
+ container = client.create_container(image='%s:%s' %
+ (consts.GRAFANA_IMAGE,
+ consts.GRAFANA_TAG),
+ name=name,
+ ports=ports,
+ detach=True,
+ tty=True,
+ host_config=host_config)
+ LOG.info('Starting container')
+ client.start(container)
+ return container