Statistics
| Branch: | Revision:

root / src / com / rackspacecloud / android / AddMoreNodesActivity.java @ 4f9d1a69

History | View | Annotate | Download (13.7 kB)

1
package com.rackspacecloud.android;
2

    
3
import java.io.IOException;
4
import java.io.StringReader;
5
import java.util.ArrayList;
6
import java.util.Arrays;
7

    
8
import javax.xml.parsers.FactoryConfigurationError;
9
import javax.xml.parsers.ParserConfigurationException;
10
import javax.xml.parsers.SAXParser;
11
import javax.xml.parsers.SAXParserFactory;
12

    
13
import org.apache.http.HttpResponse;
14
import org.apache.http.client.ClientProtocolException;
15
import org.apache.http.impl.client.BasicResponseHandler;
16
import org.xml.sax.InputSource;
17
import org.xml.sax.SAXException;
18
import org.xml.sax.XMLReader;
19

    
20
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancer;
21
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancerManager;
22
import com.rackspace.cloud.loadbalancer.api.client.Node;
23
import com.rackspace.cloud.servers.api.client.Account;
24
import com.rackspace.cloud.servers.api.client.CloudServersException;
25
import com.rackspace.cloud.servers.api.client.Server;
26
import com.rackspace.cloud.servers.api.client.ServerManager;
27
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
28
import com.rackspace.cloud.servers.api.client.parsers.CloudServersFaultXMLParser;
29

    
30
import android.app.Activity;
31
import android.app.AlertDialog;
32
import android.app.ListActivity;
33
import android.app.ProgressDialog;
34
import android.content.Context;
35
import android.content.DialogInterface;
36
import android.content.Intent;
37
import android.os.AsyncTask;
38
import android.os.Bundle;
39
import android.util.Log;
40
import android.view.LayoutInflater;
41
import android.view.View;
42
import android.view.View.OnClickListener;
43
import android.view.ViewGroup;
44
import android.view.WindowManager;
45
import android.view.ViewGroup.LayoutParams;
46
import android.widget.ArrayAdapter;
47
import android.widget.Button;
48
import android.widget.CheckBox;
49
import android.widget.CompoundButton;
50
import android.widget.LinearLayout;
51
import android.widget.ListView;
52
import android.widget.CompoundButton.OnCheckedChangeListener;
53
import android.widget.ImageView;
54
import android.widget.ProgressBar;
55
import android.widget.TextView;
56

    
57
public class AddMoreNodesActivity extends ListActivity {
58

    
59
        private static final int ADD_NODE_CODE = 178;
60
        private Server[] servers;
61
        private Context context;
62
        private int lastCheckedPos;
63
        private ArrayList<Node> nodes;
64
        private ArrayList<Node> nodesToAdd;
65
        private LoadBalancer loadBalancer;
66
        ProgressDialog pDialog;
67

    
68
        @Override
69
        public void onCreate(Bundle savedInstanceState) {
70
                super.onCreate(savedInstanceState);
71
                nodes = (ArrayList<Node>) this.getIntent().getExtras().get("nodes");
72
                loadBalancer = (LoadBalancer) this.getIntent().getExtras().get("loadBalancer");
73
                setContentView(R.layout.addnodes);
74
                restoreState(savedInstanceState);
75
        }
76

    
77
        @Override
78
        protected void onSaveInstanceState(Bundle outState) {
79
                super.onSaveInstanceState(outState);
80
                outState.putSerializable("nodes", nodes);
81
                outState.putSerializable("loadBalancer", loadBalancer);
82
                outState.putSerializable("nodesToAdd", nodesToAdd);
83
        }
84

    
85
        private void restoreState(Bundle state) {
86

    
87
                context = getApplicationContext();
88

    
89
                if (state != null && state.containsKey("nodes")){
90
                        nodes = (ArrayList<Node>) state.getSerializable("nodes");
91
                        if(nodes == null){
92
                                nodes = new ArrayList<Node>();
93
                        }
94
                }
95
                
96
                if (state != null && state.containsKey("nodesToAdd")){
97
                        nodesToAdd = (ArrayList<Node>) state.getSerializable("nodesToAdd");
98
                }
99
                else{
100
                        nodesToAdd = new ArrayList<Node>();
101
                }
102

    
103
                if (state != null && state.containsKey("server")) {
104
                        servers = (Server[]) state.getSerializable("servers");
105
                        if (servers.length == 0) {
106
                                displayNoServersCell();
107
                        } else {
108
                                getListView().setDividerHeight(1); // restore divider lines
109
                                setListAdapter(new ServerAdapter());
110
                        }
111
                } else {
112
                        loadServers();
113
                }
114

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

    
118
                        @Override
119
                        public void onClick(View v) {
120
                                new AddNodesTask().execute();
121
                        }
122
                });
123
        }
124

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

    
131
        private void displayNoServersCell() {
132
                String a[] = new String[1];
133
                a[0] = "No Servers";
134
                setListAdapter(new ArrayAdapter<String>(this, R.layout.noserverscell, R.id.no_servers_label, a));
135
                getListView().setTextFilterEnabled(true);
136
                getListView().setDividerHeight(0); // hide the dividers so it won't look like a list row
137
                getListView().setItemsCanFocus(false);
138
        }
139

    
140
        private void setServerList(ArrayList<Server> servers) {
141
                if (servers == null) {
142
                        servers = new ArrayList<Server>();
143
                }
144
                
145
                for(int i = 0; i < servers.size(); i++) {
146
                        /*
147
                         * if all the IP's of a server are
148
                         * already used as nodes, we do not 
149
                         * need to display that server 
150
                         */
151
                        if(!notAllIpsNodes(servers.get(i))){
152
                                servers.remove(i);
153
                        }
154
                }
155
                
156
                String[] serverNames = new String[servers.size()];
157
                this.servers = new Server[servers.size()];
158

    
159
                for(int i = 0; i < servers.size(); i++){
160
                        serverNames[i] = servers.get(i).getName();
161
                        this.servers[i] = servers.get(i);
162
                }
163
                
164
                if (serverNames.length == 0) {
165
                        displayNoServersCell();
166
                } else {
167
                        getListView().setDividerHeight(1); // restore divider lines 
168
                        setListAdapter(new ServerAdapter());
169
                }
170
        }
171

    
172
        /*
173
         * determine if all the IP's of a server are
174
         * already used as nodes
175
         */
176
        private boolean notAllIpsNodes(Server server){
177
                for(String address : server.getPrivateIpAddresses()){
178
                        if(!nodeHasAddress(address)){
179
                                return true;
180
                        }
181
                }
182
                for(String address : server.getPublicIpAddresses()){
183
                        if(!nodeHasAddress(address)){
184
                                return true;
185
                        }
186
                }
187
                return false;
188
        }
189

    
190
        /*
191
         * determine is an existing node has IP Address,
192
         * address
193
         */
194
        private boolean nodeHasAddress(String address){
195
                for(Node n : nodes){
196
                        if(n.getAddress().equals(address)){
197
                                return true;
198
                        }
199
                }
200
                return false;
201
        }
202

    
203
        private void loadServers() {
204
                new LoadServersTask().execute((Void[]) null);
205
        }
206

    
207
        protected void showDialog() {
208
                pDialog = new ProgressDialog(this, R.style.NewDialog);
209
                // // Set blur to background
210
                WindowManager.LayoutParams lp = pDialog.getWindow().getAttributes();
211
                lp.dimAmount = 0.0f;
212
                pDialog.getWindow().setAttributes(lp);
213
                pDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
214
                pDialog.show();
215
                pDialog.setContentView(new ProgressBar(this), new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
216
        }
217

    
218
        private void showAlert(String title, String message) {
219
                AlertDialog alert = new AlertDialog.Builder(this).create();
220
                alert.setTitle(title);
221
                alert.setMessage(message);
222
                alert.setButton("OK", new DialogInterface.OnClickListener() {
223
                        public void onClick(DialogInterface dialog, int which) {
224
                                return;
225
                        } }); 
226
                alert.show();
227
        }
228

    
229
        // * Adapter/
230
        class ServerAdapter extends ArrayAdapter<Server> {
231
                ServerAdapter() {
232
                        super(AddMoreNodesActivity.this, R.layout.listservernodecell, servers);
233
                }
234

    
235
                public View getView(int position, View convertView, ViewGroup parent) {
236

    
237
                        final Server server = servers[position];
238
                        LayoutInflater inflater = getLayoutInflater();
239
                        View row = inflater.inflate(R.layout.listservernodecell, parent, false);
240

    
241
                        TextView label = (TextView) row.findViewById(R.id.label);
242
                        label.setText(server.getName());
243

    
244
                        TextView sublabel = (TextView) row.findViewById(R.id.sublabel);
245
                        sublabel.setText(server.getFlavor().getName() + " - " + server.getImage().getName());
246

    
247
                        ImageView icon = (ImageView) row.findViewById(R.id.icon);
248
                        icon.setImageResource(server.getImage().iconResourceId());
249

    
250
                        String[] publicIp = server.getPublicIpAddresses();
251
                        String[] privateIp = server.getPrivateIpAddresses();
252

    
253
                        ArrayList<String> ipAddressList = new ArrayList<String>();
254
                        for(int i = 0; i < privateIp.length; i++){
255
                                if(!nodeHasAddress(privateIp[i])){
256
                                        ipAddressList.add(privateIp[i]);
257
                                }
258
                        }
259
                        for(int i = 0; i < publicIp.length; i++){
260
                                if(!nodeHasAddress(publicIp[i])){
261
                                        ipAddressList.add(publicIp[i]);
262
                                }
263
                        }
264

    
265
                        final String[] ipAddresses = ipAddressList.toArray(new String[ipAddressList.size()]);
266
                        final int pos = position;
267
                        CheckBox add = (CheckBox) row.findViewById(R.id.add_node_checkbox);
268
                        
269
                        add.setOnCheckedChangeListener(new OnCheckedChangeListener() {
270

    
271
                                @Override
272
                                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
273
                                        if(isChecked){
274
                                                lastCheckedPos = pos;
275
                                                Intent viewIntent = new Intent(context, AddNodeActivity.class);
276
                                                viewIntent.putExtra("ipAddresses", ipAddresses);
277
                                                startActivityForResult(viewIntent, ADD_NODE_CODE);
278
                                        }
279
                                        else{
280
                                                removeNodeFromList(server);
281
                                        }
282
                                }
283
                        });
284

    
285
                        return(row);
286
                }
287
        }
288

    
289
        /*
290
         *  need to remove by id because that is 
291
         *  what is unique
292
         */
293
        private void removeNodeFromList(Server server){
294
                for(int i = 0; i < nodes.size(); i++){
295
                        Node node = nodes.get(i);
296
                        if(serverHasIp(server, node.getAddress())){
297
                                nodes.remove(i);
298
                                break;
299
                        }
300
                }
301
        }
302

    
303
        private boolean serverHasIp(Server server, String address){
304
                String[] addresses = server.getPrivateIpAddresses();
305
                for(int i = 0; i < addresses.length; i++){
306
                        if(addresses[i].equals(address)){
307
                                return true;
308
                        }
309
                }
310
                addresses = server.getPublicIpAddresses();
311
                for(int i = 0; i < addresses.length; i++){
312
                        if(addresses[i].equals(address)){
313
                                return true;
314
                        }
315
                }
316
                return false;
317
        }
318
        
319
        private void startLoadBalancerError(String message, HttpBundle bundle){
320
                Intent viewIntent = new Intent(getApplicationContext(), ServerErrorActivity.class);
321
                viewIntent.putExtra("errorMessage", message);
322
                viewIntent.putExtra("response", bundle.getResponseText());
323
                viewIntent.putExtra("request", bundle.getCurlRequest());
324
                startActivity(viewIntent);
325
        }
326
        
327
        //using cloudServersException, it works for us too
328
        private CloudServersException parseCloudServersException(HttpResponse response) {
329
                CloudServersException cse = new CloudServersException();
330
                try {
331
                    BasicResponseHandler responseHandler = new BasicResponseHandler();
332
                    String body = responseHandler.handleResponse(response);
333
                    CloudServersFaultXMLParser parser = new CloudServersFaultXMLParser();
334
                    SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
335
                    XMLReader xmlReader = saxParser.getXMLReader();
336
                    xmlReader.setContentHandler(parser);
337
                    xmlReader.parse(new InputSource(new StringReader(body)));                            
338
                    cse = parser.getException();                            
339
                } catch (ClientProtocolException e) {
340
                        cse = new CloudServersException();
341
                        cse.setMessage(e.getLocalizedMessage());
342
                } catch (IOException e) {
343
                        cse = new CloudServersException();
344
                        cse.setMessage(e.getLocalizedMessage());
345
                } catch (ParserConfigurationException e) {
346
                        cse = new CloudServersException();
347
                        cse.setMessage(e.getLocalizedMessage());
348
                } catch (SAXException e) {
349
                        cse = new CloudServersException();
350
                        cse.setMessage(e.getLocalizedMessage());
351
                } catch (FactoryConfigurationError e) {
352
                        cse = new CloudServersException();
353
                        cse.setMessage(e.getLocalizedMessage());
354
                }
355
                return cse;
356
        }
357
        
358
        private class AddNodesTask extends AsyncTask<Void, Void, HttpBundle> {
359
                private CloudServersException exception;
360

    
361
                protected void onPreExecute(){
362
                        showDialog();
363
                }
364
                
365
                @Override
366
                protected HttpBundle doInBackground(Void... arg0) {
367
                        HttpBundle bundle = null;
368
                        try {
369
                                bundle = (new LoadBalancerManager(context)).addNodes(loadBalancer, nodesToAdd);
370
                        } catch (CloudServersException e) {
371
                                exception = e;
372
                        }
373
                        return bundle;
374
                }
375

    
376
                @Override
377
                protected void onPostExecute(HttpBundle bundle) {
378
                        pDialog.dismiss();
379
                        HttpResponse response = bundle.getResponse();
380
                        if (response != null) {
381
                                int statusCode = response.getStatusLine().getStatusCode();
382
                                if (statusCode == 202) {
383
                                        setResult(Activity.RESULT_OK);
384
                                        finish();
385
                                } else {
386
                                        CloudServersException cse = parseCloudServersException(response);
387
                                        if ("".equals(cse.getMessage())) {
388
                                                startLoadBalancerError("There was a problem creating your load balancer.", bundle);
389
                                        } else {
390
                                                //if container with same name already exists
391
                                                startLoadBalancerError("There was a problem creating your load balancer: " + cse.getMessage() + "\n See details for more information", bundle);
392
                                        }
393
                                }
394
                        } else if (exception != null) {
395
                                startLoadBalancerError("There was a problem creating your container: " + exception.getMessage()+"\n See details for more information.", bundle);                                
396
                        }
397
                        finish();
398
                }
399
        }
400

    
401
        private class LoadServersTask extends AsyncTask<Void, Void, ArrayList<Server>> {
402
                private CloudServersException exception;
403
        
404
                @Override
405
                protected void onPreExecute(){
406
                        showDialog();
407
                }
408
        
409
                @Override
410
                protected ArrayList<Server> doInBackground(Void... arg0) {
411
                        ArrayList<Server> servers = null;
412
                        try {
413
                                servers = (new ServerManager()).createList(true, context);
414
                        } catch (CloudServersException e) {
415
                                exception = e;                                
416
                        }
417
                        pDialog.dismiss();
418
                        return servers;
419
                }
420
        
421
                @Override
422
                protected void onPostExecute(ArrayList<Server> result) {
423
                        if (exception != null) {
424
                                showAlert("Error", exception.getMessage());
425
                        }
426
                        setServerList(result);
427
                }
428
        }
429

    
430
        protected void onActivityResult(int requestCode, int resultCode, Intent data){
431
                int pos = lastCheckedPos;
432
                if(requestCode == ADD_NODE_CODE && resultCode == RESULT_OK){
433
                        Node node = new Node();
434
                        node.setAddress(data.getStringExtra("nodeIp"));
435
                        node.setCondition(data.getStringExtra("nodeCondition"));
436
                        node.setName(servers[pos].getName());
437
                        node.setPort(data.getStringExtra("nodePort"));
438
                        Log.d("info", "nodesToAdd is null? " + Boolean.toString(nodesToAdd == null));
439
                        nodesToAdd.add(node);
440
                }
441
                else if(requestCode == ADD_NODE_CODE && resultCode == RESULT_CANCELED){
442
                        //uncheck the node at lastCheckedPos
443
                        LinearLayout linear = (LinearLayout) findViewById(R.id.nodes_linear_layout); 
444
                        ListView serversList = (ListView) linear.findViewById(android.R.id.list);
445
                        View row = serversList.getChildAt(pos);
446
                        CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
447
                        checkBox.setChecked(false);
448
                }
449
        }
450

    
451

    
452
}