Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / static / snf / js / ui / web / ui_public_ips_view.js @ 1fc7640d

History | View | Annotate | Download (10.9 kB)

1
// Copyright 2011 GRNET S.A. All rights reserved.
2
// 
3
// Redistribution and use in source and binary forms, with or
4
// without modification, are permitted provided that the following
5
// conditions are met:
6
// 
7
//   1. Redistributions of source code must retain the above
8
//      copyright notice, this list of conditions and the following
9
//      disclaimer.
10
// 
11
//   2. Redistributions in binary form must reproduce the above
12
//      copyright notice, this list of conditions and the following
13
//      disclaimer in the documentation and/or other materials
14
//      provided with the distribution.
15
// 
16
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
// POSSIBILITY OF SUCH DAMAGE.
28
// 
29
// The views and conclusions contained in the software and
30
// documentation are those of the authors and should not be
31
// interpreted as representing official policies, either expressed
32
// or implied, of GRNET S.A.
33
// 
34

    
35
;(function(root){
36

    
37
    // root
38
    var root = root;
39
    
40
    // setup namepsaces
41
    var snf = root.synnefo = root.synnefo || {};
42
    var api = snf.api = snf.api || {};
43
    var models = snf.models = snf.models || {}
44
    var storage = snf.storage = snf.storage || {};
45
    var ui = snf.ui = snf.ui || {};
46
    var util = snf.util = snf.util || {};
47

    
48
    var views = snf.views = snf.views || {}
49

    
50
    // shortcuts
51
    var bb = root.Backbone;
52
    
53
    views.PublicIPsConnectOverlay = views.NetworkConnectVMsOverlay.extend({
54
        css_class: "overlay-info connect-ip",
55
        title: "Connect IP to machine",
56

    
57
        initialize: function() {
58
            views.PublicIPsConnectOverlay.__super__.initialize.apply(this, arguments);
59
        },
60

    
61
        show_vms: function(ip, vms, selected, callback, subtitle) {
62
            views.PublicIPsConnectOverlay.__super__.show_vms.call(this, 
63
                  undefined, vms, selected, callback, subtitle);
64
            this.ip = ip;
65
            this.set_desc("Select machine to assign <em>" + ip.escape('ip') + "</em> to.");
66
        },
67
        
68
        handle_vm_click: function(el) {
69
            var vm = $(el).data('vm');
70
            this.cb(vm, this.ip);
71
        },
72

    
73
        set_desc: function(desc) {
74
            this.$(".description p").html(desc);
75
        },
76

    
77
        onClose: function() {
78
            views.PublicIPsConnectOverlay.__super__.onClose.apply(this, arguments);
79
            synnefo.ui.main.public_ips_view.show();
80
        }
81

    
82
    });
83

    
84
    views.PublicIPsView = views.CollectionView.extend({
85
        collection: storage.public_ips,
86

    
87
        create_success_msg: "IP created",
88
        fetch_params: {update: true},
89

    
90
        initialize: function(options) {
91
            views.PublicIPsView.__super__.initialize.apply(this, arguments);
92
            this.$(".private-cont").hide();
93
            _.bindAll(this);
94
            this.bind("item:add", this.animate_on_add);
95
            this.connect_overlay = new views.PublicIPsConnectOverlay();
96
        },
97

    
98
        init_handlers: function() {
99
            views.PublicIPsView.__super__.init_handlers.apply(this, arguments);
100
        },
101

    
102
        bind_list_item_actions: function(el, model) {
103
            var self = this;
104
            views.PublicIPsView.__super__.bind_list_item_actions.apply(this, 
105
                                                                       arguments);
106
            el.find(".connect").bind("click", _.bind(function() {
107
                this.connect_to_vm(model);
108
            }, this));
109
            el.find(".disconnect").bind("click", _.bind(function() {
110
                var confirmed = confirm("Are you sure you want to release " + model.get('ip') + " ?");
111
                if (confirmed) {
112
                    this.disconnect_from_vm(model);
113
                }
114
            }, this));
115
            synnefo.storage.vms.bind('change:task_state', function(vm) {
116
                if (model.get_vm() == vm) {
117
                  self.update_list_item(el, model);
118
                }
119
            });
120
            model.bind('change', function(arguments) {
121
                self.update_list_item(el, model);
122
            });
123
        },
124
        
125
        connect_to_vm: function(ip) {
126
            this.connect_overlay.show_vms(ip, snf.storage.vms.get_connectable(), [], this.connect_vm);
127
        },
128

    
129
        connect_vm: function(vm, ip) {
130
            var self = this;
131
            vm.call('addFloatingIp', _.bind(function() {
132
                ip.set({'state': 'connecting'});
133
                synnefo.ui.main.public_ips_view.show();
134
            }, this), undefined, {address:ip.get('ip'), error: function(xhr, err, err_type) {
135
                snf.ui.main.public_ips_view.subview.connect_overlay.hide();
136
                snf.ui.main.public_ips_view.show();
137
                snf.ui.main.public_ips_view.subview.show_list_msg("error", 
138
                                                                  "Connect failed ("+err_type+")");
139
            }});
140
        },
141

    
142
        disconnect_from_vm: function(ip) {
143
            var self = this;
144
            var vm = ip.get_vm();
145
            ip.set({'state': 'disconnecting'});
146
            vm.call('removeFloatingIp', _.bind(function() {
147
            }, this), undefined, {address:ip.get('ip'), error: function(xhr, err, err_type) {
148
                ip.set({'state': null});
149
                snf.ui.main.public_ips_view.subview.show_list_msg("error", 
150
                                                                  "Disconnect failed ("+err_type+")");
151
            }});
152
        },
153

    
154
        update_list: function() {
155
            this.check_limit();
156
            views.PublicIPsView.__super__.update_list.apply(this, arguments);
157
        },
158

    
159
        update_list_item: function(el, model) {
160
            el.toggleClass('fixed-ip', model.get('fixed_ip'));
161
            el.toggleClass('connected', model.get_vm() != null);
162

    
163
            var in_progress = model.get('state') != null || model.get_vm() && model.get_vm().get('task_state') != "";
164
            el.toggleClass('in-progress', !!in_progress);
165
            if (in_progress) {
166
              var progress_msg = undefined;
167
              var ip_progress = model.get('state');
168
              if (ip_progress) {
169
                progress_msg_map = {'connecting': 'Connecting', 
170
                  'disconnecting': 'Disconnecting'};
171
                progress_msg = progress_msg_map[ip_progress]
172
              } else {
173
                  progress_msg = "Machine busy";
174
              };
175
              el.find(".progres-msg span").text(progress_msg);
176
            }
177
            
178
            el.find(".address").text(model.get('ip'));
179
            if (model.get_vm()) {
180
              el.find(".vm-name").text(model.get_vm().escape('name'));
181
            } else {
182
              el.find(".vm-name").text('');
183
            }
184
            return el;
185
        },
186

    
187
        reset: function() {
188
            this.check_limit();
189
        },
190

    
191
        show_form: function() {
192
            this.creating = true;
193
            this.submit_form();
194
            this.close_form();
195
        },
196

    
197
        get_form_data: function() {
198
            return {'pool': undefined, 'address': undefined}
199
        },
200
    
201
        validate_data: function() {
202
            return new snf.util.errorList();
203
        },
204

    
205
        show_form_errors: function(errors) {
206
            this.show_list_msg("error", errors[''])
207
        },
208

    
209
        check_limit: function() {
210
            var can_create = true;
211
            var resource = synnefo.storage.quotas.get('cyclades.floating_ip');
212
            if (!resource) { 
213
              can_create = true 
214
            } else {
215
              var limit = resource.get('limit');
216
              if (limit <= synnefo.storage.public_ips.length) {
217
                can_create = false;
218
              }
219
              var left = limit - synnefo.storage.public_ips.length;
220
              this.$(".quotas .available").text(left);
221
            };
222
            if (can_create) {
223
              this.$(".limit-msg").hide();
224
              this.$(".top-actions .collection-action").show();
225
            } else {
226
              this.$(".limit-msg").show();
227
              this.$(".top-actions .collection-action").hide();
228
            }
229
        },
230

    
231
        append_actions: function(el, model) {
232
            var actions = $('<div class="item-actions">' +
233
                            '<div class="item-action remove">remove</div>' + 
234
                            '<div class="item-action confirm-remove confirm">' +
235
                            '<span class="text">confirm</span>' + 
236
                            '<span class="cancel-remove cancel">cancel</span></div>' + 
237
                            '<div class="item-action disconnect">disconnect</div>' +
238
                            '<div class="item-action connect">connect to machine</div>' +
239
                            '</div>');
240
            el.append(actions);
241
        },
242

    
243
    })
244

    
245
    views.PublicIPsOverlay = views.Overlay.extend({
246
        
247
        view_id: "public_ips_view",
248
        content_selector: "#user_public_ips",
249
        css_class: 'overlay-public-ips overlay-info',
250
        overlay_id: "user_public_ips_overlay",
251

    
252
        title: "Manage your IP addresses",
253
        subtitle: "IP addresses",
254

    
255
        initialize: function(options) {
256
            views.PublicIPsOverlay.__super__.initialize.apply(this, arguments);
257
            this.subview = new views.PublicIPsView({el:this.$(".public-ips-view")});
258
            this.fetcher_params = [snf.config.update_interval, 
259
                                  snf.config.update_interval_increase || 500,
260
                                  snf.config.fast_interval || snf.config.update_interval/2, 
261
                                  snf.config.update_interval_increase_after_calls || 4,
262
                                  snf.config.update_interval_max || 20000,
263
                                  true, 
264
                                  {is_recurrent: true, update: true}]
265
        },
266

    
267
        show: function(view) {
268
            if (!this.fetcher) {
269
              this.fetcher = snf.storage.public_ips.get_fetcher.apply(snf.storage.public_ips, 
270
                                                        _.clone(this.fetcher_params));
271
            }
272
            this.fetcher.start();
273
            this.subview.reset();
274
            this.subview.update_models();
275
            views.PublicIPsOverlay.__super__.show.apply(this, arguments);
276
        },
277
        
278
        init_handlers: function() {
279
        },
280

    
281
        onClose: function() {
282
            if (this.fetcher) {
283
                this.fetcher.stop();
284
            }
285
        }
286
        
287
    });
288
})(this);