Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (15.4 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.text.Editable;
12
import android.text.TextWatcher;
13
import android.util.Log;
14
import android.view.View;
15
import android.view.View.OnClickListener;
16
import android.widget.AdapterView;
17
import android.widget.AdapterView.OnItemSelectedListener;
18
import android.widget.ArrayAdapter;
19
import android.widget.Button;
20
import android.widget.EditText;
21
import android.widget.Spinner;
22
import android.widget.TableRow;
23

    
24
import com.rackspace.cloud.android.R;
25
import com.rackspace.cloud.loadbalancer.api.client.Algorithm;
26
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancer;
27
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancerManager;
28
import com.rackspace.cloud.loadbalancer.api.client.Node;
29
import com.rackspace.cloud.loadbalancer.api.client.Protocol;
30
import com.rackspace.cloud.loadbalancer.api.client.VirtualIp;
31
import com.rackspace.cloud.servers.api.client.Account;
32
import com.rackspace.cloud.servers.api.client.CloudServersException;
33
import com.rackspace.cloud.servers.api.client.Server;
34
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
35

    
36
public class AddLoadBalancerActivity extends CloudActivity implements OnItemSelectedListener {
37

    
38
        private static final String[] VIP_TYPES = {"Public", "ServiceNet", "Shared"};
39

    
40
        private static final int ADD_NODES_ACTIVITY_CODE = 165;
41
        private static final int SHARED_VIP_ACTIVITY_CODE = 235;
42

    
43
        private ArrayList<Node> nodes;
44
        private ArrayList<Server> possibleNodes;
45
        private LoadBalancer loadBalancer;
46
        private Protocol[] protocols;
47
        private Protocol selectedProtocol;
48
        private Algorithm[] algorithms;
49
        private Algorithm selectedAlgorithm;
50
        private VirtualIp selectedVip;
51
        private EditText portEditText;
52
        private Spinner protocolSpinner;
53
        private Spinner protocolSubSpinner;
54
        private Spinner algorithmSpinner;
55
        private Spinner vipSpinner;
56
        private Spinner regionSpinner;
57
        private Button selectVipButton;
58
        private Button selectNodesButton;
59
        private String selectedVipType;
60
        private String selectedRegion;
61
        private String selectedName;
62
        private String selectedPort;
63

    
64
        @Override
65
        public void onCreate(Bundle savedInstanceState) {
66
                super.onCreate(savedInstanceState);
67
                trackPageView(GoogleAnalytics.PAGE_ADD_LOADBALANCER);
68
                setContentView(R.layout.view_add_loadbalancer);
69
                restoreState(savedInstanceState);
70
        }
71

    
72
        @SuppressWarnings("unchecked")
73
        protected void restoreState(Bundle state) {
74
                super.restoreState(state);
75

    
76
                if(state != null && state.containsKey("nodes")){
77
                        nodes = (ArrayList<Node>) state.getSerializable("nodes");
78
                }
79
                else{
80
                        nodes = new ArrayList<Node>();
81
                }
82
                
83
                if(state != null && state.containsKey("possibleNodes")){
84
                        possibleNodes = (ArrayList<Server>) state.getSerializable("possibleNodes");
85
                }
86
                else{
87
                        possibleNodes = new ArrayList<Server>();
88
                }
89

    
90
                if(state != null && state.containsKey("selectedVip")){
91
                        selectedVip = (VirtualIp) state.getSerializable("selectedVip");
92
                }
93
                
94
                setupText();
95
                loadProtocolSpinner();
96
                loadProtocolSubSpinner();
97
                loadAlgorithmSpinner();
98
                loadVipSpinner();
99
                loadRegionSpinner();
100
                setUpButtons();
101
        }
102

    
103
        @Override
104
        protected void onSaveInstanceState(Bundle outState) {
105
                super.onSaveInstanceState(outState);
106
                outState.putSerializable("nodes", nodes);
107
                outState.putSerializable("possibleNodes", possibleNodes);
108
                outState.putSerializable("selectedVip", selectedVip);
109
        }
110

    
111
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
112
                if (parent == protocolSpinner) {
113
                        TableRow customProtocol = (TableRow)findViewById(R.id.custom_protocol_row);
114
                        if(position < protocols.length){
115
                                selectedProtocol = protocols[position];
116
                                selectedPort = protocols[position].getDefaultPort();
117
                                customProtocol.setVisibility(View.GONE);
118
                        } else {
119
                                customProtocol.setVisibility(View.VISIBLE);
120
                        }
121
                        updateVipIndicatorLight();
122
                } else if (parent == algorithmSpinner){
123
                        selectedAlgorithm = algorithms[position];
124
                } else if (parent == vipSpinner){
125
                        selectedVipType = VIP_TYPES[position];
126
                        if(VIP_TYPES[position].equals("Shared")){
127
                                ((TableRow) findViewById(R.id.select_vip_layout)).setVisibility(View.VISIBLE);
128
                        } else {
129
                                ((TableRow) findViewById(R.id.select_vip_layout)).setVisibility(View.GONE);
130
                        }
131
                        updateVipIndicatorLight();
132
                } else if (parent == regionSpinner){
133
                        selectedRegion = Account.getAccount().getLoadBalancerRegions()[position];
134
                        updateVipIndicatorLight();
135
                } else if (parent == protocolSubSpinner){
136
                        selectedProtocol = protocols[position];
137
                        updateVipIndicatorLight();
138
                }
139
        }
140

    
141
        public void onNothingSelected(AdapterView<?> parent) {
142

    
143
        }
144

    
145
        private void setUpButtons(){
146
                selectVipButton = (Button) findViewById(R.id.selected_shared_vip);
147
                updateVipIndicatorLight();
148
                selectVipButton.setOnClickListener(new OnClickListener() {
149
                        @Override
150
                        public void onClick(View v) {
151
                                Intent viewIntent = new Intent(getApplicationContext(), SharedVipActivity.class);
152
                                viewIntent.putExtra("loadBalancerPort", selectedPort);
153
                                viewIntent.putExtra("loadBalancerRegion", selectedRegion);
154
                                viewIntent.putExtra("selectedVip", selectedVip);
155
                                startActivityForResult(viewIntent, SHARED_VIP_ACTIVITY_CODE);                                
156
                        }
157
                });
158
                ((TableRow) findViewById(R.id.select_vip_layout)).setVisibility(View.GONE);
159

    
160
                selectNodesButton = (Button) findViewById(R.id.add_nodes_button);
161
                updateNodesIndicatorLight();
162
                selectNodesButton.setOnClickListener(new OnClickListener() {
163
                        @Override
164
                        public void onClick(View v) {
165
                                Intent viewIntent = new Intent(getApplicationContext(), AddNodesActivity.class);
166
                                viewIntent.putExtra("nodes", nodes);
167
                                if(validPort(selectedPort)){
168
                                        viewIntent.putExtra("loadBalancerPort", selectedPort);
169
                                }
170
                                viewIntent.putExtra("possibleNodes", possibleNodes);
171
                                startActivityForResult(viewIntent, ADD_NODES_ACTIVITY_CODE);
172
                        }
173
                });
174

    
175
                Button addLoadBalancer = (Button) findViewById(R.id.add_lb_button);
176
                addLoadBalancer.setOnClickListener(new OnClickListener() {
177

    
178
                        @Override
179
                        public void onClick(View v) {
180
                                selectedName = ((EditText)findViewById(R.id.edit_lb_name_text)).getText().toString();
181
                                //selectedPort = ((EditText)findViewById(R.id.edit_port_text)).getText().toString();
182
                                if(!validName()){
183
                                        showAlert("Error", "Load balancer name cannot be blank.");
184
                                } else if(!validPort(selectedPort)){
185
                                        showAlert("Error", "Must have a protocol port number that is between 1 and 65535.");
186
                                } else if(!validVip()){
187
                                        showAlert("Error", "Please select a valid Virtual IP.");
188
                                } else if(!validNodes()){
189
                                        showAlert("Error", "You must select at least one enabled cloud server or add and enable at least one external node.");
190
                                } else {
191
                                        loadBalancer = new LoadBalancer();
192
                                        loadBalancer.setName(selectedName);
193
                                        loadBalancer.setProtocol(selectedProtocol.getName());
194
                                        loadBalancer.setPort(selectedPort);
195
                                        loadBalancer.setVirtualIpType(selectedVipType);
196
                                        loadBalancer.setAlgorithm(selectedAlgorithm.getName());
197
                                        loadBalancer.setRegion(selectedRegion);
198
                                        loadBalancer.setNodes(nodes);
199
                                        if(selectedVip != null){
200
                                                ArrayList<VirtualIp> vips = new ArrayList<VirtualIp>();
201
                                                vips.add(selectedVip);
202
                                                loadBalancer.setVirtualIps(vips);
203
                                        }
204
                                        trackEvent(GoogleAnalytics.CATEGORY_LOAD_BALANCER, GoogleAnalytics.EVENT_CREATE, "", -1);
205
                                        new AddLoadBalancerTask().execute();
206
                                        Log.d("info", "the port is " + selectedPort);
207
                                }
208
                        }
209
                });
210
        }
211

    
212
        private boolean validName(){
213
                return !selectedName.equals("");
214
        }
215

    
216
        private boolean validPort(String selectedPort){
217
                boolean result;
218
                try{
219
                        result = !selectedPort.equals("") && Integer.valueOf(selectedPort) > 0 && Integer.valueOf(selectedPort) < 65536; 
220
                } catch (NumberFormatException e){
221
                        result = false;
222
                }
223
                return result;
224
        }
225

    
226
        private boolean validNodes(){
227
                boolean exist = nodes != null && nodes.size() > 0;
228
                boolean enabled = false;
229
                for(Node n: nodes){
230
                        enabled = enabled || n.getCondition().equalsIgnoreCase("enabled");
231
                }
232
                return exist && enabled;
233
        }
234

    
235
        private boolean validVip(){
236
                /*
237
                 * assign selectedVipType to the
238
                 * first value in the list, the default
239
                 * if its null
240
                 */
241
                if(selectedVipType == null){
242
                        selectedVipType = VIP_TYPES[0];
243
                }
244
                return !selectedVipType.equalsIgnoreCase("Shared") 
245
                ||(selectedVip != null && !selectedVip.getLoadBalancer().getPort().equals(selectedPort) 
246
                                && selectedVip.getLoadBalancer().getRegion().equals(selectedRegion));
247
        }
248
        
249
        private void updateNodesIndicatorLight(){
250
                if(validNodes()){
251
                        selectNodesButton.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0);
252
                } else {
253
                        selectNodesButton.setCompoundDrawablesWithIntrinsicBounds(0,0,R.drawable.ic_notification_overlay,0);
254
                }
255
        }
256

    
257
        private void updateVipIndicatorLight(){
258
                if(validVip()){
259
                        selectVipButton.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0);
260
                } else {
261
                        selectVipButton.setCompoundDrawablesWithIntrinsicBounds(0,0,R.drawable.ic_notification_overlay,0);
262
                }
263
        }
264

    
265
        private void setupText(){
266
                portEditText = (EditText)findViewById(R.id.edit_port_text);
267
                portEditText.addTextChangedListener(new TextWatcher() {
268

    
269
                        @Override
270
                        public void onTextChanged(CharSequence s, int start, int before, int count) {
271
                                selectedPort = s.toString();
272
                                updateVipIndicatorLight();
273
                        }                
274
                        @Override
275
                        public void beforeTextChanged(CharSequence s, int start, int count,
276
                                        int after) {
277
                                // do nothing
278
                        }
279
                        @Override
280
                        public void afterTextChanged(Editable s) {
281
                                // do nothing
282
                        }
283
                });
284
        }
285

    
286
        private void loadRegionSpinner() {
287
                regionSpinner = (Spinner) findViewById(R.id.edit_region_spinner);
288
                regionSpinner.setOnItemSelectedListener(this);
289

    
290
                ArrayAdapter<String> regionAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, 
291
                                Account.getAccount().getLoadBalancerRegions());
292
                regionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
293
                regionSpinner.setAdapter(regionAdapter);
294
        }
295

    
296
        private void loadVipSpinner() {
297
                vipSpinner = (Spinner) findViewById(R.id.edit_vip_spinner);
298
                vipSpinner.setOnItemSelectedListener(this);
299

    
300
                ArrayAdapter<String> vipAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, VIP_TYPES);
301
                vipAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
302
                vipSpinner.setAdapter(vipAdapter);
303
        }
304

    
305
        private void loadProtocolSpinner() {
306
                protocolSpinner = (Spinner) findViewById(R.id.edit_protocol_spinner);
307
                protocolSpinner.setOnItemSelectedListener(this);
308
                String protocolNames[] = new String[Protocol.getProtocols().size() + 1]; 
309
                protocols = new Protocol[Protocol.getProtocols().size()];
310

    
311
                int httpIndex = 0;
312
                for(int i = 0; i < Protocol.getProtocols().size(); i++){
313
                        protocols[i] = Protocol.getProtocols().get(i);
314
                        protocolNames[i] = Protocol.getProtocols().get(i).getName() + " (" + Protocol.getProtocols().get(i).getDefaultPort() + ")";
315
                        if(Protocol.getProtocols().get(i).getName().equals("HTTP")){
316
                                httpIndex = i;
317
                        }
318
                }
319
                protocolNames[protocolNames.length - 1] = "Custom";
320

    
321
                ArrayAdapter<String> protocolAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, protocolNames);
322
                protocolAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
323
                protocolSpinner.setAdapter(protocolAdapter);
324
                protocolSpinner.setSelection(httpIndex);
325

    
326
        }
327

    
328
        /*
329
         * this is the spinner for protocol selection that 
330
         * appears if custom is chosen from protocolSpinner
331
         */
332
        private void loadProtocolSubSpinner() {
333
                protocolSubSpinner = (Spinner) findViewById(R.id.edit_protocol_sub_spinner);
334
                protocolSubSpinner.setOnItemSelectedListener(this);
335
                String protocolNames[] = new String[Protocol.getProtocols().size()]; 
336

    
337
                for(int i = 0; i < Protocol.getProtocols().size(); i++){
338
                        protocolNames[i] = Protocol.getProtocols().get(i).getName();
339
                }
340

    
341
                ArrayAdapter<String> protocolAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, protocolNames);
342
                protocolAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
343
                protocolSubSpinner.setAdapter(protocolAdapter);
344
        }
345

    
346
        private void loadAlgorithmSpinner() {
347
                algorithmSpinner = (Spinner) findViewById(R.id.edit_algorithm_spinner);
348
                algorithmSpinner.setOnItemSelectedListener(this);
349
                String algorithmNames[] = new String[Algorithm.getAlgorithms().size()]; 
350
                algorithms = new Algorithm[Algorithm.getAlgorithms().size()];
351

    
352
                for(int i = 0; i < Algorithm.getAlgorithms().size(); i++){
353
                        algorithms[i] = Algorithm.getAlgorithms().get(i);
354
                        algorithmNames[i] = getPrettyAlgoName(Algorithm.getAlgorithms().get(i).getName());
355
                }
356

    
357
                ArrayAdapter<String> algorithmAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, algorithmNames);
358
                algorithmAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
359
                algorithmSpinner.setAdapter(algorithmAdapter);
360
        }
361

    
362
        private String getPrettyAlgoName(String name){
363
                if(name == null || name.length() == 0){
364
                        return "";
365
                } else {
366
                        String result = name.charAt(0) + "";
367
                        boolean previousWasSpace = false;;
368
                        for(int i = 1; i < name.length(); i++){
369
                                char curLetter = name.charAt(i);
370
                                if(curLetter == '_'){
371
                                        result += " ";
372
                                        previousWasSpace = true;
373
                                } else {
374
                                        if(previousWasSpace){
375
                                                result += Character.toUpperCase(curLetter);
376
                                        } else {
377
                                                result += Character.toLowerCase(curLetter);
378
                                        }
379
                                        previousWasSpace = false;
380
                                }
381
                        }
382
                        return result;
383
                }
384
        }
385
        
386
        private class AddLoadBalancerTask extends AsyncTask<Void, Void, HttpBundle> {
387
                private CloudServersException exception;
388

    
389
                protected void onPreExecute(){
390
                        showDialog();
391
                }
392

    
393
                @Override
394
                protected HttpBundle doInBackground(Void... arg0) {
395
                        HttpBundle bundle = null;
396
                        try {
397
                                bundle = (new LoadBalancerManager(getContext())).create(loadBalancer, LoadBalancer.getRegionUrl(selectedRegion));
398
                        } catch (CloudServersException e) {
399
                                exception = e;
400
                        }
401
                        return bundle;
402
                }
403

    
404
                @Override
405
                protected void onPostExecute(HttpBundle bundle) {
406
                        hideDialog();
407
                        HttpResponse response = bundle.getResponse();
408
                        if (response != null) {
409
                                int statusCode = response.getStatusLine().getStatusCode();
410
                                if (statusCode == 202) {
411
                                        setResult(Activity.RESULT_OK);
412
                                        finish();
413
                                } else {
414
                                        CloudServersException cse = parseCloudServersException(response);
415
                                        if ("".equals(cse.getMessage())) {
416
                                                showError("There was a problem creating your load balancer.", bundle);
417
                                        } else {
418
                                                //if container with same name already exists
419
                                                showError("There was a problem creating your load balancer: " + cse.getMessage() + "\n See details for more information", bundle);
420
                                        }
421
                                }
422
                        } else if (exception != null) {
423
                                showError("There was a problem creating your container: " + exception.getMessage()+"\n See details for more information.", bundle);                                
424
                        }
425
                        finish();
426
                }
427
        }
428

    
429
        private void printNodes(ArrayList<Node> nodes){
430
                for(Node n : nodes){
431
                        Log.d("info", "node is: " + n.getAddress());
432
                }
433
        }
434
        
435
        @SuppressWarnings("unchecked")
436
        @Override
437
        protected void onActivityResult (int requestCode, int resultCode, Intent data){
438
                if(requestCode == ADD_NODES_ACTIVITY_CODE && resultCode == RESULT_OK){
439
                        //set node list
440
                        nodes = ((ArrayList<Node>)data.getSerializableExtra("nodes"));
441
                        updateNodesIndicatorLight();
442
                        printNodes(nodes);
443
                }
444
                else if(requestCode == ADD_NODES_ACTIVITY_CODE && resultCode == RESULT_CANCELED){
445
                        //don't change list
446
                }
447
                else if(requestCode == SHARED_VIP_ACTIVITY_CODE){
448
                        if(data != null){
449
                                selectedVip = (VirtualIp)data.getSerializableExtra("selectedVip");
450
                        }
451
                        updateVipIndicatorLight();
452
                }
453
        }
454
}