-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmupload.ps1
executable file
·291 lines (250 loc) · 9.06 KB
/
mupload.ps1
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
Param (
[alias("nl")]
[switch]
$NoLinks,
[alias("v")]
[switch]
$Verbose,
[alias("m")]
[switch]
$MD5,
[alias("f")]
[switch]
$Force,
[alias("d")]
[switch]
$DryRun
)
<#
.SYNOPSIS
Get-ChildItem -recurse | mupload [-NoLinks|nl] [-MD5|m] [-Verbose|v]
[-DryRun|d] <basedirectory>
.DESCRIPTION
Upload a Windows directory hierarchy to Joyent Manta
Joyent Manta is a cloud-based object storage system, with an
integrated compute cluster. mupload uploads a directory
hierarchy to a particular manta account.
There is one required parameter, which is the base directory
in the remote Manta system. Those directories are of the form
"/<accountname>/[stor|public]/<user-selectable-names>". NOTE
that these are forward slashes.
mupload takes a piped tree of items,
from Get-ChildItem -recurse (or use gci -recurse)
and determines each item type.
-If the item is a directory, it creates it on Manta.
-If the item is a file, it uploads it to Manta in the
relative directory
The current working Windows directory is the relative
tree to upload, and it is appended to the Manta base directory
specified above.
e.g. if you are in
c:\Users\Administrator, and you provide
/benwen20131018/stor/windowsbak001 as the Manta base directory,
all files and paths relative to c:\Users\Administrator will
be uploaded relative to /benwen20131018/stor/windowsbak001
with the necessary conversion of Windows \ to Unix / path
separators.
Using -Force does NOT delete existing Manta objects if there is
not a local file to overwrite it.
.PARAMETER
-NoLinks | nl
Ignore files that end in '.lnk', which are typically Windows soft
links.
-Verbose | v
Provide more output.
-MD5 | m
Uses a local install of openssl to compute the md5 digest and
use that to force server side validation that the file uploaded
is identical. openssl must be installed and found in the PATH
tested with: http://slproweb.com/download/Win64OpenSSL-1_0_1h.exe
-Force | f
Ignore existing Manta base directory checks. Note that
existing objects will be overwritten, but non-overlapping
objects will still remain.
-DryRun | d
Show what commands would be run, but don't actually execute them.
.EXAMPLE
gci -recurse | mupload /benwen/stor/windowsbackup001/
.NOTES
Getting started with Joyent Manta:
1) Download and Install Node.js as all of the client tools are
built on Node.js. http://nodejs.org/download/
2) Run this in a Powershell propmt. It installes the Node
Package called "manta": npm install -g manta
3) Create a Joyent Cloud account at http://joyent.com
4) Create a private / public ssh key pair using the Joyent web
console (you should be prompted as you sign up to create and
download a key. Note that some versions of IE may not work
properly here).
5) Put the private key in your Windows home directory in a
folder called ".ssh", for example "/User/benwen/.ssh/ (the key
file should be called simply "id_rsa" in that directory.
6) Do the same with the public key, except it's named
"id_rsa.pub". Note that DSA keys don't work yet with Manta
(as of 2013-Oct).
7) Create these three environment variables:
$env:MANTA_USER = "benwen20131018"
$env:MANTA_URL = "https://us-east.manta.joyent.com"
$env:MANTA_KEY_ID = "11:de:e4:68:f1:b9:3c:1b:9a:9d:01:f5:8c:eb:b7:7c"
(substituting your Joyent username for benwen20131018, and
your key fingerprint (the 11:de:e4...) which can be found in
the Joyent web console in the same place. Click on the
generated key to expand the field to show both the fingerprint
and public key)
8) Run this command to test that Manta is working: "mls".
If you don't get an error message you're good to go. Visit:
http://apidocs.joyent.com/manta for more information.
9) To make -m MD5 work, install OpenSSL
http://slproweb.com/download/Win64OpenSSL-1_0_1e.exe and
add the directory for openssl.exe to your PATH
TODO: figure out how to display the help text in the right
place.
TODO: what is this thing going to do with special characters
like quotes, etc?
TODO: Error checking try/catch look for ENOTFOUND - broken connection
and ContentMD5MismatchError - set up retry...
TODO: Check for object being overwritten better
[Compare|c] compare only option to check stored value MD5
with directory tree and report differences (missing files, bad MD5)
.LINK
http://apidocs.joyent.com/manta
#>
function Manta-Exists ($mydir) {
$mycmd = 'mls'
$invokeme = "& $mycmd $mydir 2>&1"
$console_out = invoke-expression $invokeme
## "Console: " + $console_out | echo
$returnme = [string]::join("`r`n",$console_out)
## "Return: " + $returnme | echo
if ($returnme -match '.*Error.*') {
$False
} else {
$True
}
}
## First, see if Manta node command mls installed, callable
$mlscmd = "mls"
if (!(Get-Command $mlscmd -errorAction SilentlyContinue)) {
"Node.js Manta command mls is not found" | echo
"Check your Node.js, npm manta installations" | echo
exit 1
}
## Second, see if mls works with supplied account information
$mydir=""
if (Manta-Exists($mydir)) {
"Manta connection seems ok." | echo
} else {
"Manta not responding, check network with mls and check that your Manta" | echo
"environment variables have proper values: MANTA_USR, MANTA_URL, MANTA_KEY_ID" | echo
"SSH keys in place: id_rsa and id_rsa.pub downloaded from Joyent, placed in in $HOME/.ssh" | echo
exit 2
}
## Third if MD5 - check to see if openssl is in the PATH
if ($MD5) {
$openssl = "openssl"
if (!(Get-Command $openssl -errorAction SilentlyContinue)) {
"For MD5 validtation, openssl must be installed" | echo
"Check your path" | echo
exit 3
}
}
if (!( $args[0] -match '.*/$')) {
$base = $args[0] += "/"
} else {
$base = $args[0]
}
if ($Verbose) { "Basedir: " + $base | echo }
if (! $Force) {
if (Manta-Exists($base)) {
"Manta directory " + $base + " not found OR already exists. Aborting. Use -Force to override." | echo
exit 4
}
} else {
$mcmd = "mmkdir"
$mopts = "-p", $base
if ($Verbose) { "Creating Manta base directory: " + $base | echo }
if ($DryRun) {
"Dry Run: " + $mcmd + " " + $mopts | echo
} else {
& $mcmd $mopts
}
$mcmd = ""
$mopts = ""
}
foreach ($i in $input) {
if ($Verbose) {"Processing: " + $i.name + " is a container: " + $i.PSIsContainer | echo}
$tmp = Resolve-Path -relative $i.fullname
$tmp = $tmp -replace '\\', '/'
$tmp = $tmp -replace '\./', ''
$mdir = $base + $tmp
if ($Verbose) {"manta path: " + $mdir | echo}
if ($i.PSIsContainer) {
## mmkdir -p makes parent directories if needed
$mcmd = "mmkdir"
$mopts = "-p", $mdir
} else {
## Is this a soft link
if (($i.name -match '.*.lnk$') -and ($NoLinks)) {
## do nothing
$mcmd = ""
$mopts = ""
$mdhr = ""
} else {
## A regular file
if ($i.Length -gt 5000000000) {
## Set header to break 5Gb upload limit, pad size with 50Mb
$mcmd = "mput"
$size = $i.Length + 50000000
$mhdr = " -H `"max-content-length: $size`" "
$mopts = "-f", $i.fullname, $mdir
if ($Verbose) {$i.fullname + " Larger than 5Gb, using header: " + $mhdr | echo}
} else {
$mhdr = " "
$mcmd = "mput"
$mopts = "-f", $i.fullname, $mdir
}
if ($MD5) {
$digest = "dgst -md5 -binary -out digest.bin"
$encrypt = "enc -base64 -in digest.bin"
$fullname = $i.fullname
$quote = '"'
$opensslargs = $openssl + " " + $digest + " " + $quote + $fullname + $quote
if ($DryRun) {
"Dry Run: " + "cmd /c" + " " + $opensslargs | echo
}
if ($Verbose) { echo $opensslargs }
## PowerScript escape syntax - problems with
## spaces inside quotes inside file args for openssl
## http://connect.microsoft.com/PowerShell/feedback/details/376207
## So we run in command.com shell instead
& cmd /c $opensslargs
$opensslargs = $openssl + " " + $encrypt
if ($DryRun) {
"Dry Run: " + "cmd /c" + " " + $opensslargs | echo
}
if ($Verbose) { echo $opensslargs }
$md5string = & cmd /c $opensslargs
$md5HDR = "-H `"content-md5: $md5string`" "
& rm digest.bin
if ($DryRun) {
"Dry Run: " + $md5HDR | echo
}
} else {
$md5HDR = ""
}
}
}
if ($DryRun) {
"Dry Run: " + $mcmd + " " + $mhdr + " " + $md5HDR + " " + $mopts | echo
} else {
if ($Verbose) {
$mcmd + $mhdr + $md5HDR + $mopts | echo
} else {
if ($mcmd -match "mmkdir") {
# mmkdir is silent, provide feedback
$mcmd + $mhdr + $md5HDR + $mopts | echo
}
}
& $mcmd $mhdr $md5DHR $mopts
}
}