// // AccountManager.m // OpenStack // // Created by Mike Mayo on 10/21/10. // The OpenStack project is provided under the Apache 2.0 license. // #import "AccountManager.h" #import "OpenStackAccount.h" #import "OpenStackRequest.h" #import "Server.h" #import "Provider.h" #import "Image.h" #import "Container.h" #import "Folder.h" #import "StorageObject.h" #import "GetServersRequest.h" #import "GetContainersRequest.h" #import "GetObjectsRequest.h" #import "GetImagesRequest.h" #import "ASINetworkQueue.h" #import "UpdateCDNContainerRequest.h" #import "GetFlavorsRequest.h" #import "LoadBalancer.h" #import "LoadBalancerRequest.h" #import "APICallback.h" #import "Analytics.h" #import "JSON.h" #import "OpenStackAppDelegate.h" @implementation AccountManager @synthesize account, queue, objectDownloadRequests; #pragma mark - Callbacks - (APICallback *)callbackWithRequest:(id)request success:(APIResponseBlock)success failure:(APIResponseBlock)failure { APICallback *callback = [[[APICallback alloc] initWithAccount:self.account request:request] autorelease]; ((OpenStackRequest *)request).delegate = self; ((OpenStackRequest *)request).callback = callback; [request setCompletionBlock:^{ if ([request isSuccess]) { success(request); [request notify]; } else { failure(request); [request notify]; } }]; [request setFailedBlock:^{ failure(request); [request notify]; }]; [request startAsynchronous]; return callback; } - (APICallback *)callbackWithRequest:(id)request success:(APIResponseBlock)success { return [self callbackWithRequest:request success:success failure:^(OpenStackRequest *request){}]; } - (APICallback *)callbackWithRequest:(id)request { return [self callbackWithRequest:request success:^(OpenStackRequest *request){} failure:^(OpenStackRequest *request){}]; } #pragma mark - Notification - (NSString *)notificationName:(NSString *)key identifier:(NSString *)identifier { return [NSString stringWithFormat:@"%@-%@-%@", key, self.account.uuid, identifier]; } - (void)requestFinished:(OpenStackRequest *)request { NSString *notificationName = [request.userInfo objectForKey:@"notificationName"]; id notificationObject = [request.userInfo objectForKey:@"notificationObject"]; if ([request isSuccess]) { NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Succeeded", notificationName] object:notificationObject]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } else { NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Failed", notificationName] object:notificationObject userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } } - (void)requestFailed:(OpenStackRequest *)request { NSString *notificationName = [request.userInfo objectForKey:@"notificationName"]; id notificationObject = [request.userInfo objectForKey:@"notificationObject"]; NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Failed", notificationName] object:notificationObject userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } - (void)sendRequest:(OpenStackRequest *)request name:(NSString *)name object:(id)notificationObject { request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:name, notificationObject, nil] forKeys:[NSArray arrayWithObjects:@"notificationName", @"notificationObject", nil]]; [request startAsynchronous]; } - (void)notify:(NSString *)name request:(OpenStackRequest *)request { NSNotification *notification = [NSNotification notificationWithName:name object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } - (void)notify:(NSString *)name request:(OpenStackRequest *)request object:(id)object { NSNotification *notification = [NSNotification notificationWithName:name object:object userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } #pragma mark - API Calls #pragma mark Get Limits - (void)getLimits { __block OpenStackRequest *request = [OpenStackRequest getLimitsRequest:self.account]; request.delegate = self; [request setCompletionBlock:^{ if ([request isSuccess] && [request limits]) { self.account.rateLimits = [request rateLimits]; [self.account persist]; [self notify:@"getLimitsSucceeded" request:request object:self.account]; } else { [self notify:@"getLimitsFailed" request:request object:self.account]; } }]; [request setFailedBlock:^{ [self notify:@"getLimitsFailed" request:request object:self.account]; }]; [request startAsynchronous]; } #pragma mark Reboot Server - (void)softRebootServer:(Server *)server { TrackEvent(CATEGORY_SERVER, EVENT_REBOOTED); __block OpenStackRequest *request = [OpenStackRequest softRebootServerRequest:self.account server:server]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; [request setCompletionBlock:^{ [self notify:([request isSuccess] ? @"rebootSucceeded" : @"rebootFailed") request:request object:[request.userInfo objectForKey:@"server"]]; }]; [request setFailedBlock:^{ [self notify:@"rebootFailed" request:request object:[request.userInfo objectForKey:@"server"]]; }]; [request startAsynchronous]; } - (void)hardRebootServer:(Server *)server { TrackEvent(CATEGORY_SERVER, EVENT_REBOOTED); __block OpenStackRequest *request = [OpenStackRequest hardRebootServerRequest:self.account server:server]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; [request setCompletionBlock:^{ [self notify:([request isSuccess] ? @"rebootSucceeded" : @"rebootFailed") request:request object:[request.userInfo objectForKey:@"server"]]; }]; [request setFailedBlock:^{ [self notify:@"rebootFailed" request:request object:[request.userInfo objectForKey:@"server"]]; }]; [request startAsynchronous]; } #pragma mark Change Admin Password - (void)changeAdminPassword:(Server *)server password:(NSString *)password { TrackEvent(CATEGORY_SERVER, EVENT_PASSWORD_CHANGED); __block OpenStackRequest *request = [OpenStackRequest changeServerAdminPasswordRequest:self.account server:server password:password]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; [request setCompletionBlock:^{ [self notify:([request isSuccess] ? @"changeAdminPasswordSucceeded" : @"changeAdminPasswordFailed") request:request object:[request.userInfo objectForKey:@"server"]]; }]; [request setFailedBlock:^{ [self notify:@"changeAdminPasswordFailed" request:request object:[request.userInfo objectForKey:@"server"]]; }]; [request startAsynchronous]; } #pragma mark Rename Server - (APICallback *)renameServer:(Server *)server name:(NSString *)name { TrackEvent(CATEGORY_SERVER, EVENT_RENAMED); __block OpenStackRequest *request = [OpenStackRequest renameServerRequest:self.account server:server name:name]; return [self callbackWithRequest:request]; } #pragma mark Delete Server - (void)deleteServer:(Server *)server { TrackEvent(CATEGORY_SERVER, EVENT_DELETED); __block OpenStackRequest *request = [OpenStackRequest deleteServerRequest:self.account server:server]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; [request setCompletionBlock:^{ [self notify:([request isSuccess] ? @"deleteServerSucceeded" : @"deleteServerFailed") request:request object:[request.userInfo objectForKey:@"server"]]; [self notify:([request isSuccess] ? @"deleteServerSucceeded" : @"deleteServerFailed") request:request object:self.account]; }]; [request setFailedBlock:^{ [self notify:@"deleteServerFailed" request:request object:[request.userInfo objectForKey:@"server"]]; }]; if (![self queue]) { [self setQueue:(ASINetworkQueue *)[[[NSOperationQueue alloc] init] autorelease]]; } [queue addOperation:request]; } #pragma mark Create Server - (void)createServer:(Server *)server { TrackEvent(CATEGORY_SERVER, EVENT_CREATED); __block OpenStackRequest *request = [OpenStackRequest createServerRequest:self.account server:server]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; // TODO: make these success block and failure block with "response" arg [request setCompletionBlock:^{ NSLog(@"create server response: %i - %@", request.responseStatusCode, request.responseStatusMessage); NSLog(@"body: %@", [request responseString]); [self notify:([request isSuccess] ? @"createServerSucceeded" : @"createServerFailed") request:request object:[request.userInfo objectForKey:@"server"]]; [self notify:([request isSuccess] ? @"createServerSucceeded" : @"createServerFailed") request:request object:self.account]; }]; [request setFailedBlock:^{ NSLog(@"create server response: %i - %@", request.responseStatusCode, request.responseStatusMessage); NSLog(@"body: %@", [request responseString]); [self notify:@"createServerFailed" request:request object:[request.userInfo objectForKey:@"server"]]; }]; if (![self queue]) { [self setQueue:(ASINetworkQueue *)[[[NSOperationQueue alloc] init] autorelease]]; } [queue addOperation:request]; } #pragma mark Resize Server - (void)resizeServer:(Server *)server flavor:(Flavor *)flavor { TrackEvent(CATEGORY_SERVER, EVENT_RESIZED); __block OpenStackRequest *request = [OpenStackRequest resizeServerRequest:self.account server:server flavor:flavor]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; [request setCompletionBlock:^{ NSString *name = [request isSuccess] ? @"resizeServerSucceeded" : @"resizeServerFailed"; NSNotification *notification = [NSNotification notificationWithName:[self notificationName:name identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }]; [request setFailedBlock:^{ NSNotification *notification = [NSNotification notificationWithName:[self notificationName:@"resizeServerFailed" identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }]; [request startAsynchronous]; } - (void)confirmResizeServer:(Server *)server { __block OpenStackRequest *request = [OpenStackRequest confirmResizeServerRequest:self.account server:server]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; [request setCompletionBlock:^{ NSString *name = [request isSuccess] ? @"confirmResizeServerSucceeded" : @"confirmResizeServerFailed"; NSNotification *notification = [NSNotification notificationWithName:[self notificationName:name identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }]; [request setFailedBlock:^{ NSNotification *notification = [NSNotification notificationWithName:[self notificationName:@"confirmResizeServerFailed" identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }]; [request startAsynchronous]; } - (void)revertResizeServer:(Server *)server { __block OpenStackRequest *request = [OpenStackRequest revertResizeServerRequest:self.account server:server]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; [request setCompletionBlock:^{ NSString *name = [request isSuccess] ? @"revertResizeServerSucceeded" : @"revertResizeServerFailed"; NSNotification *notification = [NSNotification notificationWithName:[self notificationName:name identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }]; [request setFailedBlock:^{ NSNotification *notification = [NSNotification notificationWithName:[self notificationName:@"revertResizeServerFailed" identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }]; [request startAsynchronous]; } - (void)rebuildServer:(Server *)server image:(Image *)image { TrackEvent(CATEGORY_SERVER, EVENT_REBUILT); __block OpenStackRequest *request = [OpenStackRequest rebuildServerRequest:self.account server:server image:image]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; [request setCompletionBlock:^{ NSString *name = [request isSuccess] ? @"rebuildServerSucceeded" : @"rebuildServerFailed"; NSNotification *notification = [NSNotification notificationWithName:[self notificationName:name identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }]; [request setFailedBlock:^{ NSNotification *notification = [NSNotification notificationWithName:[self notificationName:@"rebuildServerFailed" identifier:server.identifier] object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }]; [request startAsynchronous]; } - (void)getBackupSchedule:(Server *)server { __block OpenStackRequest *request = [OpenStackRequest getBackupScheduleRequest:self.account server:server]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; [request setCompletionBlock:^{ server.backupSchedule = [request backupSchedule]; [self notify:([request isSuccess] ? @"getBackupScheduleSucceeded" : @"getBackupScheduleFailed") request:request object:[request.userInfo objectForKey:@"server"]]; }]; [request setFailedBlock:^{ [self notify:@"getBackupScheduleFailed" request:request object:[request.userInfo objectForKey:@"server"]]; }]; [request startAsynchronous]; } - (void)updateBackupSchedule:(Server *)server { TrackEvent(CATEGORY_SERVER, EVENT_BACKUP_SCHEDULE_CHANGED); __block OpenStackRequest *request = [OpenStackRequest updateBackupScheduleRequest:self.account server:server]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server forKey:@"server"]; [request setCompletionBlock:^{ [self notify:([request isSuccess] ? @"updateBackupScheduleSucceeded" : @"updateBackupScheduleFailed") request:request object:[request.userInfo objectForKey:@"server"]]; [self notify:([request isSuccess] ? @"updateBackupScheduleSucceeded" : @"updateBackupScheduleFailed") request:request object:self.account]; }]; [request setFailedBlock:^{ [self notify:@"updateBackupScheduleFailed" request:request object:[request.userInfo objectForKey:@"server"]]; [self notify:@"updateBackupScheduleFailed" request:request object:self.account]; }]; [request startAsynchronous]; } #pragma mark Get Image - (void)getImage:(Server *)server { __block OpenStackRequest *request = [OpenStackRequest getImageRequest:self.account imageId:server.imageId]; request.delegate = self; request.userInfo = [NSDictionary dictionaryWithObject:server.imageId forKey:@"imageId"]; [request setCompletionBlock:^{ if ([request isSuccess]) { Image *image = [request image]; if ([image isKindOfClass:[Image class]]) { image.canBeLaunched = NO; [self.account.images setObject:image forKey:image.identifier]; [self.account persist]; } [self notify:@"getImageSucceeded" request:request]; } else { [self notify:@"getImageFailed" request:request object:[request.userInfo objectForKey:@"imageId"]]; } }]; [request setFailedBlock:^{ [self notify:@"getImageFailed" request:request object:[request.userInfo objectForKey:@"imageId"]]; }]; [request startAsynchronous]; } #pragma mark Get Servers - (void)getServers { if (![self queue]) { [self setQueue:[[[ASINetworkQueue alloc] init] autorelease]]; } GetServersRequest *request = [GetServersRequest request:self.account]; [queue addOperation:request]; } - (APICallback *)getServersWithCallback { __block OpenStackRequest *request = [OpenStackRequest serversRequest:self.account method:@"GET" path:@"/servers/detail"]; return [self callbackWithRequest:request]; } #pragma mark Get Flavors - (void)getFlavors { if (![self queue]) { [self setQueue:[[[ASINetworkQueue alloc] init] autorelease]]; } GetFlavorsRequest *request = [GetFlavorsRequest request:self.account]; [queue addOperation:request]; } #pragma mark Get Images - (void)getImages { if (![self queue]) { [self setQueue:[[[ASINetworkQueue alloc] init] autorelease]]; } GetImagesRequest *request = [GetImagesRequest request:self.account]; [queue addOperation:request]; } #pragma mark - #pragma mark Object Storage - (APICallback *)getStorageAccountInfo { __block OpenStackRequest *request = [OpenStackRequest getStorageAccountInfoRequest:self.account]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { self.account.containerCount = [[[request responseHeaders] objectForKey:@"X-Account-Container-Count"] intValue]; NSString *numStr = [[request responseHeaders] objectForKey:@"X-Account-Bytes-Used"]; self.account.totalBytesUsed = strtoull([numStr UTF8String], NULL, 0); [self.account persist]; self.account.containerCount = [self.account.containers count]; }]; } - (APICallback *)getSharingAccounts { __block OpenStackRequest *request = [OpenStackRequest getSharingAccountsRequest:self.account]; return [self callbackWithRequest:request]; } - (APICallback *)getContainers { __block OpenStackRequest *request = [OpenStackRequest filesRequest:self.account method:@"GET" path:@""]; return [self callbackWithRequest:request]; } - (APICallback *)createContainer:(Container *)container { TrackEvent(CATEGORY_CONTAINERS, EVENT_CREATED); __block OpenStackRequest *request = [OpenStackRequest createContainerRequest:self.account container:container]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { [self.account.containers setObject:container forKey:container.name]; [self.account persist]; self.account.containerCount = [self.account.containers count]; }]; } - (APICallback *)deleteContainer:(Container *)container { TrackEvent(CATEGORY_CONTAINERS, EVENT_DELETED); __block OpenStackRequest *request = [OpenStackRequest deleteContainerRequest:self.account container:container]; return [self callbackWithRequest:request]; } - (void)getObjects:(Container *)container { [self getObjects:container afterMarker:nil objectsBuffer:nil]; } - (void)getObjects:(Container *)container afterMarker:(NSString *)marker objectsBuffer:(NSMutableDictionary *)objectsBuffer { if (![self queue]) { [self setQueue:(ASINetworkQueue *)[[[NSOperationQueue alloc] init] autorelease]]; } GetObjectsRequest *request = [GetObjectsRequest request:self.account container:container marker:marker objectsBuffer:objectsBuffer]; [queue addOperation:request]; } - (void)updateCDNContainer:(Container *)container { TrackEvent(CATEGORY_CONTAINERS, EVENT_UPDATED); if (![self queue]) { [self setQueue:(ASINetworkQueue *)[[[NSOperationQueue alloc] init] autorelease]]; } UpdateCDNContainerRequest *request = [UpdateCDNContainerRequest request:self.account container:container]; [queue addOperation:request]; } - (void)getObjectsSucceeded:(OpenStackRequest *)request { if ([request isSuccess]) { Container *container = [request.userInfo objectForKey:@"container"]; NSMutableDictionary *objects = [request objects]; container.rootFolder = [Folder folder]; container.rootFolder.objects = objects; [self.account persist]; NSNotification *notification = [NSNotification notificationWithName:@"getObjectsSucceeded" object:self.account userInfo:[NSDictionary dictionaryWithObject:container forKey:@"container"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } else { NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } } - (void)getObjectsFailed:(OpenStackRequest *)request { NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } - (APICallback *)getContainerInfo:(Container *)container { __block OpenStackRequest *request = [OpenStackRequest getContainerInfoRequest:self.account container:container]; return [self callbackWithRequest:request]; } - (APICallback *)getObjectInfo:(Container *)container object:(StorageObject *)object { __block OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object]; return [self callbackWithRequest:request]; } - (APICallback *)getObjectInfo:(Container *)container object:(StorageObject *)object version:(NSString *)version { if (!version) return [self getObjectInfo:container object:object]; __block OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object version:version]; return [self callbackWithRequest:request]; } - (APICallback *)getObjectVersionsList:(Container *)container object:(StorageObject *)object { __block OpenStackRequest *request = [OpenStackRequest getObjectVersionsRequest:account container:container object:object]; return [self callbackWithRequest:request]; } - (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate { return [self getObject:container object:object downloadProgressDelegate:downloadProgressDelegate requestUserInfo:nil]; } - (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate requestUserInfo:(NSDictionary *)requestUserInfo { return [self getObject:container object:object downloadProgressDelegate:downloadProgressDelegate requestUserInfo:requestUserInfo version:nil]; } - (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate requestUserInfo:(NSDictionary *)requestUserInfo version:(NSString *)version{ __block OpenStackRequest *request = [OpenStackRequest getObjectRequest:self.account container:container object:object version:version]; request.delegate = self; request.downloadProgressDelegate = downloadProgressDelegate; request.showAccurateProgress = YES; if (requestUserInfo) { request.userInfo = requestUserInfo; } if (!objectDownloadRequests) self.objectDownloadRequests = [NSMutableDictionary dictionary]; [objectDownloadRequests setObject:request forKey:object.fullPath]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { OpenStackAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; NSString *filePath = [appDelegate.cacheDirectoryPath stringByAppendingFormat:@"/%@.%@",object.hash, object.name.pathExtension]; [[request responseData] writeToFile:filePath atomically:YES]; @synchronized(appDelegate.cachedObjectsDictionary) { if (!object.hash) object.hash = [request.responseHeaders objectForKey:@"X-Object-Hash"]; [appDelegate.cachedObjectsDictionary setObject:filePath forKey:object.hash]; [appDelegate saveCacheDictionary]; } [objectDownloadRequests removeObjectForKey:object.fullPath]; } failure:^(OpenStackRequest *request) { [objectDownloadRequests removeObjectForKey:object.fullPath]; }]; } - (APICallback *)writeObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate { TrackEvent(CATEGORY_FILES, EVENT_CREATED); __block OpenStackRequest *request = [OpenStackRequest writeObjectRequest:self.account container:container object:object]; request.delegate = self; request.uploadProgressDelegate = downloadProgressDelegate; request.showAccurateProgress = YES; return [self callbackWithRequest:request]; } - (APICallback *)deleteObject:(Container *)container object:(StorageObject *)object { TrackEvent(CATEGORY_FILES, EVENT_DELETED); __block OpenStackRequest *request = [OpenStackRequest deleteObjectRequest:self.account container:container object:object]; return [self callbackWithRequest:request]; } - (APICallback *)writeObjectMetadata:(Container *)container object:(StorageObject *)object { __block OpenStackRequest *request = [OpenStackRequest writeObjectMetadataRequest:self.account container:container object:object]; return [self callbackWithRequest:request]; } - (APICallback *)writeAccountMetadata:(NSDictionary *)accountInfo { __block OpenStackRequest *request = [OpenStackRequest writeAccountMetadataRequest:self.account withAccountInfo:accountInfo]; return [self callbackWithRequest:request]; } - (APICallback *)writeContainerPolicy:(Container *)container { __block OpenStackRequest *request = [OpenStackRequest writeContainerPolicyRequest:self.account container:container]; return [self callbackWithRequest:request]; } #pragma mark - #pragma mark Load Balancing - (APICallback *)getLoadBalancers:(NSString *)endpoint { __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancersRequest:self.account endpoint:endpoint]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { if (!self.account.loadBalancers) { self.account.loadBalancers = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease]; } NSLog(@"%@", self.account.loadBalancers); NSLog(@"%@", [(LoadBalancerRequest *)request loadBalancers:self.account]); NSLog(@"%@", endpoint); NSMutableDictionary *lbs = [(LoadBalancerRequest *)request loadBalancers:self.account]; for (NSString *identifier in lbs) { LoadBalancer *lb = [lbs objectForKey:identifier]; lb.region = [self.account loadBalancerRegionForEndpoint:endpoint]; NSLog(@"lb.region = %@", lb.region); } [self.account.loadBalancers setObject:lbs forKey:endpoint]; [self.account persist]; }]; } - (APICallback *)getLoadBalancerDetails:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint { __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancerDetailsRequest:self.account loadBalancer:loadBalancer endpoint:endpoint]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { LoadBalancer *newLB = [(LoadBalancerRequest *)request loadBalancer:self.account]; loadBalancer.status = newLB.status; loadBalancer.nodes = newLB.nodes; loadBalancer.connectionLoggingEnabled = newLB.connectionLoggingEnabled; // if (!self.account.loadBalancers) { // self.account.loadBalancers = [[NSMutableDictionary alloc] initWithCapacity:2]; // } // // NSLog(@"%@", self.account.loadBalancers); // NSLog(@"%@", [(LoadBalancerRequest *)request loadBalancers]); // NSLog(@"%@", endpoint); // NSMutableDictionary *lbs = [(LoadBalancerRequest *)request loadBalancers]; // // for (NSString *identifier in lbs) { // LoadBalancer *lb = [lbs objectForKey:identifier]; // lb.region = [self.account loadBalancerRegionForEndpoint:endpoint]; // NSLog(@"lb.region = %@", lb.region); // } // // [self.account.loadBalancers setObject:lbs forKey:endpoint]; [self.account persist]; }]; } - (APICallback *)getLoadBalancerProtocols:(NSString *)endpoint { __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancerProtocols:self.account endpoint:endpoint]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { self.account.lbProtocols = [(LoadBalancerRequest *)request protocols]; }]; } - (APICallback *)createLoadBalancer:(LoadBalancer *)loadBalancer { TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_CREATED); NSString *endpoint = @""; for (NSString *url in [self.account loadBalancerURLs]) { if ([url hasPrefix:[NSString stringWithFormat:@"https://%@", [loadBalancer.region lowercaseString]]]) { endpoint = url; break; } } __block LoadBalancerRequest *request = [LoadBalancerRequest createLoadBalancerRequest:self.account loadBalancer:loadBalancer endpoint:endpoint]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { }]; } - (APICallback *)updateLoadBalancer:(LoadBalancer *)loadBalancer { TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED); NSString *endpoint = [self.account loadBalancerEndpointForRegion:loadBalancer.region]; __block LoadBalancerRequest *request = [LoadBalancerRequest updateLoadBalancerRequest:self.account loadBalancer:loadBalancer endpoint:endpoint]; return [self callbackWithRequest:request]; } - (APICallback *)deleteLoadBalancer:(LoadBalancer *)loadBalancer { TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_DELETED); NSString *endpoint = [self.account loadBalancerEndpointForRegion:loadBalancer.region]; NSLog(@"endpoint: %@", endpoint); __block LoadBalancerRequest *request = [LoadBalancerRequest deleteLoadBalancerRequest:self.account loadBalancer:loadBalancer endpoint:endpoint]; return [self callbackWithRequest:request]; } - (APICallback *)updateLoadBalancerConnectionLogging:(LoadBalancer *)loadBalancer { TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED_LB_CONNECTION_LOGGING); __block LoadBalancerRequest *request = [LoadBalancerRequest updateConnectionLoggingRequest:self.account loadBalancer:loadBalancer]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { } failure:^(OpenStackRequest *request) { loadBalancer.connectionLoggingEnabled = !loadBalancer.connectionLoggingEnabled; }]; } - (APICallback *)getLoadBalancerConnectionThrottling:(LoadBalancer *)loadBalancer { __block LoadBalancerRequest *request = [LoadBalancerRequest getConnectionThrottlingRequest:self.account loadBalancer:loadBalancer]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { loadBalancer.connectionThrottle = [(LoadBalancerRequest *)request connectionThrottle]; }]; } - (APICallback *)updateLoadBalancerConnectionThrottling:(LoadBalancer *)loadBalancer { TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED_LB_CONNECTION_THROTTLING); __block LoadBalancerRequest *request = [LoadBalancerRequest updateConnectionThrottlingRequest:self.account loadBalancer:loadBalancer]; return [self callbackWithRequest:request]; } - (APICallback *)deleteLoadBalancerConnectionThrottling:(LoadBalancer *)loadBalancer { TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_DISABLED_LB_CONNECTION_THROTTLING); __block LoadBalancerRequest *request = [LoadBalancerRequest disableConnectionThrottlingRequest:self.account loadBalancer:loadBalancer]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { loadBalancer.connectionThrottle = nil; }]; } - (APICallback *)getLoadBalancerUsage:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint { __block LoadBalancerRequest *request = [LoadBalancerRequest getLoadBalancerUsageRequest:self.account loadBalancer:loadBalancer endpoint:endpoint]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { loadBalancer.usage = [(LoadBalancerRequest *)request usage]; }]; } - (APICallback *)addLBNodes:(NSArray *)nodes loadBalancer:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint { TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_ADDED_LB_NODES); __block LoadBalancerRequest *request = [LoadBalancerRequest addLoadBalancerNodesRequest:self.account loadBalancer:loadBalancer nodes:nodes endpoint:endpoint]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { for (LoadBalancerNode *node in nodes) { [loadBalancer.nodes addObject:node]; } [self.account persist]; }]; } - (APICallback *)updateLBNode:(LoadBalancerNode *)node loadBalancer:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint { TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_UPDATED_LB_NODE); __block LoadBalancerRequest *request = [LoadBalancerRequest updateLoadBalancerNodeRequest:self.account loadBalancer:loadBalancer node:node endpoint:endpoint]; return [self callbackWithRequest:request]; } - (APICallback *)deleteLBNode:(LoadBalancerNode *)node loadBalancer:(LoadBalancer *)loadBalancer endpoint:(NSString *)endpoint { TrackEvent(CATEGORY_LOAD_BALANCER, EVENT_DELETED_LB_NODE); __block LoadBalancerRequest *request = [LoadBalancerRequest deleteLoadBalancerNodeRequest:self.account loadBalancer:loadBalancer node:node endpoint:endpoint]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { [loadBalancer.nodes removeObject:node]; }]; } - (APICallback *)authenticate { __block OpenStackRequest *request = [OpenStackRequest authenticationRequest:self.account]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { if ([request isSuccess]) { self.account.authToken = [[request responseHeaders] objectForKey:@"X-Auth-Token"]; self.account.serversURL = [NSURL URLWithString:[[request responseHeaders] objectForKey:@"X-Server-Management-Url"]]; if (![[request responseHeaders] objectForKey:@"X-Storage-URL"]) { NSString *filesStorageURL = [NSString stringWithFormat:@"%@/v1/%@", [self.account.hostURL absoluteString], [self.account username]]; self.account.filesURL = [NSURL URLWithString:filesStorageURL]; } else { self.account.filesURL = [NSURL URLWithString:[[request responseHeaders] objectForKey:@"X-Storage-Url"]]; } self.account.pithosPublicLinkURLPrefix = self.account.hostURL; self.account.pithosLoginURLPrefix = [NSURL URLWithString: [[self.account.hostURL absoluteString] stringByAppendingString:@"/login"]]; self.account.cdnURL = [NSURL URLWithString:[[request responseHeaders] objectForKey:@"X-Cdn-Management-Url"]]; [self.account persist]; } }]; } #pragma mark - #pragma mark Memory Management - (void)dealloc { [objectDownloadRequests release]; [super dealloc]; } @end