testhost = ctx.cluster.only(config['server']).remotes.keys()[0].name
testhost = testhost.split('@')[1]
mypath = os.path.dirname(__file__)
- cmd_list = [os.path.join(mypath, 'calamari_testdir',
- 'test_server_1_0.py')]
+ cmd_list = [os.path.join(mypath, 'calamari', 'servertest_1_0.py')]
os.environ['CALAMARI_BASE_URI'] = 'http://{0}/api/v1/'.format(testhost)
log.info("testing %s", testhost)
return subprocess.call(cmd_list)
--- /dev/null
+#!/usr/bin/env python
+
+import json
+import logging
+import requests
+
+log = logging.getLogger(__name__)
+
+
+class AuthenticatedHttpClient(requests.Session):
+ """
+ Client for the calamari REST API, principally exists to do
+ authentication, but also helpfully prefixes
+ URLs in requests with the API base URL and JSONizes
+ POST data.
+ """
+ def __init__(self, api_url, username, password):
+ super(AuthenticatedHttpClient, self).__init__()
+ self._username = username
+ self._password = password
+ self._api_url = api_url
+ self.headers = {
+ 'Content-type': "application/json; charset=UTF-8"
+ }
+
+ def request(self, method, url, **kwargs):
+ if not url.startswith('/'):
+ url = self._api_url + url
+ response = super(AuthenticatedHttpClient, self).request(method, url, **kwargs)
+ if response.status_code >= 400:
+ # For the benefit of test logs
+ print "%s: %s" % (response.status_code, response.content)
+ return response
+
+ def post(self, url, data=None, **kwargs):
+ if isinstance(data, dict):
+ data = json.dumps(data)
+ return super(AuthenticatedHttpClient, self).post(url, data, **kwargs)
+
+ def patch(self, url, data=None, **kwargs):
+ if isinstance(data, dict):
+ data = json.dumps(data)
+ return super(AuthenticatedHttpClient, self).patch(url, data, **kwargs)
+
+ def login(self):
+ """
+ Authenticate with the Django auth system as
+ it is exposed in the Calamari REST API.
+ """
+ log.info("Logging in as %s" % self._username)
+ response = self.get("auth/login/")
+ response.raise_for_status()
+ self.headers['X-XSRF-TOKEN'] = response.cookies['XSRF-TOKEN']
+
+ self.post("auth/login/", {
+ 'next': "/",
+ 'username': self._username,
+ 'password': self._password
+ })
+ response.raise_for_status()
+
+ # Check we're allowed in now.
+ response = self.get("cluster")
+ response.raise_for_status()
+
+if __name__ == "__main__":
+
+ import argparse
+
+ p = argparse.ArgumentParser()
+ p.add_argument('-u', '--uri', default='http://mira035/api/v1/')
+ p.add_argument('--user', default='admin')
+ p.add_argument('--pass', dest='password', default='admin')
+ args, remainder = p.parse_known_args()
+
+ c = AuthenticatedHttpClient(args.uri, args.user, args.password)
+ c.login()
+ response = c.request('GET', ''.join(remainder)).json()
+ print json.dumps(response, indent=2)
--- /dev/null
+#!/usr/bin/env python
+
+import datetime
+import os
+import logging
+import logging.handlers
+import requests
+import uuid
+import unittest
+from http_client import AuthenticatedHttpClient
+
+log = logging.getLogger(__name__)
+log.addHandler(logging.StreamHandler())
+log.setLevel(logging.INFO)
+
+global base_uri
+global client
+base_uri = None
+server_uri = None
+client = None
+
+def setUpModule():
+ global base_uri
+ global server_uri
+ global client
+ try:
+ base_uri = os.environ['CALAMARI_BASE_URI']
+ except KeyError:
+ log.error('Must define CALAMARI_BASE_URI')
+ os._exit(1)
+ if not base_uri.endswith('/'):
+ base_uri += '/'
+ if not base_uri.endswith('api/v1/'):
+ base_uri += 'api/v1/'
+ client = AuthenticatedHttpClient(base_uri, 'admin', 'admin')
+ server_uri = base_uri.replace('api/v1/', '')
+ client.login()
+
+class RestTest(unittest.TestCase):
+ 'Base class for all tests here; get class\'s data'
+
+ def setUp(self):
+ # Called once for each test_* case. A bit wasteful, but we
+ # really like using the simple class variable self.uri
+ # to customize each derived TestCase
+ method = getattr(self, 'method', 'GET')
+ raw = self.uri.startswith('/')
+ self.response = self.get_object(method, self.uri, raw=raw)
+
+ def get_object(self, method, url, raw=False):
+ global server_uri
+ 'Return Python object decoded from JSON response to method/url'
+ if not raw:
+ return client.request(method, url).json()
+ else:
+ return requests.request(method, server_uri + url).json()
+
+class TestUserMe(RestTest):
+
+ uri = 'user/me'
+
+ def test_me(self):
+ self.assertEqual(self.response['username'], 'admin')
+
+class TestCluster(RestTest):
+
+ uri = 'cluster'
+
+ def test_id(self):
+ self.assertEqual(self.response[0]['id'], 1)
+
+ def test_times(self):
+ for time in (
+ self.response[0]['cluster_update_time'],
+ self.response[0]['cluster_update_attempt_time'],
+ ):
+ self.assertTrue(is_datetime(time))
+
+ def test_api_base_url(self):
+ api_base_url = self.response[0]['api_base_url']
+ self.assertTrue(api_base_url.startswith('http'))
+ self.assertIn('api/v0.1', api_base_url)
+
+class TestHealth(RestTest):
+
+ uri = 'cluster/1/health'
+
+ def test_cluster(self):
+ self.assertEqual(self.response['cluster'], 1)
+
+ def test_times(self):
+ for time in (
+ self.response['cluster_update_time'],
+ self.response['added'],
+ ):
+ self.assertTrue(is_datetime(time))
+
+ def test_report_and_overall_status(self):
+ self.assertIn('report', self.response)
+ self.assertIn('overall_status', self.response['report'])
+
+class TestHealthCounters(RestTest):
+
+ uri = 'cluster/1/health_counters'
+
+ def test_cluster(self):
+ self.assertEqual(self.response['cluster'], 1)
+
+ def test_time(self):
+ self.assertTrue(is_datetime(self.response['cluster_update_time']))
+
+ def test_existence(self):
+ for section in ('pg', 'mon', 'osd'):
+ for counter in ('warn', 'critical', 'ok'):
+ count = self.response[section][counter]['count']
+ self.assertIsInstance(count, int)
+ self.assertIsInstance(self.response['pool']['total'], int)
+
+ def test_mds_sum(self):
+ count = self.response['mds']
+ self.assertEqual(
+ count['up_not_in'] + count['not_up_not_in'] + count['up_in'],
+ count['total']
+ )
+
+class TestSpace(RestTest):
+
+ uri = 'cluster/1/space'
+
+ def test_cluster(self):
+ self.assertEqual(self.response['cluster'], 1)
+
+ def test_times(self):
+ for time in (
+ self.response['cluster_update_time'],
+ self.response['added'],
+ ):
+ self.assertTrue(is_datetime(time))
+
+ def test_space(self):
+ for size in ('free_bytes', 'used_bytes', 'capacity_bytes'):
+ self.assertIsInstance(self.response['space'][size], int)
+ self.assertGreater(self.response['space'][size], 0)
+
+ def test_report(self):
+ for size in ('total_used', 'total_space', 'total_avail'):
+ self.assertIsInstance(self.response['report'][size], int)
+ self.assertGreater(self.response['report'][size], 0)
+
+class TestOSD(RestTest):
+
+ uri = 'cluster/1/osd'
+
+ def test_cluster(self):
+ self.assertEqual(self.response['cluster'], 1)
+
+ def test_times(self):
+ for time in (
+ self.response['cluster_update_time'],
+ self.response['added'],
+ ):
+ self.assertTrue(is_datetime(time))
+
+ def test_osd_uuid(self):
+ for osd in self.response['osds']:
+ uuidobj = uuid.UUID(osd['uuid'])
+ self.assertEqual(str(uuidobj), osd['uuid'])
+
+ def test_osd_pools(self):
+ for osd in self.response['osds']:
+ if osd['up'] != 1:
+ continue
+ self.assertIsInstance(osd['pools'], list)
+ self.assertIsInstance(osd['pools'][0], basestring)
+
+ def test_osd_up_in(self):
+ for osd in self.response['osds']:
+ for flag in ('up', 'in'):
+ self.assertIn(osd[flag], (0, 1))
+
+ def test_osd_0(self):
+ osd0 = self.get_object('GET', 'cluster/1/osd/0')['osd']
+ for field in osd0.keys():
+ if not field.startswith('cluster_update_time'):
+ self.assertEqual(self.response['osds'][0][field], osd0[field])
+
+class TestPool(RestTest):
+
+ uri = 'cluster/1/pool'
+
+ def test_cluster(self):
+ for pool in self.response:
+ self.assertEqual(pool['cluster'], 1)
+
+ def test_fields_are_ints(self):
+ for pool in self.response:
+ for field in ('id', 'used_objects', 'used_bytes'):
+ self.assertIsInstance(pool[field], int)
+
+ def test_name_is_str(self):
+ for pool in self.response:
+ self.assertIsInstance(pool['name'], basestring)
+
+ def test_pool_0(self):
+ poolid = self.response[0]['id']
+ pool = self.get_object('GET', 'cluster/1/pool/{id}'.format(id=poolid))
+ self.assertEqual(self.response[0], pool)
+
+class TestServer(RestTest):
+
+ uri = 'cluster/1/server'
+
+ def test_ipaddr(self):
+ for server in self.response:
+ octets = server['addr'].split('.')
+ self.assertEqual(len(octets), 4)
+ for octetstr in octets:
+ octet = int(octetstr)
+ self.assertIsInstance(octet, int)
+ self.assertGreaterEqual(octet, 0)
+ self.assertLessEqual(octet, 255)
+
+ def test_hostname_name_strings(self):
+ for server in self.response:
+ for field in ('name', 'hostname'):
+ self.assertIsInstance(server[field], basestring)
+
+ def test_services(self):
+ for server in self.response:
+ self.assertIsInstance(server['services'], list)
+ for service in server['services']:
+ self.assertIn(service['type'], ('osd', 'mon', 'mds'))
+
+class TestGraphitePoolIOPS(RestTest):
+
+ uri = '/graphite/render?format=json-array&' \
+ 'target=ceph.cluster.ceph.pool.0.num_read&' \
+ 'target=ceph.cluster.ceph.pool.0.num_write'
+
+ def test_targets_contain_request(self):
+ self.assertIn('targets', self.response)
+ self.assertIn('ceph.cluster.ceph.pool.0.num_read',
+ self.response['targets'])
+ self.assertIn('ceph.cluster.ceph.pool.0.num_write',
+ self.response['targets'])
+
+ def test_datapoints(self):
+ self.assertIn('datapoints', self.response)
+ self.assertGreater(len(self.response['datapoints']), 0)
+ data = self.response['datapoints'][0]
+ self.assertEqual(len(data), 3)
+ self.assertIsInstance(data[0], int)
+ if data[1]:
+ self.assertIsInstance(data[1], float)
+ if data[2]:
+ self.assertIsInstance(data[2], float)
+
+#
+# Utility functions
+#
+
+DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
+
+def is_datetime(time):
+ datetime.datetime.strptime(time, DATETIME_FORMAT)
+ return True
+
+if __name__ == '__main__':
+ unittest.main()
+++ /dev/null
-#!/usr/bin/env python
-
-import json
-import logging
-import requests
-
-log = logging.getLogger(__name__)
-
-
-class AuthenticatedHttpClient(requests.Session):
- """
- Client for the calamari REST API, principally exists to do
- authentication, but also helpfully prefixes
- URLs in requests with the API base URL and JSONizes
- POST data.
- """
- def __init__(self, api_url, username, password):
- super(AuthenticatedHttpClient, self).__init__()
- self._username = username
- self._password = password
- self._api_url = api_url
- self.headers = {
- 'Content-type': "application/json; charset=UTF-8"
- }
-
- def request(self, method, url, **kwargs):
- if not url.startswith('/'):
- url = self._api_url + url
- response = super(AuthenticatedHttpClient, self).request(method, url, **kwargs)
- if response.status_code >= 400:
- # For the benefit of test logs
- print "%s: %s" % (response.status_code, response.content)
- return response
-
- def post(self, url, data=None, **kwargs):
- if isinstance(data, dict):
- data = json.dumps(data)
- return super(AuthenticatedHttpClient, self).post(url, data, **kwargs)
-
- def patch(self, url, data=None, **kwargs):
- if isinstance(data, dict):
- data = json.dumps(data)
- return super(AuthenticatedHttpClient, self).patch(url, data, **kwargs)
-
- def login(self):
- """
- Authenticate with the Django auth system as
- it is exposed in the Calamari REST API.
- """
- log.info("Logging in as %s" % self._username)
- response = self.get("auth/login/")
- response.raise_for_status()
- self.headers['X-XSRF-TOKEN'] = response.cookies['XSRF-TOKEN']
-
- self.post("auth/login/", {
- 'next': "/",
- 'username': self._username,
- 'password': self._password
- })
- response.raise_for_status()
-
- # Check we're allowed in now.
- response = self.get("cluster")
- response.raise_for_status()
-
-if __name__ == "__main__":
-
- import argparse
-
- p = argparse.ArgumentParser()
- p.add_argument('-u', '--uri', default='http://mira035/api/v1/')
- p.add_argument('--user', default='admin')
- p.add_argument('--pass', dest='password', default='admin')
- args, remainder = p.parse_known_args()
-
- c = AuthenticatedHttpClient(args.uri, args.user, args.password)
- c.login()
- response = c.request('GET', ''.join(remainder)).json()
- print json.dumps(response, indent=2)
+++ /dev/null
-#!/usr/bin/env python
-
-import datetime
-import os
-import logging
-import logging.handlers
-import requests
-import uuid
-import unittest
-from http_client import AuthenticatedHttpClient
-
-log = logging.getLogger(__name__)
-log.addHandler(logging.StreamHandler())
-log.setLevel(logging.INFO)
-
-global base_uri
-global client
-base_uri = None
-server_uri = None
-client = None
-
-def setUpModule():
- global base_uri
- global server_uri
- global client
- try:
- base_uri = os.environ['CALAMARI_BASE_URI']
- except KeyError:
- log.error('Must define CALAMARI_BASE_URI')
- os._exit(1)
- if not base_uri.endswith('/'):
- base_uri += '/'
- if not base_uri.endswith('api/v1/'):
- base_uri += 'api/v1/'
- client = AuthenticatedHttpClient(base_uri, 'admin', 'admin')
- server_uri = base_uri.replace('api/v1/', '')
- client.login()
-
-class RestTest(unittest.TestCase):
- 'Base class for all tests here; get class\'s data'
-
- def setUp(self):
- # Called once for each test_* case. A bit wasteful, but we
- # really like using the simple class variable self.uri
- # to customize each derived TestCase
- method = getattr(self, 'method', 'GET')
- raw = self.uri.startswith('/')
- self.response = self.get_object(method, self.uri, raw=raw)
-
- def get_object(self, method, url, raw=False):
- global server_uri
- 'Return Python object decoded from JSON response to method/url'
- if not raw:
- return client.request(method, url).json()
- else:
- return requests.request(method, server_uri + url).json()
-
-class TestUserMe(RestTest):
-
- uri = 'user/me'
-
- def test_me(self):
- self.assertEqual(self.response['username'], 'admin')
-
-class TestCluster(RestTest):
-
- uri = 'cluster'
-
- def test_id(self):
- self.assertEqual(self.response[0]['id'], 1)
-
- def test_times(self):
- for time in (
- self.response[0]['cluster_update_time'],
- self.response[0]['cluster_update_attempt_time'],
- ):
- self.assertTrue(is_datetime(time))
-
- def test_api_base_url(self):
- api_base_url = self.response[0]['api_base_url']
- self.assertTrue(api_base_url.startswith('http'))
- self.assertIn('api/v0.1', api_base_url)
-
-class TestHealth(RestTest):
-
- uri = 'cluster/1/health'
-
- def test_cluster(self):
- self.assertEqual(self.response['cluster'], 1)
-
- def test_times(self):
- for time in (
- self.response['cluster_update_time'],
- self.response['added'],
- ):
- self.assertTrue(is_datetime(time))
-
- def test_report_and_overall_status(self):
- self.assertIn('report', self.response)
- self.assertIn('overall_status', self.response['report'])
-
-class TestHealthCounters(RestTest):
-
- uri = 'cluster/1/health_counters'
-
- def test_cluster(self):
- self.assertEqual(self.response['cluster'], 1)
-
- def test_time(self):
- self.assertTrue(is_datetime(self.response['cluster_update_time']))
-
- def test_existence(self):
- for section in ('pg', 'mon', 'osd'):
- for counter in ('warn', 'critical', 'ok'):
- count = self.response[section][counter]['count']
- self.assertIsInstance(count, int)
- self.assertIsInstance(self.response['pool']['total'], int)
-
- def test_mds_sum(self):
- count = self.response['mds']
- self.assertEqual(
- count['up_not_in'] + count['not_up_not_in'] + count['up_in'],
- count['total']
- )
-
-class TestSpace(RestTest):
-
- uri = 'cluster/1/space'
-
- def test_cluster(self):
- self.assertEqual(self.response['cluster'], 1)
-
- def test_times(self):
- for time in (
- self.response['cluster_update_time'],
- self.response['added'],
- ):
- self.assertTrue(is_datetime(time))
-
- def test_space(self):
- for size in ('free_bytes', 'used_bytes', 'capacity_bytes'):
- self.assertIsInstance(self.response['space'][size], int)
- self.assertGreater(self.response['space'][size], 0)
-
- def test_report(self):
- for size in ('total_used', 'total_space', 'total_avail'):
- self.assertIsInstance(self.response['report'][size], int)
- self.assertGreater(self.response['report'][size], 0)
-
-class TestOSD(RestTest):
-
- uri = 'cluster/1/osd'
-
- def test_cluster(self):
- self.assertEqual(self.response['cluster'], 1)
-
- def test_times(self):
- for time in (
- self.response['cluster_update_time'],
- self.response['added'],
- ):
- self.assertTrue(is_datetime(time))
-
- def test_osd_uuid(self):
- for osd in self.response['osds']:
- uuidobj = uuid.UUID(osd['uuid'])
- self.assertEqual(str(uuidobj), osd['uuid'])
-
- def test_osd_pools(self):
- for osd in self.response['osds']:
- if osd['up'] != 1:
- continue
- self.assertIsInstance(osd['pools'], list)
- self.assertIsInstance(osd['pools'][0], basestring)
-
- def test_osd_up_in(self):
- for osd in self.response['osds']:
- for flag in ('up', 'in'):
- self.assertIn(osd[flag], (0, 1))
-
- def test_osd_0(self):
- osd0 = self.get_object('GET', 'cluster/1/osd/0')['osd']
- for field in osd0.keys():
- if not field.startswith('cluster_update_time'):
- self.assertEqual(self.response['osds'][0][field], osd0[field])
-
-class TestPool(RestTest):
-
- uri = 'cluster/1/pool'
-
- def test_cluster(self):
- for pool in self.response:
- self.assertEqual(pool['cluster'], 1)
-
- def test_fields_are_ints(self):
- for pool in self.response:
- for field in ('id', 'used_objects', 'used_bytes'):
- self.assertIsInstance(pool[field], int)
-
- def test_name_is_str(self):
- for pool in self.response:
- self.assertIsInstance(pool['name'], basestring)
-
- def test_pool_0(self):
- poolid = self.response[0]['id']
- pool = self.get_object('GET', 'cluster/1/pool/{id}'.format(id=poolid))
- self.assertEqual(self.response[0], pool)
-
-class TestServer(RestTest):
-
- uri = 'cluster/1/server'
-
- def test_ipaddr(self):
- for server in self.response:
- octets = server['addr'].split('.')
- self.assertEqual(len(octets), 4)
- for octetstr in octets:
- octet = int(octetstr)
- self.assertIsInstance(octet, int)
- self.assertGreaterEqual(octet, 0)
- self.assertLessEqual(octet, 255)
-
- def test_hostname_name_strings(self):
- for server in self.response:
- for field in ('name', 'hostname'):
- self.assertIsInstance(server[field], basestring)
-
- def test_services(self):
- for server in self.response:
- self.assertIsInstance(server['services'], list)
- for service in server['services']:
- self.assertIn(service['type'], ('osd', 'mon', 'mds'))
-
-class TestGraphitePoolIOPS(RestTest):
-
- uri = '/graphite/render?format=json-array&' \
- 'target=ceph.cluster.ceph.pool.0.num_read&' \
- 'target=ceph.cluster.ceph.pool.0.num_write'
-
- def test_targets_contain_request(self):
- self.assertIn('targets', self.response)
- self.assertIn('ceph.cluster.ceph.pool.0.num_read',
- self.response['targets'])
- self.assertIn('ceph.cluster.ceph.pool.0.num_write',
- self.response['targets'])
-
- def test_datapoints(self):
- self.assertIn('datapoints', self.response)
- self.assertGreater(len(self.response['datapoints']), 0)
- data = self.response['datapoints'][0]
- self.assertEqual(len(data), 3)
- self.assertIsInstance(data[0], int)
- if data[1]:
- self.assertIsInstance(data[1], float)
- if data[2]:
- self.assertIsInstance(data[2], float)
-
-#
-# Utility functions
-#
-
-DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
-
-def is_datetime(time):
- datetime.datetime.strptime(time, DATETIME_FORMAT)
- return True
-
-if __name__ == '__main__':
- unittest.main()