Statistics
| Branch: | Tag: | Revision:

root / Classes / AccountManager.m @ 38d59b6c

History | View | Annotate | Download (42.3 kB)

1
//
2
//  AccountManager.m
3
//  OpenStack
4
//
5
//  Created by Mike Mayo on 10/21/10.
6
//  The OpenStack project is provided under the Apache 2.0 license.
7
//
8

    
9
#import "AccountManager.h"
10
#import "OpenStackAccount.h"
11
#import "OpenStackRequest.h"
12
#import "Server.h"
13
#import "Provider.h"
14
#import "Image.h"
15
#import "Container.h"
16
#import "Folder.h"
17
#import "StorageObject.h"
18
#import "GetServersRequest.h"
19
#import "GetContainersRequest.h"
20
#import "GetObjectsRequest.h"
21
#import "GetImagesRequest.h"
22
#import "ASINetworkQueue.h"
23
#import "UpdateCDNContainerRequest.h"
24
#import "GetFlavorsRequest.h"
25
#import "LoadBalancer.h"
26
#import "LoadBalancerRequest.h"
27
#import "APICallback.h"
28
#import "Analytics.h"
29

    
30

    
31
@implementation AccountManager
32

    
33
@synthesize account, queue;
34

    
35
#pragma mark - Callbacks
36

    
37
- (APICallback *)callbackWithRequest:(id)request success:(APIResponseBlock)success failure:(APIResponseBlock)failure {
38
    APICallback *callback = [[[APICallback alloc] initWithAccount:self.account request:request] autorelease];
39
    ((OpenStackRequest *)request).delegate = self;
40
    ((OpenStackRequest *)request).callback = callback;    
41
    [request setCompletionBlock:^{
42
        if ([request isSuccess]) {
43
            success(request);
44
            [request notify];
45
        } else {
46
            failure(request);
47
            [request notify];
48
        }
49
    }];
50
    [request setFailedBlock:^{
51
        failure(request);
52
        [request notify];
53
    }];
54
    [request startAsynchronous];    
55
    return callback;
56
}
57

    
58
- (APICallback *)callbackWithRequest:(id)request success:(APIResponseBlock)success {
59
    return [self callbackWithRequest:request success:success failure:^(OpenStackRequest *request){}];
60
}
61

    
62
- (APICallback *)callbackWithRequest:(id)request {
63
    return [self callbackWithRequest:request success:^(OpenStackRequest *request){} failure:^(OpenStackRequest *request){}];
64
}
65

    
66
#pragma mark - Notification
67

    
68
- (NSString *)notificationName:(NSString *)key identifier:(NSString *)identifier {
69
    return [NSString stringWithFormat:@"%@-%@-%i", key, self.account.uuid, identifier];
70
}
71

    
72
- (void)requestFinished:(OpenStackRequest *)request {
73
    NSString *notificationName = [request.userInfo objectForKey:@"notificationName"];
74
    id notificationObject = [request.userInfo objectForKey:@"notificationObject"];
75
    
76
    if ([request isSuccess]) {
77
        NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Succeeded", notificationName] object:notificationObject];
78
        [[NSNotificationCenter defaultCenter] postNotification:notification];
79
    } else {
80
        NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Failed", notificationName] object:notificationObject userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
81
        [[NSNotificationCenter defaultCenter] postNotification:notification];
82
    }
83
}
84

    
85
- (void)requestFailed:(OpenStackRequest *)request {
86
    NSString *notificationName = [request.userInfo objectForKey:@"notificationName"];
87
    id notificationObject = [request.userInfo objectForKey:@"notificationObject"];
88
    NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Failed", notificationName] object:notificationObject userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
89
    [[NSNotificationCenter defaultCenter] postNotification:notification];
90
}
91

    
92
- (void)sendRequest:(OpenStackRequest *)request name:(NSString *)name object:(id)notificationObject {
93
    request.delegate = self;
94
    request.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:name, notificationObject, nil] forKeys:[NSArray arrayWithObjects:@"notificationName", @"notificationObject", nil]];
95
    [request startAsynchronous];
96
}
97

    
98
- (void)notify:(NSString *)name request:(OpenStackRequest *)request {
99
    NSNotification *notification = [NSNotification notificationWithName:name object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
100
    [[NSNotificationCenter defaultCenter] postNotification:notification];
101
}
102

    
103
- (void)notify:(NSString *)name request:(OpenStackRequest *)request object:(id)object {
104
    NSNotification *notification = [NSNotification notificationWithName:name object:object userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
105
    [[NSNotificationCenter defaultCenter] postNotification:notification];
106
}
107

    
108
#pragma mark - API Calls
109

    
110
#pragma mark Get Limits
111

    
112
- (void)getLimits {
113
    __block OpenStackRequest *request = [OpenStackRequest getLimitsRequest:self.account];
114
    request.delegate = self;
115
    [request setCompletionBlock:^{
116
        if ([request isSuccess] && [request limits]) {
117
            self.account.rateLimits = [request rateLimits];
118
            [self.account persist];
119
            [self notify:@"getLimitsSucceeded" request:request object:self.account];
120
        } else {
121
            [self notify:@"getLimitsFailed" request:request object:self.account];
122
        }
123
    }];
124
    [request setFailedBlock:^{
125
        [self notify:@"getLimitsFailed" request:request object:self.account];
126
    }];    
127
    [request startAsynchronous];
128
}
129

    
130
#pragma mark Reboot Server
131

    
132
- (void)softRebootServer:(Server *)server {
133
    TrackEvent(CATEGORY_SERVER, EVENT_REBOOTED);
134
    
135
    __block OpenStackRequest *request = [OpenStackRequest softRebootServerRequest:self.account server:server];
136
    request.delegate = self;
137
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
138
    [request setCompletionBlock:^{
139
        [self notify:([request isSuccess] ? @"rebootSucceeded" : @"rebootFailed") request:request object:[request.userInfo objectForKey:@"server"]];
140
    }];
141
    [request setFailedBlock:^{
142
        [self notify:@"rebootFailed" request:request object:[request.userInfo objectForKey:@"server"]];
143
    }];
144
    [request startAsynchronous];    
145
}
146

    
147
- (void)hardRebootServer:(Server *)server {
148
    TrackEvent(CATEGORY_SERVER, EVENT_REBOOTED);
149
    
150
    __block OpenStackRequest *request = [OpenStackRequest hardRebootServerRequest:self.account server:server];
151
    request.delegate = self;
152
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
153
    [request setCompletionBlock:^{
154
        [self notify:([request isSuccess] ? @"rebootSucceeded" : @"rebootFailed") request:request object:[request.userInfo objectForKey:@"server"]];
155
    }];
156
    [request setFailedBlock:^{
157
        [self notify:@"rebootFailed" request:request object:[request.userInfo objectForKey:@"server"]];
158
    }];
159
    [request startAsynchronous];
160
}
161

    
162
#pragma mark Change Admin Password
163

    
164
- (void)changeAdminPassword:(Server *)server password:(NSString *)password {
165
    TrackEvent(CATEGORY_SERVER, EVENT_PASSWORD_CHANGED);
166
    
167
    __block OpenStackRequest *request = [OpenStackRequest changeServerAdminPasswordRequest:self.account server:server password:password];
168
    request.delegate = self;
169
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
170
    [request setCompletionBlock:^{
171
        [self notify:([request isSuccess] ? @"changeAdminPasswordSucceeded" : @"changeAdminPasswordFailed") request:request object:[request.userInfo objectForKey:@"server"]];
172
    }];
173
    [request setFailedBlock:^{
174
        [self notify:@"changeAdminPasswordFailed" request:request object:[request.userInfo objectForKey:@"server"]];
175
    }];
176
    [request startAsynchronous];
177
}
178

    
179
#pragma mark Rename Server
180

    
181
- (APICallback *)renameServer:(Server *)server name:(NSString *)name {
182
    TrackEvent(CATEGORY_SERVER, EVENT_RENAMED);
183
    
184
    __block OpenStackRequest *request = [OpenStackRequest renameServerRequest:self.account server:server name:name];
185
    return [self callbackWithRequest:request];
186
}
187

    
188
#pragma mark Delete Server
189

    
190
- (void)deleteServer:(Server *)server {
191
    TrackEvent(CATEGORY_SERVER, EVENT_DELETED);
192
    
193
    __block OpenStackRequest *request = [OpenStackRequest deleteServerRequest:self.account server:server];
194
    request.delegate = self;
195
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
196
    [request setCompletionBlock:^{
197
        [self notify:([request isSuccess] ? @"deleteServerSucceeded" : @"deleteServerFailed") request:request object:[request.userInfo objectForKey:@"server"]];        
198
        [self notify:([request isSuccess] ? @"deleteServerSucceeded" : @"deleteServerFailed") request:request object:self.account];
199
    }];
200
    [request setFailedBlock:^{
201
        [self notify:@"deleteServerFailed" request:request object:[request.userInfo objectForKey:@"server"]];        
202
    }];
203
    if (![self queue]) {
204
        [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
205
    }
206
    [queue addOperation:request];    
207
}
208

    
209
#pragma mark Create Server
210

    
211
- (void)createServer:(Server *)server {
212
    TrackEvent(CATEGORY_SERVER, EVENT_CREATED);
213
    
214
    __block OpenStackRequest *request = [OpenStackRequest createServerRequest:self.account server:server];
215
    request.delegate = self;
216
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
217
    
218
    // TODO: make these success block and failure block with "response" arg
219
    [request setCompletionBlock:^{
220
        NSLog(@"create server response: %i - %@", request.responseStatusCode, request.responseStatusMessage);
221
        NSLog(@"body: %@", [request responseString]);            
222
        [self notify:([request isSuccess] ? @"createServerSucceeded" : @"createServerFailed") request:request object:[request.userInfo objectForKey:@"server"]];        
223
        [self notify:([request isSuccess] ? @"createServerSucceeded" : @"createServerFailed") request:request object:self.account];
224
    }];    
225
    [request setFailedBlock:^{
226
        NSLog(@"create server response: %i - %@", request.responseStatusCode, request.responseStatusMessage);
227
        NSLog(@"body: %@", [request responseString]);            
228
        [self notify:@"createServerFailed" request:request object:[request.userInfo objectForKey:@"server"]];        
229
    }];
230
    if (![self queue]) {
231
        [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
232
    }
233
    [queue addOperation:request];
234
}
235

    
236
#pragma mark Resize Server
237

    
238
- (void)resizeServer:(Server *)server flavor:(Flavor *)flavor {
239
    TrackEvent(CATEGORY_SERVER, EVENT_RESIZED);
240
    
241
    __block OpenStackRequest *request = [OpenStackRequest resizeServerRequest:self.account server:server flavor:flavor];
242
    request.delegate = self;
243
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
244
    [request setCompletionBlock:^{
245
        NSString *name = [request isSuccess] ? @"resizeServerSucceeded" : @"resizeServerFailed";
246
        NSNotification *notification = [NSNotification notificationWithName:[self notificationName:name identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
247
        [[NSNotificationCenter defaultCenter] postNotification:notification];
248
    }];
249
    [request setFailedBlock:^{
250
        NSNotification *notification = [NSNotification notificationWithName:[self notificationName:@"resizeServerFailed" identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
251
        [[NSNotificationCenter defaultCenter] postNotification:notification];
252
    }];
253
    [request startAsynchronous];
254
}
255

    
256
- (void)confirmResizeServer:(Server *)server {
257
    __block OpenStackRequest *request = [OpenStackRequest confirmResizeServerRequest:self.account server:server];
258
    request.delegate = self;
259
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
260
    [request setCompletionBlock:^{
261
        NSString *name = [request isSuccess] ? @"confirmResizeServerSucceeded" : @"confirmResizeServerFailed";
262
        NSNotification *notification = [NSNotification notificationWithName:[self notificationName:name identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
263
        [[NSNotificationCenter defaultCenter] postNotification:notification];
264
    }];
265
    [request setFailedBlock:^{
266
        NSNotification *notification = [NSNotification notificationWithName:[self notificationName:@"confirmResizeServerFailed" identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
267
        [[NSNotificationCenter defaultCenter] postNotification:notification];
268
        
269
    }];
270
    [request startAsynchronous];
271
}
272

    
273
- (void)revertResizeServer:(Server *)server {
274
    __block OpenStackRequest *request = [OpenStackRequest revertResizeServerRequest:self.account server:server];
275
    request.delegate = self;
276
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
277
    [request setCompletionBlock:^{
278
        NSString *name = [request isSuccess] ? @"revertResizeServerSucceeded" : @"revertResizeServerFailed";
279
        NSNotification *notification = [NSNotification notificationWithName:[self notificationName:name identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
280
        [[NSNotificationCenter defaultCenter] postNotification:notification];
281
    }];
282
    [request setFailedBlock:^{
283
        NSNotification *notification = [NSNotification notificationWithName:[self notificationName:@"revertResizeServerFailed" identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
284
        [[NSNotificationCenter defaultCenter] postNotification:notification];
285
    }];
286
    [request startAsynchronous];
287
}
288

    
289
- (void)rebuildServer:(Server *)server image:(Image *)image {
290
    TrackEvent(CATEGORY_SERVER, EVENT_REBUILT);
291
    
292
    __block OpenStackRequest *request = [OpenStackRequest rebuildServerRequest:self.account server:server image:image];
293
    request.delegate = self;
294
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
295
    [request setCompletionBlock:^{
296
        NSString *name = [request isSuccess] ? @"rebuildServerSucceeded" : @"rebuildServerFailed";
297
        NSNotification *notification = [NSNotification notificationWithName:[self notificationName:name identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
298
        [[NSNotificationCenter defaultCenter] postNotification:notification];
299
    }];
300
    [request setFailedBlock:^{
301
        NSNotification *notification = [NSNotification notificationWithName:[self notificationName:@"rebuildServerFailed" identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
302
        [[NSNotificationCenter defaultCenter] postNotification:notification];
303
    }];
304
    [request startAsynchronous];
305
}
306

    
307
- (void)getBackupSchedule:(Server *)server {
308
    __block OpenStackRequest *request = [OpenStackRequest getBackupScheduleRequest:self.account server:server];
309
    request.delegate = self;
310
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
311
    [request setCompletionBlock:^{
312
        server.backupSchedule = [request backupSchedule];
313
        [self notify:([request isSuccess] ? @"getBackupScheduleSucceeded" : @"getBackupScheduleFailed") request:request object:[request.userInfo objectForKey:@"server"]];
314
    }];
315
    [request setFailedBlock:^{
316
        [self notify:@"getBackupScheduleFailed" request:request object:[request.userInfo objectForKey:@"server"]];        
317
    }];
318
    [request startAsynchronous];
319
}
320

    
321
- (void)updateBackupSchedule:(Server *)server {
322
    TrackEvent(CATEGORY_SERVER, EVENT_BACKUP_SCHEDULE_CHANGED);
323
    
324
    __block OpenStackRequest *request = [OpenStackRequest updateBackupScheduleRequest:self.account server:server];
325
    request.delegate = self;
326
    request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"];
327
    [request setCompletionBlock:^{
328
        [self notify:([request isSuccess] ? @"updateBackupScheduleSucceeded" : @"updateBackupScheduleFailed") request:request object:[request.userInfo objectForKey:@"server"]];
329
        [self notify:([request isSuccess] ? @"updateBackupScheduleSucceeded" : @"updateBackupScheduleFailed") request:request object:self.account];
330
    }];
331
    [request setFailedBlock:^{
332
        [self notify:@"updateBackupScheduleFailed" request:request object:[request.userInfo objectForKey:@"server"]];        
333
        [self notify:@"updateBackupScheduleFailed" request:request object:self.account];        
334
    }];
335
    [request startAsynchronous];
336
}
337

    
338
#pragma mark Get Image
339

    
340
- (void)getImage:(Server *)server {
341
    __block OpenStackRequest *request = [OpenStackRequest getImageRequest:self.account imageId:server.imageId];
342
    request.delegate = self;
343
    request.userInfo = [NSDictionary dictionaryWithObject:server.imageId forKey:@"imageId"];
344
    [request setCompletionBlock:^{
345
        if ([request isSuccess]) {
346
            Image *image = [request image];
347
            if ([image isKindOfClass:[Image class]]) {
348
                image.canBeLaunched = NO;
349
                [self.account.images setObject:image forKey:image.identifier];        
350
                [self.account persist];        
351
            }
352
            [self notify:@"getImageSucceeded" request:request];
353
        } else {
354
            [self notify:@"getImageFailed" request:request object:[request.userInfo objectForKey:@"imageId"]];
355
        }
356
    }];
357
    [request setFailedBlock:^{
358
        [self notify:@"getImageFailed" request:request object:[request.userInfo objectForKey:@"imageId"]];
359
    }];
360
    [request startAsynchronous];
361
}
362

    
363
#pragma mark Get Servers
364

    
365
- (void)getServers {
366
    if (![self queue]) {
367
        [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
368
    }
369
    GetServersRequest *request = [GetServersRequest request:self.account];
370
    [queue addOperation:request];
371
}
372

    
373
- (APICallback *)getServersWithCallback {
374
    __block OpenStackRequest *request = [OpenStackRequest serversRequest:self.account method:@"GET" path:@"/servers/detail"];
375
    return [self callbackWithRequest:request];
376
}
377

    
378

    
379
#pragma mark Get Flavors
380

    
381
- (void)getFlavors {
382
    if (![self queue]) {
383
        [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
384
    }
385
    GetFlavorsRequest *request = [GetFlavorsRequest request:self.account];
386
    [queue addOperation:request];
387
}
388

    
389
#pragma mark Get Images
390

    
391
- (void)getImages {
392
    if (![self queue]) {
393
        [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
394
    }
395
    GetImagesRequest *request = [GetImagesRequest request:self.account];
396
    [queue addOperation:request];
397
}
398

    
399
#pragma mark -
400
#pragma mark Object Storage
401

    
402
- (void)getStorageAccountInfo {
403
    __block OpenStackRequest *request = [OpenStackRequest getStorageAccountInfoRequest:self.account];
404
    
405
    request.delegate = self;
406
    [request setCompletionBlock:^{
407
        if ([request isSuccess]) {
408
            self.account.containerCount = [[[request responseHeaders] objectForKey:@"X-Account-Container-Count"] intValue];
409
            NSString *numStr = [[request responseHeaders] objectForKey:@"X-Account-Bytes-Used"];
410
            self.account.totalBytesUsed = strtoull([numStr UTF8String], NULL, 0);
411
            [self.account persist];
412
            [self notify:@"getStorageAccountInfoSucceeded" request:request object:self.account];
413
        } else {
414
            [self notify:@"getStorageAccountInfoFailed" request:request object:self.account];
415
        }
416
    }];
417
    [request setFailedBlock:^{
418
        [self notify:@"getStorageAccountInfoFailed" request:request object:self.account];
419
    }];
420
    [request startAsynchronous];
421
}
422

    
423
- (void)getContainers {
424
    if (![self queue]) {
425
        [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
426
    }
427
    
428
    GetContainersRequest *request = [GetContainersRequest request:self.account];
429
    //[request startAsynchronous];
430
    [queue addOperation:request];
431
}
432

    
433
- (APICallback *)getContainersWithCallback {
434
    __block OpenStackRequest *request = [OpenStackRequest filesRequest:self.account method:@"GET" path:@""];
435
    return [self callbackWithRequest:request];    
436
}
437

    
438
- (void)createContainer:(Container *)container {
439
    TrackEvent(CATEGORY_CONTAINERS, EVENT_CREATED);
440
    
441
    OpenStackRequest *request = [OpenStackRequest createContainerRequest:self.account container:container];
442
    request.delegate = self;
443
    request.didFinishSelector = @selector(createContainerSucceeded:);
444
    request.didFailSelector = @selector(createContainerFailed:);
445
    request.userInfo = [NSDictionary dictionaryWithObject:container forKey:@"container"];
446
    [request startAsynchronous];
447
}
448

    
449
- (void)createContainerSucceeded:(OpenStackRequest *)request {
450
    if ([request isSuccess]) {        
451
        Container *container = [request.userInfo objectForKey:@"container"];
452
        [self.account.containers setObject:container forKey:container.name];        
453
        [self.account persist];
454
        self.account.containerCount = [self.account.containers count];
455
        [self notify:@"createContainerSucceeded" request:request object:self.account];
456
    } else {
457
        [self notify:@"createContainerFailed" request:request object:self.account];
458
    }
459
}
460

    
461
- (void)createContainerFailed:(OpenStackRequest *)request {
462
    [self notify:@"createContainerFailed" request:request object:self.account];
463
}
464

    
465
- (void)deleteContainer:(Container *)container {
466
    TrackEvent(CATEGORY_CONTAINERS, EVENT_DELETED);
467
    
468
    OpenStackRequest *request = [OpenStackRequest deleteContainerRequest:self.account container:container];
469
    request.delegate = self;
470
    request.didFinishSelector = @selector(deleteContainerSucceeded:);
471
    request.didFailSelector = @selector(deleteContainerFailed:);
472
    request.userInfo = [NSDictionary dictionaryWithObject:container forKey:@"container"];
473
    [request startAsynchronous];
474
}
475

    
476
- (void)deleteContainerSucceeded:(OpenStackRequest *)request {
477
    if ([request isSuccess] || [request responseStatusCode] == 404) {
478
        Container *container = [request.userInfo objectForKey:@"container"];
479
        [self.account.containers setObject:container forKey:container.name];                
480
        [self.account persist];        
481
        [self notify:@"deleteContainerSucceeded" request:request object:self.account];
482
        [self notify:@"deleteContainerSucceeded" request:request object:[request.userInfo objectForKey:@"container"]];
483
    } else {
484
        [self notify:@"deleteContainerFailed" request:request object:self.account];
485
        [self notify:@"deleteContainerFailed" request:request object:[request.userInfo objectForKey:@"container"]];
486
    }
487
}
488

    
489
- (void)deleteContainerFailed:(OpenStackRequest *)request {
490
    [self notify:@"deleteContainerFailed" request:request object:self.account];
491
    [self notify:@"deleteContainerFailed" request:request object:[request.userInfo objectForKey:@"container"]];
492
}
493

    
494
- (void)getObjects:(Container *)container {
495
    if (![self queue]) {
496
        [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
497
    }    
498
    GetObjectsRequest *request = [GetObjectsRequest request:self.account container:container];
499
    [queue addOperation:request];
500
}
501

    
502
- (void)updateCDNContainer:(Container *)container {
503
    TrackEvent(CATEGORY_CONTAINERS, EVENT_UPDATED);
504
    
505
    if (![self queue]) {
506
        [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
507
    }
508
    UpdateCDNContainerRequest *request = [UpdateCDNContainerRequest request:self.account container:container];
509
    [queue addOperation:request];
510
}
511

    
512
- (void)getObjectsSucceeded:(OpenStackRequest *)request {
513
    if ([request isSuccess]) {
514
        Container *container = [request.userInfo objectForKey:@"container"];
515
        NSMutableDictionary *objects = [request objects];
516
        container.rootFolder = [Folder folder];
517
        container.rootFolder.objects = objects;
518
        [self.account persist];
519

    
520
        NSNotification *notification = [NSNotification notificationWithName:@"getObjectsSucceeded" object:self.account userInfo:[NSDictionary dictionaryWithObject:container forKey:@"container"]];
521
        [[NSNotificationCenter defaultCenter] postNotification:notification];
522
    } else {
523
        NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
524
        [[NSNotificationCenter defaultCenter] postNotification:notification];
525
    }
526
}
527

    
528
- (void)getObjectsFailed:(OpenStackRequest *)request {
529
    NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
530
    [[NSNotificationCenter defaultCenter] postNotification:notification];
531
}
532

    
533
- (void)getObjectInfo:(Container *)container object:(StorageObject *)object {
534
    OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object];
535
    request.delegate = self;
536
    request.didFinishSelector = @selector(getObjectInfoSucceeded:);
537
    request.didFailSelector = @selector(getObjectInfoFailed:);
538
    request.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:container, object, nil] forKeys:[NSArray arrayWithObjects:@"container", @"object", nil]];
539
    [request startAsynchronous];
540
}
541

    
542
- (void)getObjectInfoSucceeded:(OpenStackRequest *)request {
543
    if ([request isSuccess]) {
544
    } else {
545
        NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
546
        [[NSNotificationCenter defaultCenter] postNotification:notification];
547
    }
548
}
549

    
550
- (void)getObjectInfoFailed:(OpenStackRequest *)request {
551
    NSNotification *notification = [NSNotification notificationWithName:@"getObjectInfoFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
552
    [[NSNotificationCenter defaultCenter] postNotification:notification];
553
}
554

    
555
- (void)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate {
556
    OpenStackRequest *request = [OpenStackRequest getObjectRequest:self.account container:container object:object];
557
    request.delegate = self;
558
    request.downloadProgressDelegate = downloadProgressDelegate;
559
    request.showAccurateProgress = YES;    
560
    request.didFinishSelector = @selector(getObjectSucceeded:);
561
    request.didFailSelector = @selector(getObjectFailed:);
562
    request.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:container, object, nil] forKeys:[NSArray arrayWithObjects:@"container", @"object", nil]];
563
    [request startAsynchronous];
564
}
565

    
566
- (void)getObjectSucceeded:(OpenStackRequest *)request {
567
    if ([request isSuccess]) {
568
        Container *container = [request.userInfo objectForKey:@"container"];
569
        StorageObject *object = [request.userInfo objectForKey:@"object"];
570
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
571
        NSString *documentsDirectory = [paths objectAtIndex:0];        
572
        NSString *shortPath = [NSString stringWithFormat:@"/%@/%@", container.name, object.fullPath];
573
        NSString *filePath = [documentsDirectory stringByAppendingString:shortPath];
574
        NSString *directoryPath = [filePath stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"/%@", object.name] withString:@""];
575

    
576
        NSFileManager *fileManager = [NSFileManager defaultManager];
577
        if ([fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil]) {
578
            NSData *data = [request responseData];
579
            if ([data writeToFile:filePath atomically:YES]) {
580
                NSNotification *notification = [NSNotification notificationWithName:@"getObjectSucceeded" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
581
                [[NSNotificationCenter defaultCenter] postNotification:notification];
582
            } else {
583
                NSNotification *notification = [NSNotification notificationWithName:@"getObjectFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
584
                [[NSNotificationCenter defaultCenter] postNotification:notification];
585
            }
586
        } else {
587
            NSNotification *notification = [NSNotification notificationWithName:@"getObjectFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
588
            [[NSNotificationCenter defaultCenter] postNotification:notification];
589
        }
590
    } else {
591
        NSNotification *notification = [NSNotification notificationWithName:@"getObjectFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
592
        [[NSNotificationCenter defaultCenter] postNotification:notification];
593
    }
594
}
595

    
596
- (void)getObjectFailed:(OpenStackRequest *)request {
597
    NSNotification *notification = [NSNotification notificationWithName:@"getObjectFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
598
    [[NSNotificationCenter defaultCenter] postNotification:notification];
599
}
600

    
601
- (void)writeObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate {
602
    TrackEvent(CATEGORY_FILES, EVENT_CREATED);
603
    
604
    OpenStackRequest *request = [OpenStackRequest writeObjectRequest:self.account container:container object:object];
605
    request.delegate = self;
606
    request.didFinishSelector = @selector(writeObjectSucceeded:);
607
    request.didFailSelector = @selector(writeObjectFailed:);
608
    request.uploadProgressDelegate = downloadProgressDelegate;
609
    request.showAccurateProgress = YES;
610
    request.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:container, object, nil] forKeys:[NSArray arrayWithObjects:@"container", @"object", nil]];
611
    [request startAsynchronous];
612
}
613

    
614
- (void)writeObjectSucceeded:(OpenStackRequest *)request {
615
    if ([request isSuccess]) {
616
        NSNotification *notification = [NSNotification notificationWithName:@"writeObjectSucceeded" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
617
        [[NSNotificationCenter defaultCenter] postNotification:notification];
618
    } else {
619
        NSNotification *notification = [NSNotification notificationWithName:@"writeObjectFailed" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
620
        [[NSNotificationCenter defaultCenter] postNotification:notification];
621
    }
622
}
623

    
624
- (void)writeObjectFailed:(OpenStackRequest *)request {
625
    NSNotification *notification = [NSNotification notificationWithName:@"writeObjectFailed" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
626
    [[NSNotificationCenter defaultCenter] postNotification:notification];
627
}
628

    
629
- (void)writeObjectMetadata:(Container *)container object:(StorageObject *)object {
630
    OpenStackRequest *request = [OpenStackRequest writeObjectMetadataRequest:self.account container:container object:object];
631
    request.delegate = self;
632
    request.didFinishSelector = @selector(writeObjectMetadataSucceeded:);
633
    request.didFailSelector = @selector(writeObjectMetadataFailed:);
634
    request.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:container, object, nil] forKeys:[NSArray arrayWithObjects:@"container", @"object", nil]];
635
    [request startAsynchronous];
636
}
637

    
638
- (void)writeObjectMetadataSucceeded:(OpenStackRequest *)request {
639
    if ([request isSuccess]) {
640
        NSNotification *notification = [NSNotification notificationWithName:@"writeObjectMetadataSucceeded" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
641
        [[NSNotificationCenter defaultCenter] postNotification:notification];
642
    } else {
643
        NSNotification *notification = [NSNotification notificationWithName:@"writeObjectMetadataFailed" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
644
        [[NSNotificationCenter defaultCenter] postNotification:notification];
645
    }
646
}
647

    
648
- (void)writeObjectMetadataFailed:(OpenStackRequest *)request {
649
    NSNotification *notification = [NSNotification notificationWithName:@"writeObjectMetadataFailed" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
650
    [[NSNotificationCenter defaultCenter] postNotification:notification];
651
}
652

    
653
- (void)deleteObject:(Container *)container object:(StorageObject *)object {
654
    TrackEvent(CATEGORY_FILES, EVENT_DELETED);
655
    
656
    OpenStackRequest *request = [OpenStackRequest deleteObjectRequest:self.account container:container object:object];
657
    request.delegate = self;
658
    request.didFinishSelector = @selector(deleteObjectSucceeded:);
659
    request.didFailSelector = @selector(deleteObjectFailed:);
660
    request.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:container, object, nil] forKeys:[NSArray arrayWithObjects:@"container", @"object", nil]];
661
    [request startAsynchronous];
662
}
663

    
664
- (void)deleteObjectSucceeded:(OpenStackRequest *)request {
665
    if ([request isSuccess] || [request responseStatusCode] == 404) {
666
        NSNotification *notification = [NSNotification notificationWithName:@"deleteObjectSucceeded" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
667
        [[NSNotificationCenter defaultCenter] postNotification:notification];
668
    } else {
669
        NSNotification *notification = [NSNotification notificationWithName:@"deleteObjectFailed" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
670
        [[NSNotificationCenter defaultCenter] postNotification:notification];
671
    }
672
}
673

    
674
- (void)deleteObjectFailed:(OpenStackRequest *)request {
675
    NSNotification *notification = [NSNotification notificationWithName:@"deleteObjectFailed" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
676
    [[NSNotificationCenter defaultCenter] postNotification:notification];
677
}
678

    
679
#pragma mark -
680
#pragma mark Load Balancing
681

    
682
- (APICallback *)getLoadBalancers:(NSString *)endpoint {
683
    __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancersRequest:self.account endpoint:endpoint];
684
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
685
        if (!self.account.loadBalancers) {
686
            self.account.loadBalancers = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
687
        }
688
        
689
        NSLog(@"%@", self.account.loadBalancers);
690
        NSLog(@"%@", [(LoadBalancerRequest *)request loadBalancers:self.account]);
691
        NSLog(@"%@", endpoint);
692
        NSMutableDictionary *lbs = [(LoadBalancerRequest *)request loadBalancers:self.account];
693
        
694
        for (NSString *identifier in lbs) {
695
            LoadBalancer *lb = [lbs objectForKey:identifier];
696
            lb.region = [self.account loadBalancerRegionForEndpoint:endpoint];
697
            NSLog(@"lb.region = %@", lb.region);
698
        }
699
        
700
        [self.account.loadBalancers setObject:lbs forKey:endpoint];
701
        [self.account persist];
702
    }];
703
}
704

    
705
- (APICallback *)getLoadBalancerDetails:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint {
706
    __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancerDetailsRequest:self.account loadBalancer:loadBalancer endpoint:endpoint];
707
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
708

    
709
        LoadBalancer *newLB = [(LoadBalancerRequest *)request loadBalancer:self.account];
710
        loadBalancer.status = newLB.status;
711
        loadBalancer.nodes = newLB.nodes;
712
        loadBalancer.connectionLoggingEnabled = newLB.connectionLoggingEnabled;
713
        
714
//        if (!self.account.loadBalancers) {
715
//            self.account.loadBalancers = [[NSMutableDictionary alloc] initWithCapacity:2];
716
//        }
717
//        
718
//        NSLog(@"%@", self.account.loadBalancers);
719
//        NSLog(@"%@", [(LoadBalancerRequest *)request loadBalancers]);
720
//        NSLog(@"%@", endpoint);
721
//        NSMutableDictionary *lbs = [(LoadBalancerRequest *)request loadBalancers];
722
//        
723
//        for (NSString *identifier in lbs) {
724
//            LoadBalancer *lb = [lbs objectForKey:identifier];
725
//            lb.region = [self.account loadBalancerRegionForEndpoint:endpoint];
726
//            NSLog(@"lb.region = %@", lb.region);
727
//        }
728
//        
729
//        [self.account.loadBalancers setObject:lbs forKey:endpoint];
730
        [self.account persist];
731
    }];
732
}
733

    
734
- (APICallback *)getLoadBalancerProtocols:(NSString *)endpoint {
735
    __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancerProtocols:self.account endpoint:endpoint];
736
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
737
        self.account.lbProtocols = [(LoadBalancerRequest *)request protocols];
738
    }];
739
}
740

    
741
- (APICallback *)createLoadBalancer:(LoadBalancer *)loadBalancer {
742
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_CREATED);
743
    
744
    NSString *endpoint = @"";
745
    
746
    for (NSString *url in [self.account loadBalancerURLs]) {
747
        if ([url hasPrefix:[NSString stringWithFormat:@"https://%@", [loadBalancer.region lowercaseString]]]) {
748
            endpoint = url;
749
            break;
750
        }
751
    }
752
    
753
    __block LoadBalancerRequest *request = [LoadBalancerRequest createLoadBalancerRequest:self.account loadBalancer:loadBalancer endpoint:endpoint];
754
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
755
    }];
756
}
757

    
758
- (APICallback *)updateLoadBalancer:(LoadBalancer *)loadBalancer {
759
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED);
760
    NSString *endpoint = [self.account loadBalancerEndpointForRegion:loadBalancer.region];
761
    __block LoadBalancerRequest *request = [LoadBalancerRequest updateLoadBalancerRequest:self.account loadBalancer:loadBalancer endpoint:endpoint];
762
    return [self callbackWithRequest:request];
763
}
764

    
765
- (APICallback *)deleteLoadBalancer:(LoadBalancer *)loadBalancer {
766
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_DELETED);
767
    NSString *endpoint = [self.account loadBalancerEndpointForRegion:loadBalancer.region];
768
    NSLog(@"endpoint: %@", endpoint);
769
    __block LoadBalancerRequest *request = [LoadBalancerRequest deleteLoadBalancerRequest:self.account loadBalancer:loadBalancer endpoint:endpoint];
770
    return [self callbackWithRequest:request];
771
}
772

    
773
- (APICallback *)updateLoadBalancerConnectionLogging:(LoadBalancer *)loadBalancer {
774
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED_LB_CONNECTION_LOGGING);
775
    __block LoadBalancerRequest *request = [LoadBalancerRequest updateConnectionLoggingRequest:self.account loadBalancer:loadBalancer];
776
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
777
    } failure:^(OpenStackRequest *request) {
778
        loadBalancer.connectionLoggingEnabled = !loadBalancer.connectionLoggingEnabled;
779
    }];
780
}
781

    
782
- (APICallback *)getLoadBalancerConnectionThrottling:(LoadBalancer *)loadBalancer {
783
    __block LoadBalancerRequest *request = [LoadBalancerRequest getConnectionThrottlingRequest:self.account loadBalancer:loadBalancer];
784
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
785
        loadBalancer.connectionThrottle = [(LoadBalancerRequest *)request connectionThrottle];
786
    }];
787
}
788

    
789
- (APICallback *)updateLoadBalancerConnectionThrottling:(LoadBalancer *)loadBalancer {
790
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED_LB_CONNECTION_THROTTLING);
791
    __block LoadBalancerRequest *request = [LoadBalancerRequest updateConnectionThrottlingRequest:self.account loadBalancer:loadBalancer];
792
    return [self callbackWithRequest:request];
793
}
794

    
795
- (APICallback *)deleteLoadBalancerConnectionThrottling:(LoadBalancer *)loadBalancer {
796
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_DISABLED_LB_CONNECTION_THROTTLING);
797
    __block LoadBalancerRequest *request = [LoadBalancerRequest disableConnectionThrottlingRequest:self.account loadBalancer:loadBalancer];
798
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
799
        loadBalancer.connectionThrottle = nil;
800
    }];
801
}
802

    
803
- (APICallback *)getLoadBalancerUsage:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint {
804
    __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancerUsageRequest:self.account loadBalancer:loadBalancer endpoint:endpoint];
805
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
806
        loadBalancer.usage = [(LoadBalancerRequest *)request usage];
807
    }];
808
}
809

    
810
- (APICallback *)addLBNodes:(NSArray *)nodes loadBalancer:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint {
811
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_ADDED_LB_NODES);
812
    __block LoadBalancerRequest *request = [LoadBalancerRequest addLoadBalancerNodesRequest:self.account loadBalancer:loadBalancer nodes:nodes endpoint:endpoint];
813
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
814
        for (LoadBalancerNode *node in nodes) {
815
            [loadBalancer.nodes addObject:node];
816
        }
817
        [self.account persist];
818
    }];
819
}
820

    
821
- (APICallback *)updateLBNode:(LoadBalancerNode *)node loadBalancer:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint {
822
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED_LB_NODE);
823
    __block LoadBalancerRequest *request = [LoadBalancerRequest updateLoadBalancerNodeRequest:self.account loadBalancer:loadBalancer node:node endpoint:endpoint];
824
    return [self callbackWithRequest:request];
825
}
826

    
827
- (APICallback *)deleteLBNode:(LoadBalancerNode *)node loadBalancer:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint {
828
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_DELETED_LB_NODE);
829
    __block LoadBalancerRequest *request = [LoadBalancerRequest deleteLoadBalancerNodeRequest:self.account loadBalancer:loadBalancer node:node endpoint:endpoint];
830
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
831
        [loadBalancer.nodes removeObject:node];
832
    }];
833
}
834

    
835
- (APICallback *)authenticate {
836
    __block OpenStackRequest *request = [OpenStackRequest authenticationRequest:self.account];
837
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
838
        if ([request isSuccess]) {        
839
            self.account.authToken = [[request responseHeaders] objectForKey:@"X-Auth-Token"];
840
            self.account.serversURL = [NSURL URLWithString:[[request responseHeaders] objectForKey:@"X-Server-Management-Url"]];
841
            self.account.filesURL = [NSURL URLWithString:[[request responseHeaders] objectForKey:@"X-Storage-Url"]];
842
            self.account.cdnURL = [NSURL URLWithString:[[request responseHeaders] objectForKey:@"X-Cdn-Management-Url"]];
843
            
844
            [self.account persist];
845
        }
846
    }];
847
}
848

    
849
#pragma mark -
850
#pragma mark Memory Management
851

    
852
- (void)dealloc {
853
    [super dealloc];
854
}
855

    
856
@end