Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (18.8 kB)

1
package com.rackspacecloud.android;
2

    
3
import java.util.ArrayList;
4

    
5
import org.apache.http.HttpResponse;
6

    
7
import android.app.Activity;
8
import android.content.Intent;
9
import android.os.AsyncTask;
10
import android.os.Bundle;
11
import android.util.Log;
12
import android.view.LayoutInflater;
13
import android.view.View;
14
import android.view.View.OnClickListener;
15
import android.view.ViewGroup;
16
import android.widget.ArrayAdapter;
17
import android.widget.Button;
18
import android.widget.CheckBox;
19
import android.widget.CompoundButton;
20
import android.widget.CompoundButton.OnCheckedChangeListener;
21
import android.widget.LinearLayout;
22
import android.widget.ListView;
23
import android.widget.TextView;
24

    
25
import com.rackspace.cloud.android.R;
26
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancer;
27
import com.rackspace.cloud.loadbalancer.api.client.Node;
28
import com.rackspace.cloud.loadbalancer.api.client.NodeManager;
29
import com.rackspace.cloud.servers.api.client.CloudServersException;
30
import com.rackspace.cloud.servers.api.client.Server;
31
import com.rackspace.cloud.servers.api.client.ServerManager;
32
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
33

    
34
public class AddMoreNodesActivity extends CloudListActivity {
35

    
36
        private static final int ADD_NODE_CODE = 178;
37
        private static final int ADD_EXTERNAL_NODE_CODE = 188;
38
        private ArrayList<Server> possibleNodes; 
39
        //the last position in the listview that was clicked
40
        private int lastCheckedPos;
41
        //the location in nodes of the last node that was clicked
42
        private int positionOfNode;
43
        private ArrayList<Node> nodes;
44
        private ArrayList<Node> nodesToAdd;
45
        private LoadBalancer loadBalancer;
46

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

    
57
        @Override
58
        protected void onSaveInstanceState(Bundle outState) {
59
                super.onSaveInstanceState(outState);
60

    
61
                outState.putSerializable("nodes", nodes);
62
                outState.putSerializable("loadBalancer", loadBalancer);
63
                outState.putSerializable("nodesToAdd", nodesToAdd);
64
                outState.putSerializable("possibleNodes", possibleNodes);
65
                outState.putInt("lastCheckedPos", lastCheckedPos);
66
                outState.putInt("positionOfNode", positionOfNode);
67
        }
68

    
69
        @SuppressWarnings("unchecked")
70
        protected void restoreState(Bundle state) {
71
                super.restoreState(state);
72

    
73
                if (state != null && state.containsKey("nodes")){
74
                        nodes = (ArrayList<Node>) state.getSerializable("nodes");
75
                        if(nodes == null){
76
                                nodes = new ArrayList<Node>();
77
                        }
78
                }
79

    
80
                if (state != null && state.containsKey("loadBalancer")){
81
                        loadBalancer = (LoadBalancer) state.getSerializable("loadBalancer");
82
                        if(loadBalancer == null){
83
                                loadBalancer = new LoadBalancer();
84
                        }
85
                }
86

    
87
                if (state != null && state.containsKey("lastCheckedPos")){
88
                        lastCheckedPos = (Integer) state.getSerializable("lastCheckedPos");
89
                }
90

    
91
                if (state != null && state.containsKey("positionOfNode")){
92
                        positionOfNode = (Integer) state.getSerializable("positionOfNode");
93
                }
94

    
95
                if (state != null && state.containsKey("nodesToAdd")){
96
                        nodesToAdd = (ArrayList<Node>) state.getSerializable("nodesToAdd");
97
                }
98
                else{
99
                        nodesToAdd = new ArrayList<Node>();
100
                }
101

    
102
                if (state != null && state.containsKey("possibleNodes") && state.getSerializable("possibleNodes") != null) { 
103
                        possibleNodes = (ArrayList<Server>) state.getSerializable("possibleNodes");
104
                        if (possibleNodes.size() == 0) {
105
                                displayNoServersCell();
106
                        } else {
107
                                getListView().setDividerHeight(1); // restore divider lines
108
                                setListAdapter(new ServerAdapter());
109
                        }
110
                } else {
111
                        loadServers();
112
                }
113

    
114
                Button submitNodes = (Button) findViewById(R.id.submit_nodes_button);
115
                submitNodes.setOnClickListener(new OnClickListener() {
116

    
117
                        @Override
118
                        public void onClick(View v) {
119
                                if(nodesToAdd.size() == 0){
120
                                        finish();
121
                                } else {
122
                                        trackEvent(GoogleAnalytics.CATEGORY_LOAD_BALANCER, GoogleAnalytics.EVENT_ADD_LB_NODES, "", -1);
123
                                        new AddNodesTask().execute();
124
                                }
125
                        }
126
                });
127

    
128
                Button addExternalNode = (Button) findViewById(R.id.add_external_node);
129
                addExternalNode.setOnClickListener(new OnClickListener() {
130

    
131
                        @Override
132
                        public void onClick(View v) {
133
                                positionOfNode = -1;
134
                                lastCheckedPos = -1;
135
                                Intent viewIntent = new Intent(getContext(), AddExternalNodeActivity.class);
136
                                viewIntent.putExtra("loadBalancerPort", loadBalancer.getPort());
137
                                viewIntent.putExtra("weighted", loadBalancer.getAlgorithm().toLowerCase().contains("weighted"));
138
                                startActivityForResult(viewIntent, ADD_EXTERNAL_NODE_CODE);
139
                        }
140
                });
141
        }
142

    
143
        @Override
144
        public void onBackPressed(){
145
                setResult(RESULT_CANCELED);
146
                finish();
147
        }
148

    
149
        //When a list item is click just change the checkbox state
150
        //and then the checkbox's onClick will be performed
151
        protected void onListItemClick(ListView l, View v, int position, long id) {
152
                if (possibleNodes != null && possibleNodes.size() > 0) {
153
                        if(!possibleNodes.get(position).getName().equals("External Node")){
154
                                LinearLayout linear = (LinearLayout) findViewById(R.id.nodes_linear_layout); 
155
                                ListView serversList = (ListView) linear.findViewById(android.R.id.list);
156
                                View row = serversList.getChildAt(position);
157
                                CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
158
                                if(!checkBox.isChecked()){
159
                                        //if the checkbox was not previously checked, treat the listItemClick
160
                                        //the same as checking the checkbox
161
                                        checkBox.setChecked(!checkBox.isChecked());
162
                                } else {
163
                                        //if the checkbox was already checked when the listItemClick occurred,
164
                                        //then treat it like an edit
165

    
166
                                        Server server = possibleNodes.get(position);
167

    
168
                                        //Need to put all the ip's of the server into one
169
                                        //list so they can all be displayed in one spinner
170
                                        String[] ipAddresses = getAllIpsOfServer(server);
171

    
172
                                        Node node = getNodeFromServer(server);
173

    
174
                                        positionOfNode = findNodePosition(node);
175
                                        lastCheckedPos = position;
176

    
177
                                        Intent viewIntent = new Intent(getContext(), AddNodeActivity.class);
178
                                        viewIntent.putExtra("ipAddresses", ipAddresses);
179
                                        viewIntent.putExtra("name", server.getName());
180
                                        if(node != null){
181
                                                viewIntent.putExtra("node", node);
182
                                        }
183
                                        viewIntent.putExtra("weighted", loadBalancer.getAlgorithm().toLowerCase().contains("weighted"));
184
                                        startActivityForResult(viewIntent, ADD_NODE_CODE);
185
                                }
186
                        } else {
187
                                //When clicked on an external node
188
                                Server server = possibleNodes.get(position);
189
                                Node node = getNodeFromServer(server);
190
                                positionOfNode = findNodePosition(node);
191
                                lastCheckedPos = position;
192
                                Intent viewIntent = new Intent(getContext(), AddExternalNodeActivity.class);
193
                                if(node != null){
194
                                        viewIntent.putExtra("node", node);
195
                                }
196
                                //weighted is false, because on initial node add
197
                                //weight is not option
198
                                viewIntent.putExtra("weighted", false);
199
                                startActivityForResult(viewIntent, ADD_EXTERNAL_NODE_CODE);
200
                        }
201
                }
202
        }
203

    
204
        //return the location of node in nodes
205
        //if it is no in there then -1
206
        private int findNodePosition(Node node){
207
                for(int i = 0; i < nodesToAdd.size(); i++){
208
                        String address = node.getAddress();
209
                        if(address.equals(nodesToAdd.get(i).getAddress())){
210
                                return i;
211
                        }
212
                }
213
                return -1;
214
        }
215

    
216
        private void displayNoServersCell() {
217
                String a[] = new String[1];
218
                a[0] = "No Servers";
219
                setListAdapter(new ArrayAdapter<String>(this, R.layout.noserverscell2, R.id.no_servers_label, a));
220
                getListView().setTextFilterEnabled(true);
221
                getListView().setDividerHeight(0); // hide the dividers so it won't look like a list row
222
                getListView().setItemsCanFocus(false);
223
        }
224

    
225
        private void setServerList(ArrayList<Server> servers) {
226
                if (servers == null) {
227
                        servers = new ArrayList<Server>();
228
                }
229

    
230
                for(int i = 0; i < servers.size(); i++) {
231
                        /*
232
                         * if all the IP's of a server are
233
                         * already used as nodes, we do not 
234
                         * need to display that server 
235
                         */
236
                        if(!notAllIpsNodes(servers.get(i))){
237
                                servers.remove(i);
238
                        }
239
                }
240

    
241
                String[] serverNames = new String[servers.size()];
242
                this.possibleNodes = new ArrayList<Server>();
243

    
244
                for(int i = 0; i < servers.size(); i++){
245
                        serverNames[i] = servers.get(i).getName();
246
                        this.possibleNodes.add(i, servers.get(i));
247
                }
248

    
249
                if (serverNames.length == 0) {
250
                        displayNoServersCell();
251
                } else {
252
                        getListView().setDividerHeight(1); // restore divider lines 
253
                        setListAdapter(new ServerAdapter());
254
                }
255
        }
256

    
257
        /*
258
         * determine if all the IP's of a server are
259
         * already used as nodes
260
         */
261
        private boolean notAllIpsNodes(Server server){
262
                for(String address : server.getPrivateIpAddresses()){
263
                        if(!nodeHasAddress(address)){
264
                                return true;
265
                        }
266
                }
267
                for(String address : server.getPublicIpAddresses()){
268
                        if(!nodeHasAddress(address)){
269
                                return true;
270
                        }
271
                }
272
                return false;
273
        }
274

    
275
        /*
276
         * determine is an existing node has IP Address,
277
         * address
278
         */
279
        private boolean nodeHasAddress(String address){
280
                for(Node n : nodes){
281
                        if(n.getAddress().equals(address)){
282
                                return true;
283
                        }
284
                }
285
                return false;
286
        }
287

    
288
        private void loadServers() {
289
                new LoadServersTask().execute((Void[]) null);
290
        }
291

    
292
        // * Adapter/
293
        class ServerAdapter extends ArrayAdapter<Server> {
294
                ServerAdapter() {
295
                        super(AddMoreNodesActivity.this, R.layout.listservernodecell, possibleNodes);
296
                }
297

    
298
                public View getView(int position, View convertView, ViewGroup parent) {
299

    
300
                        final Server server = possibleNodes.get(position);
301
                        LayoutInflater inflater = getLayoutInflater();
302
                        View row = inflater.inflate(R.layout.listservernodecell, parent, false);
303

    
304
                        TextView label = (TextView) row.findViewById(R.id.label);
305
                        label.setText(server.getName());
306

    
307
                        TextView sublabel = (TextView) row.findViewById(R.id.sublabel);
308
                        if(server.getName().equals("External Node")){
309
                                sublabel.setText(server.getPrivateIpAddresses()[0]);
310
                        } else {
311
                                sublabel.setText(server.getFlavor().getName() + " - " + server.getImage().getName());
312
                        }
313

    
314
                        String[] publicIp = server.getPublicIpAddresses();
315
                        String[] privateIp = server.getPrivateIpAddresses();
316

    
317
                        if(publicIp == null){
318
                                publicIp = new String[0];
319
                        }
320

    
321
                        if(privateIp == null){
322
                                privateIp = new String[0];
323
                        }
324

    
325
                        ArrayList<String> ipAddressList = new ArrayList<String>();
326
                        for(int i = 0; i < privateIp.length; i++){
327
                                if(!nodeHasAddress(privateIp[i])){
328
                                        ipAddressList.add(privateIp[i]);
329
                                }
330
                        }
331
                        for(int i = 0; i < publicIp.length; i++){
332
                                if(!nodeHasAddress(publicIp[i])){
333
                                        ipAddressList.add(publicIp[i]);
334
                                }
335
                        }
336

    
337
                        final String[] ipAddresses = ipAddressList.toArray(new String[ipAddressList.size()]);
338
                        final int pos = position;
339
                        CheckBox add = (CheckBox) row.findViewById(R.id.add_node_checkbox);
340

    
341
                        if(inToAddList(server)){
342
                                add.setChecked(true);
343
                        }
344

    
345
                        add.setOnCheckedChangeListener(new OnCheckedChangeListener() {
346

    
347
                                @Override
348
                                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
349
                                        if(isChecked){
350
                                                //if node is being check it won't be in nodes positionOfNode is -1
351
                                                positionOfNode = -1;
352
                                                lastCheckedPos = pos;
353
                                                Intent viewIntent = new Intent(getContext(), AddNodeActivity.class);
354
                                                viewIntent.putExtra("ipAddresses", ipAddresses);
355
                                                viewIntent.putExtra("name", server.getName());
356
                                                viewIntent.putExtra("loadBalancerPort", loadBalancer.getPort());
357
                                                viewIntent.putExtra("weighted", loadBalancer.getAlgorithm().contains("WEIGHTED"));
358
                                                startActivityForResult(viewIntent, ADD_NODE_CODE);
359
                                        }
360
                                        else{
361
                                                removeNodeFromList(server);
362
                                                if(server.getName().equals("External Node")){
363
                                                        possibleNodes.remove(server);
364
                                                        setServerList(possibleNodes);
365
                                                }
366
                                        }
367
                                }
368
                        });
369

    
370
                        return(row);
371
                }
372

    
373
                /*
374
                 *  need to remove by id because that is 
375
                 *  what is unique
376
                 */
377
                private void removeNodeFromList(Server server){
378
                        for(int i = 0; i < nodesToAdd.size(); i++){
379
                                Node node = nodesToAdd.get(i);
380
                                if(serverHasIp(server, node.getAddress())){
381
                                        nodesToAdd.remove(i);
382
                                        break;
383
                                }
384
                        }
385
                }
386
        }
387
        private boolean serverHasIp(Server server, String address){
388
                String[] addresses = server.getPrivateIpAddresses();
389
                if(addresses != null){
390
                        for(int i = 0; i < addresses.length; i++){
391
                                if(addresses[i].equals(address)){
392
                                        return true;
393
                                }
394
                        }
395
                }
396
                addresses = server.getPublicIpAddresses();
397
                if(addresses != null){
398
                        for(int i = 0; i < addresses.length; i++){
399
                                if(addresses[i].equals(address)){
400
                                        return true;
401
                                }
402
                        }
403
                }
404
                return false;
405
        }
406

    
407
        private boolean inToAddList(Server server){
408
                for(Node node : nodesToAdd){
409
                        if(serverHasIp(server, node.getAddress())){
410
                                return true;
411
                        }
412
                }
413
                return false;
414
        }
415

    
416

    
417
        private class AddNodesTask extends AsyncTask<Void, Void, HttpBundle> {
418
                private CloudServersException exception;
419

    
420
                protected void onPreExecute(){
421
                        showDialog();
422
                }
423

    
424
                @Override
425
                protected HttpBundle doInBackground(Void... arg0) {
426
                        HttpBundle bundle = null;
427
                        try {
428
                                bundle = (new NodeManager(getContext())).add(loadBalancer, nodesToAdd);
429
                        } catch (CloudServersException e) {
430
                                exception = e;
431
                        }
432
                        return bundle;
433
                }
434

    
435
                @Override
436
                protected void onPostExecute(HttpBundle bundle) {
437
                        hideDialog();
438
                        HttpResponse response = bundle.getResponse();
439
                        if (response != null) {
440
                                int statusCode = response.getStatusLine().getStatusCode();
441
                                if (statusCode == 202) {
442
                                        setResult(Activity.RESULT_OK);
443
                                        finish();
444
                                } else {
445
                                        CloudServersException cse = parseCloudServersException(response);
446
                                        if ("".equals(cse.getMessage())) {
447
                                                showError("There was a problem creating your load balancer.", bundle);
448
                                        } else {
449
                                                //if container with same name already exists
450
                                                showError("There was a problem creating your load balancer: " + cse.getMessage() + "\n See details for more information", bundle);
451
                                        }
452
                                }
453
                        } else if (exception != null) {
454
                                showError("There was a problem creating your container: " + exception.getMessage()+"\n See details for more information.", bundle);                                
455
                        }
456
                        finish();
457
                }
458
        }
459

    
460
        private class LoadServersTask extends AsyncTask<Void, Void, ArrayList<Server>> {
461
                private CloudServersException exception;
462

    
463
                @Override
464
                protected void onPreExecute(){
465
                        showDialog();
466
                }
467

    
468
                @Override
469
                protected ArrayList<Server> doInBackground(Void... arg0) {
470
                        ArrayList<Server> servers = null;
471
                        try {
472
                                servers = (new ServerManager()).createList(true, getContext());
473
                        } catch (CloudServersException e) {
474
                                exception = e;                                
475
                        } 
476
                        return servers;
477
                }
478

    
479
                @Override
480
                protected void onPostExecute(ArrayList<Server> result) {
481
                        hideDialog();
482
                        if (exception != null) {
483
                                showAlert("Error", exception.getMessage());
484
                        }
485
                        setServerList(result);
486
                }
487
        }
488

    
489
        private String getNameFromIp(String address){
490
                for(Server s: possibleNodes){
491
                        if(serverHasIp(s, address)){
492
                                return s.getName();
493
                        }
494
                }
495
                return "";
496
        }
497

    
498
        private boolean ipInList(String address){
499
                for(Server s : possibleNodes){
500
                        if(serverHasIp(s, address) && !s.getName().equals("External Node")){
501
                                return true;
502
                        }
503
                }
504
                return false;
505
        }
506

    
507
        //returns the node that is using an ip from server
508
        private Node getNodeFromServer(Server server){
509
                for(Node node : nodesToAdd){
510
                        if(serverHasIp(server, node.getAddress())){
511
                                return node;
512
                        }
513
                }
514
                return null;
515
        }
516

    
517
        //returns an array of all the ip's of server
518
        private String[] getAllIpsOfServer(Server server){
519
                String[] publicIp = server.getPublicIpAddresses();
520
                String[] privateIp = server.getPrivateIpAddresses();
521
                if(publicIp == null){
522
                        publicIp = new String[0];
523
                }
524
                if(privateIp == null){
525
                        privateIp = new String[0];
526
                }
527
                String[] ipAddresses = new String[privateIp.length + publicIp.length];
528
                for(int i = 0; i < privateIp.length; i++){
529
                        ipAddresses[i] = privateIp[i];
530
                }
531
                for(int i = 0; i < publicIp.length; i++){
532
                        ipAddresses[i+privateIp.length] = publicIp[i];
533
                }
534

    
535
                return ipAddresses;
536
        }
537

    
538
        protected void onActivityResult(int requestCode, int resultCode, Intent data){
539
                int pos = lastCheckedPos;
540
                if(requestCode == ADD_NODE_CODE && resultCode == RESULT_OK){
541
                        //data will be null if user backed out on edit
542
                        //we dont need to do anything then
543
                        //if new node added data won't be null
544
                        //so create the new node and add it to the list
545
                        if(data != null){
546
                                //will remove the node if it's already in the list 
547
                                //so we can update it
548
                                if(positionOfNode >= 0){
549
                                        nodesToAdd.remove(positionOfNode);
550
                                }
551

    
552
                                Node node = new Node();
553
                                node.setAddress(data.getStringExtra("nodeIp"));
554
                                node.setCondition(data.getStringExtra("nodeCondition"));
555
                                node.setName(possibleNodes.get(pos).getName());
556
                                node.setPort(data.getStringExtra("nodePort"));
557
                                node.setWeight(data.getStringExtra("nodeWeight"));
558
                                nodesToAdd.add(node);
559
                        }
560
                }
561
                else if(requestCode == ADD_NODE_CODE && resultCode == RESULT_CANCELED){
562
                        //uncheck the node at lastCheckedPos
563
                        LinearLayout linear = (LinearLayout) findViewById(R.id.nodes_linear_layout); 
564
                        ListView serversList = (ListView) linear.findViewById(android.R.id.list);
565
                        View row = serversList.getChildAt(pos);
566
                        CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
567
                        checkBox.setChecked(false);
568
                }
569
                else if(requestCode == ADD_EXTERNAL_NODE_CODE && resultCode == RESULT_OK){
570
                        Node node = new Node();
571
                        node.setAddress(data.getStringExtra("nodeIp"));
572
                        node.setCondition(data.getStringExtra("nodeCondition"));
573
                        node.setName("External Node");
574
                        node.setPort(data.getStringExtra("nodePort"));
575
                        node.setWeight(data.getStringExtra("nodeWeight"));
576

    
577
                        /*
578
                         * If the ip is from a cloud server or already added, alert to user
579
                         * so they can select it from there
580
                         */        
581
                        String nodeIP = node.getAddress();
582
                        ArrayList<Node> lbNodes = loadBalancer.getNodes();
583
                        boolean nodeIpExists = false;
584
                        for(int i = 0; i < lbNodes.size(); i++){
585
                                if(nodeIP.equals(lbNodes.get(i).getAddress())){
586
                                        nodeIpExists = true;
587
                                }
588
                        }
589
                        if(nodeIpExists){
590
                                        showAlert("Error", "This IP has already been added as an external node, please edit " +
591
                                        "it from the list.");
592
                        } else if(!ipInList(node.getAddress())){
593
                                
594
                                
595
                                if(positionOfNode >= 0){
596
                                        nodesToAdd.remove(positionOfNode);
597
                                }
598

    
599
                                nodesToAdd.add(node);
600
                                //Add it to server list so it display in the listview
601
                                Server server = new Server();
602
                                server.setName("External Node");
603
                                String[] ip = {data.getStringExtra("nodeIp")};
604
                                server.setPrivateIpAddresses(ip);
605
                                if(pos != -1){
606
                                        possibleNodes.remove(pos);
607
                                }
608
                                possibleNodes.add(server);
609
                                setServerList(possibleNodes);
610
                        } else {
611
                                String name = getNameFromIp(node.getAddress());
612
                                if(name.equals("External Node")){
613
                                        showAlert("Error", "This IP has already been added as an external node, please edit " +
614
                                        "it from the list.");
615
                                } else {
616
                                        showAlert("Error", "This IP belongs to a cloud server: \"" + getNameFromIp(node.getAddress()) 
617
                                                        + "\", please edit it from the list.");
618
                                }
619
                        }
620
                }
621
                printTheNodes();
622
        }
623

    
624
        private void printTheNodes(){
625
                for(Node n: nodesToAdd){
626
                        Log.d("info", "address: " + n.getAddress() + " Port: " + n.getPort() + " Cond: " + n.getCondition());
627
                }
628
                Log.d("info", " SPACE ");
629
        }
630
}