2 // LBNodeViewController.m
5 // Created by Mike Mayo on 6/27/11.
6 // Copyright 2011 __MyCompanyName__. All rights reserved.
9 #import "LBNodeViewController.h"
10 #import "LoadBalancerNode.h"
11 #import "LoadBalancer.h"
12 #import "UIViewController+Conveniences.h"
13 #import "RSTextFieldCell.h"
14 #import "UIColor+MoreColors.h"
15 #import "OpenStackAccount.h"
16 #import "AccountManager.h"
17 #import "APICallback.h"
18 #import "LoadBalancerViewController.h"
20 #define kConditionSection 0
27 @implementation LBNodeViewController
29 @synthesize node, loadBalancer, account, lbViewController, lbIndexPath;
31 - (id)initWithNode:(LoadBalancerNode *)n loadBalancer:(LoadBalancer *)lb account:(OpenStackAccount *)a {
32 self = [self initWithStyle:UITableViewStyleGrouped];
35 self.loadBalancer = lb;
43 [loadBalancer release];
46 [lbIndexPath release];
50 #pragma mark - View lifecycle
54 self.navigationItem.title = self.node.address;
56 NSMutableArray *s = [[NSMutableArray alloc] initWithCapacity:3];
57 for (int i = 0; i < 3; i++) {
58 UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
59 spinner.hidesWhenStopped = YES;
60 [s addObject:spinner];
63 spinners = [[NSArray alloc] initWithArray:s];
66 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
72 // if there is only one enabled node on the load balancer, it can't be
74 if ([self.loadBalancer.nodes count] == 1) {
77 NSInteger enabledCount = 0;
78 for (LoadBalancerNode *n in self.loadBalancer.nodes) {
79 if ([n.condition isEqualToString:@"ENABLED"]) {
84 if (enabledCount <= 1 && [self.node.condition isEqualToString:@"ENABLED"]) {
90 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
91 return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (interfaceOrientation == UIInterfaceOrientationPortrait);
94 #pragma mark - Table view data source
96 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
100 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
101 if (section == kConditionSection) {
108 - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
109 if (section == kConditionSection) {
111 return @"Draining nodes are disabled after all current connections are completed.";
113 return @"There must be at least one enabled node for this load balancer.";
120 - (UITableViewCell *)removeNodeCell {
121 static NSString *CellIdentifier = @"RemoveNodeCell";
122 UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
124 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
125 cell.textLabel.textAlignment = UITextAlignmentCenter;
126 cell.textLabel.textColor = editable ? [UIColor value1DetailTextLabelColor] : [UIColor lightGrayColor];
127 cell.textLabel.text = @"Remove Node";
128 cell.selectionStyle = editable ? UITableViewCellSelectionStyleBlue : UITableViewCellSelectionStyleNone;
134 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
135 if (indexPath.section == kRemoveNode) {
136 return [self removeNodeCell];
138 static NSString *CellIdentifier = @"Cell";
140 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
142 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
145 cell.selectionStyle = editable ? UITableViewCellSelectionStyleBlue : UITableViewCellSelectionStyleNone;
147 switch (indexPath.row) {
149 cell.textLabel.text = @"Enabled";
150 cell.textLabel.textColor = [UIColor blackColor];
153 cell.textLabel.text = @"Draining";
154 cell.textLabel.textColor = editable ? [UIColor blackColor] : [UIColor lightGrayColor];
157 cell.textLabel.text = @"Disabled";
158 cell.textLabel.textColor = editable ? [UIColor blackColor] : [UIColor lightGrayColor];
164 if ([self.node.condition isEqualToString:[cell.textLabel.text uppercaseString]]) {
165 cell.accessoryType = UITableViewCellAccessoryCheckmark;
166 cell.accessoryView = nil;
168 cell.accessoryType = UITableViewCellAccessoryNone;
169 cell.accessoryView = [spinners objectAtIndex:indexPath.row];
176 #pragma mark - Table view delegate
178 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
180 if (indexPath.section == kConditionSection) {
182 if ([self.loadBalancer shouldBePolled]) {
183 [self alert:nil message:@"This node can not be changed until the load balancer is in an active state."];
184 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
186 NSString *oldCondition = [NSString stringWithString:self.node.condition];
188 switch (indexPath.row) {
190 self.node.condition = @"ENABLED";
193 self.node.condition = @"DRAINING";
196 self.node.condition = @"DISABLED";
203 NSString *endpoint = [self.account loadBalancerEndpointForRegion:self.loadBalancer.region];
204 [[spinners objectAtIndex:indexPath.row] startAnimating];
205 APICallback *callback = [self.account.manager updateLBNode:self.node loadBalancer:self.loadBalancer endpoint:endpoint];
207 [callback success:^(OpenStackRequest *request) {
208 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
209 [NSTimer scheduledTimerWithTimeInterval:0.35 target:self.tableView selector:@selector(reloadData) userInfo:nil repeats:NO];
210 } failure:^(OpenStackRequest *request) {
211 self.node.condition = oldCondition;
212 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
213 [NSTimer scheduledTimerWithTimeInterval:0.35 target:self.tableView selector:@selector(reloadData) userInfo:nil repeats:NO];
214 [self alert:@"There was a problem changing the condition of this node." request:request];
219 UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"Are you sure you want to remove this node from the load balancer?" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Delete" otherButtonTitles:nil];
220 sheet.delegate = self;
221 [sheet showInView:self.view];
227 #pragma mark - Action Sheet Delegate
229 - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
230 if (buttonIndex == 0) {
231 NSString *endpoint = [self.account loadBalancerEndpointForRegion:self.loadBalancer.region];
232 APICallback *callback = [self.account.manager deleteLBNode:self.node loadBalancer:self.loadBalancer endpoint:endpoint];
233 [callback success:^(OpenStackRequest *request) {
234 [self.navigationController popViewControllerAnimated:YES];
235 } failure:^(OpenStackRequest *request) {
236 [self alert:@"There was a problem removing this node." request:request];
239 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:kRemoveNode];
240 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
243 #pragma mark - Button Handlers
245 - (void)doneButtonPressed:(id)sender {
246 [self dismissModalViewControllerAnimated:YES];
247 [self.lbViewController.tableView deselectRowAtIndexPath:self.lbIndexPath animated:YES];