"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/geo-replication/src/peer_mountbroker.py.in" (16 Sep 2020, 12833 Bytes) of package /linux/misc/glusterfs-8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 #!/usr/bin/python3
    2 
    3 from __future__ import print_function
    4 
    5 import os
    6 from errno import EEXIST, ENOENT
    7 
    8 from gluster.cliutils import (execute, Cmd, node_output_ok,
    9                               node_output_notok, execute_in_peers,
   10                               runcli, oknotok)
   11 from prettytable import PrettyTable
   12 
   13 LOG_DIR = "@localstatedir@/log/glusterfs/geo-replication-slaves"
   14 CLI_LOG = "@localstatedir@/log/glusterfs/cli.log"
   15 GEOREP_DIR = "@GLUSTERD_WORKDIR@/geo-replication"
   16 GLUSTERD_VOLFILE = "@GLUSTERD_VOLFILE@"
   17 
   18 
   19 class MountbrokerUserMgmt(object):
   20     def __init__(self, volfile):
   21         self.volfile = volfile
   22         self._options = {}
   23         self.commented_lines = []
   24         self.user_volumes = {}
   25         self._parse()
   26 
   27     def _parse(self):
   28         """ Example glusterd.vol
   29         volume management
   30             type mgmt/glusterd
   31             option working-directory /var/lib/glusterd
   32             option transport-type socket,rdma
   33             option transport.socket.keepalive-time 10
   34             option transport.socket.keepalive-interval 2
   35             option transport.socket.read-fail-log off
   36             option rpc-auth-allow-insecure on
   37             option ping-timeout 0
   38             option event-threads 1
   39             # option base-port 49152
   40             option mountbroker-root /var/mountbroker-root
   41             option mountbroker-geo-replication.user1 vol1,vol2,vol3
   42             option geo-replication-log-group geogroup
   43             option rpc-auth-allow-insecure on
   44         end-volume
   45         """
   46         with open(self.volfile, "r") as f:
   47             for line in f:
   48                 line = line.strip()
   49                 if line.startswith("option "):
   50                     key, value = line.split()[1:]
   51                     self._options[key] = value
   52                 if line.startswith("#"):
   53                     self.commented_lines.append(line)
   54 
   55         for k, v in self._options.items():
   56             if k.startswith("mountbroker-geo-replication."):
   57                 user = k.split(".")[-1]
   58                 self.user_volumes[user] = set(v.split(","))
   59 
   60     def get_group(self):
   61         return self._options.get("geo-replication-log-group", None)
   62 
   63     def _get_write_data(self):
   64         op = "volume management\n"
   65         op += "    type mgmt/glusterd\n"
   66         for k, v in self._options.items():
   67             if k.startswith("mountbroker-geo-replication."):
   68                 # Users will be added seperately
   69                 continue
   70 
   71             op += "    option %s %s\n" % (k, v)
   72 
   73         for k, v in self.user_volumes.items():
   74             if v:
   75                 op += ("    option mountbroker-geo-replication."
   76                        "%s %s\n" % (k, ",".join(v)))
   77 
   78         for line in self.commented_lines:
   79             op += "    %s\n" % line
   80 
   81         op += "end-volume"
   82         return op
   83 
   84     def save(self):
   85         with open(self.volfile + "_tmp", "w") as f:
   86             f.write(self._get_write_data())
   87             f.flush()
   88             os.fsync(f.fileno())
   89         os.rename(self.volfile + "_tmp", self.volfile)
   90 
   91     def set_mount_root_and_group(self, mnt_root, group):
   92         self._options["mountbroker-root"] = mnt_root
   93         self._options["geo-replication-log-group"] = group
   94 
   95     def add(self, volume, user):
   96         user_volumes = self.user_volumes.get(user, None)
   97 
   98         if user_volumes is not None and volume in user_volumes:
   99             # User and Volume already exists
  100             return
  101 
  102         if user_volumes is None:
  103             # User not exists
  104             self.user_volumes[user] = set()
  105 
  106         self.user_volumes[user].add(volume)
  107 
  108     def remove(self, volume=None, user=None):
  109         if user is not None:
  110             if volume is None:
  111                 self.user_volumes[user] = set()
  112             else:
  113                 try:
  114                     self.user_volumes.get(user, set()).remove(volume)
  115                 except KeyError:
  116                     pass
  117         else:
  118             if volume is None:
  119                 return
  120 
  121             for k, v in self.user_volumes.items():
  122                 try:
  123                     self.user_volumes[k].remove(volume)
  124                 except KeyError:
  125                     pass
  126 
  127     def info(self):
  128         # Convert Volumes set into Volumes list
  129         users = {}
  130         for k, v in self.user_volumes.items():
  131             users[k] = list(v)
  132 
  133         data = {
  134             "mountbroker-root": self._options.get("mountbroker-root", "None"),
  135             "geo-replication-log-group": self._options.get(
  136                 "geo-replication-log-group", ""),
  137             "users": users
  138         }
  139 
  140         return data
  141 
  142 
  143 class NodeSetup(Cmd):
  144     # Test if group exists using `getent group <grp>`
  145     # and then group add using `groupadd <grp>`
  146     # chgrp -R <grp> /var/log/glusterfs/geo-replication-slaves
  147     # chgrp -R <grp> /var/lib/glusterd/geo-replication
  148     # chmod -R 770 /var/log/glusterfs/geo-replication-slaves
  149     # chmod 770 /var/lib/glusterd/geo-replication
  150     # mkdir -p <mnt_root>
  151     # chmod 0711 <mnt_root>
  152     # If selinux,
  153     # semanage fcontext -a -e /home /var/mountbroker-root
  154     # restorecon -Rv /var/mountbroker-root
  155     name = "node-setup"
  156 
  157     def args(self, parser):
  158         parser.add_argument("mount_root")
  159         parser.add_argument("group")
  160 
  161     def run(self, args):
  162         m = MountbrokerUserMgmt(GLUSTERD_VOLFILE)
  163 
  164         try:
  165             os.makedirs(args.mount_root)
  166         except OSError as e:
  167             if e.errno == EEXIST:
  168                 pass
  169             else:
  170                 node_output_notok("Unable to Create {0}".format(
  171                     args.mount_root))
  172 
  173         execute(["chmod", "0711", args.mount_root])
  174         try:
  175             execute(["semanage", "fcontext", "-a", "-e",
  176                      "/home", args.mount_root])
  177         except OSError as e:
  178             if e.errno == ENOENT:
  179                 pass
  180             else:
  181                 node_output_notok(
  182                     "Unable to run semanage: {0}".format(e))
  183 
  184         try:
  185             execute(["restorecon", "-Rv", args.mount_root])
  186         except OSError as e:
  187             if e.errno == ENOENT:
  188                 pass
  189             else:
  190                 node_output_notok(
  191                     "Unable to run restorecon: {0}".format(e))
  192 
  193         rc, out, err = execute(["getent", "group", args.group])
  194         if rc != 0:
  195             node_output_notok("User Group not exists")
  196 
  197         execute(["chgrp", "-R", args.group, GEOREP_DIR])
  198         execute(["chgrp", "-R", args.group, LOG_DIR])
  199         execute(["chgrp", args.group, CLI_LOG])
  200         execute(["chmod", "770", GEOREP_DIR])
  201         execute(["find", LOG_DIR, "-type", "d", "-exec", "chmod", "770", "{}",
  202                  "+"])
  203         execute(["find", LOG_DIR, "-type", "f", "-exec", "chmod", "660", "{}",
  204                  "+"])
  205         execute(["chmod", "660", CLI_LOG])
  206 
  207         m.set_mount_root_and_group(args.mount_root, args.group)
  208         m.save()
  209 
  210         node_output_ok()
  211 
  212 
  213 def color_status(value):
  214     if value.lower() in ("up", "ok", "yes"):
  215         return "green"
  216     else:
  217         return "red"
  218 
  219 
  220 class CliSetup(Cmd):
  221     # gluster-mountbroker setup <MOUNT_ROOT> <GROUP>
  222     name = "setup"
  223 
  224     def args(self, parser):
  225         parser.add_argument("mount_root",
  226                             help="Path to the mountbroker-root directory.")
  227         parser.add_argument("group",
  228                             help="Group to be used for setup.")
  229 
  230     def run(self, args):
  231         out = execute_in_peers("node-setup", [args.mount_root,
  232                                               args.group])
  233         table = PrettyTable(["NODE", "NODE STATUS", "SETUP STATUS"])
  234         table.align["NODE STATUS"] = "r"
  235         table.align["SETUP STATUS"] = "r"
  236         for p in out:
  237             table.add_row([p.hostname,
  238                            "UP" if p.node_up else "DOWN",
  239                            "OK" if p.ok else "NOT OK: {0}".format(
  240                                p.error)])
  241 
  242         print(table)
  243 
  244 
  245 class NodeStatus(Cmd):
  246     # Check if Group exists
  247     # Check if user exists
  248     # Check directory permission /var/log/glusterfs/geo-replication-slaves
  249     # and /var/lib/glusterd/geo-replication
  250     # Check mount root and its permissions
  251     # Check glusterd.vol file for user, group, dir existance
  252     name = "node-status"
  253 
  254     def run(self, args):
  255         m = MountbrokerUserMgmt(GLUSTERD_VOLFILE)
  256         data = m.info()
  257         data["group_exists"] = False
  258         data["path_exists"] = False
  259 
  260         rc, out, err = execute(["getent", "group",
  261                                 data["geo-replication-log-group"]])
  262 
  263         if rc == 0:
  264             data["group_exists"] = True
  265 
  266         if os.path.exists(data["mountbroker-root"]):
  267             data["path_exists"] = True
  268 
  269         node_output_ok(data)
  270 
  271 
  272 class CliStatus(Cmd):
  273     # gluster-mountbroker status
  274     name = "status"
  275 
  276     def run(self, args):
  277         out = execute_in_peers("node-status")
  278         table = PrettyTable(["NODE", "NODE STATUS", "MOUNT ROOT",
  279                              "GROUP", "USERS"])
  280         table.align["NODE STATUS"] = "r"
  281 
  282         for p in out:
  283             node_data = p.output
  284             if node_data == "" or node_data == "N/A":
  285                 node_data = {}
  286 
  287             users_row_data = ""
  288             for k, v in node_data.get("users", {}).items():
  289                 users_row_data += "{0}({1}) ".format(k, ", ".join(v))
  290 
  291             if not users_row_data:
  292                 users_row_data = "None"
  293 
  294             mount_root = node_data.get("mountbroker-root", "None")
  295             if mount_root != "None":
  296                 mount_root += "({0})".format(oknotok(
  297                     node_data.get("path_exists", False)))
  298 
  299             grp = node_data.get("geo-replication-log-group", "None")
  300             if grp != "None":
  301                 grp += "({0})".format(oknotok(
  302                     node_data.get("group_exists", False)))
  303 
  304             table.add_row([p.hostname,
  305                            "UP" if p.node_up else "DOWN",
  306                            mount_root,
  307                            grp,
  308                            users_row_data])
  309 
  310         print(table)
  311 
  312 
  313 class NodeAdd(Cmd):
  314     # useradd -m -g <grp> <usr>
  315     # useradd to glusterd.vol
  316     name = "node-add"
  317 
  318     def args(self, parser):
  319         parser.add_argument("volume")
  320         parser.add_argument("user")
  321 
  322     def run(self, args):
  323         m = MountbrokerUserMgmt(GLUSTERD_VOLFILE)
  324         grp = m.get_group()
  325         if grp is None:
  326             node_output_notok("Group is not available")
  327 
  328         m.add(args.volume, args.user)
  329         m.save()
  330         node_output_ok()
  331 
  332 
  333 class CliAdd(Cmd):
  334     # gluster-mountbroker add <VOLUME> <USER>
  335     name = "add"
  336 
  337     def args(self, parser):
  338         parser.add_argument("volume",
  339                             help="Volume to be added.")
  340         parser.add_argument("user",
  341                             help="User for which volume is to be added.")
  342 
  343     def run(self, args):
  344         out = execute_in_peers("node-add", [args.volume,
  345                                             args.user])
  346         table = PrettyTable(["NODE", "NODE STATUS", "ADD STATUS"])
  347         table.align["NODE STATUS"] = "r"
  348         table.align["ADD STATUS"] = "r"
  349 
  350         for p in out:
  351             table.add_row([p.hostname,
  352                            "UP" if p.node_up else "DOWN",
  353                            "OK" if p.ok else "NOT OK: {0}".format(
  354                                p.error)])
  355 
  356         print(table)
  357 
  358 
  359 class NodeRemove(Cmd):
  360     # userremove from glusterd.vol file
  361     name = "node-remove"
  362 
  363     def args(self, parser):
  364         parser.add_argument("volume")
  365         parser.add_argument("user")
  366 
  367     def run(self, args):
  368         m = MountbrokerUserMgmt(GLUSTERD_VOLFILE)
  369         volume = None if args.volume == "." else args.volume
  370         user = None if args.user == "." else args.user
  371         m.remove(volume=volume, user=user)
  372         m.save()
  373         node_output_ok()
  374 
  375 
  376 class CliRemove(Cmd):
  377     # gluster-mountbroker remove --volume <VOLUME> --user <USER>
  378     name = "remove"
  379 
  380     def args(self, parser):
  381         parser.add_argument("--volume", default=".", help="Volume to be removed.")
  382         parser.add_argument("--user", default=".",
  383                             help="User for which volume has to be removed.")
  384 
  385     def run(self, args):
  386         out = execute_in_peers("node-remove", [args.volume,
  387                                                args.user])
  388         table = PrettyTable(["NODE", "NODE STATUS", "REMOVE STATUS"])
  389         table.align["NODE STATUS"] = "r"
  390         table.align["REMOVE STATUS"] = "r"
  391 
  392         for p in out:
  393             table.add_row([p.hostname,
  394                            "UP" if p.node_up else "DOWN",
  395                            "OK" if p.ok else "NOT OK: {0}".format(
  396                                p.error)])
  397 
  398         print(table)
  399 
  400 if __name__ == "__main__":
  401     runcli()