]> git.proxmox.com Git - pve-cluster.git/blob - data/src/pmxcfs.c
imported from svn 'pve-cluster/trunk'
[pve-cluster.git] / data / src / pmxcfs.c
1 /*
2 Copyright (C) 2010 Proxmox Server Solutions GmbH
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Affero General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Affero General Public License for more details.
13
14 You should have received a copy of the GNU Affero General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 Author: Dietmar Maurer <dietmar@proxmox.com>
18
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif /* HAVE_CONFIG_H */
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <glib.h>
30 #include <syslog.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <sys/mount.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <sys/file.h>
37 #include <sys/types.h>
38 #include <dirent.h>
39 #include <sys/utsname.h>
40 #include <grp.h>
41 #include <netdb.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45
46 #include <qb/qbdefs.h>
47 #include <qb/qbutil.h>
48
49 #include "cfs-utils.h"
50 #include "cfs-plug.h"
51 #include "cfs-plug-memdb.h"
52 #include "status.h"
53 #include "dcdb.h"
54 #include "dfsm.h"
55 #include "quorum.h"
56 #include "confdb.h"
57 #include "server.h"
58
59 #define DBFILENAME VARLIBDIR "/config.db"
60 #define LOCKFILE VARLIBDIR "/.pmxcfs.lockfile"
61
62 #define CFSDIR "/etc/pve"
63
64 cfs_t cfs = {
65 .debug = 0,
66 .print_to_console = 1,
67 };
68
69 static struct fuse *fuse = NULL;
70
71 static cfs_plug_t *root_plug;
72
73 static void glib_print_handler(const gchar *string)
74 {
75 if (cfs.debug || cfs.print_to_console)
76 printf("%s", string);
77 }
78
79 static void glib_log_handler(const gchar *log_domain,
80 GLogLevelFlags log_level,
81 const gchar *message,
82 gpointer user_data)
83 {
84
85 cfs_log(log_domain, log_level, NULL, 0, NULL, message);
86 }
87
88 static gboolean write_pidfile(pid_t pid)
89 {
90 char *strpid = g_strdup_printf("%d\n", pid);
91 gboolean res = atomic_write_file(CFS_PID_FN, strpid, strlen(strpid), 0644, getgid());
92 g_free(strpid);
93
94 return res;
95 }
96
97 static cfs_plug_t *find_plug(const char *path, char **sub)
98 {
99 g_return_val_if_fail(root_plug != NULL, NULL);
100 g_return_val_if_fail(path != NULL, NULL);
101
102 while(*path == '/') path++;
103
104 cfs_debug("find_plug start %s", path);
105
106 char *tmppath = g_strdup(path);
107 char *subpath = tmppath;
108
109 cfs_plug_t *plug = root_plug->lookup_plug(root_plug, &subpath);
110
111 cfs_debug("find_plug end %s = %p (%s)", path, plug, subpath);
112
113 if (subpath && subpath[0])
114 *sub = g_strdup(subpath);
115
116 g_free(tmppath);
117
118 return plug;
119 }
120
121 void *cfs_fuse_init(struct fuse_conn_info *conn)
122 {
123 return NULL;
124 }
125
126 static int cfs_fuse_getattr(const char *path, struct stat *stbuf)
127 {
128 cfs_debug("enter cfs_fuse_getattr %s", path);
129
130 int ret = -EACCES;
131
132 char *subpath = NULL;
133 cfs_plug_t *plug = find_plug(path, &subpath);
134
135 if (plug && plug->ops && plug->ops->getattr) {
136 ret = plug->ops->getattr(plug, subpath ? subpath : "", stbuf);
137
138 stbuf->st_gid = cfs.gid;
139
140 stbuf->st_mode &= 0777750; // no access for other users
141
142 if (path_is_private(path))
143 stbuf->st_mode &= 0777700;
144 }
145
146 cfs_debug("leave cfs_fuse_getattr %s (%d)", path, ret);
147
148 if (subpath)
149 g_free(subpath);
150
151 return ret;
152
153 }
154
155 static int cfs_fuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
156 off_t offset, struct fuse_file_info *fi)
157 {
158 (void) offset;
159 (void) fi;
160
161 cfs_debug("enter cfs_fuse_readdir %s", path);
162
163 int ret = -EACCES;
164
165 char *subpath = NULL;
166 cfs_plug_t *plug = find_plug(path, &subpath);
167
168 if (!plug)
169 goto ret;
170
171 if (plug->ops && plug->ops->readdir)
172 ret = plug->ops->readdir(plug, subpath ? subpath : "", buf, filler, 0, fi);
173 ret:
174 cfs_debug("leave cfs_fuse_readdir %s (%d)", path, ret);
175
176 if (subpath)
177 g_free(subpath);
178
179 return ret;
180 }
181
182 static int cfs_fuse_mkdir(const char *path, mode_t mode)
183 {
184 cfs_debug("enter cfs_fuse_mkdir %s", path);
185
186 int ret = -EACCES;
187
188 char *subpath = NULL;
189 cfs_plug_t *plug = find_plug(path, &subpath);
190
191 if (!plug)
192 goto ret;
193
194 if (subpath && plug->ops && plug->ops->mkdir)
195 ret = plug->ops->mkdir(plug, subpath, mode);
196
197 ret:
198 cfs_debug("leave cfs_fuse_mkdir %s (%d)", path, ret);
199
200 if (subpath)
201 g_free(subpath);
202
203 return ret;
204 }
205
206 static int cfs_fuse_rmdir(const char *path)
207 {
208 cfs_debug("enter cfs_fuse_rmdir %s", path);
209
210 int ret = -EACCES;
211
212 char *subpath = NULL;
213 cfs_plug_t *plug = find_plug(path, &subpath);
214
215 if (!plug)
216 goto ret;
217
218 if (subpath && plug->ops && plug->ops->rmdir)
219 ret = plug->ops->rmdir(plug, subpath);
220
221 ret:
222 cfs_debug("leave cfs_fuse_rmdir %s (%d)", path, ret);
223
224 if (subpath)
225 g_free(subpath);
226
227 return ret;
228 }
229
230 static int cfs_fuse_rename(const char *from, const char *to)
231 {
232 cfs_debug("enter cfs_fuse_rename from %s to %s", from, to);
233
234 int ret = -EACCES;
235
236 char *sub_from = NULL;
237 cfs_plug_t *plug_from = find_plug(from, &sub_from);
238
239 char *sub_to = NULL;
240 cfs_plug_t *plug_to = find_plug(to, &sub_to);
241
242 if (!plug_from || !plug_to || plug_from != plug_to)
243 goto ret;
244
245 if (plug_from->ops && plug_from->ops->rename && sub_from && sub_to)
246 ret = plug_from->ops->rename(plug_from, sub_from, sub_to);
247
248 ret:
249 cfs_debug("leave cfs_fuse_rename from %s to %s (%d)", from, to, ret);
250
251 if (sub_from)
252 g_free(sub_from);
253
254 if (sub_to)
255 g_free(sub_to);
256
257 return ret;
258 }
259
260 static int cfs_fuse_open(const char *path, struct fuse_file_info *fi)
261 {
262 cfs_debug("enter cfs_fuse_open %s", path);
263
264 fi->direct_io = 1;
265 fi->keep_cache = 0;
266
267 int ret = -EACCES;
268
269 char *subpath = NULL;
270 cfs_plug_t *plug = find_plug(path, &subpath);
271
272 if (plug && plug->ops) {
273 if ((subpath || !plug->ops->readdir) && plug->ops->open) {
274 ret = plug->ops->open(plug, subpath ? subpath : "", fi);
275 }
276 }
277
278 cfs_debug("leave cfs_fuse_open %s (%d)", path, ret);
279
280 if (subpath)
281 g_free(subpath);
282
283 return ret;
284 }
285
286 static int cfs_fuse_read(const char *path, char *buf, size_t size, off_t offset,
287 struct fuse_file_info *fi)
288 {
289 (void) fi;
290
291 cfs_debug("enter cfs_fuse_read %s %lu %ld", path, size, offset);
292
293 int ret = -EACCES;
294
295 char *subpath = NULL;
296 cfs_plug_t *plug = find_plug(path, &subpath);
297
298 if (plug && plug->ops) {
299 if ((subpath || !plug->ops->readdir) && plug->ops->read)
300 ret = plug->ops->read(plug, subpath ? subpath : "", buf, size, offset, fi);
301 }
302
303 cfs_debug("leave cfs_fuse_read %s (%d)", path, ret);
304
305 if (subpath)
306 g_free(subpath);
307
308 return ret;
309 }
310
311 static int cfs_fuse_write(const char *path, const char *buf, size_t size,
312 off_t offset, struct fuse_file_info *fi)
313 {
314 (void) fi;
315
316 cfs_debug("enter cfs_fuse_write %s %lu %ld", path, size, offset);
317
318 int ret = -EACCES;
319
320 char *subpath = NULL;
321 cfs_plug_t *plug = find_plug(path, &subpath);
322
323 if (plug && plug->ops) {
324 if ((subpath || !plug->ops->readdir) && plug->ops->write)
325 ret = plug->ops->write(plug, subpath ? subpath : "",
326 buf, size, offset, fi);
327 }
328
329 cfs_debug("leave cfs_fuse_write %s (%d)", path, ret);
330
331 if (subpath)
332 g_free(subpath);
333
334 return ret;
335 }
336
337 static int cfs_fuse_truncate(const char *path, off_t size)
338 {
339 cfs_debug("enter cfs_fuse_truncate %s %ld", path, size);
340
341 int ret = -EACCES;
342
343 char *subpath = NULL;
344 cfs_plug_t *plug = find_plug(path, &subpath);
345
346 if (plug && plug->ops) {
347 if ((subpath || !plug->ops->readdir) && plug->ops->truncate)
348 ret = plug->ops->truncate(plug, subpath ? subpath : "", size);
349 }
350
351 cfs_debug("leave cfs_fuse_truncate %s (%d)", path, ret);
352
353 if (subpath)
354 g_free(subpath);
355
356 return ret;
357 }
358
359 static int cfs_fuse_create(const char *path, mode_t mode, struct fuse_file_info *fi)
360 {
361 cfs_debug("enter cfs_fuse_create %s", path);
362
363 int ret = -EACCES;
364
365 char *subpath = NULL;
366 cfs_plug_t *plug = find_plug(path, &subpath);
367
368 if (!plug)
369 goto ret;
370
371 if (subpath && plug->ops && plug->ops->create)
372 ret = plug->ops->create(plug, subpath, mode, fi);
373
374 ret:
375 cfs_debug("leave cfs_fuse_create %s (%d)", path, ret);
376
377 if (subpath)
378 g_free(subpath);
379
380 return ret;
381 }
382
383 static int cfs_fuse_unlink(const char *path)
384 {
385 cfs_debug("enter cfs_fuse_unlink %s", path);
386
387 int ret = -EACCES;
388
389 char *subpath = NULL;
390 cfs_plug_t *plug = find_plug(path, &subpath);
391
392 if (!plug)
393 goto ret;
394
395 if (subpath && plug->ops && plug->ops->unlink)
396 ret = plug->ops->unlink(plug, subpath);
397
398 ret:
399 cfs_debug("leave cfs_fuse_unlink %s (%d)", path, ret);
400
401 if (subpath)
402 g_free(subpath);
403
404 return ret;
405 }
406
407 static int cfs_fuse_readlink(const char *path, char *buf, size_t max)
408 {
409 cfs_debug("enter cfs_fuse_readlink %s", path);
410
411 int ret = -EACCES;
412
413 char *subpath = NULL;
414 cfs_plug_t *plug = find_plug(path, &subpath);
415
416 if (!plug)
417 goto ret;
418
419 if (plug->ops && plug->ops->readlink)
420 ret = plug->ops->readlink(plug, subpath ? subpath : "", buf, max);
421
422 ret:
423 cfs_debug("leave cfs_fuse_readlink %s (%d)", path, ret);
424
425 if (subpath)
426 g_free(subpath);
427
428 return ret;
429 }
430
431 static int cfs_fuse_utimens(const char *path, const struct timespec tv[2])
432 {
433 cfs_debug("enter cfs_fuse_utimens %s", path);
434
435 int ret = -EACCES;
436
437 char *subpath = NULL;
438 cfs_plug_t *plug = find_plug(path, &subpath);
439
440 if (!plug)
441 goto ret;
442
443 if (plug->ops && plug->ops->utimens)
444 ret = plug->ops->utimens(plug, subpath ? subpath : "", tv);
445
446 ret:
447 cfs_debug("leave cfs_fuse_utimens %s (%d)", path, ret);
448
449 if (subpath)
450 g_free(subpath);
451
452 return ret;
453 }
454
455 static int cfs_fuse_statfs(const char *path, struct statvfs *stbuf)
456 {
457 g_return_val_if_fail(root_plug != NULL, PARAM_CHECK_ERRNO);
458
459 cfs_debug("enter cfs_fuse_statfs %s", path);
460
461 int ret = -EACCES;
462
463 if (root_plug && root_plug->ops && root_plug->ops->statfs)
464 ret = root_plug->ops->statfs(root_plug, "", stbuf);
465
466 return ret;
467 }
468
469 static struct fuse_operations fuse_ops = {
470 .getattr = cfs_fuse_getattr,
471 .readdir = cfs_fuse_readdir,
472 .mkdir = cfs_fuse_mkdir,
473 .rmdir = cfs_fuse_rmdir,
474 .rename = cfs_fuse_rename,
475 .open = cfs_fuse_open,
476 .read = cfs_fuse_read,
477 .write = cfs_fuse_write,
478 .truncate = cfs_fuse_truncate,
479 .create = cfs_fuse_create,
480 .unlink = cfs_fuse_unlink,
481 .readlink = cfs_fuse_readlink,
482 .utimens = cfs_fuse_utimens,
483 .statfs = cfs_fuse_statfs,
484 .init = cfs_fuse_init
485 };
486
487 static char *
488 create_dot_version_cb(cfs_plug_t *plug)
489 {
490 GString *outbuf = g_string_new(NULL);
491 char *data = NULL;
492
493 if (cfs_create_version_msg(outbuf) == 0) {
494 data = outbuf->str;
495 g_string_free(outbuf, FALSE);
496 } else {
497 g_string_free(outbuf, TRUE);
498 }
499
500 return data;
501 }
502
503 static char *
504 create_dot_members_cb(cfs_plug_t *plug)
505 {
506 GString *outbuf = g_string_new(NULL);
507 char *data = NULL;
508
509 if (cfs_create_memberlist_msg(outbuf) == 0) {
510 data = outbuf->str;
511 g_string_free(outbuf, FALSE);
512 } else {
513 g_string_free(outbuf, TRUE);
514 }
515
516 return data;
517 }
518
519 static char *
520 create_dot_vmlist_cb(cfs_plug_t *plug)
521 {
522 GString *outbuf = g_string_new(NULL);
523 char *data = NULL;
524
525 if (cfs_create_vmlist_msg(outbuf) == 0) {
526 data = outbuf->str;
527 g_string_free(outbuf, FALSE);
528 } else {
529 g_string_free(outbuf, TRUE);
530 }
531
532 return data;
533 }
534
535 static char *
536 create_dot_rrd_cb(cfs_plug_t *plug)
537 {
538 GString *outbuf = g_string_new(NULL);
539
540 cfs_rrd_dump(outbuf);
541 char *data = outbuf->str;
542 g_string_free(outbuf, FALSE);
543
544 return data;
545 }
546
547 static char *
548 create_dot_clusterlog_cb(cfs_plug_t *plug)
549 {
550 GString *outbuf = g_string_new(NULL);
551
552 cfs_cluster_log_dump(outbuf, NULL, 50);
553 char *data = outbuf->str;
554 g_string_free(outbuf, FALSE);
555
556 return data;
557 }
558
559 static char *
560 read_debug_setting_cb(cfs_plug_t *plug)
561 {
562 return g_strdup_printf("%d\n", !!cfs.debug);
563 }
564
565 static int write_debug_setting_cb(
566 cfs_plug_t *plug,
567 const char *buf,
568 size_t size)
569 {
570 int res = -EIO;
571
572 if (size < 2)
573 return res;
574
575 if (strncmp(buf, "0\n", 2) == 0) {
576 if (cfs.debug) {
577 cfs_message("disable debug mode");
578 cfs.debug = 0;
579 }
580 return 2;
581 } else if (strncmp(buf, "1\n", 2) == 0) {
582 if (!cfs.debug) {
583 cfs_message("enable debug mode");
584 cfs.debug = 1;
585 }
586 return 2;
587 }
588
589 return res;
590 }
591
592
593 static void
594 create_symlinks(cfs_plug_base_t *bplug, const char *nodename)
595 {
596 g_return_if_fail(bplug != NULL);
597 g_return_if_fail(nodename != NULL);
598
599 char *lnktarget = g_strdup_printf("nodes/%s", nodename);
600 cfs_plug_link_t *lnk = cfs_plug_link_new("local", lnktarget);
601 g_free(lnktarget);
602 cfs_plug_base_insert(bplug, (cfs_plug_t*)lnk);
603
604 lnktarget = g_strdup_printf("nodes/%s/qemu-server", nodename);
605 lnk = cfs_plug_link_new("qemu-server", lnktarget);
606 g_free(lnktarget);
607 cfs_plug_base_insert(bplug, (cfs_plug_t*)lnk);
608
609 lnktarget = g_strdup_printf("nodes/%s/openvz", nodename);
610 lnk = cfs_plug_link_new("openvz", lnktarget);
611 g_free(lnktarget);
612 cfs_plug_base_insert(bplug, (cfs_plug_t*)lnk);
613
614 cfs_plug_func_t *fplug = cfs_plug_func_new(".version", 0440, create_dot_version_cb, NULL);
615 cfs_plug_base_insert(bplug, (cfs_plug_t*)fplug);
616
617 fplug = cfs_plug_func_new(".members", 0440, create_dot_members_cb, NULL);
618 cfs_plug_base_insert(bplug, (cfs_plug_t*)fplug);
619
620 fplug = cfs_plug_func_new(".vmlist", 0440, create_dot_vmlist_cb, NULL);
621 cfs_plug_base_insert(bplug, (cfs_plug_t*)fplug);
622
623 fplug = cfs_plug_func_new(".rrd", 0440, create_dot_rrd_cb, NULL);
624 cfs_plug_base_insert(bplug, (cfs_plug_t*)fplug);
625
626 fplug = cfs_plug_func_new(".clusterlog", 0440, create_dot_clusterlog_cb, NULL);
627 cfs_plug_base_insert(bplug, (cfs_plug_t*)fplug);
628
629 fplug = cfs_plug_func_new(".debug", 0640, read_debug_setting_cb, write_debug_setting_cb);
630 cfs_plug_base_insert(bplug, (cfs_plug_t*)fplug);
631
632
633 }
634
635 static char *
636 lookup_node_ip(const char *nodename)
637 {
638 struct addrinfo *ainfo;
639 struct addrinfo ahints;
640 memset(&ahints, 0, sizeof(ahints));
641
642 if (getaddrinfo(nodename, NULL, &ahints, &ainfo))
643 return NULL;
644
645 if (ainfo->ai_family == AF_INET) {
646 char buf[INET6_ADDRSTRLEN];
647 struct sockaddr_in *sa = (struct sockaddr_in *)ainfo->ai_addr;
648 inet_ntop(ainfo->ai_family, &sa->sin_addr, buf, sizeof(buf));
649 if (strncmp(buf, "127.", 4) != 0) {
650 return g_strdup(buf);
651 }
652 }
653
654 // ipv6 support ?
655
656 return NULL;
657 }
658 int main(int argc, char *argv[])
659 {
660 int ret = -1;
661 int lockfd = -1;
662
663 gboolean foreground = FALSE;
664 gboolean force_local_mode = FALSE;
665 gboolean wrote_pidfile = FALSE;
666 memdb_t *memdb = NULL;
667 dfsm_t *dcdb = NULL;
668 dfsm_t *status_fsm = NULL;
669
670 openlog("pmxcfs", LOG_PID, LOG_DAEMON);
671
672 g_set_print_handler(glib_print_handler);
673 g_set_printerr_handler(glib_print_handler);
674 g_log_set_default_handler(glib_log_handler, NULL);
675
676 GOptionContext *context;
677 gboolean opt_quiet = FALSE;
678
679 GOptionEntry entries[] = {
680 { "debug", 'd', 0, G_OPTION_ARG_NONE, &cfs.debug, "Turn on debug messages", NULL },
681 { "foreground", 'f', 0, G_OPTION_ARG_NONE, &foreground, "Do not daemonize server", NULL },
682 { "local", 'l', 0, G_OPTION_ARG_NONE, &force_local_mode,
683 "Force local mode (ignore cluster.conf, force quorum)", NULL },
684 { "quiet", 'q', 0, G_OPTION_ARG_NONE, &opt_quiet, "Supress console output", NULL },
685 { NULL },
686 };
687
688 context = g_option_context_new ("");
689 g_option_context_add_main_entries (context, entries, NULL);
690
691 GError *err = NULL;
692 if (!g_option_context_parse (context, &argc, &argv, &err))
693 {
694 cfs_critical("option parsing failed: %s", err->message);
695 g_error_free (err);
696 exit (1);
697 }
698 g_option_context_free(context);
699
700 if (optind < argc) {
701 cfs_critical("too many arguments");
702 exit(-1);
703 }
704
705 if (opt_quiet)
706 cfs.print_to_console = 0;
707
708 struct utsname utsname;
709 if (uname(&utsname) != 0) {
710 cfs_critical("Unable to read local node name");
711 exit (-1);
712 }
713
714 for (int i=0; i < sizeof(utsname.nodename); i++) {
715 if (utsname.nodename[i] =='.') utsname.nodename[i] = 0;
716 }
717
718 cfs.nodename = g_strdup(utsname.nodename);
719
720 if (!(cfs.ip = lookup_node_ip(cfs.nodename))) {
721 cfs_critical("Unable to get local IP address");
722 exit(-1);
723 }
724
725 struct group *www_data = getgrnam("www-data");
726 if (!www_data) {
727 cfs_critical("Unable to get www-data group ID");
728 exit (-1);
729 }
730 cfs.gid = www_data->gr_gid;
731
732 g_thread_init(NULL);
733
734 qb_util_set_log_function(ipc_log_fn);
735
736 umask(027);
737
738 mkdir(VARLIBDIR, 0755);
739
740 if ((lockfd = open(LOCKFILE, O_RDWR|O_CREAT|O_APPEND)) == -1) {
741 cfs_critical("unable to create lock '%s': %s", LOCKFILE, strerror (errno));
742 goto err;
743 }
744
745 for (int i = 10; i >= 0; i--) {
746 if (flock(lockfd, LOCK_EX|LOCK_NB) != 0) {
747 if (!i) {
748 cfs_critical("unable to aquire pmxcfs lock: %s", strerror (errno));
749 goto err;
750 }
751 if (i == 10)
752 cfs_message("unable to aquire pmxcfs lock - trying again");
753
754 sleep(1);
755 }
756 }
757
758 cfs_status_init();
759
760 gboolean create = !g_file_test(DBFILENAME, G_FILE_TEST_EXISTS);
761
762 if (!(memdb = memdb_open (DBFILENAME))) {
763 cfs_critical("memdb_open failed - unable to open database '%s'", DBFILENAME);
764 goto err;
765 }
766
767 // automatically import cluster.conf from host
768 if (create && !force_local_mode) {
769 char *cdata = NULL;
770 gsize clen = 0;
771 if (g_file_get_contents(HOST_CLUSTER_CONF_FN, &cdata, &clen, NULL)) {
772
773 guint32 mtime = time(NULL);
774
775 memdb_create(memdb, "/cluster.conf", 0, mtime);
776 if (memdb_write(memdb, "/cluster.conf", 0, mtime, cdata, clen, 0, 1) < 0) {
777 cfs_critical("memdb_write failed - unable to import cluster.conf");
778 goto err;
779 }
780 }
781 }
782
783 // does cluster.conf exist?
784 gpointer conf_data = NULL;
785 int len = memdb_read(memdb, "cluster.conf", &conf_data);
786 if (len >= 0) {
787 if (force_local_mode) {
788 cfs_message("forcing local mode (althought cluster.conf exists)");
789 cfs_set_quorate(1, TRUE);
790 } else {
791 if (!(dcdb = dcdb_new(memdb)))
792 goto err;
793 dcdb_sync_cluster_conf(memdb, 1);
794 }
795 } else {
796 cfs_debug("using local mode (cluster.conf does not exist)");
797 cfs_set_quorate(1, TRUE);
798 }
799 if (conf_data) g_free(conf_data);
800
801 cfs_plug_memdb_t *config = cfs_plug_memdb_new("memdb", memdb, dcdb);
802
803 cfs_plug_base_t *bplug = cfs_plug_base_new("", (cfs_plug_t *)config);
804
805 create_symlinks(bplug, cfs.nodename);
806
807 root_plug = (cfs_plug_t *)bplug;
808
809 system("umount -f " CFSDIR " >/dev/null 2>&1");
810
811 char *fa[] = { "-f", "-odefault_permissions", "-oallow_other", NULL};
812
813 struct fuse_args fuse_args = FUSE_ARGS_INIT(sizeof (fa)/sizeof(gpointer) - 1, fa);
814
815 struct fuse_chan *fuse_chan = fuse_mount(CFSDIR, &fuse_args);
816 if (!fuse_chan) {
817 cfs_critical("fuse_mount error: %s", strerror(errno));
818 goto err;
819 }
820
821 if (!(fuse = fuse_new(fuse_chan, &fuse_args, &fuse_ops, sizeof(fuse_ops), NULL))) {
822 cfs_critical("fuse_new error: %s", strerror(errno));
823 goto err;
824 }
825
826 fuse_set_signal_handlers(fuse_get_session(fuse));
827
828 cfs_message("starting proxmox configuration filesystem (node = %s)",
829 cfs.nodename);
830
831 if (!foreground) {
832 pid_t cpid = fork();
833
834 if (cpid == -1) {
835 cfs_critical("failed to daemonize program - %s", strerror (errno));
836 goto err;
837 } else if (cpid) {
838 write_pidfile(cpid);
839 _exit (0);
840 } else {
841 int nullfd;
842
843 chroot("/");
844
845 if ((nullfd = open("/dev/null", O_RDWR, 0)) != -1) {
846 dup2(nullfd, 0);
847 dup2(nullfd, 1);
848 dup2(nullfd, 2);
849 if (nullfd > 2)
850 close (nullfd);
851 }
852
853 // do not print to the console after this point
854 cfs.print_to_console = 0;
855 setsid();
856 }
857 } else {
858 write_pidfile(getpid());
859 }
860
861 wrote_pidfile = TRUE;
862
863 cfs_loop_t *corosync_loop = cfs_loop_new(fuse);
864
865 cfs_service_t *service_quorum = NULL;
866 cfs_service_t *service_confdb = NULL;
867 cfs_service_t *service_dcdb = NULL;
868 cfs_service_t *service_status = NULL;
869
870 if (dcdb) {
871
872 service_quorum = service_quorum_new();
873
874 cfs_loop_add_service(corosync_loop, service_quorum, QB_LOOP_HIGH);
875
876 service_confdb = service_confdb_new();
877
878 cfs_loop_add_service(corosync_loop, service_confdb, QB_LOOP_MED);
879
880 service_dcdb = service_dfsm_new(dcdb);
881 cfs_service_set_timer(service_dcdb, DCDB_VERIFY_TIME);
882
883 cfs_loop_add_service(corosync_loop, service_dcdb, QB_LOOP_MED);
884
885 status_fsm = cfs_status_dfsm_new();
886 service_status = service_dfsm_new(status_fsm);
887
888 cfs_loop_add_service(corosync_loop, service_status, QB_LOOP_LOW);
889
890 }
891
892 cfs_loop_start_worker(corosync_loop);
893
894 server_start(memdb);
895
896 ret = fuse_loop_mt(fuse);
897
898 cfs_message("teardown filesystem");
899
900 server_stop();
901
902 fuse_unmount(CFSDIR, fuse_chan);
903
904 fuse_destroy(fuse);
905
906 cfs_debug("set stop event loop flag");
907
908 cfs_loop_stop_worker(corosync_loop);
909
910 cfs_loop_destroy(corosync_loop);
911
912 cfs_debug("worker finished");
913
914 if (service_dcdb)
915 service_dfsm_destroy(service_dcdb);
916
917 if (service_confdb)
918 service_confdb_destroy(service_confdb);
919
920 if (service_quorum)
921 service_quorum_destroy(service_quorum);
922
923 if (service_status)
924 service_dfsm_destroy(service_status);
925
926 sleep(1); /* do not restart too fast */
927 ret:
928
929 if (status_fsm)
930 dfsm_destroy(status_fsm);
931
932 if (dcdb)
933 dfsm_destroy(dcdb);
934
935 if (memdb)
936 memdb_close(memdb);
937
938 if (wrote_pidfile)
939 unlink(CFS_PID_FN);
940
941 cfs_message("exit proxmox configuration filesystem (%d)", ret);
942
943 cfs_status_cleanup();
944
945 exit(ret);
946
947 err:
948 goto ret;
949 }