1 #include <config.h>
2 
3 #include "viralloc.h"
4 #include "virerror.h"
5 #include "virfile.h"
6 #include "storage_backend_vstorage.h"
7 #include "virlog.h"
8 #include "virstring.h"
9 #include "virutil.h"
10 #include <mntent.h>
11 #include <paths.h>
12 #include <pwd.h>
13 #include <grp.h>
14 #include <unistd.h>
15 #include "storage_util.h"
16 
17 #define VIR_FROM_THIS VIR_FROM_STORAGE
18 
19 VIR_LOG_INIT("storage.storage_backend_vstorage");
20 
21 
22 /**
23  * @pool storage pool to build
24  * @flags controls the pool formatting behaviour
25  *
26  * Does not support @flags, if provided an error will occur.
27  *
28  * Returns 0 on success, -1 on error
29  */
30 static int
virStorageBackendVzPoolBuild(virStoragePoolObj * pool,unsigned int flags)31 virStorageBackendVzPoolBuild(virStoragePoolObj *pool,
32                              unsigned int flags)
33 {
34     virCheckFlags(0, -1);
35 
36     return virStorageBackendBuildLocal(pool);
37 }
38 
39 
40 static int
virStorageBackendVzPoolStart(virStoragePoolObj * pool)41 virStorageBackendVzPoolStart(virStoragePoolObj *pool)
42 {
43     virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
44     g_autofree char *grp_name = NULL;
45     g_autofree char *usr_name = NULL;
46     g_autofree char *mode = NULL;
47     g_autoptr(virCommand) cmd = NULL;
48     int ret;
49 
50     /* Check the permissions */
51     if (def->target.perms.mode == (mode_t)-1)
52         def->target.perms.mode = VIR_STORAGE_DEFAULT_POOL_PERM_MODE;
53     if (def->target.perms.uid == (uid_t)-1)
54         def->target.perms.uid = geteuid();
55     if (def->target.perms.gid == (gid_t)-1)
56         def->target.perms.gid = getegid();
57 
58     /* Convert ids to names because vstorage uses names */
59 
60     if (!(grp_name = virGetGroupName(def->target.perms.gid)))
61         return -1;
62 
63     if (!(usr_name = virGetUserName(def->target.perms.uid)))
64         return -1;
65 
66     mode = g_strdup_printf("%o", def->target.perms.mode);
67 
68     cmd = virCommandNewArgList("vstorage-mount",
69                                "-c", def->source.name,
70                                def->target.path,
71                                "-m", mode,
72                                "-g", grp_name, "-u", usr_name,
73                                NULL);
74 
75     /* Mounting a shared FS might take a long time. Don't hold
76      * the pool locked meanwhile. */
77     virObjectUnlock(pool);
78     ret = virCommandRun(cmd, NULL);
79     virObjectLock(pool);
80 
81     return ret;
82 }
83 
84 
85 static int
virStorageBackendVzIsMounted(virStoragePoolObj * pool)86 virStorageBackendVzIsMounted(virStoragePoolObj *pool)
87 {
88     int ret = -1;
89     virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
90     FILE *mtab;
91     struct mntent ent;
92     char buf[1024];
93     g_autofree char *cluster = NULL;
94 
95     cluster = g_strdup_printf("vstorage://%s", def->source.name);
96 
97     if ((mtab = fopen(_PATH_MOUNTED, "r")) == NULL) {
98         virReportSystemError(errno,
99                              _("cannot read mount list '%s'"),
100                              _PATH_MOUNTED);
101         goto cleanup;
102     }
103 
104     while ((getmntent_r(mtab, &ent, buf, sizeof(buf))) != NULL) {
105 
106         if (STREQ(ent.mnt_dir, def->target.path) &&
107             STREQ(ent.mnt_fsname, cluster)) {
108             ret = 1;
109             goto cleanup;
110         }
111     }
112 
113     ret = 0;
114 
115  cleanup:
116     VIR_FORCE_FCLOSE(mtab);
117     return ret;
118 }
119 
120 
121 static int
virStorageBackendVzPoolStop(virStoragePoolObj * pool)122 virStorageBackendVzPoolStop(virStoragePoolObj *pool)
123 {
124     virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
125     int rc;
126     g_autoptr(virCommand) cmd = NULL;
127 
128     /* Short-circuit if already unmounted */
129     if ((rc = virStorageBackendVzIsMounted(pool)) != 1)
130         return rc;
131 
132     cmd = virCommandNewArgList("umount", def->target.path, NULL);
133     return virCommandRun(cmd, NULL);
134 }
135 
136 
137 /*
138  * Check whether the cluster is mounted
139  */
140 static int
virStorageBackendVzCheck(virStoragePoolObj * pool,bool * isActive)141 virStorageBackendVzCheck(virStoragePoolObj *pool,
142                          bool *isActive)
143 {
144     int ret = -1;
145     *isActive = false;
146     if ((ret = virStorageBackendVzIsMounted(pool)) != 0) {
147         if (ret < 0)
148             return -1;
149         *isActive = true;
150     }
151 
152     return 0;
153 }
154 
155 
156 virStorageBackend virStorageBackendVstorage = {
157     .type = VIR_STORAGE_POOL_VSTORAGE,
158 
159     .buildPool = virStorageBackendVzPoolBuild,
160     .startPool = virStorageBackendVzPoolStart,
161     .stopPool = virStorageBackendVzPoolStop,
162     .deletePool = virStorageBackendDeleteLocal,
163     .refreshPool = virStorageBackendRefreshLocal,
164     .checkPool = virStorageBackendVzCheck,
165     .buildVol = virStorageBackendVolBuildLocal,
166     .buildVolFrom = virStorageBackendVolBuildFromLocal,
167     .createVol = virStorageBackendVolCreateLocal,
168     .refreshVol = virStorageBackendVolRefreshLocal,
169     .deleteVol = virStorageBackendVolDeleteLocal,
170     .resizeVol = virStorageBackendVolResizeLocal,
171     .uploadVol = virStorageBackendVolUploadLocal,
172     .downloadVol = virStorageBackendVolDownloadLocal,
173     .wipeVol = virStorageBackendVolWipeLocal,
174 };
175 
176 
177 int
virStorageBackendVstorageRegister(void)178 virStorageBackendVstorageRegister(void)
179 {
180     return virStorageBackendRegister(&virStorageBackendVstorage);
181 }
182