Statistics
| Branch: | Revision:

root / src / com / rackspacecloud / android / AddMoreNodesActivity.java @ 01340459

History | View | Annotate | Download (15.6 kB)

1
package com.rackspacecloud.android;
2

    
3
import java.util.ArrayList;
4

    
5
import org.apache.http.HttpResponse;
6

    
7
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancer;
8
import com.rackspace.cloud.loadbalancer.api.client.Node;
9
import com.rackspace.cloud.loadbalancer.api.client.NodeManager;
10
import com.rackspace.cloud.servers.api.client.CloudServersException;
11
import com.rackspace.cloud.servers.api.client.Server;
12
import com.rackspace.cloud.servers.api.client.ServerManager;
13
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
14

    
15
import android.app.Activity;
16
import android.content.Intent;
17
import android.os.AsyncTask;
18
import android.os.Bundle;
19
import android.util.Log;
20
import android.view.LayoutInflater;
21
import android.view.View;
22
import android.view.View.OnClickListener;
23
import android.view.ViewGroup;
24
import android.widget.ArrayAdapter;
25
import android.widget.Button;
26
import android.widget.CheckBox;
27
import android.widget.CompoundButton;
28
import android.widget.LinearLayout;
29
import android.widget.ListView;
30
import android.widget.CompoundButton.OnCheckedChangeListener;
31
import android.widget.TextView;
32

    
33
public class AddMoreNodesActivity extends CloudListActivity {
34

    
35
        private static final int ADD_NODE_CODE = 178;
36
        private static final int ADD_EXTERNAL_NODE_CODE = 188;
37
        private ArrayList<Server> servers; 
38
        private int lastCheckedPos;
39
        private ArrayList<Node> nodes;
40
        private ArrayList<Node> nodesToAdd;
41
        private LoadBalancer loadBalancer;
42

    
43
        @SuppressWarnings("unchecked")
44
        @Override
45
        public void onCreate(Bundle savedInstanceState) {
46
                super.onCreate(savedInstanceState);
47
                nodes = (ArrayList<Node>) this.getIntent().getExtras().get("nodes");
48
                loadBalancer = (LoadBalancer) this.getIntent().getExtras().get("loadBalancer");
49
                setContentView(R.layout.addnodes);
50
                restoreState(savedInstanceState);
51
        }
52

    
53
        @Override
54
        protected void onSaveInstanceState(Bundle outState) {
55
                super.onSaveInstanceState(outState);
56

    
57
                outState.putSerializable("nodes", nodes);
58
                outState.putSerializable("loadBalancer", loadBalancer);
59
                outState.putSerializable("nodesToAdd", nodesToAdd);
60
                outState.putSerializable("servers", servers);
61
        }
62

    
63
        @SuppressWarnings("unchecked")
64
        protected void restoreState(Bundle state) {
65
                super.restoreState(state);
66

    
67
                if (state != null && state.containsKey("nodes")){
68
                        nodes = (ArrayList<Node>) state.getSerializable("nodes");
69
                        if(nodes == null){
70
                                nodes = new ArrayList<Node>();
71
                        }
72
                }
73

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

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

    
88
                if (state != null && state.containsKey("servers") && state.getSerializable("servers") != null) {
89
                        servers = (ArrayList<Server>) state.getSerializable("servers");
90
                        if (servers.size() == 0) {
91
                                displayNoServersCell();
92
                        } else {
93
                                getListView().setDividerHeight(1); // restore divider lines
94
                                setListAdapter(new ServerAdapter());
95
                        }
96
                } else {
97
                        loadServers();
98
                }
99

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

    
103
                        @Override
104
                        public void onClick(View v) {
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);
121
                        }
122
                });
123
        }
124

    
125
        @Override
126
        public void onBackPressed(){
127
                setResult(RESULT_CANCELED);
128
                finish();
129
        }
130

    
131
        //When a list item is click just change the checkbox state
132
        //and then the checkbox's onClick will be performed
133
        protected void onListItemClick(ListView l, View v, int position, long id) {
134
                if (servers != null && servers.size() > 0) {
135
                        LinearLayout linear = (LinearLayout) findViewById(R.id.nodes_linear_layout); 
136
                        ListView serversList = (ListView) linear.findViewById(android.R.id.list);
137
                        View row = serversList.getChildAt(position);
138
                        CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
139
                        if(!checkBox.isChecked()){
140
                                //if the checkbox was not previously checked, treat the listItemClick
141
                                //the same as checking the checkbox
142
                                checkBox.setChecked(!checkBox.isChecked());
143
                        } else {
144
                                //if the checkbox was already checked when the listItemClick occurred,
145
                                //then treat it like an edit
146

    
147
                                Server server = servers.get(position);
148

    
149
                                //Need to put all the ip's of the server into one
150
                                //list so they can all be displayed in one spinner
151
                                String[] ipAddresses = getAllIpsOfServer(server);
152

    
153
                                Node node = getNodeFromServer(server);
154

    
155
                                lastCheckedPos = position;
156
                                Intent viewIntent = new Intent(getContext(), AddNodeActivity.class);
157
                                viewIntent.putExtra("ipAddresses", ipAddresses);
158
                                viewIntent.putExtra("name", server.getName());
159
                                if(node != null){
160
                                        viewIntent.putExtra("node", node);
161
                                }
162
                                //weighted is false, because on initial node add
163
                                //weight is not option
164
                                viewIntent.putExtra("weighted", false);
165
                                startActivityForResult(viewIntent, ADD_NODE_CODE);
166
                        }
167

    
168
                }
169
        }
170

    
171
        private void displayNoServersCell() {
172
                String a[] = new String[1];
173
                a[0] = "No Servers";
174
                setListAdapter(new ArrayAdapter<String>(this, R.layout.noserverscell, R.id.no_servers_label, a));
175
                getListView().setTextFilterEnabled(true);
176
                getListView().setDividerHeight(0); // hide the dividers so it won't look like a list row
177
                getListView().setItemsCanFocus(false);
178
        }
179

    
180
        private void setServerList(ArrayList<Server> servers) {
181
                if (servers == null) {
182
                        servers = new ArrayList<Server>();
183
                }
184

    
185
                for(int i = 0; i < servers.size(); i++) {
186
                        /*
187
                         * if all the IP's of a server are
188
                         * already used as nodes, we do not 
189
                         * need to display that server 
190
                         */
191
                        if(!notAllIpsNodes(servers.get(i))){
192
                                servers.remove(i);
193
                        }
194
                }
195

    
196
                String[] serverNames = new String[servers.size()];
197
                this.servers = new ArrayList<Server>();
198

    
199
                for(int i = 0; i < servers.size(); i++){
200
                        serverNames[i] = servers.get(i).getName();
201
                        this.servers.add(i, servers.get(i));
202
                }
203

    
204
                if (serverNames.length == 0) {
205
                        displayNoServersCell();
206
                } else {
207
                        getListView().setDividerHeight(1); // restore divider lines 
208
                        setListAdapter(new ServerAdapter());
209
                }
210
        }
211

    
212
        /*
213
         * determine if all the IP's of a server are
214
         * already used as nodes
215
         */
216
        private boolean notAllIpsNodes(Server server){
217
                for(String address : server.getPrivateIpAddresses()){
218
                        if(!nodeHasAddress(address)){
219
                                return true;
220
                        }
221
                }
222
                for(String address : server.getPublicIpAddresses()){
223
                        if(!nodeHasAddress(address)){
224
                                return true;
225
                        }
226
                }
227
                return false;
228
        }
229

    
230
        /*
231
         * determine is an existing node has IP Address,
232
         * address
233
         */
234
        private boolean nodeHasAddress(String address){
235
                for(Node n : nodes){
236
                        if(n.getAddress().equals(address)){
237
                                return true;
238
                        }
239
                }
240
                return false;
241
        }
242

    
243
        private void loadServers() {
244
                new LoadServersTask().execute((Void[]) null);
245
        }
246

    
247
        // * Adapter/
248
        class ServerAdapter extends ArrayAdapter<Server> {
249
                ServerAdapter() {
250
                        super(AddMoreNodesActivity.this, R.layout.listservernodecell, servers);
251
                }
252

    
253
                public View getView(int position, View convertView, ViewGroup parent) {
254

    
255
                        final Server server = servers.get(position);
256
                        LayoutInflater inflater = getLayoutInflater();
257
                        View row = inflater.inflate(R.layout.listservernodecell, parent, false);
258

    
259
                        TextView label = (TextView) row.findViewById(R.id.label);
260
                        label.setText(server.getName());
261

    
262
                        TextView sublabel = (TextView) row.findViewById(R.id.sublabel);
263
                        if(server.getName().equals("External Node")){
264
                                sublabel.setText(server.getPrivateIpAddresses()[0]);
265
                        } else {
266
                                sublabel.setText(server.getFlavor().getName() + " - " + server.getImage().getName());
267
                        }
268

    
269
                        String[] publicIp = server.getPublicIpAddresses();
270
                        String[] privateIp = server.getPrivateIpAddresses();
271

    
272
                        if(publicIp == null){
273
                                publicIp = new String[0];
274
                        }
275

    
276
                        if(privateIp == null){
277
                                privateIp = new String[0];
278
                        }
279

    
280
                        ArrayList<String> ipAddressList = new ArrayList<String>();
281
                        for(int i = 0; i < privateIp.length; i++){
282
                                if(!nodeHasAddress(privateIp[i])){
283
                                        ipAddressList.add(privateIp[i]);
284
                                }
285
                        }
286
                        for(int i = 0; i < publicIp.length; i++){
287
                                if(!nodeHasAddress(publicIp[i])){
288
                                        ipAddressList.add(publicIp[i]);
289
                                }
290
                        }
291

    
292
                        final String[] ipAddresses = ipAddressList.toArray(new String[ipAddressList.size()]);
293
                        final int pos = position;
294
                        CheckBox add = (CheckBox) row.findViewById(R.id.add_node_checkbox);
295

    
296
                        if(inToAddList(server)){
297
                                add.setChecked(true);
298
                        }
299

    
300
                        add.setOnCheckedChangeListener(new OnCheckedChangeListener() {
301

    
302
                                @Override
303
                                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
304
                                        if(isChecked){
305
                                                lastCheckedPos = pos;
306
                                                Intent viewIntent = new Intent(getContext(), AddNodeActivity.class);
307
                                                viewIntent.putExtra("ipAddresses", ipAddresses);
308
                                                viewIntent.putExtra("name", server.getName());
309
                                                viewIntent.putExtra("weighted", loadBalancer.getAlgorithm().contains("WEIGHTED"));
310
                                                startActivityForResult(viewIntent, ADD_NODE_CODE);
311
                                        }
312
                                        else{
313
                                                removeNodeFromList(server);
314
                                                if(server.getName().equals("External Node")){
315
                                                        servers.remove(server);
316
                                                        setServerList(servers);
317
                                                }
318
                                        }
319
                                }
320
                        });
321

    
322
                        return(row);
323
                }
324

    
325
                /*
326
                 *  need to remove by id because that is 
327
                 *  what is unique
328
                 */
329
                private void removeNodeFromList(Server server){
330
                        for(int i = 0; i < nodesToAdd.size(); i++){
331
                                Node node = nodesToAdd.get(i);
332
                                if(serverHasIp(server, node.getAddress())){
333
                                        nodesToAdd.remove(i);
334
                                        break;
335
                                }
336
                        }
337
                }
338
        }
339
        private boolean serverHasIp(Server server, String address){
340
                String[] addresses = server.getPrivateIpAddresses();
341
                for(int i = 0; i < addresses.length; i++){
342
                        Log.d("info", "server address: " + addresses[i] + " node address: " + address);
343
                        if(addresses[i].equals(address)){
344
                                return true;
345
                        }
346
                }
347
                addresses = server.getPublicIpAddresses();
348
                for(int i = 0; i < addresses.length; i++){
349
                        if(addresses[i].equals(address)){
350
                                return true;
351
                        }
352
                }
353
                return false;
354
        }
355

    
356
        private boolean inToAddList(Server server){
357
                for(Node node : nodesToAdd){
358
                        if(serverHasIp(server, node.getAddress())){
359
                                return true;
360
                        }
361
                }
362
                return false;
363
        }
364

    
365

    
366
        private class AddNodesTask extends AsyncTask<Void, Void, HttpBundle> {
367
                private CloudServersException exception;
368

    
369
                protected void onPreExecute(){
370
                        showDialog();
371
                }
372

    
373
                @Override
374
                protected HttpBundle doInBackground(Void... arg0) {
375
                        HttpBundle bundle = null;
376
                        try {
377
                                bundle = (new NodeManager(getContext())).add(loadBalancer, nodesToAdd);
378
                        } catch (CloudServersException e) {
379
                                exception = e;
380
                        }
381
                        return bundle;
382
                }
383

    
384
                @Override
385
                protected void onPostExecute(HttpBundle bundle) {
386
                        hideDialog();
387
                        HttpResponse response = bundle.getResponse();
388
                        if (response != null) {
389
                                int statusCode = response.getStatusLine().getStatusCode();
390
                                if (statusCode == 202) {
391
                                        setResult(Activity.RESULT_OK);
392
                                        finish();
393
                                } else {
394
                                        CloudServersException cse = parseCloudServersException(response);
395
                                        if ("".equals(cse.getMessage())) {
396
                                                showError("There was a problem creating your load balancer.", bundle);
397
                                        } else {
398
                                                //if container with same name already exists
399
                                                showError("There was a problem creating your load balancer: " + cse.getMessage() + "\n See details for more information", bundle);
400
                                        }
401
                                }
402
                        } else if (exception != null) {
403
                                showError("There was a problem creating your container: " + exception.getMessage()+"\n See details for more information.", bundle);                                
404
                        }
405
                        finish();
406
                }
407
        }
408

    
409
        private class LoadServersTask extends AsyncTask<Void, Void, ArrayList<Server>> {
410
                private CloudServersException exception;
411

    
412
                @Override
413
                protected void onPreExecute(){
414
                        showDialog();
415
                }
416

    
417
                @Override
418
                protected ArrayList<Server> doInBackground(Void... arg0) {
419
                        ArrayList<Server> servers = null;
420
                        try {
421
                                servers = (new ServerManager()).createList(true, getContext());
422
                        } catch (CloudServersException e) {
423
                                exception = e;                                
424
                        } 
425
                        return servers;
426
                }
427

    
428
                @Override
429
                protected void onPostExecute(ArrayList<Server> result) {
430
                        hideDialog();
431
                        if (exception != null) {
432
                                showAlert("Error", exception.getMessage());
433
                        }
434
                        setServerList(result);
435
                }
436
        }
437

    
438
        private String getNameFromIp(String address){
439
                for(Server s: servers){
440
                        if(serverHasIp(s, address)){
441
                                return s.getName();
442
                        }
443
                }
444
                return "";
445
        }
446

    
447
        private boolean isCloudServerIp(String address){
448
                for(Server s : servers){
449
                        if(serverHasIp(s, address)){
450
                                return true;
451
                        }
452
                }
453
                return false;
454
        }
455

    
456
        //returns the node that is using an ip from server
457
        private Node getNodeFromServer(Server server){
458
                for(Node node : nodesToAdd){
459
                        if(serverHasIp(server, node.getAddress())){
460
                                return node;
461
                        }
462
                }
463
                return null;
464
        }
465

    
466
        //returns an array of all the ip's of server
467
        private String[] getAllIpsOfServer(Server server){
468
                String[] publicIp = server.getPublicIpAddresses();
469
                String[] privateIp = server.getPrivateIpAddresses();
470
                if(publicIp == null){
471
                        publicIp = new String[0];
472
                }
473
                if(privateIp == null){
474
                        privateIp = new String[0];
475
                }
476
                String[] ipAddresses = new String[privateIp.length + publicIp.length];
477
                for(int i = 0; i < privateIp.length; i++){
478
                        ipAddresses[i] = privateIp[i];
479
                }
480
                for(int i = 0; i < publicIp.length; i++){
481
                        ipAddresses[i+privateIp.length] = publicIp[i];
482
                }
483

    
484
                return ipAddresses;
485
        }
486

    
487
        protected void onActivityResult(int requestCode, int resultCode, Intent data){
488
                int pos = lastCheckedPos;
489
                if(requestCode == ADD_NODE_CODE && resultCode == RESULT_OK){
490
                        //data will be null is user back out on edit
491
                        //we dont need to do anything then
492
                        //if new node added data won't be null
493
                        //so create the new node and add it to the list
494
                        if(data != null){
495
                                Node node = new Node();
496
                                node.setAddress(data.getStringExtra("nodeIp"));
497
                                node.setCondition(data.getStringExtra("nodeCondition"));
498
                                node.setName(servers.get(pos).getName());
499
                                node.setPort(data.getStringExtra("nodePort"));
500
                                node.setWeight(data.getStringExtra("nodeWeight"));
501
                                nodesToAdd.add(node);
502
                        }
503
                }
504
                else if(requestCode == ADD_NODE_CODE && resultCode == RESULT_CANCELED){
505
                        //uncheck the node at lastCheckedPos
506
                        LinearLayout linear = (LinearLayout) findViewById(R.id.nodes_linear_layout); 
507
                        ListView serversList = (ListView) linear.findViewById(android.R.id.list);
508
                        View row = serversList.getChildAt(pos);
509
                        CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
510
                        checkBox.setChecked(false);
511
                }
512
                else if(requestCode == ADD_EXTERNAL_NODE_CODE && resultCode == RESULT_OK){
513
                        Node node = new Node();
514
                        node.setAddress(data.getStringExtra("nodeIp"));
515
                        node.setCondition(data.getStringExtra("nodeCondition"));
516
                        node.setName("External Node");
517
                        node.setPort(data.getStringExtra("nodePort"));
518
                        node.setWeight(data.getStringExtra("nodeWeight"));
519

    
520
                        /*
521
                         * If the ip is from a cloud server, alert to user
522
                         * so they can select it from there
523
                         */        
524
                        if(!isCloudServerIp(node.getAddress())){
525
                                nodesToAdd.add(node);
526
                                //Add it to server list so it display in the listview
527
                                Server server = new Server();
528
                                server.setName("External Node");
529
                                String[] ip = {data.getStringExtra("nodeIp")};
530
                                server.setPrivateIpAddresses(ip);
531
                                servers.add(server);
532
                                setServerList(servers);
533
                        } else {
534
                                showAlert("Error", "This IP belongs to a cloud server: \"" + getNameFromIp(node.getAddress()) 
535
                                                + "\", please select it from the list.");
536
                        }
537
                }
538
        }
539
}