-
Notifications
You must be signed in to change notification settings - Fork 192
/
SSHShell.cs
215 lines (200 loc) · 7.13 KB
/
SSHShell.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Renci.SshNet;
using System;
using System.IO;
namespace Microsoft.Azure.Management.Samples.Common
{
public class SSHShell : IDisposable
{
const string UBUNTU_HOME_DIRECTORY = "/home/";
private SshClient sshClient;
private ScpClient scpClient;
private string homeDirectory;
/**
* Creates SSHShell.
*
* @param host the host name
* @param port the ssh port
* @param userName the ssh user name
* @param password the ssh password
* @return the shell client
*/
private SSHShell(string host, int port, string userName, string password)
{
var backoffTime = 30 * 1000;
var retryCount = 3;
while (retryCount > 0)
{
try
{
sshClient = new SshClient(host, port, userName, password);
sshClient.Connect();
scpClient = new ScpClient(host, port, userName, password);
scpClient.Connect();
homeDirectory = UBUNTU_HOME_DIRECTORY + userName + "/";
break;
}
catch (Exception exception)
{
retryCount--;
if (retryCount == 0)
{
throw exception;
}
}
SdkContext.DelayProvider.Delay(backoffTime);
}
}
/**
* Opens a SSH shell.
*
* @param host the host name
* @param port the ssh port
* @param userName the ssh user name
* @param password the ssh password
* @return the shell client
*/
public static SSHShell Open(string host, int port, string userName, string password)
{
return new SSHShell(host, port, userName, password);
}
/**
* Executes a command on the remote host.
*
* @param shell the SSH shell client into which the command will be executed
* @param commandToExecute the command to be executed
* @return the content of the remote output from executing the command
*/
public string ExecuteCommand(string commandToExecute)
{
if (sshClient != null)
{
using (var command = sshClient.CreateCommand(commandToExecute))
{
return command.Execute();
}
}
else
{
return null;
}
}
/**
* Downloads the content of a file from the remote host as a String.
*
* @param fileName the name of the file for which the content will be downloaded
* @param fromPath the path of the file for which the content will be downloaded
* @param isUserHomeBased true if the path of the file is relative to the user's home directory
* @return the content of the file
*/
public string Download(string fileName, string fromPath, bool isUserHomeBased)
{
if (scpClient != null)
{
string path = fromPath;
if (isUserHomeBased)
{
path = homeDirectory + path;
}
using (var mstream = new MemoryStream())
{
scpClient.Download(path + "/" + fileName, mstream);
mstream.Position = 0;
return (new System.IO.StreamReader(mstream)).ReadToEnd();
}
}
else
{
return null;
}
}
/**
* Downloads the content of a file from the remote host as a String.
*
* @param fileName the name of the file for which the content will be downloaded
* @param fromPath the path of the file for which the content will be downloaded
* @param isUserHomeBased true if the path of the file is relative to the user's home directory
* @return the content of the file
*/
public int Download(byte[] destBuff, int maxCount, string fileName, string fromPath, bool isUserHomeBased)
{
if (scpClient != null)
{
string path = fromPath;
if (isUserHomeBased)
{
path = homeDirectory + path;
}
using (MemoryStream mstream = new MemoryStream())
{
scpClient.Download(path + "/" + fileName, mstream);
if (mstream.Position >= maxCount)
{
return -1;
}
mstream.Position = 0;
return mstream.Read(destBuff, 0, maxCount);
}
}
else
{
return -1;
}
}
/**
* Creates a new file on the remote host using the input content.
*
* @param data the byte array content to be uploaded
* @param fileName the name of the file for which the content will be saved into
* @param toPath the path of the file for which the content will be saved into
* @param isUserHomeBased true if the path of the file is relative to the user's home directory
* @param filePerm file permissions to be set
*/
public void Upload(byte[] data, string fileName, string toPath, bool isUserHomeBased)
{
if (scpClient != null && sshClient != null)
{
string path = toPath;
if (isUserHomeBased)
{
path = homeDirectory + path;
}
// Create the directory on the remote host
using (var command = sshClient.CreateCommand("mkdir -p " + path))
{
command.Execute();
}
// Create the file containing the uploaded data
// byte[] data = System.Text.Encoding.ASCII.GetBytes("");
using (var mstream = new MemoryStream(data))
{
scpClient.Upload(mstream, path + "/" + fileName);
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (sshClient != null)
{
sshClient.Disconnect();
sshClient.Dispose();
}
if (scpClient != null)
{
scpClient.Disconnect();
scpClient.Dispose();
}
}
// free native resources if there are any.
}
}
}