Statistics
| Branch: | Tag: | Revision:

root / Classes / AccountManager.m @ 64929bae

History | View | Annotate | Download (36.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
#import "JSON.h"
30
#import "OpenStackAppDelegate.h"
31

    
32

    
33

    
34

    
35
@implementation AccountManager
36

    
37
@synthesize account, queue, objectDownloadRequests;
38

    
39
#pragma mark - Callbacks
40

    
41
- (APICallback *)callbackWithRequest:(id)request success:(APIResponseBlock)success failure:(APIResponseBlock)failure {
42
    APICallback *callback = [[[APICallback alloc] initWithAccount:self.account request:request] autorelease];
43
    ((OpenStackRequest *)request).delegate = self;
44
    ((OpenStackRequest *)request).callback = callback; 
45

    
46
    [request setCompletionBlock:^{
47
        if ([request isSuccess]) {
48
            success(request);
49
            [request notify];
50
        } else {
51
            failure(request);
52
            [request notify];
53
        }
54
    }];
55
    [request setFailedBlock:^{
56
        failure(request);
57
        [request notify];
58
    }];
59
    [request startAsynchronous];    
60
    return callback;
61
}
62

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

    
67
- (APICallback *)callbackWithRequest:(id)request {
68
    return [self callbackWithRequest:request success:^(OpenStackRequest *request){} failure:^(OpenStackRequest *request){}];
69
}
70

    
71
#pragma mark - Notification
72

    
73
- (NSString *)notificationName:(NSString *)key identifier:(NSString *)identifier {
74
    return [NSString stringWithFormat:@"%@-%@-%i", key, self.account.uuid, identifier];
75
}
76

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

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

    
97
- (void)sendRequest:(OpenStackRequest *)request name:(NSString *)name object:(id)notificationObject {
98
    request.delegate = self;
99
    request.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:name, notificationObject, nil] forKeys:[NSArray arrayWithObjects:@"notificationName", @"notificationObject", nil]];
100
    [request startAsynchronous];
101
}
102

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

    
108
- (void)notify:(NSString *)name request:(OpenStackRequest *)request object:(id)object {
109
    NSNotification *notification = [NSNotification notificationWithName:name object:object userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
110
    [[NSNotificationCenter defaultCenter] postNotification:notification];
111
}
112

    
113
#pragma mark - API Calls
114

    
115
#pragma mark Get Limits
116

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

    
135
#pragma mark Reboot Server
136

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

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

    
167
#pragma mark Change Admin Password
168

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

    
184
#pragma mark Rename Server
185

    
186
- (APICallback *)renameServer:(Server *)server name:(NSString *)name {
187
    TrackEvent(CATEGORY_SERVER, EVENT_RENAMED);
188
    
189
    __block OpenStackRequest *request = [OpenStackRequest renameServerRequest:self.account server:server name:name];
190
    return [self callbackWithRequest:request];
191
}
192

    
193
#pragma mark Delete Server
194

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

    
214
#pragma mark Create Server
215

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

    
241
#pragma mark Resize Server
242

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

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

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

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

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

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

    
343
#pragma mark Get Image
344

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

    
368
#pragma mark Get Servers
369

    
370
- (void)getServers {
371
    if (![self queue]) {
372
        [self setQueue:[[[ASINetworkQueue alloc] init] autorelease]];
373
    }
374
    GetServersRequest *request = [GetServersRequest request:self.account];
375
    [queue addOperation:request];
376
}
377

    
378
- (APICallback *)getServersWithCallback {
379
    __block OpenStackRequest *request = [OpenStackRequest serversRequest:self.account method:@"GET" path:@"/servers/detail"];
380
    return [self callbackWithRequest:request];
381
}
382

    
383

    
384
#pragma mark Get Flavors
385

    
386
- (void)getFlavors {
387
    if (![self queue]) {
388
        [self setQueue:[[[ASINetworkQueue alloc] init] autorelease]];
389
    }
390
    GetFlavorsRequest *request = [GetFlavorsRequest request:self.account];
391
    [queue addOperation:request];
392
}
393

    
394
#pragma mark Get Images
395

    
396
- (void)getImages {
397
    if (![self queue]) {
398
        [self setQueue:[[[ASINetworkQueue alloc] init] autorelease]];
399
    }
400
    GetImagesRequest *request = [GetImagesRequest request:self.account];
401
    [queue addOperation:request];
402
}
403

    
404
#pragma mark -
405
#pragma mark Object Storage
406

    
407

    
408
- (APICallback *)getStorageAccountInfo {
409
    __block OpenStackRequest *request = [OpenStackRequest getStorageAccountInfoRequest:self.account];
410
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {        
411
        self.account.containerCount = [[[request responseHeaders] objectForKey:@"X-Account-Container-Count"] intValue];
412
        NSString *numStr = [[request responseHeaders] objectForKey:@"X-Account-Bytes-Used"];
413
        self.account.totalBytesUsed = strtoull([numStr UTF8String], NULL, 0);
414
        [self.account persist];
415
        self.account.containerCount = [self.account.containers count];        
416
    }];
417
}
418

    
419
- (APICallback *)getSharingAccounts {
420
    __block OpenStackRequest *request = [OpenStackRequest getSharingAccountsRequest:self.account];
421
    return [self callbackWithRequest:request];        
422
}
423

    
424
- (APICallback *)getContainers {
425
    __block OpenStackRequest *request = [OpenStackRequest filesRequest:self.account method:@"GET" path:@""];
426
    return [self callbackWithRequest:request];    
427
}
428

    
429
- (APICallback *)createContainer:(Container *)container {
430
    TrackEvent(CATEGORY_CONTAINERS, EVENT_CREATED);
431

    
432
    __block OpenStackRequest *request = [OpenStackRequest createContainerRequest:self.account container:container];
433
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
434
        
435
        [self.account.containers setObject:container forKey:container.name];        
436
        [self.account persist];
437
        self.account.containerCount = [self.account.containers count];        
438
    }];
439
}
440

    
441
- (APICallback *)deleteContainer:(Container *)container {
442
    TrackEvent(CATEGORY_CONTAINERS, EVENT_DELETED);
443
    __block OpenStackRequest *request = [OpenStackRequest deleteContainerRequest:self.account container:container];
444
    return [self callbackWithRequest:request];
445
    
446
}
447

    
448
- (void)getObjects:(Container *)container {
449
    [self getObjects:container afterMarker:nil objectsBuffer:nil];
450
}
451

    
452
- (void)getObjects:(Container *)container
453
       afterMarker:(NSString *)marker
454
     objectsBuffer:(NSMutableDictionary *)objectsBuffer {
455
    if (![self queue]) {
456
        [self setQueue:(ASINetworkQueue *)[[[NSOperationQueue alloc] init] autorelease]];
457
    }    
458
    GetObjectsRequest *request = [GetObjectsRequest request:self.account container:container marker:marker objectsBuffer:objectsBuffer];
459
    [queue addOperation:request];
460
}
461

    
462
- (void)updateCDNContainer:(Container *)container {
463
    TrackEvent(CATEGORY_CONTAINERS, EVENT_UPDATED);
464
    
465
    if (![self queue]) {
466
        [self setQueue:(ASINetworkQueue *)[[[NSOperationQueue alloc] init] autorelease]];
467
    }
468
    UpdateCDNContainerRequest *request = [UpdateCDNContainerRequest request:self.account container:container];
469
    [queue addOperation:request];
470
}
471

    
472
- (void)getObjectsSucceeded:(OpenStackRequest *)request {
473
    if ([request isSuccess]) {
474
        Container *container = [request.userInfo objectForKey:@"container"];
475
        NSMutableDictionary *objects = [request objects];
476
        container.rootFolder = [Folder folder];
477
        container.rootFolder.objects = objects;
478
        [self.account persist];
479
        
480
        NSNotification *notification = [NSNotification notificationWithName:@"getObjectsSucceeded" object:self.account userInfo:[NSDictionary dictionaryWithObject:container forKey:@"container"]];
481
        [[NSNotificationCenter defaultCenter] postNotification:notification];
482
    } else {
483
        NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
484
        [[NSNotificationCenter defaultCenter] postNotification:notification];
485
    }
486
}
487

    
488
- (void)getObjectsFailed:(OpenStackRequest *)request {
489
    NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
490
    [[NSNotificationCenter defaultCenter] postNotification:notification];
491
}
492

    
493
- (APICallback *)getObjectInfo:(Container *)container object:(StorageObject *)object {    
494
    __block OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object];
495
    return [self callbackWithRequest:request];
496
}
497

    
498
- (APICallback *)getObjectInfo:(Container *)container object:(StorageObject *)object version:(NSString *)version {
499
    if (!version)
500
        return [self getObjectInfo:container object:object];
501
    
502
    __block OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object version:version];
503
    return [self callbackWithRequest:request];
504
}
505

    
506
- (APICallback *)getObjectVersionsList:(Container *)container object:(StorageObject *)object {
507
    __block OpenStackRequest *request = [OpenStackRequest getObjectVersionsRequest:account container:container object:object];
508
    return [self callbackWithRequest:request];
509
}
510

    
511
- (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate {
512
    return [self getObject:container object:object downloadProgressDelegate:downloadProgressDelegate requestUserInfo:nil];
513
}
514

    
515
- (APICallback *)getObject:(Container *)container
516
                    object:(StorageObject *)object
517
  downloadProgressDelegate:(id)downloadProgressDelegate
518
           requestUserInfo:(NSDictionary *)requestUserInfo {
519
    
520
    return [self getObject:container object:object downloadProgressDelegate:downloadProgressDelegate requestUserInfo:requestUserInfo version:nil];
521
}
522

    
523

    
524
- (APICallback *)getObject:(Container *)container
525
                    object:(StorageObject *)object
526
  downloadProgressDelegate:(id)downloadProgressDelegate 
527
           requestUserInfo:(NSDictionary *)requestUserInfo
528
                   version:(NSString *)version{
529
    __block OpenStackRequest *request = [OpenStackRequest getObjectRequest:self.account container:container object:object version:version];
530
    request.delegate = self;
531
    request.downloadProgressDelegate = downloadProgressDelegate;
532
    request.showAccurateProgress = YES;  
533
    if (requestUserInfo) {
534
        request.userInfo = requestUserInfo;
535
    }
536
    if (!objectDownloadRequests)
537
        self.objectDownloadRequests = [NSMutableDictionary dictionary];
538
    [objectDownloadRequests setObject:request forKey:object.fullPath];
539
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
540
        
541
        OpenStackAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
542
        NSString *filePath = [appDelegate.cacheDirectoryPath stringByAppendingFormat:@"/%@.%@",object.hash, object.name.pathExtension];
543
        [[request responseData] writeToFile:filePath atomically:YES];
544
        @synchronized(appDelegate.cachedObjectsDictionary) {
545
            [appDelegate.cachedObjectsDictionary setObject:filePath forKey:object.hash];
546
            [appDelegate saveCacheDictionary];
547
        }
548
        [objectDownloadRequests removeObjectForKey:object.fullPath];
549
    }
550
    failure:^(OpenStackRequest *request) { 
551
        [objectDownloadRequests removeObjectForKey:object.fullPath];
552
    }];
553
}
554

    
555
- (APICallback *)writeObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate {
556
    TrackEvent(CATEGORY_FILES, EVENT_CREATED);
557
    
558
    __block OpenStackRequest *request = [OpenStackRequest writeObjectRequest:self.account container:container object:object];
559
    request.delegate = self;
560
    request.uploadProgressDelegate = downloadProgressDelegate;
561
    request.showAccurateProgress = YES;
562
    
563
    return [self callbackWithRequest:request];
564
}
565

    
566
- (APICallback *)deleteObject:(Container *)container object:(StorageObject *)object {
567
    TrackEvent(CATEGORY_FILES, EVENT_DELETED);
568
    
569
    __block OpenStackRequest *request = [OpenStackRequest deleteObjectRequest:self.account container:container object:object];
570
    return [self callbackWithRequest:request];
571
}
572

    
573
- (APICallback *)writeObjectMetadata:(Container *)container object:(StorageObject *)object {
574
    __block OpenStackRequest *request = [OpenStackRequest writeObjectMetadataRequest:self.account container:container object:object];
575
    return [self callbackWithRequest:request];
576
}
577

    
578
- (APICallback *)writeAccountMetadata:(NSDictionary *)accountInfo {
579
    __block OpenStackRequest *request = [OpenStackRequest writeAccountMetadataRequest:self.account withAccountInfo:accountInfo];
580
    return [self callbackWithRequest:request];
581
}
582

    
583
- (APICallback *)writeContainerPolicy:(Container *)container {
584
    __block OpenStackRequest *request = [OpenStackRequest writeContainerPolicyRequest:self.account container:container];
585
    return [self callbackWithRequest:request];
586
}
587

    
588
#pragma mark -
589
#pragma mark Load Balancing
590

    
591
- (APICallback *)getLoadBalancers:(NSString *)endpoint {
592
    __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancersRequest:self.account endpoint:endpoint];
593
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
594
        if (!self.account.loadBalancers) {
595
            self.account.loadBalancers = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
596
        }
597
        
598
        NSLog(@"%@", self.account.loadBalancers);
599
        NSLog(@"%@", [(LoadBalancerRequest *)request loadBalancers:self.account]);
600
        NSLog(@"%@", endpoint);
601
        NSMutableDictionary *lbs = [(LoadBalancerRequest *)request loadBalancers:self.account];
602
        
603
        for (NSString *identifier in lbs) {
604
            LoadBalancer *lb = [lbs objectForKey:identifier];
605
            lb.region = [self.account loadBalancerRegionForEndpoint:endpoint];
606
            NSLog(@"lb.region = %@", lb.region);
607
        }
608
        
609
        [self.account.loadBalancers setObject:lbs forKey:endpoint];
610
        [self.account persist];
611
    }];
612
}
613

    
614
- (APICallback *)getLoadBalancerDetails:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint {
615
    __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancerDetailsRequest:self.account loadBalancer:loadBalancer endpoint:endpoint];
616
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
617

    
618
        LoadBalancer *newLB = [(LoadBalancerRequest *)request loadBalancer:self.account];
619
        loadBalancer.status = newLB.status;
620
        loadBalancer.nodes = newLB.nodes;
621
        loadBalancer.connectionLoggingEnabled = newLB.connectionLoggingEnabled;
622
        
623
//        if (!self.account.loadBalancers) {
624
//            self.account.loadBalancers = [[NSMutableDictionary alloc] initWithCapacity:2];
625
//        }
626
//        
627
//        NSLog(@"%@", self.account.loadBalancers);
628
//        NSLog(@"%@", [(LoadBalancerRequest *)request loadBalancers]);
629
//        NSLog(@"%@", endpoint);
630
//        NSMutableDictionary *lbs = [(LoadBalancerRequest *)request loadBalancers];
631
//        
632
//        for (NSString *identifier in lbs) {
633
//            LoadBalancer *lb = [lbs objectForKey:identifier];
634
//            lb.region = [self.account loadBalancerRegionForEndpoint:endpoint];
635
//            NSLog(@"lb.region = %@", lb.region);
636
//        }
637
//        
638
//        [self.account.loadBalancers setObject:lbs forKey:endpoint];
639
        [self.account persist];
640
    }];
641
}
642

    
643
- (APICallback *)getLoadBalancerProtocols:(NSString *)endpoint {
644
    __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancerProtocols:self.account endpoint:endpoint];
645
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
646
        self.account.lbProtocols = [(LoadBalancerRequest *)request protocols];
647
    }];
648
}
649

    
650
- (APICallback *)createLoadBalancer:(LoadBalancer *)loadBalancer {
651
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_CREATED);
652
    
653
    NSString *endpoint = @"";
654
    
655
    for (NSString *url in [self.account loadBalancerURLs]) {
656
        if ([url hasPrefix:[NSString stringWithFormat:@"https://%@", [loadBalancer.region lowercaseString]]]) {
657
            endpoint = url;
658
            break;
659
        }
660
    }
661
    
662
    __block LoadBalancerRequest *request = [LoadBalancerRequest createLoadBalancerRequest:self.account loadBalancer:loadBalancer endpoint:endpoint];
663
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
664
    }];
665
}
666

    
667
- (APICallback *)updateLoadBalancer:(LoadBalancer *)loadBalancer {
668
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED);
669
    NSString *endpoint = [self.account loadBalancerEndpointForRegion:loadBalancer.region];
670
    __block LoadBalancerRequest *request = [LoadBalancerRequest updateLoadBalancerRequest:self.account loadBalancer:loadBalancer endpoint:endpoint];
671
    return [self callbackWithRequest:request];
672
}
673

    
674
- (APICallback *)deleteLoadBalancer:(LoadBalancer *)loadBalancer {
675
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_DELETED);
676
    NSString *endpoint = [self.account loadBalancerEndpointForRegion:loadBalancer.region];
677
    NSLog(@"endpoint: %@", endpoint);
678
    __block LoadBalancerRequest *request = [LoadBalancerRequest deleteLoadBalancerRequest:self.account loadBalancer:loadBalancer endpoint:endpoint];
679
    return [self callbackWithRequest:request];
680
}
681

    
682
- (APICallback *)updateLoadBalancerConnectionLogging:(LoadBalancer *)loadBalancer {
683
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED_LB_CONNECTION_LOGGING);
684
    __block LoadBalancerRequest *request = [LoadBalancerRequest updateConnectionLoggingRequest:self.account loadBalancer:loadBalancer];
685
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
686
    } failure:^(OpenStackRequest *request) {
687
        loadBalancer.connectionLoggingEnabled = !loadBalancer.connectionLoggingEnabled;
688
    }];
689
}
690

    
691
- (APICallback *)getLoadBalancerConnectionThrottling:(LoadBalancer *)loadBalancer {
692
    __block LoadBalancerRequest *request = [LoadBalancerRequest getConnectionThrottlingRequest:self.account loadBalancer:loadBalancer];
693
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
694
        loadBalancer.connectionThrottle = [(LoadBalancerRequest *)request connectionThrottle];
695
    }];
696
}
697

    
698
- (APICallback *)updateLoadBalancerConnectionThrottling:(LoadBalancer *)loadBalancer {
699
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED_LB_CONNECTION_THROTTLING);
700
    __block LoadBalancerRequest *request = [LoadBalancerRequest updateConnectionThrottlingRequest:self.account loadBalancer:loadBalancer];
701
    return [self callbackWithRequest:request];
702
}
703

    
704
- (APICallback *)deleteLoadBalancerConnectionThrottling:(LoadBalancer *)loadBalancer {
705
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_DISABLED_LB_CONNECTION_THROTTLING);
706
    __block LoadBalancerRequest *request = [LoadBalancerRequest disableConnectionThrottlingRequest:self.account loadBalancer:loadBalancer];
707
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
708
        loadBalancer.connectionThrottle = nil;
709
    }];
710
}
711

    
712
- (APICallback *)getLoadBalancerUsage:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint {
713
    __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancerUsageRequest:self.account loadBalancer:loadBalancer endpoint:endpoint];
714
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
715
        loadBalancer.usage = [(LoadBalancerRequest *)request usage];
716
    }];
717
}
718

    
719
- (APICallback *)addLBNodes:(NSArray *)nodes loadBalancer:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint {
720
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_ADDED_LB_NODES);
721
    __block LoadBalancerRequest *request = [LoadBalancerRequest addLoadBalancerNodesRequest:self.account loadBalancer:loadBalancer nodes:nodes endpoint:endpoint];
722
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
723
        for (LoadBalancerNode *node in nodes) {
724
            [loadBalancer.nodes addObject:node];
725
        }
726
        [self.account persist];
727
    }];
728
}
729

    
730
- (APICallback *)updateLBNode:(LoadBalancerNode *)node loadBalancer:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint {
731
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED_LB_NODE);
732
    __block LoadBalancerRequest *request = [LoadBalancerRequest updateLoadBalancerNodeRequest:self.account loadBalancer:loadBalancer node:node endpoint:endpoint];
733
    return [self callbackWithRequest:request];
734
}
735

    
736
- (APICallback *)deleteLBNode:(LoadBalancerNode *)node loadBalancer:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint {
737
    TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_DELETED_LB_NODE);
738
    __block LoadBalancerRequest *request = [LoadBalancerRequest deleteLoadBalancerNodeRequest:self.account loadBalancer:loadBalancer node:node endpoint:endpoint];
739
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
740
        [loadBalancer.nodes removeObject:node];
741
    }];
742
}
743

    
744
- (APICallback *)authenticate {
745
    __block OpenStackRequest *request = [OpenStackRequest authenticationRequest:self.account];
746
    return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
747
        if ([request isSuccess]) {        
748
            self.account.authToken = [[request responseHeaders] objectForKey:@"X-Auth-Token"];
749
            self.account.serversURL = [NSURL URLWithString:[[request responseHeaders] objectForKey:@"X-Server-Management-Url"]];
750
            
751
            if (![[request responseHeaders] objectForKey:@"X-Storage-URL"]) {
752
                NSString *filesStorageURL = [NSString stringWithFormat:@"%@/v1/%@",
753
                                             [self.account.hostURL absoluteString],
754
                                             [self.account username]];
755

    
756
                self.account.filesURL = [NSURL URLWithString:filesStorageURL];
757
            }
758
            else {
759
                self.account.filesURL = [NSURL URLWithString:[[request responseHeaders] objectForKey:@"X-Storage-Url"]];
760
            }
761
            
762
            self.account.pithosPublicLinkURLPrefix = self.account.hostURL;
763
            self.account.pithosLoginURLPrefix = [NSURL URLWithString:
764
                                            [[self.account.hostURL absoluteString]
765
                                             stringByAppendingString:@"/login"]];
766
            self.account.cdnURL = [NSURL URLWithString:[[request responseHeaders] objectForKey:@"X-Cdn-Management-Url"]];
767
            
768
            [self.account persist];
769
        }
770
    }];
771
}
772

    
773

    
774
#pragma mark -
775
#pragma mark Memory Management
776

    
777
- (void)dealloc {
778
    [objectDownloadRequests release];
779
    [super dealloc];
780
}
781

    
782
@end