]> git-server-git.apps.pok.os.sepia.ceph.com Git - teuthology.git/commitdiff
Add ceph_ansible task 789/head
authorZack Cerza <zack@redhat.com>
Tue, 9 Feb 2016 17:39:57 +0000 (10:39 -0700)
committerZack Cerza <zack@redhat.com>
Thu, 18 Feb 2016 22:46:48 +0000 (15:46 -0700)
Signed-off-by: Zack Cerza <zack@redhat.com>
teuthology/task/ceph_ansible.py [new file with mode: 0644]
teuthology/test/task/test_ceph_ansible.py [new file with mode: 0644]

diff --git a/teuthology/task/ceph_ansible.py b/teuthology/task/ceph_ansible.py
new file mode 100644 (file)
index 0000000..1da38ad
--- /dev/null
@@ -0,0 +1,96 @@
+import os
+
+from cStringIO import StringIO
+
+from . import ansible
+
+from ..config import config as teuth_config
+
+
+class CephAnsible(ansible.Ansible):
+    name = 'ceph_ansible'
+
+    _default_playbook = [
+        dict(
+            hosts='mons',
+            become=True,
+            roles=['ceph-mon'],
+        ),
+        dict(
+            hosts='osds',
+            become=True,
+            roles=['ceph-osd'],
+        ),
+        dict(
+            hosts='mdss',
+            become=True,
+            roles=['ceph-mds'],
+        ),
+        dict(
+            hosts='rgws',
+            become=True,
+            roles=['ceph-rgw'],
+        ),
+        dict(
+            hosts='restapis',
+            become=True,
+            roles=['ceph-restapi'],
+        ),
+    ]
+
+    __doc__ = """
+    A subclass of Ansible that defaults to:
+
+    - ansible:
+        repo: {git_base}ceph-ansible.git
+        playbook: {playbook}
+
+    It always uses a dynamic inventory.
+    """.format(
+        git_base=teuth_config.ceph_git_base_url,
+        playbook=_default_playbook,
+    )
+
+    def __init__(self, ctx, config):
+        config = config or dict()
+        if 'playbook' not in config:
+            config['playbook'] = self._default_playbook
+        if 'repo' not in config:
+            config['repo'] = os.path.join(teuth_config.ceph_git_base_url,
+                                          'ceph-ansible.git')
+        super(CephAnsible, self).__init__(ctx, config)
+
+    def get_inventory(self):
+        """
+        Stub this method so we always generate the hosts file
+        """
+        pass
+
+    def generate_hosts_file(self):
+        groups_to_roles = dict(
+            mons='mon',
+            mdss='mds',
+            osds='osd',
+        )
+        hosts_dict = dict()
+        for group in sorted(groups_to_roles.keys()):
+            role_prefix = groups_to_roles[group]
+            want = lambda role: role.startswith(role_prefix)
+            for (remote, roles) in self.cluster.only(want).remotes.iteritems():
+                hostname = remote.hostname
+                if group not in hosts_dict:
+                    hosts_dict[group] = [hostname]
+                elif hostname not in hosts_dict[group]:
+                    hosts_dict[group].append(hostname)
+
+        hosts_stringio = StringIO()
+        for group in sorted(hosts_dict.keys()):
+            hosts = hosts_dict[group]
+            hosts_stringio.write('[%s]\n' % group)
+            hosts_stringio.write('\n'.join(hosts))
+            hosts_stringio.write('\n\n')
+        hosts_stringio.seek(0)
+        self.inventory = self._write_hosts_file(hosts_stringio.read().strip())
+        self.generated_inventory = True
+
+task = CephAnsible
diff --git a/teuthology/test/task/test_ceph_ansible.py b/teuthology/test/task/test_ceph_ansible.py
new file mode 100644 (file)
index 0000000..253e116
--- /dev/null
@@ -0,0 +1,81 @@
+from mock import patch, MagicMock
+from pytest import skip
+from StringIO import StringIO
+
+from teuthology.config import FakeNamespace
+from teuthology.orchestra.cluster import Cluster
+from teuthology.orchestra.remote import Remote
+from teuthology.task import ansible
+from teuthology.task.ceph_ansible import CephAnsible
+
+from .test_ansible import TestAnsibleTask
+
+SKIP_IRRELEVANT = "Not relevant to this subclass"
+
+
+class TestCephAnsibleTask(TestAnsibleTask):
+    klass = CephAnsible
+    task_name = 'ceph_ansible'
+
+    def setup(self):
+        self.ctx = FakeNamespace()
+        self.ctx.cluster = Cluster()
+        self.ctx.cluster.add(Remote('user@remote1'), ['mon.0'])
+        self.ctx.cluster.add(Remote('user@remote2'), ['mds.0'])
+        self.ctx.cluster.add(Remote('user@remote3'), ['osd.0'])
+        self.ctx.config = dict()
+        self.task_config = dict()
+        self.start_patchers()
+
+    def start_patchers(self):
+        super(TestCephAnsibleTask, self).start_patchers()
+        m_fetch_repo = MagicMock()
+        m_fetch_repo.return_value = 'PATH'
+        self.patcher_fetch_repo = patch(
+            'teuthology.task.ceph_ansible.ansible.fetch_repo',
+            m_fetch_repo,
+        )
+        self.patcher_fetch_repo.start()
+
+    def stop_patchers(self):
+        super(TestCephAnsibleTask, self).stop_patchers()
+        self.patcher_fetch_repo.stop()
+
+    def test_playbook_none(self):
+        skip(SKIP_IRRELEVANT)
+
+    def test_inventory_none(self):
+        skip(SKIP_IRRELEVANT)
+
+    def test_inventory_path(self):
+        skip(SKIP_IRRELEVANT)
+
+    def test_inventory_etc(self):
+        skip(SKIP_IRRELEVANT)
+
+    def test_generate_hosts_file(self):
+        self.task_config.update(dict(
+            playbook=[]
+        ))
+        task = self.klass(self.ctx, self.task_config)
+        hosts_file_path = '/my/hosts/file'
+        hosts_file_obj = StringIO()
+        hosts_file_obj.name = hosts_file_path
+        with patch.object(ansible, 'NamedTemporaryFile') as m_NTF:
+            m_NTF.return_value = hosts_file_obj
+            task.generate_hosts_file()
+            m_NTF.assert_called_once_with(prefix="teuth_ansible_hosts_",
+                                          delete=False)
+        assert task.generated_inventory is True
+        assert task.inventory == hosts_file_path
+        hosts_file_obj.seek(0)
+        assert hosts_file_obj.read() == '\n'.join([
+            '[mdss]',
+            'remote2',
+            '',
+            '[mons]',
+            'remote1',
+            '',
+            '[osds]',
+            'remote3',
+        ])