glusterfs

Форк
0
/
peer_mountbroker.py.in 
401 строка · 12.6 Кб
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-secondaries"
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-secondaries
147
    # chgrp -R <grp> /var/lib/glusterd/geo-replication
148
    # chmod -R 770 /var/log/glusterfs/geo-replication-secondaries
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-secondaries
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()
402

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.