Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / static / snf / js / models.js @ 336ddd59

History | View | Annotate | Download (81.1 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 a429705e Kostas Papadimitriou
                }, this);
619 a429705e Kostas Papadimitriou
                var _error = _.bind(function() {
620 a429705e Kostas Papadimitriou
                    this.set({state: previous_state, status: previous_status})
621 a429705e Kostas Papadimitriou
                    if (error) { error() };
622 a429705e Kostas Papadimitriou
                }, this);
623 a429705e Kostas Papadimitriou
624 a429705e Kostas Papadimitriou
                this.remove(undefined, _error, _success);
625 101e6604 Kostas Papadimitriou
            }
626 101e6604 Kostas Papadimitriou
            
627 101e6604 Kostas Papadimitriou
            if (action == "disconnect") {
628 126a01f2 Kostas Papadimitriou
                if (this.get("state") == "DESTROY") {
629 126a01f2 Kostas Papadimitriou
                    return;
630 126a01f2 Kostas Papadimitriou
                }
631 a429705e Kostas Papadimitriou
                
632 126a01f2 Kostas Papadimitriou
                _.each(params, _.bind(function(nic_id) {
633 126a01f2 Kostas Papadimitriou
                    var nic = snf.storage.nics.get(nic_id);
634 126a01f2 Kostas Papadimitriou
                    this.get("actions").remove("disconnect", nic_id);
635 126a01f2 Kostas Papadimitriou
                    if (nic) {
636 126a01f2 Kostas Papadimitriou
                        this.remove_nic(nic, success, error);
637 101e6604 Kostas Papadimitriou
                    }
638 101e6604 Kostas Papadimitriou
                }, this));
639 101e6604 Kostas Papadimitriou
            }
640 101e6604 Kostas Papadimitriou
        },
641 8d08f18a Kostas Papadimitriou
642 9ce969a7 Kostas Papadimitriou
        add_vm: function (vm, callback, error, options) {
643 9ce969a7 Kostas Papadimitriou
            var payload = {add:{serverRef:"" + vm.id}};
644 9ce969a7 Kostas Papadimitriou
            payload._options = options || {};
645 258235f4 Kostas Papadimitriou
            return this.api_call(this.api_path() + "/action", "create", 
646 9ce969a7 Kostas Papadimitriou
                                 payload,
647 c6f9918c Kostas Papadimitriou
                                 undefined,
648 c6f9918c Kostas Papadimitriou
                                 error,
649 8d08f18a Kostas Papadimitriou
                                 _.bind(function(){
650 126a01f2 Kostas Papadimitriou
                                     //this.vms.add_pending(vm.id);
651 126a01f2 Kostas Papadimitriou
                                     this.increase_connecting();
652 8d08f18a Kostas Papadimitriou
                                     if (callback) {callback()}
653 9ce969a7 Kostas Papadimitriou
                                 },this), error);
654 8d08f18a Kostas Papadimitriou
        },
655 8d08f18a Kostas Papadimitriou
656 126a01f2 Kostas Papadimitriou
        remove_nic: function (nic, callback, error, options) {
657 126a01f2 Kostas Papadimitriou
            var payload = {remove:{attachment:"" + nic.get("attachment_id")}};
658 9ce969a7 Kostas Papadimitriou
            payload._options = options || {};
659 258235f4 Kostas Papadimitriou
            return this.api_call(this.api_path() + "/action", "create", 
660 126a01f2 Kostas Papadimitriou
                                 payload,
661 c6f9918c Kostas Papadimitriou
                                 undefined,
662 c6f9918c Kostas Papadimitriou
                                 error,
663 8d08f18a Kostas Papadimitriou
                                 _.bind(function(){
664 126a01f2 Kostas Papadimitriou
                                     nic.set({"removing": 1});
665 126a01f2 Kostas Papadimitriou
                                     nic.get_network().update_state();
666 126a01f2 Kostas Papadimitriou
                                     //this.vms.add_pending_for_remove(vm.id);
667 8d08f18a Kostas Papadimitriou
                                     if (callback) {callback()}
668 9ce969a7 Kostas Papadimitriou
                                 },this), error);
669 8d08f18a Kostas Papadimitriou
        },
670 8d08f18a Kostas Papadimitriou
671 8d08f18a Kostas Papadimitriou
        rename: function(name, callback) {
672 258235f4 Kostas Papadimitriou
            return this.api_call(this.api_path(), "update", {
673 9ffd10ce Kostas Papadimitriou
                network:{name:name}, 
674 9ffd10ce Kostas Papadimitriou
                _options:{
675 9ffd10ce Kostas Papadimitriou
                    critical: false, 
676 9ffd10ce Kostas Papadimitriou
                    error_params:{
677 9ffd10ce Kostas Papadimitriou
                        title: "Network action failed",
678 9ffd10ce Kostas Papadimitriou
                        ns: "Networks",
679 4dabb5cb Kostas Papadimitriou
                        extra_details: {"Network id": this.id}
680 9ffd10ce Kostas Papadimitriou
                    }
681 9ffd10ce Kostas Papadimitriou
                }}, callback);
682 8d08f18a Kostas Papadimitriou
        },
683 8d08f18a Kostas Papadimitriou
684 8d08f18a Kostas Papadimitriou
        get_connectable_vms: function() {
685 3162bebd Kostas Papadimitriou
            return storage.vms.filter(function(vm){
686 4792afbe Kostas Papadimitriou
                return !vm.in_error_state() && !vm.is_building();
687 3162bebd Kostas Papadimitriou
            })
688 8d08f18a Kostas Papadimitriou
        },
689 8d08f18a Kostas Papadimitriou
690 8d08f18a Kostas Papadimitriou
        state_message: function() {
691 126a01f2 Kostas Papadimitriou
            if (this.get("state") == "ACTIVE" && !this.is_public()) {
692 126a01f2 Kostas Papadimitriou
                if (this.get("cidr") && this.get("dhcp") == true) {
693 126a01f2 Kostas Papadimitriou
                    return this.get("cidr");
694 126a01f2 Kostas Papadimitriou
                } else {
695 126a01f2 Kostas Papadimitriou
                    return "Private network";
696 126a01f2 Kostas Papadimitriou
                }
697 126a01f2 Kostas Papadimitriou
            }
698 126a01f2 Kostas Papadimitriou
            if (this.get("state") == "ACTIVE" && this.is_public()) {
699 126a01f2 Kostas Papadimitriou
                  return "Public network";
700 8d08f18a Kostas Papadimitriou
            }
701 8d08f18a Kostas Papadimitriou
702 8d08f18a Kostas Papadimitriou
            return models.Network.STATES[this.get("state")];
703 8d08f18a Kostas Papadimitriou
        },
704 8d08f18a Kostas Papadimitriou
705 8d08f18a Kostas Papadimitriou
        in_progress: function() {
706 8d08f18a Kostas Papadimitriou
            return models.Network.STATES_TRANSITIONS[this.get("state")] != undefined;
707 101e6604 Kostas Papadimitriou
        },
708 101e6604 Kostas Papadimitriou
709 101e6604 Kostas Papadimitriou
        do_all_pending_actions: function(success, error) {
710 a429705e Kostas Papadimitriou
          var params, actions, action_params;
711 a429705e Kostas Papadimitriou
          actions = _.clone(this.get("actions").actions);
712 a429705e Kostas Papadimitriou
            _.each(actions, _.bind(function(params, action) {
713 a429705e Kostas Papadimitriou
                action_params = _.map(actions[action], function(a){ return _.clone(a)});
714 a429705e Kostas Papadimitriou
                _.each(action_params, _.bind(function(params) {
715 a429705e Kostas Papadimitriou
                    this.call(action, params, success, error);
716 101e6604 Kostas Papadimitriou
                }, this));
717 101e6604 Kostas Papadimitriou
            }, this));
718 126a01f2 Kostas Papadimitriou
            this.get("actions").reset();
719 8d08f18a Kostas Papadimitriou
        }
720 8d08f18a Kostas Papadimitriou
    });
721 8d08f18a Kostas Papadimitriou
    
722 8d08f18a Kostas Papadimitriou
    models.Network.STATES = {
723 126a01f2 Kostas Papadimitriou
        'ACTIVE': 'Private network',
724 8d08f18a Kostas Papadimitriou
        'CONNECTING': 'Connecting...',
725 8d08f18a Kostas Papadimitriou
        'DISCONNECTING': 'Disconnecting...',
726 25b225a5 Kostas Papadimitriou
        'FIREWALLING': 'Firewall update...',
727 126a01f2 Kostas Papadimitriou
        'DESTROY': 'Destroying...',
728 126a01f2 Kostas Papadimitriou
        'PENDING': 'Pending...',
729 126a01f2 Kostas Papadimitriou
        'ERROR': 'Error'
730 8d08f18a Kostas Papadimitriou
    }
731 8d08f18a Kostas Papadimitriou
732 8d08f18a Kostas Papadimitriou
    models.Network.STATES_TRANSITIONS = {
733 126a01f2 Kostas Papadimitriou
        'CONNECTING': ['ACTIVE'],
734 126a01f2 Kostas Papadimitriou
        'DISCONNECTING': ['ACTIVE'],
735 126a01f2 Kostas Papadimitriou
        'PENDING': ['ACTIVE'],
736 126a01f2 Kostas Papadimitriou
        'FIREWALLING': ['ACTIVE']
737 8d08f18a Kostas Papadimitriou
    }
738 8d08f18a Kostas Papadimitriou
739 8d08f18a Kostas Papadimitriou
    // Virtualmachine model
740 8d08f18a Kostas Papadimitriou
    models.VM = models.Model.extend({
741 8d08f18a Kostas Papadimitriou
742 8d08f18a Kostas Papadimitriou
        path: 'servers',
743 8d08f18a Kostas Papadimitriou
        has_status: true,
744 8d08f18a Kostas Papadimitriou
        initialize: function(params) {
745 8d08f18a Kostas Papadimitriou
            
746 8d08f18a Kostas Papadimitriou
            this.pending_firewalls = {};
747 8d08f18a Kostas Papadimitriou
            
748 8d08f18a Kostas Papadimitriou
            models.VM.__super__.initialize.apply(this, arguments);
749 8d08f18a Kostas Papadimitriou
750 8d08f18a Kostas Papadimitriou
            this.set({state: params.status || "ERROR"});
751 8d08f18a Kostas Papadimitriou
            this.log = new snf.logging.logger("VM " + this.id);
752 8d08f18a Kostas Papadimitriou
            this.pending_action = undefined;
753 8d08f18a Kostas Papadimitriou
            
754 8d08f18a Kostas Papadimitriou
            // init stats parameter
755 8d08f18a Kostas Papadimitriou
            this.set({'stats': undefined}, {silent: true});
756 8d08f18a Kostas Papadimitriou
            // defaults to not update the stats
757 8d08f18a Kostas Papadimitriou
            // each view should handle this vm attribute 
758 8d08f18a Kostas Papadimitriou
            // depending on if it displays stat images or not
759 8d08f18a Kostas Papadimitriou
            this.do_update_stats = false;
760 8d08f18a Kostas Papadimitriou
            
761 8d08f18a Kostas Papadimitriou
            // interval time
762 8d08f18a Kostas Papadimitriou
            // this will dynamicaly change if the server responds that
763 8d08f18a Kostas Papadimitriou
            // images get refreshed on different intervals
764 8d08f18a Kostas Papadimitriou
            this.stats_update_interval = synnefo.config.STATS_INTERVAL || 5000;
765 96d725ac Kostas Papadimitriou
            this.stats_available = false;
766 8d08f18a Kostas Papadimitriou
767 8d08f18a Kostas Papadimitriou
            // initialize interval
768 8d08f18a Kostas Papadimitriou
            this.init_stats_intervals(this.stats_update_interval);
769 8d08f18a Kostas Papadimitriou
            
770 1e882dd7 Kostas Papadimitriou
            // handle progress message on instance change
771 1e882dd7 Kostas Papadimitriou
            this.bind("change", _.bind(this.update_status_message, this));
772 1e882dd7 Kostas Papadimitriou
            // force update of progress message
773 1e882dd7 Kostas Papadimitriou
            this.update_status_message(true);
774 1e882dd7 Kostas Papadimitriou
            
775 8d08f18a Kostas Papadimitriou
            // default values
776 126a01f2 Kostas Papadimitriou
            this.bind("change:state", _.bind(function(){
777 126a01f2 Kostas Papadimitriou
                if (this.state() == "DESTROY") { 
778 126a01f2 Kostas Papadimitriou
                    this.handle_destroy() 
779 126a01f2 Kostas Papadimitriou
                }
780 126a01f2 Kostas Papadimitriou
            }, this));
781 8d08f18a Kostas Papadimitriou
782 126a01f2 Kostas Papadimitriou
            this.bind("change:nics", _.bind(synnefo.storage.nics.update_vm_nics, synnefo.storage.nics));
783 8d08f18a Kostas Papadimitriou
        },
784 8d08f18a Kostas Papadimitriou
785 8d08f18a Kostas Papadimitriou
        status: function(st) {
786 8d08f18a Kostas Papadimitriou
            if (!st) { return this.get("status")}
787 8d08f18a Kostas Papadimitriou
            return this.set({status:st});
788 8d08f18a Kostas Papadimitriou
        },
789 8d08f18a Kostas Papadimitriou
790 8d08f18a Kostas Papadimitriou
        set_status: function(st) {
791 8d08f18a Kostas Papadimitriou
            var new_state = this.state_for_api_status(st);
792 8d08f18a Kostas Papadimitriou
            var transition = false;
793 8d08f18a Kostas Papadimitriou
794 8d08f18a Kostas Papadimitriou
            if (this.state() != new_state) {
795 8d08f18a Kostas Papadimitriou
                if (models.VM.STATES_TRANSITIONS[this.state()]) {
796 8d08f18a Kostas Papadimitriou
                    transition = this.state();
797 8d08f18a Kostas Papadimitriou
                }
798 8d08f18a Kostas Papadimitriou
            }
799 8d08f18a Kostas Papadimitriou
            
800 8d08f18a Kostas Papadimitriou
            // call it silently to avoid double change trigger
801 8d08f18a Kostas Papadimitriou
            this.set({'state': this.state_for_api_status(st)}, {silent: true});
802 8d08f18a Kostas Papadimitriou
            
803 8d08f18a Kostas Papadimitriou
            // trigger transition
804 572dbe3d Kostas Papadimitriou
            if (transition && models.VM.TRANSITION_STATES.indexOf(new_state) == -1) { 
805 572dbe3d Kostas Papadimitriou
                this.trigger("transition", {from:transition, to:new_state}) 
806 572dbe3d Kostas Papadimitriou
            };
807 8d08f18a Kostas Papadimitriou
            return st;
808 8d08f18a Kostas Papadimitriou
        },
809 1e882dd7 Kostas Papadimitriou
            
810 1e882dd7 Kostas Papadimitriou
        get_diagnostics: function(success) {
811 1e882dd7 Kostas Papadimitriou
            this.__make_api_call(this.get_diagnostics_url(),
812 1e882dd7 Kostas Papadimitriou
                                 "read", // create so that sync later uses POST to make the call
813 1e882dd7 Kostas Papadimitriou
                                 null, // payload
814 1e882dd7 Kostas Papadimitriou
                                 function(data) {
815 1e882dd7 Kostas Papadimitriou
                                     success(data);
816 1e882dd7 Kostas Papadimitriou
                                 },  
817 1e882dd7 Kostas Papadimitriou
                                 null, 'diagnostics');
818 1e882dd7 Kostas Papadimitriou
        },
819 8d08f18a Kostas Papadimitriou
820 1e882dd7 Kostas Papadimitriou
        has_diagnostics: function() {
821 1e882dd7 Kostas Papadimitriou
            return this.get("diagnostics") && this.get("diagnostics").length;
822 1e882dd7 Kostas Papadimitriou
        },
823 1e882dd7 Kostas Papadimitriou
824 1e882dd7 Kostas Papadimitriou
        get_progress_info: function() {
825 1e882dd7 Kostas Papadimitriou
            // details about progress message
826 1e882dd7 Kostas Papadimitriou
            // contains a list of diagnostic messages
827 1e882dd7 Kostas Papadimitriou
            return this.get("status_messages");
828 1e882dd7 Kostas Papadimitriou
        },
829 1e882dd7 Kostas Papadimitriou
830 1e882dd7 Kostas Papadimitriou
        get_status_message: function() {
831 1e882dd7 Kostas Papadimitriou
            return this.get('status_message');
832 1e882dd7 Kostas Papadimitriou
        },
833 1e882dd7 Kostas Papadimitriou
        
834 1e882dd7 Kostas Papadimitriou
        // extract status message from diagnostics
835 1e882dd7 Kostas Papadimitriou
        status_message_from_diagnostics: function(diagnostics) {
836 1e882dd7 Kostas Papadimitriou
            var valid_sources_map = synnefo.config.diagnostics_status_messages_map;
837 1e882dd7 Kostas Papadimitriou
            var valid_sources = valid_sources_map[this.get('status')];
838 1e882dd7 Kostas Papadimitriou
            if (!valid_sources) { return null };
839 1e882dd7 Kostas Papadimitriou
            
840 1e882dd7 Kostas Papadimitriou
            // filter messsages based on diagnostic source
841 1e882dd7 Kostas Papadimitriou
            var messages = _.filter(diagnostics, function(diag) {
842 1e882dd7 Kostas Papadimitriou
                return valid_sources.indexOf(diag.source) > -1;
843 1e882dd7 Kostas Papadimitriou
            });
844 1e882dd7 Kostas Papadimitriou
845 1e882dd7 Kostas Papadimitriou
            var msg = messages[0];
846 1e882dd7 Kostas Papadimitriou
            if (msg) {
847 1e882dd7 Kostas Papadimitriou
              var message = msg.message;
848 1e882dd7 Kostas Papadimitriou
              var message_tpl = snf.config.diagnostic_messages_tpls[msg.source];
849 1e882dd7 Kostas Papadimitriou
850 1e882dd7 Kostas Papadimitriou
              if (message_tpl) {
851 1e882dd7 Kostas Papadimitriou
                  message = message_tpl.replace('MESSAGE', msg.message);
852 1e882dd7 Kostas Papadimitriou
              }
853 1e882dd7 Kostas Papadimitriou
              return message;
854 1e882dd7 Kostas Papadimitriou
            }
855 1e882dd7 Kostas Papadimitriou
            
856 1e882dd7 Kostas Papadimitriou
            // no message to display, but vm in build state, display
857 1e882dd7 Kostas Papadimitriou
            // finalizing message.
858 1e882dd7 Kostas Papadimitriou
            if (this.is_building() == 'BUILD') {
859 1e882dd7 Kostas Papadimitriou
                return synnefo.config.BUILDING_MESSAGES['FINAL'];
860 1e882dd7 Kostas Papadimitriou
            }
861 1e882dd7 Kostas Papadimitriou
            return null;
862 1e882dd7 Kostas Papadimitriou
        },
863 1e882dd7 Kostas Papadimitriou
864 1e882dd7 Kostas Papadimitriou
        update_status_message: function(force) {
865 1e882dd7 Kostas Papadimitriou
            // update only if one of the specified attributes has changed
866 1e882dd7 Kostas Papadimitriou
            if (
867 1e882dd7 Kostas Papadimitriou
              !this.keysChanged(['diagnostics', 'progress', 'status', 'state'])
868 1e882dd7 Kostas Papadimitriou
                && !force
869 1e882dd7 Kostas Papadimitriou
            ) { return };
870 1e882dd7 Kostas Papadimitriou
            
871 1e882dd7 Kostas Papadimitriou
            // if user requested to destroy the vm set the appropriate 
872 1e882dd7 Kostas Papadimitriou
            // message.
873 1e882dd7 Kostas Papadimitriou
            if (this.get('state') == "DESTROY") { 
874 1e882dd7 Kostas Papadimitriou
                message = "Terminating..."
875 1e882dd7 Kostas Papadimitriou
                this.set({status_message: message})
876 1e882dd7 Kostas Papadimitriou
                return;
877 1e882dd7 Kostas Papadimitriou
            }
878 1e882dd7 Kostas Papadimitriou
            
879 1e882dd7 Kostas Papadimitriou
            // set error message, if vm has diagnostic message display it as
880 1e882dd7 Kostas Papadimitriou
            // progress message
881 1e882dd7 Kostas Papadimitriou
            if (this.in_error_state()) {
882 1e882dd7 Kostas Papadimitriou
                var d = this.get('diagnostics');
883 1e882dd7 Kostas Papadimitriou
                if (d && d.length) {
884 1e882dd7 Kostas Papadimitriou
                    var message = this.status_message_from_diagnostics(d);
885 1e882dd7 Kostas Papadimitriou
                    this.set({status_message: message});
886 1e882dd7 Kostas Papadimitriou
                } else {
887 1e882dd7 Kostas Papadimitriou
                    this.set({status_message: null});
888 8d08f18a Kostas Papadimitriou
                }
889 1e882dd7 Kostas Papadimitriou
                return;
890 1e882dd7 Kostas Papadimitriou
            }
891 1e882dd7 Kostas Papadimitriou
            
892 1e882dd7 Kostas Papadimitriou
            // identify building status message
893 1e882dd7 Kostas Papadimitriou
            if (this.is_building()) {
894 1e882dd7 Kostas Papadimitriou
                var self = this;
895 1e882dd7 Kostas Papadimitriou
                var success = function(msg) {
896 1e882dd7 Kostas Papadimitriou
                    self.set({status_message: msg});
897 8d08f18a Kostas Papadimitriou
                }
898 1e882dd7 Kostas Papadimitriou
                this.get_building_status_message(success);
899 1e882dd7 Kostas Papadimitriou
                return;
900 1e882dd7 Kostas Papadimitriou
            }
901 1e882dd7 Kostas Papadimitriou
902 1e882dd7 Kostas Papadimitriou
            this.set({status_message:null});
903 1e882dd7 Kostas Papadimitriou
        },
904 1e882dd7 Kostas Papadimitriou
            
905 1e882dd7 Kostas Papadimitriou
        // get building status message. Asynchronous function since it requires
906 1e882dd7 Kostas Papadimitriou
        // access to vm image.
907 1e882dd7 Kostas Papadimitriou
        get_building_status_message: function(callback) {
908 1e882dd7 Kostas Papadimitriou
            // no progress is set, vm is in initial build status
909 1e882dd7 Kostas Papadimitriou
            var progress = this.get("progress");
910 1e882dd7 Kostas Papadimitriou
            if (progress == 0 || !progress) {
911 1e882dd7 Kostas Papadimitriou
                return callback(BUILDING_MESSAGES['INIT']);
912 1e882dd7 Kostas Papadimitriou
            }
913 1e882dd7 Kostas Papadimitriou
            
914 1e882dd7 Kostas Papadimitriou
            // vm has copy progress, display copy percentage
915 1e882dd7 Kostas Papadimitriou
            if (progress > 0 && progress <= 99) {
916 1e882dd7 Kostas Papadimitriou
                this.get_copy_details(true, undefined, _.bind(
917 1e882dd7 Kostas Papadimitriou
                    function(details){
918 1e882dd7 Kostas Papadimitriou
                        callback(BUILDING_MESSAGES['COPY'].format(details.copy, 
919 1e882dd7 Kostas Papadimitriou
                                                           details.size, 
920 1e882dd7 Kostas Papadimitriou
                                                           details.progress));
921 1e882dd7 Kostas Papadimitriou
                }, this));
922 1e882dd7 Kostas Papadimitriou
                return;
923 1e882dd7 Kostas Papadimitriou
            }
924 1e882dd7 Kostas Papadimitriou
925 1e882dd7 Kostas Papadimitriou
            // copy finished display FINAL message or identify status message
926 1e882dd7 Kostas Papadimitriou
            // from diagnostics.
927 1e882dd7 Kostas Papadimitriou
            if (progress >= 100) {
928 1e882dd7 Kostas Papadimitriou
                if (!this.has_diagnostics()) {
929 1e882dd7 Kostas Papadimitriou
                        callback(BUILDING_MESSAGES['FINAL']);
930 1e882dd7 Kostas Papadimitriou
                } else {
931 1e882dd7 Kostas Papadimitriou
                        var d = this.get("diagnostics");
932 1e882dd7 Kostas Papadimitriou
                        var msg = this.status_message_from_diagnostics(d);
933 1e882dd7 Kostas Papadimitriou
                        if (msg) {
934 1e882dd7 Kostas Papadimitriou
                              callback(msg);
935 1e882dd7 Kostas Papadimitriou
                        }
936 8d08f18a Kostas Papadimitriou
                }
937 8d08f18a Kostas Papadimitriou
            }
938 8d08f18a Kostas Papadimitriou
        },
939 8d08f18a Kostas Papadimitriou
940 c45bed88 Kostas Papadimitriou
        get_copy_details: function(human, image, callback) {
941 8d08f18a Kostas Papadimitriou
            var human = human || false;
942 c45bed88 Kostas Papadimitriou
            var image = image || this.get_image(_.bind(function(image){
943 c45bed88 Kostas Papadimitriou
                var progress = this.get('progress');
944 c45bed88 Kostas Papadimitriou
                var size = image.get_size();
945 c45bed88 Kostas Papadimitriou
                var size_copied = (size * progress / 100).toFixed(2);
946 c45bed88 Kostas Papadimitriou
                
947 c45bed88 Kostas Papadimitriou
                if (human) {
948 c45bed88 Kostas Papadimitriou
                    size = util.readablizeBytes(size*1024*1024);
949 c45bed88 Kostas Papadimitriou
                    size_copied = util.readablizeBytes(size_copied*1024*1024);
950 c45bed88 Kostas Papadimitriou
                }
951 8d08f18a Kostas Papadimitriou
952 c45bed88 Kostas Papadimitriou
                callback({'progress': progress, 'size': size, 'copy': size_copied})
953 c45bed88 Kostas Papadimitriou
            }, this));
954 8d08f18a Kostas Papadimitriou
        },
955 8d08f18a Kostas Papadimitriou
956 1f7ea2f5 Kostas Papadimitriou
        start_stats_update: function(force_if_empty) {
957 2c9bfad1 Kostas Papadimitriou
            var prev_state = this.do_update_stats;
958 2c9bfad1 Kostas Papadimitriou
959 2c9bfad1 Kostas Papadimitriou
            this.do_update_stats = true;
960 1f7ea2f5 Kostas Papadimitriou
            
961 2c9bfad1 Kostas Papadimitriou
            // fetcher initialized ??
962 2c9bfad1 Kostas Papadimitriou
            if (!this.stats_fetcher) {
963 2c9bfad1 Kostas Papadimitriou
                this.init_stats_intervals();
964 2c9bfad1 Kostas Papadimitriou
            }
965 2c9bfad1 Kostas Papadimitriou
966 1f7ea2f5 Kostas Papadimitriou
967 2c9bfad1 Kostas Papadimitriou
            // fetcher running ???
968 2c9bfad1 Kostas Papadimitriou
            if (!this.stats_fetcher.running || !prev_state) {
969 2c9bfad1 Kostas Papadimitriou
                this.stats_fetcher.start();
970 2c9bfad1 Kostas Papadimitriou
            }
971 1f7ea2f5 Kostas Papadimitriou
972 1f7ea2f5 Kostas Papadimitriou
            if (force_if_empty && this.get("stats") == undefined) {
973 1f7ea2f5 Kostas Papadimitriou
                this.update_stats(true);
974 1f7ea2f5 Kostas Papadimitriou
            }
975 2c9bfad1 Kostas Papadimitriou
        },
976 2c9bfad1 Kostas Papadimitriou
977 2c9bfad1 Kostas Papadimitriou
        stop_stats_update: function(stop_calls) {
978 2c9bfad1 Kostas Papadimitriou
            this.do_update_stats = false;
979 2c9bfad1 Kostas Papadimitriou
980 2c9bfad1 Kostas Papadimitriou
            if (stop_calls) {
981 2c9bfad1 Kostas Papadimitriou
                this.stats_fetcher.stop();
982 2c9bfad1 Kostas Papadimitriou
            }
983 2c9bfad1 Kostas Papadimitriou
        },
984 2c9bfad1 Kostas Papadimitriou
985 8d08f18a Kostas Papadimitriou
        // clear and reinitialize update interval
986 8d08f18a Kostas Papadimitriou
        init_stats_intervals: function (interval) {
987 96d725ac Kostas Papadimitriou
            this.stats_fetcher = this.get_stats_fetcher(this.stats_update_interval);
988 96d725ac Kostas Papadimitriou
            this.stats_fetcher.start();
989 8d08f18a Kostas Papadimitriou
        },
990 8d08f18a Kostas Papadimitriou
        
991 96d725ac Kostas Papadimitriou
        get_stats_fetcher: function(timeout) {
992 96d725ac Kostas Papadimitriou
            var cb = _.bind(function(data){
993 96d725ac Kostas Papadimitriou
                this.update_stats();
994 96d725ac Kostas Papadimitriou
            }, this);
995 258235f4 Kostas Papadimitriou
            var fetcher = new snf.api.updateHandler({'callback': cb, interval: timeout, id:'stats'});
996 96d725ac Kostas Papadimitriou
            return fetcher;
997 96d725ac Kostas Papadimitriou
        },
998 96d725ac Kostas Papadimitriou
999 8d08f18a Kostas Papadimitriou
        // do the api call
1000 8d08f18a Kostas Papadimitriou
        update_stats: function(force) {
1001 8d08f18a Kostas Papadimitriou
            // do not update stats if flag not set
1002 1f7ea2f5 Kostas Papadimitriou
            if ((!this.do_update_stats && !force) || this.updating_stats) {
1003 8d08f18a Kostas Papadimitriou
                return;
1004 8d08f18a Kostas Papadimitriou
            }
1005 96d725ac Kostas Papadimitriou
1006 8d08f18a Kostas Papadimitriou
            // make the api call, execute handle_stats_update on sucess
1007 8d08f18a Kostas Papadimitriou
            // TODO: onError handler ???
1008 8d08f18a Kostas Papadimitriou
            stats_url = this.url() + "/stats";
1009 1f7ea2f5 Kostas Papadimitriou
            this.updating_stats = true;
1010 258235f4 Kostas Papadimitriou
            this.sync("read", this, {
1011 96d725ac Kostas Papadimitriou
                handles_error:true, 
1012 96d725ac Kostas Papadimitriou
                url: stats_url, 
1013 96d725ac Kostas Papadimitriou
                refresh:true, 
1014 96d725ac Kostas Papadimitriou
                success: _.bind(this.handle_stats_update, this),
1015 ec511098 Kostas Papadimitriou
                error: _.bind(this.handle_stats_error, this),
1016 1f7ea2f5 Kostas Papadimitriou
                complete: _.bind(function(){this.updating_stats = false;}, this),
1017 ec511098 Kostas Papadimitriou
                critical: false,
1018 0375f6c5 Kostas Papadimitriou
                log_error: false,
1019 0375f6c5 Kostas Papadimitriou
                skips_timeouts: true
1020 96d725ac Kostas Papadimitriou
            });
1021 96d725ac Kostas Papadimitriou
        },
1022 96d725ac Kostas Papadimitriou
1023 96d725ac Kostas Papadimitriou
        get_stats_image: function(stat, type) {
1024 8d08f18a Kostas Papadimitriou
        },
1025 8d08f18a Kostas Papadimitriou
        
1026 96d725ac Kostas Papadimitriou
        _set_stats: function(stats) {
1027 96d725ac Kostas Papadimitriou
            var silent = silent === undefined ? false : silent;
1028 96d725ac Kostas Papadimitriou
            // unavailable stats while building
1029 96d725ac Kostas Papadimitriou
            if (this.get("status") == "BUILD") { 
1030 96d725ac Kostas Papadimitriou
                this.stats_available = false;
1031 96d725ac Kostas Papadimitriou
            } else { this.stats_available = true; }
1032 96d725ac Kostas Papadimitriou
1033 96d725ac Kostas Papadimitriou
            if (this.get("status") == "DESTROY") { this.stats_available = false; }
1034 96d725ac Kostas Papadimitriou
            
1035 96d725ac Kostas Papadimitriou
            this.set({stats: stats}, {silent:true});
1036 96d725ac Kostas Papadimitriou
            this.trigger("stats:update", stats);
1037 96d725ac Kostas Papadimitriou
        },
1038 96d725ac Kostas Papadimitriou
1039 96d725ac Kostas Papadimitriou
        unbind: function() {
1040 96d725ac Kostas Papadimitriou
            models.VM.__super__.unbind.apply(this, arguments);
1041 96d725ac Kostas Papadimitriou
        },
1042 96d725ac Kostas Papadimitriou
1043 96d725ac Kostas Papadimitriou
        handle_stats_error: function() {
1044 96d725ac Kostas Papadimitriou
            stats = {};
1045 96d725ac Kostas Papadimitriou
            _.each(['cpuBar', 'cpuTimeSeries', 'netBar', 'netTimeSeries'], function(k) {
1046 96d725ac Kostas Papadimitriou
                stats[k] = false;
1047 96d725ac Kostas Papadimitriou
            });
1048 96d725ac Kostas Papadimitriou
1049 96d725ac Kostas Papadimitriou
            this.set({'stats': stats});
1050 96d725ac Kostas Papadimitriou
        },
1051 96d725ac Kostas Papadimitriou
1052 8d08f18a Kostas Papadimitriou
        // this method gets executed after a successful vm stats api call
1053 8d08f18a Kostas Papadimitriou
        handle_stats_update: function(data) {
1054 96d725ac Kostas Papadimitriou
            var self = this;
1055 8d08f18a Kostas Papadimitriou
            // avoid browser caching
1056 96d725ac Kostas Papadimitriou
            
1057 8d08f18a Kostas Papadimitriou
            if (data.stats && _.size(data.stats) > 0) {
1058 8d08f18a Kostas Papadimitriou
                var ts = $.now();
1059 8d08f18a Kostas Papadimitriou
                var stats = data.stats;
1060 96d725ac Kostas Papadimitriou
                var images_loaded = 0;
1061 96d725ac Kostas Papadimitriou
                var images = {};
1062 96d725ac Kostas Papadimitriou
1063 96d725ac Kostas Papadimitriou
                function check_images_loaded() {
1064 96d725ac Kostas Papadimitriou
                    images_loaded++;
1065 96d725ac Kostas Papadimitriou
1066 96d725ac Kostas Papadimitriou
                    if (images_loaded == 4) {
1067 96d725ac Kostas Papadimitriou
                        self._set_stats(images);
1068 96d725ac Kostas Papadimitriou
                    }
1069 96d725ac Kostas Papadimitriou
                }
1070 8d08f18a Kostas Papadimitriou
                _.each(['cpuBar', 'cpuTimeSeries', 'netBar', 'netTimeSeries'], function(k) {
1071 96d725ac Kostas Papadimitriou
                    
1072 8d08f18a Kostas Papadimitriou
                    stats[k] = stats[k] + "?_=" + ts;
1073 96d725ac Kostas Papadimitriou
                    
1074 96d725ac Kostas Papadimitriou
                    var stat = k.slice(0,3);
1075 96d725ac Kostas Papadimitriou
                    var type = k.slice(3,6) == "Bar" ? "bar" : "time";
1076 96d725ac Kostas Papadimitriou
                    var img = $("<img />");
1077 96d725ac Kostas Papadimitriou
                    var val = stats[k];
1078 96d725ac Kostas Papadimitriou
                    
1079 96d725ac Kostas Papadimitriou
                    // load stat image to a temporary dom element
1080 96d725ac Kostas Papadimitriou
                    // update model stats on image load/error events
1081 96d725ac Kostas Papadimitriou
                    img.load(function() {
1082 96d725ac Kostas Papadimitriou
                        images[k] = val;
1083 96d725ac Kostas Papadimitriou
                        check_images_loaded();
1084 96d725ac Kostas Papadimitriou
                    });
1085 96d725ac Kostas Papadimitriou
1086 96d725ac Kostas Papadimitriou
                    img.error(function() {
1087 96d725ac Kostas Papadimitriou
                        images[stat + type] = false;
1088 96d725ac Kostas Papadimitriou
                        check_images_loaded();
1089 96d725ac Kostas Papadimitriou
                    });
1090 96d725ac Kostas Papadimitriou
1091 96d725ac Kostas Papadimitriou
                    img.attr({'src': stats[k]});
1092 8d08f18a Kostas Papadimitriou
                })
1093 8d08f18a Kostas Papadimitriou
                data.stats = stats;
1094 8d08f18a Kostas Papadimitriou
            }
1095 96d725ac Kostas Papadimitriou
1096 8d08f18a Kostas Papadimitriou
            // do we need to change the interval ??
1097 8d08f18a Kostas Papadimitriou
            if (data.stats.refresh * 1000 != this.stats_update_interval) {
1098 8d08f18a Kostas Papadimitriou
                this.stats_update_interval = data.stats.refresh * 1000;
1099 1cc6e94f Kostas Papadimitriou
                this.stats_fetcher.interval = this.stats_update_interval;
1100 1cc6e94f Kostas Papadimitriou
                this.stats_fetcher.maximum_interval = this.stats_update_interval;
1101 96d725ac Kostas Papadimitriou
                this.stats_fetcher.stop();
1102 2c9bfad1 Kostas Papadimitriou
                this.stats_fetcher.start(false);
1103 8d08f18a Kostas Papadimitriou
            }
1104 8d08f18a Kostas Papadimitriou
        },
1105 96d725ac Kostas Papadimitriou
1106 8d08f18a Kostas Papadimitriou
        // helper method that sets the do_update_stats
1107 8d08f18a Kostas Papadimitriou
        // in the future this method could also make an api call
1108 8d08f18a Kostas Papadimitriou
        // immediaetly if needed
1109 8d08f18a Kostas Papadimitriou
        enable_stats_update: function() {
1110 8d08f18a Kostas Papadimitriou
            this.do_update_stats = true;
1111 8d08f18a Kostas Papadimitriou
        },
1112 96d725ac Kostas Papadimitriou
        
1113 96d725ac Kostas Papadimitriou
        handle_destroy: function() {
1114 96d725ac Kostas Papadimitriou
            this.stats_fetcher.stop();
1115 96d725ac Kostas Papadimitriou
        },
1116 122850c5 Kostas Papadimitriou
1117 122850c5 Kostas Papadimitriou
        require_reboot: function() {
1118 122850c5 Kostas Papadimitriou
            if (this.is_active()) {
1119 122850c5 Kostas Papadimitriou
                this.set({'reboot_required': true});
1120 122850c5 Kostas Papadimitriou
            }
1121 122850c5 Kostas Papadimitriou
        },
1122 8d08f18a Kostas Papadimitriou
        
1123 8d08f18a Kostas Papadimitriou
        set_pending_action: function(data) {
1124 8d08f18a Kostas Papadimitriou
            this.pending_action = data;
1125 8d08f18a Kostas Papadimitriou
            return data;
1126 8d08f18a Kostas Papadimitriou
        },
1127 8d08f18a Kostas Papadimitriou
1128 8d08f18a Kostas Papadimitriou
        // machine has pending action
1129 8d08f18a Kostas Papadimitriou
        update_pending_action: function(action, force) {
1130 8d08f18a Kostas Papadimitriou
            this.set({pending_action: action});
1131 8d08f18a Kostas Papadimitriou
        },
1132 8d08f18a Kostas Papadimitriou
1133 8d08f18a Kostas Papadimitriou
        clear_pending_action: function() {
1134 8d08f18a Kostas Papadimitriou
            this.set({pending_action: undefined});
1135 8d08f18a Kostas Papadimitriou
        },
1136 8d08f18a Kostas Papadimitriou
1137 8d08f18a Kostas Papadimitriou
        has_pending_action: function() {
1138 8d08f18a Kostas Papadimitriou
            return this.get("pending_action") ? this.get("pending_action") : false;
1139 8d08f18a Kostas Papadimitriou
        },
1140 8d08f18a Kostas Papadimitriou
        
1141 8d08f18a Kostas Papadimitriou
        // machine is active
1142 8d08f18a Kostas Papadimitriou
        is_active: function() {
1143 8d08f18a Kostas Papadimitriou
            return models.VM.ACTIVE_STATES.indexOf(this.state()) > -1;
1144 8d08f18a Kostas Papadimitriou
        },
1145 8d08f18a Kostas Papadimitriou
        
1146 122850c5 Kostas Papadimitriou
        // machine is building 
1147 8d08f18a Kostas Papadimitriou
        is_building: function() {
1148 8d08f18a Kostas Papadimitriou
            return models.VM.BUILDING_STATES.indexOf(this.state()) > -1;
1149 8d08f18a Kostas Papadimitriou
        },
1150 3162bebd Kostas Papadimitriou
        
1151 3162bebd Kostas Papadimitriou
        in_error_state: function() {
1152 3162bebd Kostas Papadimitriou
            return this.state() === "ERROR"
1153 3162bebd Kostas Papadimitriou
        },
1154 8d08f18a Kostas Papadimitriou
1155 8d08f18a Kostas Papadimitriou
        // user can connect to machine
1156 8d08f18a Kostas Papadimitriou
        is_connectable: function() {
1157 8d08f18a Kostas Papadimitriou
            // check if ips exist
1158 8d08f18a Kostas Papadimitriou
            if (!this.get_addresses().ip4 && !this.get_addresses().ip6) {
1159 8d08f18a Kostas Papadimitriou
                return false;
1160 8d08f18a Kostas Papadimitriou
            }
1161 8d08f18a Kostas Papadimitriou
            return models.VM.CONNECT_STATES.indexOf(this.state()) > -1;
1162 8d08f18a Kostas Papadimitriou
        },
1163 8d08f18a Kostas Papadimitriou
        
1164 8d08f18a Kostas Papadimitriou
        remove_meta: function(key, complete, error) {
1165 8d08f18a Kostas Papadimitriou
            var url = this.api_path() + "/meta/" + key;
1166 258235f4 Kostas Papadimitriou
            this.api_call(url, "delete", undefined, complete, error);
1167 8d08f18a Kostas Papadimitriou
        },
1168 8d08f18a Kostas Papadimitriou
1169 8d08f18a Kostas Papadimitriou
        save_meta: function(meta, complete, error) {
1170 8d08f18a Kostas Papadimitriou
            var url = this.api_path() + "/meta/" + meta.key;
1171 8d08f18a Kostas Papadimitriou
            var payload = {meta:{}};
1172 8d08f18a Kostas Papadimitriou
            payload.meta[meta.key] = meta.value;
1173 9ffd10ce Kostas Papadimitriou
            payload._options = {
1174 9ffd10ce Kostas Papadimitriou
                critical:false, 
1175 9ffd10ce Kostas Papadimitriou
                error_params: {
1176 9ffd10ce Kostas Papadimitriou
                    title: "Machine metadata error",
1177 9ffd10ce Kostas Papadimitriou
                    extra_details: {"Machine id": this.id}
1178 9ffd10ce Kostas Papadimitriou
            }};
1179 8d08f18a Kostas Papadimitriou
1180 258235f4 Kostas Papadimitriou
            this.api_call(url, "update", payload, complete, error);
1181 8d08f18a Kostas Papadimitriou
        },
1182 8d08f18a Kostas Papadimitriou
1183 8d08f18a Kostas Papadimitriou
1184 8d08f18a Kostas Papadimitriou
        // update/get the state of the machine
1185 8d08f18a Kostas Papadimitriou
        state: function() {
1186 8d08f18a Kostas Papadimitriou
            var args = slice.call(arguments);
1187 8d08f18a Kostas Papadimitriou
                
1188 643de8c0 Kostas Papadimitriou
            // TODO: it might not be a good idea to set the state in set_state method
1189 8d08f18a Kostas Papadimitriou
            if (args.length > 0 && models.VM.STATES.indexOf(args[0]) > -1) {
1190 8d08f18a Kostas Papadimitriou
                this.set({'state': args[0]});
1191 8d08f18a Kostas Papadimitriou
            }
1192 8d08f18a Kostas Papadimitriou
1193 8d08f18a Kostas Papadimitriou
            return this.get('state');
1194 8d08f18a Kostas Papadimitriou
        },
1195 8d08f18a Kostas Papadimitriou
        
1196 8d08f18a Kostas Papadimitriou
        // get the state that the api status corresponds to
1197 8d08f18a Kostas Papadimitriou
        state_for_api_status: function(status) {
1198 8d08f18a Kostas Papadimitriou
            return this.state_transition(this.state(), status);
1199 8d08f18a Kostas Papadimitriou
        },
1200 8d08f18a Kostas Papadimitriou
        
1201 8d08f18a Kostas Papadimitriou
        // vm state equals vm api status
1202 8d08f18a Kostas Papadimitriou
        state_is_status: function(state) {
1203 8d08f18a Kostas Papadimitriou
            return models.VM.STATUSES.indexOf(state) != -1;
1204 8d08f18a Kostas Papadimitriou
        },
1205 8d08f18a Kostas Papadimitriou
        
1206 8d08f18a Kostas Papadimitriou
        // get transition state for the corresponging api status
1207 8d08f18a Kostas Papadimitriou
        state_transition: function(state, new_status) {
1208 8d08f18a Kostas Papadimitriou
            var statuses = models.VM.STATES_TRANSITIONS[state];
1209 8d08f18a Kostas Papadimitriou
            if (statuses) {
1210 8d08f18a Kostas Papadimitriou
                if (statuses.indexOf(new_status) > -1) {
1211 8d08f18a Kostas Papadimitriou
                    return new_status;
1212 8d08f18a Kostas Papadimitriou
                } else {
1213 8d08f18a Kostas Papadimitriou
                    return state;
1214 8d08f18a Kostas Papadimitriou
                }
1215 8d08f18a Kostas Papadimitriou
            } else {
1216 8d08f18a Kostas Papadimitriou
                return new_status;
1217 8d08f18a Kostas Papadimitriou
            }
1218 8d08f18a Kostas Papadimitriou
        },
1219 8d08f18a Kostas Papadimitriou
        
1220 8d08f18a Kostas Papadimitriou
        // the current vm state is a transition state
1221 8d08f18a Kostas Papadimitriou
        in_transition: function() {
1222 8d08f18a Kostas Papadimitriou
            return models.VM.TRANSITION_STATES.indexOf(this.state()) > -1 || 
1223 8d08f18a Kostas Papadimitriou
                models.VM.TRANSITION_STATES.indexOf(this.get('status')) > -1;
1224 8d08f18a Kostas Papadimitriou
        },
1225 8d08f18a Kostas Papadimitriou
        
1226 8d08f18a Kostas Papadimitriou
        // get image object
1227 c45bed88 Kostas Papadimitriou
        get_image: function(callback) {
1228 cde8cde3 Kostas Papadimitriou
            if (callback == undefined) { callback = function(){} }
1229 bedfe884 Kostas Papadimitriou
            var image = storage.images.get(this.get('imageRef'));
1230 bedfe884 Kostas Papadimitriou
            if (!image) {
1231 c45bed88 Kostas Papadimitriou
                storage.images.update_unknown_id(this.get('imageRef'), callback);
1232 c45bed88 Kostas Papadimitriou
                return;
1233 bedfe884 Kostas Papadimitriou
            }
1234 c45bed88 Kostas Papadimitriou
            callback(image);
1235 bedfe884 Kostas Papadimitriou
            return image;
1236 8d08f18a Kostas Papadimitriou
        },
1237 8d08f18a Kostas Papadimitriou
        
1238 8d08f18a Kostas Papadimitriou
        // get flavor object
1239 8d08f18a Kostas Papadimitriou
        get_flavor: function() {
1240 bedfe884 Kostas Papadimitriou
            var flv = storage.flavors.get(this.get('flavorRef'));
1241 bedfe884 Kostas Papadimitriou
            if (!flv) {
1242 bedfe884 Kostas Papadimitriou
                storage.flavors.update_unknown_id(this.get('flavorRef'));
1243 bedfe884 Kostas Papadimitriou
                flv = storage.flavors.get(this.get('flavorRef'));
1244 bedfe884 Kostas Papadimitriou
            }
1245 bedfe884 Kostas Papadimitriou
            return flv;
1246 8d08f18a Kostas Papadimitriou
        },
1247 8d08f18a Kostas Papadimitriou
1248 cde8cde3 Kostas Papadimitriou
        get_meta: function(key, deflt) {
1249 88d6d677 Kostas Papadimitriou
            if (this.get('metadata') && this.get('metadata').values) {
1250 cde8cde3 Kostas Papadimitriou
                if (!this.get('metadata').values[key]) { return deflt }
1251 df251d55 Kostas Papadimitriou
                return _.escape(this.get('metadata').values[key]);
1252 88d6d677 Kostas Papadimitriou
            } else {
1253 cde8cde3 Kostas Papadimitriou
                return deflt;
1254 88d6d677 Kostas Papadimitriou
            }
1255 88d6d677 Kostas Papadimitriou
        },
1256 88d6d677 Kostas Papadimitriou
1257 88d6d677 Kostas Papadimitriou
        get_meta_keys: function() {
1258 88d6d677 Kostas Papadimitriou
            if (this.get('metadata') && this.get('metadata').values) {
1259 88d6d677 Kostas Papadimitriou
                return _.keys(this.get('metadata').values);
1260 88d6d677 Kostas Papadimitriou
            } else {
1261 88d6d677 Kostas Papadimitriou
                return [];
1262 8d08f18a Kostas Papadimitriou
            }
1263 8d08f18a Kostas Papadimitriou
        },
1264 8d08f18a Kostas Papadimitriou
        
1265 8d08f18a Kostas Papadimitriou
        // get metadata OS value
1266 8d08f18a Kostas Papadimitriou
        get_os: function() {
1267 cde8cde3 Kostas Papadimitriou
            var image = this.get_image();
1268 cde8cde3 Kostas Papadimitriou
            return this.get_meta('OS') || (image ? 
1269 cde8cde3 Kostas Papadimitriou
                                            image.get_os() || "okeanos" : "okeanos");
1270 8d08f18a Kostas Papadimitriou
        },
1271 258235f4 Kostas Papadimitriou
1272 43ec1206 Kostas Papadimitriou
        get_gui: function() {
1273 43ec1206 Kostas Papadimitriou
            return this.get_meta('GUI');
1274 43ec1206 Kostas Papadimitriou
        },
1275 126a01f2 Kostas Papadimitriou
        
1276 126a01f2 Kostas Papadimitriou
        connected_to: function(net) {
1277 126a01f2 Kostas Papadimitriou
            return this.get('linked_to').indexOf(net.id) > -1;
1278 126a01f2 Kostas Papadimitriou
        },
1279 43ec1206 Kostas Papadimitriou
1280 126a01f2 Kostas Papadimitriou
        connected_with_nic_id: function(nic_id) {
1281 126a01f2 Kostas Papadimitriou
            return _.keys(this.get('nics')).indexOf(nic_id) > -1;
1282 8d08f18a Kostas Papadimitriou
        },
1283 8d08f18a Kostas Papadimitriou
1284 126a01f2 Kostas Papadimitriou
        get_nics: function(filter) {
1285 126a01f2 Kostas Papadimitriou
            ret = synnefo.storage.nics.filter(function(nic) {
1286 126a01f2 Kostas Papadimitriou
                return parseInt(nic.get('vm_id')) == this.id;
1287 126a01f2 Kostas Papadimitriou
            }, this);
1288 8d08f18a Kostas Papadimitriou
1289 126a01f2 Kostas Papadimitriou
            if (filter) {
1290 126a01f2 Kostas Papadimitriou
                return _.filter(ret, filter);
1291 8d08f18a Kostas Papadimitriou
            }
1292 126a01f2 Kostas Papadimitriou
1293 126a01f2 Kostas Papadimitriou
            return ret;
1294 126a01f2 Kostas Papadimitriou
        },
1295 126a01f2 Kostas Papadimitriou
1296 126a01f2 Kostas Papadimitriou
        get_net_nics: function(net_id) {
1297 126a01f2 Kostas Papadimitriou
            return this.get_nics(function(n){return n.get('network_id') == net_id});
1298 8d08f18a Kostas Papadimitriou
        },
1299 8d08f18a Kostas Papadimitriou
1300 126a01f2 Kostas Papadimitriou
        get_public_nic: function() {
1301 47c66641 Dimitris Aragiorgis
            return this.get_nics(function(n){ return n.get_network().is_public() === true })[0];
1302 8d08f18a Kostas Papadimitriou
        },
1303 8d08f18a Kostas Papadimitriou
1304 3796f345 Kostas Papadimitriou
        get_hostname: function() {
1305 3796f345 Kostas Papadimitriou
          var hostname = this.get_meta('hostname');
1306 3796f345 Kostas Papadimitriou
          if (!hostname) {
1307 f5e97e7f Kostas Papadimitriou
            if (synnefo.config.vm_hostname_format) {
1308 f5e97e7f Kostas Papadimitriou
              hostname = synnefo.config.vm_hostname_format.format(this.id);
1309 f5e97e7f Kostas Papadimitriou
            } else {
1310 f5e97e7f Kostas Papadimitriou
              hostname = this.get_public_nic().get('ipv4');
1311 f5e97e7f Kostas Papadimitriou
            }
1312 3796f345 Kostas Papadimitriou
          }
1313 3796f345 Kostas Papadimitriou
          return hostname;
1314 3796f345 Kostas Papadimitriou
        },
1315 3796f345 Kostas Papadimitriou
1316 126a01f2 Kostas Papadimitriou
        get_nic: function(net_id) {
1317 126a01f2 Kostas Papadimitriou
        },
1318 126a01f2 Kostas Papadimitriou
1319 126a01f2 Kostas Papadimitriou
        has_firewall: function() {
1320 126a01f2 Kostas Papadimitriou
            var nic = this.get_public_nic();
1321 126a01f2 Kostas Papadimitriou
            if (nic) {
1322 126a01f2 Kostas Papadimitriou
                var profile = nic.get('firewallProfile'); 
1323 126a01f2 Kostas Papadimitriou
                return ['ENABLED', 'PROTECTED'].indexOf(profile) > -1;
1324 126a01f2 Kostas Papadimitriou
            }
1325 126a01f2 Kostas Papadimitriou
            return false;
1326 126a01f2 Kostas Papadimitriou
        },
1327 126a01f2 Kostas Papadimitriou
1328 126a01f2 Kostas Papadimitriou
        get_firewall_profile: function() {
1329 126a01f2 Kostas Papadimitriou
            var nic = this.get_public_nic();
1330 126a01f2 Kostas Papadimitriou
            if (nic) {
1331 126a01f2 Kostas Papadimitriou
                return nic.get('firewallProfile');
1332 126a01f2 Kostas Papadimitriou
            }
1333 126a01f2 Kostas Papadimitriou
            return null;
1334 126a01f2 Kostas Papadimitriou
        },
1335 126a01f2 Kostas Papadimitriou
1336 126a01f2 Kostas Papadimitriou
        get_addresses: function() {
1337 126a01f2 Kostas Papadimitriou
            var pnic = this.get_public_nic();
1338 126a01f2 Kostas Papadimitriou
            if (!pnic) { return {'ip4': undefined, 'ip6': undefined }};
1339 126a01f2 Kostas Papadimitriou
            return {'ip4': pnic.get('ipv4'), 'ip6': pnic.get('ipv6')};
1340 8d08f18a Kostas Papadimitriou
        },
1341 8d08f18a Kostas Papadimitriou
    
1342 8d08f18a Kostas Papadimitriou
        // get actions that the user can execute
1343 8d08f18a Kostas Papadimitriou
        // depending on the vm state/status
1344 8d08f18a Kostas Papadimitriou
        get_available_actions: function() {
1345 8d08f18a Kostas Papadimitriou
            return models.VM.AVAILABLE_ACTIONS[this.state()];
1346 8d08f18a Kostas Papadimitriou
        },
1347 8d08f18a Kostas Papadimitriou
1348 8d08f18a Kostas Papadimitriou
        set_profile: function(profile, net_id) {
1349 8d08f18a Kostas Papadimitriou
        },
1350 8d08f18a Kostas Papadimitriou
        
1351 8d08f18a Kostas Papadimitriou
        // call rename api
1352 8d08f18a Kostas Papadimitriou
        rename: function(new_name) {
1353 8d08f18a Kostas Papadimitriou
            //this.set({'name': new_name});
1354 8d08f18a Kostas Papadimitriou
            this.sync("update", this, {
1355 9ffd10ce Kostas Papadimitriou
                critical: true,
1356 8d08f18a Kostas Papadimitriou
                data: {
1357 8d08f18a Kostas Papadimitriou
                    'server': {
1358 8d08f18a Kostas Papadimitriou
                        'name': new_name
1359 8d08f18a Kostas Papadimitriou
                    }
1360 8d08f18a Kostas Papadimitriou
                }, 
1361 8d08f18a Kostas Papadimitriou
                // do the rename after the method succeeds
1362 8d08f18a Kostas Papadimitriou
                success: _.bind(function(){
1363 8d08f18a Kostas Papadimitriou
                    //this.set({name: new_name});
1364 8d08f18a Kostas Papadimitriou
                    snf.api.trigger("call");
1365 8d08f18a Kostas Papadimitriou
                }, this)
1366 8d08f18a Kostas Papadimitriou
            });
1367 8d08f18a Kostas Papadimitriou
        },
1368 8d08f18a Kostas Papadimitriou
        
1369 8d08f18a Kostas Papadimitriou
        get_console_url: function(data) {
1370 8d08f18a Kostas Papadimitriou
            var url_params = {
1371 8d08f18a Kostas Papadimitriou
                machine: this.get("name"),
1372 8d08f18a Kostas Papadimitriou
                host_ip: this.get_addresses().ip4,
1373 8d08f18a Kostas Papadimitriou
                host_ip_v6: this.get_addresses().ip6,
1374 8d08f18a Kostas Papadimitriou
                host: data.host,
1375 8d08f18a Kostas Papadimitriou
                port: data.port,
1376 8d08f18a Kostas Papadimitriou
                password: data.password
1377 8d08f18a Kostas Papadimitriou
            }
1378 8d08f18a Kostas Papadimitriou
            return '/machines/console?' + $.param(url_params);
1379 8d08f18a Kostas Papadimitriou
        },
1380 8d08f18a Kostas Papadimitriou
1381 8d08f18a Kostas Papadimitriou
        // action helper
1382 738a9b18 Kostas Papadimitriou
        call: function(action_name, success, error, params) {
1383 8d08f18a Kostas Papadimitriou
            var id_param = [this.id];
1384 738a9b18 Kostas Papadimitriou
            
1385 738a9b18 Kostas Papadimitriou
            params = params || {};
1386 8d08f18a Kostas Papadimitriou
            success = success || function() {};
1387 8d08f18a Kostas Papadimitriou
            error = error || function() {};
1388 8d08f18a Kostas Papadimitriou
1389 8d08f18a Kostas Papadimitriou
            var self = this;
1390 8d08f18a Kostas Papadimitriou
1391 8d08f18a Kostas Papadimitriou
            switch(action_name) {
1392 8d08f18a Kostas Papadimitriou
                case 'start':
1393 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.get_action_url(), // vm actions url
1394 8d08f18a Kostas Papadimitriou
                                         "create", // create so that sync later uses POST to make the call
1395 8d08f18a Kostas Papadimitriou
                                         {start:{}}, // payload
1396 8d08f18a Kostas Papadimitriou
                                         function() {
1397 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1398 8d08f18a Kostas Papadimitriou
                                             self.state("START"); 
1399 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments);
1400 8d08f18a Kostas Papadimitriou
                                             snf.api.trigger("call");
1401 8d08f18a Kostas Papadimitriou
                                         },  
1402 738a9b18 Kostas Papadimitriou
                                         error, 'start', params);
1403 8d08f18a Kostas Papadimitriou
                    break;
1404 8d08f18a Kostas Papadimitriou
                case 'reboot':
1405 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.get_action_url(), // vm actions url
1406 8d08f18a Kostas Papadimitriou
                                         "create", // create so that sync later uses POST to make the call
1407 8d08f18a Kostas Papadimitriou
                                         {reboot:{type:"HARD"}}, // payload
1408 8d08f18a Kostas Papadimitriou
                                         function() {
1409 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1410 8d08f18a Kostas Papadimitriou
                                             self.state("REBOOT"); 
1411 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments)
1412 8d08f18a Kostas Papadimitriou
                                             snf.api.trigger("call");
1413 122850c5 Kostas Papadimitriou
                                             self.set({'reboot_required': false});
1414 8d08f18a Kostas Papadimitriou
                                         },
1415 738a9b18 Kostas Papadimitriou
                                         error, 'reboot', params);
1416 8d08f18a Kostas Papadimitriou
                    break;
1417 8d08f18a Kostas Papadimitriou
                case 'shutdown':
1418 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.get_action_url(), // vm actions url
1419 8d08f18a Kostas Papadimitriou
                                         "create", // create so that sync later uses POST to make the call
1420 8d08f18a Kostas Papadimitriou
                                         {shutdown:{}}, // payload
1421 8d08f18a Kostas Papadimitriou
                                         function() {
1422 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1423 8d08f18a Kostas Papadimitriou
                                             self.state("SHUTDOWN"); 
1424 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments)
1425 8d08f18a Kostas Papadimitriou
                                             snf.api.trigger("call");
1426 8d08f18a Kostas Papadimitriou
                                         },  
1427 738a9b18 Kostas Papadimitriou
                                         error, 'shutdown', params);
1428 8d08f18a Kostas Papadimitriou
                    break;
1429 8d08f18a Kostas Papadimitriou
                case 'console':
1430 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.url() + "/action", "create", {'console': {'type':'vnc'}}, function(data) {
1431 8d08f18a Kostas Papadimitriou
                        var cons_data = data.console;
1432 8d08f18a Kostas Papadimitriou
                        success.apply(this, [cons_data]);
1433 738a9b18 Kostas Papadimitriou
                    }, undefined, 'console', params)
1434 8d08f18a Kostas Papadimitriou
                    break;
1435 8d08f18a Kostas Papadimitriou
                case 'destroy':
1436 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.url(), // vm actions url
1437 8d08f18a Kostas Papadimitriou
                                         "delete", // create so that sync later uses POST to make the call
1438 8d08f18a Kostas Papadimitriou
                                         undefined, // payload
1439 8d08f18a Kostas Papadimitriou
                                         function() {
1440 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1441 8d08f18a Kostas Papadimitriou
                                             self.state('DESTROY');
1442 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments)
1443 8d08f18a Kostas Papadimitriou
                                         },  
1444 738a9b18 Kostas Papadimitriou
                                         error, 'destroy', params);
1445 8d08f18a Kostas Papadimitriou
                    break;
1446 8d08f18a Kostas Papadimitriou
                default:
1447 8d08f18a Kostas Papadimitriou
                    throw "Invalid VM action ("+action_name+")";
1448 8d08f18a Kostas Papadimitriou
            }
1449 8d08f18a Kostas Papadimitriou
        },
1450 8d08f18a Kostas Papadimitriou
        
1451 738a9b18 Kostas Papadimitriou
        __make_api_call: function(url, method, data, success, error, action, extra_params) {
1452 8d08f18a Kostas Papadimitriou
            var self = this;
1453 8d08f18a Kostas Papadimitriou
            error = error || function(){};
1454 8d08f18a Kostas Papadimitriou
            success = success || function(){};
1455 8d08f18a Kostas Papadimitriou
1456 8d08f18a Kostas Papadimitriou
            var params = {
1457 8d08f18a Kostas Papadimitriou
                url: url,
1458 8d08f18a Kostas Papadimitriou
                data: data,
1459 8d08f18a Kostas Papadimitriou
                success: function(){ self.handle_action_succeed.apply(self, arguments); success.apply(this, arguments)},
1460 edd1d565 Kostas Papadimitriou
                error: function(){ self.handle_action_fail.apply(self, arguments); error.apply(this, arguments)},
1461 edd1d565 Kostas Papadimitriou
                error_params: { ns: "Machines actions", 
1462 9ffd10ce Kostas Papadimitriou
                                title: "'" + this.get("name") + "'" + " " + action + " failed", 
1463 6a3a5bf7 Kostas Papadimitriou
                                extra_details: { 'Machine ID': this.id, 'URL': url, 'Action': action || "undefined" },
1464 6a3a5bf7 Kostas Papadimitriou
                                allow_reload: false
1465 6a3a5bf7 Kostas Papadimitriou
                              },
1466 9ce969a7 Kostas Papadimitriou
                display: false,
1467 9ce969a7 Kostas Papadimitriou
                critical: false
1468 8d08f18a Kostas Papadimitriou
            }
1469 738a9b18 Kostas Papadimitriou
            _.extend(params, extra_params)
1470 8d08f18a Kostas Papadimitriou
            this.sync(method, this, params);
1471 8d08f18a Kostas Papadimitriou
        },
1472 8d08f18a Kostas Papadimitriou
1473 8d08f18a Kostas Papadimitriou
        handle_action_succeed: function() {
1474 8d08f18a Kostas Papadimitriou
            this.trigger("action:success", arguments);
1475 8d08f18a Kostas Papadimitriou
        },
1476 6a3a5bf7 Kostas Papadimitriou
        
1477 6a3a5bf7 Kostas Papadimitriou
        reset_action_error: function() {
1478 6a3a5bf7 Kostas Papadimitriou
            this.action_error = false;
1479 6a3a5bf7 Kostas Papadimitriou
            this.trigger("action:fail:reset", this.action_error);
1480 6a3a5bf7 Kostas Papadimitriou
        },
1481 8d08f18a Kostas Papadimitriou
1482 8d08f18a Kostas Papadimitriou
        handle_action_fail: function() {
1483 6a3a5bf7 Kostas Papadimitriou
            this.action_error = arguments;
1484 8d08f18a Kostas Papadimitriou
            this.trigger("action:fail", arguments);
1485 8d08f18a Kostas Papadimitriou
        },
1486 8d08f18a Kostas Papadimitriou
1487 8d08f18a Kostas Papadimitriou
        get_action_url: function(name) {
1488 8d08f18a Kostas Papadimitriou
            return this.url() + "/action";
1489 1c922789 Kostas Papadimitriou
        },
1490 1c922789 Kostas Papadimitriou
1491 1e882dd7 Kostas Papadimitriou
        get_diagnostics_url: function() {
1492 1e882dd7 Kostas Papadimitriou
            return this.url() + "/diagnostics";
1493 1e882dd7 Kostas Papadimitriou
        },
1494 1e882dd7 Kostas Papadimitriou
1495 1c922789 Kostas Papadimitriou
        get_connection_info: function(host_os, success, error) {
1496 1c922789 Kostas Papadimitriou
            var url = "/machines/connect";
1497 1c922789 Kostas Papadimitriou
            params = {
1498 3796f345 Kostas Papadimitriou
                ip_address: this.get_public_nic().get('ipv4'),
1499 3796f345 Kostas Papadimitriou
                hostname: this.get_hostname(),
1500 1c922789 Kostas Papadimitriou
                os: this.get_os(),
1501 1c922789 Kostas Papadimitriou
                host_os: host_os,
1502 1c922789 Kostas Papadimitriou
                srv: this.id
1503 1c922789 Kostas Papadimitriou
            }
1504 1c922789 Kostas Papadimitriou
1505 1c922789 Kostas Papadimitriou
            url = url + "?" + $.param(params);
1506 1c922789 Kostas Papadimitriou
1507 1c922789 Kostas Papadimitriou
            var ajax = snf.api.sync("read", undefined, { url: url, 
1508 1c922789 Kostas Papadimitriou
                                                         error:error, 
1509 1c922789 Kostas Papadimitriou
                                                         success:success, 
1510 1c922789 Kostas Papadimitriou
                                                         handles_error:1});
1511 8d08f18a Kostas Papadimitriou
        }
1512 8d08f18a Kostas Papadimitriou
    })
1513 8d08f18a Kostas Papadimitriou
    
1514 8d08f18a Kostas Papadimitriou
    models.VM.ACTIONS = [
1515 8d08f18a Kostas Papadimitriou
        'start',
1516 8d08f18a Kostas Papadimitriou
        'shutdown',
1517 8d08f18a Kostas Papadimitriou
        'reboot',
1518 0f7214b3 Kostas Papadimitriou
        'console',
1519 8d08f18a Kostas Papadimitriou
        'destroy'
1520 8d08f18a Kostas Papadimitriou
    ]
1521 8d08f18a Kostas Papadimitriou
1522 8d08f18a Kostas Papadimitriou
    models.VM.AVAILABLE_ACTIONS = {
1523 8d08f18a Kostas Papadimitriou
        'UNKNWON'       : ['destroy'],
1524 8d08f18a Kostas Papadimitriou
        'BUILD'         : ['destroy'],
1525 8d08f18a Kostas Papadimitriou
        'REBOOT'        : ['shutdown', 'destroy', 'console'],
1526 8d08f18a Kostas Papadimitriou
        'STOPPED'       : ['start', 'destroy'],
1527 8d08f18a Kostas Papadimitriou
        'ACTIVE'        : ['shutdown', 'destroy', 'reboot', 'console'],
1528 8d08f18a Kostas Papadimitriou
        'ERROR'         : ['destroy'],
1529 643de8c0 Kostas Papadimitriou
        'DELETED'        : [],
1530 8d08f18a Kostas Papadimitriou
        'DESTROY'       : [],
1531 8d08f18a Kostas Papadimitriou
        'BUILD_INIT'    : ['destroy'],
1532 8d08f18a Kostas Papadimitriou
        'BUILD_COPY'    : ['destroy'],
1533 8d08f18a Kostas Papadimitriou
        'BUILD_FINAL'   : ['destroy'],
1534 8d08f18a Kostas Papadimitriou
        'SHUTDOWN'      : ['destroy'],
1535 8d08f18a Kostas Papadimitriou
        'START'         : [],
1536 8d08f18a Kostas Papadimitriou
        'CONNECT'       : [],
1537 8d08f18a Kostas Papadimitriou
        'DISCONNECT'    : []
1538 8d08f18a Kostas Papadimitriou
    }
1539 8d08f18a Kostas Papadimitriou
1540 8d08f18a Kostas Papadimitriou
    // api status values
1541 8d08f18a Kostas Papadimitriou
    models.VM.STATUSES = [
1542 8d08f18a Kostas Papadimitriou
        'UNKNWON',
1543 8d08f18a Kostas Papadimitriou
        'BUILD',
1544 8d08f18a Kostas Papadimitriou
        'REBOOT',
1545 8d08f18a Kostas Papadimitriou
        'STOPPED',
1546 8d08f18a Kostas Papadimitriou
        'ACTIVE',
1547 8d08f18a Kostas Papadimitriou
        'ERROR',
1548 643de8c0 Kostas Papadimitriou
        'DELETED'
1549 8d08f18a Kostas Papadimitriou
    ]
1550 8d08f18a Kostas Papadimitriou
1551 8d08f18a Kostas Papadimitriou
    // api status values
1552 8d08f18a Kostas Papadimitriou
    models.VM.CONNECT_STATES = [
1553 8d08f18a Kostas Papadimitriou
        'ACTIVE',
1554 8d08f18a Kostas Papadimitriou
        'REBOOT',
1555 df12e032 Kostas Papadimitriou
        'SHUTDOWN'
1556 8d08f18a Kostas Papadimitriou
    ]
1557 8d08f18a Kostas Papadimitriou
1558 8d08f18a Kostas Papadimitriou
    // vm states
1559 8d08f18a Kostas Papadimitriou
    models.VM.STATES = models.VM.STATUSES.concat([
1560 8d08f18a Kostas Papadimitriou
        'DESTROY',
1561 8d08f18a Kostas Papadimitriou
        'BUILD_INIT',
1562 8d08f18a Kostas Papadimitriou
        'BUILD_COPY',
1563 8d08f18a Kostas Papadimitriou
        'BUILD_FINAL',
1564 8d08f18a Kostas Papadimitriou
        'SHUTDOWN',
1565 8d08f18a Kostas Papadimitriou
        'START',
1566 8d08f18a Kostas Papadimitriou
        'CONNECT',
1567 8d08f18a Kostas Papadimitriou
        'DISCONNECT',
1568 8d08f18a Kostas Papadimitriou
        'FIREWALL'
1569 8d08f18a Kostas Papadimitriou
    ]);
1570 8d08f18a Kostas Papadimitriou
    
1571 8d08f18a Kostas Papadimitriou
    models.VM.STATES_TRANSITIONS = {
1572 643de8c0 Kostas Papadimitriou
        'DESTROY' : ['DELETED'],
1573 8d08f18a Kostas Papadimitriou
        'SHUTDOWN': ['ERROR', 'STOPPED', 'DESTROY'],
1574 8d08f18a Kostas Papadimitriou
        'STOPPED': ['ERROR', 'ACTIVE', 'DESTROY'],
1575 8d08f18a Kostas Papadimitriou
        'ACTIVE': ['ERROR', 'STOPPED', 'REBOOT', 'SHUTDOWN', 'DESTROY'],
1576 8d08f18a Kostas Papadimitriou
        'START': ['ERROR', 'ACTIVE', 'DESTROY'],
1577 8d08f18a Kostas Papadimitriou
        'REBOOT': ['ERROR', 'ACTIVE', 'STOPPED', 'DESTROY'],
1578 8d08f18a Kostas Papadimitriou
        'BUILD': ['ERROR', 'ACTIVE', 'DESTROY'],
1579 8d08f18a Kostas Papadimitriou
        'BUILD_COPY': ['ERROR', 'ACTIVE', 'BUILD_FINAL', 'DESTROY'],
1580 8d08f18a Kostas Papadimitriou
        'BUILD_FINAL': ['ERROR', 'ACTIVE', 'DESTROY'],
1581 8d08f18a Kostas Papadimitriou
        'BUILD_INIT': ['ERROR', 'ACTIVE', 'BUILD_COPY', 'BUILD_FINAL', 'DESTROY']
1582 8d08f18a Kostas Papadimitriou
    }
1583 8d08f18a Kostas Papadimitriou
1584 8d08f18a Kostas Papadimitriou
    models.VM.TRANSITION_STATES = [
1585 8d08f18a Kostas Papadimitriou
        'DESTROY',
1586 8d08f18a Kostas Papadimitriou
        'SHUTDOWN',
1587 8d08f18a Kostas Papadimitriou
        'START',
1588 8d08f18a Kostas Papadimitriou
        'REBOOT',
1589 8d08f18a Kostas Papadimitriou
        'BUILD'
1590 8d08f18a Kostas Papadimitriou
    ]
1591 8d08f18a Kostas Papadimitriou
1592 8d08f18a Kostas Papadimitriou
    models.VM.ACTIVE_STATES = [
1593 8d08f18a Kostas Papadimitriou
        'BUILD', 'REBOOT', 'ACTIVE',
1594 8d08f18a Kostas Papadimitriou
        'BUILD_INIT', 'BUILD_COPY', 'BUILD_FINAL',
1595 4e365467 Kostas Papadimitriou
        'SHUTDOWN', 'CONNECT', 'DISCONNECT'
1596 8d08f18a Kostas Papadimitriou
    ]
1597 8d08f18a Kostas Papadimitriou
1598 8d08f18a Kostas Papadimitriou
    models.VM.BUILDING_STATES = [
1599 8d08f18a Kostas Papadimitriou
        'BUILD', 'BUILD_INIT', 'BUILD_COPY', 'BUILD_FINAL'
1600 8d08f18a Kostas Papadimitriou
    ]
1601 8d08f18a Kostas Papadimitriou
1602 8d08f18a Kostas Papadimitriou
    models.Networks = models.Collection.extend({
1603 8d08f18a Kostas Papadimitriou
        model: models.Network,
1604 8d08f18a Kostas Papadimitriou
        path: 'networks',
1605 8d08f18a Kostas Papadimitriou
        details: true,
1606 8d08f18a Kostas Papadimitriou
        //noUpdate: true,
1607 126a01f2 Kostas Papadimitriou
        defaults: {'nics':[],'linked_to':[]},
1608 126a01f2 Kostas Papadimitriou
        
1609 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1610 8d08f18a Kostas Papadimitriou
            // FIXME: depricated global var
1611 8d08f18a Kostas Papadimitriou
            if (!resp) { return []};
1612 01461689 Kostas Papadimitriou
            var data = _.filter(_.map(resp.networks.values, _.bind(this.parse_net_api_data, this)),
1613 01461689 Kostas Papadimitriou
                               function(e){ return e });
1614 8d08f18a Kostas Papadimitriou
            return data;
1615 8d08f18a Kostas Papadimitriou
        },
1616 8d08f18a Kostas Papadimitriou
1617 126a01f2 Kostas Papadimitriou
        add: function() {
1618 126a01f2 Kostas Papadimitriou
            ret = models.Networks.__super__.add.apply(this, arguments);
1619 126a01f2 Kostas Papadimitriou
            // update nics after each network addition
1620 126a01f2 Kostas Papadimitriou
            ret.each(function(r){
1621 126a01f2 Kostas Papadimitriou
                synnefo.storage.nics.update_net_nics(r);
1622 126a01f2 Kostas Papadimitriou
            });
1623 126a01f2 Kostas Papadimitriou
        },
1624 126a01f2 Kostas Papadimitriou
1625 101e6604 Kostas Papadimitriou
        reset_pending_actions: function() {
1626 101e6604 Kostas Papadimitriou
            this.each(function(net) {
1627 101e6604 Kostas Papadimitriou
                net.get("actions").reset();
1628 126a01f2 Kostas Papadimitriou
            });
1629 101e6604 Kostas Papadimitriou
        },
1630 101e6604 Kostas Papadimitriou
1631 101e6604 Kostas Papadimitriou
        do_all_pending_actions: function() {
1632 101e6604 Kostas Papadimitriou
            this.each(function(net) {
1633 101e6604 Kostas Papadimitriou
                net.do_all_pending_actions();
1634 101e6604 Kostas Papadimitriou
            })
1635 101e6604 Kostas Papadimitriou
        },
1636 101e6604 Kostas Papadimitriou
1637 8d08f18a Kostas Papadimitriou
        parse_net_api_data: function(data) {
1638 126a01f2 Kostas Papadimitriou
            // append nic metadata
1639 126a01f2 Kostas Papadimitriou
            // net.get('nics') contains a list of vm/index objects 
1640 126a01f2 Kostas Papadimitriou
            // e.g. {'vm_id':12231, 'index':1}
1641 126a01f2 Kostas Papadimitriou
            // net.get('linked_to') contains a list of vms the network is 
1642 126a01f2 Kostas Papadimitriou
            // connected to e.g. [1001, 1002]
1643 126a01f2 Kostas Papadimitriou
            if (data.attachments && data.attachments.values) {
1644 126a01f2 Kostas Papadimitriou
                data['nics'] = {};
1645 126a01f2 Kostas Papadimitriou
                data['linked_to'] = [];
1646 126a01f2 Kostas Papadimitriou
                _.each(data.attachments.values, function(nic_id){
1647 126a01f2 Kostas Papadimitriou
                  
1648 126a01f2 Kostas Papadimitriou
                  var vm_id = NIC_REGEX.exec(nic_id)[1];
1649 126a01f2 Kostas Papadimitriou
                  var nic_index = parseInt(NIC_REGEX.exec(nic_id)[2]);
1650 126a01f2 Kostas Papadimitriou
1651 126a01f2 Kostas Papadimitriou
                  if (vm_id !== undefined && nic_index !== undefined) {
1652 126a01f2 Kostas Papadimitriou
                      data['nics'][nic_id] = {
1653 126a01f2 Kostas Papadimitriou
                          'vm_id': vm_id, 
1654 126a01f2 Kostas Papadimitriou
                          'index': nic_index, 
1655 126a01f2 Kostas Papadimitriou
                          'id': nic_id
1656 126a01f2 Kostas Papadimitriou
                      };
1657 126a01f2 Kostas Papadimitriou
                      if (data['linked_to'].indexOf(vm_id) == -1) {
1658 126a01f2 Kostas Papadimitriou
                        data['linked_to'].push(vm_id);
1659 126a01f2 Kostas Papadimitriou
                      }
1660 126a01f2 Kostas Papadimitriou
                  }
1661 126a01f2 Kostas Papadimitriou
                });
1662 8d08f18a Kostas Papadimitriou
            }
1663 01461689 Kostas Papadimitriou
1664 01461689 Kostas Papadimitriou
            if (data.status == "DELETED" && !this.get(parseInt(data.id))) {
1665 01461689 Kostas Papadimitriou
              return false;
1666 01461689 Kostas Papadimitriou
            }
1667 8d08f18a Kostas Papadimitriou
            return data;
1668 8d08f18a Kostas Papadimitriou
        },
1669 8d08f18a Kostas Papadimitriou
1670 126a01f2 Kostas Papadimitriou
        create: function (name, type, cidr, dhcp, callback) {
1671 126a01f2 Kostas Papadimitriou
            var params = {
1672 126a01f2 Kostas Papadimitriou
                network:{
1673 126a01f2 Kostas Papadimitriou
                    name:name
1674 126a01f2 Kostas Papadimitriou
                }
1675 126a01f2 Kostas Papadimitriou
            };
1676 126a01f2 Kostas Papadimitriou
1677 126a01f2 Kostas Papadimitriou
            if (type) {
1678 126a01f2 Kostas Papadimitriou
                params.network.type = type;
1679 126a01f2 Kostas Papadimitriou
            }
1680 126a01f2 Kostas Papadimitriou
            if (cidr) {
1681 126a01f2 Kostas Papadimitriou
                params.network.cidr = cidr;
1682 126a01f2 Kostas Papadimitriou
            }
1683 126a01f2 Kostas Papadimitriou
            if (dhcp) {
1684 126a01f2 Kostas Papadimitriou
                params.network.dhcp = dhcp;
1685 126a01f2 Kostas Papadimitriou
            }
1686 126a01f2 Kostas Papadimitriou
1687 126a01f2 Kostas Papadimitriou
            if (dhcp === false) {
1688 126a01f2 Kostas Papadimitriou
                params.network.dhcp = false;
1689 126a01f2 Kostas Papadimitriou
            }
1690 126a01f2 Kostas Papadimitriou
            
1691 126a01f2 Kostas Papadimitriou
            return this.api_call(this.path, "create", params, callback);
1692 6de7fde5 Kostas Papadimitriou
        },
1693 6de7fde5 Kostas Papadimitriou
1694 6de7fde5 Kostas Papadimitriou
        get_public: function(){
1695 6de7fde5 Kostas Papadimitriou
          return this.filter(function(n){return n.get('public')});
1696 8d08f18a Kostas Papadimitriou
        }
1697 8d08f18a Kostas Papadimitriou
    })
1698 8d08f18a Kostas Papadimitriou
1699 8d08f18a Kostas Papadimitriou
    models.Images = models.Collection.extend({
1700 8d08f18a Kostas Papadimitriou
        model: models.Image,
1701 8d08f18a Kostas Papadimitriou
        path: 'images',
1702 8d08f18a Kostas Papadimitriou
        details: true,
1703 8d08f18a Kostas Papadimitriou
        noUpdate: true,
1704 16392650 Kostas Papadimitriou
        supportIncUpdates: false,
1705 8d08f18a Kostas Papadimitriou
        meta_keys_as_attrs: ["OS", "description", "kernel", "size", "GUI"],
1706 88d6d677 Kostas Papadimitriou
        meta_labels: {},
1707 258235f4 Kostas Papadimitriou
        read_method: 'read',
1708 8d08f18a Kostas Papadimitriou
1709 bedfe884 Kostas Papadimitriou
        // update collection model with id passed
1710 1420aae4 Kostas Papadimitriou
        // making a direct call to the image
1711 bedfe884 Kostas Papadimitriou
        // api url
1712 c45bed88 Kostas Papadimitriou
        update_unknown_id: function(id, callback) {
1713 bedfe884 Kostas Papadimitriou
            var url = getUrl.call(this) + "/" + id;
1714 126a01f2 Kostas Papadimitriou
            this.api_call(this.path + "/" + id, this.read_method, {
1715 126a01f2 Kostas Papadimitriou
              _options:{
1716 126a01f2 Kostas Papadimitriou
                async:true, 
1717 126a01f2 Kostas Papadimitriou
                skip_api_error:true}
1718 126a01f2 Kostas Papadimitriou
              }, undefined, 
1719 bedfe884 Kostas Papadimitriou
            _.bind(function() {
1720 327f0d58 Kostas Papadimitriou
                if (!this.get(id)) {
1721 d7612b6e Kostas Papadimitriou
                            if (this.fallback_service) {
1722 d7612b6e Kostas Papadimitriou
                        // if current service has fallback_service attribute set
1723 d7612b6e Kostas Papadimitriou
                        // use this service to retrieve the missing image model
1724 d7612b6e Kostas Papadimitriou
                        var tmpservice = new this.fallback_service();
1725 d7612b6e Kostas Papadimitriou
                        tmpservice.update_unknown_id(id, _.bind(function(img){
1726 d7612b6e Kostas Papadimitriou
                            img.attributes.status = "DELETED";
1727 d7612b6e Kostas Papadimitriou
                            this.add(img.attributes);
1728 d7612b6e Kostas Papadimitriou
                            callback(this.get(id));
1729 d7612b6e Kostas Papadimitriou
                        }, this));
1730 d7612b6e Kostas Papadimitriou
                    } else {
1731 03639c6d Kostas Papadimitriou
                        var title = synnefo.config.image_deleted_title || 'Deleted';
1732 d7612b6e Kostas Papadimitriou
                        // else add a dummy DELETED state image entry
1733 03639c6d Kostas Papadimitriou
                        this.add({id:id, name:title, size:-1, 
1734 d7612b6e Kostas Papadimitriou
                                  progress:100, status:"DELETED"});
1735 d7612b6e Kostas Papadimitriou
                        callback(this.get(id));
1736 d7612b6e Kostas Papadimitriou
                    }   
1737 d7612b6e Kostas Papadimitriou
                } else {
1738 d7612b6e Kostas Papadimitriou
                    callback(this.get(id));
1739 327f0d58 Kostas Papadimitriou
                }
1740 258235f4 Kostas Papadimitriou
            }, this), _.bind(function(image, msg, xhr) {
1741 f70c8d47 Kostas Papadimitriou
                if (!image) {
1742 03639c6d Kostas Papadimitriou
                    var title = synnefo.config.image_deleted_title || 'Deleted';
1743 03639c6d Kostas Papadimitriou
                    this.add({id:id, name:title, size:-1, 
1744 f70c8d47 Kostas Papadimitriou
                              progress:100, status:"DELETED"});
1745 f70c8d47 Kostas Papadimitriou
                    callback(this.get(id));
1746 f70c8d47 Kostas Papadimitriou
                    return;
1747 f70c8d47 Kostas Papadimitriou
                }
1748 258235f4 Kostas Papadimitriou
                var img_data = this._read_image_from_request(image, msg, xhr);
1749 258235f4 Kostas Papadimitriou
                this.add(img_data);
1750 c45bed88 Kostas Papadimitriou
                callback(this.get(id));
1751 bedfe884 Kostas Papadimitriou
            }, this));
1752 bedfe884 Kostas Papadimitriou
        },
1753 bedfe884 Kostas Papadimitriou
1754 258235f4 Kostas Papadimitriou
        _read_image_from_request: function(image, msg, xhr) {
1755 258235f4 Kostas Papadimitriou
            return image.image;
1756 258235f4 Kostas Papadimitriou
        },
1757 258235f4 Kostas Papadimitriou
1758 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1759 8f53cfa3 Kostas Papadimitriou
            var parsed = _.map(resp.images.values, _.bind(this.parse_meta, this));
1760 8f53cfa3 Kostas Papadimitriou
            parsed = this.fill_owners(parsed);
1761 8f53cfa3 Kostas Papadimitriou
            return parsed;
1762 8f53cfa3 Kostas Papadimitriou
        },
1763 8f53cfa3 Kostas Papadimitriou
1764 8f53cfa3 Kostas Papadimitriou
        fill_owners: function(images) {
1765 8f53cfa3 Kostas Papadimitriou
            // do translate uuid->displayname if needed
1766 8f53cfa3 Kostas Papadimitriou
            // store display name in owner attribute for compatibility
1767 8f53cfa3 Kostas Papadimitriou
            var uuids = [];
1768 8f53cfa3 Kostas Papadimitriou
1769 8f53cfa3 Kostas Papadimitriou
            var images = _.map(images, function(img, index) {
1770 8f53cfa3 Kostas Papadimitriou
                if (synnefo.config.translate_uuids) {
1771 8f53cfa3 Kostas Papadimitriou
                    uuids.push(img['owner']);
1772 8f53cfa3 Kostas Papadimitriou
                }
1773 8f53cfa3 Kostas Papadimitriou
                img['owner_uuid'] = img['owner'];
1774 8f53cfa3 Kostas Papadimitriou
                return img;
1775 8f53cfa3 Kostas Papadimitriou
            });
1776 8f53cfa3 Kostas Papadimitriou
            
1777 8f53cfa3 Kostas Papadimitriou
            if (uuids.length > 0) {
1778 8f53cfa3 Kostas Papadimitriou
                var handle_results = function(data) {
1779 8f53cfa3 Kostas Papadimitriou
                    _.each(images, function (img) {
1780 8f53cfa3 Kostas Papadimitriou
                        img['owner'] = data.uuid_catalog[img['owner_uuid']];
1781 8f53cfa3 Kostas Papadimitriou
                    });
1782 8f53cfa3 Kostas Papadimitriou
                }
1783 8f53cfa3 Kostas Papadimitriou
                // notice the async false
1784 8f53cfa3 Kostas Papadimitriou
                var uuid_map = this.translate_uuids(uuids, false, 
1785 8f53cfa3 Kostas Papadimitriou
                                                    handle_results)
1786 8f53cfa3 Kostas Papadimitriou
            }
1787 8f53cfa3 Kostas Papadimitriou
            return images;
1788 8f53cfa3 Kostas Papadimitriou
        },
1789 8f53cfa3 Kostas Papadimitriou
1790 8f53cfa3 Kostas Papadimitriou
        translate_uuids: function(uuids, async, cb) {
1791 8f53cfa3 Kostas Papadimitriou
            var url = synnefo.config.user_catalog_url;
1792 8f53cfa3 Kostas Papadimitriou
            var data = JSON.stringify({'uuids': uuids});
1793 8f53cfa3 Kostas Papadimitriou
          
1794 8f53cfa3 Kostas Papadimitriou
            // post to user_catalogs api
1795 8f53cfa3 Kostas Papadimitriou
            snf.api.sync('create', undefined, {
1796 8f53cfa3 Kostas Papadimitriou
                url: url,
1797 8f53cfa3 Kostas Papadimitriou
                data: data,
1798 8f53cfa3 Kostas Papadimitriou
                async: async,
1799 8f53cfa3 Kostas Papadimitriou
                success:  cb
1800 8f53cfa3 Kostas Papadimitriou
            });
1801 8d08f18a Kostas Papadimitriou
        },
1802 8d08f18a Kostas Papadimitriou
1803 8d08f18a Kostas Papadimitriou
        get_meta_key: function(img, key) {
1804 8d08f18a Kostas Papadimitriou
            if (img.metadata && img.metadata.values && img.metadata.values[key]) {
1805 df251d55 Kostas Papadimitriou
                return _.escape(img.metadata.values[key]);
1806 8d08f18a Kostas Papadimitriou
            }
1807 8d08f18a Kostas Papadimitriou
            return undefined;
1808 8d08f18a Kostas Papadimitriou
        },
1809 8d08f18a Kostas Papadimitriou
1810 ccb14ad0 Kostas Papadimitriou
        comparator: function(img) {
1811 ccb14ad0 Kostas Papadimitriou
            return -img.get_sort_order("sortorder") || 1000 * img.id;
1812 ccb14ad0 Kostas Papadimitriou
        },
1813 ccb14ad0 Kostas Papadimitriou
1814 8d08f18a Kostas Papadimitriou
        parse_meta: function(img) {
1815 8d08f18a Kostas Papadimitriou
            _.each(this.meta_keys_as_attrs, _.bind(function(key){
1816 258235f4 Kostas Papadimitriou
                if (img[key]) { return };
1817 2a5ae934 Kostas Papadimitriou
                img[key] = this.get_meta_key(img, key) || "";
1818 8d08f18a Kostas Papadimitriou
            }, this));
1819 8d08f18a Kostas Papadimitriou
            return img;
1820 bedfe884 Kostas Papadimitriou
        },
1821 bedfe884 Kostas Papadimitriou
1822 bedfe884 Kostas Papadimitriou
        active: function() {
1823 bedfe884 Kostas Papadimitriou
            return this.filter(function(img){return img.get('status') != "DELETED"});
1824 2cee7cb0 Kostas Papadimitriou
        },
1825 2cee7cb0 Kostas Papadimitriou
1826 2cee7cb0 Kostas Papadimitriou
        predefined: function() {
1827 2cee7cb0 Kostas Papadimitriou
            return _.filter(this.active(), function(i) { return !i.get("serverRef")});
1828 948042ca Kostas Papadimitriou
        },
1829 948042ca Kostas Papadimitriou
        
1830 948042ca Kostas Papadimitriou
        fetch_for_type: function(type, complete, error) {
1831 948042ca Kostas Papadimitriou
            this.fetch({update:true, 
1832 948042ca Kostas Papadimitriou
                        success: complete, 
1833 948042ca Kostas Papadimitriou
                        error: error, 
1834 948042ca Kostas Papadimitriou
                        skip_api_error: true });
1835 948042ca Kostas Papadimitriou
        },
1836 948042ca Kostas Papadimitriou
        
1837 948042ca Kostas Papadimitriou
        get_images_for_type: function(type) {
1838 948042ca Kostas Papadimitriou
            if (this['get_{0}_images'.format(type)]) {
1839 948042ca Kostas Papadimitriou
                return this['get_{0}_images'.format(type)]();
1840 948042ca Kostas Papadimitriou
            }
1841 948042ca Kostas Papadimitriou
1842 948042ca Kostas Papadimitriou
            return this.active();
1843 948042ca Kostas Papadimitriou
        },
1844 948042ca Kostas Papadimitriou
1845 948042ca Kostas Papadimitriou
        update_images_for_type: function(type, onStart, onComplete, onError, force_load) {
1846 948042ca Kostas Papadimitriou
            var load = false;
1847 948042ca Kostas Papadimitriou
            error = onError || function() {};
1848 948042ca Kostas Papadimitriou
            function complete(collection) { 
1849 948042ca Kostas Papadimitriou
                onComplete(collection.get_images_for_type(type)); 
1850 948042ca Kostas Papadimitriou
            }
1851 948042ca Kostas Papadimitriou
            
1852 948042ca Kostas Papadimitriou
            // do we need to fetch/update current collection entries
1853 948042ca Kostas Papadimitriou
            if (load) {
1854 948042ca Kostas Papadimitriou
                onStart();
1855 948042ca Kostas Papadimitriou
                this.fetch_for_type(type, complete, error);
1856 948042ca Kostas Papadimitriou
            } else {
1857 948042ca Kostas Papadimitriou
                // fallback to complete
1858 948042ca Kostas Papadimitriou
                complete(this);
1859 948042ca Kostas Papadimitriou
            }
1860 8d08f18a Kostas Papadimitriou
        }
1861 8d08f18a Kostas Papadimitriou
    })
1862 8d08f18a Kostas Papadimitriou
1863 8d08f18a Kostas Papadimitriou
    models.Flavors = models.Collection.extend({
1864 8d08f18a Kostas Papadimitriou
        model: models.Flavor,
1865 8d08f18a Kostas Papadimitriou
        path: 'flavors',
1866 8d08f18a Kostas Papadimitriou
        details: true,
1867 8d08f18a Kostas Papadimitriou
        noUpdate: true,
1868 16392650 Kostas Papadimitriou
        supportIncUpdates: false,
1869 bedfe884 Kostas Papadimitriou
        // update collection model with id passed
1870 bedfe884 Kostas Papadimitriou
        // making a direct call to the flavor
1871 bedfe884 Kostas Papadimitriou
        // api url
1872 c45bed88 Kostas Papadimitriou
        update_unknown_id: function(id, callback) {
1873 bedfe884 Kostas Papadimitriou
            var url = getUrl.call(this) + "/" + id;
1874 258235f4 Kostas Papadimitriou
            this.api_call(this.path + "/" + id, "read", {_options:{async:false, skip_api_error:true}}, undefined, 
1875 bedfe884 Kostas Papadimitriou
            _.bind(function() {
1876 9555268a Kostas Papadimitriou
                this.add({id:id, cpu:"Unknown", ram:"Unknown", disk:"Unknown", name: "Unknown", status:"DELETED"})
1877 bedfe884 Kostas Papadimitriou
            }, this), _.bind(function(flv) {
1878 bedfe884 Kostas Papadimitriou
                if (!flv.flavor.status) { flv.flavor.status = "DELETED" };
1879 bedfe884 Kostas Papadimitriou
                this.add(flv.flavor);
1880 bedfe884 Kostas Papadimitriou
            }, this));
1881 bedfe884 Kostas Papadimitriou
        },
1882 8d08f18a Kostas Papadimitriou
1883 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1884 d965e6dc Kostas Papadimitriou
            return _.map(resp.flavors.values, function(o) { o.disk_template = o['SNF:disk_template']; return o});
1885 8d08f18a Kostas Papadimitriou
        },
1886 8d08f18a Kostas Papadimitriou
1887 ccb14ad0 Kostas Papadimitriou
        comparator: function(flv) {
1888 ccb14ad0 Kostas Papadimitriou
            return flv.get("disk") * flv.get("cpu") * flv.get("ram");
1889 ccb14ad0 Kostas Papadimitriou
        },
1890 ccb14ad0 Kostas Papadimitriou
1891 7ac49c2e Kostas Papadimitriou
        unavailable_values_for_quotas: function(quotas, flavors) {
1892 7ac49c2e Kostas Papadimitriou
            var flavors = flavors || this.active();
1893 7ac49c2e Kostas Papadimitriou
            var index = {cpu:[], disk:[], ram:[]};
1894 7ac49c2e Kostas Papadimitriou
            
1895 7ac49c2e Kostas Papadimitriou
            _.each(flavors, function(el) {
1896 7ac49c2e Kostas Papadimitriou
1897 7ac49c2e Kostas Papadimitriou
                var disk_available = quotas['disk'];
1898 7ac49c2e Kostas Papadimitriou
                var disk_size = el.get_disk_size();
1899 7ac49c2e Kostas Papadimitriou
                if (index.disk.indexOf(disk_size) == -1) {
1900 7ac49c2e Kostas Papadimitriou
                  var disk = el.disk_to_bytes();
1901 7ac49c2e Kostas Papadimitriou
                  if (disk > disk_available) {
1902 7ac49c2e Kostas Papadimitriou
                    index.disk.push(disk_size);
1903 7ac49c2e Kostas Papadimitriou
                  }
1904 7ac49c2e Kostas Papadimitriou
                }
1905 7ac49c2e Kostas Papadimitriou
1906 7ac49c2e Kostas Papadimitriou
                var ram_available = quotas['ram'];
1907 7ac49c2e Kostas Papadimitriou
                var ram_size = el.get_ram_size();
1908 7ac49c2e Kostas Papadimitriou
                if (index.ram.indexOf(disk_size) == -1) {
1909 7ac49c2e Kostas Papadimitriou
                  var ram = el.ram_to_bytes();
1910 7ac49c2e Kostas Papadimitriou
                  if (ram > ram_available) {
1911 7ac49c2e Kostas Papadimitriou
                    index.ram.push(el.get('ram'))
1912 7ac49c2e Kostas Papadimitriou
                  }
1913 7ac49c2e Kostas Papadimitriou
                }
1914 7ac49c2e Kostas Papadimitriou
1915 7ac49c2e Kostas Papadimitriou
                var cpu = el.get('cpu');
1916 7ac49c2e Kostas Papadimitriou
                var cpu_available = quotas['cpu'];
1917 7ac49c2e Kostas Papadimitriou
                if (index.ram.indexOf(cpu) == -1) {
1918 7ac49c2e Kostas Papadimitriou
                  if (cpu > cpu_available) {
1919 7ac49c2e Kostas Papadimitriou
                    index.cpu.push(el.get('cpu'))
1920 7ac49c2e Kostas Papadimitriou
                  }
1921 7ac49c2e Kostas Papadimitriou
                }
1922 7ac49c2e Kostas Papadimitriou
            });
1923 7ac49c2e Kostas Papadimitriou
            return index;
1924 7ac49c2e Kostas Papadimitriou
        },
1925 7ac49c2e Kostas Papadimitriou
1926 820ef2f0 Kostas Papadimitriou
        unavailable_values_for_image: function(img, flavors) {
1927 820ef2f0 Kostas Papadimitriou
            var flavors = flavors || this.active();
1928 820ef2f0 Kostas Papadimitriou
            var size = img.get_size();
1929 820ef2f0 Kostas Papadimitriou
            
1930 820ef2f0 Kostas Papadimitriou
            var index = {cpu:[], disk:[], ram:[]};
1931 820ef2f0 Kostas Papadimitriou
1932 820ef2f0 Kostas Papadimitriou
            _.each(this.active(), function(el) {
1933 820ef2f0 Kostas Papadimitriou
                var img_size = size;
1934 820ef2f0 Kostas Papadimitriou
                var flv_size = el.get_disk_size();
1935 820ef2f0 Kostas Papadimitriou
                if (flv_size < img_size) {
1936 820ef2f0 Kostas Papadimitriou
                    if (index.disk.indexOf(flv_size) == -1) {
1937 820ef2f0 Kostas Papadimitriou
                        index.disk.push(flv_size);
1938 820ef2f0 Kostas Papadimitriou
                    }
1939 820ef2f0 Kostas Papadimitriou
                };
1940 820ef2f0 Kostas Papadimitriou
            });
1941 820ef2f0 Kostas Papadimitriou
            
1942 820ef2f0 Kostas Papadimitriou
            return index;
1943 8d08f18a Kostas Papadimitriou
        },
1944 820ef2f0 Kostas Papadimitriou
1945 d965e6dc Kostas Papadimitriou
        get_flavor: function(cpu, mem, disk, disk_template, filter_list) {
1946 8d08f18a Kostas Papadimitriou
            if (!filter_list) { filter_list = this.models };
1947 d965e6dc Kostas Papadimitriou
            
1948 8d08f18a Kostas Papadimitriou
            return this.select(function(flv){
1949 8d08f18a Kostas Papadimitriou
                if (flv.get("cpu") == cpu + "" &&
1950 8d08f18a Kostas Papadimitriou
                   flv.get("ram") == mem + "" &&
1951 8d08f18a Kostas Papadimitriou
                   flv.get("disk") == disk + "" &&
1952 d965e6dc Kostas Papadimitriou
                   flv.get("disk_template") == disk_template &&
1953 820ef2f0 Kostas Papadimitriou
                   filter_list.indexOf(flv) > -1) { return true; }
1954 9ce969a7 Kostas Papadimitriou
            })[0];
1955 8d08f18a Kostas Papadimitriou
        },
1956 820ef2f0 Kostas Papadimitriou
        
1957 8d08f18a Kostas Papadimitriou
        get_data: function(lst) {
1958 8d08f18a Kostas Papadimitriou
            var data = {'cpu': [], 'mem':[], 'disk':[]};
1959 820ef2f0 Kostas Papadimitriou
1960 8d08f18a Kostas Papadimitriou
            _.each(lst, function(flv) {
1961 820ef2f0 Kostas Papadimitriou
                if (data.cpu.indexOf(flv.get("cpu")) == -1) {
1962 820ef2f0 Kostas Papadimitriou
                    data.cpu.push(flv.get("cpu"));
1963 8d08f18a Kostas Papadimitriou
                }
1964 820ef2f0 Kostas Papadimitriou
                if (data.mem.indexOf(flv.get("ram")) == -1) {
1965 820ef2f0 Kostas Papadimitriou
                    data.mem.push(flv.get("ram"));
1966 8d08f18a Kostas Papadimitriou
                }
1967 820ef2f0 Kostas Papadimitriou
                if (data.disk.indexOf(flv.get("disk")) == -1) {
1968 820ef2f0 Kostas Papadimitriou
                    data.disk.push(flv.get("disk"));
1969 8d08f18a Kostas Papadimitriou
                }
1970 8d08f18a Kostas Papadimitriou
            })
1971 820ef2f0 Kostas Papadimitriou
            
1972 8d08f18a Kostas Papadimitriou
            return data;
1973 bedfe884 Kostas Papadimitriou
        },
1974 bedfe884 Kostas Papadimitriou
1975 bedfe884 Kostas Papadimitriou
        active: function() {
1976 bedfe884 Kostas Papadimitriou
            return this.filter(function(flv){return flv.get('status') != "DELETED"});
1977 8d08f18a Kostas Papadimitriou
        }
1978 8d08f18a Kostas Papadimitriou
            
1979 8d08f18a Kostas Papadimitriou
    })
1980 8d08f18a Kostas Papadimitriou
1981 8d08f18a Kostas Papadimitriou
    models.VMS = models.Collection.extend({
1982 8d08f18a Kostas Papadimitriou
        model: models.VM,
1983 8d08f18a Kostas Papadimitriou
        path: 'servers',
1984 8d08f18a Kostas Papadimitriou
        details: true,
1985 8d08f18a Kostas Papadimitriou
        copy_image_meta: true,
1986 126a01f2 Kostas Papadimitriou
1987 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1988 8d08f18a Kostas Papadimitriou
            var data = resp;
1989 8d08f18a Kostas Papadimitriou
            if (!resp) { return [] };
1990 820ef2f0 Kostas Papadimitriou
            data = _.filter(_.map(resp.servers.values, _.bind(this.parse_vm_api_data, this)), function(v){return v});
1991 8d08f18a Kostas Papadimitriou
            return data;
1992 8d08f18a Kostas Papadimitriou
        },
1993 126a01f2 Kostas Papadimitriou
1994 1e882dd7 Kostas Papadimitriou
        parse_vm_api_data: function(data) {
1995 1e882dd7 Kostas Papadimitriou
            // do not add non existing DELETED entries
1996 1e882dd7 Kostas Papadimitriou
            if (data.status && data.status == "DELETED") {
1997 1e882dd7 Kostas Papadimitriou
                if (!this.get(data.id)) {
1998 1e882dd7 Kostas Papadimitriou
                    return false;
1999 1e882dd7 Kostas Papadimitriou
                }
2000 1e882dd7 Kostas Papadimitriou
            }
2001 1e882dd7 Kostas Papadimitriou
2002 1e882dd7 Kostas Papadimitriou
            // OS attribute
2003 1e882dd7 Kostas Papadimitriou
            if (this.has_meta(data)) {
2004 1e882dd7 Kostas Papadimitriou
                data['OS'] = data.metadata.values.OS || "okeanos";
2005 1e882dd7 Kostas Papadimitriou
            }
2006 1e882dd7 Kostas Papadimitriou
            
2007 1e882dd7 Kostas Papadimitriou
            if (!data.diagnostics) {
2008 1e882dd7 Kostas Papadimitriou
                data.diagnostics = [];
2009 1e882dd7 Kostas Papadimitriou
            }
2010 1e882dd7 Kostas Papadimitriou
2011 1e882dd7 Kostas Papadimitriou
            // network metadata
2012 1e882dd7 Kostas Papadimitriou
            data['firewalls'] = {};
2013 1e882dd7 Kostas Papadimitriou
            data['nics'] = {};
2014 1e882dd7 Kostas Papadimitriou
            data['linked_to'] = [];
2015 1e882dd7 Kostas Papadimitriou
2016 1e882dd7 Kostas Papadimitriou
            if (data['attachments'] && data['attachments'].values) {
2017 1e882dd7 Kostas Papadimitriou
                var nics = data['attachments'].values;
2018 1e882dd7 Kostas Papadimitriou
                _.each(nics, function(nic) {
2019 1e882dd7 Kostas Papadimitriou
                    var net_id = nic.network_id;
2020 1e882dd7 Kostas Papadimitriou
                    var index = parseInt(NIC_REGEX.exec(nic.id)[2]);
2021 1e882dd7 Kostas Papadimitriou
                    if (data['linked_to'].indexOf(net_id) == -1) {
2022 1e882dd7 Kostas Papadimitriou
                        data['linked_to'].push(net_id);
2023 1e882dd7 Kostas Papadimitriou
                    }
2024 1e882dd7 Kostas Papadimitriou
2025 1e882dd7 Kostas Papadimitriou
                    data['nics'][nic.id] = nic;
2026 1e882dd7 Kostas Papadimitriou
                })
2027 1e882dd7 Kostas Papadimitriou
            }
2028 1e882dd7 Kostas Papadimitriou
            
2029 1e882dd7 Kostas Papadimitriou
            // if vm has no metadata, no metadata object
2030 1e882dd7 Kostas Papadimitriou
            // is in json response, reset it to force
2031 1e882dd7 Kostas Papadimitriou
            // value update
2032 1e882dd7 Kostas Papadimitriou
            if (!data['metadata']) {
2033 1e882dd7 Kostas Papadimitriou
                data['metadata'] = {values:{}};
2034 1e882dd7 Kostas Papadimitriou
            }
2035 1e882dd7 Kostas Papadimitriou
2036 1e882dd7 Kostas Papadimitriou
            return data;
2037 1e882dd7 Kostas Papadimitriou
        },
2038 1e882dd7 Kostas Papadimitriou
2039 126a01f2 Kostas Papadimitriou
        add: function() {
2040 126a01f2 Kostas Papadimitriou
            ret = models.VMS.__super__.add.apply(this, arguments);
2041 126a01f2 Kostas Papadimitriou
            ret.each(function(r){
2042 126a01f2 Kostas Papadimitriou
                synnefo.storage.nics.update_vm_nics(r);
2043 126a01f2 Kostas Papadimitriou
            });
2044 126a01f2 Kostas Papadimitriou
        },
2045 122850c5 Kostas Papadimitriou
        
2046 122850c5 Kostas Papadimitriou
        get_reboot_required: function() {
2047 122850c5 Kostas Papadimitriou
            return this.filter(function(vm){return vm.get("reboot_required") == true})
2048 122850c5 Kostas Papadimitriou
        },
2049 122850c5 Kostas Papadimitriou
2050 122850c5 Kostas Papadimitriou
        has_pending_actions: function() {
2051 122850c5 Kostas Papadimitriou
            return this.filter(function(vm){return vm.pending_action}).length > 0;
2052 122850c5 Kostas Papadimitriou
        },
2053 8d08f18a Kostas Papadimitriou
2054 8d08f18a Kostas Papadimitriou
        reset_pending_actions: function() {
2055 8d08f18a Kostas Papadimitriou
            this.each(function(vm) {
2056 8d08f18a Kostas Papadimitriou
                vm.clear_pending_action();
2057 8d08f18a Kostas Papadimitriou
            })
2058 8d08f18a Kostas Papadimitriou
        },
2059 101e6604 Kostas Papadimitriou
2060 101e6604 Kostas Papadimitriou
        do_all_pending_actions: function(success, error) {
2061 101e6604 Kostas Papadimitriou
            this.each(function(vm) {
2062 101e6604 Kostas Papadimitriou
                if (vm.has_pending_action()) {
2063 101e6604 Kostas Papadimitriou
                    vm.call(vm.pending_action, success, error);
2064 101e6604 Kostas Papadimitriou
                    vm.clear_pending_action();
2065 101e6604 Kostas Papadimitriou
                }
2066 101e6604 Kostas Papadimitriou
            })
2067 101e6604 Kostas Papadimitriou
        },
2068 101e6604 Kostas Papadimitriou
        
2069 101e6604 Kostas Papadimitriou
        do_all_reboots: function(success, error) {
2070 101e6604 Kostas Papadimitriou
            this.each(function(vm) {
2071 101e6604 Kostas Papadimitriou
                if (vm.get("reboot_required")) {
2072 101e6604 Kostas Papadimitriou
                    vm.call("reboot", success, error);
2073 101e6604 Kostas Papadimitriou
                }
2074 101e6604 Kostas Papadimitriou
            });
2075 101e6604 Kostas Papadimitriou
        },
2076 101e6604 Kostas Papadimitriou
2077 101e6604 Kostas Papadimitriou
        reset_reboot_required: function() {
2078 101e6604 Kostas Papadimitriou
            this.each(function(vm) {
2079 101e6604 Kostas Papadimitriou
                vm.set({'reboot_required': undefined});
2080 101e6604 Kostas Papadimitriou
            })
2081 101e6604 Kostas Papadimitriou
        },
2082 2c9bfad1 Kostas Papadimitriou
        
2083 2c9bfad1 Kostas Papadimitriou
        stop_stats_update: function(exclude) {
2084 2c9bfad1 Kostas Papadimitriou
            var exclude = exclude || [];
2085 96d725ac Kostas Papadimitriou
            this.each(function(vm) {
2086 2c9bfad1 Kostas Papadimitriou
                if (exclude.indexOf(vm) > -1) {
2087 2c9bfad1 Kostas Papadimitriou
                    return;
2088 2c9bfad1 Kostas Papadimitriou
                }
2089 2c9bfad1 Kostas Papadimitriou
                vm.stop_stats_update();
2090 96d725ac Kostas Papadimitriou
            })
2091 96d725ac Kostas Papadimitriou
        },
2092 8d08f18a Kostas Papadimitriou
        
2093 8d08f18a Kostas Papadimitriou
        has_meta: function(vm_data) {
2094 8d08f18a Kostas Papadimitriou
            return vm_data.metadata && vm_data.metadata.values
2095 8d08f18a Kostas Papadimitriou
        },
2096 8d08f18a Kostas Papadimitriou
2097 8d08f18a Kostas Papadimitriou
        has_addresses: function(vm_data) {
2098 8d08f18a Kostas Papadimitriou
            return vm_data.metadata && vm_data.metadata.values
2099 8d08f18a Kostas Papadimitriou
        },
2100 8d08f18a Kostas Papadimitriou
2101 8d08f18a Kostas Papadimitriou
        create: function (name, image, flavor, meta, extra, callback) {
2102 88d6d677 Kostas Papadimitriou
2103 8d08f18a Kostas Papadimitriou
            if (this.copy_image_meta) {
2104 88d6d677 Kostas Papadimitriou
                if (synnefo.config.vm_image_common_metadata) {
2105 88d6d677 Kostas Papadimitriou
                    _.each(synnefo.config.vm_image_common_metadata, 
2106 88d6d677 Kostas Papadimitriou
                        function(key){
2107 88d6d677 Kostas Papadimitriou
                            if (image.get_meta(key)) {
2108 88d6d677 Kostas Papadimitriou
                                meta[key] = image.get_meta(key);
2109 88d6d677 Kostas Papadimitriou
                            }
2110 88d6d677 Kostas Papadimitriou
                    });
2111 88d6d677 Kostas Papadimitriou
                }
2112 88d6d677 Kostas Papadimitriou
2113 d5ba5588 Kostas Papadimitriou
                if (image.get("OS")) {
2114 d5ba5588 Kostas Papadimitriou
                    meta['OS'] = image.get("OS");
2115 d5ba5588 Kostas Papadimitriou
                }
2116 88d6d677 Kostas Papadimitriou
            }
2117 8d08f18a Kostas Papadimitriou
            
2118 8d08f18a Kostas Papadimitriou
            opts = {name: name, imageRef: image.id, flavorRef: flavor.id, metadata:meta}
2119 8d08f18a Kostas Papadimitriou
            opts = _.extend(opts, extra);
2120 8d08f18a Kostas Papadimitriou
2121 ce93b80c Kostas Papadimitriou
            this.api_call(this.path, "create", {'server': opts}, undefined, undefined, callback, {critical: true});
2122 336ddd59 Kostas Papadimitriou
        },
2123 336ddd59 Kostas Papadimitriou
2124 336ddd59 Kostas Papadimitriou
        load_missing_images: function(callback) {
2125 336ddd59 Kostas Papadimitriou
          var missing_ids = [];
2126 336ddd59 Kostas Papadimitriou
          this.each(function(el) {
2127 336ddd59 Kostas Papadimitriou
            var imgid = el.get("imageRef");
2128 336ddd59 Kostas Papadimitriou
            var existing = synnefo.storage.images.get(imgid);
2129 336ddd59 Kostas Papadimitriou
            if (!existing && missing_ids.indexOf(imgid) == -1) {
2130 336ddd59 Kostas Papadimitriou
                missing_ids.push(imgid);
2131 336ddd59 Kostas Papadimitriou
                synnefo.storage.images.update_unknown_id(imgid, function(){});
2132 336ddd59 Kostas Papadimitriou
            }
2133 336ddd59 Kostas Papadimitriou
          });
2134 336ddd59 Kostas Papadimitriou
          callback(missing_ids);
2135 8d08f18a Kostas Papadimitriou
        }
2136 8d08f18a Kostas Papadimitriou
2137 8d08f18a Kostas Papadimitriou
    })
2138 126a01f2 Kostas Papadimitriou
    
2139 126a01f2 Kostas Papadimitriou
    models.NIC = models.Model.extend({
2140 126a01f2 Kostas Papadimitriou
        
2141 126a01f2 Kostas Papadimitriou
        initialize: function() {
2142 126a01f2 Kostas Papadimitriou
            models.NIC.__super__.initialize.apply(this, arguments);
2143 126a01f2 Kostas Papadimitriou
            this.pending_for_firewall = false;
2144 126a01f2 Kostas Papadimitriou
            this.bind("change:firewallProfile", _.bind(this.check_firewall, this));
2145 126a01f2 Kostas Papadimitriou
            this.bind("change:pending_firewall", function(nic) {
2146 126a01f2 Kostas Papadimitriou
                nic.get_network().update_state();
2147 126a01f2 Kostas Papadimitriou
            });
2148 126a01f2 Kostas Papadimitriou
            this.get_vm().bind("remove", function(){
2149 97d3fca1 Kostas Papadimitriou
                try {
2150 97d3fca1 Kostas Papadimitriou
                    this.collection.remove(this);
2151 97d3fca1 Kostas Papadimitriou
                } catch (err) {};
2152 126a01f2 Kostas Papadimitriou
            }, this);
2153 126a01f2 Kostas Papadimitriou
            this.get_network().bind("remove", function(){
2154 126a01f2 Kostas Papadimitriou
                try {
2155 126a01f2 Kostas Papadimitriou
                    this.collection.remove(this);
2156 126a01f2 Kostas Papadimitriou
                } catch (err) {};
2157 126a01f2 Kostas Papadimitriou
            }, this);
2158 e49565e1 Kostas Papadimitriou
2159 126a01f2 Kostas Papadimitriou
        },
2160 126a01f2 Kostas Papadimitriou
2161 126a01f2 Kostas Papadimitriou
        get_vm: function() {
2162 126a01f2 Kostas Papadimitriou
            return synnefo.storage.vms.get(parseInt(this.get('vm_id')));
2163 126a01f2 Kostas Papadimitriou
        },
2164 126a01f2 Kostas Papadimitriou
2165 126a01f2 Kostas Papadimitriou
        get_network: function() {
2166 126a01f2 Kostas Papadimitriou
            return synnefo.storage.networks.get(this.get('network_id'));
2167 126a01f2 Kostas Papadimitriou
        },
2168 126a01f2 Kostas Papadimitriou
2169 126a01f2 Kostas Papadimitriou
        get_v6_address: function() {
2170 126a01f2 Kostas Papadimitriou
            return this.get("ipv6");
2171 126a01f2 Kostas Papadimitriou
        },
2172 126a01f2 Kostas Papadimitriou
2173 126a01f2 Kostas Papadimitriou
        get_v4_address: function() {
2174 126a01f2 Kostas Papadimitriou
            return this.get("ipv4");
2175 126a01f2 Kostas Papadimitriou
        },
2176 126a01f2 Kostas Papadimitriou
2177 126a01f2 Kostas Papadimitriou
        set_firewall: function(value, callback, error, options) {
2178 126a01f2 Kostas Papadimitriou
            var net_id = this.get('network_id');
2179 126a01f2 Kostas Papadimitriou
            var self = this;
2180 126a01f2 Kostas Papadimitriou
2181 126a01f2 Kostas Papadimitriou
            // api call data
2182 126a01f2 Kostas Papadimitriou
            var payload = {"firewallProfile":{"profile":value}};
2183 126a01f2 Kostas Papadimitriou
            payload._options = _.extend({critical: false}, options);
2184 126a01f2 Kostas Papadimitriou
            
2185 126a01f2 Kostas Papadimitriou
            this.set({'pending_firewall': value});
2186 126a01f2 Kostas Papadimitriou
            this.set({'pending_firewall_sending': true});
2187 4792afbe Kostas Papadimitriou
            this.set({'pending_firewall_from': this.get('firewallProfile')});
2188 126a01f2 Kostas Papadimitriou
2189 126a01f2 Kostas Papadimitriou
            var success_cb = function() {
2190 126a01f2 Kostas Papadimitriou
                if (callback) {
2191 126a01f2 Kostas Papadimitriou
                    callback();
2192 126a01f2 Kostas Papadimitriou
                }
2193 126a01f2 Kostas Papadimitriou
                self.set({'pending_firewall_sending': false});
2194 126a01f2 Kostas Papadimitriou
            };
2195 126a01f2 Kostas Papadimitriou
2196 126a01f2 Kostas Papadimitriou
            var error_cb = function() {
2197 126a01f2 Kostas Papadimitriou
                self.reset_pending_firewall();
2198 126a01f2 Kostas Papadimitriou
            }
2199 126a01f2 Kostas Papadimitriou
            
2200 126a01f2 Kostas Papadimitriou
            this.get_vm().api_call(this.get_vm().api_path() + "/action", "create", payload, success_cb, error_cb);
2201 126a01f2 Kostas Papadimitriou
        },
2202 126a01f2 Kostas Papadimitriou
2203 126a01f2 Kostas Papadimitriou
        reset_pending_firewall: function() {
2204 126a01f2 Kostas Papadimitriou
            this.set({'pending_firewall': false});
2205 4792afbe Kostas Papadimitriou
            this.set({'pending_firewall': false});
2206 126a01f2 Kostas Papadimitriou
        },
2207 126a01f2 Kostas Papadimitriou
2208 126a01f2 Kostas Papadimitriou
        check_firewall: function() {
2209 126a01f2 Kostas Papadimitriou
            var firewall = this.get('firewallProfile');
2210 126a01f2 Kostas Papadimitriou
            var pending = this.get('pending_firewall');
2211 4792afbe Kostas Papadimitriou
            var previous = this.get('pending_firewall_from');
2212 4792afbe Kostas Papadimitriou
            if (previous != firewall) { this.get_vm().require_reboot() };
2213 126a01f2 Kostas Papadimitriou
            this.reset_pending_firewall();
2214 126a01f2 Kostas Papadimitriou
        }
2215 126a01f2 Kostas Papadimitriou
        
2216 126a01f2 Kostas Papadimitriou
    });
2217 126a01f2 Kostas Papadimitriou
2218 126a01f2 Kostas Papadimitriou
    models.NICs = models.Collection.extend({
2219 126a01f2 Kostas Papadimitriou
        model: models.NIC,
2220 126a01f2 Kostas Papadimitriou
        
2221 126a01f2 Kostas Papadimitriou
        add_or_update: function(nic_id, data, vm) {
2222 126a01f2 Kostas Papadimitriou
            var params = _.clone(data);
2223 e49565e1 Kostas Papadimitriou
            var vm;
2224 126a01f2 Kostas Papadimitriou
            params.attachment_id = params.id;
2225 126a01f2 Kostas Papadimitriou
            params.id = params.id + '-' + params.network_id;
2226 126a01f2 Kostas Papadimitriou
            params.vm_id = parseInt(NIC_REGEX.exec(nic_id)[1]);
2227 126a01f2 Kostas Papadimitriou
2228 126a01f2 Kostas Papadimitriou
            if (!this.get(params.id)) {
2229 126a01f2 Kostas Papadimitriou
                this.add(params);
2230 126a01f2 Kostas Papadimitriou
                var nic = this.get(params.id);
2231 e49565e1 Kostas Papadimitriou
                vm = nic.get_vm();
2232 126a01f2 Kostas Papadimitriou
                nic.get_network().decrease_connecting();
2233 126a01f2 Kostas Papadimitriou
                nic.bind("remove", function() {
2234 126a01f2 Kostas Papadimitriou
                    nic.set({"removing": 0});
2235 126a01f2 Kostas Papadimitriou
                    if (this.get_network()) {
2236 126a01f2 Kostas Papadimitriou
                        // network might got removed before nic
2237 126a01f2 Kostas Papadimitriou
                        nic.get_network().update_state();
2238 126a01f2 Kostas Papadimitriou
                    }
2239 e49565e1 Kostas Papadimitriou
                });
2240 e49565e1 Kostas Papadimitriou
2241 126a01f2 Kostas Papadimitriou
            } else {
2242 126a01f2 Kostas Papadimitriou
                this.get(params.id).set(params);
2243 e49565e1 Kostas Papadimitriou
                vm = this.get(params.id).get_vm();
2244 126a01f2 Kostas Papadimitriou
            }
2245 e49565e1 Kostas Papadimitriou
            
2246 e49565e1 Kostas Papadimitriou
            // vm nics changed, trigger vm update
2247 e49565e1 Kostas Papadimitriou
            if (vm) { vm.trigger("change", vm)};
2248 126a01f2 Kostas Papadimitriou
        },
2249 126a01f2 Kostas Papadimitriou
        
2250 126a01f2 Kostas Papadimitriou
        reset_nics: function(nics, filter_attr, filter_val) {
2251 126a01f2 Kostas Papadimitriou
            var nics_to_check = this.filter(function(nic) {
2252 126a01f2 Kostas Papadimitriou
                return nic.get(filter_attr) == filter_val;
2253 126a01f2 Kostas Papadimitriou
            });
2254 126a01f2 Kostas Papadimitriou
            
2255 126a01f2 Kostas Papadimitriou
            _.each(nics_to_check, function(nic) {
2256 126a01f2 Kostas Papadimitriou
                if (nics.indexOf(nic.get('id')) == -1) {
2257 126a01f2 Kostas Papadimitriou
                    this.remove(nic);
2258 126a01f2 Kostas Papadimitriou
                } else {
2259 126a01f2 Kostas Papadimitriou
                }
2260 126a01f2 Kostas Papadimitriou
            }, this);
2261 126a01f2 Kostas Papadimitriou
        },
2262 126a01f2 Kostas Papadimitriou
2263 126a01f2 Kostas Papadimitriou
        update_vm_nics: function(vm) {
2264 126a01f2 Kostas Papadimitriou
            var nics = vm.get('nics');
2265 126a01f2 Kostas Papadimitriou
            this.reset_nics(_.map(nics, function(nic, key){
2266 126a01f2 Kostas Papadimitriou
                return key + "-" + nic.network_id;
2267 126a01f2 Kostas Papadimitriou
            }), 'vm_id', vm.id);
2268 126a01f2 Kostas Papadimitriou
2269 126a01f2 Kostas Papadimitriou
            _.each(nics, function(val, key) {
2270 126a01f2 Kostas Papadimitriou
                var net = synnefo.storage.networks.get(val.network_id);
2271 126a01f2 Kostas Papadimitriou
                if (net && net.connected_with_nic_id(key) && vm.connected_with_nic_id(key)) {
2272 126a01f2 Kostas Papadimitriou
                    this.add_or_update(key, vm.get('nics')[key], vm);
2273 126a01f2 Kostas Papadimitriou
                }
2274 126a01f2 Kostas Papadimitriou
            }, this);
2275 126a01f2 Kostas Papadimitriou
        },
2276 126a01f2 Kostas Papadimitriou
2277 126a01f2 Kostas Papadimitriou
        update_net_nics: function(net) {
2278 126a01f2 Kostas Papadimitriou
            var nics = net.get('nics');
2279 126a01f2 Kostas Papadimitriou
            this.reset_nics(_.map(nics, function(nic, key){
2280 126a01f2 Kostas Papadimitriou
                return key + "-" + net.get('id');
2281 126a01f2 Kostas Papadimitriou
            }), 'network_id', net.id);
2282 126a01f2 Kostas Papadimitriou
2283 126a01f2 Kostas Papadimitriou
            _.each(nics, function(val, key) {
2284 126a01f2 Kostas Papadimitriou
                var vm = synnefo.storage.vms.get(val.vm_id);
2285 126a01f2 Kostas Papadimitriou
                if (vm && 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 c4fff449 Kostas Papadimitriou
2292 c4fff449 Kostas Papadimitriou
    models.PublicKey = models.Model.extend({
2293 859a4609 Kostas Papadimitriou
        path: 'keys',
2294 859a4609 Kostas Papadimitriou
        base_url: '/ui/userdata',
2295 859a4609 Kostas Papadimitriou
        details: false,
2296 859a4609 Kostas Papadimitriou
        noUpdate: true,
2297 859a4609 Kostas Papadimitriou
2298 859a4609 Kostas Papadimitriou
2299 859a4609 Kostas Papadimitriou
        get_public_key: function() {
2300 859a4609 Kostas Papadimitriou
            return cryptico.publicKeyFromString(this.get("content"));
2301 859a4609 Kostas Papadimitriou
        },
2302 859a4609 Kostas Papadimitriou
2303 859a4609 Kostas Papadimitriou
        get_filename: function() {
2304 859a4609 Kostas Papadimitriou
            return "{0}.pub".format(this.get("name"));
2305 859a4609 Kostas Papadimitriou
        },
2306 859a4609 Kostas Papadimitriou
2307 859a4609 Kostas Papadimitriou
        identify_type: function() {
2308 859a4609 Kostas Papadimitriou
            try {
2309 859a4609 Kostas Papadimitriou
                var cont = snf.util.validatePublicKey(this.get("content"));
2310 859a4609 Kostas Papadimitriou
                var type = cont.split(" ")[0];
2311 859a4609 Kostas Papadimitriou
                return synnefo.util.publicKeyTypesMap[type];
2312 859a4609 Kostas Papadimitriou
            } catch (err) { return false };
2313 859a4609 Kostas Papadimitriou
        }
2314 859a4609 Kostas Papadimitriou
2315 c4fff449 Kostas Papadimitriou
    })
2316 c4fff449 Kostas Papadimitriou
    
2317 c4fff449 Kostas Papadimitriou
    models.PublicKeys = models.Collection.extend({
2318 859a4609 Kostas Papadimitriou
        model: models.PublicKey,
2319 859a4609 Kostas Papadimitriou
        details: false,
2320 859a4609 Kostas Papadimitriou
        path: 'keys',
2321 859a4609 Kostas Papadimitriou
        base_url: '/ui/userdata',
2322 859a4609 Kostas Papadimitriou
        noUpdate: true,
2323 859a4609 Kostas Papadimitriou
2324 556dcd88 Kostas Papadimitriou
        generate_new: function(success, error) {
2325 386481eb Kostas Papadimitriou
            snf.api.sync('create', undefined, {
2326 556dcd88 Kostas Papadimitriou
                url: getUrl.call(this, this.base_url) + "/generate", 
2327 556dcd88 Kostas Papadimitriou
                success: success, 
2328 556dcd88 Kostas Papadimitriou
                error: error,
2329 556dcd88 Kostas Papadimitriou
                skip_api_error: true
2330 556dcd88 Kostas Papadimitriou
            });
2331 859a4609 Kostas Papadimitriou
        },
2332 859a4609 Kostas Papadimitriou
2333 859a4609 Kostas Papadimitriou
        add_crypto_key: function(key, success, error, options) {
2334 859a4609 Kostas Papadimitriou
            var options = options || {};
2335 859a4609 Kostas Papadimitriou
            var m = new models.PublicKey();
2336 556dcd88 Kostas Papadimitriou
2337 556dcd88 Kostas Papadimitriou
            // guess a name
2338 1efe6159 Kostas Papadimitriou
            var name_tpl = "my generated public key";
2339 859a4609 Kostas Papadimitriou
            var name = name_tpl;
2340 859a4609 Kostas Papadimitriou
            var name_count = 1;
2341 859a4609 Kostas Papadimitriou
            
2342 859a4609 Kostas Papadimitriou
            while(this.filter(function(m){ return m.get("name") == name }).length > 0) {
2343 859a4609 Kostas Papadimitriou
                name = name_tpl + " " + name_count;
2344 859a4609 Kostas Papadimitriou
                name_count++;
2345 859a4609 Kostas Papadimitriou
            }
2346 556dcd88 Kostas Papadimitriou
            
2347 859a4609 Kostas Papadimitriou
            m.set({name: name});
2348 556dcd88 Kostas Papadimitriou
            m.set({content: key});
2349 859a4609 Kostas Papadimitriou
            
2350 859a4609 Kostas Papadimitriou
            options.success = function () { return success(m) };
2351 859a4609 Kostas Papadimitriou
            options.errror = error;
2352 c72a830d Kostas Papadimitriou
            options.skip_api_error = true;
2353 859a4609 Kostas Papadimitriou
            
2354 859a4609 Kostas Papadimitriou
            this.create(m.attributes, options);
2355 859a4609 Kostas Papadimitriou
        }
2356 c4fff449 Kostas Papadimitriou
    })
2357 8d08f18a Kostas Papadimitriou
    
2358 8d08f18a Kostas Papadimitriou
    // storage initialization
2359 8d08f18a Kostas Papadimitriou
    snf.storage.images = new models.Images();
2360 8d08f18a Kostas Papadimitriou
    snf.storage.flavors = new models.Flavors();
2361 8d08f18a Kostas Papadimitriou
    snf.storage.networks = new models.Networks();
2362 8d08f18a Kostas Papadimitriou
    snf.storage.vms = new models.VMS();
2363 c4fff449 Kostas Papadimitriou
    snf.storage.keys = new models.PublicKeys();
2364 126a01f2 Kostas Papadimitriou
    snf.storage.nics = new models.NICs();
2365 8d08f18a Kostas Papadimitriou
2366 8d08f18a Kostas Papadimitriou
    //snf.storage.vms.fetch({update:true});
2367 8d08f18a Kostas Papadimitriou
    //snf.storage.images.fetch({update:true});
2368 8d08f18a Kostas Papadimitriou
    //snf.storage.flavors.fetch({update:true});
2369 8d08f18a Kostas Papadimitriou
2370 8d08f18a Kostas Papadimitriou
})(this);