1 /*
2  * virsh-completer-host.c: virsh completer callbacks related to host
3  *
4  * Copyright (C) 2019 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library.  If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <config.h>
22 
23 #include "virsh-completer-host.h"
24 #include "viralloc.h"
25 #include "virsh.h"
26 #include "virstring.h"
27 #include "virxml.h"
28 #include "virutil.h"
29 #include "virsh-host.h"
30 
31 static char *
virshPagesizeNodeToString(xmlNodePtr node)32 virshPagesizeNodeToString(xmlNodePtr node)
33 {
34     g_autofree char *pagesize = NULL;
35     g_autofree char *unit = NULL;
36     unsigned long long byteval = 0;
37     const char *suffix = NULL;
38     double size = 0;
39     char *ret;
40 
41     pagesize = virXMLPropString(node, "size");
42     unit = virXMLPropString(node, "unit");
43     if (virStrToLong_ull(pagesize, NULL, 10, &byteval) < 0)
44         return NULL;
45     if (virScaleInteger(&byteval, unit, 1024, UINT_MAX) < 0)
46         return NULL;
47     size = vshPrettyCapacity(byteval, &suffix);
48     ret = g_strdup_printf("%.0f%s", size, suffix);
49     return ret;
50 }
51 
52 char **
virshAllocpagesPagesizeCompleter(vshControl * ctl,const vshCmd * cmd G_GNUC_UNUSED,unsigned int flags)53 virshAllocpagesPagesizeCompleter(vshControl *ctl,
54                                  const vshCmd *cmd G_GNUC_UNUSED,
55                                  unsigned int flags)
56 {
57     g_autoptr(xmlXPathContext) ctxt = NULL;
58     virshControl *priv = ctl->privData;
59     int npages = 0;
60     g_autofree xmlNodePtr *pages = NULL;
61     g_autoptr(xmlDoc) doc = NULL;
62     size_t i = 0;
63     const char *cellnum = NULL;
64     bool cellno = vshCommandOptBool(cmd, "cellno");
65     g_autofree char *path = NULL;
66     g_autofree char *cap_xml = NULL;
67     g_auto(GStrv) tmp = NULL;
68 
69     virCheckFlags(0, NULL);
70 
71     if (!priv->conn || virConnectIsAlive(priv->conn) <= 0)
72         return NULL;
73 
74     if (!(cap_xml = virConnectGetCapabilities(priv->conn)))
75         return NULL;
76 
77     if (!(doc = virXMLParseStringCtxt(cap_xml, _("capabilities"), &ctxt)))
78         return NULL;
79 
80     if (cellno && vshCommandOptStringQuiet(ctl, cmd, "cellno", &cellnum) > 0) {
81         path = g_strdup_printf("/capabilities/host/topology/cells/cell[@id=\"%s\"]/pages",
82                                cellnum);
83     } else {
84         path = g_strdup("/capabilities/host/cpu/pages");
85     }
86 
87     npages = virXPathNodeSet(path, ctxt, &pages);
88     if (npages <= 0)
89         return NULL;
90 
91     tmp = g_new0(char *, npages + 1);
92 
93     for (i = 0; i < npages; i++) {
94         if (!(tmp[i] = virshPagesizeNodeToString(pages[i])))
95             return NULL;
96     }
97 
98     return g_steal_pointer(&tmp);
99 }
100 
101 
102 char **
virshCellnoCompleter(vshControl * ctl,const vshCmd * cmd G_GNUC_UNUSED,unsigned int flags)103 virshCellnoCompleter(vshControl *ctl,
104                      const vshCmd *cmd G_GNUC_UNUSED,
105                      unsigned int flags)
106 {
107     g_autoptr(xmlXPathContext) ctxt = NULL;
108     virshControl *priv = ctl->privData;
109     int ncells = 0;
110     g_autofree xmlNodePtr *cells = NULL;
111     g_autoptr(xmlDoc) doc = NULL;
112     size_t i = 0;
113     g_autofree char *cap_xml = NULL;
114     g_auto(GStrv) tmp = NULL;
115 
116     virCheckFlags(0, NULL);
117 
118     if (!priv->conn || virConnectIsAlive(priv->conn) <= 0)
119         return NULL;
120 
121     if (!(cap_xml = virConnectGetCapabilities(priv->conn)))
122         return NULL;
123 
124     if (!(doc = virXMLParseStringCtxt(cap_xml, _("capabilities"), &ctxt)))
125         return NULL;
126 
127     ncells = virXPathNodeSet("/capabilities/host/topology/cells/cell", ctxt, &cells);
128     if (ncells <= 0)
129         return NULL;
130 
131     tmp = g_new0(char *, ncells + 1);
132 
133     for (i = 0; i < ncells; i++) {
134         if (!(tmp[i] = virXMLPropString(cells[i], "id")))
135             return NULL;
136     }
137 
138     return g_steal_pointer(&tmp);
139 }
140 
141 
142 char **
virshNodeCpuCompleter(vshControl * ctl,const vshCmd * cmd G_GNUC_UNUSED,unsigned int flags)143 virshNodeCpuCompleter(vshControl *ctl,
144                       const vshCmd *cmd G_GNUC_UNUSED,
145                       unsigned int flags)
146 {
147     virshControl *priv = ctl->privData;
148     g_auto(GStrv) tmp = NULL;
149     size_t i;
150     int cpunum;
151     size_t offset = 0;
152     unsigned int online;
153     g_autofree unsigned char *cpumap = NULL;
154 
155     virCheckFlags(0, NULL);
156 
157     if ((cpunum = virNodeGetCPUMap(priv->conn, &cpumap, &online, 0)) < 0)
158         return NULL;
159 
160     tmp = g_new0(char *, online + 1);
161 
162     for (i = 0; i < cpunum; i++) {
163         if (VIR_CPU_USED(cpumap, i) == 0)
164             continue;
165 
166         tmp[offset++] = g_strdup_printf("%zu", i);
167     }
168 
169     return g_steal_pointer(&tmp);
170 }
171 
172 
173 char **
virshNodeSuspendTargetCompleter(vshControl * ctl G_GNUC_UNUSED,const vshCmd * cmd G_GNUC_UNUSED,unsigned int flags)174 virshNodeSuspendTargetCompleter(vshControl *ctl G_GNUC_UNUSED,
175                                 const vshCmd *cmd G_GNUC_UNUSED,
176                                 unsigned int flags)
177 {
178     char **ret = NULL;
179     size_t i;
180 
181     virCheckFlags(0, NULL);
182 
183     ret = g_new0(char *, VIR_NODE_SUSPEND_TARGET_LAST + 1);
184 
185     for (i = 0; i < VIR_NODE_SUSPEND_TARGET_LAST; i++)
186         ret[i] = g_strdup(virshNodeSuspendTargetTypeToString(i));
187 
188     return ret;
189 }
190