kolla-ansible/ansible/library/kolla_ceph_keyring.py
Jeffrey Zhang 20c5e8fe13 Update ceph client.admin caps during upgrade
When upgrade from ceph Jewel to ceph luminous, the client.admin caps
should add `mgr 'allow *'` caps

Change-Id: Ia4cb7a59d4cf215a1dce1efe31e00f1401e0b753
Closes-Bug: #1750967
2018-03-30 08:07:18 +00:00

154 lines
4.6 KiB
Python

#!/usr/bin/env python
# Copyright 2018 99cloud
#
# 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 json
import subprocess # nosec
DOCUMENTATION = '''
---
module: kolla_ceph_keyring
short_description: >
Module for update ceph client keyring caps in kolla.
description:
- A module used to update ceph client keyring caps in kolla.
options:
name:
description:
- the client name in ceph
required: True
type: str
container_name:
description:
- the ceph mon container name
required: True
default: ceph_mon
type: str
caps:
description:
- the ceph auth caps
required: True
type: dict
author: Jeffrey Zhang
'''
EXAMPLES = '''
- name: configure admin client caps
kolla_ceph_keyring:
name: client.admin
container_name: ceph_mon
caps:
mds: 'allow'
mon: 'allow *'
osd: 'allow *'
mgr: 'allow *'
'''
class CephKeyring(object):
def __init__(self, name, caps, container_name='ceph_mon'):
self.name = name
self.caps = caps
self.container_name = container_name
self.changed = False
self.message = None
def _run(self, cmd):
_prefix = ['docker', 'exec', self.container_name]
cmd = _prefix + cmd
proc = subprocess.Popen(cmd, # nosec
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
retcode = proc.poll()
if retcode != 0:
output = 'stdout: "%s", stderr: "%s"' % (stdout, stderr)
raise subprocess.CalledProcessError(retcode, cmd, output)
return stdout
def _format_caps(self):
caps = []
for obj in sorted(self.caps):
caps.extend([obj, self.caps[obj]])
return caps
def parse_stdout(self, stdout):
keyring = json.loads(stdout)
# there should be only one element
return keyring[0]
def ensure_keyring(self):
try:
stdout = self.get_keyring()
except subprocess.CalledProcessError:
# keyring doesn't exsit, try to create it
stdout = self.create_keyring()
self.changed = True
self.message = 'ceph keyring for %s is created' % self.name
keyring = self.parse_stdout(stdout)
if keyring['caps'] != self.caps:
self.update_caps()
stdout = self.get_keyring()
keyring = self.parse_stdout(stdout)
self.changed = True
self.message = 'ceph keyring for %s is updated' % self.name
self.keyring = keyring
return self.keyring
def get_keyring(self):
ceph_cmd = ['ceph', '--format', 'json', 'auth', 'get', self.name]
return self._run(ceph_cmd)
def update_caps(self):
ceph_cmd = ['ceph', '--format', 'json', 'auth', 'caps', self.name]
caps = self._format_caps()
ceph_cmd.extend(caps)
self._run(ceph_cmd)
def create_keyring(self):
ceph_cmd = ['ceph', '--format', 'json', 'auth',
'get-or-create', self.name]
caps = self._format_caps()
ceph_cmd.extend(caps)
return self._run(ceph_cmd)
def main():
specs = dict(
name=dict(type='str', required=True),
container_name=dict(type='str', default='ceph_mon'),
caps=dict(type='dict', required=True)
)
module = AnsibleModule(argument_spec=specs) # noqa
params = module.params
ceph_keyring = CephKeyring(params['name'],
params['caps'],
params['container_name'])
try:
keyring = ceph_keyring.ensure_keyring()
module.exit_json(changed=ceph_keyring.changed,
keyring=keyring,
message=ceph_keyring.message)
except subprocess.CalledProcessError as ex:
msg = ('Failed to call command: %s returncode: %s output: %s' %
(ex.cmd, ex.returncode, ex.output))
module.fail_json(msg=msg)
from ansible.module_utils.basic import * # noqa
if __name__ == "__main__":
main()