Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / static / snf / js / models.js @ 8fa1cbc9

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