azureStorageClientUtils.ts 8.79 KB
Newer Older
liuzhe-lz's avatar
liuzhe-lz committed
1
2
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
SparkSnail's avatar
SparkSnail committed
3
4
5

'use strict';

6
7
import * as azureStorage from 'azure-storage';
import * as fs from 'fs';
SparkSnail's avatar
SparkSnail committed
8
9
import * as path from 'path';
import { Deferred } from 'ts-deferred';
10
import { String } from 'typescript-string-operations';
SparkSnail's avatar
SparkSnail committed
11
12
13
14
import { getLogger } from '../../common/log';
import { mkDirP } from '../../common/utils';

export namespace AzureStorageClientUtility {
15

SparkSnail's avatar
SparkSnail committed
16
17
    /**
     * create azure share
18
19
     * @param fileServerClient
     * @param azureShare
SparkSnail's avatar
SparkSnail committed
20
     */
21
22
    export async function createShare(fileServerClient: any, azureShare: any): Promise<boolean> {
        const deferred: Deferred<boolean> = new Deferred<boolean>();
23
24
25
26
        fileServerClient.createShareIfNotExists(azureShare, (error: any, result: any, response: any) => {
            if (error) {
                getLogger()
                  .error(`Create share failed:, ${error}`);
27
                deferred.resolve(false);
28
            } else {
29
                deferred.resolve(true);
SparkSnail's avatar
SparkSnail committed
30
            }
31
32
        });

SparkSnail's avatar
SparkSnail committed
33
34
        return deferred.promise;
    }
35

SparkSnail's avatar
SparkSnail committed
36
37
    /**
     * Create a new directory (NOT recursively) in azure file storage.
38
39
40
     * @param fileServerClient
     * @param azureFoler
     * @param azureShare
SparkSnail's avatar
SparkSnail committed
41
     */
42
43
    export async function createDirectory(fileServerClient: azureStorage.FileService, azureFoler: any, azureShare: any): Promise<boolean> {
        const deferred: Deferred<boolean> = new Deferred<boolean>();
44
45
46
47
        fileServerClient.createDirectoryIfNotExists(azureShare, azureFoler, (error: any, result: any, response: any) => {
            if (error) {
                getLogger()
                  .error(`Create directory failed:, ${error}`);
48
                deferred.resolve(false);
49
            } else {
50
                deferred.resolve(true);
SparkSnail's avatar
SparkSnail committed
51
            }
52
        });
SparkSnail's avatar
SparkSnail committed
53
54
55
56
57
58
        return deferred.promise;
    }

    /**
     * Create a new directory recursively in azure file storage
     * @param fileServerClient
59
     * @param azureDirectory
SparkSnail's avatar
SparkSnail committed
60
     */
61
    export async function createDirectoryRecursive(fileServerClient: azureStorage.FileService, azureDirectory: string,
62
63
                                                   azureShare: any): Promise<boolean> {
        const deferred: Deferred<boolean> = new Deferred<boolean>();
64
65
66
        const directories: string[] = azureDirectory.split('/');
        let rootDirectory: string = '';
        for (const directory of directories) {
SparkSnail's avatar
SparkSnail committed
67
            rootDirectory += directory;
chicm-ms's avatar
chicm-ms committed
68
            const result: boolean = await createDirectory(fileServerClient, rootDirectory, azureShare);
69
70
71
72
            if (!result) {
                deferred.resolve(false);
                return deferred.promise;
            }
SparkSnail's avatar
SparkSnail committed
73
74
            rootDirectory += '/';
        }
75
        deferred.resolve(true);
76

SparkSnail's avatar
SparkSnail committed
77
78
        return deferred.promise;
    }
79

SparkSnail's avatar
SparkSnail committed
80
81
    /**
     * upload a file to azure storage
82
83
84
85
86
     * @param fileServerClient
     * @param azureDirectory
     * @param azureFileName
     * @param azureShare
     * @param localFilePath
SparkSnail's avatar
SparkSnail committed
87
     */
88
    async function uploadFileToAzure(fileServerClient: any, azureDirectory: string, azureFileName: any, azureShare: any,
89
90
                                     localFilePath: string): Promise<boolean> {
        const deferred: Deferred<boolean> = new Deferred<boolean>();
91
92
93
94
95
        await fileServerClient.createFileFromLocalFile(azureShare, azureDirectory, azureFileName, localFilePath,
                                                       (error: any, result: any, response: any) => {
            if (error) {
                getLogger()
                  .error(`Upload file failed:, ${error}`);
96
                deferred.resolve(false);
97
            } else {
98
                deferred.resolve(true);
SparkSnail's avatar
SparkSnail committed
99
            }
100
101
        });

SparkSnail's avatar
SparkSnail committed
102
103
        return deferred.promise;
    }
104

SparkSnail's avatar
SparkSnail committed
105
106
    /**
     * download a file from azure storage
107
108
109
110
111
     * @param fileServerClient
     * @param azureDirectory
     * @param azureFileName
     * @param azureShare
     * @param localFilePath
SparkSnail's avatar
SparkSnail committed
112
     */
113
    async function downloadFile(fileServerClient: any, azureDirectory: string, azureFileName: any, azureShare: any,
114
115
                                localFilePath: string): Promise<boolean> {
        const deferred: Deferred<boolean> = new Deferred<boolean>();
116
117
118
119
120
        await fileServerClient.getFileToStream(azureShare, azureDirectory, azureFileName, fs.createWriteStream(localFilePath),
                                               (error: any, result: any, response: any) => {
            if (error) {
                getLogger()
                  .error(`Download file failed:, ${error}`);
121
                deferred.resolve(false);
122
            } else {
123
                deferred.resolve(true);
SparkSnail's avatar
SparkSnail committed
124
            }
125
126
        });

SparkSnail's avatar
SparkSnail committed
127
128
129
130
131
132
133
134
135
136
        return deferred.promise;
    }

    /**
     * Upload a directory to azure file storage
     * @param fileServerClient : the client of file server
     * @param azureDirectory : the directory in azure file storage
     * @param azureShare : the azure share used
     * @param localDirectory : local directory to be uploaded
     */
137
    export async function uploadDirectory(fileServerClient: azureStorage.FileService, azureDirectory: string, azureShare: any,
138
139
                                          localDirectory: string): Promise<boolean> {
        const deferred: Deferred<boolean> = new Deferred<boolean>();
SparkSnail's avatar
SparkSnail committed
140
        const fileNameArray: string[] = fs.readdirSync(localDirectory);
chicm-ms's avatar
chicm-ms committed
141
        const result: boolean = await createDirectoryRecursive(fileServerClient, azureDirectory, azureShare);
142
143
144
145
        if (!result) {
            deferred.resolve(false);
            return deferred.promise;
        }
146
        for (const fileName of fileNameArray) {
SparkSnail's avatar
SparkSnail committed
147
148
            const fullFilePath: string = path.join(localDirectory, fileName);
            try {
149
150
                let resultUploadFile: boolean = true;
                let resultUploadDir: boolean = true;
151
152
                if (fs.lstatSync(fullFilePath)
                      .isFile()) {
153
                    resultUploadFile = await uploadFileToAzure(fileServerClient, azureDirectory, fileName, azureShare, fullFilePath);
SparkSnail's avatar
SparkSnail committed
154
155
                } else {
                    // If filePath is a directory, recuisively copy it to azure
156
157
158
159
160
                    resultUploadDir = await uploadDirectory(fileServerClient, String.Format('{0}/{1}', azureDirectory, fileName), azureShare, fullFilePath);
                }
                if (!(resultUploadFile && resultUploadDir)) {
                    deferred.resolve(false);
                    return deferred.promise;
SparkSnail's avatar
SparkSnail committed
161
                }
162
            } catch (error) {
163
                deferred.resolve(false);
164

SparkSnail's avatar
SparkSnail committed
165
166
167
168
                return deferred.promise;
            }
        }
        // All files/directories are copied successfully, resolve
169
        deferred.resolve(true);
170

SparkSnail's avatar
SparkSnail committed
171
172
        return deferred.promise;
    }
173

SparkSnail's avatar
SparkSnail committed
174
175
    /**
     * downlod a directory from azure
176
177
178
179
     * @param fileServerClient
     * @param azureDirectory
     * @param azureShare
     * @param localDirectory
SparkSnail's avatar
SparkSnail committed
180
     */
181
182
    export async function downloadDirectory(fileServerClient: any, azureDirectory: string, azureShare: any, localDirectory: string):
     Promise<void> {
SparkSnail's avatar
SparkSnail committed
183
        const deferred: Deferred<void> = new Deferred<void>();
184
185
186
187
188
189
        await mkDirP(localDirectory);
        fileServerClient.listFilesAndDirectoriesSegmented(azureShare, azureDirectory, 'null',
                                                          async (error: any, result: any, response: any) => {
            if (('entries' in result) === false) {
                getLogger()
                  .error(`list files failed, can't get entries in result`);
SparkSnail's avatar
SparkSnail committed
190
191
192
                throw new Error(`list files failed, can't get entries in result`);
            }

193
194
195
            if (('files' in result.entries) === false) {
                getLogger()
                  .error(`list files failed, can't get files in result['entries']`);
SparkSnail's avatar
SparkSnail committed
196
197
198
                throw new Error(`list files failed, can't get files in result['entries']`);
            }

199
200
201
            if (('directories' in result.directories) === false) {
                getLogger()
                  .error(`list files failed, can't get directories in result['entries']`);
SparkSnail's avatar
SparkSnail committed
202
203
204
                throw new Error(`list files failed, can't get directories in result['entries']`);
            }

205
            for (const fileName of result.entries.files) {
SparkSnail's avatar
SparkSnail committed
206
                const fullFilePath: string = path.join(localDirectory, fileName.name);
207
                await downloadFile(fileServerClient, azureDirectory, fileName.name, azureShare, fullFilePath);
SparkSnail's avatar
SparkSnail committed
208
            }
209

210
211
212
213
            for (const directoryName of result.entries.directories) {
                const fullDirectoryPath: string = path.join(localDirectory, directoryName.name);
                const fullAzureDirectory: string = path.join(azureDirectory, directoryName.name);
                await downloadDirectory(fileServerClient, fullAzureDirectory, azureShare, fullDirectoryPath);
SparkSnail's avatar
SparkSnail committed
214
215
            }
            deferred.resolve();
216
217
        });

SparkSnail's avatar
SparkSnail committed
218
219
220
        return deferred.promise;
    }
}