1 #include "domainsnapshot.h"
2 #include "domain.h"
3 #include "util.h"
4
5 #include <libvirt/libvirt.h>
6
7 static virDomainSnapshotPtr
virtDBusDomainSnapshotGetVirDomainSnapshot(virtDBusConnect * connect,const gchar * objectPath,GError ** error)8 virtDBusDomainSnapshotGetVirDomainSnapshot(virtDBusConnect *connect,
9 const gchar *objectPath,
10 GError **error)
11 {
12 virDomainSnapshotPtr domSnap;
13
14 if (!virtDBusConnectOpen(connect, error))
15 return NULL;
16
17 domSnap = virtDBusUtilVirDomainSnapshotFromBusPath(connect->connection,
18 objectPath,
19 connect->domainSnapshotPath);
20 if (!domSnap) {
21 virtDBusUtilSetLastVirtError(error);
22 return NULL;
23 }
24
25 return domSnap;
26 }
27
28 static void
virtDBusDomainSnapshotDelete(GVariant * inArgs,GUnixFDList * inFDs G_GNUC_UNUSED,const gchar * objectPath,gpointer userData,GVariant ** outArgs G_GNUC_UNUSED,GUnixFDList ** outFDs G_GNUC_UNUSED,GError ** error)29 virtDBusDomainSnapshotDelete(GVariant *inArgs,
30 GUnixFDList *inFDs G_GNUC_UNUSED,
31 const gchar *objectPath,
32 gpointer userData,
33 GVariant **outArgs G_GNUC_UNUSED,
34 GUnixFDList **outFDs G_GNUC_UNUSED,
35 GError **error)
36 {
37 virtDBusConnect *connect = userData;
38 g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
39 guint flags;
40
41 g_variant_get(inArgs, "(u)", &flags);
42
43 domainSnapshot = virtDBusDomainSnapshotGetVirDomainSnapshot(connect,
44 objectPath,
45 error);
46 if (!domainSnapshot)
47 return;
48
49 if (virDomainSnapshotDelete(domainSnapshot, flags) < 0)
50 return virtDBusUtilSetLastVirtError(error);
51 }
52
53 static void
virtDBusDomainSnapshotGetParent(GVariant * inArgs,GUnixFDList * inFDs G_GNUC_UNUSED,const gchar * objectPath,gpointer userData,GVariant ** outArgs G_GNUC_UNUSED,GUnixFDList ** outFDs G_GNUC_UNUSED,GError ** error)54 virtDBusDomainSnapshotGetParent(GVariant *inArgs,
55 GUnixFDList *inFDs G_GNUC_UNUSED,
56 const gchar *objectPath,
57 gpointer userData,
58 GVariant **outArgs G_GNUC_UNUSED,
59 GUnixFDList **outFDs G_GNUC_UNUSED,
60 GError **error)
61 {
62 virtDBusConnect *connect = userData;
63 g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
64 g_autoptr(virDomainSnapshot) parent = NULL;
65 guint flags;
66 virDomainPtr domain = NULL;
67 g_autofree gchar *parentPath = NULL;
68
69 g_variant_get(inArgs, "(u)", &flags);
70
71 domainSnapshot = virtDBusDomainSnapshotGetVirDomainSnapshot(connect,
72 objectPath,
73 error);
74 if (!domainSnapshot)
75 return;
76
77 parent = virDomainSnapshotGetParent(domainSnapshot, flags);
78 if (!parent)
79 return virtDBusUtilSetLastVirtError(error);
80
81 domain = virDomainSnapshotGetDomain(domainSnapshot);
82 parentPath = virtDBusUtilBusPathForVirDomainSnapshot(domain,
83 parent,
84 connect->domainSnapshotPath);
85
86 *outArgs = g_variant_new("(o)", parentPath);
87 }
88
89 static void
virtDBusDomainSnapshotGetXMLDesc(GVariant * inArgs,GUnixFDList * inFDs G_GNUC_UNUSED,const gchar * objectPath,gpointer userData,GVariant ** outArgs G_GNUC_UNUSED,GUnixFDList ** outFDs G_GNUC_UNUSED,GError ** error)90 virtDBusDomainSnapshotGetXMLDesc(GVariant *inArgs,
91 GUnixFDList *inFDs G_GNUC_UNUSED,
92 const gchar *objectPath,
93 gpointer userData,
94 GVariant **outArgs G_GNUC_UNUSED,
95 GUnixFDList **outFDs G_GNUC_UNUSED,
96 GError **error)
97 {
98 virtDBusConnect *connect = userData;
99 g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
100 guint flags;
101 g_autofree gchar *xml = NULL;
102
103 g_variant_get(inArgs, "(u)", &flags);
104
105 domainSnapshot = virtDBusDomainSnapshotGetVirDomainSnapshot(connect,
106 objectPath,
107 error);
108 if (!domainSnapshot)
109 return;
110
111 xml = virDomainSnapshotGetXMLDesc(domainSnapshot, flags);
112 if (!xml)
113 return virtDBusUtilSetLastVirtError(error);
114
115 *outArgs = g_variant_new("(s)", xml);
116 }
117
118 static void
virtDBusDomainSnapshotIsCurrent(GVariant * inArgs,GUnixFDList * inFDs G_GNUC_UNUSED,const gchar * objectPath,gpointer userData,GVariant ** outArgs G_GNUC_UNUSED,GUnixFDList ** outFDs G_GNUC_UNUSED,GError ** error)119 virtDBusDomainSnapshotIsCurrent(GVariant *inArgs,
120 GUnixFDList *inFDs G_GNUC_UNUSED,
121 const gchar *objectPath,
122 gpointer userData,
123 GVariant **outArgs G_GNUC_UNUSED,
124 GUnixFDList **outFDs G_GNUC_UNUSED,
125 GError **error)
126 {
127 virtDBusConnect *connect = userData;
128 g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
129 guint flags;
130 gint isCurrent;
131
132 g_variant_get(inArgs, "(u)", &flags);
133
134 domainSnapshot = virtDBusDomainSnapshotGetVirDomainSnapshot(connect,
135 objectPath,
136 error);
137 if (!domainSnapshot)
138 return;
139
140 isCurrent = virDomainSnapshotIsCurrent(domainSnapshot, flags);
141 if (isCurrent < 0)
142 return virtDBusUtilSetLastVirtError(error);
143
144 *outArgs = g_variant_new("(b)", !!isCurrent);
145 }
146
147 static void
virtDBusDomainSnapshotListAllChildren(GVariant * inArgs,GUnixFDList * inFDs G_GNUC_UNUSED,const gchar * objectPath,gpointer userData,GVariant ** outArgs G_GNUC_UNUSED,GUnixFDList ** outFDs G_GNUC_UNUSED,GError ** error)148 virtDBusDomainSnapshotListAllChildren(GVariant *inArgs,
149 GUnixFDList *inFDs G_GNUC_UNUSED,
150 const gchar *objectPath,
151 gpointer userData,
152 GVariant **outArgs G_GNUC_UNUSED,
153 GUnixFDList **outFDs G_GNUC_UNUSED,
154 GError **error)
155 {
156 virtDBusConnect *connect = userData;
157 g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
158 g_autoptr(virDomainSnapshotPtr) snaps = NULL;
159 guint flags;
160 GVariantBuilder builder;
161 GVariant *gdomainSnapshots;
162 virDomainPtr domain = NULL;
163
164 g_variant_get(inArgs, "(u)", &flags);
165
166 domainSnapshot = virtDBusDomainSnapshotGetVirDomainSnapshot(connect,
167 objectPath,
168 error);
169 if (!domainSnapshot)
170 return;
171
172 if (virDomainSnapshotListAllChildren(domainSnapshot, &snaps, flags) < 0)
173 return virtDBusUtilSetLastVirtError(error);
174
175 g_variant_builder_init(&builder, G_VARIANT_TYPE("ao"));
176
177 domain = virDomainSnapshotGetDomain(domainSnapshot);
178 for (gint i = 0; snaps[i]; i++) {
179 g_autofree gchar *path = NULL;
180 path = virtDBusUtilBusPathForVirDomainSnapshot(domain,
181 snaps[i],
182 connect->domainSnapshotPath);
183
184 g_variant_builder_add(&builder, "o", path);
185 }
186
187 gdomainSnapshots = g_variant_builder_end(&builder);
188 *outArgs = g_variant_new_tuple(&gdomainSnapshots, 1);
189 }
190
191 static void
virtDBusDomainSnapshotRevert(GVariant * inArgs,GUnixFDList * inFDs G_GNUC_UNUSED,const gchar * objectPath,gpointer userData,GVariant ** outArgs G_GNUC_UNUSED,GUnixFDList ** outFDs G_GNUC_UNUSED,GError ** error)192 virtDBusDomainSnapshotRevert(GVariant *inArgs,
193 GUnixFDList *inFDs G_GNUC_UNUSED,
194 const gchar *objectPath,
195 gpointer userData,
196 GVariant **outArgs G_GNUC_UNUSED,
197 GUnixFDList **outFDs G_GNUC_UNUSED,
198 GError **error)
199 {
200 virtDBusConnect *connect = userData;
201 g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
202 guint flags;
203
204 g_variant_get(inArgs, "(u)", &flags);
205
206 domainSnapshot = virtDBusDomainSnapshotGetVirDomainSnapshot(connect,
207 objectPath,
208 error);
209 if (!domainSnapshot)
210 return;
211
212 if (virDomainRevertToSnapshot(domainSnapshot, flags) < 0)
213 return virtDBusUtilSetLastVirtError(error);
214 }
215
216 static virtDBusGDBusPropertyTable virtDBusDomainSnapshotPropertyTable[] = {
217 { 0 }
218 };
219
220 static virtDBusGDBusMethodTable virtDBusDomainSnapshotMethodTable[] = {
221 { "Delete", virtDBusDomainSnapshotDelete },
222 { "GetParent", virtDBusDomainSnapshotGetParent },
223 { "GetXMLDesc", virtDBusDomainSnapshotGetXMLDesc },
224 { "IsCurrent", virtDBusDomainSnapshotIsCurrent },
225 { "ListChildren", virtDBusDomainSnapshotListAllChildren },
226 { "Revert", virtDBusDomainSnapshotRevert },
227 { 0 }
228 };
229
230 static gchar **
virtDBusDomainSnapshotEnumerate(gpointer userData)231 virtDBusDomainSnapshotEnumerate(gpointer userData)
232 {
233 virtDBusConnect *connect = userData;
234 g_autoptr(virDomainPtr) domains = NULL;
235 gint numDoms = 0;
236 GPtrArray *list = NULL;
237
238 if (!virtDBusConnectOpen(connect, NULL))
239 return NULL;
240
241 numDoms = virConnectListAllDomains(connect->connection, &domains, 0);
242 if (numDoms <= 0)
243 return NULL;
244
245 list = g_ptr_array_new();
246
247 for (gint i = 0; i < numDoms; i++) {
248 g_autoptr(virDomainSnapshotPtr) domainSnapshots = NULL;
249 gint numSnaps;
250
251 numSnaps = virDomainListAllSnapshots(domains[i], &domainSnapshots, 0);
252 if (numSnaps <= 0)
253 continue;
254
255 for (gint j = 0; j < numSnaps; j++) {
256 gchar *snapPath = virtDBusUtilBusPathForVirDomainSnapshot(domains[i],
257 domainSnapshots[j],
258 connect->domainSnapshotPath);
259 g_ptr_array_add(list, snapPath);
260 }
261 }
262
263 if (list->len > 0)
264 g_ptr_array_add(list, NULL);
265
266 return (gchar **)g_ptr_array_free(list, FALSE);
267 }
268
269 static GDBusInterfaceInfo *interfaceInfo = NULL;
270
271 void
virtDBusDomainSnapshotRegister(virtDBusConnect * connect,GError ** error)272 virtDBusDomainSnapshotRegister(virtDBusConnect *connect,
273 GError **error)
274 {
275 connect->domainSnapshotPath = g_strdup_printf("%s/domainsnapshot", connect->connectPath);
276
277 if (!interfaceInfo) {
278 interfaceInfo = virtDBusGDBusLoadIntrospectData(VIRT_DBUS_DOMAIN_SNAPSHOT_INTERFACE,
279 error);
280 if (!interfaceInfo)
281 return;
282 }
283
284 virtDBusGDBusRegisterSubtree(connect->bus,
285 connect->domainSnapshotPath,
286 interfaceInfo,
287 virtDBusDomainSnapshotEnumerate,
288 virtDBusDomainSnapshotMethodTable,
289 virtDBusDomainSnapshotPropertyTable,
290 connect);
291 }
292