1 package org.metricshub.winrm;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.util.Objects;
24 import java.util.Optional;
25 import java.util.concurrent.TimeoutException;
26 import org.metricshub.winrm.exceptions.WindowsRemoteException;
27 import org.metricshub.winrm.exceptions.WqlQuerySyntaxException;
28
29 public class WindowsTempShare {
30
31
32 private final String shareName;
33
34
35 private final String uncSharePath;
36
37
38 private final String remotePath;
39
40
41 private final WindowsRemoteExecutor windowsRemoteExecutor;
42
43
44
45
46
47
48
49
50
51 public WindowsTempShare(
52 final WindowsRemoteExecutor windowsRemoteExecutor,
53 final String shareNameOrUnc,
54 final String remotePath
55 ) {
56 Utils.checkNonNull(windowsRemoteExecutor, "windowsRemoteExecutor");
57 Utils.checkNonNull(shareNameOrUnc, "shareNameOrUnc");
58
59 if (shareNameOrUnc.startsWith("\\\\")) {
60 this.uncSharePath = shareNameOrUnc;
61 final String[] uncElements = shareNameOrUnc.split("\\\\");
62 this.shareName = uncElements[3];
63 } else {
64 this.uncSharePath = buildUncPath(windowsRemoteExecutor.getHostname(), shareNameOrUnc);
65 this.shareName = shareNameOrUnc;
66 }
67
68 this.remotePath = remotePath;
69 this.windowsRemoteExecutor = windowsRemoteExecutor;
70 }
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public static WindowsTempShare getOrCreateShare(
85 final WindowsRemoteExecutor windowsRemoteExecutor,
86 final long timeout,
87 final ShareRemoteDirectoryConsumer<WindowsRemoteExecutor, String, String, Long> shareRemoteDirectory
88 ) throws TimeoutException, WindowsRemoteException {
89 Utils.checkNonNull(windowsRemoteExecutor, "windowsRemoteExecutor");
90 Utils.checkArgumentNotZeroOrNegative(timeout, "timeout");
91 Utils.checkNonNull(shareRemoteDirectory, "shareRemoteDirectory");
92
93 final long start = Utils.getCurrentTimeMillis();
94
95
96
97
98
99 final Optional<WindowsTempShare> clusterShare = getClusterShare(
100 windowsRemoteExecutor,
101 TimeoutHelper.getRemainingTime(timeout, start, "No time left to check for cluster share"),
102 start
103 );
104
105 if (clusterShare.isPresent()) {
106 return clusterShare.get();
107 }
108
109
110 final String shareName = buildShareName();
111 final Optional<WindowsTempShare> share = getShare(
112 windowsRemoteExecutor,
113 shareName,
114 TimeoutHelper.getRemainingTime(timeout, start, "No time left to get a normal temporary share")
115 );
116 if (share.isPresent()) {
117 return share.get();
118 }
119
120 return createTempShare(
121 windowsRemoteExecutor,
122 shareName,
123 TimeoutHelper.getRemainingTime(timeout, start, "No time left to create the temporary share"),
124 shareRemoteDirectory
125 );
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 public static String getWindowsDirectory(final WindowsRemoteExecutor windowsRemoteExecutor, final long timeout)
144 throws WindowsRemoteException, TimeoutException {
145 Utils.checkNonNull(windowsRemoteExecutor, "windowsRemoteExecutor");
146 Utils.checkArgumentNotZeroOrNegative(timeout, "timeout");
147
148 try {
149
150 return windowsRemoteExecutor
151 .executeWql("SELECT WindowsDirectory FROM Win32_OperatingSystem", timeout)
152 .stream()
153 .limit(1)
154 .map(row -> (String) row.get("WindowsDirectory"))
155 .filter(Objects::nonNull)
156 .findFirst()
157 .orElseThrow(() ->
158 new WindowsRemoteException(
159 String.format("Couldn't identify the Windows root directory on %s.", windowsRemoteExecutor.getHostname())
160 )
161 );
162 } catch (final WqlQuerySyntaxException e) {
163 throw new WindowsRemoteException(e);
164 }
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178 public static void createRemoteDirectory(
179 final WindowsRemoteExecutor windowsRemoteExecutor,
180 final String remotePath,
181 final long timeout,
182 final long start
183 ) throws WindowsRemoteException, TimeoutException {
184 Utils.checkNonNull(windowsRemoteExecutor, "windowsRemoteExecutor");
185
186 windowsRemoteExecutor.executeCommand(buildCreateRemoteDirectoryCommand(remotePath), null, null, timeout);
187 }
188
189
190
191
192
193
194
195
196
197
198
199 static String buildUncPath(final String hostname, final String share) {
200 Utils.checkNonNull(hostname, "hostname");
201
202 return hostname.contains(":")
203 ? String.format("\\\\%s.ipv6-literal.net\\%s", hostname.replace(":", "-").replace("%", "s"), share)
204 : String.format("\\\\%s\\%s", hostname, share);
205 }
206
207
208
209
210
211
212
213
214 static String buildCreateRemoteDirectoryCommand(final String remotePath) {
215 Utils.checkNonBlank(remotePath, "remotePath");
216
217 return String.format("CMD.EXE /C IF NOT EXIST \"%s\" MKDIR %s", remotePath, remotePath);
218 }
219
220
221
222
223
224
225 static String buildPathOnCluster(final String path) {
226 Utils.checkNonNull(path, "path");
227
228 return String.format("%s\\Temp\\SEN_TempFor_%s", path, Utils.getComputerName());
229 }
230
231
232
233
234
235
236
237
238
239 static String buildRemotePath(final String folder, final String shareName) {
240 Utils.checkNonNull(folder, "folder");
241 Utils.checkNonBlank(shareName, "shareName");
242
243 return String.format("%s\\Temp\\%s", folder, shareName);
244 }
245
246
247
248
249
250
251 static String buildShareName() {
252 return String.format("SEN_ShareFor_%s$", Utils.getComputerName());
253 }
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 static Optional<WindowsTempShare> getClusterShare(
270 final WindowsRemoteExecutor windowsRemoteExecutor,
271 final long timeout,
272 final long start
273 ) throws TimeoutException, WindowsRemoteException {
274 try {
275 final Optional<WindowsTempShare> clusterShare = windowsRemoteExecutor
276 .executeWql(
277 "SELECT Name,Path FROM Win32_ClusterShare WHERE " +
278 "ServerName <> '*' AND (Type = 2147483648 OR Type = 3221225472) AND Name LIKE '%\\\\_$'",
279 timeout
280 )
281 .stream()
282 .limit(1)
283 .map(row ->
284 new WindowsTempShare(
285 windowsRemoteExecutor,
286 buildPathOnCluster((String) row.get("Name")),
287 buildPathOnCluster((String) row.get("Path"))
288 )
289 )
290 .findFirst();
291
292 if (clusterShare.isPresent()) {
293
294 createRemoteDirectory(windowsRemoteExecutor, clusterShare.get().getRemotePath(), timeout, start);
295 }
296
297 return clusterShare;
298 } catch (final WqlQuerySyntaxException e) {
299 throw new WindowsRemoteException(e);
300 }
301 }
302
303
304
305
306
307
308
309
310
311
312
313
314
315 static Optional<WindowsTempShare> getShare(
316 final WindowsRemoteExecutor windowsRemoteExecutor,
317 final String shareName,
318 final long timeout
319 ) throws TimeoutException, WindowsRemoteException {
320 try {
321 return windowsRemoteExecutor
322 .executeWql(String.format("SELECT Name,Path FROM Win32_Share WHERE Name = '%s'", shareName), timeout)
323 .stream()
324 .limit(1)
325 .map(row -> new WindowsTempShare(windowsRemoteExecutor, (String) row.get("Name"), (String) row.get("Path")))
326 .findFirst();
327 } catch (final WqlQuerySyntaxException e) {
328 throw new WindowsRemoteException(e);
329 }
330 }
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345 static WindowsTempShare createTempShare(
346 final WindowsRemoteExecutor windowsRemoteExecutor,
347 final String shareName,
348 final long timeout,
349 final ShareRemoteDirectoryConsumer<WindowsRemoteExecutor, String, String, Long> shareRemoteDirectory
350 ) throws WindowsRemoteException, TimeoutException {
351 final long start = Utils.getCurrentTimeMillis();
352
353
354 final String folder = getWindowsDirectory(windowsRemoteExecutor, timeout);
355
356
357 final String remotePath = buildRemotePath(folder, shareName);
358 createRemoteDirectory(
359 windowsRemoteExecutor,
360 remotePath,
361 TimeoutHelper.getRemainingTime(timeout, start, "No time left to create the temporary directory"),
362 start
363 );
364
365
366 shareRemoteDirectory.apply(windowsRemoteExecutor, remotePath, shareName, timeout);
367
368 return new WindowsTempShare(windowsRemoteExecutor, shareName, remotePath);
369 }
370
371
372 public String getShareName() {
373 return shareName;
374 }
375
376
377 public String getUncSharePath() {
378 return uncSharePath;
379 }
380
381
382 public String getRemotePath() {
383 return remotePath;
384 }
385
386
387 public WindowsRemoteExecutor getWindowsRemoteExecutor() {
388 return windowsRemoteExecutor;
389 }
390 }