Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (17.8 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> possibleNodes; 
38
        //the last position in the listview that was clicked
39
        private int lastCheckedPos;
40
        //the location in nodes of the last node that was clicked
41
        private int positionOfNode;
42
        private ArrayList<Node> nodes;
43
        private ArrayList<Node> nodesToAdd;
44
        private LoadBalancer loadBalancer;
45

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

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

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

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

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

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

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

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

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

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

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

    
116
                        @Override
117
                        public void onClick(View v) {
118
                                if(nodesToAdd.size() == 0){
119
                                        finish();
120
                                } else {
121
                                        new AddNodesTask().execute();
122
                                }
123
                        }
124
                });
125

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

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

    
139
        @Override
140
        public void onBackPressed(){
141
                setResult(RESULT_CANCELED);
142
                finish();
143
        }
144

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

    
162
                                        Server server = possibleNodes.get(position);
163

    
164
                                        //Need to put all the ip's of the server into one
165
                                        //list so they can all be displayed in one spinner
166
                                        String[] ipAddresses = getAllIpsOfServer(server);
167

    
168
                                        Node node = getNodeFromServer(server);
169

    
170
                                        positionOfNode = findNodePosition(node);
171
                                        lastCheckedPos = position;
172

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

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

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

    
221
        private void setServerList(ArrayList<Server> servers) {
222
                if (servers == null) {
223
                        servers = new ArrayList<Server>();
224
                }
225

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

    
237
                String[] serverNames = new String[servers.size()];
238
                this.possibleNodes = new ArrayList<Server>();
239

    
240
                for(int i = 0; i < servers.size(); i++){
241
                        serverNames[i] = servers.get(i).getName();
242
                        this.possibleNodes.add(i, servers.get(i));
243
                }
244

    
245
                if (serverNames.length == 0) {
246
                        displayNoServersCell();
247
                } else {
248
                        getListView().setDividerHeight(1); // restore divider lines 
249
                        setListAdapter(new ServerAdapter());
250
                }
251
        }
252

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

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

    
284
        private void loadServers() {
285
                new LoadServersTask().execute((Void[]) null);
286
        }
287

    
288
        // * Adapter/
289
        class ServerAdapter extends ArrayAdapter<Server> {
290
                ServerAdapter() {
291
                        super(AddMoreNodesActivity.this, R.layout.listservernodecell, possibleNodes);
292
                }
293

    
294
                public View getView(int position, View convertView, ViewGroup parent) {
295

    
296
                        final Server server = possibleNodes.get(position);
297
                        LayoutInflater inflater = getLayoutInflater();
298
                        View row = inflater.inflate(R.layout.listservernodecell, parent, false);
299

    
300
                        TextView label = (TextView) row.findViewById(R.id.label);
301
                        label.setText(server.getName());
302

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

    
310
                        String[] publicIp = server.getPublicIpAddresses();
311
                        String[] privateIp = server.getPrivateIpAddresses();
312

    
313
                        if(publicIp == null){
314
                                publicIp = new String[0];
315
                        }
316

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

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

    
333
                        final String[] ipAddresses = ipAddressList.toArray(new String[ipAddressList.size()]);
334
                        final int pos = position;
335
                        CheckBox add = (CheckBox) row.findViewById(R.id.add_node_checkbox);
336

    
337
                        if(inToAddList(server)){
338
                                add.setChecked(true);
339
                        }
340

    
341
                        add.setOnCheckedChangeListener(new OnCheckedChangeListener() {
342

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

    
365
                        return(row);
366
                }
367

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

    
402
        private boolean inToAddList(Server server){
403
                for(Node node : nodesToAdd){
404
                        if(serverHasIp(server, node.getAddress())){
405
                                return true;
406
                        }
407
                }
408
                return false;
409
        }
410

    
411

    
412
        private class AddNodesTask extends AsyncTask<Void, Void, HttpBundle> {
413
                private CloudServersException exception;
414

    
415
                protected void onPreExecute(){
416
                        showDialog();
417
                }
418

    
419
                @Override
420
                protected HttpBundle doInBackground(Void... arg0) {
421
                        HttpBundle bundle = null;
422
                        try {
423
                                bundle = (new NodeManager(getContext())).add(loadBalancer, nodesToAdd);
424
                        } catch (CloudServersException e) {
425
                                exception = e;
426
                        }
427
                        return bundle;
428
                }
429

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

    
455
        private class LoadServersTask extends AsyncTask<Void, Void, ArrayList<Server>> {
456
                private CloudServersException exception;
457

    
458
                @Override
459
                protected void onPreExecute(){
460
                        showDialog();
461
                }
462

    
463
                @Override
464
                protected ArrayList<Server> doInBackground(Void... arg0) {
465
                        ArrayList<Server> servers = null;
466
                        try {
467
                                servers = (new ServerManager()).createList(true, getContext());
468
                        } catch (CloudServersException e) {
469
                                exception = e;                                
470
                        } 
471
                        return servers;
472
                }
473

    
474
                @Override
475
                protected void onPostExecute(ArrayList<Server> result) {
476
                        hideDialog();
477
                        if (exception != null) {
478
                                showAlert("Error", exception.getMessage());
479
                        }
480
                        setServerList(result);
481
                }
482
        }
483

    
484
        private String getNameFromIp(String address){
485
                for(Server s: possibleNodes){
486
                        if(serverHasIp(s, address)){
487
                                return s.getName();
488
                        }
489
                }
490
                return "";
491
        }
492

    
493
        private boolean isCloudServerIp(String address){
494
                for(Server s : possibleNodes){
495
                        if(serverHasIp(s, address)){
496
                                return true;
497
                        }
498
                }
499
                return false;
500
        }
501

    
502
        //returns the node that is using an ip from server
503
        private Node getNodeFromServer(Server server){
504
                for(Node node : nodesToAdd){
505
                        if(serverHasIp(server, node.getAddress())){
506
                                return node;
507
                        }
508
                }
509
                return null;
510
        }
511

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

    
530
                return ipAddresses;
531
        }
532

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

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

    
572
                        /*
573
                         * If the ip is from a cloud server, alert to user
574
                         * so they can select it from there
575
                         */        
576
                        if(!isCloudServerIp(node.getAddress())){
577

    
578
                                if(positionOfNode >= 0){
579
                                        nodesToAdd.remove(positionOfNode);
580
                                }
581

    
582
                                nodesToAdd.add(node);
583
                                //Add it to server list so it display in the listview
584
                                Server server = new Server();
585
                                server.setName("External Node");
586
                                String[] ip = {data.getStringExtra("nodeIp")};
587
                                server.setPrivateIpAddresses(ip);
588
                                possibleNodes.add(server);
589
                                setServerList(possibleNodes);
590
                        } else {
591
                                showAlert("Error", "This IP belongs to a cloud server: \"" + getNameFromIp(node.getAddress()) 
592
                                                + "\", please select it from the list.");
593
                        }
594
                }
595
                printTheNodes();
596
        }
597

    
598
        private void printTheNodes(){
599
                for(Node n: nodesToAdd){
600
                        Log.d("info", "address: " + n.getAddress() + " Port: " + n.getPort() + " Cond: " + n.getCondition());
601
                }
602
                Log.d("info", " SPACE ");
603
        }
604
}