Revision b5f66d0e

b/AndroidManifest.xml
130 130
		<activity android:name=".EditNodesActivity"></activity>
131 131
		<activity android:name=".EditLoadBalancerActivity"></activity>
132 132
		<activity android:name=".AddMoreNodesActivity"></activity>
133
		<activity android:name=".AddExternalNodeActivity"></activity>
133 134

  
134 135

  
135 136

  
b/res/layout/addexternalnode.xml
1
<?xml version="1.0" encoding="utf-8"?>
2
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
3
	android:orientation="vertical" android:layout_height="fill_parent"
4
	android:layout_width="fill_parent">
5
	<LinearLayout android:layout_height="wrap_content"
6
		android:id="@+id/linearLayout1" android:orientation="vertical"
7
		android:layout_width="fill_parent">
8
		<TextView android:id="@+id/textView1" android:layout_width="wrap_content"
9
			android:layout_height="wrap_content" android:text="IP Address"
10
			android:layout_marginLeft="10dip" android:layout_marginTop="10dip"></TextView>
11
		<EditText android:layout_height="wrap_content"
12
			android:layout_width="fill_parent" android:layout_marginLeft="20dip"
13
			android:layout_marginRight="30dip" android:id="@+id/ip_address"></EditText>
14
		<TextView android:id="@+id/textView2" android:layout_width="wrap_content"
15
			android:layout_height="wrap_content" android:layout_marginLeft="10dip"
16
			android:text="Port"></TextView>
17
		<EditText android:layout_width="fill_parent"
18
			android:layout_height="wrap_content" android:inputType="number"
19
			android:layout_marginLeft="20dip" android:layout_marginRight="30dip"
20
			android:id="@+id/node_port_text">
21
			<requestFocus></requestFocus>
22
		</EditText>
23
		<TextView android:layout_width="wrap_content" android:id="@+id/TextView01"
24
			android:layout_marginLeft="10dip" android:layout_height="wrap_content"
25
			android:text="Condition"></TextView>
26
		<Spinner android:layout_marginLeft="20dip"
27
			android:layout_height="wrap_content" android:layout_width="fill_parent"
28
			android:layout_marginRight="30dip" android:id="@+id/node_condition_spinner"></Spinner>
29
		<TextView android:layout_height="wrap_content"
30
			android:layout_marginLeft="10dip" android:id="@+id/node_weight_label"
31
			android:layout_width="wrap_content" android:text="Weight"></TextView>
32
		<EditText android:layout_height="wrap_content"
33
			android:layout_marginRight="30dip" android:layout_marginLeft="20dip"
34
			android:inputType="number" android:layout_width="fill_parent"
35
			android:id="@+id/node_weight_text"></EditText>
36
		<Button android:layout_gravity="center_horizontal"
37
			android:layout_marginTop="10dip" android:layout_marginBottom="10dip"
38
			android:layout_width="120dip" android:text="Submit" android:id="@+id/add_node_button"
39
			android:layout_height="wrap_content"></Button>
40
	</LinearLayout>
41

  
42
</ScrollView>
b/res/layout/addnode.xml
1 1
<?xml version="1.0" encoding="utf-8"?>
2 2
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
3
	android:orientation="vertical" android:layout_height="fill_parent" android:layout_width="fill_parent">
3
	android:orientation="vertical" android:layout_height="fill_parent"
4
	android:layout_width="fill_parent">
4 5
	<LinearLayout android:layout_height="wrap_content"
5
		android:id="@+id/linearLayout1" android:orientation="vertical" android:layout_width="fill_parent">
6
		<TextView android:id="@+id/node_name" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="CentOS1" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_marginLeft="10dip" android:layout_marginTop="10dip"></TextView>
7
		<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="IP Address" android:layout_marginLeft="10dip" android:layout_marginTop="10dip"></TextView>
8
		<Spinner android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_marginLeft="20dip" android:layout_marginRight="30dip" android:id="@+id/node_ip_spinner"></Spinner>
9
		<TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dip" android:text="Port"></TextView>
10
		<EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputType="number" android:layout_marginLeft="20dip" android:layout_marginRight="30dip" android:id="@+id/node_port_text">
6
		android:id="@+id/linearLayout1" android:orientation="vertical"
7
		android:layout_width="fill_parent">
8
		<TextView android:id="@+id/node_name" android:layout_height="wrap_content"
9
			android:layout_width="wrap_content" android:text="CentOS1"
10
			android:textAppearance="?android:attr/textAppearanceLarge"
11
			android:layout_marginLeft="10dip" android:layout_marginTop="10dip"></TextView>
12
		<TextView android:id="@+id/textView1" android:layout_width="wrap_content"
13
			android:layout_height="wrap_content" android:text="IP Address"
14
			android:layout_marginLeft="10dip" android:layout_marginTop="10dip"></TextView>
15
		<Spinner android:layout_height="wrap_content"
16
			android:layout_width="fill_parent" android:layout_marginLeft="20dip"
17
			android:layout_marginRight="30dip" android:id="@+id/node_ip_spinner"></Spinner>
18
		<TextView android:id="@+id/textView2" android:layout_width="wrap_content"
19
			android:layout_height="wrap_content" android:layout_marginLeft="10dip"
20
			android:text="Port"></TextView>
21
		<EditText android:layout_width="fill_parent"
22
			android:layout_height="wrap_content" android:inputType="number"
23
			android:layout_marginLeft="20dip" android:layout_marginRight="30dip"
24
			android:id="@+id/node_port_text">
11 25
			<requestFocus></requestFocus>
12 26
		</EditText>
13
		<TextView android:layout_width="wrap_content" android:id="@+id/TextView01" android:layout_marginLeft="10dip" android:layout_height="wrap_content" android:text="Condition"></TextView>
14
		<Spinner android:layout_marginLeft="20dip" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_marginRight="30dip" android:id="@+id/node_condition_spinner"></Spinner>
15
		<TextView android:layout_height="wrap_content" android:layout_marginLeft="10dip" android:id="@+id/node_weight_label" android:layout_width="wrap_content" android:text="Weight"></TextView>
16
		<EditText android:layout_height="wrap_content" android:layout_marginRight="30dip" android:layout_marginLeft="20dip" android:inputType="number" android:layout_width="fill_parent" android:id="@+id/node_weight_text"></EditText>
17
		<Button android:layout_gravity="center_horizontal" android:layout_marginTop="10dip" android:layout_marginBottom="10dip" android:layout_width="120dip" android:text="Submit" android:id="@+id/add_node_button" android:layout_height="wrap_content"></Button>
27
		<TextView android:layout_width="wrap_content" android:id="@+id/TextView01"
28
			android:layout_marginLeft="10dip" android:layout_height="wrap_content"
29
			android:text="Condition"></TextView>
30
		<Spinner android:layout_marginLeft="20dip"
31
			android:layout_height="wrap_content" android:layout_width="fill_parent"
32
			android:layout_marginRight="30dip" android:id="@+id/node_condition_spinner"></Spinner>
33
		<TextView android:layout_height="wrap_content"
34
			android:layout_marginLeft="10dip" android:id="@+id/node_weight_label"
35
			android:layout_width="wrap_content" android:text="Weight"></TextView>
36
		<EditText android:layout_height="wrap_content"
37
			android:layout_marginRight="30dip" android:layout_marginLeft="20dip"
38
			android:inputType="number" android:layout_width="fill_parent"
39
			android:id="@+id/node_weight_text"></EditText>
40
		<Button android:layout_gravity="center_horizontal"
41
			android:layout_marginTop="10dip" android:layout_marginBottom="10dip"
42
			android:layout_width="120dip" android:text="Submit" android:id="@+id/add_node_button"
43
			android:layout_height="wrap_content"></Button>
18 44
	</LinearLayout>
19 45

  
20 46
</ScrollView>
b/res/layout/addnodes.xml
14 14
					android:layout_height="417dp" android:id="@android:id/list"></ListView>
15 15
			</LinearLayout>
16 16
		</ScrollView>
17
		<Button android:layout_height="wrap_content" android:layout_alignParentBottom="true"
18
			android:layout_centerInParent="true" android:layout_marginBottom="15dip"
19
			android:layout_width="120dp" android:text="Add Nodes"
20
			android:layout_marginTop="5dip" android:id="@+id/submit_nodes_button"></Button>
17
		<LinearLayout android:id="@+id/linearLayout1"
18
			android:layout_width="wrap_content" android:layout_height="wrap_content"
19
			android:layout_alignParentRight="true"
20
			android:layout_alignParentLeft="true" android:layout_below="@+id/node_scroll"
21
			android:gravity="center_horizontal">
22
			<Button android:id="@+id/submit_nodes_button"
23
				android:layout_marginBottom="15dip" android:layout_height="wrap_content"
24
				android:layout_marginTop="5dip" android:text="Add Selected Nodes"
25
				android:layout_width="145dip"></Button>
26
			<Button android:layout_marginBottom="15dip"
27
				android:layout_height="wrap_content" android:layout_marginTop="5dip"
28
				android:id="@+id/add_external_node" android:text="Add External Node"
29
				android:layout_width="145dip"></Button>
30
		</LinearLayout>
21 31
	</RelativeLayout>
22 32
</LinearLayout>
23 33

  
b/res/layout/editnodes.xml
1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
	android:orientation="vertical" android:layout_width="fill_parent"
4
	android:layout_height="fill_parent">
5
	<RelativeLayout android:layout_width="fill_parent"
6
		android:id="@+id/nodes_relative" android:layout_height="fill_parent">
7
		<ScrollView android:layout_height="wrap_content"
8
			android:orientation="vertical" android:layout_width="wrap_content"
9
			android:id="@+id/node_scroll" android:layout_above="@+id/submit_nodes_button">
10
			<LinearLayout android:layout_width="fill_parent"
11
				android:id="@+id/nodes_linear_layout" android:layout_height="fill_parent">
12
				<ListView android:layout_weight="1" android:layout_width="fill_parent"
13
					android:cacheColorHint="@android:color/transparent"
14
					android:layout_height="417dp" android:id="@android:id/list"></ListView>
15
			</LinearLayout>
16
		</ScrollView>
17
		<LinearLayout android:id="@+id/linearLayout1"
18
			android:layout_width="wrap_content" android:layout_height="wrap_content"
19
			android:layout_alignParentRight="true"
20
			android:layout_alignParentLeft="true" android:layout_below="@+id/node_scroll"
21
			android:gravity="center_horizontal">
22
			<Button android:id="@+id/submit_nodes_button"
23
				android:layout_marginBottom="15dip" android:layout_height="wrap_content"
24
				android:layout_marginTop="5dip" android:layout_width="145dip" android:text="Add More Nodes"></Button>
25
		</LinearLayout>
26
	</RelativeLayout>
27
</LinearLayout>
28

  
29
  
b/res/layout/listservernodecell.xml
1 1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
	android:orientation="horizontal" android:layout_width="fill_parent"
4
	android:layout_height="64dip">
5
	<ImageView android:id="@+id/icon" android:layout_width="37px"
6
		android:paddingLeft="0px" android:paddingRight="0px"
7
		android:paddingTop="0px" android:layout_marginRight="10px"
8
		android:layout_marginLeft="10px" android:layout_marginTop="13px"
9
		android:layout_height="37px" android:src="@drawable/ubuntu_icon" />
2
<RelativeLayout android:id="@+id/LinearLayout1" xmlns:android="http://schemas.android.com/apk/res/android"
3
	android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content">
4
    <TextView android:textColor="#FFFFFF" android:id="@+id/label" android:layout_height="wrap_content" android:text="Server Name" android:textSize="24sp" android:lines="1" android:layout_width="wrap_content" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/add_node_checkbox" android:layout_marginLeft="14dp" android:layout_marginTop="1dip"></TextView>
5
    <CheckBox android:id="@+id/add_node_checkbox" android:layout_height="wrap_content" android:focusable="false" android:layout_width="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_marginLeft="16dp"></CheckBox>
6
    <TextView android:textColor="#FFFFFF" android:id="@+id/sublabel" android:layout_height="wrap_content" android:text="256 server - CentOS 5.3" android:textSize="12sp" android:layout_width="wrap_content" android:layout_below="@+id/label" android:layout_alignLeft="@+id/label" android:paddingBottom="5dip"></TextView>
10 7

  
11
	<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
12
		android:orientation="vertical" android:layout_width="fill_parent"
13
		android:layout_height="fill_parent">
14 8

  
15
		<TableRow>
16
			<RelativeLayout android:id="@+id/relativeLayout1"
17
				android:layout_width="wrap_content" android:layout_height="wrap_content">
18
				<CheckBox android:layout_width="wrap_content"
19
					android:layout_height="wrap_content" android:layout_centerVertical="true"
20
					android:layout_alignParentRight="true" android:layout_marginRight="10dip"
21
					android:id="@+id/add_node_checkbox" android:focusable="false"></CheckBox>
22
				<TextView android:layout_width="wrap_content" android:id="@+id/label"
23
					android:layout_height="wrap_content" android:textSize="24sp"
24
					android:textColor="#FFFFFF" android:layout_centerVertical="true"
25
					android:layout_alignParentLeft="true" android:layout_marginLeft="16dp"
26
					android:layout_toLeftOf="@+id/checkBox1" android:lines="1"></TextView>
27
			</RelativeLayout>
28
		</TableRow>
29

  
30
		<TableRow>
31
			<TextView android:id="@+id/sublabel" android:layout_width="wrap_content"
32
				android:layout_height="wrap_content" android:layout_marginTop="0px"
33
				android:textColor="#FFFFFF" android:text="256 server - CentOS 5.3"
34
				android:textSize="12sp" />
35
		</TableRow>
36
	</TableLayout>
37

  
38

  
39
</LinearLayout>
9
</RelativeLayout>
b/src/com/rackspacecloud/android/AddExternalNodeActivity.java
1
package com.rackspacecloud.android;
2

  
3
import android.app.Activity;
4
import android.content.Intent;
5
import android.os.Bundle;
6
import android.util.Log;
7
import android.view.View;
8
import android.view.Window;
9
import android.view.View.OnClickListener;
10
import android.widget.AdapterView;
11
import android.widget.ArrayAdapter;
12
import android.widget.Button;
13
import android.widget.EditText;
14
import android.widget.Spinner;
15
import android.widget.TextView;
16
import android.widget.AdapterView.OnItemSelectedListener;
17

  
18
public class AddExternalNodeActivity extends CloudActivity {
19

  
20
	private final String[] CONDITIONS = {"Enabled", "Disabled", "Draining"};
21
	private String name;
22
	private String selectedPort;
23
	private String selectedIp;
24
	private String selectedWeight;
25
	private boolean weighted;
26
	private String selectedCondition;
27
	private Spinner conditionSpinner;
28
	private EditText ipAddress;
29
	private EditText weightText;
30

  
31
	public void onCreate(Bundle savedInstanceState) {
32
		super.onCreate(savedInstanceState);
33
		requestWindowFeature(Window.FEATURE_NO_TITLE);
34
		setContentView(R.layout.addexternalnode);
35
		weighted = (Boolean) this.getIntent().getExtras().get("weighted");
36
		restoreState(savedInstanceState);
37
	} 
38

  
39
	protected void restoreState(Bundle state) {
40
		super.restoreState(state);
41
		setupInputs();
42
	}
43

  
44
	private void setupInputs(){
45

  
46
		ipAddress = (EditText) findViewById(R.id.ip_address);
47
		
48
		weightText = (EditText) findViewById(R.id.node_weight_text);
49

  
50
		//if algorithm is not weighted then then node's weight will be null
51
		if(!weighted){
52
			TextView weightLabel = (TextView) findViewById(R.id.node_weight_label);
53
			weightLabel.setVisibility(View.GONE);
54
			weightText.setVisibility(View.GONE);
55
		}
56

  
57
		loadConditionSpinner();
58
		setUpButton();
59

  
60
	}
61

  
62
	private void setUpButton(){
63
		Button submit = (Button) findViewById(R.id.add_node_button);
64
		submit.setOnClickListener(new OnClickListener() {
65

  
66
			@Override
67
			public void onClick(View v) {
68
				selectedIp = ipAddress.getText().toString();
69
				selectedPort = ((EditText)findViewById(R.id.node_port_text)).getText().toString();
70
				selectedWeight = weightText.getText().toString();
71
				if(!validPort()){
72
					showAlert("Error", "Must have a protocol port number that is between 1 and 65535.");
73
				} else if(!(weightText.getVisibility() == View.GONE || (weightText.getVisibility() != View.GONE && validWeight(selectedWeight)))){
74
					showAlert("Error", "Weight must be between 1 and 100.");
75
				} else if(ipAddress.getText().toString().equals("")){
76
					//TODO use regex to validate the ip for IPV4 and IPV6
77
					showAlert("Error", "Enter an IP Address");
78
				}
79

  
80
				else{
81
					Intent data = new Intent();
82
					data.putExtra("nodeIp", selectedIp);
83
					data.putExtra("nodePort", selectedPort);
84
					data.putExtra("nodeCondition", selectedCondition);
85
					data.putExtra("nodeWeight", selectedWeight);
86
					setResult(RESULT_OK, data);
87
					finish();
88
				}
89

  
90
			}
91
		});
92
	}
93

  
94
	public void onBackPressed(){
95
		setResult(RESULT_CANCELED);
96
		finish();
97
	}
98

  
99
	private void loadConditionSpinner(){
100
		conditionSpinner = (Spinner) findViewById(R.id.node_condition_spinner);
101

  
102
		ArrayAdapter<String> conditionAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, CONDITIONS);
103
		conditionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
104
		conditionSpinner.setAdapter(conditionAdapter);
105

  
106
		conditionSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
107

  
108
			@Override
109
			public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
110
				selectedCondition = CONDITIONS[pos];	
111
			}
112

  
113
			@Override
114
			public void onNothingSelected(AdapterView<?> arg0) {
115

  
116
			}
117

  
118
		});
119
	}
120

  
121
	private boolean validPort(){
122
		return !selectedPort.equals("") && Integer.valueOf(selectedPort) > 0 && Integer.valueOf(selectedPort) < 65536;
123
	}
124

  
125
	private Boolean validWeight(String weight){
126
		if(weight.equals("")){
127
			return false;
128
		}
129
		else{
130
			int w = Integer.valueOf(weight);
131
			return w >= 1 && w <= 100 ;
132
		}
133
	}
134

  
135
}
136

  
b/src/com/rackspacecloud/android/AddMoreNodesActivity.java
28 28
import android.widget.LinearLayout;
29 29
import android.widget.ListView;
30 30
import android.widget.CompoundButton.OnCheckedChangeListener;
31
import android.widget.ImageView;
32 31
import android.widget.TextView;
33 32

  
34 33
public class AddMoreNodesActivity extends CloudListActivity {
35 34

  
36 35
	private static final int ADD_NODE_CODE = 178;
37
	private Server[] servers; 
36
	private static final int ADD_EXTERNAL_NODE_CODE = 188;
37
	private ArrayList<Server> servers; 
38 38
	private int lastCheckedPos;
39 39
	private ArrayList<Node> nodes;
40 40
	private ArrayList<Node> nodesToAdd;
......
53 53
	@Override
54 54
	protected void onSaveInstanceState(Bundle outState) {
55 55
		super.onSaveInstanceState(outState);
56
		
56

  
57 57
		outState.putSerializable("nodes", nodes);
58 58
		outState.putSerializable("loadBalancer", loadBalancer);
59 59
		outState.putSerializable("nodesToAdd", nodesToAdd);
......
70 70
				nodes = new ArrayList<Node>();
71 71
			}
72 72
		}
73
		
73

  
74 74
		if (state != null && state.containsKey("loadBalancer")){
75 75
			loadBalancer = (LoadBalancer) state.getSerializable("loadBalancer");
76 76
			if(loadBalancer == null){
77 77
				loadBalancer = new LoadBalancer();
78 78
			}
79 79
		}
80
		
80

  
81 81
		if (state != null && state.containsKey("nodesToAdd")){
82 82
			nodesToAdd = (ArrayList<Node>) state.getSerializable("nodesToAdd");
83 83
		}
......
86 86
		}
87 87

  
88 88
		if (state != null && state.containsKey("servers") && state.getSerializable("servers") != null) {
89
			servers = (Server[]) state.getSerializable("servers");
90
			if (servers.length == 0) {
89
			servers = (ArrayList<Server>) state.getSerializable("servers");
90
			if (servers.size() == 0) {
91 91
				displayNoServersCell();
92 92
			} else {
93 93
				getListView().setDividerHeight(1); // restore divider lines
......
98 98
		}
99 99

  
100 100
		Button submitNodes = (Button) findViewById(R.id.submit_nodes_button);
101
		submitNodes.setText("Submit");
102 101
		submitNodes.setOnClickListener(new OnClickListener() {
103 102

  
104 103
			@Override
105 104
			public void onClick(View v) {
106
				new AddNodesTask().execute();
105
				if(nodesToAdd.size() == 0){
106
					finish();
107
				} else {
108
					new AddNodesTask().execute();
109
				}
110
			}
111
		});
112

  
113
		Button addExternalNode = (Button) findViewById(R.id.add_external_node);
114
		addExternalNode.setOnClickListener(new OnClickListener() {
115

  
116
			@Override
117
			public void onClick(View v) {
118
				Intent viewIntent = new Intent(getContext(), AddExternalNodeActivity.class);
119
				viewIntent.putExtra("weighted", false);
120
				startActivityForResult(viewIntent, ADD_EXTERNAL_NODE_CODE);
107 121
			}
108 122
		});
109 123
	}
......
127 141
		if (servers == null) {
128 142
			servers = new ArrayList<Server>();
129 143
		}
130
		
144

  
131 145
		for(int i = 0; i < servers.size(); i++) {
132 146
			/*
133 147
			 * if all the IP's of a server are
......
138 152
				servers.remove(i);
139 153
			}
140 154
		}
141
		
155

  
142 156
		String[] serverNames = new String[servers.size()];
143
		this.servers = new Server[servers.size()];
157
		this.servers = new ArrayList<Server>();
144 158

  
145 159
		for(int i = 0; i < servers.size(); i++){
146 160
			serverNames[i] = servers.get(i).getName();
147
			this.servers[i] = servers.get(i);
161
			this.servers.add(i, servers.get(i));
148 162
		}
149
		
163

  
150 164
		if (serverNames.length == 0) {
151 165
			displayNoServersCell();
152 166
		} else {
......
198 212

  
199 213
		public View getView(int position, View convertView, ViewGroup parent) {
200 214

  
201
			final Server server = servers[position];
215
			final Server server = servers.get(position);
202 216
			LayoutInflater inflater = getLayoutInflater();
203 217
			View row = inflater.inflate(R.layout.listservernodecell, parent, false);
204 218

  
......
206 220
			label.setText(server.getName());
207 221

  
208 222
			TextView sublabel = (TextView) row.findViewById(R.id.sublabel);
209
			sublabel.setText(server.getFlavor().getName() + " - " + server.getImage().getName());
210

  
211
			ImageView icon = (ImageView) row.findViewById(R.id.icon);
212
			icon.setImageResource(server.getImage().iconResourceId());
223
			if(server.getName().equals("External Node")){
224
				sublabel.setText(server.getPrivateIpAddresses()[0]);
225
			} else {
226
				sublabel.setText(server.getFlavor().getName() + " - " + server.getImage().getName());
227
			}
213 228

  
214 229
			String[] publicIp = server.getPublicIpAddresses();
215 230
			String[] privateIp = server.getPrivateIpAddresses();
216 231

  
232
			if(publicIp == null){
233
				publicIp = new String[0];
234
			}
235

  
236
			if(privateIp == null){
237
				privateIp = new String[0];
238
			}
239

  
217 240
			ArrayList<String> ipAddressList = new ArrayList<String>();
218 241
			for(int i = 0; i < privateIp.length; i++){
219 242
				if(!nodeHasAddress(privateIp[i])){
......
229 252
			final String[] ipAddresses = ipAddressList.toArray(new String[ipAddressList.size()]);
230 253
			final int pos = position;
231 254
			CheckBox add = (CheckBox) row.findViewById(R.id.add_node_checkbox);
232
			
255

  
233 256
			if(inToAddList(server)){
234 257
				add.setChecked(true);
235 258
			}
236
			
259

  
237 260
			add.setOnCheckedChangeListener(new OnCheckedChangeListener() {
238 261

  
239 262
				@Override
......
247 270
						startActivityForResult(viewIntent, ADD_NODE_CODE);
248 271
					}
249 272
					else{
250
						Log.d("info", "before removing node, size is " + nodesToAdd.size());
251 273
						removeNodeFromList(server);
252
						Log.d("info", "after removing node, size is " + nodesToAdd.size());
274
						if(server.getName().equals("External Node")){
275
							servers.remove(server);
276
							setServerList(servers);
277
						}
253 278
					}
254 279
				}
255 280
			});
256 281

  
257 282
			return(row);
258 283
		}
259
		
284

  
260 285
		/*
261 286
		 *  need to remove by id because that is 
262 287
		 *  what is unique
......
287 312
		}
288 313
		return false;
289 314
	}
290
	
315

  
291 316
	private boolean inToAddList(Server server){
292 317
		for(Node node : nodesToAdd){
293 318
			if(serverHasIp(server, node.getAddress())){
......
297 322
		return false;
298 323
	}
299 324

  
300
	
325

  
301 326
	private class AddNodesTask extends AsyncTask<Void, Void, HttpBundle> {
302 327
		private CloudServersException exception;
303 328

  
304 329
		protected void onPreExecute(){
305 330
			showDialog();
306 331
		}
307
		
332

  
308 333
		@Override
309 334
		protected HttpBundle doInBackground(Void... arg0) {
310 335
			HttpBundle bundle = null;
......
343 368

  
344 369
	private class LoadServersTask extends AsyncTask<Void, Void, ArrayList<Server>> {
345 370
		private CloudServersException exception;
346
	
371

  
347 372
		@Override
348 373
		protected void onPreExecute(){
349 374
			showDialog();
350 375
		}
351
	
376

  
352 377
		@Override
353 378
		protected ArrayList<Server> doInBackground(Void... arg0) {
354 379
			ArrayList<Server> servers = null;
......
359 384
			} 
360 385
			return servers;
361 386
		}
362
	
387

  
363 388
		@Override
364 389
		protected void onPostExecute(ArrayList<Server> result) {
365 390
			hideDialog();
......
370 395
		}
371 396
	}
372 397

  
398
	private String getNameFromIp(String address){
399
		for(Server s: servers){
400
			if(serverHasIp(s, address)){
401
				return s.getName();
402
			}
403
		}
404
		return "";
405
	}
406

  
407
	private boolean isCloudServerIp(String address){
408
		for(Server s : servers){
409
			if(serverHasIp(s, address)){
410
				return true;
411
			}
412
		}
413
		return false;
414
	}
415

  
373 416
	protected void onActivityResult(int requestCode, int resultCode, Intent data){
374 417
		int pos = lastCheckedPos;
375 418
		if(requestCode == ADD_NODE_CODE && resultCode == RESULT_OK){
376 419
			Node node = new Node();
377 420
			node.setAddress(data.getStringExtra("nodeIp"));
378 421
			node.setCondition(data.getStringExtra("nodeCondition"));
379
			node.setName(servers[pos].getName());
422
			node.setName(servers.get(pos).getName());
380 423
			node.setPort(data.getStringExtra("nodePort"));
381 424
			Log.d("info", "setting the weight in addmore to " + data.getStringExtra("nodeWeight"));
382 425
			node.setWeight(data.getStringExtra("nodeWeight"));
......
390 433
			CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
391 434
			checkBox.setChecked(false);
392 435
		}
393
	}
394

  
436
		else if(requestCode == ADD_EXTERNAL_NODE_CODE && resultCode == RESULT_OK){
437
			Node node = new Node();
438
			node.setAddress(data.getStringExtra("nodeIp"));
439
			node.setCondition(data.getStringExtra("nodeCondition"));
440
			node.setName("External Node");
441
			node.setPort(data.getStringExtra("nodePort"));
442
			node.setWeight(data.getStringExtra("nodeWeight"));
395 443

  
444
			/*
445
			 * If the ip is from a cloud server, alert to user
446
			 * so they can select it from there
447
			 */	
448
			if(!isCloudServerIp(node.getAddress())){
449
				nodesToAdd.add(node);
450
				//Add it to server list so it display in the listview
451
				Server server = new Server();
452
				server.setName("External Node");
453
				String[] ip = {data.getStringExtra("nodeIp")};
454
				server.setPrivateIpAddresses(ip);
455
				servers.add(server);
456
			} else {
457
				showAlert("Error", "This IP belongs to a cloud server: \"" + getNameFromIp(node.getAddress()) 
458
						+ "\", please select it from the list.");
459
			}
460
		}
461
	}
396 462
}
b/src/com/rackspacecloud/android/AddNodesActivity.java
10 10
import android.content.Intent;
11 11
import android.os.AsyncTask;
12 12
import android.os.Bundle;
13
import android.util.Log;
14 13
import android.view.LayoutInflater;
15 14
import android.view.View;
16 15
import android.view.View.OnClickListener;
......
22 21
import android.widget.LinearLayout;
23 22
import android.widget.ListView;
24 23
import android.widget.CompoundButton.OnCheckedChangeListener;
25
import android.widget.ImageView;
26 24
import android.widget.TextView;
27 25

  
28 26
public class AddNodesActivity extends CloudListActivity {
29 27

  
30 28
	private static final int ADD_NODE_CODE = 178;
29
	private static final int ADD_EXTERNAL_NODE_CODE = 188;
31 30

  
32
	private Server[] servers;
31
	private ArrayList<Server> servers;
33 32
	private int lastCheckedPos;
34 33
	private ArrayList<Node> nodes;
35 34

  
......
61 60
		}
62 61

  
63 62
		if (state != null && state.containsKey("servers")) {
64
			servers = (Server[]) state.getSerializable("servers");
65
			if (servers.length == 0) {
63
			servers = (ArrayList<Server>) state.getSerializable("servers");
64
			if (servers.size() == 0) {
66 65
				displayNoServersCell();
67 66
			} else {
68 67
				getListView().setDividerHeight(1); // restore divider lines
......
83 82
				finish();
84 83
			}
85 84
		});
85

  
86
		Button addExternalNode = (Button) findViewById(R.id.add_external_node);
87
		addExternalNode.setOnClickListener(new OnClickListener() {
88

  
89
			@Override
90
			public void onClick(View v) {
91
				Intent viewIntent = new Intent(getContext(), AddExternalNodeActivity.class);
92
				viewIntent.putExtra("weighted", false);
93
				startActivityForResult(viewIntent, ADD_EXTERNAL_NODE_CODE);
94
			}
95
		});
86 96
	}
87 97

  
88 98
	@Override
......
105 115
			servers = new ArrayList<Server>();
106 116
		}
107 117
		String[] serverNames = new String[servers.size()];
108
		this.servers = new Server[servers.size()];
118
		this.servers = new ArrayList<Server>();
109 119

  
110 120
		if (servers != null) {
111 121
			for (int i = 0; i < servers.size(); i++) {
112 122
				Server server = servers.get(i);
113
				this.servers[i] = server;
123
				this.servers.add(i, server);
114 124
				serverNames[i] = server.getName();
115 125
			}
116 126
		}
......
152 162
			if (exception != null) {
153 163
				showAlert("Error", exception.getMessage());
154 164
			}
165

  
166
			//Add the external nodes
167
			for(int i = 0; i < nodes.size(); i++){
168
				if(nodes.get(i).getName().equals("External Node")){
169
					Server server = new Server();
170
					server.setName("External Node");
171
					String[] ip = {nodes.get(i).getAddress()};
172
					server.setPrivateIpAddresses(ip);
173
					result.add(server);
174
				}
175
			}
155 176
			setServerList(result);
156 177
		}
157 178
	}
......
164 185

  
165 186
		public View getView(int position, View convertView, ViewGroup parent) {
166 187

  
167
			final Server server = servers[position];
188
			final Server server = servers.get(position);
168 189
			LayoutInflater inflater = getLayoutInflater();
169 190
			View row = inflater.inflate(R.layout.listservernodecell, parent, false);
170 191

  
......
172 193
			label.setText(server.getName());
173 194

  
174 195
			TextView sublabel = (TextView) row.findViewById(R.id.sublabel);
175
			sublabel.setText(server.getFlavor().getName() + " - " + server.getImage().getName());
176

  
177
			ImageView icon = (ImageView) row.findViewById(R.id.icon);
178
			icon.setImageResource(server.getImage().iconResourceId());
196
			if(server.getName().equals("External Node")){
197
				sublabel.setText(server.getPrivateIpAddresses()[0]);
198
			} else {
199
				sublabel.setText(server.getFlavor().getName() + " - " + server.getImage().getName());
200
			}
179 201

  
180 202
			String[] publicIp = server.getPublicIpAddresses();
181 203
			String[] privateIp = server.getPrivateIpAddresses();
182 204

  
205
			if(publicIp == null){
206
				publicIp = new String[0];
207
			}
208

  
209
			if(privateIp == null){
210
				privateIp = new String[0];
211
			}
183 212

  
184 213
			final String[] ipAddresses = new String[privateIp.length + publicIp.length];
185 214
			for(int i = 0; i < privateIp.length; i++){
......
212 241
					}
213 242
					else{
214 243
						removeNodeFromList(server);
244
						if(server.getName().equals("External Node")){
245
							servers.remove(server);
246
							setServerList(servers);
247
						}
215 248
					}
216 249
				}
217 250
			});
......
242 275
				}
243 276
			}
244 277
		}
278
	}
245 279

  
246
		private boolean serverHasIp(Server server, String address){
247
			String[] addresses = server.getPrivateIpAddresses();
280
	private String getNameFromIp(String address){
281
		for(Server s: servers){
282
			if(serverHasIp(s, address)){
283
				return s.getName();
284
			}
285
		}
286
		return "";
287
	}
288

  
289
	private boolean isCloudServerIp(String address){
290
		for(Server s : servers){
291
			if(serverHasIp(s, address)){
292
				return true;
293
			}
294
		}
295
		return false;
296
	}
297

  
298
	private boolean serverHasIp(Server server, String address){
299
		String[] addresses = server.getPrivateIpAddresses();
300
		if(addresses != null){
248 301
			for(int i = 0; i < addresses.length; i++){
249 302
				if(addresses[i].equals(address)){
250 303
					return true;
251 304
				}
252 305
			}
253
			addresses = server.getPublicIpAddresses();
306
		}
307
		addresses = server.getPublicIpAddresses();
308
		if(addresses != null){
254 309
			for(int i = 0; i < addresses.length; i++){
255 310
				if(addresses[i].equals(address)){
256 311
					return true;
257 312
				}
258 313
			}
259
			return false;
260 314
		}
315
		return false;
261 316
	}
262 317

  
263

  
264

  
265 318
	protected void onActivityResult(int requestCode, int resultCode, Intent data){
266 319
		int pos = lastCheckedPos;
267 320
		if(requestCode == ADD_NODE_CODE && resultCode == RESULT_OK){
268 321
			Node node = new Node();
269 322
			node.setAddress(data.getStringExtra("nodeIp"));
270 323
			node.setCondition(data.getStringExtra("nodeCondition"));
271
			node.setName(servers[pos].getName());
324
			node.setName(servers.get(pos).getName());
272 325
			node.setPort(data.getStringExtra("nodePort"));
273
			Log.d("info", "the node weight is " + data.getStringExtra("nodeWeight"));
274 326
			node.setWeight(data.getStringExtra("nodeWeight"));
275 327
			nodes.add(node);
276 328
		}
......
282 334
			CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
283 335
			checkBox.setChecked(false);
284 336
		}
337

  
338
		else if(requestCode == ADD_EXTERNAL_NODE_CODE && resultCode == RESULT_OK){
339
			Node node = new Node();
340
			node.setAddress(data.getStringExtra("nodeIp"));
341
			node.setCondition(data.getStringExtra("nodeCondition"));
342
			node.setName("External Node");
343
			node.setPort(data.getStringExtra("nodePort"));
344
			node.setWeight(data.getStringExtra("nodeWeight"));
345

  
346
			/*
347
			 * If the ip is from a cloud server, alert to user
348
			 * so they can select it from there
349
			 */	
350
			if(!isCloudServerIp(node.getAddress())){
351
				nodes.add(node);
352
				//Add it to server list so it display in the listview
353
				Server server = new Server();
354
				server.setName("External Node");
355
				String[] ip = {data.getStringExtra("nodeIp")};
356
				server.setPrivateIpAddresses(ip);
357
				servers.add(server);
358
			} else {
359
				showAlert("Error", "This IP belongs to a cloud server: \"" + getNameFromIp(node.getAddress()) 
360
						+ "\", please select it from the list.");
361
			}
362
		}
285 363
	}
286 364

  
287 365

  
b/src/com/rackspacecloud/android/EditNodesActivity.java
33 33
	@Override
34 34
	public void onCreate(Bundle savedInstanceState) {
35 35
		super.onCreate(savedInstanceState);
36
		setContentView(R.layout.addnodes);
36
		setContentView(R.layout.editnodes);
37 37
		nodes = (ArrayList<Node>) this.getIntent().getExtras().get("nodes");
38 38
		loadBalancer = (LoadBalancer) this.getIntent().getExtras().get("loadBalancer");
39 39
		displayNodes();
b/src/com/rackspacecloud/android/ViewLoadBalancerActivity.java
116 116

  
117 117
			@Override
118 118
			public void onClick(View v) {
119
				showAlert(loadBalancer.getStatus(), "The Load Balancer cannot currently be updated");
119
				showAlert(loadBalancer.getStatus(), "The load balancer cannot be updated");
120 120
			}
121 121

  
122 122
		});
......
126 126

  
127 127
			@Override
128 128
			public void onClick(View v) {
129
				showAlert(loadBalancer.getStatus(), "The Load Balancer cannot currently be deleted");
129
				showAlert(loadBalancer.getStatus(), "The load balancer cannot be deleted");
130 130
			}
131 131

  
132 132
		});
......
136 136

  
137 137
			@Override
138 138
			public void onClick(View v) {
139
				showAlert(loadBalancer.getStatus(), "The nodes cannot currently be edited");
139
				showAlert(loadBalancer.getStatus(), "The nodes cannot be edited");
140 140
			}
141 141
		});
142 142

  
......
221 221
			}
222 222
		}
223 223

  
224
		//TextView vipId = (TextView) findViewById(R.id.view_vip_id);
225
		//vipId.setText(loadBalancer.getVirtualIps().get(0).getId());
226

  
227
		//TextView address = (TextView) findViewById(R.id.view_vip_address);
228

  
229
		//TextView ipVersion = (TextView) findViewById(R.id.view_ipversion);
230
		//ipVersion.setText(loadBalancer.getVirtualIps().get(0).getIpVersion());
231

  
232
		//TextView type = (TextView) findViewById(R.id.view_vip_type);
233
		//type.setText(loadBalancer.getVirtualIps().get(0).getType());
234

  
235 224
		loadNodeData();
236 225
	}
237 226

  
......
240 229
		LinearLayout layout = (LinearLayout) this.findViewById(R.id.node_addresses);   
241 230
		layout.removeAllViews();
242 231
		ArrayList<Node> nodeIps = loadBalancer.getNodes();
232
		if(nodeIps == null){
233
			nodeIps = new ArrayList<Node>();
234
		}
243 235
		
244 236
		/*
245 237
		 * need to sort the addresses because during polling
......
265 257
				layout.addView(tv, layoutIndex++);
266 258
			}
267 259
		}
268

  
269
		/*
270
		TextView nodeID = (TextView) findViewById(R.id.view_node_id);
271
		nodeID.setText(loadBalancer.getNodes().get(0).getId());
272

  
273
		TextView address = (TextView) findViewById(R.id.view_node_address);
274
		address.setText(loadBalancer.getNodes().get(0).getAddress());
275

  
276
		TextView nodePort = (TextView) findViewById(R.id.view_node_port);
277
		nodePort.setText(loadBalancer.getNodes().get(0).getPort());
278

  
279
		TextView condition = (TextView) findViewById(R.id.view_node_condition);
280
		condition.setText(loadBalancer.getNodes().get(0).getCondition());
281

  
282
		TextView nodeStatus = (TextView) findViewById(R.id.view_node_status);
283
		nodeStatus.setText(loadBalancer.getNodes().get(0).getStatus());
284
		 */
285 260
	}
286 261

  
287 262
	//setup menu for when menu button is pressed

Also available in: Unified diff