Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (15.3 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.Algorithm;
8
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancer;
9
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancerManager;
10
import com.rackspace.cloud.loadbalancer.api.client.Node;
11
import com.rackspace.cloud.loadbalancer.api.client.Protocol;
12
import com.rackspace.cloud.loadbalancer.api.client.VirtualIp;
13
import com.rackspace.cloud.servers.api.client.Account;
14
import com.rackspace.cloud.servers.api.client.CloudServersException;
15
import com.rackspace.cloud.servers.api.client.Server;
16
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
17

    
18
import android.app.Activity;
19
import android.content.Intent;
20
import android.os.AsyncTask;
21
import android.os.Bundle;
22
import android.text.Editable;
23
import android.text.TextWatcher;
24
import android.util.Log;
25
import android.view.View;
26
import android.view.View.OnClickListener;
27
import android.widget.AdapterView;
28
import android.widget.AdapterView.OnItemSelectedListener;
29
import android.widget.ArrayAdapter;
30
import android.widget.Button;
31
import android.widget.EditText;
32
import android.widget.Spinner;
33
import android.widget.TableRow;;
34

    
35
public class AddLoadBalancerActivity extends CloudActivity implements OnItemSelectedListener {
36

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

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

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

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

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

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

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

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

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

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

    
142
        }
143

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
325
        }
326

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

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

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

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

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

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

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

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

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

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

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