Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / static / snf / js / ui / web / ui_ips_view.js @ 198b546d

History | View | Annotate | Download (10.4 kB)

1
// Copyright 2014 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 views = snf.views = snf.views || {}
43
    var storage = snf.storage = snf.storage || {};
44
    var util = snf.util = snf.util || {};
45

    
46
    views.IpPortView = views.ext.ModelView.extend({
47
      tpl: '#ip-port-view-tpl',
48
      
49
      init: function() {
50
        this.model.bind("remove", function() {
51
          this.el.remove();
52
        }, this);
53
      },
54

    
55
      vm_status_cls: function(vm) {
56
        var cls = 'inner clearfix main-content';
57
        if (!this.model.get('vm')) { return cls }
58
        if (this.model.get('vm').in_error_state()) {
59
          cls += ' vm-status-error';
60
        }
61
        return cls
62
      },
63
      
64
      vm_style: function() {
65
        var cls, icon_state;
66
        var style = "background-image: url('{0}')";
67
        var vm = this.model.get('vm')
68
        if (!vm) { return }
69
        this.$(".model-logo").removeClass("state1 state2 state3 state4");
70
        icon_state = vm.is_active() ? "on" : "off";
71
        if (icon_state == "on") {
72
          cls = "state1"
73
        } else {
74
          cls = "state2"
75
        }
76
        this.$(".model-logo").addClass(cls);
77
        return style.format(this.get_vm_icon_path(this.model.get('vm'), 
78
                                                  'medium2'));
79
      },
80

    
81
      get_vm_icon_path: function(vm, icon_type) {
82
        var os = vm.get_os();
83
        var icons = window.os_icons || views.IconView.VM_OS_ICONS;
84

    
85
        if (icons.indexOf(os) == -1) {
86
          os = "unknown";
87
        }
88

    
89
        return views.IconView.VM_OS_ICON_TPLS()[icon_type].format(os);
90
      },
91

    
92
      disconnect: function() {
93
        this.model.actions.reset_pending();
94
        this.model.set({status: 'DISCONNECTING'});
95
      }
96
    });
97

    
98
    views.IpView = views.ext.ModelView.extend({
99
      status_map: {
100
        'CONNECTED': 'In use',
101
        'ACTIVE': 'In use',
102
        'CONNECTING': 'Attaching',
103
        'DISCONNECTING': 'Detaching',
104
        'DOWN': 'In use',
105
        'DISCONNECTED': 'Available',
106
        'REMOVING': 'Destroying'
107
      },
108

    
109
      status_cls_map: {
110
        'CONNECTED': 'status-active',
111
        'ACTIVE': 'status-active',
112
        'CONNECTING': 'status-progress',
113
        'DISCONNECTING': 'status-progress',
114
        'DOWN': 'status-inactive',
115
        'DISCONNECTED': 'status-inactive',
116
        'UP': 'status-active',
117
        'REMOVING': 'status-progress destroying-state',
118
      },
119

    
120
      tpl: '#ip-view-tpl',
121
      auto_bind: ['connect_vm'],
122
        
123
      show_reassign_view: function() {
124
          synnefo.ui.main.ip_reassign_view.show(this.model);
125
      },
126

    
127
      status_cls: function() {
128
        return this.status_cls_map[this.model.get('status')];
129
      },
130

    
131
      status_display: function(v) {
132
        return this.status_map[this.model.get('status')];
133
      },
134
      
135
      show_reassign_view: function() {
136
          synnefo.ui.main.ip_reassign_view.show(this.model);
137
      },
138

    
139
      model_icon: function() {
140
        var img = 'ip-icon-detached.png';
141
        var src = synnefo.config.images_url + '/{0}';
142
        if (this.model.get('port_id')) {
143
          img = 'ip-icon.png';
144
        }
145
        return src.format(img);
146
      },
147

    
148
      show_connect_overlay: function() {
149
        this.model.actions.reset_pending();
150
        var vms = this.model.get("network").connectable_vms;
151
        var overlay = this.parent_view.connect_view;
152
        overlay.show_vms(this.model, vms, [], this.connect_vm);
153
      },
154
      
155
      disconnect: function(model, e) {
156
        e && e.stopPropagation();
157
        this.model.do_disconnect();
158
      },
159

    
160
      connect_vm: function(vms) {
161
        var overlay = this.parent_view.connect_view;
162
        overlay.set_in_progress();
163
        _.each(vms, function(vm) {
164
          vm.connect_floating_ip(this.model, 
165
                                 _.bind(this.connect_complete,this),
166
                                 _.bind(this.connect_error, this));
167
        }, this);
168
      },
169

    
170
      connect_complete: function() {
171
        var overlay = this.parent_view.connect_view;
172
        overlay.hide();
173
        overlay.unset_in_progress();
174
        this.model.set({'status': 'CONNECTING'});
175
      },
176

    
177
      connect_error: function() {
178
        var overlay = this.parent_view.connect_view;
179
        overlay.hide();
180
        overlay.unset_in_progress();
181
      },
182

    
183
      remove: function(model, e) {
184
        e && e.stopPropagation();
185
        this.model.do_destroy();
186
      }
187
    });
188
      
189
    views.FloatingIPCreateView = views.Overlay.extend({
190
        view_id: "ip_create_view",
191
        content_selector: "#ips-create-content",
192
        css_class: 'overlay-ip-create overlay-info',
193
        overlay_id: "ip-create-overlay",
194

    
195
        title: "Create new IP address",
196
        subtitle: "IP addresses",
197

    
198
        initialize: function(options) {
199
            views.FloatingIPCreateView.__super__.initialize.apply(this);
200

    
201
            this.create_button = this.$("form .form-action.create");
202
            this.form = this.$("form");
203
            this.project_select = this.$(".project-select");
204
            this.init_handlers();
205
        },
206

    
207
        init_handlers: function() {
208
            this.create_button.click(_.bind(function(e){
209
                this.submit();
210
            }, this));
211

    
212
            this.form.submit(_.bind(function(e){
213
                e.preventDefault();
214
                this.submit();
215
                return false;
216
            }, this))
217
        },
218

    
219
        submit: function() {
220
            if (this.validate()) {
221
                this.create();
222
            };
223
        },
224
        
225
        validate: function() {
226
            var project = this.get_project();
227
            if (!project || !project.quotas.can_fit({'cyclades.floating_ip': 1})) {
228
                this.project_select.closest(".form-field").addClass("error");
229
                this.project_select.focus();
230
                return false;
231
            }
232
            return true;
233
        },
234
        
235
        create: function() {
236
            if (this.create_button.hasClass("in-progress")) { return }
237
            this.create_button.addClass("in-progress");
238

    
239
            var project_id = this.project_select.val();
240
            var project = synnefo.storage.projects.get(project_id);
241

    
242

    
243
            var cb = _.bind(function() { 
244
              synnefo.api.trigger("quota:update");
245
              this.hide(); 
246
            }, this);
247

    
248
            snf.storage.floating_ips.create({
249
                floatingip: {
250
                  project: project_id
251
                }
252
              }, 
253
              { 
254
                complete: cb 
255
              });
256
        },
257
        
258
        update_projects: function() {
259
          this.project_select.find("option").remove();
260
          var min_ip_quota = {'cyclades.floating_ip': 1}
261
          synnefo.storage.projects.each(function(project){
262
            var el = $("<option></option>");
263
            el.attr("value", project.id);
264
            var project_name = util.truncate(project.get('name'), 34);
265
            var name = '{0} ({1} available)'.format(project_name, 
266
              project.quotas.get('cyclades.floating_ip').get('available'));
267
            el.text(name);
268
            if (!project.quotas.can_fit(min_ip_quota)) {
269
              el.attr('disabled', true);
270
            }
271
            this.project_select.append(el);
272
          }, this);
273
        },
274
        
275
        get_project: function() {
276
          var project_id = this.project_select.val();
277
          var project = synnefo.storage.projects.get(project_id);
278
          return project;
279
        },
280

    
281
        beforeOpen: function() {
282
            this.update_projects();
283
            this.create_button.removeClass("in-progress")
284
            this.$(".form-field").removeClass("error");
285
        },
286

    
287
        onOpen: function() {
288
            this.project_select.focus();
289
        }    
290
    });
291

    
292
    views.IpCollectionView = views.ext.CollectionView.extend({
293
      collection: storage.floating_ips,
294
      collection_name: 'floating_ips',
295
      model_view_cls: views.IpView,
296
      create_view_cls: views.FloatingIPCreateView,
297
      quota_key: 'ip',
298
      initialize: function() {
299
        views.IpCollectionView.__super__.initialize.apply(this, arguments);
300
        this.connect_view = new views.IPConnectVmOverlay();
301
      }
302
    });
303

    
304
    views.IpsPaneView = views.ext.PaneView.extend({
305
      el: '#ips-pane',
306
      collection_view_cls: views.IpCollectionView,
307
    });
308

    
309
    views.IPConnectVmOverlay = views.NetworkConnectVMsOverlay.extend({
310
        css_class: "overlay-info connect-ip",
311
        title: "Attach IP to machine",
312
        allow_multiple: false,
313

    
314
        show_vms: function(ip, vms, selected, callback, subtitle) {
315
            views.IPConnectVmOverlay.__super__.show_vms.call(this, 
316
                  undefined, vms, selected, callback, subtitle);
317
            this.ip = ip;
318
            this.set_desc("Select machine to attach <em>" + 
319
                          ip.escape('floating_ip_address') + 
320
                          "</em> to.");
321
        },
322
        
323
        set_desc: function(desc) {
324
            this.$(".description p").html(desc);
325
        }
326

    
327
    });
328

    
329

    
330
})(this);