
In standard system locations, check for the client.admin key for each detected Ceph cluster and conditionally suppress Ceph agent checks that require it if it is not found. Change-Id: If3a28ceb5cdde40749d077ad465054eba37c848c Story: 2005172
254 lines
9.4 KiB
Python
254 lines
9.4 KiB
Python
# 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 mock
|
|
|
|
from oslotest import base
|
|
import psutil
|
|
|
|
from monasca_setup.detection.plugins import ceph
|
|
|
|
|
|
MON_PROCESSES = [
|
|
{'name': 'ceph-mon.mon0',
|
|
'type': 'ceph-mon',
|
|
'search_string': [
|
|
'/usr/bin/ceph-mon --cluster ceph --id mon0 -f',
|
|
'/usr/bin/ceph-mon --cluster ceph -f --id mon0',
|
|
'/usr/bin/ceph-mon --id mon0 --cluster ceph -f',
|
|
'/usr/bin/ceph-mon --id mon0 -f --cluster ceph',
|
|
'/usr/bin/ceph-mon -f --cluster ceph --id mon0',
|
|
'/usr/bin/ceph-mon -f --id mon0 --cluster ceph'
|
|
]},
|
|
{'name': 'ceph1-mon.mon0',
|
|
'type': 'ceph-mon',
|
|
'search_string': [
|
|
'/usr/bin/ceph-mon --cluster ceph1 --id mon0 -f',
|
|
'/usr/bin/ceph-mon --cluster ceph1 -f --id mon0',
|
|
'/usr/bin/ceph-mon --id mon0 --cluster ceph1 -f',
|
|
'/usr/bin/ceph-mon --id mon0 -f --cluster ceph1',
|
|
'/usr/bin/ceph-mon -f --cluster ceph1 --id mon0',
|
|
'/usr/bin/ceph-mon -f --id mon0 --cluster ceph1'
|
|
]},
|
|
]
|
|
|
|
RGW_PROCESSES = [
|
|
{'name': 'ceph-radosgw.rgw0',
|
|
'type': 'ceph-radosgw',
|
|
'search_string': [
|
|
'/usr/bin/radosgw --cluster ceph --name client.rgw.rgw0 -f',
|
|
'/usr/bin/radosgw --cluster ceph -f --name client.rgw.rgw0',
|
|
'/usr/bin/radosgw --name client.rgw.rgw0 --cluster ceph -f',
|
|
'/usr/bin/radosgw --name client.rgw.rgw0 -f --cluster ceph',
|
|
'/usr/bin/radosgw -f --cluster ceph --name client.rgw.rgw0',
|
|
'/usr/bin/radosgw -f --name client.rgw.rgw0 --cluster ceph'
|
|
]},
|
|
{'name': 'ceph1-radosgw.rgw0',
|
|
'type': 'ceph-radosgw',
|
|
'search_string': [
|
|
'/usr/bin/radosgw --cluster ceph1 --name client.rgw.rgw0 -f',
|
|
'/usr/bin/radosgw --cluster ceph1 -f --name client.rgw.rgw0',
|
|
'/usr/bin/radosgw --name client.rgw.rgw0 --cluster ceph1 -f',
|
|
'/usr/bin/radosgw --name client.rgw.rgw0 -f --cluster ceph1',
|
|
'/usr/bin/radosgw -f --cluster ceph1 --name client.rgw.rgw0',
|
|
'/usr/bin/radosgw -f --name client.rgw.rgw0 --cluster ceph1'
|
|
]},
|
|
]
|
|
|
|
|
|
def mocked_service_config(*args, **kwargs):
|
|
if args[1] == 'mon':
|
|
return MON_PROCESSES
|
|
elif args[1] == 'radosgw':
|
|
return RGW_PROCESSES
|
|
return []
|
|
|
|
|
|
class FakeProcess(object):
|
|
cmdLine = None
|
|
|
|
def as_dict(self, attrs=None):
|
|
all_attrs = {'name': 'ceph',
|
|
'exe': FakeProcess.exe(),
|
|
'cmdline': FakeProcess.cmdline()}
|
|
if attrs:
|
|
for key in attrs:
|
|
if key not in all_attrs:
|
|
all_attrs.pop(key, None)
|
|
return all_attrs
|
|
|
|
@staticmethod
|
|
def exe():
|
|
line = FakeProcess.cmdLine
|
|
if not line:
|
|
return None
|
|
return line[0]
|
|
|
|
@staticmethod
|
|
def cmdline():
|
|
return FakeProcess.cmdLine
|
|
|
|
|
|
class TestCephDetection(base.BaseTestCase):
|
|
CLUSTERS = [
|
|
{
|
|
'cluster_name': 'ceph',
|
|
'config_file': '/etc/ceph/ceph.conf'
|
|
},
|
|
{
|
|
'cluster_name': 'ceph1',
|
|
'config_file': '/etc/ceph/ceph1.conf'
|
|
},
|
|
]
|
|
|
|
def setUp(self):
|
|
super(TestCephDetection, self).setUp()
|
|
with mock.patch.object(ceph.Ceph, '_detect') as mock_detect:
|
|
self._ceph = ceph.Ceph('ceph')
|
|
self.assertTrue(mock_detect.called)
|
|
|
|
def test_should_not_configure_if_no_process(self):
|
|
FakeProcess.cmdLine = []
|
|
self._detect(proc=True)
|
|
self.assertFalse(self._ceph.available)
|
|
|
|
def test_should_be_available_if_everything_matches(self):
|
|
ceph_cmd = '/usr/bin/ceph-mon -f --cluster ceph --id mon0 --setuser' \
|
|
' ceph --setgroup ceph'
|
|
FakeProcess.cmdLine = [ceph_cmd]
|
|
self._detect()
|
|
self.assertTrue(self._ceph.available)
|
|
|
|
def test_build_search_string(self):
|
|
executable = '/usr/bin/ceph-mon'
|
|
args = ['--cluster ceph', '--id mon0', '-f']
|
|
|
|
expected_strings = [
|
|
'/usr/bin/ceph-mon --cluster ceph --id mon0 -f',
|
|
'/usr/bin/ceph-mon --cluster ceph -f --id mon0',
|
|
'/usr/bin/ceph-mon --id mon0 --cluster ceph -f',
|
|
'/usr/bin/ceph-mon --id mon0 -f --cluster ceph',
|
|
'/usr/bin/ceph-mon -f --cluster ceph --id mon0',
|
|
'/usr/bin/ceph-mon -f --id mon0 --cluster ceph'
|
|
]
|
|
|
|
search_strings = self._ceph._build_search_string(executable, args)
|
|
self.assertEqual(expected_strings, search_strings)
|
|
|
|
@mock.patch('os.path.exists', return_value=True)
|
|
@mock.patch('os.listdir', return_value=['ceph-mon0', 'ceph1-mon0'])
|
|
def test_service_config(self, list_dir, path_exists):
|
|
processes = self._ceph._service_config(self.CLUSTERS, 'mon')
|
|
self.assertEqual(MON_PROCESSES, processes)
|
|
|
|
@mock.patch('os.path.exists', return_value=True)
|
|
@mock.patch('os.listdir', return_value=['ceph-rgw.rgw0', 'ceph1-rgw.rgw0'])
|
|
def test_radosgw_service_config(self, list_dir, path_exists):
|
|
processes = self._ceph._service_config(self.CLUSTERS, 'radosgw')
|
|
self.assertEqual(RGW_PROCESSES, processes)
|
|
|
|
@mock.patch('os.path.exists', return_value=True)
|
|
@mock.patch('os.listdir', return_value=[])
|
|
def test_build_config_with_no_ceph_conf(self, list_dir, path_exists):
|
|
config = self._ceph.build_config()
|
|
self.assertEqual({}, dict(config))
|
|
|
|
@mock.patch('os.path.exists', return_value=True)
|
|
@mock.patch('os.listdir', return_value=['ceph.conf', 'ceph1.conf'])
|
|
def test_build_config_with_no_admin_key(self, list_dir, path_exists):
|
|
self._ceph._service_config = mock.Mock(
|
|
side_effect=mocked_service_config)
|
|
|
|
processes = MON_PROCESSES + RGW_PROCESSES
|
|
process_instances = list()
|
|
|
|
for p in processes:
|
|
instance = {
|
|
'exact_match': False,
|
|
'search_string': p['search_string'],
|
|
'detailed': True,
|
|
'name': p['name'],
|
|
'dimensions': {'component': p['type'], 'service': 'ceph'}
|
|
}
|
|
process_instances.append(instance)
|
|
|
|
expected_config = {
|
|
'process': {
|
|
'init_config': None,
|
|
'instances': process_instances,
|
|
},
|
|
'ceph': {
|
|
'init_config': None,
|
|
'instances': [{'cluster_name': 'ceph',
|
|
'collect_mon_metrics': False,
|
|
'collect_osd_metrics': False,
|
|
'collect_pool_metrics': False,
|
|
'collect_stats_metrics': False,
|
|
'collect_usage_metrics': False},
|
|
{'cluster_name': 'ceph1',
|
|
'collect_mon_metrics': False,
|
|
'collect_osd_metrics': False,
|
|
'collect_pool_metrics': False,
|
|
'collect_stats_metrics': False,
|
|
'collect_usage_metrics': False}]
|
|
}
|
|
}
|
|
config = self._ceph.build_config()
|
|
self.assertEqual(expected_config, dict(config))
|
|
|
|
@mock.patch('os.path.exists', return_value=True)
|
|
@mock.patch('os.listdir', return_value=['ceph.conf', 'ceph1.conf', 'ceph1.client.admin.keyring'])
|
|
def test_build_config(self, list_dir, path_exists):
|
|
self._ceph._service_config = mock.Mock(
|
|
side_effect=mocked_service_config)
|
|
|
|
processes = MON_PROCESSES + RGW_PROCESSES
|
|
process_instances = list()
|
|
|
|
for p in processes:
|
|
instance = {
|
|
'exact_match': False,
|
|
'search_string': p['search_string'],
|
|
'detailed': True,
|
|
'name': p['name'],
|
|
'dimensions': {'component': p['type'], 'service': 'ceph'}
|
|
}
|
|
process_instances.append(instance)
|
|
|
|
expected_config = {
|
|
'process': {
|
|
'init_config': None,
|
|
'instances': process_instances,
|
|
},
|
|
'ceph': {
|
|
'init_config': None,
|
|
'instances': [{'cluster_name': 'ceph',
|
|
'collect_mon_metrics': False,
|
|
'collect_osd_metrics': False,
|
|
'collect_pool_metrics': False,
|
|
'collect_stats_metrics': False,
|
|
'collect_usage_metrics': False},
|
|
{'cluster_name': 'ceph1'}]
|
|
}
|
|
}
|
|
config = self._ceph.build_config()
|
|
self.assertEqual(expected_config, dict(config))
|
|
|
|
def _detect(self, proc=False):
|
|
self._ceph.available = False
|
|
processes = [FakeProcess()] if not proc else []
|
|
process_iter = mock.patch.object(psutil, 'process_iter',
|
|
return_value=processes)
|
|
with process_iter as mock_process_iter:
|
|
self._ceph._detect()
|
|
self.assertTrue(mock_process_iter.called)
|