Subversion Repositories DevTools

Rev

Rev 6023 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5608 dpurdie 1
#!/bin/bash
2
#   This script will restore a package from S3 into dpkg_archive
3
#   See savePkgToS3.sh
4
#
5
#   The source bucket is: aupera-dpkg-quarantine
6
#   
7
#   The package version is expeced to be tar-zipped
8
#
9
#   The resulatant tar-zip will be transferred to S3
10
#
11
#       Reduced redundancy is used
12
#
13
#       Credentials: s3_dpkg user 
14
#
15
#       Usage:  getPkgFromS3.sh /PathTo/pkgName/pkgVersion
16
#
17
function doHelp {
18
cat <<endOfHelp
19
    Command: getPkgFromS3
20
 
21
    This program will retrieve tar-zip Package/Version from an Amazon S3 bucket
22
    and store it into a subdirectory specified
23
 
24
    Options
25
    -h, --help              - Display this message
26
    -v, --verbose           - Increase verbosity
27
    -q, --quiet             - No status messages
28
    -b, --bucket=name       - Specifies the name of the target bucket
29
    -p, --path=PVPath       - Specifies the path to the Package-Version to restore
30
    -f, --force             - Delete target and force package download
31
    -k, --key=keyVar        - Name of the EnvVar that conains the AWS key
32
                              Default is AWSKEY
33
    -s, --secret=secretVar  - Name of the EnvVar that conains the AWS secret
34
                              Default is AWSSECRET
35
 
36
   Example:
37
    getPkgFromS3.sh -p \$GBE_DPKG/AcceptanceTestFramework/1.0.10000.cr
38
endOfHelp
39
}
40
 
41
#
42
#   Init defaults
43
#
44
ProgName=getPkgFromS3
45
awsKeyVar=AWSKEY
46
awsSecretVar=AWSSECRET
47
bucket=aupera-dpkg-quarantine
48
verbose=1
49
forceDelete=0
50
 
51
# Note that we use `"$@"' to let each command-line parameter expand to a 
52
# separate word. The quotes around `$@' are essential!
53
# We need TEMP as the `eval set --' would nuke the return value of getopt.
54
TEMP=$( getopt -n ${ProgName} -o qfvhb:p:k:s: --long quiet,force,verbose,help,bucket:,path:,key:,secret: -- "$@" )
55
 
56
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
57
 
58
# Note the quotes around `$TEMP': they are essential!
59
eval set -- "$TEMP"
60
 
61
while true ; do
62
    case "$1" in
63
        -h|--help)    doHelp; exit 0;;
64
        -f|--force)   let forceDelete++; shift 1;;
65
        -q|--quiet)   verbose=0; shift 1;;
66
        -v|--verbose) let verbose++; shift 1;;
67
        -b|--bucket)  bucket="$2" ; shift 2 ;;
68
        -p|--path)    dpkgPath="$2" ; shift 2 ;;
69
        -k|--key)     awsKeyVar="$2" ; shift 2 ;;
70
        -s|--secret)  awsSecretVar="$2" ; shift 2 ;;
71
        --) shift ; break ;;
72
        *) echo "Internal error!" ; exit 1 ;;
73
    esac
74
done
75
 
76
if [ $verbose -gt 1 ] ; then
77
    echo bucket      :$bucket
78
    echo dpkgPath    :$dpkgPath
79
    echo awsKeyVar   :$awsKeyVar
80
    echo awsSecretVar:$awsSecretVar
81
 
82
    echo "Remaining arguments:"
83
    for arg do echo '--> '"\`$arg'" ; done
84
fi
85
 
86
: ${bucket:?No Bucket Specified}
87
: ${dpkgPath:?No Package Version Path}
88
: ${awsKeyVar:?No AWS Key specified}
89
: ${awsSecretVar:?No AWS Secret specified}
90
 
91
#
92
#   The KEY and the Secret are passed via EnvVars
93
#   The name of the vars are passed on the command line
94
#
95
aws_access_key_id=${!awsKeyVar}
96
aws_secret_access_key=${!awsSecretVar}
97
 
98
: ${aws_access_key_id:?No AWS Key found}
99
: ${aws_secret_access_key:?No AWS Secret found}
100
 
101
if [ $verbose -gt 1 ] ; then
102
    echo aws_access_key_id:$aws_access_key_id
103
    echo aws_secret_access_key:$aws_secret_access_key
104
fi
105
 
106
#
107
#   Determine
108
#       dpkgPath    - Cleanup the user arg
109
#       pkgBase     - Base of the package
110
#       pkgName     - Package Name
111
#       pkgVer      - Package Version
112
#
113
 
114
dpkgPath=${dpkgPath%/}
115
 
116
pkgBase=${dpkgPath%/*}
117
pkgBase=${pkgBase%/*}
118
 
119
pkgVer=${dpkgPath##*/}
120
 
121
pkgName=${dpkgPath%/*}
122
pkgName=${pkgName##*/}
123
 
124
if [ $verbose -gt 0 ] ; then
125
    echo Bucket  : $bucket
126
    echo pkgBase : $pkgBase
127
    echo pkgName : $pkgName
128
    echo pkgVer  : $pkgVer
129
fi
130
 
131
if [  ! -d $pkgBase ] ; then
132
    echo "Error: Package archive base does not exist: $pkgBase"
133
    exit 1
134
fi
135
 
136
# Force version deletion - more for test.
137
if [ $forceDelete -gt 0 ] ; then 
138
    [ $verbose -gt 0 ] && echo "Force removal of $pkgName/$pkgVer"
139
    if [ -d $dpkgPath ] ; then
140
        chmod -R +w $dpkgPath
141
        rm -rf $dpkgPath
142
    fi
143
fi
144
 
145
if [  -d $dpkgPath ] ; then
146
    echo "Error: Target PV Path already exists: $dpkgPath"
147
    exit 1
148
fi
149
 
150
#
151
#   Create the source file name
152
#   Format: Quarantined/PkgName_PkgVersion.tgz
153
file="Quarantined/${pkgName}_${pkgVer}.tgz"
154
 
155
# Basic transfer requirements
156
resource="/${bucket}/${file}"
157
dateValue=$(date -R)
158
 
159
 
160
#############################################################
161
#   Fetch file info, just to be sure that the file is there
162
#   Get data about the file
163
#
164
# Calculate the HEAD signature.
165
#   Note the need for a triple \n
166
#   Is that because there is no contentType ?
167
#
168
stringToSign="HEAD\n\n\n${dateValue}\n${resource}"
169
signature=$(
170
    echo -en "${stringToSign}" |
171
    openssl sha1 -hmac "${aws_secret_access_key}" -binary |
172
    base64
173
)
174
 
175
#set -x
176
fileTest=0
177
[ $verbose -gt 1 ] && echo "Testing file presence: ${file}"
178
results=$(curl -I -X HEAD \
179
        -s \
180
         --insecure \
181
        -H "Host: ${bucket}.s3.amazonaws.com" \
182
        -H "Date: ${dateValue}" \
183
        -H "Authorization: AWS ${aws_access_key_id}:${signature}" \
184
        "https://${bucket}.s3.amazonaws.com/${file}" \
185
        )
6128 dpurdie 186
[ $verbose -gt 2 ] && echo "Testing file response: ${results}"
5608 dpurdie 187
if [[ "$results" =~ "HTTP/1.1 200 OK" ]]; then
188
    fileTest=1
189
fi
190
 
191
# Display results
192
if [ $fileTest -gt 0 ]; then
193
    if [ $verbose -gt 1 ] ; then
194
        echo "${ProgName}: Package Version Exists: $pkgName/$pkgVer" 
195
    fi
196
else
197
    echo "${ProgName}: Error cannot access $pkgName/$pkgVer in S3 bucket ${bucket}"
198
    exit 1
199
fi
200
 
201
# Ensure correct storage class
6128 dpurdie 202
#   STANDARD_IA - Good
203
#   REDUCED_REDUNDANCY - Good
204
#   GLACIER - May be good
205
#       If it has been restored, then its good
206
#       Else its an error
207
#       Restored status is held in x-amz-restore attribute
208
#           When it exists the file is restored or is being restored
209
#           When the 'ongoing-request' is false, then it has been restored
210
canGet=false
211
mustRestore=false
212
message=""
5608 dpurdie 213
storageClass=$( echo $results | tr '\r' '\n' | awk -F: '/x-amz-storage-class/{print $2}')
214
[ $verbose -gt 0 ] && echo storageClass : $storageClass
5805 dpurdie 215
if [[ "$storageClass" != " REDUCED_REDUNDANCY" &&  "$storageClass" != " STANDARD_IA" ]]; then
6128 dpurdie 216
    if [[ "$storageClass" == " GLACIER" ]]; then
217
        [ $verbose -gt 1 ] && echo "$pkgName/$pkgVer has been transferred to glacier"
218
        glacierState="In Glacier"
219
        RestoreData=$( echo $results | tr '\r' '\n' | awk -F: '/x-amz-restore/{print $2,$3,$4,$5,$6,$7,$8,$9}')
220
        if [ -n "$RestoreData" ] ; then
221
            [ $verbose -gt 1 ] && echo "$pkgName/$pkgVer Restored progress: $RestoreData"
222
            ongoingRequest=$( echo "$RestoreData" | sed -n 's/.*ongoing-request="\([^"]*\)".*'/\\1/p)
223
            expiryDate=$( echo "$RestoreData" | sed -n 's/.*expiry-date="\([^"]*\)".*'/\\1/p )
224
            [ $verbose -gt 1 ] && echo "$pkgName/$pkgVer Restored State: $ongoingRequest"
225
            [ $verbose -gt 1 ] && echo "$pkgName/$pkgVer Restored Expiry Date: $expiryDate"
226
            if [ "$ongoingRequest" != "false" ] ; then
227
                glacierState="Restore in progress"
228
                message="Restore not complete: ongoing-request=$ongoingRequest"
229
            else
230
                glacierState="Restored"
231
                canGet=true
232
            fi
233
        else
234
            message="Incorrect storage class: '$storageClass'"
235
            mustRestore="true"        
236
        fi
237
        [ $verbose -gt 0 ] && echo "glacierState : $glacierState"
238
    else
239
        message="Unhandled storage class: '$storageClass'"        
240
    fi
241
else
242
    canGet=true
5608 dpurdie 243
fi
244
 
6128 dpurdie 245
##############################################################
246
#   Initiate a Restore from Glacier
247
#
248
if $mustRestore ; then
249
    if [ 1 ] ; then
250
        [ $verbose -gt 0 ] && echo "Initiate restore from Glacier $pkgName/$pkgVer"
251
 
252
        # Generate a Restore Request
253
        #   And an MD5 over the data
254
        tmpData=$( mktemp )
255
        echo > $tmpData '<RestoreRequest>'
256
        echo >>$tmpData '  <Days>1</Days>'
257
        echo >>$tmpData '  <GlacierJobParameters>'
258
        echo >>$tmpData '    <Tier>Standard</Tier>'
259
        echo >>$tmpData '  </GlacierJobParameters>'
260
        echo >>$tmpData '</RestoreRequest>'
261
 
262
        md5Value=$(
263
            openssl md5 -binary $tmpData |
264
            base64
265
        )
266
 
267
        # Generate the request signature
268
        contentType="application/xml"
269
        stringToSign="POST\n${md5Value}\n${contentType}\n${dateValue}\n${resource}?restore"
270
        signature=$(
271
            echo -en "${stringToSign}" |
272
            openssl sha1 -hmac "${aws_secret_access_key}" -binary |
273
            base64
274
        )
275
 
276
        #set -x
277
        tmpResult=$( mktemp )
278
        results=$(curl -s -w '%{http_code}' -o $tmpResult\
279
             --insecure \
280
             --data @$tmpData \
281
            -H "Host: ${bucket}.s3.amazonaws.com" \
282
            -H "Date: ${dateValue}" \
283
            -H "Content-MD5: ${md5Value}" \
284
            -H "Authorization: AWS ${aws_access_key_id}:${signature}" \
285
            -H "Content-Type: ${contentType}" \
286
            "https://${bucket}.s3.amazonaws.com/${file}?restore"
287
            )
288
 
289
        canGet=false
290
        if [[ "$results" == "200" ]] ; then
291
            canGet=true
292
        elif [[ "$results" == "202" ]] ; then
293
            message="Restore from Glacier initiated"
294
        elif [[ "$results" == "409" ]] ; then
295
            message="Restore already in progress"
296
        elif [[ "$results" == "503" ]] ; then
297
            message="Glacier expedited retrievals are currently not available"
298
        else
299
            mesage="Error previously reported"
300
            echo "Glacier restore error code: $results"
301
            tail -n+2 $tmpResult | fold | awk '{print "    " $0}'
302
        fi                              
303
        set +x
304
        rm -rf $tmpData $tmpResult
305
 
306
    fi
307
fi
308
 
309
if ! $canGet; then
310
        echo "${ProgName}: Error cannot access $pkgName/$pkgVer. $message"
311
        echo "Resource: $resource"
312
        exit 1
313
fi
314
 
5608 dpurdie 315
#############################################################
316
# GET!
317
 
318
# Calculate the signature.
319
#   Note the need for a triple \n
320
#   Needed becase there is no content type
321
stringToSign="GET\n\n\n${dateValue}\n${resource}"
322
signature=$(
323
    echo -en "${stringToSign}" |
324
    openssl sha1 -hmac "${aws_secret_access_key}" -binary |
325
    base64
326
)
327
 
328
#echo dateValue: ${dateValue} 
329
#echo stringToSign: ${stringToSign}
330
#echo signature: ${signature}
331
#exit 1
332
 
333
mkdir -p $dpkgPath
334
if [  ! -d $dpkgPath ] ; then
335
    echo "Error: Could not create: $dpkgPath"
336
    exit 1
337
fi
338
 
339
if [ 1 ] ; then
340
[ $verbose -gt 0 ] && echo "Transfer $pkgName/$pkgVer from bucket $bucket"
341
#set -x
342
    curl -s \
343
        -X GET \
344
         --insecure \
345
        -H "Host: ${bucket}.s3.amazonaws.com" \
346
        -H "Date: ${dateValue}" \
347
        -H "Authorization: AWS ${aws_access_key_id}:${signature}" \
348
        "https://${bucket}.s3.amazonaws.com/${file}" \
349
        | tar -xz --strip=2 -C $dpkgPath
350
fi
351
 
352
if [ ! -f "$dpkgPath/descpkg" ] ; then
353
    echo "Error: Target PV did not populate as expected: $dpkgPath"
354
 
355
    # Remove if not correctly formatted
356
    chmod -R +w $dpkgPath
357
    rm -rf $dpkgPath
358
    exit 1
6128 dpurdie 359
else
360
    # Package extracted
361
    # Touch the top directory so that it will not be quarantined immediatly
362
    chmod +w "$dpkgPath"
363
    chmod -w "$dpkgPath"
5608 dpurdie 364
fi
365
 
366
[ $verbose -gt 0 ] && echo "Transfer complete"
367
 
368
 
369
 
370