geo-rep: mountbroker user management
Non root geo-replication setup is now simplified. This patch provides cli for mountbroker user and options management To set Options, gluster system:: execute mountbroker opt <KEY> <VALUE> # for example, gluster system:: execute mountbroker opt mountbroker-root /var/mountbroker-root gluster system:: execute mountbroker opt geo-replication-log-group geogroup gluster system:: execute mountbroker opt rpc-auth-allow-insecure on To remove option, gluster system:: execute mountbroker optdel <KEY> # for example, gluster system:: execute mountbroker optdel geo-replication-log-group To add/edit user, gluster system:: execute mountbroker user <USERNAME> <VOLUMES> # for example gluster system:: execute mountbroker user geoaccount slavevol1,slavevol2 To remove user, gluster system:: execute mountbroker userdel <USERNAME> # for example gluster system:: execute mountbroker userdel geoaccount For info, gluster system:: execute mountbroker info gluster system:: execute mountbroker -j info For JSON output add -j after mountbroker, for example, gluster system:: execute mountbroker -j user geoaccount slavevol1,slavevol2 PS: Each peer prints its own JSON output, aggregator required from consumer side BUG: 1136312 Change-Id: Ie52210c0bcc91ac2ffd3ba58988222ffca62b47f Signed-off-by: Aravinda VK <avishwan@redhat.com> Reviewed-on: http://review.gluster.org/9398 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: darshan n <dnarayan@redhat.com> Reviewed-by: Kotresh HR <khiremat@redhat.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
This commit is contained in:
parent
fb6858b475
commit
79009691c0
1
.gitignore
vendored
1
.gitignore
vendored
@ -59,6 +59,7 @@ geo-replication/src/gsyncd
|
|||||||
geo-replication/src/gsyncd
|
geo-replication/src/gsyncd
|
||||||
geo-replication/src/peer_add_secret_pub
|
geo-replication/src/peer_add_secret_pub
|
||||||
geo-replication/src/peer_gsec_create
|
geo-replication/src/peer_gsec_create
|
||||||
|
geo-replication/src/peer_mountbroker
|
||||||
geo-replication/src/set_geo_rep_pem_keys.sh
|
geo-replication/src/set_geo_rep_pem_keys.sh
|
||||||
geo-replication/syncdaemon.egg-info
|
geo-replication/syncdaemon.egg-info
|
||||||
geo-replication/syncdaemon/configinterface.py
|
geo-replication/syncdaemon/configinterface.py
|
||||||
|
10
configure.ac
10
configure.ac
@ -40,6 +40,7 @@ AC_CONFIG_FILES([Makefile
|
|||||||
libglusterfs/src/Makefile
|
libglusterfs/src/Makefile
|
||||||
geo-replication/src/peer_gsec_create
|
geo-replication/src/peer_gsec_create
|
||||||
geo-replication/src/peer_add_secret_pub
|
geo-replication/src/peer_add_secret_pub
|
||||||
|
geo-replication/src/peer_mountbroker
|
||||||
geo-replication/syncdaemon/configinterface.py
|
geo-replication/syncdaemon/configinterface.py
|
||||||
glusterfsd/Makefile
|
glusterfsd/Makefile
|
||||||
glusterfsd/src/Makefile
|
glusterfsd/src/Makefile
|
||||||
@ -887,6 +888,14 @@ else
|
|||||||
LOCALSTATEDIR=$(eval echo ${localstatedir})
|
LOCALSTATEDIR=$(eval echo ${localstatedir})
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
old_prefix=$prefix
|
||||||
|
if test "x$prefix" = xNONE; then
|
||||||
|
prefix=$ac_default_prefix
|
||||||
|
fi
|
||||||
|
GLUSTERD_VOLFILE="$(eval echo ${sysconfdir})/glusterfs/glusterd.vol"
|
||||||
|
prefix=$old_prefix
|
||||||
|
|
||||||
|
|
||||||
case $host_os in
|
case $host_os in
|
||||||
linux*)
|
linux*)
|
||||||
GF_HOST_OS="GF_LINUX_HOST_OS"
|
GF_HOST_OS="GF_LINUX_HOST_OS"
|
||||||
@ -1175,6 +1184,7 @@ AM_CONDITIONAL([GF_BSD_HOST_OS], test "${GF_HOST_OS}" = "GF_BSD_HOST_OS")
|
|||||||
|
|
||||||
AC_SUBST(GLUSTERD_WORKDIR)
|
AC_SUBST(GLUSTERD_WORKDIR)
|
||||||
AM_CONDITIONAL([GF_INSTALL_GLUSTERD_WORKDIR], test ! -d ${GLUSTERD_WORKDIR} && test -d ${sysconfdir}/glusterd )
|
AM_CONDITIONAL([GF_INSTALL_GLUSTERD_WORKDIR], test ! -d ${GLUSTERD_WORKDIR} && test -d ${sysconfdir}/glusterd )
|
||||||
|
AC_SUBST(GLUSTERD_VOLFILE)
|
||||||
|
|
||||||
dnl pkg-config versioning
|
dnl pkg-config versioning
|
||||||
dnl
|
dnl
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
gsyncddir = $(libexecdir)/glusterfs
|
gsyncddir = $(libexecdir)/glusterfs
|
||||||
|
|
||||||
gsyncd_SCRIPTS = gverify.sh peer_add_secret_pub peer_gsec_create set_geo_rep_pem_keys.sh
|
gsyncd_SCRIPTS = gverify.sh peer_add_secret_pub peer_gsec_create \
|
||||||
|
set_geo_rep_pem_keys.sh peer_mountbroker
|
||||||
|
|
||||||
# peer_gsec_create and peer_add_secret_pub are not added to
|
# peer_gsec_create and peer_add_secret_pub are not added to
|
||||||
# EXTRA_DIST as it's derived from a .in file
|
# EXTRA_DIST as it's derived from a .in file
|
||||||
|
177
geo-replication/src/peer_mountbroker
Normal file
177
geo-replication/src/peer_mountbroker
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import os
|
||||||
|
from argparse import ArgumentParser, RawDescriptionHelpFormatter
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
PROG_DESCRIPTION = """
|
||||||
|
GlusterFS Mountbroker user management
|
||||||
|
"""
|
||||||
|
|
||||||
|
args = None
|
||||||
|
|
||||||
|
|
||||||
|
def ok(message=""):
|
||||||
|
if (not args and "-j" in sys.argv) or (args and args.json):
|
||||||
|
print json.dumps({"ok": True, "message": message})
|
||||||
|
else:
|
||||||
|
if message:
|
||||||
|
print message
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def notok(message=""):
|
||||||
|
if (not args and "-j" in sys.argv) or (args and args.json):
|
||||||
|
print json.dumps({"ok": False, "message": message})
|
||||||
|
else:
|
||||||
|
print "error: %s" % message
|
||||||
|
|
||||||
|
# Always return zero due to limitation while executing
|
||||||
|
# as `gluster system:: execute`
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
class NoStdErrParser(ArgumentParser):
|
||||||
|
"""
|
||||||
|
with gluster system:: execute, stderr gives
|
||||||
|
"Unable to end. Error : Bad file descriptor" error,
|
||||||
|
so deriving new class, prints error message and
|
||||||
|
exits with zero.
|
||||||
|
"""
|
||||||
|
def error(self, message):
|
||||||
|
notok(message)
|
||||||
|
|
||||||
|
|
||||||
|
class MountbrokerUserMgmt(object):
|
||||||
|
def __init__(self, volfile):
|
||||||
|
self.volfile = volfile
|
||||||
|
self._options = {}
|
||||||
|
self.commented_lines = []
|
||||||
|
self._parse()
|
||||||
|
|
||||||
|
def _parse(self):
|
||||||
|
with open(self.volfile, "r") as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith("option "):
|
||||||
|
key, value = line.split(" ")[1:]
|
||||||
|
self._options[key] = value
|
||||||
|
if line.startswith("#"):
|
||||||
|
self.commented_lines.append(line)
|
||||||
|
|
||||||
|
def _get_write_data(self):
|
||||||
|
op = "volume management\n"
|
||||||
|
op += " type mgmt/glusterd\n"
|
||||||
|
for k, v in self._options.iteritems():
|
||||||
|
op += " option %s %s\n" % (k, v)
|
||||||
|
for line in self.commented_lines:
|
||||||
|
op += " %s\n" % line
|
||||||
|
op += "end-volume"
|
||||||
|
return op
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
with open(self.volfile + "_tmp", "w") as f:
|
||||||
|
f.write(self._get_write_data())
|
||||||
|
f.flush()
|
||||||
|
os.fsync(f.fileno())
|
||||||
|
os.rename(self.volfile + "_tmp", self.volfile)
|
||||||
|
|
||||||
|
def set_opt(self, key, value):
|
||||||
|
self._options[key] = value.strip()
|
||||||
|
|
||||||
|
def remove_opt(self, key):
|
||||||
|
if key in self._options:
|
||||||
|
del(self._options[key])
|
||||||
|
|
||||||
|
def add_user(self, user, volumes):
|
||||||
|
self.set_opt("mountbroker-geo-replication.%s" % user,
|
||||||
|
",".join(volumes))
|
||||||
|
|
||||||
|
def remove_user(self, user):
|
||||||
|
self.remove_opt("mountbroker-geo-replication.%s" % user)
|
||||||
|
|
||||||
|
def info(self):
|
||||||
|
data = {"users": []}
|
||||||
|
|
||||||
|
for k, v in self._options.iteritems():
|
||||||
|
if k.startswith("mountbroker-geo-replication."):
|
||||||
|
data["users"].append(
|
||||||
|
{"name": k.split(".")[-1], "volumes": v.split(",")}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
data[k] = v
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def format_info(data):
|
||||||
|
op = "%s %s\n" % ("Option".ljust(50), "Value".ljust(50))
|
||||||
|
op += ("-" * 101) + "\n"
|
||||||
|
for key, value in data.iteritems():
|
||||||
|
if key != "users":
|
||||||
|
op += "%s %s\n" % (key.ljust(50), value)
|
||||||
|
|
||||||
|
op += "\nUsers: %s\n" % ("None" if not data["users"] else "")
|
||||||
|
for user in data["users"]:
|
||||||
|
op += "%s: %s\n" % (user["name"], ", ".join(user["volumes"]))
|
||||||
|
op += "\n\n"
|
||||||
|
return op
|
||||||
|
|
||||||
|
|
||||||
|
def _get_args():
|
||||||
|
parser = NoStdErrParser(formatter_class=RawDescriptionHelpFormatter,
|
||||||
|
description=PROG_DESCRIPTION)
|
||||||
|
|
||||||
|
parser.add_argument('-j', dest="json", help="JSON output",
|
||||||
|
action="store_true")
|
||||||
|
subparsers = parser.add_subparsers(title='subcommands', dest='cmd')
|
||||||
|
parser_useradd = subparsers.add_parser('user')
|
||||||
|
parser_userdel = subparsers.add_parser('userdel')
|
||||||
|
subparsers.add_parser('info')
|
||||||
|
parser_opt = subparsers.add_parser('opt')
|
||||||
|
parser_optdel = subparsers.add_parser('optdel')
|
||||||
|
|
||||||
|
parser_useradd.add_argument('username', help="Username", type=str)
|
||||||
|
parser_useradd.add_argument('volumes', type=str, default='',
|
||||||
|
help="Volumes list. ',' seperated")
|
||||||
|
|
||||||
|
parser_userdel.add_argument('username', help="Username", type=str)
|
||||||
|
|
||||||
|
parser_opt.add_argument('opt_name', help="Name", type=str)
|
||||||
|
parser_opt.add_argument('opt_value', help="Value", type=str)
|
||||||
|
|
||||||
|
parser_optdel.add_argument('opt_name', help="Name", type=str)
|
||||||
|
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global args
|
||||||
|
args = _get_args()
|
||||||
|
|
||||||
|
m = MountbrokerUserMgmt("/etc/glusterfs/glusterd.vol")
|
||||||
|
|
||||||
|
if args.cmd == "opt":
|
||||||
|
m.set_opt(args.opt_name, args.opt_value)
|
||||||
|
elif args.cmd == "optdel":
|
||||||
|
m.remove_opt(args.opt_name)
|
||||||
|
elif args.cmd == "userdel":
|
||||||
|
m.remove_user(args.username)
|
||||||
|
elif args.cmd == "user":
|
||||||
|
volumes = [v.strip() for v in args.volumes.split(",")
|
||||||
|
if v.strip() != ""]
|
||||||
|
m.add_user(args.username, volumes)
|
||||||
|
elif args.cmd == "info":
|
||||||
|
info = m.info()
|
||||||
|
if not args.json:
|
||||||
|
info = format_info(info)
|
||||||
|
ok(info)
|
||||||
|
|
||||||
|
if args.cmd != "info":
|
||||||
|
m.save()
|
||||||
|
ok()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
177
geo-replication/src/peer_mountbroker.in
Normal file
177
geo-replication/src/peer_mountbroker.in
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import os
|
||||||
|
from argparse import ArgumentParser, RawDescriptionHelpFormatter
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
PROG_DESCRIPTION = """
|
||||||
|
GlusterFS Mountbroker user management
|
||||||
|
"""
|
||||||
|
|
||||||
|
args = None
|
||||||
|
|
||||||
|
|
||||||
|
def ok(message=""):
|
||||||
|
if (not args and "-j" in sys.argv) or (args and args.json):
|
||||||
|
print json.dumps({"ok": True, "message": message})
|
||||||
|
else:
|
||||||
|
if message:
|
||||||
|
print message
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def notok(message=""):
|
||||||
|
if (not args and "-j" in sys.argv) or (args and args.json):
|
||||||
|
print json.dumps({"ok": False, "message": message})
|
||||||
|
else:
|
||||||
|
print "error: %s" % message
|
||||||
|
|
||||||
|
# Always return zero due to limitation while executing
|
||||||
|
# as `gluster system:: execute`
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
class NoStdErrParser(ArgumentParser):
|
||||||
|
"""
|
||||||
|
with gluster system:: execute, stderr gives
|
||||||
|
"Unable to end. Error : Bad file descriptor" error,
|
||||||
|
so deriving new class, prints error message and
|
||||||
|
exits with zero.
|
||||||
|
"""
|
||||||
|
def error(self, message):
|
||||||
|
notok(message)
|
||||||
|
|
||||||
|
|
||||||
|
class MountbrokerUserMgmt(object):
|
||||||
|
def __init__(self, volfile):
|
||||||
|
self.volfile = volfile
|
||||||
|
self._options = {}
|
||||||
|
self.commented_lines = []
|
||||||
|
self._parse()
|
||||||
|
|
||||||
|
def _parse(self):
|
||||||
|
with open(self.volfile, "r") as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith("option "):
|
||||||
|
key, value = line.split(" ")[1:]
|
||||||
|
self._options[key] = value
|
||||||
|
if line.startswith("#"):
|
||||||
|
self.commented_lines.append(line)
|
||||||
|
|
||||||
|
def _get_write_data(self):
|
||||||
|
op = "volume management\n"
|
||||||
|
op += " type mgmt/glusterd\n"
|
||||||
|
for k, v in self._options.iteritems():
|
||||||
|
op += " option %s %s\n" % (k, v)
|
||||||
|
for line in self.commented_lines:
|
||||||
|
op += " %s\n" % line
|
||||||
|
op += "end-volume"
|
||||||
|
return op
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
with open(self.volfile + "_tmp", "w") as f:
|
||||||
|
f.write(self._get_write_data())
|
||||||
|
f.flush()
|
||||||
|
os.fsync(f.fileno())
|
||||||
|
os.rename(self.volfile + "_tmp", self.volfile)
|
||||||
|
|
||||||
|
def set_opt(self, key, value):
|
||||||
|
self._options[key] = value.strip()
|
||||||
|
|
||||||
|
def remove_opt(self, key):
|
||||||
|
if key in self._options:
|
||||||
|
del(self._options[key])
|
||||||
|
|
||||||
|
def add_user(self, user, volumes):
|
||||||
|
self.set_opt("mountbroker-geo-replication.%s" % user,
|
||||||
|
",".join(volumes))
|
||||||
|
|
||||||
|
def remove_user(self, user):
|
||||||
|
self.remove_opt("mountbroker-geo-replication.%s" % user)
|
||||||
|
|
||||||
|
def info(self):
|
||||||
|
data = {"users": []}
|
||||||
|
|
||||||
|
for k, v in self._options.iteritems():
|
||||||
|
if k.startswith("mountbroker-geo-replication."):
|
||||||
|
data["users"].append(
|
||||||
|
{"name": k.split(".")[-1], "volumes": v.split(",")}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
data[k] = v
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def format_info(data):
|
||||||
|
op = "%s %s\n" % ("Option".ljust(50), "Value".ljust(50))
|
||||||
|
op += ("-" * 101) + "\n"
|
||||||
|
for key, value in data.iteritems():
|
||||||
|
if key != "users":
|
||||||
|
op += "%s %s\n" % (key.ljust(50), value)
|
||||||
|
|
||||||
|
op += "\nUsers: %s\n" % ("None" if not data["users"] else "")
|
||||||
|
for user in data["users"]:
|
||||||
|
op += "%s: %s\n" % (user["name"], ", ".join(user["volumes"]))
|
||||||
|
op += "\n\n"
|
||||||
|
return op
|
||||||
|
|
||||||
|
|
||||||
|
def _get_args():
|
||||||
|
parser = NoStdErrParser(formatter_class=RawDescriptionHelpFormatter,
|
||||||
|
description=PROG_DESCRIPTION)
|
||||||
|
|
||||||
|
parser.add_argument('-j', dest="json", help="JSON output",
|
||||||
|
action="store_true")
|
||||||
|
subparsers = parser.add_subparsers(title='subcommands', dest='cmd')
|
||||||
|
parser_useradd = subparsers.add_parser('user')
|
||||||
|
parser_userdel = subparsers.add_parser('userdel')
|
||||||
|
subparsers.add_parser('info')
|
||||||
|
parser_opt = subparsers.add_parser('opt')
|
||||||
|
parser_optdel = subparsers.add_parser('optdel')
|
||||||
|
|
||||||
|
parser_useradd.add_argument('username', help="Username", type=str)
|
||||||
|
parser_useradd.add_argument('volumes', type=str, default='',
|
||||||
|
help="Volumes list. ',' seperated")
|
||||||
|
|
||||||
|
parser_userdel.add_argument('username', help="Username", type=str)
|
||||||
|
|
||||||
|
parser_opt.add_argument('opt_name', help="Name", type=str)
|
||||||
|
parser_opt.add_argument('opt_value', help="Value", type=str)
|
||||||
|
|
||||||
|
parser_optdel.add_argument('opt_name', help="Name", type=str)
|
||||||
|
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global args
|
||||||
|
args = _get_args()
|
||||||
|
|
||||||
|
m = MountbrokerUserMgmt("@GLUSTERD_VOLFILE@")
|
||||||
|
|
||||||
|
if args.cmd == "opt":
|
||||||
|
m.set_opt(args.opt_name, args.opt_value)
|
||||||
|
elif args.cmd == "optdel":
|
||||||
|
m.remove_opt(args.opt_name)
|
||||||
|
elif args.cmd == "userdel":
|
||||||
|
m.remove_user(args.username)
|
||||||
|
elif args.cmd == "user":
|
||||||
|
volumes = [v.strip() for v in args.volumes.split(",")
|
||||||
|
if v.strip() != ""]
|
||||||
|
m.add_user(args.username, volumes)
|
||||||
|
elif args.cmd == "info":
|
||||||
|
info = m.info()
|
||||||
|
if not args.json:
|
||||||
|
info = format_info(info)
|
||||||
|
ok(info)
|
||||||
|
|
||||||
|
if args.cmd != "info":
|
||||||
|
m.save()
|
||||||
|
ok()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -943,6 +943,7 @@ fi
|
|||||||
%{_libexecdir}/glusterfs/set_geo_rep_pem_keys.sh
|
%{_libexecdir}/glusterfs/set_geo_rep_pem_keys.sh
|
||||||
%{_libexecdir}/glusterfs/peer_add_secret_pub
|
%{_libexecdir}/glusterfs/peer_add_secret_pub
|
||||||
%{_libexecdir}/glusterfs/peer_gsec_create
|
%{_libexecdir}/glusterfs/peer_gsec_create
|
||||||
|
%{_libexecdir}/glusterfs/peer_mountbroker
|
||||||
%ghost %dir %attr(0755,-,-) %{_sharedstatedir}/glusterd/geo-replication
|
%ghost %dir %attr(0755,-,-) %{_sharedstatedir}/glusterd/geo-replication
|
||||||
%dir %{_sharedstatedir}/glusterd/hooks
|
%dir %{_sharedstatedir}/glusterd/hooks
|
||||||
%dir %{_sharedstatedir}/glusterd/hooks/1
|
%dir %{_sharedstatedir}/glusterd/hooks/1
|
||||||
@ -1078,6 +1079,9 @@ fi
|
|||||||
* Fri Jan 16 2015 Niels de Vos <ndevos@redhat.com>
|
* Fri Jan 16 2015 Niels de Vos <ndevos@redhat.com>
|
||||||
- add support for /run/gluster through a tmpfiles.d config file (#1182934)
|
- add support for /run/gluster through a tmpfiles.d config file (#1182934)
|
||||||
|
|
||||||
|
* Tue Jan 6 2015 Aravinda VK<avishwan@redhat.com>
|
||||||
|
- Added new libexec script for mountbroker user management (peer_mountbroker)
|
||||||
|
|
||||||
* Fri Dec 12 2014 Niels de Vos <ndevos@redhat.com>
|
* Fri Dec 12 2014 Niels de Vos <ndevos@redhat.com>
|
||||||
- do not package all /usr/share/glusterfs/* files in regression-tests (#1169005)
|
- do not package all /usr/share/glusterfs/* files in regression-tests (#1169005)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user