add reload nonce, and fix up some setup bits

This commit is contained in:
Chris MacNaughton 2022-01-05 16:07:36 -06:00
parent d968d6ec88
commit c9817a4b17
5 changed files with 59 additions and 27 deletions

View File

@ -1,16 +1,10 @@
# Copyright 2021 OpenStack Charmers
# Copyright 2022 Canonical
# See LICENSE file for licensing details.
#
# TEMPLATE-TODO: change this example to suit your needs.
# If you don't need actions, you can remove the file entirely.
# It ties in to the example _on_fortune_action handler in src/charm.py
#
# Learn more about actions at: https://juju.is/docs/sdk/actions
# fortune:
# description: Returns a pithy phrase.
# params:
# fail:
# description: "Fail with this message"
# type: string
# default: ""
create-share:
description: Create a new CephFS Backed NFS export
params:
allowed-ips:
description: IP Addresses to grant Read/Write access to
type: string
default: "0.0.0.0"

View File

@ -17,6 +17,7 @@ import os
from pathlib import Path
import socket
import subprocess
import tempfile
from ops.framework import StoredState
from ops.main import main
@ -174,6 +175,9 @@ class CephNfsCharm(
self.framework.observe(
self.peers.on.pool_initialised,
self.on_pool_initialised)
self.framework.observe(
self.peers.on.reload_nonce,
self.on_reload_nonce)
def config_get(self, key, default=None):
"""Retrieve config option.
@ -264,7 +268,7 @@ class CephNfsCharm(
if not self._stored.is_cluster_setup:
subprocess.check_call([
'ganesha-rados-grace', '--userid', self.client_name,
'--cephconf', '/etc/ceph/ganesha/ceph.conf', '--pool', self.pool_name,
'--cephconf', self.CEPH_CONF, '--pool', self.pool_name,
'add', socket.gethostname()])
self._stored.is_cluster_setup = True
@ -273,11 +277,21 @@ class CephNfsCharm(
return
cmd = [
'rados', '-p', self.pool_name,
'-c', '/etc/ceph/ganesha/ceph.conf',
'-c', self.CEPH_CONF,
'--id', self.client_name,
'put', 'ganesha-export-index', '/dev/null'
]
try:
subprocess.check_call(cmd)
counter = tempfile.NamedTemporaryFile('w+')
counter.write('1000')
counter.seek(0)
cmd = [
'rados', '-p', self.pool_name,
'-c', self.CEPH_CONF,
'--id', self.client_name,
'put', 'ganesha-export-counter', counter.name
]
subprocess.check_call(cmd)
self.peers.pool_initialised()
except subprocess.CalledProcessError:
@ -291,6 +305,10 @@ class CephNfsCharm(
logging.error("Failed torestart nfs-ganesha")
event.defer()
def on_reload_nonce(self, _event):
logging.info("Reloading Ganesha after nonce triggered reload")
subprocess.call(['killall', '-HUP', 'ganesha.nfsd'])
@ops_openstack.core.charm_class
class CephNFSCharmOcto(CephNfsCharm):

View File

@ -34,7 +34,7 @@ GANESHA_EXPORT_TEMPLATE = """EXPORT {{
SecType = "sys";
CLIENT {{
Access_Type = "rw";
Clients = {clients}
Clients = {clients};
}}
# User id squashing, one of None, Root, All
Squash = "None";
@ -64,10 +64,12 @@ class GaneshaNfs(object):
secret_key=self._ceph_auth_key(),
clients='0.0.0.0'
)
logging.debug("Export template:: \n{}".format(export_template))
logging.debug("Export template::\n{}".format(export_template))
tmp_file = self._tmpfile(export_template)
self.rados_put('ganesha-export-{}'.format(export_id), tmp_file.name)
self._rados_put('ganesha-export-{}'.format(export_id), tmp_file.name)
self._ganesha_add_export(self.export_path, tmp_file.name)
self._add_share_to_index(export_id)
return self.export_path
def _ganesha_add_export(self, export_path, tmp_path):
"""Add a configured NFS export to Ganesha"""
@ -131,7 +133,7 @@ class GaneshaNfs(object):
def _ceph_command(self, *cmd):
"""Run a ceph command"""
cmd = ["ceph", "--id", self.client_name, "--conf=/etc/ceph/ganesha/ceph.conf"] + [*cmd]
cmd = ["ceph", "--id", self.client_name, "--conf=/etc/ceph/ceph.conf"] + [*cmd]
return subprocess.check_output(cmd)
def _get_next_export_id(self):
@ -140,9 +142,9 @@ class GaneshaNfs(object):
:returns: The export ID
:rtype: str
"""
next_id = int(self.rados_get(self.export_counter))
next_id = int(self._rados_get(self.export_counter))
file = self._tmpfile(next_id + 1)
self.rados_put(self.export_counter, file.name)
self._rados_put(self.export_counter, file.name)
return next_id
def _tmpfile(self, value):
@ -151,7 +153,7 @@ class GaneshaNfs(object):
file.seek(0)
return file
def rados_get(self, name):
def _rados_get(self, name):
"""Retrieve the content of the RADOS object with a given name
:param name: Name of the RADOS object to retrieve
@ -167,7 +169,7 @@ class GaneshaNfs(object):
output = subprocess.check_output(cmd)
return output.decode('utf-8')
def rados_put(self, name, source):
def _rados_put(self, name, source):
"""Store the contents of the source file in a named RADOS object.
:param name: Name of the RADOS object to retrieve
@ -181,3 +183,9 @@ class GaneshaNfs(object):
]
logging.debug("About to call: {}".format(cmd))
subprocess.check_call(cmd)
def _add_share_to_index(self, export_id):
index = self._rados_get(self.export_index)
index += '%url rados://{}/ganesha-export-{}'.format(self.ceph_pool, export_id)
tmpfile = self._tmpfile(index)
self._rados_put(self.export_index, tmpfile.name)

View File

@ -3,6 +3,7 @@
# import json
import logging
# import socket
import uuid
from ops.framework import (
StoredState,
@ -15,9 +16,12 @@ from ops.framework import (
class PoolInitialisedEvent(EventBase):
pass
class ReloadNonceEvent(EventBase):
pass
class CephNfsPeerEvents(ObjectEvents):
pool_initialised = EventSource(PoolInitialisedEvent)
reload_nonce = EventSource(ReloadNonceEvent)
class CephNfsPeers(Object):
@ -30,7 +34,8 @@ class CephNfsPeers(Object):
self.relation_name = relation_name
self.this_unit = self.framework.model.unit
self._stored.set_default(
pool_initialised=False)
pool_initialised=False,
reload_nonce=None)
self.framework.observe(
charm.on[relation_name].relation_changed,
self.on_changed)
@ -40,12 +45,19 @@ class CephNfsPeers(Object):
if self.pool_initialised == 'True' and not self._stored.pool_initialised:
self.on.pool_initialised.emit()
self._stored.pool_initialised = True
if self._stored.reload_nonce != self.reload_nonce():
self.on.reload_nonce.emit()
self._stored.reload_nonce = self.reload_nonce()
def pool_initialised(self):
logging.info("Setting pool initialised")
self.peer_rel.data[self.peer_rel.app]['pool_initialised'] = 'True'
self.on.pool_initialised.emit()
def trigger_reload(self):
self.peer_rel.data[self.peer_rel.app]['reload_nonce'] = uuid.uuid4()
self.on.reload_nonce.emit()
@property
def peer_rel(self):
return self.framework.model.get_relation(self.relation_name)

View File

@ -68,7 +68,7 @@ MDCACHE {
# To read exports from RADOS objects
RADOS_URLS {
ceph_conf = "/etc/ceph/ganesha/ceph.conf";
ceph_conf = "/etc/ceph/ceph.conf";
userid = "{{ ceph_nfs.client_name }}";
}
@ -76,7 +76,7 @@ RADOS_URLS {
# To store client recovery data in the same RADOS pool
RADOS_KV {
ceph_conf = "/etc/ceph/ganesha/ceph.conf";
ceph_conf = "/etc/ceph/ceph.conf";
userid = "{{ ceph_nfs.client_name }}";
pool = "{{ ceph_nfs.pool_name }}";
nodeid = "{{ ceph_nfs.hostname }}";