6
6
7
7
package com .microsoft .azure .management .samples ;
8
8
9
+ import com .jcraft .jsch .Channel ;
10
+ import com .jcraft .jsch .ChannelExec ;
11
+ import com .jcraft .jsch .ChannelSftp ;
9
12
import com .jcraft .jsch .ChannelShell ;
10
13
import com .jcraft .jsch .JSch ;
11
14
import com .jcraft .jsch .JSchException ;
15
+ import com .jcraft .jsch .KeyPair ;
12
16
import com .jcraft .jsch .Session ;
13
17
import expect4j .Closure ;
14
18
import expect4j .Expect4j ;
17
21
import expect4j .matches .RegExpMatch ;
18
22
import org .apache .oro .text .regex .MalformedPatternException ;
19
23
24
+ import java .io .BufferedOutputStream ;
25
+ import java .io .ByteArrayOutputStream ;
20
26
import java .io .IOException ;
27
+ import java .io .InputStream ;
21
28
import java .util .ArrayList ;
22
29
import java .util .Hashtable ;
23
30
import java .util .List ;
@@ -105,6 +112,116 @@ public String runCommands(List<String> commands) throws Exception {
105
112
return output ;
106
113
}
107
114
115
+ /**
116
+ * Executes a command on the remote host.
117
+ *
118
+ * @param command the command to be executed
119
+ * @param getExitStatus return the exit status captured in the stdout
120
+ * @param withErr capture the stderr as part of the output
121
+ * @return the content of the remote output from executing the command
122
+ * @throws Exception exception thrown
123
+ */
124
+ public String executeCommand (String command , Boolean getExitStatus , Boolean withErr ) throws Exception {
125
+ String result = "" ;
126
+ String resultErr = "" ;
127
+
128
+ Channel channel = this .session .openChannel ("exec" );
129
+ ((ChannelExec ) channel ).setCommand (command );
130
+ InputStream commandOutput = channel .getInputStream ();
131
+ InputStream commandErr = ((ChannelExec ) channel ).getErrStream ();
132
+ channel .connect ();
133
+ byte [] tmp = new byte [4096 ];
134
+ while (true ) {
135
+ while (commandOutput .available () > 0 ) {
136
+ int i = commandOutput .read (tmp , 0 , 4096 );
137
+ if (i < 0 ) {
138
+ break ;
139
+ }
140
+ result += new String (tmp , 0 , i );
141
+ }
142
+ while (commandErr .available () > 0 ) {
143
+ int i = commandErr .read (tmp , 0 , 4096 );
144
+ if (i < 0 ) {
145
+ break ;
146
+ }
147
+ resultErr += new String (tmp , 0 , i );
148
+ }
149
+ if (channel .isClosed ()) {
150
+ if (commandOutput .available () > 0 ) {
151
+ continue ;
152
+ }
153
+ if (getExitStatus ) {
154
+ result += "exit-status: " + channel .getExitStatus ();
155
+ if (withErr ) {
156
+ result += "\n With error:\n " + resultErr ;
157
+ }
158
+ }
159
+ break ;
160
+ }
161
+ try {
162
+ Thread .sleep (100 );
163
+ } catch (Exception ee ) { }
164
+ }
165
+ channel .disconnect ();
166
+
167
+ return result ;
168
+ }
169
+
170
+ /**
171
+ * Downloads the content of a file from the remote host as a String.
172
+ *
173
+ * @param fileName the name of the file for which the content will be downloaded
174
+ * @param fromPath the path of the file for which the content will be downloaded
175
+ * @param isUserHomeBased true if the path of the file is relative to the user's home directory
176
+ * @return the content of the file
177
+ * @throws Exception exception thrown
178
+ */
179
+ public String download (String fileName , String fromPath , boolean isUserHomeBased ) throws Exception {
180
+ ChannelSftp channel = (ChannelSftp ) this .session .openChannel ("sftp" );
181
+ channel .connect ();
182
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream ();
183
+ BufferedOutputStream buff = new BufferedOutputStream (outputStream );
184
+ String absolutePath = isUserHomeBased ? channel .getHome () + "/" + fromPath : fromPath ;
185
+ channel .cd (absolutePath );
186
+ channel .get (fileName , buff );
187
+
188
+ channel .disconnect ();
189
+
190
+ return outputStream .toString ();
191
+ }
192
+
193
+ /**
194
+ * Creates a new file on the remote host using the input content.
195
+ *
196
+ * @param from the byte array content to be uploaded
197
+ * @param fileName the name of the file for which the content will be saved into
198
+ * @param toPath the path of the file for which the content will be saved into
199
+ * @param isUserHomeBased true if the path of the file is relative to the user's home directory
200
+ * @param filePerm file permissions to be set
201
+ * @throws Exception exception thrown
202
+ */
203
+ public void upload (InputStream from , String fileName , String toPath , boolean isUserHomeBased , String filePerm ) throws Exception {
204
+ ChannelSftp channel = (ChannelSftp ) this .session .openChannel ("sftp" );
205
+ channel .connect ();
206
+ String absolutePath = isUserHomeBased ? channel .getHome () + "/" + toPath : toPath ;
207
+
208
+ String path = "" ;
209
+ for (String dir : absolutePath .split ("/" )) {
210
+ path = path + "/" + dir ;
211
+ try {
212
+ channel .mkdir (path );
213
+ } catch (Exception ee ) {
214
+ }
215
+ }
216
+ channel .cd (absolutePath );
217
+ channel .put (from , fileName );
218
+ if (filePerm != null ) {
219
+ channel .chmod (Integer .parseInt (filePerm ), absolutePath + "/" + fileName );
220
+ }
221
+
222
+ channel .disconnect ();
223
+ }
224
+
108
225
/**
109
226
* Closes shell.
110
227
*/
@@ -130,4 +247,78 @@ public void run(ExpectState expectState) throws Exception {
130
247
}
131
248
};
132
249
}
250
+
251
+ /**
252
+ * Automatically generate SSH keys.
253
+ * @param passPhrase the byte array content to be uploaded
254
+ * @param comment the name of the file for which the content will be saved into
255
+ * @return SSH public and private key
256
+ * @throws Exception exception thrown
257
+ */
258
+ public static SshPublicPrivateKey generateSSHKeys (String passPhrase , String comment ) throws Exception {
259
+ JSch jsch = new JSch ();
260
+ KeyPair keyPair = KeyPair .genKeyPair (jsch , KeyPair .RSA );
261
+ ByteArrayOutputStream privateKeyBuff = new ByteArrayOutputStream (2048 );
262
+ ByteArrayOutputStream publicKeyBuff = new ByteArrayOutputStream (2048 );
263
+
264
+ keyPair .writePublicKey (publicKeyBuff , (comment != null ) ? comment : "SSHCerts" );
265
+
266
+ if (passPhrase == null || passPhrase .isEmpty ()) {
267
+ keyPair .writePrivateKey (privateKeyBuff );
268
+ } else {
269
+ keyPair .writePrivateKey (privateKeyBuff , passPhrase .getBytes ());
270
+ }
271
+
272
+ return new SshPublicPrivateKey (privateKeyBuff .toString (), publicKeyBuff .toString ());
273
+ }
274
+
275
+ /**
276
+ * Internal class to retain the generate SSH keys.
277
+ */
278
+ public static class SshPublicPrivateKey {
279
+ private String sshPublicKey ;
280
+ private String sshPrivateKey ;
281
+
282
+ /**
283
+ * Constructor.
284
+ * @param sshPrivateKey SSH private key
285
+ * @param sshPublicKey SSH public key
286
+ */
287
+ public SshPublicPrivateKey (String sshPrivateKey , String sshPublicKey ) {
288
+ this .sshPrivateKey = sshPrivateKey ;
289
+ this .sshPublicKey = sshPublicKey ;
290
+ }
291
+
292
+ /**
293
+ * Get SSH public key.
294
+ * @return public key
295
+ */
296
+ public String getSshPublicKey () {
297
+ return sshPublicKey ;
298
+ }
299
+
300
+ /**
301
+ * Get SSH private key.
302
+ * @return private key
303
+ */
304
+ public String getSshPrivateKey () {
305
+ return sshPrivateKey ;
306
+ }
307
+
308
+ /**
309
+ * Set SSH public key.
310
+ * @param sshPublicKey public key
311
+ */
312
+ public void setSshPublicKey (String sshPublicKey ) {
313
+ this .sshPublicKey = sshPublicKey ;
314
+ }
315
+
316
+ /**
317
+ * Set SSH private key.
318
+ * @param sshPrivateKey private key
319
+ */
320
+ public void setSshPrivateKey (String sshPrivateKey ) {
321
+ this .sshPrivateKey = sshPrivateKey ;
322
+ }
323
+ }
133
324
}
0 commit comments