Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / static / snf / js / models.js @ 426e1fb9

History | View | Annotate | Download (84.3 kB)

1 00469232 Kostas Papadimitriou
// Copyright 2011 GRNET S.A. All rights reserved.
2 00469232 Kostas Papadimitriou
// 
3 00469232 Kostas Papadimitriou
// Redistribution and use in source and binary forms, with or
4 00469232 Kostas Papadimitriou
// without modification, are permitted provided that the following
5 00469232 Kostas Papadimitriou
// conditions are met:
6 00469232 Kostas Papadimitriou
// 
7 00469232 Kostas Papadimitriou
//   1. Redistributions of source code must retain the above
8 00469232 Kostas Papadimitriou
//      copyright notice, this list of conditions and the following
9 00469232 Kostas Papadimitriou
//      disclaimer.
10 00469232 Kostas Papadimitriou
// 
11 00469232 Kostas Papadimitriou
//   2. Redistributions in binary form must reproduce the above
12 00469232 Kostas Papadimitriou
//      copyright notice, this list of conditions and the following
13 00469232 Kostas Papadimitriou
//      disclaimer in the documentation and/or other materials
14 00469232 Kostas Papadimitriou
//      provided with the distribution.
15 00469232 Kostas Papadimitriou
// 
16 00469232 Kostas Papadimitriou
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 00469232 Kostas Papadimitriou
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 00469232 Kostas Papadimitriou
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 00469232 Kostas Papadimitriou
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 00469232 Kostas Papadimitriou
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 00469232 Kostas Papadimitriou
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 00469232 Kostas Papadimitriou
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 00469232 Kostas Papadimitriou
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 00469232 Kostas Papadimitriou
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 00469232 Kostas Papadimitriou
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 00469232 Kostas Papadimitriou
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 00469232 Kostas Papadimitriou
// POSSIBILITY OF SUCH DAMAGE.
28 00469232 Kostas Papadimitriou
// 
29 00469232 Kostas Papadimitriou
// The views and conclusions contained in the software and
30 00469232 Kostas Papadimitriou
// documentation are those of the authors and should not be
31 00469232 Kostas Papadimitriou
// interpreted as representing official policies, either expressed
32 00469232 Kostas Papadimitriou
// or implied, of GRNET S.A.
33 00469232 Kostas Papadimitriou
// 
34 00469232 Kostas Papadimitriou
35 8d08f18a Kostas Papadimitriou
;(function(root){
36 8d08f18a Kostas Papadimitriou
    
37 8d08f18a Kostas Papadimitriou
    // root
38 8d08f18a Kostas Papadimitriou
    var root = root;
39 8d08f18a Kostas Papadimitriou
    
40 8d08f18a Kostas Papadimitriou
    // setup namepsaces
41 8d08f18a Kostas Papadimitriou
    var snf = root.synnefo = root.synnefo || {};
42 8d08f18a Kostas Papadimitriou
    var models = snf.models = snf.models || {}
43 8d08f18a Kostas Papadimitriou
    var storage = snf.storage = snf.storage || {};
44 8d08f18a Kostas Papadimitriou
    var util = snf.util = snf.util || {};
45 8d08f18a Kostas Papadimitriou
46 8d08f18a Kostas Papadimitriou
    // shortcuts
47 8d08f18a Kostas Papadimitriou
    var bb = root.Backbone;
48 8d08f18a Kostas Papadimitriou
    var slice = Array.prototype.slice
49 8d08f18a Kostas Papadimitriou
50 8d08f18a Kostas Papadimitriou
    // logging
51 8d08f18a Kostas Papadimitriou
    var logger = new snf.logging.logger("SNF-MODELS");
52 8d08f18a Kostas Papadimitriou
    var debug = _.bind(logger.debug, logger);
53 8d08f18a Kostas Papadimitriou
    
54 8d08f18a Kostas Papadimitriou
    // get url helper
55 c4fff449 Kostas Papadimitriou
    var getUrl = function(baseurl) {
56 47e34b99 Kostas Papadimitriou
        var baseurl = baseurl || snf.config.api_urls[this.api_type];
57 c4fff449 Kostas Papadimitriou
        return baseurl + "/" + this.path;
58 8d08f18a Kostas Papadimitriou
    }
59 126a01f2 Kostas Papadimitriou
60 126a01f2 Kostas Papadimitriou
    var NIC_REGEX = /^nic-([0-9]+)-([0-9]+)$/
61 8d08f18a Kostas Papadimitriou
    
62 8d08f18a Kostas Papadimitriou
    // i18n
63 8d08f18a Kostas Papadimitriou
    BUILDING_MESSAGES = window.BUILDING_MESSAGES || {'INIT': 'init', 'COPY': '{0}, {1}, {2}', 'FINAL': 'final'};
64 8d08f18a Kostas Papadimitriou
65 8d08f18a Kostas Papadimitriou
    // Base object for all our models
66 8d08f18a Kostas Papadimitriou
    models.Model = bb.Model.extend({
67 8d08f18a Kostas Papadimitriou
        sync: snf.api.sync,
68 8d08f18a Kostas Papadimitriou
        api: snf.api,
69 47e34b99 Kostas Papadimitriou
        api_type: 'compute',
70 8d08f18a Kostas Papadimitriou
        has_status: false,
71 8d08f18a Kostas Papadimitriou
72 8d08f18a Kostas Papadimitriou
        initialize: function() {
73 8d08f18a Kostas Papadimitriou
            if (this.has_status) {
74 8d08f18a Kostas Papadimitriou
                this.bind("change:status", this.handle_remove);
75 8d08f18a Kostas Papadimitriou
                this.handle_remove();
76 8d08f18a Kostas Papadimitriou
            }
77 47e34b99 Kostas Papadimitriou
            
78 258235f4 Kostas Papadimitriou
            this.api_call = _.bind(this.api.call, this);
79 df251d55 Kostas Papadimitriou
            models.Model.__super__.initialize.apply(this, arguments);
80 8d08f18a Kostas Papadimitriou
        },
81 8d08f18a Kostas Papadimitriou
82 8d08f18a Kostas Papadimitriou
        handle_remove: function() {
83 643de8c0 Kostas Papadimitriou
            if (this.get("status") == 'DELETED') {
84 8d08f18a Kostas Papadimitriou
                if (this.collection) {
85 643de8c0 Kostas Papadimitriou
                    try { this.clear_pending_action();} catch (err) {};
86 643de8c0 Kostas Papadimitriou
                    try { this.reset_pending_actions();} catch (err) {};
87 2c9bfad1 Kostas Papadimitriou
                    try { this.stop_stats_update();} catch (err) {};
88 8d08f18a Kostas Papadimitriou
                    this.collection.remove(this.id);
89 8d08f18a Kostas Papadimitriou
                }
90 8d08f18a Kostas Papadimitriou
            }
91 8d08f18a Kostas Papadimitriou
        },
92 8d08f18a Kostas Papadimitriou
        
93 8d08f18a Kostas Papadimitriou
        // custom set method to allow submodels to use
94 8d08f18a Kostas Papadimitriou
        // set_<attr> methods for handling the value of each
95 8d08f18a Kostas Papadimitriou
        // attribute and overriding the default set method
96 8d08f18a Kostas Papadimitriou
        // for specific parameters
97 8d08f18a Kostas Papadimitriou
        set: function(params, options) {
98 8d08f18a Kostas Papadimitriou
            _.each(params, _.bind(function(value, key){
99 8d08f18a Kostas Papadimitriou
                if (this["set_" + key]) {
100 8d08f18a Kostas Papadimitriou
                    params[key] = this["set_" + key](value);
101 8d08f18a Kostas Papadimitriou
                }
102 8d08f18a Kostas Papadimitriou
            }, this))
103 8d08f18a Kostas Papadimitriou
            var ret = bb.Model.prototype.set.call(this, params, options);
104 8d08f18a Kostas Papadimitriou
            return ret;
105 8d08f18a Kostas Papadimitriou
        },
106 8d08f18a Kostas Papadimitriou
107 8d08f18a Kostas Papadimitriou
        url: function(options) {
108 c4fff449 Kostas Papadimitriou
            return getUrl.call(this, this.base_url) + "/" + this.id;
109 8d08f18a Kostas Papadimitriou
        },
110 8d08f18a Kostas Papadimitriou
111 8d08f18a Kostas Papadimitriou
        api_path: function(options) {
112 8d08f18a Kostas Papadimitriou
            return this.path + "/" + this.id;
113 8d08f18a Kostas Papadimitriou
        },
114 8d08f18a Kostas Papadimitriou
115 8d08f18a Kostas Papadimitriou
        parse: function(resp, xhr) {
116 8d08f18a Kostas Papadimitriou
        },
117 8d08f18a Kostas Papadimitriou
118 a429705e Kostas Papadimitriou
        remove: function(complete, error, success) {
119 a429705e Kostas Papadimitriou
            this.api_call(this.api_path(), "delete", undefined, complete, error, success);
120 2506f741 Kostas Papadimitriou
        },
121 2506f741 Kostas Papadimitriou
122 2506f741 Kostas Papadimitriou
        changedKeys: function() {
123 2506f741 Kostas Papadimitriou
            return _.keys(this.changedAttributes() || {});
124 2506f741 Kostas Papadimitriou
        },
125 1e882dd7 Kostas Papadimitriou
            
126 1e882dd7 Kostas Papadimitriou
        // return list of changed attributes that included in passed list
127 1e882dd7 Kostas Papadimitriou
        // argument
128 1e882dd7 Kostas Papadimitriou
        getKeysChanged: function(keys) {
129 1e882dd7 Kostas Papadimitriou
            return _.intersection(keys, this.changedKeys());
130 1e882dd7 Kostas Papadimitriou
        },
131 1e882dd7 Kostas Papadimitriou
        
132 1e882dd7 Kostas Papadimitriou
        // boolean check of keys changed
133 1e882dd7 Kostas Papadimitriou
        keysChanged: function(keys) {
134 1e882dd7 Kostas Papadimitriou
            return this.getKeysChanged(keys).length > 0;
135 1e882dd7 Kostas Papadimitriou
        },
136 2506f741 Kostas Papadimitriou
137 1e882dd7 Kostas Papadimitriou
        // check if any of the passed attribues has changed
138 2506f741 Kostas Papadimitriou
        hasOnlyChange: function(keys) {
139 2506f741 Kostas Papadimitriou
            var ret = false;
140 2506f741 Kostas Papadimitriou
            _.each(keys, _.bind(function(key) {
141 2506f741 Kostas Papadimitriou
                if (this.changedKeys().length == 1 && this.changedKeys().indexOf(key) > -1) { ret = true};
142 2506f741 Kostas Papadimitriou
            }, this));
143 2506f741 Kostas Papadimitriou
            return ret;
144 8d08f18a Kostas Papadimitriou
        }
145 8d08f18a Kostas Papadimitriou
146 8d08f18a Kostas Papadimitriou
    })
147 8d08f18a Kostas Papadimitriou
    
148 8d08f18a Kostas Papadimitriou
    // Base object for all our model collections
149 8d08f18a Kostas Papadimitriou
    models.Collection = bb.Collection.extend({
150 8d08f18a Kostas Papadimitriou
        sync: snf.api.sync,
151 8d08f18a Kostas Papadimitriou
        api: snf.api,
152 47e34b99 Kostas Papadimitriou
        api_type: 'compute',
153 16392650 Kostas Papadimitriou
        supportIncUpdates: true,
154 47e34b99 Kostas Papadimitriou
155 47e34b99 Kostas Papadimitriou
        initialize: function() {
156 47e34b99 Kostas Papadimitriou
            models.Collection.__super__.initialize.apply(this, arguments);
157 258235f4 Kostas Papadimitriou
            this.api_call = _.bind(this.api.call, this);
158 47e34b99 Kostas Papadimitriou
        },
159 47e34b99 Kostas Papadimitriou
160 2cee7cb0 Kostas Papadimitriou
        url: function(options, method) {
161 2cee7cb0 Kostas Papadimitriou
            return getUrl.call(this, this.base_url) + (
162 2cee7cb0 Kostas Papadimitriou
                    options.details || this.details && method != 'create' ? '/detail' : '');
163 8d08f18a Kostas Papadimitriou
        },
164 8d08f18a Kostas Papadimitriou
165 8d08f18a Kostas Papadimitriou
        fetch: function(options) {
166 859a4609 Kostas Papadimitriou
            if (!options) { options = {} };
167 8d08f18a Kostas Papadimitriou
            // default to update
168 8d08f18a Kostas Papadimitriou
            if (!this.noUpdate) {
169 8d08f18a Kostas Papadimitriou
                if (options.update === undefined) { options.update = true };
170 8d08f18a Kostas Papadimitriou
                if (!options.removeMissing && options.refresh) { options.removeMissing = true };
171 859a4609 Kostas Papadimitriou
            } else {
172 859a4609 Kostas Papadimitriou
                if (options.refresh === undefined) {
173 859a4609 Kostas Papadimitriou
                    options.refresh = true;
174 859a4609 Kostas Papadimitriou
                }
175 8d08f18a Kostas Papadimitriou
            }
176 8d08f18a Kostas Papadimitriou
            // custom event foreach fetch
177 8d08f18a Kostas Papadimitriou
            return bb.Collection.prototype.fetch.call(this, options)
178 8d08f18a Kostas Papadimitriou
        },
179 8d08f18a Kostas Papadimitriou
180 859a4609 Kostas Papadimitriou
        create: function(model, options) {
181 859a4609 Kostas Papadimitriou
            var coll = this;
182 859a4609 Kostas Papadimitriou
            options || (options = {});
183 859a4609 Kostas Papadimitriou
            model = this._prepareModel(model, options);
184 859a4609 Kostas Papadimitriou
            if (!model) return false;
185 859a4609 Kostas Papadimitriou
            var success = options.success;
186 859a4609 Kostas Papadimitriou
            options.success = function(nextModel, resp, xhr) {
187 859a4609 Kostas Papadimitriou
                if (success) success(nextModel, resp, xhr);
188 859a4609 Kostas Papadimitriou
            };
189 859a4609 Kostas Papadimitriou
            model.save(null, options);
190 859a4609 Kostas Papadimitriou
            return model;
191 859a4609 Kostas Papadimitriou
        },
192 859a4609 Kostas Papadimitriou
193 1cc6e94f Kostas Papadimitriou
        get_fetcher: function(interval, increase, fast, increase_after_calls, max, initial_call, params) {
194 9ce969a7 Kostas Papadimitriou
            var fetch_params = params || {};
195 1cc6e94f Kostas Papadimitriou
            var handler_options = {};
196 258235f4 Kostas Papadimitriou
197 258235f4 Kostas Papadimitriou
            fetch_params.skips_timeouts = true;
198 1cc6e94f Kostas Papadimitriou
            handler_options.interval = interval;
199 1cc6e94f Kostas Papadimitriou
            handler_options.increase = increase;
200 1cc6e94f Kostas Papadimitriou
            handler_options.fast = fast;
201 1cc6e94f Kostas Papadimitriou
            handler_options.increase_after_calls = increase_after_calls;
202 1cc6e94f Kostas Papadimitriou
            handler_options.max= max;
203 258235f4 Kostas Papadimitriou
            handler_options.id = "collection id";
204 1cc6e94f Kostas Papadimitriou
205 8d08f18a Kostas Papadimitriou
            var last_ajax = undefined;
206 258235f4 Kostas Papadimitriou
            var callback = _.bind(function() {
207 9ce969a7 Kostas Papadimitriou
                // clone to avoid referenced objects
208 9ce969a7 Kostas Papadimitriou
                var params = _.clone(fetch_params);
209 8d08f18a Kostas Papadimitriou
                updater._ajax = last_ajax;
210 a89ef0f5 Kostas Papadimitriou
                
211 42fb39fb Kostas Papadimitriou
                // wait for previous request to finish
212 a89ef0f5 Kostas Papadimitriou
                if (last_ajax && last_ajax.readyState < 4 && last_ajax.statusText != "timeout") {
213 a89ef0f5 Kostas Papadimitriou
                    // opera readystate for 304 responses is 0
214 a89ef0f5 Kostas Papadimitriou
                    if (!($.browser.opera && last_ajax.readyState == 0 && last_ajax.status == 304)) {
215 a89ef0f5 Kostas Papadimitriou
                        return;
216 a89ef0f5 Kostas Papadimitriou
                    }
217 8d08f18a Kostas Papadimitriou
                }
218 258235f4 Kostas Papadimitriou
                
219 9ce969a7 Kostas Papadimitriou
                last_ajax = this.fetch(params);
220 8d08f18a Kostas Papadimitriou
            }, this);
221 258235f4 Kostas Papadimitriou
            handler_options.callback = callback;
222 8d08f18a Kostas Papadimitriou
223 258235f4 Kostas Papadimitriou
            var updater = new snf.api.updateHandler(_.clone(_.extend(handler_options, fetch_params)));
224 35855ff5 Kostas Papadimitriou
            snf.api.bind("call", _.throttle(_.bind(function(){ updater.faster(true)}, this)), 1000);
225 8d08f18a Kostas Papadimitriou
            return updater;
226 8d08f18a Kostas Papadimitriou
        }
227 8d08f18a Kostas Papadimitriou
    });
228 8d08f18a Kostas Papadimitriou
    
229 8d08f18a Kostas Papadimitriou
    // Image model
230 8d08f18a Kostas Papadimitriou
    models.Image = models.Model.extend({
231 8d08f18a Kostas Papadimitriou
        path: 'images',
232 8f53cfa3 Kostas Papadimitriou
        
233 8d08f18a Kostas Papadimitriou
        get_size: function() {
234 820ef2f0 Kostas Papadimitriou
            return parseInt(this.get('metadata') ? this.get('metadata').values.size : -1)
235 820ef2f0 Kostas Papadimitriou
        },
236 820ef2f0 Kostas Papadimitriou
237 88d6d677 Kostas Papadimitriou
        get_description: function(escape) {
238 88d6d677 Kostas Papadimitriou
            if (escape == undefined) { escape = true };
239 88d6d677 Kostas Papadimitriou
            if (escape) { return this.escape('description') || "No description available"}
240 88d6d677 Kostas Papadimitriou
            return this.get('description') || "No description available."
241 88d6d677 Kostas Papadimitriou
        },
242 88d6d677 Kostas Papadimitriou
243 948042ca Kostas Papadimitriou
        get_meta: function(key) {
244 88d6d677 Kostas Papadimitriou
            if (this.get('metadata') && this.get('metadata').values) {
245 88d6d677 Kostas Papadimitriou
                if (!this.get('metadata').values[key]) { return null }
246 df251d55 Kostas Papadimitriou
                return _.escape(this.get('metadata').values[key]);
247 88d6d677 Kostas Papadimitriou
            } else {
248 88d6d677 Kostas Papadimitriou
                return null;
249 88d6d677 Kostas Papadimitriou
            }
250 88d6d677 Kostas Papadimitriou
        },
251 88d6d677 Kostas Papadimitriou
252 88d6d677 Kostas Papadimitriou
        get_meta_keys: function() {
253 88d6d677 Kostas Papadimitriou
            if (this.get('metadata') && this.get('metadata').values) {
254 88d6d677 Kostas Papadimitriou
                return _.keys(this.get('metadata').values);
255 88d6d677 Kostas Papadimitriou
            } else {
256 88d6d677 Kostas Papadimitriou
                return [];
257 948042ca Kostas Papadimitriou
            }
258 948042ca Kostas Papadimitriou
        },
259 948042ca Kostas Papadimitriou
260 948042ca Kostas Papadimitriou
        get_owner: function() {
261 1faf0b9c Kostas Papadimitriou
            return this.get('owner') || _.keys(synnefo.config.system_images_owners)[0];
262 948042ca Kostas Papadimitriou
        },
263 948042ca Kostas Papadimitriou
264 8f53cfa3 Kostas Papadimitriou
        get_owner_uuid: function() {
265 8f53cfa3 Kostas Papadimitriou
            return this.get('owner_uuid');
266 8f53cfa3 Kostas Papadimitriou
        },
267 8f53cfa3 Kostas Papadimitriou
268 fc6f43c3 Kostas Papadimitriou
        is_system_image: function() {
269 fc6f43c3 Kostas Papadimitriou
          var owner = this.get_owner();
270 fc6f43c3 Kostas Papadimitriou
          return _.include(_.keys(synnefo.config.system_images_owners), owner)
271 fc6f43c3 Kostas Papadimitriou
        },
272 fc6f43c3 Kostas Papadimitriou
273 fc6f43c3 Kostas Papadimitriou
        owned_by: function(user) {
274 fc6f43c3 Kostas Papadimitriou
          if (!user) { user = synnefo.user }
275 afe9ca75 Kostas Papadimitriou
          return user.get_username() == this.get('owner_uuid');
276 fc6f43c3 Kostas Papadimitriou
        },
277 fc6f43c3 Kostas Papadimitriou
278 babfdb9b Kostas Papadimitriou
        display_owner: function() {
279 babfdb9b Kostas Papadimitriou
            var owner = this.get_owner();
280 babfdb9b Kostas Papadimitriou
            if (_.include(_.keys(synnefo.config.system_images_owners), owner)) {
281 babfdb9b Kostas Papadimitriou
                return synnefo.config.system_images_owners[owner];
282 babfdb9b Kostas Papadimitriou
            } else {
283 babfdb9b Kostas Papadimitriou
                return owner;
284 babfdb9b Kostas Papadimitriou
            }
285 babfdb9b Kostas Papadimitriou
        },
286 03639c6d Kostas Papadimitriou
    
287 5a434360 Kostas Papadimitriou
        get_readable_size: function() {
288 03639c6d Kostas Papadimitriou
            if (this.is_deleted()) {
289 03639c6d Kostas Papadimitriou
                return synnefo.config.image_deleted_size_title || '(none)';
290 03639c6d Kostas Papadimitriou
            }
291 03639c6d Kostas Papadimitriou
            return this.get_size() > 0 ? util.readablizeBytes(this.get_size() * 1024 * 1024) : '(none)';
292 5a434360 Kostas Papadimitriou
        },
293 5a434360 Kostas Papadimitriou
294 820ef2f0 Kostas Papadimitriou
        get_os: function() {
295 88d6d677 Kostas Papadimitriou
            return this.get_meta('OS');
296 ccb14ad0 Kostas Papadimitriou
        },
297 ccb14ad0 Kostas Papadimitriou
298 6a0915f7 Kostas Papadimitriou
        get_gui: function() {
299 6a0915f7 Kostas Papadimitriou
            return this.get_meta('GUI');
300 6a0915f7 Kostas Papadimitriou
        },
301 6a0915f7 Kostas Papadimitriou
302 bdfb089f Kostas Papadimitriou
        get_created_users: function() {
303 bdfb089f Kostas Papadimitriou
            try {
304 bdfb089f Kostas Papadimitriou
              var users = this.get_meta('users').split(" ");
305 bdfb089f Kostas Papadimitriou
            } catch (err) { users = null }
306 bdfb089f Kostas Papadimitriou
            if (!users) { users = [synnefo.config.os_created_users[this.get_os()] || "root"]}
307 bdfb089f Kostas Papadimitriou
            return users;
308 47276ec2 Kostas Papadimitriou
        },
309 47276ec2 Kostas Papadimitriou
310 ccb14ad0 Kostas Papadimitriou
        get_sort_order: function() {
311 ccb14ad0 Kostas Papadimitriou
            return parseInt(this.get('metadata') ? this.get('metadata').values.sortorder : -1)
312 47276ec2 Kostas Papadimitriou
        },
313 2cee7cb0 Kostas Papadimitriou
314 2cee7cb0 Kostas Papadimitriou
        get_vm: function() {
315 2cee7cb0 Kostas Papadimitriou
            var vm_id = this.get("serverRef");
316 2cee7cb0 Kostas Papadimitriou
            var vm = undefined;
317 2cee7cb0 Kostas Papadimitriou
            vm = storage.vms.get(vm_id);
318 2cee7cb0 Kostas Papadimitriou
            return vm;
319 2cee7cb0 Kostas Papadimitriou
        },
320 948042ca Kostas Papadimitriou
321 948042ca Kostas Papadimitriou
        is_public: function() {
322 77baab80 Kostas Papadimitriou
            return this.get('is_public') == undefined ? true : this.get('is_public');
323 948042ca Kostas Papadimitriou
        },
324 03639c6d Kostas Papadimitriou
325 03639c6d Kostas Papadimitriou
        is_deleted: function() {
326 03639c6d Kostas Papadimitriou
            return this.get('status') == "DELETED"
327 03639c6d Kostas Papadimitriou
        },
328 47276ec2 Kostas Papadimitriou
        
329 bdfb089f Kostas Papadimitriou
        ssh_keys_paths: function() {
330 bdfb089f Kostas Papadimitriou
            return _.map(this.get_created_users(), function(username) {
331 bdfb089f Kostas Papadimitriou
                prepend = '';
332 bdfb089f Kostas Papadimitriou
                if (username != 'root') {
333 bdfb089f Kostas Papadimitriou
                    prepend = '/home'
334 bdfb089f Kostas Papadimitriou
                }
335 5d9ac244 Kostas Papadimitriou
                return {'user': username, 'path': '{1}/{0}/.ssh/authorized_keys'.format(username, 
336 5d9ac244 Kostas Papadimitriou
                                                             prepend)};
337 bdfb089f Kostas Papadimitriou
            });
338 47276ec2 Kostas Papadimitriou
        },
339 47276ec2 Kostas Papadimitriou
340 47276ec2 Kostas Papadimitriou
        _supports_ssh: function() {
341 47276ec2 Kostas Papadimitriou
            if (synnefo.config.support_ssh_os_list.indexOf(this.get_os()) > -1) {
342 47276ec2 Kostas Papadimitriou
                return true;
343 47276ec2 Kostas Papadimitriou
            }
344 d3e4bca7 Kostas Papadimitriou
            if (this.get_meta('osfamily') == 'linux') {
345 d3e4bca7 Kostas Papadimitriou
              return true;
346 d3e4bca7 Kostas Papadimitriou
            }
347 47276ec2 Kostas Papadimitriou
            return false;
348 47276ec2 Kostas Papadimitriou
        },
349 47276ec2 Kostas Papadimitriou
350 47276ec2 Kostas Papadimitriou
        supports: function(feature) {
351 47276ec2 Kostas Papadimitriou
            if (feature == "ssh") {
352 47276ec2 Kostas Papadimitriou
                return this._supports_ssh()
353 47276ec2 Kostas Papadimitriou
            }
354 47276ec2 Kostas Papadimitriou
            return false;
355 47276ec2 Kostas Papadimitriou
        },
356 47276ec2 Kostas Papadimitriou
357 47276ec2 Kostas Papadimitriou
        personality_data_for_keys: function(keys) {
358 5d9ac244 Kostas Papadimitriou
            return _.map(this.ssh_keys_paths(), function(pathinfo) {
359 bdfb089f Kostas Papadimitriou
                var contents = '';
360 bdfb089f Kostas Papadimitriou
                _.each(keys, function(key){
361 bdfb089f Kostas Papadimitriou
                    contents = contents + key.get("content") + "\n"
362 bdfb089f Kostas Papadimitriou
                });
363 bdfb089f Kostas Papadimitriou
                contents = $.base64.encode(contents);
364 bdfb089f Kostas Papadimitriou
365 bdfb089f Kostas Papadimitriou
                return {
366 5d9ac244 Kostas Papadimitriou
                    path: pathinfo.path,
367 5d9ac244 Kostas Papadimitriou
                    contents: contents,
368 5d9ac244 Kostas Papadimitriou
                    mode: 0600,
369 5d9ac244 Kostas Papadimitriou
                    owner: pathinfo.user,
370 5d9ac244 Kostas Papadimitriou
                    group: pathinfo.user
371 bdfb089f Kostas Papadimitriou
                }
372 47276ec2 Kostas Papadimitriou
            });
373 8d08f18a Kostas Papadimitriou
        }
374 8d08f18a Kostas Papadimitriou
    });
375 8d08f18a Kostas Papadimitriou
376 8d08f18a Kostas Papadimitriou
    // Flavor model
377 8d08f18a Kostas Papadimitriou
    models.Flavor = models.Model.extend({
378 8d08f18a Kostas Papadimitriou
        path: 'flavors',
379 8d08f18a Kostas Papadimitriou
380 8d08f18a Kostas Papadimitriou
        details_string: function() {
381 8d08f18a Kostas Papadimitriou
            return "{0} CPU, {1}MB, {2}GB".format(this.get('cpu'), this.get('ram'), this.get('disk'));
382 820ef2f0 Kostas Papadimitriou
        },
383 820ef2f0 Kostas Papadimitriou
384 820ef2f0 Kostas Papadimitriou
        get_disk_size: function() {
385 820ef2f0 Kostas Papadimitriou
            return parseInt(this.get("disk") * 1000)
386 d965e6dc Kostas Papadimitriou
        },
387 d965e6dc Kostas Papadimitriou
388 7ac49c2e Kostas Papadimitriou
        get_ram_size: function() {
389 7ac49c2e Kostas Papadimitriou
            return parseInt(this.get("ram"))
390 7ac49c2e Kostas Papadimitriou
        },
391 7ac49c2e Kostas Papadimitriou
392 d965e6dc Kostas Papadimitriou
        get_disk_template_info: function() {
393 d965e6dc Kostas Papadimitriou
            var info = snf.config.flavors_disk_templates_info[this.get("disk_template")];
394 d965e6dc Kostas Papadimitriou
            if (!info) {
395 d965e6dc Kostas Papadimitriou
                info = { name: this.get("disk_template"), description:'' };
396 d965e6dc Kostas Papadimitriou
            }
397 d965e6dc Kostas Papadimitriou
            return info
398 7ac49c2e Kostas Papadimitriou
        },
399 7ac49c2e Kostas Papadimitriou
400 7ac49c2e Kostas Papadimitriou
        disk_to_bytes: function() {
401 7ac49c2e Kostas Papadimitriou
            return parseInt(this.get("disk")) * 1024 * 1024 * 1024;
402 7ac49c2e Kostas Papadimitriou
        },
403 7ac49c2e Kostas Papadimitriou
404 7ac49c2e Kostas Papadimitriou
        ram_to_bytes: function() {
405 7ac49c2e Kostas Papadimitriou
            return parseInt(this.get("ram")) * 1024 * 1024;
406 7ac49c2e Kostas Papadimitriou
        },
407 820ef2f0 Kostas Papadimitriou
408 8d08f18a Kostas Papadimitriou
    });
409 8d08f18a Kostas Papadimitriou
    
410 101e6604 Kostas Papadimitriou
    models.ParamsList = function(){this.initialize.apply(this, arguments)};
411 101e6604 Kostas Papadimitriou
    _.extend(models.ParamsList.prototype, bb.Events, {
412 101e6604 Kostas Papadimitriou
413 101e6604 Kostas Papadimitriou
        initialize: function(parent, param_name) {
414 101e6604 Kostas Papadimitriou
            this.parent = parent;
415 101e6604 Kostas Papadimitriou
            this.actions = {};
416 101e6604 Kostas Papadimitriou
            this.param_name = param_name;
417 101e6604 Kostas Papadimitriou
            this.length = 0;
418 101e6604 Kostas Papadimitriou
        },
419 101e6604 Kostas Papadimitriou
        
420 101e6604 Kostas Papadimitriou
        has_action: function(action) {
421 101e6604 Kostas Papadimitriou
            return this.actions[action] ? true : false;
422 101e6604 Kostas Papadimitriou
        },
423 101e6604 Kostas Papadimitriou
            
424 101e6604 Kostas Papadimitriou
        _parse_params: function(arguments) {
425 101e6604 Kostas Papadimitriou
            if (arguments.length <= 1) {
426 101e6604 Kostas Papadimitriou
                return [];
427 101e6604 Kostas Papadimitriou
            }
428 101e6604 Kostas Papadimitriou
429 101e6604 Kostas Papadimitriou
            var args = _.toArray(arguments);
430 101e6604 Kostas Papadimitriou
            return args.splice(1);
431 101e6604 Kostas Papadimitriou
        },
432 101e6604 Kostas Papadimitriou
433 101e6604 Kostas Papadimitriou
        contains: function(action, params) {
434 101e6604 Kostas Papadimitriou
            params = this._parse_params(arguments);
435 101e6604 Kostas Papadimitriou
            var has_action = this.has_action(action);
436 101e6604 Kostas Papadimitriou
            if (!has_action) { return false };
437 101e6604 Kostas Papadimitriou
438 101e6604 Kostas Papadimitriou
            var paramsEqual = false;
439 101e6604 Kostas Papadimitriou
            _.each(this.actions[action], function(action_params) {
440 101e6604 Kostas Papadimitriou
                if (_.isEqual(action_params, params)) {
441 101e6604 Kostas Papadimitriou
                    paramsEqual = true;
442 101e6604 Kostas Papadimitriou
                }
443 101e6604 Kostas Papadimitriou
            });
444 101e6604 Kostas Papadimitriou
                
445 101e6604 Kostas Papadimitriou
            return paramsEqual;
446 101e6604 Kostas Papadimitriou
        },
447 101e6604 Kostas Papadimitriou
        
448 101e6604 Kostas Papadimitriou
        is_empty: function() {
449 101e6604 Kostas Papadimitriou
            return _.isEmpty(this.actions);
450 101e6604 Kostas Papadimitriou
        },
451 101e6604 Kostas Papadimitriou
452 101e6604 Kostas Papadimitriou
        add: function(action, params) {
453 101e6604 Kostas Papadimitriou
            params = this._parse_params(arguments);
454 101e6604 Kostas Papadimitriou
            if (this.contains.apply(this, arguments)) { return this };
455 101e6604 Kostas Papadimitriou
            var isnew = false
456 101e6604 Kostas Papadimitriou
            if (!this.has_action(action)) {
457 101e6604 Kostas Papadimitriou
                this.actions[action] = [];
458 101e6604 Kostas Papadimitriou
                isnew = true;
459 101e6604 Kostas Papadimitriou
            };
460 101e6604 Kostas Papadimitriou
461 101e6604 Kostas Papadimitriou
            this.actions[action].push(params);
462 101e6604 Kostas Papadimitriou
            this.parent.trigger("change:" + this.param_name, this.parent, this);
463 101e6604 Kostas Papadimitriou
            if (isnew) {
464 101e6604 Kostas Papadimitriou
                this.trigger("add", action, params);
465 101e6604 Kostas Papadimitriou
            } else {
466 101e6604 Kostas Papadimitriou
                this.trigger("change", action, params);
467 101e6604 Kostas Papadimitriou
            }
468 101e6604 Kostas Papadimitriou
            return this;
469 101e6604 Kostas Papadimitriou
        },
470 101e6604 Kostas Papadimitriou
        
471 101e6604 Kostas Papadimitriou
        remove_all: function(action) {
472 101e6604 Kostas Papadimitriou
            if (this.has_action(action)) {
473 101e6604 Kostas Papadimitriou
                delete this.actions[action];
474 101e6604 Kostas Papadimitriou
                this.parent.trigger("change:" + this.param_name, this.parent, this);
475 101e6604 Kostas Papadimitriou
                this.trigger("remove", action);
476 101e6604 Kostas Papadimitriou
            }
477 101e6604 Kostas Papadimitriou
            return this;
478 101e6604 Kostas Papadimitriou
        },
479 101e6604 Kostas Papadimitriou
480 101e6604 Kostas Papadimitriou
        reset: function() {
481 101e6604 Kostas Papadimitriou
            this.actions = {};
482 101e6604 Kostas Papadimitriou
            this.parent.trigger("change:" + this.param_name, this.parent, this);
483 101e6604 Kostas Papadimitriou
            this.trigger("reset");
484 101e6604 Kostas Papadimitriou
            this.trigger("remove");
485 101e6604 Kostas Papadimitriou
        },
486 101e6604 Kostas Papadimitriou
487 101e6604 Kostas Papadimitriou
        remove: function(action, params) {
488 101e6604 Kostas Papadimitriou
            params = this._parse_params(arguments);
489 101e6604 Kostas Papadimitriou
            if (!this.has_action(action)) { return this };
490 101e6604 Kostas Papadimitriou
            var index = -1;
491 101e6604 Kostas Papadimitriou
            _.each(this.actions[action], _.bind(function(action_params) {
492 101e6604 Kostas Papadimitriou
                if (_.isEqual(action_params, params)) {
493 101e6604 Kostas Papadimitriou
                    index = this.actions[action].indexOf(action_params);
494 101e6604 Kostas Papadimitriou
                }
495 101e6604 Kostas Papadimitriou
            }, this));
496 101e6604 Kostas Papadimitriou
            
497 101e6604 Kostas Papadimitriou
            if (index > -1) {
498 101e6604 Kostas Papadimitriou
                this.actions[action].splice(index, 1);
499 101e6604 Kostas Papadimitriou
                if (_.isEmpty(this.actions[action])) {
500 101e6604 Kostas Papadimitriou
                    delete this.actions[action];
501 101e6604 Kostas Papadimitriou
                }
502 101e6604 Kostas Papadimitriou
                this.parent.trigger("change:" + this.param_name, this.parent, this);
503 101e6604 Kostas Papadimitriou
                this.trigger("remove", action, params);
504 101e6604 Kostas Papadimitriou
            }
505 101e6604 Kostas Papadimitriou
        }
506 101e6604 Kostas Papadimitriou
507 101e6604 Kostas Papadimitriou
    });
508 8d08f18a Kostas Papadimitriou
509 8d08f18a Kostas Papadimitriou
    // Image model
510 8d08f18a Kostas Papadimitriou
    models.Network = models.Model.extend({
511 8d08f18a Kostas Papadimitriou
        path: 'networks',
512 8d08f18a Kostas Papadimitriou
        has_status: true,
513 126a01f2 Kostas Papadimitriou
        defaults: {'connecting':0},
514 8d08f18a Kostas Papadimitriou
        
515 8d08f18a Kostas Papadimitriou
        initialize: function() {
516 1afc3946 Kostas Papadimitriou
            var ret = models.Network.__super__.initialize.apply(this, arguments);
517 101e6604 Kostas Papadimitriou
            this.set({"actions": new models.ParamsList(this, "actions")});
518 126a01f2 Kostas Papadimitriou
            this.update_state();
519 126a01f2 Kostas Papadimitriou
            this.bind("change:nics", _.bind(synnefo.storage.nics.update_net_nics, synnefo.storage.nics));
520 126a01f2 Kostas Papadimitriou
            this.bind("change:status", _.bind(this.update_state, this));
521 8d08f18a Kostas Papadimitriou
            return ret;
522 8d08f18a Kostas Papadimitriou
        },
523 cbf7b384 Kostas Papadimitriou
        
524 cbf7b384 Kostas Papadimitriou
        is_deleted: function() {
525 cbf7b384 Kostas Papadimitriou
          return this.get('status') == 'DELETED';
526 cbf7b384 Kostas Papadimitriou
        },
527 8d08f18a Kostas Papadimitriou
528 c40b07e0 Kostas Papadimitriou
        toJSON: function() {
529 c40b07e0 Kostas Papadimitriou
            var attrs = _.clone(this.attributes);
530 c40b07e0 Kostas Papadimitriou
            attrs.actions = _.clone(this.get("actions").actions);
531 c40b07e0 Kostas Papadimitriou
            return attrs;
532 c40b07e0 Kostas Papadimitriou
        },
533 126a01f2 Kostas Papadimitriou
        
534 126a01f2 Kostas Papadimitriou
        set_state: function(val) {
535 126a01f2 Kostas Papadimitriou
            if (val == "PENDING" && this.get("state") == "DESTORY") {
536 126a01f2 Kostas Papadimitriou
                return "DESTROY";
537 126a01f2 Kostas Papadimitriou
            }
538 126a01f2 Kostas Papadimitriou
            return val;
539 126a01f2 Kostas Papadimitriou
        },
540 c40b07e0 Kostas Papadimitriou
541 8d08f18a Kostas Papadimitriou
        update_state: function() {
542 126a01f2 Kostas Papadimitriou
            if (this.get("connecting") > 0) {
543 8d08f18a Kostas Papadimitriou
                this.set({state: "CONNECTING"});
544 8d08f18a Kostas Papadimitriou
                return
545 8d08f18a Kostas Papadimitriou
            }
546 126a01f2 Kostas Papadimitriou
            
547 126a01f2 Kostas Papadimitriou
            if (this.get_nics(function(nic){ return nic.get("removing") == 1}).length > 0) {
548 8d08f18a Kostas Papadimitriou
                this.set({state: "DISCONNECTING"});
549 8d08f18a Kostas Papadimitriou
                return
550 8d08f18a Kostas Papadimitriou
            }   
551 8d08f18a Kostas Papadimitriou
            
552 126a01f2 Kostas Papadimitriou
            if (this.contains_firewalling_nics() > 0) {
553 126a01f2 Kostas Papadimitriou
                this.set({state: "FIREWALLING"});
554 126a01f2 Kostas Papadimitriou
                return
555 126a01f2 Kostas Papadimitriou
            }   
556 126a01f2 Kostas Papadimitriou
            
557 126a01f2 Kostas Papadimitriou
            if (this.get("state") == "DESTROY") { 
558 126a01f2 Kostas Papadimitriou
                this.set({"destroyed":1});
559 126a01f2 Kostas Papadimitriou
            }
560 126a01f2 Kostas Papadimitriou
            
561 126a01f2 Kostas Papadimitriou
            this.set({state:this.get('status')});
562 126a01f2 Kostas Papadimitriou
        },
563 8d08f18a Kostas Papadimitriou
564 126a01f2 Kostas Papadimitriou
        is_public: function() {
565 47c66641 Dimitris Aragiorgis
            return this.get("public");
566 8d08f18a Kostas Papadimitriou
        },
567 8d08f18a Kostas Papadimitriou
568 126a01f2 Kostas Papadimitriou
        decrease_connecting: function() {
569 126a01f2 Kostas Papadimitriou
            var conn = this.get("connecting");
570 126a01f2 Kostas Papadimitriou
            if (!conn) { conn = 0 };
571 126a01f2 Kostas Papadimitriou
            if (conn > 0) {
572 126a01f2 Kostas Papadimitriou
                conn--;
573 126a01f2 Kostas Papadimitriou
            }
574 126a01f2 Kostas Papadimitriou
            this.set({"connecting": conn});
575 8d08f18a Kostas Papadimitriou
            this.update_state();
576 8d08f18a Kostas Papadimitriou
        },
577 8d08f18a Kostas Papadimitriou
578 126a01f2 Kostas Papadimitriou
        increase_connecting: function() {
579 126a01f2 Kostas Papadimitriou
            var conn = this.get("connecting");
580 126a01f2 Kostas Papadimitriou
            if (!conn) { conn = 0 };
581 126a01f2 Kostas Papadimitriou
            conn++;
582 126a01f2 Kostas Papadimitriou
            this.set({"connecting": conn});
583 126a01f2 Kostas Papadimitriou
            this.update_state();
584 8d08f18a Kostas Papadimitriou
        },
585 8d08f18a Kostas Papadimitriou
586 126a01f2 Kostas Papadimitriou
        connected_to: function(vm) {
587 126a01f2 Kostas Papadimitriou
            return this.get('linked_to').indexOf(""+vm.id) > -1;
588 8d08f18a Kostas Papadimitriou
        },
589 8d08f18a Kostas Papadimitriou
590 126a01f2 Kostas Papadimitriou
        connected_with_nic_id: function(nic_id) {
591 126a01f2 Kostas Papadimitriou
            return _.keys(this.get('nics')).indexOf(nic_id) > -1;
592 8d08f18a Kostas Papadimitriou
        },
593 126a01f2 Kostas Papadimitriou
594 126a01f2 Kostas Papadimitriou
        get_nics: function(filter) {
595 126a01f2 Kostas Papadimitriou
            var nics = synnefo.storage.nics.filter(function(nic) {
596 126a01f2 Kostas Papadimitriou
                return nic.get('network_id') == this.id;
597 126a01f2 Kostas Papadimitriou
            }, this);
598 126a01f2 Kostas Papadimitriou
599 126a01f2 Kostas Papadimitriou
            if (filter) {
600 126a01f2 Kostas Papadimitriou
                return _.filter(nics, filter);
601 126a01f2 Kostas Papadimitriou
            }
602 126a01f2 Kostas Papadimitriou
            return nics;
603 126a01f2 Kostas Papadimitriou
        },
604 126a01f2 Kostas Papadimitriou
605 126a01f2 Kostas Papadimitriou
        contains_firewalling_nics: function() {
606 126a01f2 Kostas Papadimitriou
            return this.get_nics(function(n){return n.get('pending_firewall')}).length
607 126a01f2 Kostas Papadimitriou
        },
608 126a01f2 Kostas Papadimitriou
609 101e6604 Kostas Papadimitriou
        call: function(action, params, success, error) {
610 101e6604 Kostas Papadimitriou
            if (action == "destroy") {
611 a429705e Kostas Papadimitriou
                var previous_state = this.get('state');
612 a429705e Kostas Papadimitriou
                var previous_status = this.get('status');
613 a429705e Kostas Papadimitriou
614 101e6604 Kostas Papadimitriou
                this.set({state:"DESTROY"});
615 a429705e Kostas Papadimitriou
616 a429705e Kostas Papadimitriou
                var _success = _.bind(function() {
617 a429705e Kostas Papadimitriou
                    if (success) { success() };
618 426e1fb9 Kostas Papadimitriou
                    synnefo.storage.quotas.get('cyclades.network.private').decrease();
619 a429705e Kostas Papadimitriou
                }, this);
620 a429705e Kostas Papadimitriou
                var _error = _.bind(function() {
621 a429705e Kostas Papadimitriou
                    this.set({state: previous_state, status: previous_status})
622 a429705e Kostas Papadimitriou
                    if (error) { error() };
623 a429705e Kostas Papadimitriou
                }, this);
624 a429705e Kostas Papadimitriou
625 a429705e Kostas Papadimitriou
                this.remove(undefined, _error, _success);
626 101e6604 Kostas Papadimitriou
            }
627 101e6604 Kostas Papadimitriou
            
628 101e6604 Kostas Papadimitriou
            if (action == "disconnect") {
629 126a01f2 Kostas Papadimitriou
                if (this.get("state") == "DESTROY") {
630 126a01f2 Kostas Papadimitriou
                    return;
631 126a01f2 Kostas Papadimitriou
                }
632 a429705e Kostas Papadimitriou
                
633 126a01f2 Kostas Papadimitriou
                _.each(params, _.bind(function(nic_id) {
634 126a01f2 Kostas Papadimitriou
                    var nic = snf.storage.nics.get(nic_id);
635 126a01f2 Kostas Papadimitriou
                    this.get("actions").remove("disconnect", nic_id);
636 126a01f2 Kostas Papadimitriou
                    if (nic) {
637 126a01f2 Kostas Papadimitriou
                        this.remove_nic(nic, success, error);
638 101e6604 Kostas Papadimitriou
                    }
639 101e6604 Kostas Papadimitriou
                }, this));
640 101e6604 Kostas Papadimitriou
            }
641 101e6604 Kostas Papadimitriou
        },
642 8d08f18a Kostas Papadimitriou
643 9ce969a7 Kostas Papadimitriou
        add_vm: function (vm, callback, error, options) {
644 9ce969a7 Kostas Papadimitriou
            var payload = {add:{serverRef:"" + vm.id}};
645 9ce969a7 Kostas Papadimitriou
            payload._options = options || {};
646 258235f4 Kostas Papadimitriou
            return this.api_call(this.api_path() + "/action", "create", 
647 9ce969a7 Kostas Papadimitriou
                                 payload,
648 c6f9918c Kostas Papadimitriou
                                 undefined,
649 c6f9918c Kostas Papadimitriou
                                 error,
650 8d08f18a Kostas Papadimitriou
                                 _.bind(function(){
651 126a01f2 Kostas Papadimitriou
                                     //this.vms.add_pending(vm.id);
652 126a01f2 Kostas Papadimitriou
                                     this.increase_connecting();
653 8d08f18a Kostas Papadimitriou
                                     if (callback) {callback()}
654 9ce969a7 Kostas Papadimitriou
                                 },this), error);
655 8d08f18a Kostas Papadimitriou
        },
656 8d08f18a Kostas Papadimitriou
657 126a01f2 Kostas Papadimitriou
        remove_nic: function (nic, callback, error, options) {
658 126a01f2 Kostas Papadimitriou
            var payload = {remove:{attachment:"" + nic.get("attachment_id")}};
659 9ce969a7 Kostas Papadimitriou
            payload._options = options || {};
660 258235f4 Kostas Papadimitriou
            return this.api_call(this.api_path() + "/action", "create", 
661 126a01f2 Kostas Papadimitriou
                                 payload,
662 c6f9918c Kostas Papadimitriou
                                 undefined,
663 c6f9918c Kostas Papadimitriou
                                 error,
664 8d08f18a Kostas Papadimitriou
                                 _.bind(function(){
665 126a01f2 Kostas Papadimitriou
                                     nic.set({"removing": 1});
666 126a01f2 Kostas Papadimitriou
                                     nic.get_network().update_state();
667 126a01f2 Kostas Papadimitriou
                                     //this.vms.add_pending_for_remove(vm.id);
668 8d08f18a Kostas Papadimitriou
                                     if (callback) {callback()}
669 9ce969a7 Kostas Papadimitriou
                                 },this), error);
670 8d08f18a Kostas Papadimitriou
        },
671 8d08f18a Kostas Papadimitriou
672 8d08f18a Kostas Papadimitriou
        rename: function(name, callback) {
673 258235f4 Kostas Papadimitriou
            return this.api_call(this.api_path(), "update", {
674 9ffd10ce Kostas Papadimitriou
                network:{name:name}, 
675 9ffd10ce Kostas Papadimitriou
                _options:{
676 9ffd10ce Kostas Papadimitriou
                    critical: false, 
677 9ffd10ce Kostas Papadimitriou
                    error_params:{
678 9ffd10ce Kostas Papadimitriou
                        title: "Network action failed",
679 9ffd10ce Kostas Papadimitriou
                        ns: "Networks",
680 4dabb5cb Kostas Papadimitriou
                        extra_details: {"Network id": this.id}
681 9ffd10ce Kostas Papadimitriou
                    }
682 9ffd10ce Kostas Papadimitriou
                }}, callback);
683 8d08f18a Kostas Papadimitriou
        },
684 8d08f18a Kostas Papadimitriou
685 8d08f18a Kostas Papadimitriou
        get_connectable_vms: function() {
686 3162bebd Kostas Papadimitriou
            return storage.vms.filter(function(vm){
687 4792afbe Kostas Papadimitriou
                return !vm.in_error_state() && !vm.is_building();
688 3162bebd Kostas Papadimitriou
            })
689 8d08f18a Kostas Papadimitriou
        },
690 8d08f18a Kostas Papadimitriou
691 8d08f18a Kostas Papadimitriou
        state_message: function() {
692 126a01f2 Kostas Papadimitriou
            if (this.get("state") == "ACTIVE" && !this.is_public()) {
693 126a01f2 Kostas Papadimitriou
                if (this.get("cidr") && this.get("dhcp") == true) {
694 126a01f2 Kostas Papadimitriou
                    return this.get("cidr");
695 126a01f2 Kostas Papadimitriou
                } else {
696 126a01f2 Kostas Papadimitriou
                    return "Private network";
697 126a01f2 Kostas Papadimitriou
                }
698 126a01f2 Kostas Papadimitriou
            }
699 126a01f2 Kostas Papadimitriou
            if (this.get("state") == "ACTIVE" && this.is_public()) {
700 126a01f2 Kostas Papadimitriou
                  return "Public network";
701 8d08f18a Kostas Papadimitriou
            }
702 8d08f18a Kostas Papadimitriou
703 8d08f18a Kostas Papadimitriou
            return models.Network.STATES[this.get("state")];
704 8d08f18a Kostas Papadimitriou
        },
705 8d08f18a Kostas Papadimitriou
706 8d08f18a Kostas Papadimitriou
        in_progress: function() {
707 8d08f18a Kostas Papadimitriou
            return models.Network.STATES_TRANSITIONS[this.get("state")] != undefined;
708 101e6604 Kostas Papadimitriou
        },
709 101e6604 Kostas Papadimitriou
710 101e6604 Kostas Papadimitriou
        do_all_pending_actions: function(success, error) {
711 a429705e Kostas Papadimitriou
          var params, actions, action_params;
712 a429705e Kostas Papadimitriou
          actions = _.clone(this.get("actions").actions);
713 a429705e Kostas Papadimitriou
            _.each(actions, _.bind(function(params, action) {
714 a429705e Kostas Papadimitriou
                action_params = _.map(actions[action], function(a){ return _.clone(a)});
715 a429705e Kostas Papadimitriou
                _.each(action_params, _.bind(function(params) {
716 a429705e Kostas Papadimitriou
                    this.call(action, params, success, error);
717 101e6604 Kostas Papadimitriou
                }, this));
718 101e6604 Kostas Papadimitriou
            }, this));
719 126a01f2 Kostas Papadimitriou
            this.get("actions").reset();
720 8d08f18a Kostas Papadimitriou
        }
721 8d08f18a Kostas Papadimitriou
    });
722 8d08f18a Kostas Papadimitriou
    
723 8d08f18a Kostas Papadimitriou
    models.Network.STATES = {
724 126a01f2 Kostas Papadimitriou
        'ACTIVE': 'Private network',
725 8d08f18a Kostas Papadimitriou
        'CONNECTING': 'Connecting...',
726 8d08f18a Kostas Papadimitriou
        'DISCONNECTING': 'Disconnecting...',
727 25b225a5 Kostas Papadimitriou
        'FIREWALLING': 'Firewall update...',
728 126a01f2 Kostas Papadimitriou
        'DESTROY': 'Destroying...',
729 126a01f2 Kostas Papadimitriou
        'PENDING': 'Pending...',
730 126a01f2 Kostas Papadimitriou
        'ERROR': 'Error'
731 8d08f18a Kostas Papadimitriou
    }
732 8d08f18a Kostas Papadimitriou
733 8d08f18a Kostas Papadimitriou
    models.Network.STATES_TRANSITIONS = {
734 126a01f2 Kostas Papadimitriou
        'CONNECTING': ['ACTIVE'],
735 126a01f2 Kostas Papadimitriou
        'DISCONNECTING': ['ACTIVE'],
736 126a01f2 Kostas Papadimitriou
        'PENDING': ['ACTIVE'],
737 126a01f2 Kostas Papadimitriou
        'FIREWALLING': ['ACTIVE']
738 8d08f18a Kostas Papadimitriou
    }
739 8d08f18a Kostas Papadimitriou
740 8d08f18a Kostas Papadimitriou
    // Virtualmachine model
741 8d08f18a Kostas Papadimitriou
    models.VM = models.Model.extend({
742 8d08f18a Kostas Papadimitriou
743 8d08f18a Kostas Papadimitriou
        path: 'servers',
744 8d08f18a Kostas Papadimitriou
        has_status: true,
745 8d08f18a Kostas Papadimitriou
        initialize: function(params) {
746 8d08f18a Kostas Papadimitriou
            
747 8d08f18a Kostas Papadimitriou
            this.pending_firewalls = {};
748 8d08f18a Kostas Papadimitriou
            
749 8d08f18a Kostas Papadimitriou
            models.VM.__super__.initialize.apply(this, arguments);
750 8d08f18a Kostas Papadimitriou
751 8d08f18a Kostas Papadimitriou
            this.set({state: params.status || "ERROR"});
752 8d08f18a Kostas Papadimitriou
            this.log = new snf.logging.logger("VM " + this.id);
753 8d08f18a Kostas Papadimitriou
            this.pending_action = undefined;
754 8d08f18a Kostas Papadimitriou
            
755 8d08f18a Kostas Papadimitriou
            // init stats parameter
756 8d08f18a Kostas Papadimitriou
            this.set({'stats': undefined}, {silent: true});
757 8d08f18a Kostas Papadimitriou
            // defaults to not update the stats
758 8d08f18a Kostas Papadimitriou
            // each view should handle this vm attribute 
759 8d08f18a Kostas Papadimitriou
            // depending on if it displays stat images or not
760 8d08f18a Kostas Papadimitriou
            this.do_update_stats = false;
761 8d08f18a Kostas Papadimitriou
            
762 8d08f18a Kostas Papadimitriou
            // interval time
763 8d08f18a Kostas Papadimitriou
            // this will dynamicaly change if the server responds that
764 8d08f18a Kostas Papadimitriou
            // images get refreshed on different intervals
765 8d08f18a Kostas Papadimitriou
            this.stats_update_interval = synnefo.config.STATS_INTERVAL || 5000;
766 96d725ac Kostas Papadimitriou
            this.stats_available = false;
767 8d08f18a Kostas Papadimitriou
768 8d08f18a Kostas Papadimitriou
            // initialize interval
769 8d08f18a Kostas Papadimitriou
            this.init_stats_intervals(this.stats_update_interval);
770 8d08f18a Kostas Papadimitriou
            
771 1e882dd7 Kostas Papadimitriou
            // handle progress message on instance change
772 1e882dd7 Kostas Papadimitriou
            this.bind("change", _.bind(this.update_status_message, this));
773 1e882dd7 Kostas Papadimitriou
            // force update of progress message
774 1e882dd7 Kostas Papadimitriou
            this.update_status_message(true);
775 1e882dd7 Kostas Papadimitriou
            
776 8d08f18a Kostas Papadimitriou
            // default values
777 126a01f2 Kostas Papadimitriou
            this.bind("change:state", _.bind(function(){
778 126a01f2 Kostas Papadimitriou
                if (this.state() == "DESTROY") { 
779 126a01f2 Kostas Papadimitriou
                    this.handle_destroy() 
780 126a01f2 Kostas Papadimitriou
                }
781 126a01f2 Kostas Papadimitriou
            }, this));
782 8d08f18a Kostas Papadimitriou
783 126a01f2 Kostas Papadimitriou
            this.bind("change:nics", _.bind(synnefo.storage.nics.update_vm_nics, synnefo.storage.nics));
784 8d08f18a Kostas Papadimitriou
        },
785 8d08f18a Kostas Papadimitriou
786 8d08f18a Kostas Papadimitriou
        status: function(st) {
787 8d08f18a Kostas Papadimitriou
            if (!st) { return this.get("status")}
788 8d08f18a Kostas Papadimitriou
            return this.set({status:st});
789 8d08f18a Kostas Papadimitriou
        },
790 8d08f18a Kostas Papadimitriou
791 8d08f18a Kostas Papadimitriou
        set_status: function(st) {
792 8d08f18a Kostas Papadimitriou
            var new_state = this.state_for_api_status(st);
793 8d08f18a Kostas Papadimitriou
            var transition = false;
794 8d08f18a Kostas Papadimitriou
795 8d08f18a Kostas Papadimitriou
            if (this.state() != new_state) {
796 8d08f18a Kostas Papadimitriou
                if (models.VM.STATES_TRANSITIONS[this.state()]) {
797 8d08f18a Kostas Papadimitriou
                    transition = this.state();
798 8d08f18a Kostas Papadimitriou
                }
799 8d08f18a Kostas Papadimitriou
            }
800 8d08f18a Kostas Papadimitriou
            
801 8d08f18a Kostas Papadimitriou
            // call it silently to avoid double change trigger
802 8d08f18a Kostas Papadimitriou
            this.set({'state': this.state_for_api_status(st)}, {silent: true});
803 8d08f18a Kostas Papadimitriou
            
804 8d08f18a Kostas Papadimitriou
            // trigger transition
805 572dbe3d Kostas Papadimitriou
            if (transition && models.VM.TRANSITION_STATES.indexOf(new_state) == -1) { 
806 572dbe3d Kostas Papadimitriou
                this.trigger("transition", {from:transition, to:new_state}) 
807 572dbe3d Kostas Papadimitriou
            };
808 8d08f18a Kostas Papadimitriou
            return st;
809 8d08f18a Kostas Papadimitriou
        },
810 1e882dd7 Kostas Papadimitriou
            
811 1e882dd7 Kostas Papadimitriou
        get_diagnostics: function(success) {
812 1e882dd7 Kostas Papadimitriou
            this.__make_api_call(this.get_diagnostics_url(),
813 1e882dd7 Kostas Papadimitriou
                                 "read", // create so that sync later uses POST to make the call
814 1e882dd7 Kostas Papadimitriou
                                 null, // payload
815 1e882dd7 Kostas Papadimitriou
                                 function(data) {
816 1e882dd7 Kostas Papadimitriou
                                     success(data);
817 1e882dd7 Kostas Papadimitriou
                                 },  
818 1e882dd7 Kostas Papadimitriou
                                 null, 'diagnostics');
819 1e882dd7 Kostas Papadimitriou
        },
820 8d08f18a Kostas Papadimitriou
821 1e882dd7 Kostas Papadimitriou
        has_diagnostics: function() {
822 1e882dd7 Kostas Papadimitriou
            return this.get("diagnostics") && this.get("diagnostics").length;
823 1e882dd7 Kostas Papadimitriou
        },
824 1e882dd7 Kostas Papadimitriou
825 1e882dd7 Kostas Papadimitriou
        get_progress_info: function() {
826 1e882dd7 Kostas Papadimitriou
            // details about progress message
827 1e882dd7 Kostas Papadimitriou
            // contains a list of diagnostic messages
828 1e882dd7 Kostas Papadimitriou
            return this.get("status_messages");
829 1e882dd7 Kostas Papadimitriou
        },
830 1e882dd7 Kostas Papadimitriou
831 1e882dd7 Kostas Papadimitriou
        get_status_message: function() {
832 1e882dd7 Kostas Papadimitriou
            return this.get('status_message');
833 1e882dd7 Kostas Papadimitriou
        },
834 1e882dd7 Kostas Papadimitriou
        
835 1e882dd7 Kostas Papadimitriou
        // extract status message from diagnostics
836 1e882dd7 Kostas Papadimitriou
        status_message_from_diagnostics: function(diagnostics) {
837 1e882dd7 Kostas Papadimitriou
            var valid_sources_map = synnefo.config.diagnostics_status_messages_map;
838 1e882dd7 Kostas Papadimitriou
            var valid_sources = valid_sources_map[this.get('status')];
839 1e882dd7 Kostas Papadimitriou
            if (!valid_sources) { return null };
840 1e882dd7 Kostas Papadimitriou
            
841 1e882dd7 Kostas Papadimitriou
            // filter messsages based on diagnostic source
842 1e882dd7 Kostas Papadimitriou
            var messages = _.filter(diagnostics, function(diag) {
843 1e882dd7 Kostas Papadimitriou
                return valid_sources.indexOf(diag.source) > -1;
844 1e882dd7 Kostas Papadimitriou
            });
845 1e882dd7 Kostas Papadimitriou
846 1e882dd7 Kostas Papadimitriou
            var msg = messages[0];
847 1e882dd7 Kostas Papadimitriou
            if (msg) {
848 1e882dd7 Kostas Papadimitriou
              var message = msg.message;
849 1e882dd7 Kostas Papadimitriou
              var message_tpl = snf.config.diagnostic_messages_tpls[msg.source];
850 1e882dd7 Kostas Papadimitriou
851 1e882dd7 Kostas Papadimitriou
              if (message_tpl) {
852 1e882dd7 Kostas Papadimitriou
                  message = message_tpl.replace('MESSAGE', msg.message);
853 1e882dd7 Kostas Papadimitriou
              }
854 1e882dd7 Kostas Papadimitriou
              return message;
855 1e882dd7 Kostas Papadimitriou
            }
856 1e882dd7 Kostas Papadimitriou
            
857 1e882dd7 Kostas Papadimitriou
            // no message to display, but vm in build state, display
858 1e882dd7 Kostas Papadimitriou
            // finalizing message.
859 1e882dd7 Kostas Papadimitriou
            if (this.is_building() == 'BUILD') {
860 1e882dd7 Kostas Papadimitriou
                return synnefo.config.BUILDING_MESSAGES['FINAL'];
861 1e882dd7 Kostas Papadimitriou
            }
862 1e882dd7 Kostas Papadimitriou
            return null;
863 1e882dd7 Kostas Papadimitriou
        },
864 1e882dd7 Kostas Papadimitriou
865 1e882dd7 Kostas Papadimitriou
        update_status_message: function(force) {
866 1e882dd7 Kostas Papadimitriou
            // update only if one of the specified attributes has changed
867 1e882dd7 Kostas Papadimitriou
            if (
868 1e882dd7 Kostas Papadimitriou
              !this.keysChanged(['diagnostics', 'progress', 'status', 'state'])
869 1e882dd7 Kostas Papadimitriou
                && !force
870 1e882dd7 Kostas Papadimitriou
            ) { return };
871 1e882dd7 Kostas Papadimitriou
            
872 1e882dd7 Kostas Papadimitriou
            // if user requested to destroy the vm set the appropriate 
873 1e882dd7 Kostas Papadimitriou
            // message.
874 1e882dd7 Kostas Papadimitriou
            if (this.get('state') == "DESTROY") { 
875 1e882dd7 Kostas Papadimitriou
                message = "Terminating..."
876 1e882dd7 Kostas Papadimitriou
                this.set({status_message: message})
877 1e882dd7 Kostas Papadimitriou
                return;
878 1e882dd7 Kostas Papadimitriou
            }
879 1e882dd7 Kostas Papadimitriou
            
880 1e882dd7 Kostas Papadimitriou
            // set error message, if vm has diagnostic message display it as
881 1e882dd7 Kostas Papadimitriou
            // progress message
882 1e882dd7 Kostas Papadimitriou
            if (this.in_error_state()) {
883 1e882dd7 Kostas Papadimitriou
                var d = this.get('diagnostics');
884 1e882dd7 Kostas Papadimitriou
                if (d && d.length) {
885 1e882dd7 Kostas Papadimitriou
                    var message = this.status_message_from_diagnostics(d);
886 1e882dd7 Kostas Papadimitriou
                    this.set({status_message: message});
887 1e882dd7 Kostas Papadimitriou
                } else {
888 1e882dd7 Kostas Papadimitriou
                    this.set({status_message: null});
889 8d08f18a Kostas Papadimitriou
                }
890 1e882dd7 Kostas Papadimitriou
                return;
891 1e882dd7 Kostas Papadimitriou
            }
892 1e882dd7 Kostas Papadimitriou
            
893 1e882dd7 Kostas Papadimitriou
            // identify building status message
894 1e882dd7 Kostas Papadimitriou
            if (this.is_building()) {
895 1e882dd7 Kostas Papadimitriou
                var self = this;
896 1e882dd7 Kostas Papadimitriou
                var success = function(msg) {
897 1e882dd7 Kostas Papadimitriou
                    self.set({status_message: msg});
898 8d08f18a Kostas Papadimitriou
                }
899 1e882dd7 Kostas Papadimitriou
                this.get_building_status_message(success);
900 1e882dd7 Kostas Papadimitriou
                return;
901 1e882dd7 Kostas Papadimitriou
            }
902 1e882dd7 Kostas Papadimitriou
903 1e882dd7 Kostas Papadimitriou
            this.set({status_message:null});
904 1e882dd7 Kostas Papadimitriou
        },
905 1e882dd7 Kostas Papadimitriou
            
906 1e882dd7 Kostas Papadimitriou
        // get building status message. Asynchronous function since it requires
907 1e882dd7 Kostas Papadimitriou
        // access to vm image.
908 1e882dd7 Kostas Papadimitriou
        get_building_status_message: function(callback) {
909 1e882dd7 Kostas Papadimitriou
            // no progress is set, vm is in initial build status
910 1e882dd7 Kostas Papadimitriou
            var progress = this.get("progress");
911 1e882dd7 Kostas Papadimitriou
            if (progress == 0 || !progress) {
912 1e882dd7 Kostas Papadimitriou
                return callback(BUILDING_MESSAGES['INIT']);
913 1e882dd7 Kostas Papadimitriou
            }
914 1e882dd7 Kostas Papadimitriou
            
915 1e882dd7 Kostas Papadimitriou
            // vm has copy progress, display copy percentage
916 1e882dd7 Kostas Papadimitriou
            if (progress > 0 && progress <= 99) {
917 1e882dd7 Kostas Papadimitriou
                this.get_copy_details(true, undefined, _.bind(
918 1e882dd7 Kostas Papadimitriou
                    function(details){
919 1e882dd7 Kostas Papadimitriou
                        callback(BUILDING_MESSAGES['COPY'].format(details.copy, 
920 1e882dd7 Kostas Papadimitriou
                                                           details.size, 
921 1e882dd7 Kostas Papadimitriou
                                                           details.progress));
922 1e882dd7 Kostas Papadimitriou
                }, this));
923 1e882dd7 Kostas Papadimitriou
                return;
924 1e882dd7 Kostas Papadimitriou
            }
925 1e882dd7 Kostas Papadimitriou
926 1e882dd7 Kostas Papadimitriou
            // copy finished display FINAL message or identify status message
927 1e882dd7 Kostas Papadimitriou
            // from diagnostics.
928 1e882dd7 Kostas Papadimitriou
            if (progress >= 100) {
929 1e882dd7 Kostas Papadimitriou
                if (!this.has_diagnostics()) {
930 1e882dd7 Kostas Papadimitriou
                        callback(BUILDING_MESSAGES['FINAL']);
931 1e882dd7 Kostas Papadimitriou
                } else {
932 1e882dd7 Kostas Papadimitriou
                        var d = this.get("diagnostics");
933 1e882dd7 Kostas Papadimitriou
                        var msg = this.status_message_from_diagnostics(d);
934 1e882dd7 Kostas Papadimitriou
                        if (msg) {
935 1e882dd7 Kostas Papadimitriou
                              callback(msg);
936 1e882dd7 Kostas Papadimitriou
                        }
937 8d08f18a Kostas Papadimitriou
                }
938 8d08f18a Kostas Papadimitriou
            }
939 8d08f18a Kostas Papadimitriou
        },
940 8d08f18a Kostas Papadimitriou
941 c45bed88 Kostas Papadimitriou
        get_copy_details: function(human, image, callback) {
942 8d08f18a Kostas Papadimitriou
            var human = human || false;
943 c45bed88 Kostas Papadimitriou
            var image = image || this.get_image(_.bind(function(image){
944 c45bed88 Kostas Papadimitriou
                var progress = this.get('progress');
945 c45bed88 Kostas Papadimitriou
                var size = image.get_size();
946 c45bed88 Kostas Papadimitriou
                var size_copied = (size * progress / 100).toFixed(2);
947 c45bed88 Kostas Papadimitriou
                
948 c45bed88 Kostas Papadimitriou
                if (human) {
949 c45bed88 Kostas Papadimitriou
                    size = util.readablizeBytes(size*1024*1024);
950 c45bed88 Kostas Papadimitriou
                    size_copied = util.readablizeBytes(size_copied*1024*1024);
951 c45bed88 Kostas Papadimitriou
                }
952 8d08f18a Kostas Papadimitriou
953 c45bed88 Kostas Papadimitriou
                callback({'progress': progress, 'size': size, 'copy': size_copied})
954 c45bed88 Kostas Papadimitriou
            }, this));
955 8d08f18a Kostas Papadimitriou
        },
956 8d08f18a Kostas Papadimitriou
957 1f7ea2f5 Kostas Papadimitriou
        start_stats_update: function(force_if_empty) {
958 2c9bfad1 Kostas Papadimitriou
            var prev_state = this.do_update_stats;
959 2c9bfad1 Kostas Papadimitriou
960 2c9bfad1 Kostas Papadimitriou
            this.do_update_stats = true;
961 1f7ea2f5 Kostas Papadimitriou
            
962 2c9bfad1 Kostas Papadimitriou
            // fetcher initialized ??
963 2c9bfad1 Kostas Papadimitriou
            if (!this.stats_fetcher) {
964 2c9bfad1 Kostas Papadimitriou
                this.init_stats_intervals();
965 2c9bfad1 Kostas Papadimitriou
            }
966 2c9bfad1 Kostas Papadimitriou
967 1f7ea2f5 Kostas Papadimitriou
968 2c9bfad1 Kostas Papadimitriou
            // fetcher running ???
969 2c9bfad1 Kostas Papadimitriou
            if (!this.stats_fetcher.running || !prev_state) {
970 2c9bfad1 Kostas Papadimitriou
                this.stats_fetcher.start();
971 2c9bfad1 Kostas Papadimitriou
            }
972 1f7ea2f5 Kostas Papadimitriou
973 1f7ea2f5 Kostas Papadimitriou
            if (force_if_empty && this.get("stats") == undefined) {
974 1f7ea2f5 Kostas Papadimitriou
                this.update_stats(true);
975 1f7ea2f5 Kostas Papadimitriou
            }
976 2c9bfad1 Kostas Papadimitriou
        },
977 2c9bfad1 Kostas Papadimitriou
978 2c9bfad1 Kostas Papadimitriou
        stop_stats_update: function(stop_calls) {
979 2c9bfad1 Kostas Papadimitriou
            this.do_update_stats = false;
980 2c9bfad1 Kostas Papadimitriou
981 2c9bfad1 Kostas Papadimitriou
            if (stop_calls) {
982 2c9bfad1 Kostas Papadimitriou
                this.stats_fetcher.stop();
983 2c9bfad1 Kostas Papadimitriou
            }
984 2c9bfad1 Kostas Papadimitriou
        },
985 2c9bfad1 Kostas Papadimitriou
986 8d08f18a Kostas Papadimitriou
        // clear and reinitialize update interval
987 8d08f18a Kostas Papadimitriou
        init_stats_intervals: function (interval) {
988 96d725ac Kostas Papadimitriou
            this.stats_fetcher = this.get_stats_fetcher(this.stats_update_interval);
989 96d725ac Kostas Papadimitriou
            this.stats_fetcher.start();
990 8d08f18a Kostas Papadimitriou
        },
991 8d08f18a Kostas Papadimitriou
        
992 96d725ac Kostas Papadimitriou
        get_stats_fetcher: function(timeout) {
993 96d725ac Kostas Papadimitriou
            var cb = _.bind(function(data){
994 96d725ac Kostas Papadimitriou
                this.update_stats();
995 96d725ac Kostas Papadimitriou
            }, this);
996 258235f4 Kostas Papadimitriou
            var fetcher = new snf.api.updateHandler({'callback': cb, interval: timeout, id:'stats'});
997 96d725ac Kostas Papadimitriou
            return fetcher;
998 96d725ac Kostas Papadimitriou
        },
999 96d725ac Kostas Papadimitriou
1000 8d08f18a Kostas Papadimitriou
        // do the api call
1001 8d08f18a Kostas Papadimitriou
        update_stats: function(force) {
1002 8d08f18a Kostas Papadimitriou
            // do not update stats if flag not set
1003 1f7ea2f5 Kostas Papadimitriou
            if ((!this.do_update_stats && !force) || this.updating_stats) {
1004 8d08f18a Kostas Papadimitriou
                return;
1005 8d08f18a Kostas Papadimitriou
            }
1006 96d725ac Kostas Papadimitriou
1007 8d08f18a Kostas Papadimitriou
            // make the api call, execute handle_stats_update on sucess
1008 8d08f18a Kostas Papadimitriou
            // TODO: onError handler ???
1009 8d08f18a Kostas Papadimitriou
            stats_url = this.url() + "/stats";
1010 1f7ea2f5 Kostas Papadimitriou
            this.updating_stats = true;
1011 258235f4 Kostas Papadimitriou
            this.sync("read", this, {
1012 96d725ac Kostas Papadimitriou
                handles_error:true, 
1013 96d725ac Kostas Papadimitriou
                url: stats_url, 
1014 96d725ac Kostas Papadimitriou
                refresh:true, 
1015 96d725ac Kostas Papadimitriou
                success: _.bind(this.handle_stats_update, this),
1016 ec511098 Kostas Papadimitriou
                error: _.bind(this.handle_stats_error, this),
1017 1f7ea2f5 Kostas Papadimitriou
                complete: _.bind(function(){this.updating_stats = false;}, this),
1018 ec511098 Kostas Papadimitriou
                critical: false,
1019 0375f6c5 Kostas Papadimitriou
                log_error: false,
1020 0375f6c5 Kostas Papadimitriou
                skips_timeouts: true
1021 96d725ac Kostas Papadimitriou
            });
1022 96d725ac Kostas Papadimitriou
        },
1023 96d725ac Kostas Papadimitriou
1024 96d725ac Kostas Papadimitriou
        get_stats_image: function(stat, type) {
1025 8d08f18a Kostas Papadimitriou
        },
1026 8d08f18a Kostas Papadimitriou
        
1027 96d725ac Kostas Papadimitriou
        _set_stats: function(stats) {
1028 96d725ac Kostas Papadimitriou
            var silent = silent === undefined ? false : silent;
1029 96d725ac Kostas Papadimitriou
            // unavailable stats while building
1030 96d725ac Kostas Papadimitriou
            if (this.get("status") == "BUILD") { 
1031 96d725ac Kostas Papadimitriou
                this.stats_available = false;
1032 96d725ac Kostas Papadimitriou
            } else { this.stats_available = true; }
1033 96d725ac Kostas Papadimitriou
1034 96d725ac Kostas Papadimitriou
            if (this.get("status") == "DESTROY") { this.stats_available = false; }
1035 96d725ac Kostas Papadimitriou
            
1036 96d725ac Kostas Papadimitriou
            this.set({stats: stats}, {silent:true});
1037 96d725ac Kostas Papadimitriou
            this.trigger("stats:update", stats);
1038 96d725ac Kostas Papadimitriou
        },
1039 96d725ac Kostas Papadimitriou
1040 96d725ac Kostas Papadimitriou
        unbind: function() {
1041 96d725ac Kostas Papadimitriou
            models.VM.__super__.unbind.apply(this, arguments);
1042 96d725ac Kostas Papadimitriou
        },
1043 96d725ac Kostas Papadimitriou
1044 96d725ac Kostas Papadimitriou
        handle_stats_error: function() {
1045 96d725ac Kostas Papadimitriou
            stats = {};
1046 96d725ac Kostas Papadimitriou
            _.each(['cpuBar', 'cpuTimeSeries', 'netBar', 'netTimeSeries'], function(k) {
1047 96d725ac Kostas Papadimitriou
                stats[k] = false;
1048 96d725ac Kostas Papadimitriou
            });
1049 96d725ac Kostas Papadimitriou
1050 96d725ac Kostas Papadimitriou
            this.set({'stats': stats});
1051 96d725ac Kostas Papadimitriou
        },
1052 96d725ac Kostas Papadimitriou
1053 8d08f18a Kostas Papadimitriou
        // this method gets executed after a successful vm stats api call
1054 8d08f18a Kostas Papadimitriou
        handle_stats_update: function(data) {
1055 96d725ac Kostas Papadimitriou
            var self = this;
1056 8d08f18a Kostas Papadimitriou
            // avoid browser caching
1057 96d725ac Kostas Papadimitriou
            
1058 8d08f18a Kostas Papadimitriou
            if (data.stats && _.size(data.stats) > 0) {
1059 8d08f18a Kostas Papadimitriou
                var ts = $.now();
1060 8d08f18a Kostas Papadimitriou
                var stats = data.stats;
1061 96d725ac Kostas Papadimitriou
                var images_loaded = 0;
1062 96d725ac Kostas Papadimitriou
                var images = {};
1063 96d725ac Kostas Papadimitriou
1064 96d725ac Kostas Papadimitriou
                function check_images_loaded() {
1065 96d725ac Kostas Papadimitriou
                    images_loaded++;
1066 96d725ac Kostas Papadimitriou
1067 96d725ac Kostas Papadimitriou
                    if (images_loaded == 4) {
1068 96d725ac Kostas Papadimitriou
                        self._set_stats(images);
1069 96d725ac Kostas Papadimitriou
                    }
1070 96d725ac Kostas Papadimitriou
                }
1071 8d08f18a Kostas Papadimitriou
                _.each(['cpuBar', 'cpuTimeSeries', 'netBar', 'netTimeSeries'], function(k) {
1072 96d725ac Kostas Papadimitriou
                    
1073 8d08f18a Kostas Papadimitriou
                    stats[k] = stats[k] + "?_=" + ts;
1074 96d725ac Kostas Papadimitriou
                    
1075 96d725ac Kostas Papadimitriou
                    var stat = k.slice(0,3);
1076 96d725ac Kostas Papadimitriou
                    var type = k.slice(3,6) == "Bar" ? "bar" : "time";
1077 96d725ac Kostas Papadimitriou
                    var img = $("<img />");
1078 96d725ac Kostas Papadimitriou
                    var val = stats[k];
1079 96d725ac Kostas Papadimitriou
                    
1080 96d725ac Kostas Papadimitriou
                    // load stat image to a temporary dom element
1081 96d725ac Kostas Papadimitriou
                    // update model stats on image load/error events
1082 96d725ac Kostas Papadimitriou
                    img.load(function() {
1083 96d725ac Kostas Papadimitriou
                        images[k] = val;
1084 96d725ac Kostas Papadimitriou
                        check_images_loaded();
1085 96d725ac Kostas Papadimitriou
                    });
1086 96d725ac Kostas Papadimitriou
1087 96d725ac Kostas Papadimitriou
                    img.error(function() {
1088 96d725ac Kostas Papadimitriou
                        images[stat + type] = false;
1089 96d725ac Kostas Papadimitriou
                        check_images_loaded();
1090 96d725ac Kostas Papadimitriou
                    });
1091 96d725ac Kostas Papadimitriou
1092 96d725ac Kostas Papadimitriou
                    img.attr({'src': stats[k]});
1093 8d08f18a Kostas Papadimitriou
                })
1094 8d08f18a Kostas Papadimitriou
                data.stats = stats;
1095 8d08f18a Kostas Papadimitriou
            }
1096 96d725ac Kostas Papadimitriou
1097 8d08f18a Kostas Papadimitriou
            // do we need to change the interval ??
1098 8d08f18a Kostas Papadimitriou
            if (data.stats.refresh * 1000 != this.stats_update_interval) {
1099 8d08f18a Kostas Papadimitriou
                this.stats_update_interval = data.stats.refresh * 1000;
1100 1cc6e94f Kostas Papadimitriou
                this.stats_fetcher.interval = this.stats_update_interval;
1101 1cc6e94f Kostas Papadimitriou
                this.stats_fetcher.maximum_interval = this.stats_update_interval;
1102 96d725ac Kostas Papadimitriou
                this.stats_fetcher.stop();
1103 2c9bfad1 Kostas Papadimitriou
                this.stats_fetcher.start(false);
1104 8d08f18a Kostas Papadimitriou
            }
1105 8d08f18a Kostas Papadimitriou
        },
1106 96d725ac Kostas Papadimitriou
1107 8d08f18a Kostas Papadimitriou
        // helper method that sets the do_update_stats
1108 8d08f18a Kostas Papadimitriou
        // in the future this method could also make an api call
1109 8d08f18a Kostas Papadimitriou
        // immediaetly if needed
1110 8d08f18a Kostas Papadimitriou
        enable_stats_update: function() {
1111 8d08f18a Kostas Papadimitriou
            this.do_update_stats = true;
1112 8d08f18a Kostas Papadimitriou
        },
1113 96d725ac Kostas Papadimitriou
        
1114 96d725ac Kostas Papadimitriou
        handle_destroy: function() {
1115 96d725ac Kostas Papadimitriou
            this.stats_fetcher.stop();
1116 96d725ac Kostas Papadimitriou
        },
1117 122850c5 Kostas Papadimitriou
1118 122850c5 Kostas Papadimitriou
        require_reboot: function() {
1119 122850c5 Kostas Papadimitriou
            if (this.is_active()) {
1120 122850c5 Kostas Papadimitriou
                this.set({'reboot_required': true});
1121 122850c5 Kostas Papadimitriou
            }
1122 122850c5 Kostas Papadimitriou
        },
1123 8d08f18a Kostas Papadimitriou
        
1124 8d08f18a Kostas Papadimitriou
        set_pending_action: function(data) {
1125 8d08f18a Kostas Papadimitriou
            this.pending_action = data;
1126 8d08f18a Kostas Papadimitriou
            return data;
1127 8d08f18a Kostas Papadimitriou
        },
1128 8d08f18a Kostas Papadimitriou
1129 8d08f18a Kostas Papadimitriou
        // machine has pending action
1130 8d08f18a Kostas Papadimitriou
        update_pending_action: function(action, force) {
1131 8d08f18a Kostas Papadimitriou
            this.set({pending_action: action});
1132 8d08f18a Kostas Papadimitriou
        },
1133 8d08f18a Kostas Papadimitriou
1134 8d08f18a Kostas Papadimitriou
        clear_pending_action: function() {
1135 8d08f18a Kostas Papadimitriou
            this.set({pending_action: undefined});
1136 8d08f18a Kostas Papadimitriou
        },
1137 8d08f18a Kostas Papadimitriou
1138 8d08f18a Kostas Papadimitriou
        has_pending_action: function() {
1139 8d08f18a Kostas Papadimitriou
            return this.get("pending_action") ? this.get("pending_action") : false;
1140 8d08f18a Kostas Papadimitriou
        },
1141 8d08f18a Kostas Papadimitriou
        
1142 8d08f18a Kostas Papadimitriou
        // machine is active
1143 8d08f18a Kostas Papadimitriou
        is_active: function() {
1144 8d08f18a Kostas Papadimitriou
            return models.VM.ACTIVE_STATES.indexOf(this.state()) > -1;
1145 8d08f18a Kostas Papadimitriou
        },
1146 8d08f18a Kostas Papadimitriou
        
1147 122850c5 Kostas Papadimitriou
        // machine is building 
1148 8d08f18a Kostas Papadimitriou
        is_building: function() {
1149 8d08f18a Kostas Papadimitriou
            return models.VM.BUILDING_STATES.indexOf(this.state()) > -1;
1150 8d08f18a Kostas Papadimitriou
        },
1151 3162bebd Kostas Papadimitriou
        
1152 3162bebd Kostas Papadimitriou
        in_error_state: function() {
1153 3162bebd Kostas Papadimitriou
            return this.state() === "ERROR"
1154 3162bebd Kostas Papadimitriou
        },
1155 8d08f18a Kostas Papadimitriou
1156 8d08f18a Kostas Papadimitriou
        // user can connect to machine
1157 8d08f18a Kostas Papadimitriou
        is_connectable: function() {
1158 8d08f18a Kostas Papadimitriou
            // check if ips exist
1159 8d08f18a Kostas Papadimitriou
            if (!this.get_addresses().ip4 && !this.get_addresses().ip6) {
1160 8d08f18a Kostas Papadimitriou
                return false;
1161 8d08f18a Kostas Papadimitriou
            }
1162 8d08f18a Kostas Papadimitriou
            return models.VM.CONNECT_STATES.indexOf(this.state()) > -1;
1163 8d08f18a Kostas Papadimitriou
        },
1164 8d08f18a Kostas Papadimitriou
        
1165 8d08f18a Kostas Papadimitriou
        remove_meta: function(key, complete, error) {
1166 8d08f18a Kostas Papadimitriou
            var url = this.api_path() + "/meta/" + key;
1167 258235f4 Kostas Papadimitriou
            this.api_call(url, "delete", undefined, complete, error);
1168 8d08f18a Kostas Papadimitriou
        },
1169 8d08f18a Kostas Papadimitriou
1170 8d08f18a Kostas Papadimitriou
        save_meta: function(meta, complete, error) {
1171 8d08f18a Kostas Papadimitriou
            var url = this.api_path() + "/meta/" + meta.key;
1172 8d08f18a Kostas Papadimitriou
            var payload = {meta:{}};
1173 8d08f18a Kostas Papadimitriou
            payload.meta[meta.key] = meta.value;
1174 9ffd10ce Kostas Papadimitriou
            payload._options = {
1175 9ffd10ce Kostas Papadimitriou
                critical:false, 
1176 9ffd10ce Kostas Papadimitriou
                error_params: {
1177 9ffd10ce Kostas Papadimitriou
                    title: "Machine metadata error",
1178 9ffd10ce Kostas Papadimitriou
                    extra_details: {"Machine id": this.id}
1179 9ffd10ce Kostas Papadimitriou
            }};
1180 8d08f18a Kostas Papadimitriou
1181 258235f4 Kostas Papadimitriou
            this.api_call(url, "update", payload, complete, error);
1182 8d08f18a Kostas Papadimitriou
        },
1183 8d08f18a Kostas Papadimitriou
1184 8d08f18a Kostas Papadimitriou
1185 8d08f18a Kostas Papadimitriou
        // update/get the state of the machine
1186 8d08f18a Kostas Papadimitriou
        state: function() {
1187 8d08f18a Kostas Papadimitriou
            var args = slice.call(arguments);
1188 8d08f18a Kostas Papadimitriou
                
1189 643de8c0 Kostas Papadimitriou
            // TODO: it might not be a good idea to set the state in set_state method
1190 8d08f18a Kostas Papadimitriou
            if (args.length > 0 && models.VM.STATES.indexOf(args[0]) > -1) {
1191 8d08f18a Kostas Papadimitriou
                this.set({'state': args[0]});
1192 8d08f18a Kostas Papadimitriou
            }
1193 8d08f18a Kostas Papadimitriou
1194 8d08f18a Kostas Papadimitriou
            return this.get('state');
1195 8d08f18a Kostas Papadimitriou
        },
1196 8d08f18a Kostas Papadimitriou
        
1197 8d08f18a Kostas Papadimitriou
        // get the state that the api status corresponds to
1198 8d08f18a Kostas Papadimitriou
        state_for_api_status: function(status) {
1199 8d08f18a Kostas Papadimitriou
            return this.state_transition(this.state(), status);
1200 8d08f18a Kostas Papadimitriou
        },
1201 8d08f18a Kostas Papadimitriou
        
1202 8d08f18a Kostas Papadimitriou
        // vm state equals vm api status
1203 8d08f18a Kostas Papadimitriou
        state_is_status: function(state) {
1204 8d08f18a Kostas Papadimitriou
            return models.VM.STATUSES.indexOf(state) != -1;
1205 8d08f18a Kostas Papadimitriou
        },
1206 8d08f18a Kostas Papadimitriou
        
1207 8d08f18a Kostas Papadimitriou
        // get transition state for the corresponging api status
1208 8d08f18a Kostas Papadimitriou
        state_transition: function(state, new_status) {
1209 8d08f18a Kostas Papadimitriou
            var statuses = models.VM.STATES_TRANSITIONS[state];
1210 8d08f18a Kostas Papadimitriou
            if (statuses) {
1211 8d08f18a Kostas Papadimitriou
                if (statuses.indexOf(new_status) > -1) {
1212 8d08f18a Kostas Papadimitriou
                    return new_status;
1213 8d08f18a Kostas Papadimitriou
                } else {
1214 8d08f18a Kostas Papadimitriou
                    return state;
1215 8d08f18a Kostas Papadimitriou
                }
1216 8d08f18a Kostas Papadimitriou
            } else {
1217 8d08f18a Kostas Papadimitriou
                return new_status;
1218 8d08f18a Kostas Papadimitriou
            }
1219 8d08f18a Kostas Papadimitriou
        },
1220 8d08f18a Kostas Papadimitriou
        
1221 8d08f18a Kostas Papadimitriou
        // the current vm state is a transition state
1222 8d08f18a Kostas Papadimitriou
        in_transition: function() {
1223 8d08f18a Kostas Papadimitriou
            return models.VM.TRANSITION_STATES.indexOf(this.state()) > -1 || 
1224 8d08f18a Kostas Papadimitriou
                models.VM.TRANSITION_STATES.indexOf(this.get('status')) > -1;
1225 8d08f18a Kostas Papadimitriou
        },
1226 8d08f18a Kostas Papadimitriou
        
1227 8d08f18a Kostas Papadimitriou
        // get image object
1228 c45bed88 Kostas Papadimitriou
        get_image: function(callback) {
1229 cde8cde3 Kostas Papadimitriou
            if (callback == undefined) { callback = function(){} }
1230 bedfe884 Kostas Papadimitriou
            var image = storage.images.get(this.get('imageRef'));
1231 bedfe884 Kostas Papadimitriou
            if (!image) {
1232 c45bed88 Kostas Papadimitriou
                storage.images.update_unknown_id(this.get('imageRef'), callback);
1233 c45bed88 Kostas Papadimitriou
                return;
1234 bedfe884 Kostas Papadimitriou
            }
1235 c45bed88 Kostas Papadimitriou
            callback(image);
1236 bedfe884 Kostas Papadimitriou
            return image;
1237 8d08f18a Kostas Papadimitriou
        },
1238 8d08f18a Kostas Papadimitriou
        
1239 8d08f18a Kostas Papadimitriou
        // get flavor object
1240 8d08f18a Kostas Papadimitriou
        get_flavor: function() {
1241 bedfe884 Kostas Papadimitriou
            var flv = storage.flavors.get(this.get('flavorRef'));
1242 bedfe884 Kostas Papadimitriou
            if (!flv) {
1243 bedfe884 Kostas Papadimitriou
                storage.flavors.update_unknown_id(this.get('flavorRef'));
1244 bedfe884 Kostas Papadimitriou
                flv = storage.flavors.get(this.get('flavorRef'));
1245 bedfe884 Kostas Papadimitriou
            }
1246 bedfe884 Kostas Papadimitriou
            return flv;
1247 8d08f18a Kostas Papadimitriou
        },
1248 8d08f18a Kostas Papadimitriou
1249 cde8cde3 Kostas Papadimitriou
        get_meta: function(key, deflt) {
1250 88d6d677 Kostas Papadimitriou
            if (this.get('metadata') && this.get('metadata').values) {
1251 cde8cde3 Kostas Papadimitriou
                if (!this.get('metadata').values[key]) { return deflt }
1252 df251d55 Kostas Papadimitriou
                return _.escape(this.get('metadata').values[key]);
1253 88d6d677 Kostas Papadimitriou
            } else {
1254 cde8cde3 Kostas Papadimitriou
                return deflt;
1255 88d6d677 Kostas Papadimitriou
            }
1256 88d6d677 Kostas Papadimitriou
        },
1257 88d6d677 Kostas Papadimitriou
1258 88d6d677 Kostas Papadimitriou
        get_meta_keys: function() {
1259 88d6d677 Kostas Papadimitriou
            if (this.get('metadata') && this.get('metadata').values) {
1260 88d6d677 Kostas Papadimitriou
                return _.keys(this.get('metadata').values);
1261 88d6d677 Kostas Papadimitriou
            } else {
1262 88d6d677 Kostas Papadimitriou
                return [];
1263 8d08f18a Kostas Papadimitriou
            }
1264 8d08f18a Kostas Papadimitriou
        },
1265 8d08f18a Kostas Papadimitriou
        
1266 8d08f18a Kostas Papadimitriou
        // get metadata OS value
1267 8d08f18a Kostas Papadimitriou
        get_os: function() {
1268 cde8cde3 Kostas Papadimitriou
            var image = this.get_image();
1269 cde8cde3 Kostas Papadimitriou
            return this.get_meta('OS') || (image ? 
1270 cde8cde3 Kostas Papadimitriou
                                            image.get_os() || "okeanos" : "okeanos");
1271 8d08f18a Kostas Papadimitriou
        },
1272 258235f4 Kostas Papadimitriou
1273 43ec1206 Kostas Papadimitriou
        get_gui: function() {
1274 43ec1206 Kostas Papadimitriou
            return this.get_meta('GUI');
1275 43ec1206 Kostas Papadimitriou
        },
1276 126a01f2 Kostas Papadimitriou
        
1277 126a01f2 Kostas Papadimitriou
        connected_to: function(net) {
1278 126a01f2 Kostas Papadimitriou
            return this.get('linked_to').indexOf(net.id) > -1;
1279 126a01f2 Kostas Papadimitriou
        },
1280 43ec1206 Kostas Papadimitriou
1281 126a01f2 Kostas Papadimitriou
        connected_with_nic_id: function(nic_id) {
1282 126a01f2 Kostas Papadimitriou
            return _.keys(this.get('nics')).indexOf(nic_id) > -1;
1283 8d08f18a Kostas Papadimitriou
        },
1284 8d08f18a Kostas Papadimitriou
1285 126a01f2 Kostas Papadimitriou
        get_nics: function(filter) {
1286 126a01f2 Kostas Papadimitriou
            ret = synnefo.storage.nics.filter(function(nic) {
1287 126a01f2 Kostas Papadimitriou
                return parseInt(nic.get('vm_id')) == this.id;
1288 126a01f2 Kostas Papadimitriou
            }, this);
1289 8d08f18a Kostas Papadimitriou
1290 126a01f2 Kostas Papadimitriou
            if (filter) {
1291 126a01f2 Kostas Papadimitriou
                return _.filter(ret, filter);
1292 8d08f18a Kostas Papadimitriou
            }
1293 126a01f2 Kostas Papadimitriou
1294 126a01f2 Kostas Papadimitriou
            return ret;
1295 126a01f2 Kostas Papadimitriou
        },
1296 126a01f2 Kostas Papadimitriou
1297 126a01f2 Kostas Papadimitriou
        get_net_nics: function(net_id) {
1298 126a01f2 Kostas Papadimitriou
            return this.get_nics(function(n){return n.get('network_id') == net_id});
1299 8d08f18a Kostas Papadimitriou
        },
1300 8d08f18a Kostas Papadimitriou
1301 126a01f2 Kostas Papadimitriou
        get_public_nic: function() {
1302 47c66641 Dimitris Aragiorgis
            return this.get_nics(function(n){ return n.get_network().is_public() === true })[0];
1303 8d08f18a Kostas Papadimitriou
        },
1304 8d08f18a Kostas Papadimitriou
1305 3796f345 Kostas Papadimitriou
        get_hostname: function() {
1306 3796f345 Kostas Papadimitriou
          var hostname = this.get_meta('hostname');
1307 3796f345 Kostas Papadimitriou
          if (!hostname) {
1308 f5e97e7f Kostas Papadimitriou
            if (synnefo.config.vm_hostname_format) {
1309 f5e97e7f Kostas Papadimitriou
              hostname = synnefo.config.vm_hostname_format.format(this.id);
1310 f5e97e7f Kostas Papadimitriou
            } else {
1311 f5e97e7f Kostas Papadimitriou
              hostname = this.get_public_nic().get('ipv4');
1312 f5e97e7f Kostas Papadimitriou
            }
1313 3796f345 Kostas Papadimitriou
          }
1314 3796f345 Kostas Papadimitriou
          return hostname;
1315 3796f345 Kostas Papadimitriou
        },
1316 3796f345 Kostas Papadimitriou
1317 126a01f2 Kostas Papadimitriou
        get_nic: function(net_id) {
1318 126a01f2 Kostas Papadimitriou
        },
1319 126a01f2 Kostas Papadimitriou
1320 126a01f2 Kostas Papadimitriou
        has_firewall: function() {
1321 126a01f2 Kostas Papadimitriou
            var nic = this.get_public_nic();
1322 126a01f2 Kostas Papadimitriou
            if (nic) {
1323 126a01f2 Kostas Papadimitriou
                var profile = nic.get('firewallProfile'); 
1324 126a01f2 Kostas Papadimitriou
                return ['ENABLED', 'PROTECTED'].indexOf(profile) > -1;
1325 126a01f2 Kostas Papadimitriou
            }
1326 126a01f2 Kostas Papadimitriou
            return false;
1327 126a01f2 Kostas Papadimitriou
        },
1328 126a01f2 Kostas Papadimitriou
1329 126a01f2 Kostas Papadimitriou
        get_firewall_profile: function() {
1330 126a01f2 Kostas Papadimitriou
            var nic = this.get_public_nic();
1331 126a01f2 Kostas Papadimitriou
            if (nic) {
1332 126a01f2 Kostas Papadimitriou
                return nic.get('firewallProfile');
1333 126a01f2 Kostas Papadimitriou
            }
1334 126a01f2 Kostas Papadimitriou
            return null;
1335 126a01f2 Kostas Papadimitriou
        },
1336 126a01f2 Kostas Papadimitriou
1337 126a01f2 Kostas Papadimitriou
        get_addresses: function() {
1338 126a01f2 Kostas Papadimitriou
            var pnic = this.get_public_nic();
1339 126a01f2 Kostas Papadimitriou
            if (!pnic) { return {'ip4': undefined, 'ip6': undefined }};
1340 126a01f2 Kostas Papadimitriou
            return {'ip4': pnic.get('ipv4'), 'ip6': pnic.get('ipv6')};
1341 8d08f18a Kostas Papadimitriou
        },
1342 8d08f18a Kostas Papadimitriou
    
1343 8d08f18a Kostas Papadimitriou
        // get actions that the user can execute
1344 8d08f18a Kostas Papadimitriou
        // depending on the vm state/status
1345 8d08f18a Kostas Papadimitriou
        get_available_actions: function() {
1346 8d08f18a Kostas Papadimitriou
            return models.VM.AVAILABLE_ACTIONS[this.state()];
1347 8d08f18a Kostas Papadimitriou
        },
1348 8d08f18a Kostas Papadimitriou
1349 8d08f18a Kostas Papadimitriou
        set_profile: function(profile, net_id) {
1350 8d08f18a Kostas Papadimitriou
        },
1351 8d08f18a Kostas Papadimitriou
        
1352 8d08f18a Kostas Papadimitriou
        // call rename api
1353 8d08f18a Kostas Papadimitriou
        rename: function(new_name) {
1354 8d08f18a Kostas Papadimitriou
            //this.set({'name': new_name});
1355 8d08f18a Kostas Papadimitriou
            this.sync("update", this, {
1356 9ffd10ce Kostas Papadimitriou
                critical: true,
1357 8d08f18a Kostas Papadimitriou
                data: {
1358 8d08f18a Kostas Papadimitriou
                    'server': {
1359 8d08f18a Kostas Papadimitriou
                        'name': new_name
1360 8d08f18a Kostas Papadimitriou
                    }
1361 8d08f18a Kostas Papadimitriou
                }, 
1362 8d08f18a Kostas Papadimitriou
                // do the rename after the method succeeds
1363 8d08f18a Kostas Papadimitriou
                success: _.bind(function(){
1364 8d08f18a Kostas Papadimitriou
                    //this.set({name: new_name});
1365 8d08f18a Kostas Papadimitriou
                    snf.api.trigger("call");
1366 8d08f18a Kostas Papadimitriou
                }, this)
1367 8d08f18a Kostas Papadimitriou
            });
1368 8d08f18a Kostas Papadimitriou
        },
1369 8d08f18a Kostas Papadimitriou
        
1370 8d08f18a Kostas Papadimitriou
        get_console_url: function(data) {
1371 8d08f18a Kostas Papadimitriou
            var url_params = {
1372 8d08f18a Kostas Papadimitriou
                machine: this.get("name"),
1373 8d08f18a Kostas Papadimitriou
                host_ip: this.get_addresses().ip4,
1374 8d08f18a Kostas Papadimitriou
                host_ip_v6: this.get_addresses().ip6,
1375 8d08f18a Kostas Papadimitriou
                host: data.host,
1376 8d08f18a Kostas Papadimitriou
                port: data.port,
1377 8d08f18a Kostas Papadimitriou
                password: data.password
1378 8d08f18a Kostas Papadimitriou
            }
1379 8d08f18a Kostas Papadimitriou
            return '/machines/console?' + $.param(url_params);
1380 8d08f18a Kostas Papadimitriou
        },
1381 8d08f18a Kostas Papadimitriou
1382 8d08f18a Kostas Papadimitriou
        // action helper
1383 738a9b18 Kostas Papadimitriou
        call: function(action_name, success, error, params) {
1384 8d08f18a Kostas Papadimitriou
            var id_param = [this.id];
1385 738a9b18 Kostas Papadimitriou
            
1386 738a9b18 Kostas Papadimitriou
            params = params || {};
1387 8d08f18a Kostas Papadimitriou
            success = success || function() {};
1388 8d08f18a Kostas Papadimitriou
            error = error || function() {};
1389 8d08f18a Kostas Papadimitriou
1390 8d08f18a Kostas Papadimitriou
            var self = this;
1391 8d08f18a Kostas Papadimitriou
1392 8d08f18a Kostas Papadimitriou
            switch(action_name) {
1393 8d08f18a Kostas Papadimitriou
                case 'start':
1394 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.get_action_url(), // vm actions url
1395 8d08f18a Kostas Papadimitriou
                                         "create", // create so that sync later uses POST to make the call
1396 8d08f18a Kostas Papadimitriou
                                         {start:{}}, // payload
1397 8d08f18a Kostas Papadimitriou
                                         function() {
1398 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1399 8d08f18a Kostas Papadimitriou
                                             self.state("START"); 
1400 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments);
1401 8d08f18a Kostas Papadimitriou
                                             snf.api.trigger("call");
1402 8d08f18a Kostas Papadimitriou
                                         },  
1403 738a9b18 Kostas Papadimitriou
                                         error, 'start', params);
1404 8d08f18a Kostas Papadimitriou
                    break;
1405 8d08f18a Kostas Papadimitriou
                case 'reboot':
1406 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.get_action_url(), // vm actions url
1407 8d08f18a Kostas Papadimitriou
                                         "create", // create so that sync later uses POST to make the call
1408 8d08f18a Kostas Papadimitriou
                                         {reboot:{type:"HARD"}}, // payload
1409 8d08f18a Kostas Papadimitriou
                                         function() {
1410 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1411 8d08f18a Kostas Papadimitriou
                                             self.state("REBOOT"); 
1412 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments)
1413 8d08f18a Kostas Papadimitriou
                                             snf.api.trigger("call");
1414 122850c5 Kostas Papadimitriou
                                             self.set({'reboot_required': false});
1415 8d08f18a Kostas Papadimitriou
                                         },
1416 738a9b18 Kostas Papadimitriou
                                         error, 'reboot', params);
1417 8d08f18a Kostas Papadimitriou
                    break;
1418 8d08f18a Kostas Papadimitriou
                case 'shutdown':
1419 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.get_action_url(), // vm actions url
1420 8d08f18a Kostas Papadimitriou
                                         "create", // create so that sync later uses POST to make the call
1421 8d08f18a Kostas Papadimitriou
                                         {shutdown:{}}, // payload
1422 8d08f18a Kostas Papadimitriou
                                         function() {
1423 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1424 8d08f18a Kostas Papadimitriou
                                             self.state("SHUTDOWN"); 
1425 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments)
1426 8d08f18a Kostas Papadimitriou
                                             snf.api.trigger("call");
1427 8d08f18a Kostas Papadimitriou
                                         },  
1428 738a9b18 Kostas Papadimitriou
                                         error, 'shutdown', params);
1429 8d08f18a Kostas Papadimitriou
                    break;
1430 8d08f18a Kostas Papadimitriou
                case 'console':
1431 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.url() + "/action", "create", {'console': {'type':'vnc'}}, function(data) {
1432 8d08f18a Kostas Papadimitriou
                        var cons_data = data.console;
1433 8d08f18a Kostas Papadimitriou
                        success.apply(this, [cons_data]);
1434 738a9b18 Kostas Papadimitriou
                    }, undefined, 'console', params)
1435 8d08f18a Kostas Papadimitriou
                    break;
1436 8d08f18a Kostas Papadimitriou
                case 'destroy':
1437 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.url(), // vm actions url
1438 8d08f18a Kostas Papadimitriou
                                         "delete", // create so that sync later uses POST to make the call
1439 8d08f18a Kostas Papadimitriou
                                         undefined, // payload
1440 8d08f18a Kostas Papadimitriou
                                         function() {
1441 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1442 8d08f18a Kostas Papadimitriou
                                             self.state('DESTROY');
1443 b14e3b9e Kostas Papadimitriou
                                             success.apply(this, arguments);
1444 426e1fb9 Kostas Papadimitriou
                                             synnefo.storage.quotas.get('cyclades.vm').decrease();
1445 b14e3b9e Kostas Papadimitriou
1446 8d08f18a Kostas Papadimitriou
                                         },  
1447 738a9b18 Kostas Papadimitriou
                                         error, 'destroy', params);
1448 8d08f18a Kostas Papadimitriou
                    break;
1449 8d08f18a Kostas Papadimitriou
                default:
1450 8d08f18a Kostas Papadimitriou
                    throw "Invalid VM action ("+action_name+")";
1451 8d08f18a Kostas Papadimitriou
            }
1452 8d08f18a Kostas Papadimitriou
        },
1453 8d08f18a Kostas Papadimitriou
        
1454 738a9b18 Kostas Papadimitriou
        __make_api_call: function(url, method, data, success, error, action, extra_params) {
1455 8d08f18a Kostas Papadimitriou
            var self = this;
1456 8d08f18a Kostas Papadimitriou
            error = error || function(){};
1457 8d08f18a Kostas Papadimitriou
            success = success || function(){};
1458 8d08f18a Kostas Papadimitriou
1459 8d08f18a Kostas Papadimitriou
            var params = {
1460 8d08f18a Kostas Papadimitriou
                url: url,
1461 8d08f18a Kostas Papadimitriou
                data: data,
1462 8d08f18a Kostas Papadimitriou
                success: function(){ self.handle_action_succeed.apply(self, arguments); success.apply(this, arguments)},
1463 edd1d565 Kostas Papadimitriou
                error: function(){ self.handle_action_fail.apply(self, arguments); error.apply(this, arguments)},
1464 edd1d565 Kostas Papadimitriou
                error_params: { ns: "Machines actions", 
1465 9ffd10ce Kostas Papadimitriou
                                title: "'" + this.get("name") + "'" + " " + action + " failed", 
1466 6a3a5bf7 Kostas Papadimitriou
                                extra_details: { 'Machine ID': this.id, 'URL': url, 'Action': action || "undefined" },
1467 6a3a5bf7 Kostas Papadimitriou
                                allow_reload: false
1468 6a3a5bf7 Kostas Papadimitriou
                              },
1469 9ce969a7 Kostas Papadimitriou
                display: false,
1470 9ce969a7 Kostas Papadimitriou
                critical: false
1471 8d08f18a Kostas Papadimitriou
            }
1472 738a9b18 Kostas Papadimitriou
            _.extend(params, extra_params)
1473 8d08f18a Kostas Papadimitriou
            this.sync(method, this, params);
1474 8d08f18a Kostas Papadimitriou
        },
1475 8d08f18a Kostas Papadimitriou
1476 8d08f18a Kostas Papadimitriou
        handle_action_succeed: function() {
1477 8d08f18a Kostas Papadimitriou
            this.trigger("action:success", arguments);
1478 8d08f18a Kostas Papadimitriou
        },
1479 6a3a5bf7 Kostas Papadimitriou
        
1480 6a3a5bf7 Kostas Papadimitriou
        reset_action_error: function() {
1481 6a3a5bf7 Kostas Papadimitriou
            this.action_error = false;
1482 6a3a5bf7 Kostas Papadimitriou
            this.trigger("action:fail:reset", this.action_error);
1483 6a3a5bf7 Kostas Papadimitriou
        },
1484 8d08f18a Kostas Papadimitriou
1485 8d08f18a Kostas Papadimitriou
        handle_action_fail: function() {
1486 6a3a5bf7 Kostas Papadimitriou
            this.action_error = arguments;
1487 8d08f18a Kostas Papadimitriou
            this.trigger("action:fail", arguments);
1488 8d08f18a Kostas Papadimitriou
        },
1489 8d08f18a Kostas Papadimitriou
1490 8d08f18a Kostas Papadimitriou
        get_action_url: function(name) {
1491 8d08f18a Kostas Papadimitriou
            return this.url() + "/action";
1492 1c922789 Kostas Papadimitriou
        },
1493 1c922789 Kostas Papadimitriou
1494 1e882dd7 Kostas Papadimitriou
        get_diagnostics_url: function() {
1495 1e882dd7 Kostas Papadimitriou
            return this.url() + "/diagnostics";
1496 1e882dd7 Kostas Papadimitriou
        },
1497 1e882dd7 Kostas Papadimitriou
1498 1c922789 Kostas Papadimitriou
        get_connection_info: function(host_os, success, error) {
1499 1c922789 Kostas Papadimitriou
            var url = "/machines/connect";
1500 1c922789 Kostas Papadimitriou
            params = {
1501 3796f345 Kostas Papadimitriou
                ip_address: this.get_public_nic().get('ipv4'),
1502 3796f345 Kostas Papadimitriou
                hostname: this.get_hostname(),
1503 1c922789 Kostas Papadimitriou
                os: this.get_os(),
1504 1c922789 Kostas Papadimitriou
                host_os: host_os,
1505 1c922789 Kostas Papadimitriou
                srv: this.id
1506 1c922789 Kostas Papadimitriou
            }
1507 1c922789 Kostas Papadimitriou
1508 1c922789 Kostas Papadimitriou
            url = url + "?" + $.param(params);
1509 1c922789 Kostas Papadimitriou
1510 1c922789 Kostas Papadimitriou
            var ajax = snf.api.sync("read", undefined, { url: url, 
1511 1c922789 Kostas Papadimitriou
                                                         error:error, 
1512 1c922789 Kostas Papadimitriou
                                                         success:success, 
1513 1c922789 Kostas Papadimitriou
                                                         handles_error:1});
1514 8d08f18a Kostas Papadimitriou
        }
1515 8d08f18a Kostas Papadimitriou
    })
1516 8d08f18a Kostas Papadimitriou
    
1517 8d08f18a Kostas Papadimitriou
    models.VM.ACTIONS = [
1518 8d08f18a Kostas Papadimitriou
        'start',
1519 8d08f18a Kostas Papadimitriou
        'shutdown',
1520 8d08f18a Kostas Papadimitriou
        'reboot',
1521 0f7214b3 Kostas Papadimitriou
        'console',
1522 8d08f18a Kostas Papadimitriou
        'destroy'
1523 8d08f18a Kostas Papadimitriou
    ]
1524 8d08f18a Kostas Papadimitriou
1525 8d08f18a Kostas Papadimitriou
    models.VM.AVAILABLE_ACTIONS = {
1526 8d08f18a Kostas Papadimitriou
        'UNKNWON'       : ['destroy'],
1527 8d08f18a Kostas Papadimitriou
        'BUILD'         : ['destroy'],
1528 8d08f18a Kostas Papadimitriou
        'REBOOT'        : ['shutdown', 'destroy', 'console'],
1529 8d08f18a Kostas Papadimitriou
        'STOPPED'       : ['start', 'destroy'],
1530 8d08f18a Kostas Papadimitriou
        'ACTIVE'        : ['shutdown', 'destroy', 'reboot', 'console'],
1531 8d08f18a Kostas Papadimitriou
        'ERROR'         : ['destroy'],
1532 643de8c0 Kostas Papadimitriou
        'DELETED'        : [],
1533 8d08f18a Kostas Papadimitriou
        'DESTROY'       : [],
1534 8d08f18a Kostas Papadimitriou
        'BUILD_INIT'    : ['destroy'],
1535 8d08f18a Kostas Papadimitriou
        'BUILD_COPY'    : ['destroy'],
1536 8d08f18a Kostas Papadimitriou
        'BUILD_FINAL'   : ['destroy'],
1537 8d08f18a Kostas Papadimitriou
        'SHUTDOWN'      : ['destroy'],
1538 8d08f18a Kostas Papadimitriou
        'START'         : [],
1539 8d08f18a Kostas Papadimitriou
        'CONNECT'       : [],
1540 8d08f18a Kostas Papadimitriou
        'DISCONNECT'    : []
1541 8d08f18a Kostas Papadimitriou
    }
1542 8d08f18a Kostas Papadimitriou
1543 8d08f18a Kostas Papadimitriou
    // api status values
1544 8d08f18a Kostas Papadimitriou
    models.VM.STATUSES = [
1545 8d08f18a Kostas Papadimitriou
        'UNKNWON',
1546 8d08f18a Kostas Papadimitriou
        'BUILD',
1547 8d08f18a Kostas Papadimitriou
        'REBOOT',
1548 8d08f18a Kostas Papadimitriou
        'STOPPED',
1549 8d08f18a Kostas Papadimitriou
        'ACTIVE',
1550 8d08f18a Kostas Papadimitriou
        'ERROR',
1551 643de8c0 Kostas Papadimitriou
        'DELETED'
1552 8d08f18a Kostas Papadimitriou
    ]
1553 8d08f18a Kostas Papadimitriou
1554 8d08f18a Kostas Papadimitriou
    // api status values
1555 8d08f18a Kostas Papadimitriou
    models.VM.CONNECT_STATES = [
1556 8d08f18a Kostas Papadimitriou
        'ACTIVE',
1557 8d08f18a Kostas Papadimitriou
        'REBOOT',
1558 df12e032 Kostas Papadimitriou
        'SHUTDOWN'
1559 8d08f18a Kostas Papadimitriou
    ]
1560 8d08f18a Kostas Papadimitriou
1561 8d08f18a Kostas Papadimitriou
    // vm states
1562 8d08f18a Kostas Papadimitriou
    models.VM.STATES = models.VM.STATUSES.concat([
1563 8d08f18a Kostas Papadimitriou
        'DESTROY',
1564 8d08f18a Kostas Papadimitriou
        'BUILD_INIT',
1565 8d08f18a Kostas Papadimitriou
        'BUILD_COPY',
1566 8d08f18a Kostas Papadimitriou
        'BUILD_FINAL',
1567 8d08f18a Kostas Papadimitriou
        'SHUTDOWN',
1568 8d08f18a Kostas Papadimitriou
        'START',
1569 8d08f18a Kostas Papadimitriou
        'CONNECT',
1570 8d08f18a Kostas Papadimitriou
        'DISCONNECT',
1571 8d08f18a Kostas Papadimitriou
        'FIREWALL'
1572 8d08f18a Kostas Papadimitriou
    ]);
1573 8d08f18a Kostas Papadimitriou
    
1574 8d08f18a Kostas Papadimitriou
    models.VM.STATES_TRANSITIONS = {
1575 643de8c0 Kostas Papadimitriou
        'DESTROY' : ['DELETED'],
1576 8d08f18a Kostas Papadimitriou
        'SHUTDOWN': ['ERROR', 'STOPPED', 'DESTROY'],
1577 8d08f18a Kostas Papadimitriou
        'STOPPED': ['ERROR', 'ACTIVE', 'DESTROY'],
1578 8d08f18a Kostas Papadimitriou
        'ACTIVE': ['ERROR', 'STOPPED', 'REBOOT', 'SHUTDOWN', 'DESTROY'],
1579 8d08f18a Kostas Papadimitriou
        'START': ['ERROR', 'ACTIVE', 'DESTROY'],
1580 8d08f18a Kostas Papadimitriou
        'REBOOT': ['ERROR', 'ACTIVE', 'STOPPED', 'DESTROY'],
1581 8d08f18a Kostas Papadimitriou
        'BUILD': ['ERROR', 'ACTIVE', 'DESTROY'],
1582 8d08f18a Kostas Papadimitriou
        'BUILD_COPY': ['ERROR', 'ACTIVE', 'BUILD_FINAL', 'DESTROY'],
1583 8d08f18a Kostas Papadimitriou
        'BUILD_FINAL': ['ERROR', 'ACTIVE', 'DESTROY'],
1584 8d08f18a Kostas Papadimitriou
        'BUILD_INIT': ['ERROR', 'ACTIVE', 'BUILD_COPY', 'BUILD_FINAL', 'DESTROY']
1585 8d08f18a Kostas Papadimitriou
    }
1586 8d08f18a Kostas Papadimitriou
1587 8d08f18a Kostas Papadimitriou
    models.VM.TRANSITION_STATES = [
1588 8d08f18a Kostas Papadimitriou
        'DESTROY',
1589 8d08f18a Kostas Papadimitriou
        'SHUTDOWN',
1590 8d08f18a Kostas Papadimitriou
        'START',
1591 8d08f18a Kostas Papadimitriou
        'REBOOT',
1592 8d08f18a Kostas Papadimitriou
        'BUILD'
1593 8d08f18a Kostas Papadimitriou
    ]
1594 8d08f18a Kostas Papadimitriou
1595 8d08f18a Kostas Papadimitriou
    models.VM.ACTIVE_STATES = [
1596 8d08f18a Kostas Papadimitriou
        'BUILD', 'REBOOT', 'ACTIVE',
1597 8d08f18a Kostas Papadimitriou
        'BUILD_INIT', 'BUILD_COPY', 'BUILD_FINAL',
1598 4e365467 Kostas Papadimitriou
        'SHUTDOWN', 'CONNECT', 'DISCONNECT'
1599 8d08f18a Kostas Papadimitriou
    ]
1600 8d08f18a Kostas Papadimitriou
1601 8d08f18a Kostas Papadimitriou
    models.VM.BUILDING_STATES = [
1602 8d08f18a Kostas Papadimitriou
        'BUILD', 'BUILD_INIT', 'BUILD_COPY', 'BUILD_FINAL'
1603 8d08f18a Kostas Papadimitriou
    ]
1604 8d08f18a Kostas Papadimitriou
1605 8d08f18a Kostas Papadimitriou
    models.Networks = models.Collection.extend({
1606 8d08f18a Kostas Papadimitriou
        model: models.Network,
1607 8d08f18a Kostas Papadimitriou
        path: 'networks',
1608 8d08f18a Kostas Papadimitriou
        details: true,
1609 8d08f18a Kostas Papadimitriou
        //noUpdate: true,
1610 126a01f2 Kostas Papadimitriou
        defaults: {'nics':[],'linked_to':[]},
1611 126a01f2 Kostas Papadimitriou
        
1612 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1613 8d08f18a Kostas Papadimitriou
            // FIXME: depricated global var
1614 8d08f18a Kostas Papadimitriou
            if (!resp) { return []};
1615 01461689 Kostas Papadimitriou
            var data = _.filter(_.map(resp.networks.values, _.bind(this.parse_net_api_data, this)),
1616 01461689 Kostas Papadimitriou
                               function(e){ return e });
1617 8d08f18a Kostas Papadimitriou
            return data;
1618 8d08f18a Kostas Papadimitriou
        },
1619 8d08f18a Kostas Papadimitriou
1620 126a01f2 Kostas Papadimitriou
        add: function() {
1621 126a01f2 Kostas Papadimitriou
            ret = models.Networks.__super__.add.apply(this, arguments);
1622 126a01f2 Kostas Papadimitriou
            // update nics after each network addition
1623 126a01f2 Kostas Papadimitriou
            ret.each(function(r){
1624 126a01f2 Kostas Papadimitriou
                synnefo.storage.nics.update_net_nics(r);
1625 126a01f2 Kostas Papadimitriou
            });
1626 126a01f2 Kostas Papadimitriou
        },
1627 126a01f2 Kostas Papadimitriou
1628 101e6604 Kostas Papadimitriou
        reset_pending_actions: function() {
1629 101e6604 Kostas Papadimitriou
            this.each(function(net) {
1630 101e6604 Kostas Papadimitriou
                net.get("actions").reset();
1631 126a01f2 Kostas Papadimitriou
            });
1632 101e6604 Kostas Papadimitriou
        },
1633 101e6604 Kostas Papadimitriou
1634 101e6604 Kostas Papadimitriou
        do_all_pending_actions: function() {
1635 101e6604 Kostas Papadimitriou
            this.each(function(net) {
1636 101e6604 Kostas Papadimitriou
                net.do_all_pending_actions();
1637 101e6604 Kostas Papadimitriou
            })
1638 101e6604 Kostas Papadimitriou
        },
1639 101e6604 Kostas Papadimitriou
1640 8d08f18a Kostas Papadimitriou
        parse_net_api_data: function(data) {
1641 126a01f2 Kostas Papadimitriou
            // append nic metadata
1642 126a01f2 Kostas Papadimitriou
            // net.get('nics') contains a list of vm/index objects 
1643 126a01f2 Kostas Papadimitriou
            // e.g. {'vm_id':12231, 'index':1}
1644 126a01f2 Kostas Papadimitriou
            // net.get('linked_to') contains a list of vms the network is 
1645 126a01f2 Kostas Papadimitriou
            // connected to e.g. [1001, 1002]
1646 126a01f2 Kostas Papadimitriou
            if (data.attachments && data.attachments.values) {
1647 126a01f2 Kostas Papadimitriou
                data['nics'] = {};
1648 126a01f2 Kostas Papadimitriou
                data['linked_to'] = [];
1649 126a01f2 Kostas Papadimitriou
                _.each(data.attachments.values, function(nic_id){
1650 126a01f2 Kostas Papadimitriou
                  
1651 126a01f2 Kostas Papadimitriou
                  var vm_id = NIC_REGEX.exec(nic_id)[1];
1652 126a01f2 Kostas Papadimitriou
                  var nic_index = parseInt(NIC_REGEX.exec(nic_id)[2]);
1653 126a01f2 Kostas Papadimitriou
1654 126a01f2 Kostas Papadimitriou
                  if (vm_id !== undefined && nic_index !== undefined) {
1655 126a01f2 Kostas Papadimitriou
                      data['nics'][nic_id] = {
1656 126a01f2 Kostas Papadimitriou
                          'vm_id': vm_id, 
1657 126a01f2 Kostas Papadimitriou
                          'index': nic_index, 
1658 126a01f2 Kostas Papadimitriou
                          'id': nic_id
1659 126a01f2 Kostas Papadimitriou
                      };
1660 126a01f2 Kostas Papadimitriou
                      if (data['linked_to'].indexOf(vm_id) == -1) {
1661 126a01f2 Kostas Papadimitriou
                        data['linked_to'].push(vm_id);
1662 126a01f2 Kostas Papadimitriou
                      }
1663 126a01f2 Kostas Papadimitriou
                  }
1664 126a01f2 Kostas Papadimitriou
                });
1665 8d08f18a Kostas Papadimitriou
            }
1666 01461689 Kostas Papadimitriou
1667 01461689 Kostas Papadimitriou
            if (data.status == "DELETED" && !this.get(parseInt(data.id))) {
1668 01461689 Kostas Papadimitriou
              return false;
1669 01461689 Kostas Papadimitriou
            }
1670 8d08f18a Kostas Papadimitriou
            return data;
1671 8d08f18a Kostas Papadimitriou
        },
1672 8d08f18a Kostas Papadimitriou
1673 126a01f2 Kostas Papadimitriou
        create: function (name, type, cidr, dhcp, callback) {
1674 126a01f2 Kostas Papadimitriou
            var params = {
1675 126a01f2 Kostas Papadimitriou
                network:{
1676 126a01f2 Kostas Papadimitriou
                    name:name
1677 126a01f2 Kostas Papadimitriou
                }
1678 126a01f2 Kostas Papadimitriou
            };
1679 126a01f2 Kostas Papadimitriou
1680 126a01f2 Kostas Papadimitriou
            if (type) {
1681 126a01f2 Kostas Papadimitriou
                params.network.type = type;
1682 126a01f2 Kostas Papadimitriou
            }
1683 126a01f2 Kostas Papadimitriou
            if (cidr) {
1684 126a01f2 Kostas Papadimitriou
                params.network.cidr = cidr;
1685 126a01f2 Kostas Papadimitriou
            }
1686 126a01f2 Kostas Papadimitriou
            if (dhcp) {
1687 126a01f2 Kostas Papadimitriou
                params.network.dhcp = dhcp;
1688 126a01f2 Kostas Papadimitriou
            }
1689 126a01f2 Kostas Papadimitriou
1690 126a01f2 Kostas Papadimitriou
            if (dhcp === false) {
1691 126a01f2 Kostas Papadimitriou
                params.network.dhcp = false;
1692 126a01f2 Kostas Papadimitriou
            }
1693 126a01f2 Kostas Papadimitriou
            
1694 b14e3b9e Kostas Papadimitriou
            var cb = function() {
1695 b14e3b9e Kostas Papadimitriou
              callback();
1696 426e1fb9 Kostas Papadimitriou
              synnefo.storage.quotas.get('cyclades.network.private').increase();
1697 b14e3b9e Kostas Papadimitriou
            }
1698 b14e3b9e Kostas Papadimitriou
            return this.api_call(this.path, "create", params, cb);
1699 6de7fde5 Kostas Papadimitriou
        },
1700 6de7fde5 Kostas Papadimitriou
1701 6de7fde5 Kostas Papadimitriou
        get_public: function(){
1702 6de7fde5 Kostas Papadimitriou
          return this.filter(function(n){return n.get('public')});
1703 8d08f18a Kostas Papadimitriou
        }
1704 8d08f18a Kostas Papadimitriou
    })
1705 8d08f18a Kostas Papadimitriou
1706 8d08f18a Kostas Papadimitriou
    models.Images = models.Collection.extend({
1707 8d08f18a Kostas Papadimitriou
        model: models.Image,
1708 8d08f18a Kostas Papadimitriou
        path: 'images',
1709 8d08f18a Kostas Papadimitriou
        details: true,
1710 8d08f18a Kostas Papadimitriou
        noUpdate: true,
1711 16392650 Kostas Papadimitriou
        supportIncUpdates: false,
1712 8d08f18a Kostas Papadimitriou
        meta_keys_as_attrs: ["OS", "description", "kernel", "size", "GUI"],
1713 88d6d677 Kostas Papadimitriou
        meta_labels: {},
1714 258235f4 Kostas Papadimitriou
        read_method: 'read',
1715 8d08f18a Kostas Papadimitriou
1716 bedfe884 Kostas Papadimitriou
        // update collection model with id passed
1717 1420aae4 Kostas Papadimitriou
        // making a direct call to the image
1718 bedfe884 Kostas Papadimitriou
        // api url
1719 c45bed88 Kostas Papadimitriou
        update_unknown_id: function(id, callback) {
1720 bedfe884 Kostas Papadimitriou
            var url = getUrl.call(this) + "/" + id;
1721 126a01f2 Kostas Papadimitriou
            this.api_call(this.path + "/" + id, this.read_method, {
1722 126a01f2 Kostas Papadimitriou
              _options:{
1723 126a01f2 Kostas Papadimitriou
                async:true, 
1724 126a01f2 Kostas Papadimitriou
                skip_api_error:true}
1725 126a01f2 Kostas Papadimitriou
              }, undefined, 
1726 bedfe884 Kostas Papadimitriou
            _.bind(function() {
1727 327f0d58 Kostas Papadimitriou
                if (!this.get(id)) {
1728 d7612b6e Kostas Papadimitriou
                            if (this.fallback_service) {
1729 d7612b6e Kostas Papadimitriou
                        // if current service has fallback_service attribute set
1730 d7612b6e Kostas Papadimitriou
                        // use this service to retrieve the missing image model
1731 d7612b6e Kostas Papadimitriou
                        var tmpservice = new this.fallback_service();
1732 d7612b6e Kostas Papadimitriou
                        tmpservice.update_unknown_id(id, _.bind(function(img){
1733 d7612b6e Kostas Papadimitriou
                            img.attributes.status = "DELETED";
1734 d7612b6e Kostas Papadimitriou
                            this.add(img.attributes);
1735 d7612b6e Kostas Papadimitriou
                            callback(this.get(id));
1736 d7612b6e Kostas Papadimitriou
                        }, this));
1737 d7612b6e Kostas Papadimitriou
                    } else {
1738 03639c6d Kostas Papadimitriou
                        var title = synnefo.config.image_deleted_title || 'Deleted';
1739 d7612b6e Kostas Papadimitriou
                        // else add a dummy DELETED state image entry
1740 03639c6d Kostas Papadimitriou
                        this.add({id:id, name:title, size:-1, 
1741 d7612b6e Kostas Papadimitriou
                                  progress:100, status:"DELETED"});
1742 d7612b6e Kostas Papadimitriou
                        callback(this.get(id));
1743 d7612b6e Kostas Papadimitriou
                    }   
1744 d7612b6e Kostas Papadimitriou
                } else {
1745 d7612b6e Kostas Papadimitriou
                    callback(this.get(id));
1746 327f0d58 Kostas Papadimitriou
                }
1747 258235f4 Kostas Papadimitriou
            }, this), _.bind(function(image, msg, xhr) {
1748 f70c8d47 Kostas Papadimitriou
                if (!image) {
1749 03639c6d Kostas Papadimitriou
                    var title = synnefo.config.image_deleted_title || 'Deleted';
1750 03639c6d Kostas Papadimitriou
                    this.add({id:id, name:title, size:-1, 
1751 f70c8d47 Kostas Papadimitriou
                              progress:100, status:"DELETED"});
1752 f70c8d47 Kostas Papadimitriou
                    callback(this.get(id));
1753 f70c8d47 Kostas Papadimitriou
                    return;
1754 f70c8d47 Kostas Papadimitriou
                }
1755 258235f4 Kostas Papadimitriou
                var img_data = this._read_image_from_request(image, msg, xhr);
1756 258235f4 Kostas Papadimitriou
                this.add(img_data);
1757 c45bed88 Kostas Papadimitriou
                callback(this.get(id));
1758 bedfe884 Kostas Papadimitriou
            }, this));
1759 bedfe884 Kostas Papadimitriou
        },
1760 bedfe884 Kostas Papadimitriou
1761 258235f4 Kostas Papadimitriou
        _read_image_from_request: function(image, msg, xhr) {
1762 258235f4 Kostas Papadimitriou
            return image.image;
1763 258235f4 Kostas Papadimitriou
        },
1764 258235f4 Kostas Papadimitriou
1765 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1766 8f53cfa3 Kostas Papadimitriou
            var parsed = _.map(resp.images.values, _.bind(this.parse_meta, this));
1767 8f53cfa3 Kostas Papadimitriou
            parsed = this.fill_owners(parsed);
1768 8f53cfa3 Kostas Papadimitriou
            return parsed;
1769 8f53cfa3 Kostas Papadimitriou
        },
1770 8f53cfa3 Kostas Papadimitriou
1771 8f53cfa3 Kostas Papadimitriou
        fill_owners: function(images) {
1772 8f53cfa3 Kostas Papadimitriou
            // do translate uuid->displayname if needed
1773 8f53cfa3 Kostas Papadimitriou
            // store display name in owner attribute for compatibility
1774 8f53cfa3 Kostas Papadimitriou
            var uuids = [];
1775 8f53cfa3 Kostas Papadimitriou
1776 8f53cfa3 Kostas Papadimitriou
            var images = _.map(images, function(img, index) {
1777 8f53cfa3 Kostas Papadimitriou
                if (synnefo.config.translate_uuids) {
1778 8f53cfa3 Kostas Papadimitriou
                    uuids.push(img['owner']);
1779 8f53cfa3 Kostas Papadimitriou
                }
1780 8f53cfa3 Kostas Papadimitriou
                img['owner_uuid'] = img['owner'];
1781 8f53cfa3 Kostas Papadimitriou
                return img;
1782 8f53cfa3 Kostas Papadimitriou
            });
1783 8f53cfa3 Kostas Papadimitriou
            
1784 8f53cfa3 Kostas Papadimitriou
            if (uuids.length > 0) {
1785 8f53cfa3 Kostas Papadimitriou
                var handle_results = function(data) {
1786 8f53cfa3 Kostas Papadimitriou
                    _.each(images, function (img) {
1787 8f53cfa3 Kostas Papadimitriou
                        img['owner'] = data.uuid_catalog[img['owner_uuid']];
1788 8f53cfa3 Kostas Papadimitriou
                    });
1789 8f53cfa3 Kostas Papadimitriou
                }
1790 8f53cfa3 Kostas Papadimitriou
                // notice the async false
1791 8f53cfa3 Kostas Papadimitriou
                var uuid_map = this.translate_uuids(uuids, false, 
1792 8f53cfa3 Kostas Papadimitriou
                                                    handle_results)
1793 8f53cfa3 Kostas Papadimitriou
            }
1794 8f53cfa3 Kostas Papadimitriou
            return images;
1795 8f53cfa3 Kostas Papadimitriou
        },
1796 8f53cfa3 Kostas Papadimitriou
1797 8f53cfa3 Kostas Papadimitriou
        translate_uuids: function(uuids, async, cb) {
1798 8f53cfa3 Kostas Papadimitriou
            var url = synnefo.config.user_catalog_url;
1799 8f53cfa3 Kostas Papadimitriou
            var data = JSON.stringify({'uuids': uuids});
1800 8f53cfa3 Kostas Papadimitriou
          
1801 8f53cfa3 Kostas Papadimitriou
            // post to user_catalogs api
1802 8f53cfa3 Kostas Papadimitriou
            snf.api.sync('create', undefined, {
1803 8f53cfa3 Kostas Papadimitriou
                url: url,
1804 8f53cfa3 Kostas Papadimitriou
                data: data,
1805 8f53cfa3 Kostas Papadimitriou
                async: async,
1806 8f53cfa3 Kostas Papadimitriou
                success:  cb
1807 8f53cfa3 Kostas Papadimitriou
            });
1808 8d08f18a Kostas Papadimitriou
        },
1809 8d08f18a Kostas Papadimitriou
1810 8d08f18a Kostas Papadimitriou
        get_meta_key: function(img, key) {
1811 8d08f18a Kostas Papadimitriou
            if (img.metadata && img.metadata.values && img.metadata.values[key]) {
1812 df251d55 Kostas Papadimitriou
                return _.escape(img.metadata.values[key]);
1813 8d08f18a Kostas Papadimitriou
            }
1814 8d08f18a Kostas Papadimitriou
            return undefined;
1815 8d08f18a Kostas Papadimitriou
        },
1816 8d08f18a Kostas Papadimitriou
1817 ccb14ad0 Kostas Papadimitriou
        comparator: function(img) {
1818 ccb14ad0 Kostas Papadimitriou
            return -img.get_sort_order("sortorder") || 1000 * img.id;
1819 ccb14ad0 Kostas Papadimitriou
        },
1820 ccb14ad0 Kostas Papadimitriou
1821 8d08f18a Kostas Papadimitriou
        parse_meta: function(img) {
1822 8d08f18a Kostas Papadimitriou
            _.each(this.meta_keys_as_attrs, _.bind(function(key){
1823 258235f4 Kostas Papadimitriou
                if (img[key]) { return };
1824 2a5ae934 Kostas Papadimitriou
                img[key] = this.get_meta_key(img, key) || "";
1825 8d08f18a Kostas Papadimitriou
            }, this));
1826 8d08f18a Kostas Papadimitriou
            return img;
1827 bedfe884 Kostas Papadimitriou
        },
1828 bedfe884 Kostas Papadimitriou
1829 bedfe884 Kostas Papadimitriou
        active: function() {
1830 bedfe884 Kostas Papadimitriou
            return this.filter(function(img){return img.get('status') != "DELETED"});
1831 2cee7cb0 Kostas Papadimitriou
        },
1832 2cee7cb0 Kostas Papadimitriou
1833 2cee7cb0 Kostas Papadimitriou
        predefined: function() {
1834 2cee7cb0 Kostas Papadimitriou
            return _.filter(this.active(), function(i) { return !i.get("serverRef")});
1835 948042ca Kostas Papadimitriou
        },
1836 948042ca Kostas Papadimitriou
        
1837 948042ca Kostas Papadimitriou
        fetch_for_type: function(type, complete, error) {
1838 948042ca Kostas Papadimitriou
            this.fetch({update:true, 
1839 948042ca Kostas Papadimitriou
                        success: complete, 
1840 948042ca Kostas Papadimitriou
                        error: error, 
1841 948042ca Kostas Papadimitriou
                        skip_api_error: true });
1842 948042ca Kostas Papadimitriou
        },
1843 948042ca Kostas Papadimitriou
        
1844 948042ca Kostas Papadimitriou
        get_images_for_type: function(type) {
1845 948042ca Kostas Papadimitriou
            if (this['get_{0}_images'.format(type)]) {
1846 948042ca Kostas Papadimitriou
                return this['get_{0}_images'.format(type)]();
1847 948042ca Kostas Papadimitriou
            }
1848 948042ca Kostas Papadimitriou
1849 948042ca Kostas Papadimitriou
            return this.active();
1850 948042ca Kostas Papadimitriou
        },
1851 948042ca Kostas Papadimitriou
1852 948042ca Kostas Papadimitriou
        update_images_for_type: function(type, onStart, onComplete, onError, force_load) {
1853 948042ca Kostas Papadimitriou
            var load = false;
1854 948042ca Kostas Papadimitriou
            error = onError || function() {};
1855 948042ca Kostas Papadimitriou
            function complete(collection) { 
1856 948042ca Kostas Papadimitriou
                onComplete(collection.get_images_for_type(type)); 
1857 948042ca Kostas Papadimitriou
            }
1858 948042ca Kostas Papadimitriou
            
1859 948042ca Kostas Papadimitriou
            // do we need to fetch/update current collection entries
1860 948042ca Kostas Papadimitriou
            if (load) {
1861 948042ca Kostas Papadimitriou
                onStart();
1862 948042ca Kostas Papadimitriou
                this.fetch_for_type(type, complete, error);
1863 948042ca Kostas Papadimitriou
            } else {
1864 948042ca Kostas Papadimitriou
                // fallback to complete
1865 948042ca Kostas Papadimitriou
                complete(this);
1866 948042ca Kostas Papadimitriou
            }
1867 8d08f18a Kostas Papadimitriou
        }
1868 8d08f18a Kostas Papadimitriou
    })
1869 8d08f18a Kostas Papadimitriou
1870 8d08f18a Kostas Papadimitriou
    models.Flavors = models.Collection.extend({
1871 8d08f18a Kostas Papadimitriou
        model: models.Flavor,
1872 8d08f18a Kostas Papadimitriou
        path: 'flavors',
1873 8d08f18a Kostas Papadimitriou
        details: true,
1874 8d08f18a Kostas Papadimitriou
        noUpdate: true,
1875 16392650 Kostas Papadimitriou
        supportIncUpdates: false,
1876 bedfe884 Kostas Papadimitriou
        // update collection model with id passed
1877 bedfe884 Kostas Papadimitriou
        // making a direct call to the flavor
1878 bedfe884 Kostas Papadimitriou
        // api url
1879 c45bed88 Kostas Papadimitriou
        update_unknown_id: function(id, callback) {
1880 bedfe884 Kostas Papadimitriou
            var url = getUrl.call(this) + "/" + id;
1881 258235f4 Kostas Papadimitriou
            this.api_call(this.path + "/" + id, "read", {_options:{async:false, skip_api_error:true}}, undefined, 
1882 bedfe884 Kostas Papadimitriou
            _.bind(function() {
1883 9555268a Kostas Papadimitriou
                this.add({id:id, cpu:"Unknown", ram:"Unknown", disk:"Unknown", name: "Unknown", status:"DELETED"})
1884 bedfe884 Kostas Papadimitriou
            }, this), _.bind(function(flv) {
1885 bedfe884 Kostas Papadimitriou
                if (!flv.flavor.status) { flv.flavor.status = "DELETED" };
1886 bedfe884 Kostas Papadimitriou
                this.add(flv.flavor);
1887 bedfe884 Kostas Papadimitriou
            }, this));
1888 bedfe884 Kostas Papadimitriou
        },
1889 8d08f18a Kostas Papadimitriou
1890 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1891 d965e6dc Kostas Papadimitriou
            return _.map(resp.flavors.values, function(o) { o.disk_template = o['SNF:disk_template']; return o});
1892 8d08f18a Kostas Papadimitriou
        },
1893 8d08f18a Kostas Papadimitriou
1894 ccb14ad0 Kostas Papadimitriou
        comparator: function(flv) {
1895 ccb14ad0 Kostas Papadimitriou
            return flv.get("disk") * flv.get("cpu") * flv.get("ram");
1896 ccb14ad0 Kostas Papadimitriou
        },
1897 ccb14ad0 Kostas Papadimitriou
1898 7ac49c2e Kostas Papadimitriou
        unavailable_values_for_quotas: function(quotas, flavors) {
1899 7ac49c2e Kostas Papadimitriou
            var flavors = flavors || this.active();
1900 7ac49c2e Kostas Papadimitriou
            var index = {cpu:[], disk:[], ram:[]};
1901 7ac49c2e Kostas Papadimitriou
            
1902 7ac49c2e Kostas Papadimitriou
            _.each(flavors, function(el) {
1903 7ac49c2e Kostas Papadimitriou
1904 7ac49c2e Kostas Papadimitriou
                var disk_available = quotas['disk'];
1905 7ac49c2e Kostas Papadimitriou
                var disk_size = el.get_disk_size();
1906 7ac49c2e Kostas Papadimitriou
                if (index.disk.indexOf(disk_size) == -1) {
1907 7ac49c2e Kostas Papadimitriou
                  var disk = el.disk_to_bytes();
1908 7ac49c2e Kostas Papadimitriou
                  if (disk > disk_available) {
1909 7ac49c2e Kostas Papadimitriou
                    index.disk.push(disk_size);
1910 7ac49c2e Kostas Papadimitriou
                  }
1911 7ac49c2e Kostas Papadimitriou
                }
1912 7ac49c2e Kostas Papadimitriou
1913 7ac49c2e Kostas Papadimitriou
                var ram_available = quotas['ram'];
1914 7ac49c2e Kostas Papadimitriou
                var ram_size = el.get_ram_size();
1915 2d35cfcd Kostas Papadimitriou
                if (index.ram.indexOf(ram_size) == -1) {
1916 7ac49c2e Kostas Papadimitriou
                  var ram = el.ram_to_bytes();
1917 7ac49c2e Kostas Papadimitriou
                  if (ram > ram_available) {
1918 7ac49c2e Kostas Papadimitriou
                    index.ram.push(el.get('ram'))
1919 7ac49c2e Kostas Papadimitriou
                  }
1920 7ac49c2e Kostas Papadimitriou
                }
1921 7ac49c2e Kostas Papadimitriou
1922 7ac49c2e Kostas Papadimitriou
                var cpu = el.get('cpu');
1923 7ac49c2e Kostas Papadimitriou
                var cpu_available = quotas['cpu'];
1924 7ac49c2e Kostas Papadimitriou
                if (index.ram.indexOf(cpu) == -1) {
1925 7ac49c2e Kostas Papadimitriou
                  if (cpu > cpu_available) {
1926 7ac49c2e Kostas Papadimitriou
                    index.cpu.push(el.get('cpu'))
1927 7ac49c2e Kostas Papadimitriou
                  }
1928 7ac49c2e Kostas Papadimitriou
                }
1929 7ac49c2e Kostas Papadimitriou
            });
1930 7ac49c2e Kostas Papadimitriou
            return index;
1931 7ac49c2e Kostas Papadimitriou
        },
1932 7ac49c2e Kostas Papadimitriou
1933 820ef2f0 Kostas Papadimitriou
        unavailable_values_for_image: function(img, flavors) {
1934 820ef2f0 Kostas Papadimitriou
            var flavors = flavors || this.active();
1935 820ef2f0 Kostas Papadimitriou
            var size = img.get_size();
1936 820ef2f0 Kostas Papadimitriou
            
1937 820ef2f0 Kostas Papadimitriou
            var index = {cpu:[], disk:[], ram:[]};
1938 820ef2f0 Kostas Papadimitriou
1939 820ef2f0 Kostas Papadimitriou
            _.each(this.active(), function(el) {
1940 820ef2f0 Kostas Papadimitriou
                var img_size = size;
1941 820ef2f0 Kostas Papadimitriou
                var flv_size = el.get_disk_size();
1942 820ef2f0 Kostas Papadimitriou
                if (flv_size < img_size) {
1943 820ef2f0 Kostas Papadimitriou
                    if (index.disk.indexOf(flv_size) == -1) {
1944 820ef2f0 Kostas Papadimitriou
                        index.disk.push(flv_size);
1945 820ef2f0 Kostas Papadimitriou
                    }
1946 820ef2f0 Kostas Papadimitriou
                };
1947 820ef2f0 Kostas Papadimitriou
            });
1948 820ef2f0 Kostas Papadimitriou
            
1949 820ef2f0 Kostas Papadimitriou
            return index;
1950 8d08f18a Kostas Papadimitriou
        },
1951 820ef2f0 Kostas Papadimitriou
1952 d965e6dc Kostas Papadimitriou
        get_flavor: function(cpu, mem, disk, disk_template, filter_list) {
1953 8d08f18a Kostas Papadimitriou
            if (!filter_list) { filter_list = this.models };
1954 d965e6dc Kostas Papadimitriou
            
1955 8d08f18a Kostas Papadimitriou
            return this.select(function(flv){
1956 8d08f18a Kostas Papadimitriou
                if (flv.get("cpu") == cpu + "" &&
1957 8d08f18a Kostas Papadimitriou
                   flv.get("ram") == mem + "" &&
1958 8d08f18a Kostas Papadimitriou
                   flv.get("disk") == disk + "" &&
1959 d965e6dc Kostas Papadimitriou
                   flv.get("disk_template") == disk_template &&
1960 820ef2f0 Kostas Papadimitriou
                   filter_list.indexOf(flv) > -1) { return true; }
1961 9ce969a7 Kostas Papadimitriou
            })[0];
1962 8d08f18a Kostas Papadimitriou
        },
1963 820ef2f0 Kostas Papadimitriou
        
1964 8d08f18a Kostas Papadimitriou
        get_data: function(lst) {
1965 8d08f18a Kostas Papadimitriou
            var data = {'cpu': [], 'mem':[], 'disk':[]};
1966 820ef2f0 Kostas Papadimitriou
1967 8d08f18a Kostas Papadimitriou
            _.each(lst, function(flv) {
1968 820ef2f0 Kostas Papadimitriou
                if (data.cpu.indexOf(flv.get("cpu")) == -1) {
1969 820ef2f0 Kostas Papadimitriou
                    data.cpu.push(flv.get("cpu"));
1970 8d08f18a Kostas Papadimitriou
                }
1971 820ef2f0 Kostas Papadimitriou
                if (data.mem.indexOf(flv.get("ram")) == -1) {
1972 820ef2f0 Kostas Papadimitriou
                    data.mem.push(flv.get("ram"));
1973 8d08f18a Kostas Papadimitriou
                }
1974 820ef2f0 Kostas Papadimitriou
                if (data.disk.indexOf(flv.get("disk")) == -1) {
1975 820ef2f0 Kostas Papadimitriou
                    data.disk.push(flv.get("disk"));
1976 8d08f18a Kostas Papadimitriou
                }
1977 8d08f18a Kostas Papadimitriou
            })
1978 820ef2f0 Kostas Papadimitriou
            
1979 8d08f18a Kostas Papadimitriou
            return data;
1980 bedfe884 Kostas Papadimitriou
        },
1981 bedfe884 Kostas Papadimitriou
1982 bedfe884 Kostas Papadimitriou
        active: function() {
1983 bedfe884 Kostas Papadimitriou
            return this.filter(function(flv){return flv.get('status') != "DELETED"});
1984 8d08f18a Kostas Papadimitriou
        }
1985 8d08f18a Kostas Papadimitriou
            
1986 8d08f18a Kostas Papadimitriou
    })
1987 8d08f18a Kostas Papadimitriou
1988 8d08f18a Kostas Papadimitriou
    models.VMS = models.Collection.extend({
1989 8d08f18a Kostas Papadimitriou
        model: models.VM,
1990 8d08f18a Kostas Papadimitriou
        path: 'servers',
1991 8d08f18a Kostas Papadimitriou
        details: true,
1992 8d08f18a Kostas Papadimitriou
        copy_image_meta: true,
1993 126a01f2 Kostas Papadimitriou
1994 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1995 8d08f18a Kostas Papadimitriou
            var data = resp;
1996 8d08f18a Kostas Papadimitriou
            if (!resp) { return [] };
1997 820ef2f0 Kostas Papadimitriou
            data = _.filter(_.map(resp.servers.values, _.bind(this.parse_vm_api_data, this)), function(v){return v});
1998 8d08f18a Kostas Papadimitriou
            return data;
1999 8d08f18a Kostas Papadimitriou
        },
2000 126a01f2 Kostas Papadimitriou
2001 1e882dd7 Kostas Papadimitriou
        parse_vm_api_data: function(data) {
2002 1e882dd7 Kostas Papadimitriou
            // do not add non existing DELETED entries
2003 1e882dd7 Kostas Papadimitriou
            if (data.status && data.status == "DELETED") {
2004 1e882dd7 Kostas Papadimitriou
                if (!this.get(data.id)) {
2005 1e882dd7 Kostas Papadimitriou
                    return false;
2006 1e882dd7 Kostas Papadimitriou
                }
2007 1e882dd7 Kostas Papadimitriou
            }
2008 1e882dd7 Kostas Papadimitriou
2009 1e882dd7 Kostas Papadimitriou
            // OS attribute
2010 1e882dd7 Kostas Papadimitriou
            if (this.has_meta(data)) {
2011 1e882dd7 Kostas Papadimitriou
                data['OS'] = data.metadata.values.OS || "okeanos";
2012 1e882dd7 Kostas Papadimitriou
            }
2013 1e882dd7 Kostas Papadimitriou
            
2014 1e882dd7 Kostas Papadimitriou
            if (!data.diagnostics) {
2015 1e882dd7 Kostas Papadimitriou
                data.diagnostics = [];
2016 1e882dd7 Kostas Papadimitriou
            }
2017 1e882dd7 Kostas Papadimitriou
2018 1e882dd7 Kostas Papadimitriou
            // network metadata
2019 1e882dd7 Kostas Papadimitriou
            data['firewalls'] = {};
2020 1e882dd7 Kostas Papadimitriou
            data['nics'] = {};
2021 1e882dd7 Kostas Papadimitriou
            data['linked_to'] = [];
2022 1e882dd7 Kostas Papadimitriou
2023 1e882dd7 Kostas Papadimitriou
            if (data['attachments'] && data['attachments'].values) {
2024 1e882dd7 Kostas Papadimitriou
                var nics = data['attachments'].values;
2025 1e882dd7 Kostas Papadimitriou
                _.each(nics, function(nic) {
2026 1e882dd7 Kostas Papadimitriou
                    var net_id = nic.network_id;
2027 1e882dd7 Kostas Papadimitriou
                    var index = parseInt(NIC_REGEX.exec(nic.id)[2]);
2028 1e882dd7 Kostas Papadimitriou
                    if (data['linked_to'].indexOf(net_id) == -1) {
2029 1e882dd7 Kostas Papadimitriou
                        data['linked_to'].push(net_id);
2030 1e882dd7 Kostas Papadimitriou
                    }
2031 1e882dd7 Kostas Papadimitriou
2032 1e882dd7 Kostas Papadimitriou
                    data['nics'][nic.id] = nic;
2033 1e882dd7 Kostas Papadimitriou
                })
2034 1e882dd7 Kostas Papadimitriou
            }
2035 1e882dd7 Kostas Papadimitriou
            
2036 1e882dd7 Kostas Papadimitriou
            // if vm has no metadata, no metadata object
2037 1e882dd7 Kostas Papadimitriou
            // is in json response, reset it to force
2038 1e882dd7 Kostas Papadimitriou
            // value update
2039 1e882dd7 Kostas Papadimitriou
            if (!data['metadata']) {
2040 1e882dd7 Kostas Papadimitriou
                data['metadata'] = {values:{}};
2041 1e882dd7 Kostas Papadimitriou
            }
2042 1e882dd7 Kostas Papadimitriou
2043 1e882dd7 Kostas Papadimitriou
            return data;
2044 1e882dd7 Kostas Papadimitriou
        },
2045 1e882dd7 Kostas Papadimitriou
2046 126a01f2 Kostas Papadimitriou
        add: function() {
2047 126a01f2 Kostas Papadimitriou
            ret = models.VMS.__super__.add.apply(this, arguments);
2048 126a01f2 Kostas Papadimitriou
            ret.each(function(r){
2049 126a01f2 Kostas Papadimitriou
                synnefo.storage.nics.update_vm_nics(r);
2050 126a01f2 Kostas Papadimitriou
            });
2051 126a01f2 Kostas Papadimitriou
        },
2052 122850c5 Kostas Papadimitriou
        
2053 122850c5 Kostas Papadimitriou
        get_reboot_required: function() {
2054 122850c5 Kostas Papadimitriou
            return this.filter(function(vm){return vm.get("reboot_required") == true})
2055 122850c5 Kostas Papadimitriou
        },
2056 122850c5 Kostas Papadimitriou
2057 122850c5 Kostas Papadimitriou
        has_pending_actions: function() {
2058 122850c5 Kostas Papadimitriou
            return this.filter(function(vm){return vm.pending_action}).length > 0;
2059 122850c5 Kostas Papadimitriou
        },
2060 8d08f18a Kostas Papadimitriou
2061 8d08f18a Kostas Papadimitriou
        reset_pending_actions: function() {
2062 8d08f18a Kostas Papadimitriou
            this.each(function(vm) {
2063 8d08f18a Kostas Papadimitriou
                vm.clear_pending_action();
2064 8d08f18a Kostas Papadimitriou
            })
2065 8d08f18a Kostas Papadimitriou
        },
2066 101e6604 Kostas Papadimitriou
2067 101e6604 Kostas Papadimitriou
        do_all_pending_actions: function(success, error) {
2068 101e6604 Kostas Papadimitriou
            this.each(function(vm) {
2069 101e6604 Kostas Papadimitriou
                if (vm.has_pending_action()) {
2070 101e6604 Kostas Papadimitriou
                    vm.call(vm.pending_action, success, error);
2071 101e6604 Kostas Papadimitriou
                    vm.clear_pending_action();
2072 101e6604 Kostas Papadimitriou
                }
2073 101e6604 Kostas Papadimitriou
            })
2074 101e6604 Kostas Papadimitriou
        },
2075 101e6604 Kostas Papadimitriou
        
2076 101e6604 Kostas Papadimitriou
        do_all_reboots: function(success, error) {
2077 101e6604 Kostas Papadimitriou
            this.each(function(vm) {
2078 101e6604 Kostas Papadimitriou
                if (vm.get("reboot_required")) {
2079 101e6604 Kostas Papadimitriou
                    vm.call("reboot", success, error);
2080 101e6604 Kostas Papadimitriou
                }
2081 101e6604 Kostas Papadimitriou
            });
2082 101e6604 Kostas Papadimitriou
        },
2083 101e6604 Kostas Papadimitriou
2084 101e6604 Kostas Papadimitriou
        reset_reboot_required: function() {
2085 101e6604 Kostas Papadimitriou
            this.each(function(vm) {
2086 101e6604 Kostas Papadimitriou
                vm.set({'reboot_required': undefined});
2087 101e6604 Kostas Papadimitriou
            })
2088 101e6604 Kostas Papadimitriou
        },
2089 2c9bfad1 Kostas Papadimitriou
        
2090 2c9bfad1 Kostas Papadimitriou
        stop_stats_update: function(exclude) {
2091 2c9bfad1 Kostas Papadimitriou
            var exclude = exclude || [];
2092 96d725ac Kostas Papadimitriou
            this.each(function(vm) {
2093 2c9bfad1 Kostas Papadimitriou
                if (exclude.indexOf(vm) > -1) {
2094 2c9bfad1 Kostas Papadimitriou
                    return;
2095 2c9bfad1 Kostas Papadimitriou
                }
2096 2c9bfad1 Kostas Papadimitriou
                vm.stop_stats_update();
2097 96d725ac Kostas Papadimitriou
            })
2098 96d725ac Kostas Papadimitriou
        },
2099 8d08f18a Kostas Papadimitriou
        
2100 8d08f18a Kostas Papadimitriou
        has_meta: function(vm_data) {
2101 8d08f18a Kostas Papadimitriou
            return vm_data.metadata && vm_data.metadata.values
2102 8d08f18a Kostas Papadimitriou
        },
2103 8d08f18a Kostas Papadimitriou
2104 8d08f18a Kostas Papadimitriou
        has_addresses: function(vm_data) {
2105 8d08f18a Kostas Papadimitriou
            return vm_data.metadata && vm_data.metadata.values
2106 8d08f18a Kostas Papadimitriou
        },
2107 8d08f18a Kostas Papadimitriou
2108 8d08f18a Kostas Papadimitriou
        create: function (name, image, flavor, meta, extra, callback) {
2109 88d6d677 Kostas Papadimitriou
2110 8d08f18a Kostas Papadimitriou
            if (this.copy_image_meta) {
2111 88d6d677 Kostas Papadimitriou
                if (synnefo.config.vm_image_common_metadata) {
2112 88d6d677 Kostas Papadimitriou
                    _.each(synnefo.config.vm_image_common_metadata, 
2113 88d6d677 Kostas Papadimitriou
                        function(key){
2114 88d6d677 Kostas Papadimitriou
                            if (image.get_meta(key)) {
2115 88d6d677 Kostas Papadimitriou
                                meta[key] = image.get_meta(key);
2116 88d6d677 Kostas Papadimitriou
                            }
2117 88d6d677 Kostas Papadimitriou
                    });
2118 88d6d677 Kostas Papadimitriou
                }
2119 88d6d677 Kostas Papadimitriou
2120 d5ba5588 Kostas Papadimitriou
                if (image.get("OS")) {
2121 d5ba5588 Kostas Papadimitriou
                    meta['OS'] = image.get("OS");
2122 d5ba5588 Kostas Papadimitriou
                }
2123 88d6d677 Kostas Papadimitriou
            }
2124 8d08f18a Kostas Papadimitriou
            
2125 426e1fb9 Kostas Papadimitriou
            opts = {name: name, imageRef: image.id, flavorRef: flavor.id, 
2126 426e1fb9 Kostas Papadimitriou
                    metadata:meta}
2127 8d08f18a Kostas Papadimitriou
            opts = _.extend(opts, extra);
2128 b14e3b9e Kostas Papadimitriou
            
2129 ee5d26fc Kostas Papadimitriou
            var cb = function(data) {
2130 426e1fb9 Kostas Papadimitriou
              synnefo.storage.quotas.get('cyclades.vm').increase();
2131 ee5d26fc Kostas Papadimitriou
              callback(data);
2132 b14e3b9e Kostas Papadimitriou
            }
2133 8d08f18a Kostas Papadimitriou
2134 426e1fb9 Kostas Papadimitriou
            this.api_call(this.path, "create", {'server': opts}, undefined, 
2135 426e1fb9 Kostas Papadimitriou
                          undefined, cb, {critical: true});
2136 336ddd59 Kostas Papadimitriou
        },
2137 336ddd59 Kostas Papadimitriou
2138 336ddd59 Kostas Papadimitriou
        load_missing_images: function(callback) {
2139 336ddd59 Kostas Papadimitriou
          var missing_ids = [];
2140 336ddd59 Kostas Papadimitriou
          this.each(function(el) {
2141 336ddd59 Kostas Papadimitriou
            var imgid = el.get("imageRef");
2142 336ddd59 Kostas Papadimitriou
            var existing = synnefo.storage.images.get(imgid);
2143 336ddd59 Kostas Papadimitriou
            if (!existing && missing_ids.indexOf(imgid) == -1) {
2144 336ddd59 Kostas Papadimitriou
                missing_ids.push(imgid);
2145 336ddd59 Kostas Papadimitriou
                synnefo.storage.images.update_unknown_id(imgid, function(){});
2146 336ddd59 Kostas Papadimitriou
            }
2147 336ddd59 Kostas Papadimitriou
          });
2148 336ddd59 Kostas Papadimitriou
          callback(missing_ids);
2149 8d08f18a Kostas Papadimitriou
        }
2150 8d08f18a Kostas Papadimitriou
2151 8d08f18a Kostas Papadimitriou
    })
2152 126a01f2 Kostas Papadimitriou
    
2153 126a01f2 Kostas Papadimitriou
    models.NIC = models.Model.extend({
2154 126a01f2 Kostas Papadimitriou
        
2155 126a01f2 Kostas Papadimitriou
        initialize: function() {
2156 126a01f2 Kostas Papadimitriou
            models.NIC.__super__.initialize.apply(this, arguments);
2157 126a01f2 Kostas Papadimitriou
            this.pending_for_firewall = false;
2158 126a01f2 Kostas Papadimitriou
            this.bind("change:firewallProfile", _.bind(this.check_firewall, this));
2159 126a01f2 Kostas Papadimitriou
            this.bind("change:pending_firewall", function(nic) {
2160 126a01f2 Kostas Papadimitriou
                nic.get_network().update_state();
2161 126a01f2 Kostas Papadimitriou
            });
2162 126a01f2 Kostas Papadimitriou
            this.get_vm().bind("remove", function(){
2163 97d3fca1 Kostas Papadimitriou
                try {
2164 97d3fca1 Kostas Papadimitriou
                    this.collection.remove(this);
2165 97d3fca1 Kostas Papadimitriou
                } catch (err) {};
2166 126a01f2 Kostas Papadimitriou
            }, this);
2167 126a01f2 Kostas Papadimitriou
            this.get_network().bind("remove", function(){
2168 126a01f2 Kostas Papadimitriou
                try {
2169 126a01f2 Kostas Papadimitriou
                    this.collection.remove(this);
2170 126a01f2 Kostas Papadimitriou
                } catch (err) {};
2171 126a01f2 Kostas Papadimitriou
            }, this);
2172 e49565e1 Kostas Papadimitriou
2173 126a01f2 Kostas Papadimitriou
        },
2174 126a01f2 Kostas Papadimitriou
2175 126a01f2 Kostas Papadimitriou
        get_vm: function() {
2176 126a01f2 Kostas Papadimitriou
            return synnefo.storage.vms.get(parseInt(this.get('vm_id')));
2177 126a01f2 Kostas Papadimitriou
        },
2178 126a01f2 Kostas Papadimitriou
2179 126a01f2 Kostas Papadimitriou
        get_network: function() {
2180 126a01f2 Kostas Papadimitriou
            return synnefo.storage.networks.get(this.get('network_id'));
2181 126a01f2 Kostas Papadimitriou
        },
2182 126a01f2 Kostas Papadimitriou
2183 126a01f2 Kostas Papadimitriou
        get_v6_address: function() {
2184 126a01f2 Kostas Papadimitriou
            return this.get("ipv6");
2185 126a01f2 Kostas Papadimitriou
        },
2186 126a01f2 Kostas Papadimitriou
2187 126a01f2 Kostas Papadimitriou
        get_v4_address: function() {
2188 126a01f2 Kostas Papadimitriou
            return this.get("ipv4");
2189 126a01f2 Kostas Papadimitriou
        },
2190 126a01f2 Kostas Papadimitriou
2191 126a01f2 Kostas Papadimitriou
        set_firewall: function(value, callback, error, options) {
2192 126a01f2 Kostas Papadimitriou
            var net_id = this.get('network_id');
2193 126a01f2 Kostas Papadimitriou
            var self = this;
2194 126a01f2 Kostas Papadimitriou
2195 126a01f2 Kostas Papadimitriou
            // api call data
2196 126a01f2 Kostas Papadimitriou
            var payload = {"firewallProfile":{"profile":value}};
2197 126a01f2 Kostas Papadimitriou
            payload._options = _.extend({critical: false}, options);
2198 126a01f2 Kostas Papadimitriou
            
2199 126a01f2 Kostas Papadimitriou
            this.set({'pending_firewall': value});
2200 126a01f2 Kostas Papadimitriou
            this.set({'pending_firewall_sending': true});
2201 4792afbe Kostas Papadimitriou
            this.set({'pending_firewall_from': this.get('firewallProfile')});
2202 126a01f2 Kostas Papadimitriou
2203 126a01f2 Kostas Papadimitriou
            var success_cb = function() {
2204 126a01f2 Kostas Papadimitriou
                if (callback) {
2205 126a01f2 Kostas Papadimitriou
                    callback();
2206 126a01f2 Kostas Papadimitriou
                }
2207 126a01f2 Kostas Papadimitriou
                self.set({'pending_firewall_sending': false});
2208 126a01f2 Kostas Papadimitriou
            };
2209 126a01f2 Kostas Papadimitriou
2210 126a01f2 Kostas Papadimitriou
            var error_cb = function() {
2211 126a01f2 Kostas Papadimitriou
                self.reset_pending_firewall();
2212 126a01f2 Kostas Papadimitriou
            }
2213 126a01f2 Kostas Papadimitriou
            
2214 126a01f2 Kostas Papadimitriou
            this.get_vm().api_call(this.get_vm().api_path() + "/action", "create", payload, success_cb, error_cb);
2215 126a01f2 Kostas Papadimitriou
        },
2216 126a01f2 Kostas Papadimitriou
2217 126a01f2 Kostas Papadimitriou
        reset_pending_firewall: function() {
2218 126a01f2 Kostas Papadimitriou
            this.set({'pending_firewall': false});
2219 4792afbe Kostas Papadimitriou
            this.set({'pending_firewall': false});
2220 126a01f2 Kostas Papadimitriou
        },
2221 126a01f2 Kostas Papadimitriou
2222 126a01f2 Kostas Papadimitriou
        check_firewall: function() {
2223 126a01f2 Kostas Papadimitriou
            var firewall = this.get('firewallProfile');
2224 126a01f2 Kostas Papadimitriou
            var pending = this.get('pending_firewall');
2225 4792afbe Kostas Papadimitriou
            var previous = this.get('pending_firewall_from');
2226 4792afbe Kostas Papadimitriou
            if (previous != firewall) { this.get_vm().require_reboot() };
2227 126a01f2 Kostas Papadimitriou
            this.reset_pending_firewall();
2228 126a01f2 Kostas Papadimitriou
        }
2229 126a01f2 Kostas Papadimitriou
        
2230 126a01f2 Kostas Papadimitriou
    });
2231 126a01f2 Kostas Papadimitriou
2232 126a01f2 Kostas Papadimitriou
    models.NICs = models.Collection.extend({
2233 126a01f2 Kostas Papadimitriou
        model: models.NIC,
2234 126a01f2 Kostas Papadimitriou
        
2235 126a01f2 Kostas Papadimitriou
        add_or_update: function(nic_id, data, vm) {
2236 126a01f2 Kostas Papadimitriou
            var params = _.clone(data);
2237 e49565e1 Kostas Papadimitriou
            var vm;
2238 126a01f2 Kostas Papadimitriou
            params.attachment_id = params.id;
2239 126a01f2 Kostas Papadimitriou
            params.id = params.id + '-' + params.network_id;
2240 126a01f2 Kostas Papadimitriou
            params.vm_id = parseInt(NIC_REGEX.exec(nic_id)[1]);
2241 126a01f2 Kostas Papadimitriou
2242 126a01f2 Kostas Papadimitriou
            if (!this.get(params.id)) {
2243 126a01f2 Kostas Papadimitriou
                this.add(params);
2244 126a01f2 Kostas Papadimitriou
                var nic = this.get(params.id);
2245 e49565e1 Kostas Papadimitriou
                vm = nic.get_vm();
2246 126a01f2 Kostas Papadimitriou
                nic.get_network().decrease_connecting();
2247 126a01f2 Kostas Papadimitriou
                nic.bind("remove", function() {
2248 126a01f2 Kostas Papadimitriou
                    nic.set({"removing": 0});
2249 126a01f2 Kostas Papadimitriou
                    if (this.get_network()) {
2250 126a01f2 Kostas Papadimitriou
                        // network might got removed before nic
2251 126a01f2 Kostas Papadimitriou
                        nic.get_network().update_state();
2252 126a01f2 Kostas Papadimitriou
                    }
2253 e49565e1 Kostas Papadimitriou
                });
2254 e49565e1 Kostas Papadimitriou
2255 126a01f2 Kostas Papadimitriou
            } else {
2256 126a01f2 Kostas Papadimitriou
                this.get(params.id).set(params);
2257 e49565e1 Kostas Papadimitriou
                vm = this.get(params.id).get_vm();
2258 126a01f2 Kostas Papadimitriou
            }
2259 e49565e1 Kostas Papadimitriou
            
2260 e49565e1 Kostas Papadimitriou
            // vm nics changed, trigger vm update
2261 e49565e1 Kostas Papadimitriou
            if (vm) { vm.trigger("change", vm)};
2262 126a01f2 Kostas Papadimitriou
        },
2263 126a01f2 Kostas Papadimitriou
        
2264 126a01f2 Kostas Papadimitriou
        reset_nics: function(nics, filter_attr, filter_val) {
2265 126a01f2 Kostas Papadimitriou
            var nics_to_check = this.filter(function(nic) {
2266 126a01f2 Kostas Papadimitriou
                return nic.get(filter_attr) == filter_val;
2267 126a01f2 Kostas Papadimitriou
            });
2268 126a01f2 Kostas Papadimitriou
            
2269 126a01f2 Kostas Papadimitriou
            _.each(nics_to_check, function(nic) {
2270 126a01f2 Kostas Papadimitriou
                if (nics.indexOf(nic.get('id')) == -1) {
2271 126a01f2 Kostas Papadimitriou
                    this.remove(nic);
2272 126a01f2 Kostas Papadimitriou
                } else {
2273 126a01f2 Kostas Papadimitriou
                }
2274 126a01f2 Kostas Papadimitriou
            }, this);
2275 126a01f2 Kostas Papadimitriou
        },
2276 126a01f2 Kostas Papadimitriou
2277 126a01f2 Kostas Papadimitriou
        update_vm_nics: function(vm) {
2278 126a01f2 Kostas Papadimitriou
            var nics = vm.get('nics');
2279 126a01f2 Kostas Papadimitriou
            this.reset_nics(_.map(nics, function(nic, key){
2280 126a01f2 Kostas Papadimitriou
                return key + "-" + nic.network_id;
2281 126a01f2 Kostas Papadimitriou
            }), 'vm_id', vm.id);
2282 126a01f2 Kostas Papadimitriou
2283 126a01f2 Kostas Papadimitriou
            _.each(nics, function(val, key) {
2284 126a01f2 Kostas Papadimitriou
                var net = synnefo.storage.networks.get(val.network_id);
2285 126a01f2 Kostas Papadimitriou
                if (net && net.connected_with_nic_id(key) && vm.connected_with_nic_id(key)) {
2286 126a01f2 Kostas Papadimitriou
                    this.add_or_update(key, vm.get('nics')[key], vm);
2287 126a01f2 Kostas Papadimitriou
                }
2288 126a01f2 Kostas Papadimitriou
            }, this);
2289 126a01f2 Kostas Papadimitriou
        },
2290 126a01f2 Kostas Papadimitriou
2291 126a01f2 Kostas Papadimitriou
        update_net_nics: function(net) {
2292 126a01f2 Kostas Papadimitriou
            var nics = net.get('nics');
2293 126a01f2 Kostas Papadimitriou
            this.reset_nics(_.map(nics, function(nic, key){
2294 126a01f2 Kostas Papadimitriou
                return key + "-" + net.get('id');
2295 126a01f2 Kostas Papadimitriou
            }), 'network_id', net.id);
2296 126a01f2 Kostas Papadimitriou
2297 126a01f2 Kostas Papadimitriou
            _.each(nics, function(val, key) {
2298 126a01f2 Kostas Papadimitriou
                var vm = synnefo.storage.vms.get(val.vm_id);
2299 126a01f2 Kostas Papadimitriou
                if (vm && net.connected_with_nic_id(key) && vm.connected_with_nic_id(key)) {
2300 126a01f2 Kostas Papadimitriou
                    this.add_or_update(key, vm.get('nics')[key], vm);
2301 126a01f2 Kostas Papadimitriou
                }
2302 126a01f2 Kostas Papadimitriou
            }, this);
2303 126a01f2 Kostas Papadimitriou
        }
2304 126a01f2 Kostas Papadimitriou
    });
2305 c4fff449 Kostas Papadimitriou
2306 c4fff449 Kostas Papadimitriou
    models.PublicKey = models.Model.extend({
2307 859a4609 Kostas Papadimitriou
        path: 'keys',
2308 859a4609 Kostas Papadimitriou
        base_url: '/ui/userdata',
2309 859a4609 Kostas Papadimitriou
        details: false,
2310 859a4609 Kostas Papadimitriou
        noUpdate: true,
2311 859a4609 Kostas Papadimitriou
2312 859a4609 Kostas Papadimitriou
2313 859a4609 Kostas Papadimitriou
        get_public_key: function() {
2314 859a4609 Kostas Papadimitriou
            return cryptico.publicKeyFromString(this.get("content"));
2315 859a4609 Kostas Papadimitriou
        },
2316 859a4609 Kostas Papadimitriou
2317 859a4609 Kostas Papadimitriou
        get_filename: function() {
2318 859a4609 Kostas Papadimitriou
            return "{0}.pub".format(this.get("name"));
2319 859a4609 Kostas Papadimitriou
        },
2320 859a4609 Kostas Papadimitriou
2321 859a4609 Kostas Papadimitriou
        identify_type: function() {
2322 859a4609 Kostas Papadimitriou
            try {
2323 859a4609 Kostas Papadimitriou
                var cont = snf.util.validatePublicKey(this.get("content"));
2324 859a4609 Kostas Papadimitriou
                var type = cont.split(" ")[0];
2325 859a4609 Kostas Papadimitriou
                return synnefo.util.publicKeyTypesMap[type];
2326 859a4609 Kostas Papadimitriou
            } catch (err) { return false };
2327 859a4609 Kostas Papadimitriou
        }
2328 859a4609 Kostas Papadimitriou
2329 c4fff449 Kostas Papadimitriou
    })
2330 c4fff449 Kostas Papadimitriou
    
2331 c4fff449 Kostas Papadimitriou
    models.PublicKeys = models.Collection.extend({
2332 859a4609 Kostas Papadimitriou
        model: models.PublicKey,
2333 859a4609 Kostas Papadimitriou
        details: false,
2334 859a4609 Kostas Papadimitriou
        path: 'keys',
2335 859a4609 Kostas Papadimitriou
        base_url: '/ui/userdata',
2336 859a4609 Kostas Papadimitriou
        noUpdate: true,
2337 859a4609 Kostas Papadimitriou
2338 556dcd88 Kostas Papadimitriou
        generate_new: function(success, error) {
2339 386481eb Kostas Papadimitriou
            snf.api.sync('create', undefined, {
2340 556dcd88 Kostas Papadimitriou
                url: getUrl.call(this, this.base_url) + "/generate", 
2341 556dcd88 Kostas Papadimitriou
                success: success, 
2342 556dcd88 Kostas Papadimitriou
                error: error,
2343 556dcd88 Kostas Papadimitriou
                skip_api_error: true
2344 556dcd88 Kostas Papadimitriou
            });
2345 859a4609 Kostas Papadimitriou
        },
2346 859a4609 Kostas Papadimitriou
2347 859a4609 Kostas Papadimitriou
        add_crypto_key: function(key, success, error, options) {
2348 859a4609 Kostas Papadimitriou
            var options = options || {};
2349 859a4609 Kostas Papadimitriou
            var m = new models.PublicKey();
2350 556dcd88 Kostas Papadimitriou
2351 556dcd88 Kostas Papadimitriou
            // guess a name
2352 1efe6159 Kostas Papadimitriou
            var name_tpl = "my generated public key";
2353 859a4609 Kostas Papadimitriou
            var name = name_tpl;
2354 859a4609 Kostas Papadimitriou
            var name_count = 1;
2355 859a4609 Kostas Papadimitriou
            
2356 859a4609 Kostas Papadimitriou
            while(this.filter(function(m){ return m.get("name") == name }).length > 0) {
2357 859a4609 Kostas Papadimitriou
                name = name_tpl + " " + name_count;
2358 859a4609 Kostas Papadimitriou
                name_count++;
2359 859a4609 Kostas Papadimitriou
            }
2360 556dcd88 Kostas Papadimitriou
            
2361 859a4609 Kostas Papadimitriou
            m.set({name: name});
2362 556dcd88 Kostas Papadimitriou
            m.set({content: key});
2363 859a4609 Kostas Papadimitriou
            
2364 859a4609 Kostas Papadimitriou
            options.success = function () { return success(m) };
2365 859a4609 Kostas Papadimitriou
            options.errror = error;
2366 c72a830d Kostas Papadimitriou
            options.skip_api_error = true;
2367 859a4609 Kostas Papadimitriou
            
2368 859a4609 Kostas Papadimitriou
            this.create(m.attributes, options);
2369 859a4609 Kostas Papadimitriou
        }
2370 426e1fb9 Kostas Papadimitriou
    });
2371 426e1fb9 Kostas Papadimitriou
2372 426e1fb9 Kostas Papadimitriou
  
2373 426e1fb9 Kostas Papadimitriou
    models.Quota = models.Model.extend({
2374 426e1fb9 Kostas Papadimitriou
2375 426e1fb9 Kostas Papadimitriou
        initialize: function() {
2376 426e1fb9 Kostas Papadimitriou
            models.Quota.__super__.initialize.apply(this, arguments);
2377 426e1fb9 Kostas Papadimitriou
            this.bind("change", this.check, this);
2378 426e1fb9 Kostas Papadimitriou
            this.check();
2379 426e1fb9 Kostas Papadimitriou
        },
2380 426e1fb9 Kostas Papadimitriou
        
2381 426e1fb9 Kostas Papadimitriou
        check: function() {
2382 426e1fb9 Kostas Papadimitriou
            var usage, limit;
2383 426e1fb9 Kostas Papadimitriou
            usage = this.get('usage');
2384 426e1fb9 Kostas Papadimitriou
            limit = this.get('limit');
2385 426e1fb9 Kostas Papadimitriou
            if (usage >= limit) {
2386 426e1fb9 Kostas Papadimitriou
                this.trigger("available");
2387 426e1fb9 Kostas Papadimitriou
            } else {
2388 426e1fb9 Kostas Papadimitriou
                this.trigger("unavailable");
2389 426e1fb9 Kostas Papadimitriou
            }
2390 426e1fb9 Kostas Papadimitriou
        },
2391 426e1fb9 Kostas Papadimitriou
2392 426e1fb9 Kostas Papadimitriou
        increase: function(val) {
2393 426e1fb9 Kostas Papadimitriou
            if (val === undefined) { val = 1};
2394 426e1fb9 Kostas Papadimitriou
            this.set({'usage': this.get('usage') + val})
2395 426e1fb9 Kostas Papadimitriou
        },
2396 426e1fb9 Kostas Papadimitriou
2397 426e1fb9 Kostas Papadimitriou
        decrease: function(val) {
2398 426e1fb9 Kostas Papadimitriou
            if (val === undefined) { val = 1};
2399 426e1fb9 Kostas Papadimitriou
            this.set({'usage': this.get('usage') - val})
2400 426e1fb9 Kostas Papadimitriou
        },
2401 426e1fb9 Kostas Papadimitriou
2402 426e1fb9 Kostas Papadimitriou
        can_consume: function() {
2403 426e1fb9 Kostas Papadimitriou
            var usage, limit;
2404 426e1fb9 Kostas Papadimitriou
            usage = this.get('usage');
2405 426e1fb9 Kostas Papadimitriou
            limit = this.get('limit');
2406 426e1fb9 Kostas Papadimitriou
            if (usage >= limit) {
2407 426e1fb9 Kostas Papadimitriou
                return false
2408 426e1fb9 Kostas Papadimitriou
            } else {
2409 426e1fb9 Kostas Papadimitriou
                return true
2410 426e1fb9 Kostas Papadimitriou
            }
2411 426e1fb9 Kostas Papadimitriou
        },
2412 426e1fb9 Kostas Papadimitriou
        
2413 426e1fb9 Kostas Papadimitriou
        is_bytes: function() {
2414 426e1fb9 Kostas Papadimitriou
            return this.get('resource').get('unit') == 'bytes';
2415 426e1fb9 Kostas Papadimitriou
        },
2416 426e1fb9 Kostas Papadimitriou
        
2417 426e1fb9 Kostas Papadimitriou
        get_available: function() {
2418 426e1fb9 Kostas Papadimitriou
            var value = this.get('limit') - this.get('usage');
2419 426e1fb9 Kostas Papadimitriou
            if (value < 0) { return value }
2420 426e1fb9 Kostas Papadimitriou
            return value
2421 426e1fb9 Kostas Papadimitriou
        },
2422 426e1fb9 Kostas Papadimitriou
2423 426e1fb9 Kostas Papadimitriou
        get_readable: function(key) {
2424 426e1fb9 Kostas Papadimitriou
            var value;
2425 426e1fb9 Kostas Papadimitriou
            if (key == 'available') {
2426 426e1fb9 Kostas Papadimitriou
                value = this.get_available();
2427 426e1fb9 Kostas Papadimitriou
            } else {
2428 426e1fb9 Kostas Papadimitriou
                value = this.get(key)
2429 426e1fb9 Kostas Papadimitriou
            }
2430 426e1fb9 Kostas Papadimitriou
            if (!this.is_bytes()) {
2431 426e1fb9 Kostas Papadimitriou
              return value + "";
2432 426e1fb9 Kostas Papadimitriou
            }
2433 426e1fb9 Kostas Papadimitriou
            return snf.util.readablizeBytes(value);
2434 426e1fb9 Kostas Papadimitriou
        }
2435 426e1fb9 Kostas Papadimitriou
    });
2436 426e1fb9 Kostas Papadimitriou
2437 426e1fb9 Kostas Papadimitriou
    models.Quotas = models.Collection.extend({
2438 426e1fb9 Kostas Papadimitriou
        model: models.Quota,
2439 426e1fb9 Kostas Papadimitriou
        api_type: 'accounts',
2440 426e1fb9 Kostas Papadimitriou
        path: 'quotas',
2441 426e1fb9 Kostas Papadimitriou
        parse: function(resp) {
2442 426e1fb9 Kostas Papadimitriou
            return _.map(resp.system, function(value, key) {
2443 426e1fb9 Kostas Papadimitriou
                var available = (value.limit - value.usage) || 0;
2444 426e1fb9 Kostas Papadimitriou
                return _.extend(value, {'name': key, 'id': key, 
2445 426e1fb9 Kostas Papadimitriou
                          'available': available,
2446 426e1fb9 Kostas Papadimitriou
                          'resource': snf.storage.resources.get(key)});
2447 426e1fb9 Kostas Papadimitriou
            })
2448 426e1fb9 Kostas Papadimitriou
        }
2449 c4fff449 Kostas Papadimitriou
    })
2450 426e1fb9 Kostas Papadimitriou
2451 426e1fb9 Kostas Papadimitriou
    models.Resource = models.Model.extend({
2452 426e1fb9 Kostas Papadimitriou
        api_type: 'accounts',
2453 426e1fb9 Kostas Papadimitriou
        path: 'resources'
2454 426e1fb9 Kostas Papadimitriou
    });
2455 426e1fb9 Kostas Papadimitriou
2456 426e1fb9 Kostas Papadimitriou
    models.Resources = models.Collection.extend({
2457 426e1fb9 Kostas Papadimitriou
        api_type: 'accounts',
2458 426e1fb9 Kostas Papadimitriou
        path: 'resources',
2459 426e1fb9 Kostas Papadimitriou
        model: models.Network,
2460 426e1fb9 Kostas Papadimitriou
2461 426e1fb9 Kostas Papadimitriou
        parse: function(resp) {
2462 426e1fb9 Kostas Papadimitriou
            return _.map(resp, function(value, key) {
2463 426e1fb9 Kostas Papadimitriou
                return _.extend(value, {'name': key, 'id': key});
2464 426e1fb9 Kostas Papadimitriou
            })
2465 426e1fb9 Kostas Papadimitriou
        }
2466 426e1fb9 Kostas Papadimitriou
    });
2467 8d08f18a Kostas Papadimitriou
    
2468 8d08f18a Kostas Papadimitriou
    // storage initialization
2469 8d08f18a Kostas Papadimitriou
    snf.storage.images = new models.Images();
2470 8d08f18a Kostas Papadimitriou
    snf.storage.flavors = new models.Flavors();
2471 8d08f18a Kostas Papadimitriou
    snf.storage.networks = new models.Networks();
2472 8d08f18a Kostas Papadimitriou
    snf.storage.vms = new models.VMS();
2473 c4fff449 Kostas Papadimitriou
    snf.storage.keys = new models.PublicKeys();
2474 126a01f2 Kostas Papadimitriou
    snf.storage.nics = new models.NICs();
2475 426e1fb9 Kostas Papadimitriou
    snf.storage.resources = new models.Resources();
2476 426e1fb9 Kostas Papadimitriou
    snf.storage.quotas = new models.Quotas();
2477 8d08f18a Kostas Papadimitriou
2478 8d08f18a Kostas Papadimitriou
})(this);