5 // Created by Mike Mayo on 10/4/10.
6 // The OpenStack project is provided under the Apache 2.0 license.
11 #import "NSObject+SBJSON.h"
14 #import "OpenStackAccount.h"
15 #import "NSObject+NSCoding.h"
16 #import "NSString+Conveniences.h"
19 @implementation Server
21 @synthesize progress, imageId, flavorId, status, hostId, addresses, metadata, image, flavor, urls, personality, backupSchedule, rootPassword;
24 // TODO: getter/setter for rootPassword should use Keychain class
25 // TODO: generate uuid for servers. key password on uuid
28 #pragma mark Serialization
30 - (void)encodeWithCoder: (NSCoder *)coder {
31 [self autoEncodeWithCoder:coder];
34 - (id)initWithCoder:(NSCoder *)coder {
35 if ((self = [super init])) {
36 [self autoDecode:coder];
42 - (id)copyWithZone:(NSZone *)zone {
43 Server *copy = [[Server allocWithZone:zone] init];
44 copy.identifier = self.identifier;
45 copy.imageId = self.imageId;
46 copy.flavorId = self.flavorId;
47 copy.status = self.status;
48 copy.addresses = self.addresses;
49 copy.image = self.image;
50 copy.flavor = self.flavor;
56 - (void)populateWithJSON:(NSDictionary *)dict {
57 self.identifier = [dict objectForKey:@"id"];
58 if ([dict objectForKey:@"flavorId"]) {
59 self.flavorId = [[dict objectForKey:@"flavorId"] description];
61 if ([dict objectForKey:@"flavor"]) {
62 Flavor *f = [Flavor fromJSON:[dict objectForKey:@"flavor"]];
63 self.flavorId = f.identifier;
65 if ([dict objectForKey:@"imageId"]) {
66 self.imageId = [[dict objectForKey:@"imageId"] description];
68 if ([dict objectForKey:@"image"]) {
69 self.image = [Image fromJSON:[dict objectForKey:@"image"]];
70 self.imageId = self.image.identifier;
72 self.addresses = [dict objectForKey:@"addresses"];
74 if ([[self.addresses objectForKey:@"public"] isKindOfClass:[NSArray class]]) {
76 NSMutableDictionary *newAddresses = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
78 NSArray *publicIPs = [self.addresses objectForKey:@"public"];
79 NSMutableArray *newPublicIPs = [[[NSMutableArray alloc] initWithCapacity:[publicIPs count]] autorelease];
80 for (NSDictionary *ip in publicIPs) {
81 if ([ip isKindOfClass:[NSDictionary class]]) {
82 [newPublicIPs addObject:[ip objectForKey:@"addr"]];
84 [newPublicIPs addObject:ip];
87 [newAddresses setObject:newPublicIPs forKey:@"public"];
89 NSArray *privateIPs = [self.addresses objectForKey:@"private"];
90 NSMutableArray *newPrivateIPs = [[[NSMutableArray alloc] initWithCapacity:[privateIPs count]] autorelease];
91 for (NSDictionary *ip in privateIPs) {
92 if ([ip isKindOfClass:[NSDictionary class]]) {
93 [newPrivateIPs addObject:[ip objectForKey:@"addr"]];
95 [newPrivateIPs addObject:ip];
98 [newAddresses setObject:newPrivateIPs forKey:@"private"];
100 self.addresses = newAddresses;
103 self.status = [dict objectForKey:@"status"];
105 if ([dict objectForKey:@"progress"]) {
106 self.progress = [[dict objectForKey:@"progress"] intValue];
110 - (id)initWithJSONDict:(NSDictionary *)dict {
111 self = [super initWithJSONDict:dict];
113 [self populateWithJSON:dict];
118 + (Server *)fromJSON:(NSDictionary *)dict {
119 Server *server = [[[Server alloc] initWithJSONDict:dict] autorelease];
120 [server populateWithJSON:dict];
124 - (NSString *)toJSON:(NSString *)apiVersion {
125 BOOL version1 = [apiVersion isEqualToString:@"1.0"];
128 = @"{ \"server\": { "
129 " \"name\": \"<name>\","
130 " \"<flavorType>\": <flavor>,"
131 " \"<imageType>\": <image>"
132 " <metadata><personality>"
134 json = [json replace:@"<name>" with:self.name];
135 json = [json replace:@"<flavorType>" with:version1 ? @"flavorId" : @"flavorRef"];
138 json = [json replace:@"<flavor>" with:self.flavorId];
140 json = [json replace:@"<flavor>" with:[NSString stringWithFormat:@"\"%@\"", self.flavorId]];
143 json = [json replace:@"<imageType>" with:version1 ? @"imageId" : @"imageRef"];
146 json = [json replace:@"<image>" with:self.imageId];
148 json = [json replace:@"<image>" with:[NSString stringWithFormat:@"\"%@\"", self.imageId]];
151 if (self.metadata && [self.metadata count] > 0) {
152 json = [json replace:@"<metadata>" with:[NSString stringWithFormat:@", \"metadata\": %@", [self.metadata JSONRepresentation]]];
154 json = [json replace:@"<metadata>" with:@""];
157 if (self.personality && [self.personality count] > 0) {
158 NSString *personalityJSON = @", \"personality\": [ ";
160 NSArray *paths = [self.personality allKeys];
161 for (int i = 0; i < [paths count]; i++) {
162 NSString *path = [paths objectAtIndex:i];
163 personalityJSON = [personalityJSON stringByAppendingString:[NSString stringWithFormat:@"{ \"path\": \"%@\", \"contents\": \"%@\" }", path, [Base64 encode:[[self.personality objectForKey:path] dataUsingEncoding:NSUTF8StringEncoding]]]];
164 if (i < [paths count] - 1) {
165 personalityJSON = [json stringByAppendingString:@", "];
168 personalityJSON = [personalityJSON stringByAppendingString:@" ]"];
170 json = [json replace:@"<personality>" with:personalityJSON];
173 json = [json replace:@"<personality>" with:@""];
182 - (BOOL)shouldBePolled {
183 return ([self.status isEqualToString:@"BUILD"] || [self.status isEqualToString:@"UNKNOWN"] || [self.status isEqualToString:@"RESIZE"] || [self.status isEqualToString:@"QUEUE_RESIZE"] || [self.status isEqualToString:@"PREP_RESIZE"] || [self.status isEqualToString:@"REBUILD"] || [self.status isEqualToString:@"REBOOT"] || [self.status isEqualToString:@"HARD_REBOOT"]);
189 - (void)setFlavor:(Flavor *)aFlavor {
192 self.flavorId = self.flavor.identifier;
199 for (OpenStackAccount *account in [OpenStackAccount accounts]) {
200 Image *i = [account.images objectForKey:self.imageId];
210 - (void)setImage:(Image *)anImage {
213 self.imageId = self.image.identifier;
219 #pragma mark Memory Management
229 [personality release];
230 [backupSchedule release];
231 [rootPassword release];