Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / static / snf / js / models.js @ 59f43586

History | View | Annotate | Download (68 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 8d08f18a Kostas Papadimitriou
    
60 8d08f18a Kostas Papadimitriou
    // i18n
61 8d08f18a Kostas Papadimitriou
    BUILDING_MESSAGES = window.BUILDING_MESSAGES || {'INIT': 'init', 'COPY': '{0}, {1}, {2}', 'FINAL': 'final'};
62 8d08f18a Kostas Papadimitriou
63 8d08f18a Kostas Papadimitriou
    // Base object for all our models
64 8d08f18a Kostas Papadimitriou
    models.Model = bb.Model.extend({
65 8d08f18a Kostas Papadimitriou
        sync: snf.api.sync,
66 8d08f18a Kostas Papadimitriou
        api: snf.api,
67 47e34b99 Kostas Papadimitriou
        api_type: 'compute',
68 8d08f18a Kostas Papadimitriou
        has_status: false,
69 8d08f18a Kostas Papadimitriou
70 8d08f18a Kostas Papadimitriou
        initialize: function() {
71 8d08f18a Kostas Papadimitriou
            if (this.has_status) {
72 8d08f18a Kostas Papadimitriou
                this.bind("change:status", this.handle_remove);
73 8d08f18a Kostas Papadimitriou
                this.handle_remove();
74 8d08f18a Kostas Papadimitriou
            }
75 47e34b99 Kostas Papadimitriou
            
76 258235f4 Kostas Papadimitriou
            this.api_call = _.bind(this.api.call, this);
77 df251d55 Kostas Papadimitriou
            models.Model.__super__.initialize.apply(this, arguments);
78 8d08f18a Kostas Papadimitriou
        },
79 8d08f18a Kostas Papadimitriou
80 8d08f18a Kostas Papadimitriou
        handle_remove: function() {
81 643de8c0 Kostas Papadimitriou
            if (this.get("status") == 'DELETED') {
82 8d08f18a Kostas Papadimitriou
                if (this.collection) {
83 643de8c0 Kostas Papadimitriou
                    try { this.clear_pending_action();} catch (err) {};
84 643de8c0 Kostas Papadimitriou
                    try { this.reset_pending_actions();} catch (err) {};
85 2c9bfad1 Kostas Papadimitriou
                    try { this.stop_stats_update();} catch (err) {};
86 8d08f18a Kostas Papadimitriou
                    this.collection.remove(this.id);
87 8d08f18a Kostas Papadimitriou
                }
88 8d08f18a Kostas Papadimitriou
            }
89 8d08f18a Kostas Papadimitriou
        },
90 8d08f18a Kostas Papadimitriou
        
91 8d08f18a Kostas Papadimitriou
        // custom set method to allow submodels to use
92 8d08f18a Kostas Papadimitriou
        // set_<attr> methods for handling the value of each
93 8d08f18a Kostas Papadimitriou
        // attribute and overriding the default set method
94 8d08f18a Kostas Papadimitriou
        // for specific parameters
95 8d08f18a Kostas Papadimitriou
        set: function(params, options) {
96 8d08f18a Kostas Papadimitriou
            _.each(params, _.bind(function(value, key){
97 8d08f18a Kostas Papadimitriou
                if (this["set_" + key]) {
98 8d08f18a Kostas Papadimitriou
                    params[key] = this["set_" + key](value);
99 8d08f18a Kostas Papadimitriou
                }
100 8d08f18a Kostas Papadimitriou
            }, this))
101 8d08f18a Kostas Papadimitriou
            var ret = bb.Model.prototype.set.call(this, params, options);
102 8d08f18a Kostas Papadimitriou
            return ret;
103 8d08f18a Kostas Papadimitriou
        },
104 8d08f18a Kostas Papadimitriou
105 8d08f18a Kostas Papadimitriou
        url: function(options) {
106 c4fff449 Kostas Papadimitriou
            return getUrl.call(this, this.base_url) + "/" + this.id;
107 8d08f18a Kostas Papadimitriou
        },
108 8d08f18a Kostas Papadimitriou
109 8d08f18a Kostas Papadimitriou
        api_path: function(options) {
110 8d08f18a Kostas Papadimitriou
            return this.path + "/" + this.id;
111 8d08f18a Kostas Papadimitriou
        },
112 8d08f18a Kostas Papadimitriou
113 8d08f18a Kostas Papadimitriou
        parse: function(resp, xhr) {
114 8d08f18a Kostas Papadimitriou
            return resp.server;
115 8d08f18a Kostas Papadimitriou
        },
116 8d08f18a Kostas Papadimitriou
117 8d08f18a Kostas Papadimitriou
        remove: function() {
118 258235f4 Kostas Papadimitriou
            this.api_call(this.api_path(), "delete");
119 2506f741 Kostas Papadimitriou
        },
120 2506f741 Kostas Papadimitriou
121 2506f741 Kostas Papadimitriou
        changedKeys: function() {
122 2506f741 Kostas Papadimitriou
            return _.keys(this.changedAttributes() || {});
123 2506f741 Kostas Papadimitriou
        },
124 2506f741 Kostas Papadimitriou
125 2506f741 Kostas Papadimitriou
        hasOnlyChange: function(keys) {
126 2506f741 Kostas Papadimitriou
            var ret = false;
127 2506f741 Kostas Papadimitriou
            _.each(keys, _.bind(function(key) {
128 2506f741 Kostas Papadimitriou
                if (this.changedKeys().length == 1 && this.changedKeys().indexOf(key) > -1) { ret = true};
129 2506f741 Kostas Papadimitriou
            }, this));
130 2506f741 Kostas Papadimitriou
            return ret;
131 8d08f18a Kostas Papadimitriou
        }
132 8d08f18a Kostas Papadimitriou
133 8d08f18a Kostas Papadimitriou
    })
134 8d08f18a Kostas Papadimitriou
    
135 8d08f18a Kostas Papadimitriou
    // Base object for all our model collections
136 8d08f18a Kostas Papadimitriou
    models.Collection = bb.Collection.extend({
137 8d08f18a Kostas Papadimitriou
        sync: snf.api.sync,
138 8d08f18a Kostas Papadimitriou
        api: snf.api,
139 47e34b99 Kostas Papadimitriou
        api_type: 'compute',
140 16392650 Kostas Papadimitriou
        supportIncUpdates: true,
141 47e34b99 Kostas Papadimitriou
142 47e34b99 Kostas Papadimitriou
        initialize: function() {
143 47e34b99 Kostas Papadimitriou
            models.Collection.__super__.initialize.apply(this, arguments);
144 258235f4 Kostas Papadimitriou
            this.api_call = _.bind(this.api.call, this);
145 47e34b99 Kostas Papadimitriou
        },
146 47e34b99 Kostas Papadimitriou
147 2cee7cb0 Kostas Papadimitriou
        url: function(options, method) {
148 2cee7cb0 Kostas Papadimitriou
            return getUrl.call(this, this.base_url) + (
149 2cee7cb0 Kostas Papadimitriou
                    options.details || this.details && method != 'create' ? '/detail' : '');
150 8d08f18a Kostas Papadimitriou
        },
151 8d08f18a Kostas Papadimitriou
152 8d08f18a Kostas Papadimitriou
        fetch: function(options) {
153 859a4609 Kostas Papadimitriou
            if (!options) { options = {} };
154 8d08f18a Kostas Papadimitriou
            // default to update
155 8d08f18a Kostas Papadimitriou
            if (!this.noUpdate) {
156 8d08f18a Kostas Papadimitriou
                if (options.update === undefined) { options.update = true };
157 8d08f18a Kostas Papadimitriou
                if (!options.removeMissing && options.refresh) { options.removeMissing = true };
158 859a4609 Kostas Papadimitriou
            } else {
159 859a4609 Kostas Papadimitriou
                if (options.refresh === undefined) {
160 859a4609 Kostas Papadimitriou
                    options.refresh = true;
161 859a4609 Kostas Papadimitriou
                }
162 8d08f18a Kostas Papadimitriou
            }
163 8d08f18a Kostas Papadimitriou
            // custom event foreach fetch
164 8d08f18a Kostas Papadimitriou
            return bb.Collection.prototype.fetch.call(this, options)
165 8d08f18a Kostas Papadimitriou
        },
166 8d08f18a Kostas Papadimitriou
167 859a4609 Kostas Papadimitriou
        create: function(model, options) {
168 859a4609 Kostas Papadimitriou
            var coll = this;
169 859a4609 Kostas Papadimitriou
            options || (options = {});
170 859a4609 Kostas Papadimitriou
            model = this._prepareModel(model, options);
171 859a4609 Kostas Papadimitriou
            if (!model) return false;
172 859a4609 Kostas Papadimitriou
            var success = options.success;
173 859a4609 Kostas Papadimitriou
            options.success = function(nextModel, resp, xhr) {
174 859a4609 Kostas Papadimitriou
                if (success) success(nextModel, resp, xhr);
175 859a4609 Kostas Papadimitriou
            };
176 859a4609 Kostas Papadimitriou
            model.save(null, options);
177 859a4609 Kostas Papadimitriou
            return model;
178 859a4609 Kostas Papadimitriou
        },
179 859a4609 Kostas Papadimitriou
180 1cc6e94f Kostas Papadimitriou
        get_fetcher: function(interval, increase, fast, increase_after_calls, max, initial_call, params) {
181 9ce969a7 Kostas Papadimitriou
            var fetch_params = params || {};
182 1cc6e94f Kostas Papadimitriou
            var handler_options = {};
183 258235f4 Kostas Papadimitriou
184 258235f4 Kostas Papadimitriou
            fetch_params.skips_timeouts = true;
185 1cc6e94f Kostas Papadimitriou
            handler_options.interval = interval;
186 1cc6e94f Kostas Papadimitriou
            handler_options.increase = increase;
187 1cc6e94f Kostas Papadimitriou
            handler_options.fast = fast;
188 1cc6e94f Kostas Papadimitriou
            handler_options.increase_after_calls = increase_after_calls;
189 1cc6e94f Kostas Papadimitriou
            handler_options.max= max;
190 258235f4 Kostas Papadimitriou
            handler_options.id = "collection id";
191 1cc6e94f Kostas Papadimitriou
192 8d08f18a Kostas Papadimitriou
            var last_ajax = undefined;
193 258235f4 Kostas Papadimitriou
            var callback = _.bind(function() {
194 9ce969a7 Kostas Papadimitriou
                // clone to avoid referenced objects
195 9ce969a7 Kostas Papadimitriou
                var params = _.clone(fetch_params);
196 8d08f18a Kostas Papadimitriou
                updater._ajax = last_ajax;
197 a89ef0f5 Kostas Papadimitriou
                
198 42fb39fb Kostas Papadimitriou
                // wait for previous request to finish
199 a89ef0f5 Kostas Papadimitriou
                if (last_ajax && last_ajax.readyState < 4 && last_ajax.statusText != "timeout") {
200 a89ef0f5 Kostas Papadimitriou
                    // opera readystate for 304 responses is 0
201 a89ef0f5 Kostas Papadimitriou
                    if (!($.browser.opera && last_ajax.readyState == 0 && last_ajax.status == 304)) {
202 a89ef0f5 Kostas Papadimitriou
                        return;
203 a89ef0f5 Kostas Papadimitriou
                    }
204 8d08f18a Kostas Papadimitriou
                }
205 258235f4 Kostas Papadimitriou
                
206 9ce969a7 Kostas Papadimitriou
                last_ajax = this.fetch(params);
207 8d08f18a Kostas Papadimitriou
            }, this);
208 258235f4 Kostas Papadimitriou
            handler_options.callback = callback;
209 8d08f18a Kostas Papadimitriou
210 258235f4 Kostas Papadimitriou
            var updater = new snf.api.updateHandler(_.clone(_.extend(handler_options, fetch_params)));
211 35855ff5 Kostas Papadimitriou
            snf.api.bind("call", _.throttle(_.bind(function(){ updater.faster(true)}, this)), 1000);
212 8d08f18a Kostas Papadimitriou
            return updater;
213 8d08f18a Kostas Papadimitriou
        }
214 8d08f18a Kostas Papadimitriou
    });
215 8d08f18a Kostas Papadimitriou
    
216 8d08f18a Kostas Papadimitriou
    // Image model
217 8d08f18a Kostas Papadimitriou
    models.Image = models.Model.extend({
218 8d08f18a Kostas Papadimitriou
        path: 'images',
219 8d08f18a Kostas Papadimitriou
220 8d08f18a Kostas Papadimitriou
        get_size: function() {
221 820ef2f0 Kostas Papadimitriou
            return parseInt(this.get('metadata') ? this.get('metadata').values.size : -1)
222 820ef2f0 Kostas Papadimitriou
        },
223 820ef2f0 Kostas Papadimitriou
224 948042ca Kostas Papadimitriou
        get_meta: function(key) {
225 948042ca Kostas Papadimitriou
            if (this.get('metadata') && this.get('metadata').values && this.get('metadata').values[key]) {
226 df251d55 Kostas Papadimitriou
                return _.escape(this.get('metadata').values[key]);
227 948042ca Kostas Papadimitriou
            }
228 948042ca Kostas Papadimitriou
            return undefined;
229 948042ca Kostas Papadimitriou
        },
230 948042ca Kostas Papadimitriou
231 948042ca Kostas Papadimitriou
        get_owner: function() {
232 1faf0b9c Kostas Papadimitriou
            return this.get('owner') || _.keys(synnefo.config.system_images_owners)[0];
233 948042ca Kostas Papadimitriou
        },
234 948042ca Kostas Papadimitriou
235 babfdb9b Kostas Papadimitriou
        display_owner: function() {
236 babfdb9b Kostas Papadimitriou
            var owner = this.get_owner();
237 babfdb9b Kostas Papadimitriou
            if (_.include(_.keys(synnefo.config.system_images_owners), owner)) {
238 babfdb9b Kostas Papadimitriou
                return synnefo.config.system_images_owners[owner];
239 babfdb9b Kostas Papadimitriou
            } else {
240 babfdb9b Kostas Papadimitriou
                return owner;
241 babfdb9b Kostas Papadimitriou
            }
242 babfdb9b Kostas Papadimitriou
        },
243 babfdb9b Kostas Papadimitriou
244 5a434360 Kostas Papadimitriou
        get_readable_size: function() {
245 5a434360 Kostas Papadimitriou
            return this.get_size() > 0 ? util.readablizeBytes(this.get_size() * 1024 * 1024) : "unknown";
246 5a434360 Kostas Papadimitriou
        },
247 5a434360 Kostas Papadimitriou
248 820ef2f0 Kostas Papadimitriou
        get_os: function() {
249 820ef2f0 Kostas Papadimitriou
            return this.get("OS");
250 ccb14ad0 Kostas Papadimitriou
        },
251 ccb14ad0 Kostas Papadimitriou
252 47276ec2 Kostas Papadimitriou
        get_created_user: function() {
253 47276ec2 Kostas Papadimitriou
            return synnefo.config.os_created_users[this.get_os()] || "root";
254 47276ec2 Kostas Papadimitriou
        },
255 47276ec2 Kostas Papadimitriou
256 ccb14ad0 Kostas Papadimitriou
        get_sort_order: function() {
257 ccb14ad0 Kostas Papadimitriou
            return parseInt(this.get('metadata') ? this.get('metadata').values.sortorder : -1)
258 47276ec2 Kostas Papadimitriou
        },
259 2cee7cb0 Kostas Papadimitriou
260 2cee7cb0 Kostas Papadimitriou
        get_vm: function() {
261 2cee7cb0 Kostas Papadimitriou
            var vm_id = this.get("serverRef");
262 2cee7cb0 Kostas Papadimitriou
            var vm = undefined;
263 2cee7cb0 Kostas Papadimitriou
            vm = storage.vms.get(vm_id);
264 2cee7cb0 Kostas Papadimitriou
            return vm;
265 2cee7cb0 Kostas Papadimitriou
        },
266 948042ca Kostas Papadimitriou
267 948042ca Kostas Papadimitriou
        is_public: function() {
268 948042ca Kostas Papadimitriou
            return this.get('is_public') || true;
269 948042ca Kostas Papadimitriou
        },
270 47276ec2 Kostas Papadimitriou
        
271 47276ec2 Kostas Papadimitriou
        ssh_keys_path: function() {
272 47276ec2 Kostas Papadimitriou
            prepend = '';
273 47276ec2 Kostas Papadimitriou
            if (this.get_created_user() != 'root') {
274 47276ec2 Kostas Papadimitriou
                prepend = '/home'
275 47276ec2 Kostas Papadimitriou
            }
276 47276ec2 Kostas Papadimitriou
            return '{1}/{0}/.ssh/authorized_keys'.format(this.get_created_user(), prepend);
277 47276ec2 Kostas Papadimitriou
        },
278 47276ec2 Kostas Papadimitriou
279 47276ec2 Kostas Papadimitriou
        _supports_ssh: function() {
280 47276ec2 Kostas Papadimitriou
            if (synnefo.config.support_ssh_os_list.indexOf(this.get_os()) > -1) {
281 47276ec2 Kostas Papadimitriou
                return true;
282 47276ec2 Kostas Papadimitriou
            }
283 47276ec2 Kostas Papadimitriou
            return false;
284 47276ec2 Kostas Papadimitriou
        },
285 47276ec2 Kostas Papadimitriou
286 47276ec2 Kostas Papadimitriou
        supports: function(feature) {
287 47276ec2 Kostas Papadimitriou
            if (feature == "ssh") {
288 47276ec2 Kostas Papadimitriou
                return this._supports_ssh()
289 47276ec2 Kostas Papadimitriou
            }
290 47276ec2 Kostas Papadimitriou
            return false;
291 47276ec2 Kostas Papadimitriou
        },
292 47276ec2 Kostas Papadimitriou
293 47276ec2 Kostas Papadimitriou
        personality_data_for_keys: function(keys) {
294 47276ec2 Kostas Papadimitriou
            contents = '';
295 47276ec2 Kostas Papadimitriou
            _.each(keys, function(key){
296 47276ec2 Kostas Papadimitriou
                contents = contents + key.get("content") + "\n"
297 47276ec2 Kostas Papadimitriou
            });
298 47276ec2 Kostas Papadimitriou
            contents = $.base64.encode(contents);
299 47276ec2 Kostas Papadimitriou
300 47276ec2 Kostas Papadimitriou
            return {
301 47276ec2 Kostas Papadimitriou
                path: this.ssh_keys_path(),
302 47276ec2 Kostas Papadimitriou
                contents: contents
303 47276ec2 Kostas Papadimitriou
            }
304 8d08f18a Kostas Papadimitriou
        }
305 8d08f18a Kostas Papadimitriou
    });
306 8d08f18a Kostas Papadimitriou
307 8d08f18a Kostas Papadimitriou
    // Flavor model
308 8d08f18a Kostas Papadimitriou
    models.Flavor = models.Model.extend({
309 8d08f18a Kostas Papadimitriou
        path: 'flavors',
310 8d08f18a Kostas Papadimitriou
311 8d08f18a Kostas Papadimitriou
        details_string: function() {
312 8d08f18a Kostas Papadimitriou
            return "{0} CPU, {1}MB, {2}GB".format(this.get('cpu'), this.get('ram'), this.get('disk'));
313 820ef2f0 Kostas Papadimitriou
        },
314 820ef2f0 Kostas Papadimitriou
315 820ef2f0 Kostas Papadimitriou
        get_disk_size: function() {
316 820ef2f0 Kostas Papadimitriou
            return parseInt(this.get("disk") * 1000)
317 d965e6dc Kostas Papadimitriou
        },
318 d965e6dc Kostas Papadimitriou
319 d965e6dc Kostas Papadimitriou
        get_disk_template_info: function() {
320 d965e6dc Kostas Papadimitriou
            var info = snf.config.flavors_disk_templates_info[this.get("disk_template")];
321 d965e6dc Kostas Papadimitriou
            if (!info) {
322 d965e6dc Kostas Papadimitriou
                info = { name: this.get("disk_template"), description:'' };
323 d965e6dc Kostas Papadimitriou
            }
324 d965e6dc Kostas Papadimitriou
            return info
325 ccb14ad0 Kostas Papadimitriou
        }
326 820ef2f0 Kostas Papadimitriou
327 8d08f18a Kostas Papadimitriou
    });
328 8d08f18a Kostas Papadimitriou
    
329 8d08f18a Kostas Papadimitriou
    //network vms list helper
330 8d08f18a Kostas Papadimitriou
    var NetworkVMSList = function() {
331 8d08f18a Kostas Papadimitriou
        this.initialize = function() {
332 8d08f18a Kostas Papadimitriou
            this.vms = [];
333 8d08f18a Kostas Papadimitriou
            this.pending = [];
334 8d08f18a Kostas Papadimitriou
            this.pending_for_removal = [];
335 8d08f18a Kostas Papadimitriou
        }
336 8d08f18a Kostas Papadimitriou
        
337 8d08f18a Kostas Papadimitriou
        this.add_pending_for_remove = function(vm_id) {
338 8d08f18a Kostas Papadimitriou
            if (this.pending_for_removal.indexOf(vm_id) == -1) {
339 8d08f18a Kostas Papadimitriou
                this.pending_for_removal.push(vm_id);
340 8d08f18a Kostas Papadimitriou
            }
341 8d08f18a Kostas Papadimitriou
342 8d08f18a Kostas Papadimitriou
            if (this.pending_for_removal.length) {
343 8d08f18a Kostas Papadimitriou
                this.trigger("pending:remove:add");
344 8d08f18a Kostas Papadimitriou
            }
345 8d08f18a Kostas Papadimitriou
        },
346 8d08f18a Kostas Papadimitriou
347 8d08f18a Kostas Papadimitriou
        this.add_pending = function(vm_id) {
348 8d08f18a Kostas Papadimitriou
            if (this.pending.indexOf(vm_id) == -1) {
349 8d08f18a Kostas Papadimitriou
                this.pending[this.pending.length] = vm_id;
350 8d08f18a Kostas Papadimitriou
            }
351 8d08f18a Kostas Papadimitriou
352 8d08f18a Kostas Papadimitriou
            if (this.pending.length) {
353 8d08f18a Kostas Papadimitriou
                this.trigger("pending:add");
354 8d08f18a Kostas Papadimitriou
            }
355 8d08f18a Kostas Papadimitriou
        }
356 8d08f18a Kostas Papadimitriou
357 8d08f18a Kostas Papadimitriou
        this.check_pending = function() {
358 8d08f18a Kostas Papadimitriou
            var len = this.pending.length;
359 8d08f18a Kostas Papadimitriou
            var args = [this.pending];
360 8d08f18a Kostas Papadimitriou
            this.pending = _.difference(this.pending, this.vms);
361 8d08f18a Kostas Papadimitriou
            if (len != this.pending.length) {
362 8d08f18a Kostas Papadimitriou
                if (this.pending.length == 0) {
363 8d08f18a Kostas Papadimitriou
                    this.trigger("pending:clear");
364 8d08f18a Kostas Papadimitriou
                }
365 8d08f18a Kostas Papadimitriou
            }
366 8d08f18a Kostas Papadimitriou
367 8d08f18a Kostas Papadimitriou
            var len = this.pending_for_removal.length;
368 8d08f18a Kostas Papadimitriou
            this.pending_for_removal = _.intersection(this.pending_for_removal, this.vms);
369 8d08f18a Kostas Papadimitriou
            if (this.pending_for_removal.length == 0) {
370 8d08f18a Kostas Papadimitriou
                this.trigger("pending:remove:clear");
371 8d08f18a Kostas Papadimitriou
            }
372 8d08f18a Kostas Papadimitriou
373 8d08f18a Kostas Papadimitriou
        }
374 8d08f18a Kostas Papadimitriou
375 8d08f18a Kostas Papadimitriou
376 8d08f18a Kostas Papadimitriou
        this.add = function(vm_id) {
377 8d08f18a Kostas Papadimitriou
            if (this.vms.indexOf(vm_id) == -1) {
378 8d08f18a Kostas Papadimitriou
                this.vms[this.vms.length] = vm_id;
379 8d08f18a Kostas Papadimitriou
                this.trigger("network:connect", vm_id);
380 8d08f18a Kostas Papadimitriou
                this.check_pending();
381 8d08f18a Kostas Papadimitriou
                return true;
382 8d08f18a Kostas Papadimitriou
            }
383 8d08f18a Kostas Papadimitriou
        }
384 8d08f18a Kostas Papadimitriou
385 8d08f18a Kostas Papadimitriou
        this.remove = function(vm_id) {
386 8d08f18a Kostas Papadimitriou
            if (this.vms.indexOf(vm_id) > -1) {
387 8d08f18a Kostas Papadimitriou
                this.vms = _.without(this.vms, vm_id);
388 8d08f18a Kostas Papadimitriou
                this.trigger("network:disconnect", vm_id);
389 8d08f18a Kostas Papadimitriou
                this.check_pending();
390 8d08f18a Kostas Papadimitriou
                return true;
391 8d08f18a Kostas Papadimitriou
            }
392 8d08f18a Kostas Papadimitriou
        }
393 8d08f18a Kostas Papadimitriou
394 8d08f18a Kostas Papadimitriou
        this.get = function() {
395 8d08f18a Kostas Papadimitriou
            return this.vms;
396 8d08f18a Kostas Papadimitriou
        }
397 8d08f18a Kostas Papadimitriou
398 8d08f18a Kostas Papadimitriou
        this.list = function() {
399 8d08f18a Kostas Papadimitriou
            return storage.vms.filter(_.bind(function(vm){
400 8d08f18a Kostas Papadimitriou
                return this.vms.indexOf(vm.id) > -1;
401 8d08f18a Kostas Papadimitriou
            }, this))
402 8d08f18a Kostas Papadimitriou
        }
403 8d08f18a Kostas Papadimitriou
404 8d08f18a Kostas Papadimitriou
        this.initialize();
405 8d08f18a Kostas Papadimitriou
    };
406 8d08f18a Kostas Papadimitriou
    _.extend(NetworkVMSList.prototype, bb.Events);
407 8d08f18a Kostas Papadimitriou
    
408 8d08f18a Kostas Papadimitriou
    // vm networks list helper
409 8d08f18a Kostas Papadimitriou
    var VMNetworksList = function() {
410 8d08f18a Kostas Papadimitriou
        this.initialize = function() {
411 8d08f18a Kostas Papadimitriou
            this.networks = {};
412 8d08f18a Kostas Papadimitriou
            this.network_ids = [];
413 8d08f18a Kostas Papadimitriou
        }
414 8d08f18a Kostas Papadimitriou
415 8d08f18a Kostas Papadimitriou
        this.add = function(net_id, data) {
416 8d08f18a Kostas Papadimitriou
            if (!this.networks[net_id]) {
417 8d08f18a Kostas Papadimitriou
                this.networks[net_id] = data || {};
418 8d08f18a Kostas Papadimitriou
                this.network_ids[this.network_ids.length] = net_id;
419 8d08f18a Kostas Papadimitriou
                this.trigger("network:connect", net_id);
420 8d08f18a Kostas Papadimitriou
                return true;
421 8d08f18a Kostas Papadimitriou
            }
422 8d08f18a Kostas Papadimitriou
        }
423 8d08f18a Kostas Papadimitriou
424 8d08f18a Kostas Papadimitriou
        this.remove = function(net_id) {
425 8d08f18a Kostas Papadimitriou
            if (this.networks[net_id]) {
426 8d08f18a Kostas Papadimitriou
                delete this.networks[net_id];
427 8d08f18a Kostas Papadimitriou
                this.network_ids = _.without(this.network_ids, net_id);
428 8d08f18a Kostas Papadimitriou
                this.trigger("network:disconnect", net_id);
429 8d08f18a Kostas Papadimitriou
                return true;
430 8d08f18a Kostas Papadimitriou
            }
431 8d08f18a Kostas Papadimitriou
            return false;
432 8d08f18a Kostas Papadimitriou
        }
433 8d08f18a Kostas Papadimitriou
434 8d08f18a Kostas Papadimitriou
        this.get = function() {
435 8d08f18a Kostas Papadimitriou
            return this.networks;
436 8d08f18a Kostas Papadimitriou
        }
437 8d08f18a Kostas Papadimitriou
438 8d08f18a Kostas Papadimitriou
        this.list = function() {
439 8d08f18a Kostas Papadimitriou
            return storage.networks.filter(_.bind(function(net){
440 8d08f18a Kostas Papadimitriou
                return this.network_ids.indexOf(net.id) > -1;
441 8d08f18a Kostas Papadimitriou
            }, this))
442 8d08f18a Kostas Papadimitriou
        }
443 8d08f18a Kostas Papadimitriou
444 8d08f18a Kostas Papadimitriou
        this.initialize();
445 8d08f18a Kostas Papadimitriou
    };
446 8d08f18a Kostas Papadimitriou
    _.extend(VMNetworksList.prototype, bb.Events);
447 101e6604 Kostas Papadimitriou
        
448 101e6604 Kostas Papadimitriou
    models.ParamsList = function(){this.initialize.apply(this, arguments)};
449 101e6604 Kostas Papadimitriou
    _.extend(models.ParamsList.prototype, bb.Events, {
450 101e6604 Kostas Papadimitriou
451 101e6604 Kostas Papadimitriou
        initialize: function(parent, param_name) {
452 101e6604 Kostas Papadimitriou
            this.parent = parent;
453 101e6604 Kostas Papadimitriou
            this.actions = {};
454 101e6604 Kostas Papadimitriou
            this.param_name = param_name;
455 101e6604 Kostas Papadimitriou
            this.length = 0;
456 101e6604 Kostas Papadimitriou
        },
457 101e6604 Kostas Papadimitriou
        
458 101e6604 Kostas Papadimitriou
        has_action: function(action) {
459 101e6604 Kostas Papadimitriou
            return this.actions[action] ? true : false;
460 101e6604 Kostas Papadimitriou
        },
461 101e6604 Kostas Papadimitriou
            
462 101e6604 Kostas Papadimitriou
        _parse_params: function(arguments) {
463 101e6604 Kostas Papadimitriou
            if (arguments.length <= 1) {
464 101e6604 Kostas Papadimitriou
                return [];
465 101e6604 Kostas Papadimitriou
            }
466 101e6604 Kostas Papadimitriou
467 101e6604 Kostas Papadimitriou
            var args = _.toArray(arguments);
468 101e6604 Kostas Papadimitriou
            return args.splice(1);
469 101e6604 Kostas Papadimitriou
        },
470 101e6604 Kostas Papadimitriou
471 101e6604 Kostas Papadimitriou
        contains: function(action, params) {
472 101e6604 Kostas Papadimitriou
            params = this._parse_params(arguments);
473 101e6604 Kostas Papadimitriou
            var has_action = this.has_action(action);
474 101e6604 Kostas Papadimitriou
            if (!has_action) { return false };
475 101e6604 Kostas Papadimitriou
476 101e6604 Kostas Papadimitriou
            var paramsEqual = false;
477 101e6604 Kostas Papadimitriou
            _.each(this.actions[action], function(action_params) {
478 101e6604 Kostas Papadimitriou
                if (_.isEqual(action_params, params)) {
479 101e6604 Kostas Papadimitriou
                    paramsEqual = true;
480 101e6604 Kostas Papadimitriou
                }
481 101e6604 Kostas Papadimitriou
            });
482 101e6604 Kostas Papadimitriou
                
483 101e6604 Kostas Papadimitriou
            return paramsEqual;
484 101e6604 Kostas Papadimitriou
        },
485 101e6604 Kostas Papadimitriou
        
486 101e6604 Kostas Papadimitriou
        is_empty: function() {
487 101e6604 Kostas Papadimitriou
            return _.isEmpty(this.actions);
488 101e6604 Kostas Papadimitriou
        },
489 101e6604 Kostas Papadimitriou
490 101e6604 Kostas Papadimitriou
        add: function(action, params) {
491 101e6604 Kostas Papadimitriou
            params = this._parse_params(arguments);
492 101e6604 Kostas Papadimitriou
            if (this.contains.apply(this, arguments)) { return this };
493 101e6604 Kostas Papadimitriou
            var isnew = false
494 101e6604 Kostas Papadimitriou
            if (!this.has_action(action)) {
495 101e6604 Kostas Papadimitriou
                this.actions[action] = [];
496 101e6604 Kostas Papadimitriou
                isnew = true;
497 101e6604 Kostas Papadimitriou
            };
498 101e6604 Kostas Papadimitriou
499 101e6604 Kostas Papadimitriou
            this.actions[action].push(params);
500 101e6604 Kostas Papadimitriou
            this.parent.trigger("change:" + this.param_name, this.parent, this);
501 101e6604 Kostas Papadimitriou
            if (isnew) {
502 101e6604 Kostas Papadimitriou
                this.trigger("add", action, params);
503 101e6604 Kostas Papadimitriou
            } else {
504 101e6604 Kostas Papadimitriou
                this.trigger("change", action, params);
505 101e6604 Kostas Papadimitriou
            }
506 101e6604 Kostas Papadimitriou
            return this;
507 101e6604 Kostas Papadimitriou
        },
508 101e6604 Kostas Papadimitriou
        
509 101e6604 Kostas Papadimitriou
        remove_all: function(action) {
510 101e6604 Kostas Papadimitriou
            if (this.has_action(action)) {
511 101e6604 Kostas Papadimitriou
                delete this.actions[action];
512 101e6604 Kostas Papadimitriou
                this.parent.trigger("change:" + this.param_name, this.parent, this);
513 101e6604 Kostas Papadimitriou
                this.trigger("remove", action);
514 101e6604 Kostas Papadimitriou
            }
515 101e6604 Kostas Papadimitriou
            return this;
516 101e6604 Kostas Papadimitriou
        },
517 101e6604 Kostas Papadimitriou
518 101e6604 Kostas Papadimitriou
        reset: function() {
519 101e6604 Kostas Papadimitriou
            this.actions = {};
520 101e6604 Kostas Papadimitriou
            this.parent.trigger("change:" + this.param_name, this.parent, this);
521 101e6604 Kostas Papadimitriou
            this.trigger("reset");
522 101e6604 Kostas Papadimitriou
            this.trigger("remove");
523 101e6604 Kostas Papadimitriou
        },
524 101e6604 Kostas Papadimitriou
525 101e6604 Kostas Papadimitriou
        remove: function(action, params) {
526 101e6604 Kostas Papadimitriou
            params = this._parse_params(arguments);
527 101e6604 Kostas Papadimitriou
            if (!this.has_action(action)) { return this };
528 101e6604 Kostas Papadimitriou
            var index = -1;
529 101e6604 Kostas Papadimitriou
            _.each(this.actions[action], _.bind(function(action_params) {
530 101e6604 Kostas Papadimitriou
                if (_.isEqual(action_params, params)) {
531 101e6604 Kostas Papadimitriou
                    index = this.actions[action].indexOf(action_params);
532 101e6604 Kostas Papadimitriou
                }
533 101e6604 Kostas Papadimitriou
            }, this));
534 101e6604 Kostas Papadimitriou
            
535 101e6604 Kostas Papadimitriou
            if (index > -1) {
536 101e6604 Kostas Papadimitriou
                this.actions[action].splice(index, 1);
537 101e6604 Kostas Papadimitriou
                if (_.isEmpty(this.actions[action])) {
538 101e6604 Kostas Papadimitriou
                    delete this.actions[action];
539 101e6604 Kostas Papadimitriou
                }
540 101e6604 Kostas Papadimitriou
                this.parent.trigger("change:" + this.param_name, this.parent, this);
541 101e6604 Kostas Papadimitriou
                this.trigger("remove", action, params);
542 101e6604 Kostas Papadimitriou
            }
543 101e6604 Kostas Papadimitriou
        }
544 101e6604 Kostas Papadimitriou
545 101e6604 Kostas Papadimitriou
    });
546 8d08f18a Kostas Papadimitriou
547 8d08f18a Kostas Papadimitriou
    // Image model
548 8d08f18a Kostas Papadimitriou
    models.Network = models.Model.extend({
549 8d08f18a Kostas Papadimitriou
        path: 'networks',
550 8d08f18a Kostas Papadimitriou
        has_status: true,
551 8d08f18a Kostas Papadimitriou
        
552 8d08f18a Kostas Papadimitriou
        initialize: function() {
553 8d08f18a Kostas Papadimitriou
            this.vms = new NetworkVMSList();
554 8d08f18a Kostas Papadimitriou
            this.vms.bind("pending:add", _.bind(this.handle_pending_connections, this, "add"));
555 8d08f18a Kostas Papadimitriou
            this.vms.bind("pending:clear", _.bind(this.handle_pending_connections, this, "clear"));
556 8d08f18a Kostas Papadimitriou
            this.vms.bind("pending:remove:add", _.bind(this.handle_pending_connections, this, "add"));
557 8d08f18a Kostas Papadimitriou
            this.vms.bind("pending:remove:clear", _.bind(this.handle_pending_connections, this, "clear"));
558 8d08f18a Kostas Papadimitriou
559 1afc3946 Kostas Papadimitriou
            var ret = models.Network.__super__.initialize.apply(this, arguments);
560 8d08f18a Kostas Papadimitriou
561 8d08f18a Kostas Papadimitriou
            storage.vms.bind("change:linked_to_nets", _.bind(this.update_connections, this, "vm:change"));
562 8d08f18a Kostas Papadimitriou
            storage.vms.bind("add", _.bind(this.update_connections, this, "add"));
563 8d08f18a Kostas Papadimitriou
            storage.vms.bind("remove", _.bind(this.update_connections, this, "remove"));
564 8d08f18a Kostas Papadimitriou
            storage.vms.bind("reset", _.bind(this.update_connections, this, "reset"));
565 25b225a5 Kostas Papadimitriou
566 8d08f18a Kostas Papadimitriou
            this.bind("change:linked_to", _.bind(this.update_connections, this, "net:change"));
567 8d08f18a Kostas Papadimitriou
            this.update_connections();
568 8d08f18a Kostas Papadimitriou
            this.update_state();
569 101e6604 Kostas Papadimitriou
            
570 101e6604 Kostas Papadimitriou
            this.set({"actions": new models.ParamsList(this, "actions")});
571 25b225a5 Kostas Papadimitriou
572 8d08f18a Kostas Papadimitriou
            return ret;
573 8d08f18a Kostas Papadimitriou
        },
574 8d08f18a Kostas Papadimitriou
575 c40b07e0 Kostas Papadimitriou
        toJSON: function() {
576 c40b07e0 Kostas Papadimitriou
            var attrs = _.clone(this.attributes);
577 c40b07e0 Kostas Papadimitriou
            attrs.actions = _.clone(this.get("actions").actions);
578 c40b07e0 Kostas Papadimitriou
            return attrs;
579 c40b07e0 Kostas Papadimitriou
        },
580 c40b07e0 Kostas Papadimitriou
581 8d08f18a Kostas Papadimitriou
        update_state: function() {
582 8d08f18a Kostas Papadimitriou
            if (this.vms.pending.length) {
583 8d08f18a Kostas Papadimitriou
                this.set({state: "CONNECTING"});
584 8d08f18a Kostas Papadimitriou
                return
585 8d08f18a Kostas Papadimitriou
            }
586 25b225a5 Kostas Papadimitriou
587 8d08f18a Kostas Papadimitriou
            if (this.vms.pending_for_removal.length) {
588 8d08f18a Kostas Papadimitriou
                this.set({state: "DISCONNECTING"});
589 8d08f18a Kostas Papadimitriou
                return
590 8d08f18a Kostas Papadimitriou
            }   
591 8d08f18a Kostas Papadimitriou
            
592 8d08f18a Kostas Papadimitriou
            var firewalling = false;
593 8d08f18a Kostas Papadimitriou
            _.each(this.vms.get(), _.bind(function(vm_id){
594 8d08f18a Kostas Papadimitriou
                var vm = storage.vms.get(vm_id);
595 8d08f18a Kostas Papadimitriou
                if (!vm) { return };
596 8d08f18a Kostas Papadimitriou
                if (!_.isEmpty(vm.pending_firewalls)) {
597 8d08f18a Kostas Papadimitriou
                    this.set({state:"FIREWALLING"});
598 8d08f18a Kostas Papadimitriou
                    firewalling = true;
599 8d08f18a Kostas Papadimitriou
                    return false;
600 8d08f18a Kostas Papadimitriou
                }
601 8d08f18a Kostas Papadimitriou
            },this));
602 8d08f18a Kostas Papadimitriou
            if (firewalling) { return };
603 8d08f18a Kostas Papadimitriou
604 8d08f18a Kostas Papadimitriou
            this.set({state:"NORMAL"});
605 8d08f18a Kostas Papadimitriou
        },
606 8d08f18a Kostas Papadimitriou
607 8d08f18a Kostas Papadimitriou
        handle_pending_connections: function(action) {
608 8d08f18a Kostas Papadimitriou
            this.update_state();
609 8d08f18a Kostas Papadimitriou
        },
610 8d08f18a Kostas Papadimitriou
611 8d08f18a Kostas Papadimitriou
        // handle vm/network connections
612 8d08f18a Kostas Papadimitriou
        update_connections: function(action, model) {
613 8d08f18a Kostas Papadimitriou
            
614 8d08f18a Kostas Papadimitriou
            // vm removed disconnect vm from network
615 8d08f18a Kostas Papadimitriou
            if (action == "remove") {
616 8d08f18a Kostas Papadimitriou
                var removed_from_net = this.vms.remove(model.id);
617 8d08f18a Kostas Papadimitriou
                var removed_from_vm = model.networks.remove(this.id);
618 8d08f18a Kostas Papadimitriou
                if (removed_from_net) {this.trigger("vm:disconnect", model, this); this.change()};
619 96d725ac Kostas Papadimitriou
                if (removed_from_vm) {model.trigger("network:disconnect", this, model); this.change()};
620 8d08f18a Kostas Papadimitriou
                return;
621 8d08f18a Kostas Papadimitriou
            }
622 8d08f18a Kostas Papadimitriou
            
623 8d08f18a Kostas Papadimitriou
            // update links for all vms
624 8d08f18a Kostas Papadimitriou
            var links = this.get("linked_to");
625 8d08f18a Kostas Papadimitriou
            storage.vms.each(_.bind(function(vm) {
626 8d08f18a Kostas Papadimitriou
                var vm_links = vm.get("linked_to") || [];
627 8d08f18a Kostas Papadimitriou
                if (vm_links.indexOf(this.id) > -1) {
628 8d08f18a Kostas Papadimitriou
                    // vm has connection to current network
629 8d08f18a Kostas Papadimitriou
                    if (links.indexOf(vm.id) > -1) {
630 8d08f18a Kostas Papadimitriou
                        // and network has connection to vm, so try
631 8d08f18a Kostas Papadimitriou
                        // to append it
632 8d08f18a Kostas Papadimitriou
                        var add_to_net = this.vms.add(vm.id);
633 8d08f18a Kostas Papadimitriou
                        var index = _.indexOf(vm_links, this.id);
634 8d08f18a Kostas Papadimitriou
                        var add_to_vm = vm.networks.add(this.id, vm.get("linked_to_nets")[index]);
635 8d08f18a Kostas Papadimitriou
                        
636 8d08f18a Kostas Papadimitriou
                        // call only if connection did not existed
637 8d08f18a Kostas Papadimitriou
                        if (add_to_net) {this.trigger("vm:connect", vm, this); this.change()};
638 8d08f18a Kostas Papadimitriou
                        if (add_to_vm) {vm.trigger("network:connect", this, vm); vm.change()};
639 8d08f18a Kostas Papadimitriou
                    } else {
640 8d08f18a Kostas Papadimitriou
                        // no connection, try to remove it
641 8d08f18a Kostas Papadimitriou
                        var removed_from_net = this.vms.remove(vm.id);
642 8d08f18a Kostas Papadimitriou
                        var removed_from_vm = vm.networks.remove(this.id);
643 8d08f18a Kostas Papadimitriou
                        if (removed_from_net) {this.trigger("vm:disconnect", vm, this); this.change()};
644 8d08f18a Kostas Papadimitriou
                        if (removed_from_vm) {vm.trigger("network:disconnect", this, vm); vm.change()};
645 8d08f18a Kostas Papadimitriou
                    }
646 8d08f18a Kostas Papadimitriou
                } else {
647 8d08f18a Kostas Papadimitriou
                    // vm has no connection to current network, try to remove it
648 8d08f18a Kostas Papadimitriou
                    var removed_from_net = this.vms.remove(vm.id);
649 8d08f18a Kostas Papadimitriou
                    var removed_from_vm = vm.networks.remove(this.id);
650 8d08f18a Kostas Papadimitriou
                    if (removed_from_net) {this.trigger("vm:disconnect", vm, this); this.change()};
651 8d08f18a Kostas Papadimitriou
                    if (removed_from_vm) {vm.trigger("network:disconnect", this, vm); vm.change()};
652 8d08f18a Kostas Papadimitriou
                }
653 8d08f18a Kostas Papadimitriou
            },this));
654 8d08f18a Kostas Papadimitriou
        },
655 8d08f18a Kostas Papadimitriou
656 8d08f18a Kostas Papadimitriou
        is_public: function() {
657 8d08f18a Kostas Papadimitriou
            return this.id == "public";
658 8d08f18a Kostas Papadimitriou
        },
659 8d08f18a Kostas Papadimitriou
660 8d08f18a Kostas Papadimitriou
        contains_vm: function(vm) {
661 8d08f18a Kostas Papadimitriou
            var net_vm_exists = this.vms.get().indexOf(vm.id) > -1;
662 8d08f18a Kostas Papadimitriou
            var vm_net_exists = vm.is_connected_to(this);
663 8d08f18a Kostas Papadimitriou
            return net_vm_exists && vm_net_exists;
664 8d08f18a Kostas Papadimitriou
        },
665 101e6604 Kostas Papadimitriou
        
666 101e6604 Kostas Papadimitriou
        call: function(action, params, success, error) {
667 101e6604 Kostas Papadimitriou
            if (action == "destroy") {
668 101e6604 Kostas Papadimitriou
                this.set({state:"DESTROY"});
669 101e6604 Kostas Papadimitriou
                this.get("actions").remove("destroy");
670 101e6604 Kostas Papadimitriou
                this.remove(_.bind(function(){
671 101e6604 Kostas Papadimitriou
                    success();
672 101e6604 Kostas Papadimitriou
                }, this), error);
673 101e6604 Kostas Papadimitriou
            }
674 101e6604 Kostas Papadimitriou
            
675 101e6604 Kostas Papadimitriou
            if (action == "disconnect") {
676 101e6604 Kostas Papadimitriou
                _.each(params, _.bind(function(vm_id) {
677 101e6604 Kostas Papadimitriou
                    var vm = snf.storage.vms.get(vm_id);
678 101e6604 Kostas Papadimitriou
                    this.get("actions").remove("disconnect", vm_id);
679 101e6604 Kostas Papadimitriou
                    if (vm) {
680 101e6604 Kostas Papadimitriou
                        this.remove_vm(vm, success, error);
681 101e6604 Kostas Papadimitriou
                    }
682 101e6604 Kostas Papadimitriou
                }, this));
683 101e6604 Kostas Papadimitriou
            }
684 101e6604 Kostas Papadimitriou
        },
685 8d08f18a Kostas Papadimitriou
686 9ce969a7 Kostas Papadimitriou
        add_vm: function (vm, callback, error, options) {
687 9ce969a7 Kostas Papadimitriou
            var payload = {add:{serverRef:"" + vm.id}};
688 9ce969a7 Kostas Papadimitriou
            payload._options = options || {};
689 258235f4 Kostas Papadimitriou
            return this.api_call(this.api_path() + "/action", "create", 
690 9ce969a7 Kostas Papadimitriou
                                 payload,
691 8d08f18a Kostas Papadimitriou
                                 _.bind(function(){
692 8d08f18a Kostas Papadimitriou
                                     this.vms.add_pending(vm.id);
693 8d08f18a Kostas Papadimitriou
                                     if (callback) {callback()}
694 9ce969a7 Kostas Papadimitriou
                                 },this), error);
695 8d08f18a Kostas Papadimitriou
        },
696 8d08f18a Kostas Papadimitriou
697 9ce969a7 Kostas Papadimitriou
        remove_vm: function (vm, callback, error, options) {
698 9ce969a7 Kostas Papadimitriou
            var payload = {remove:{serverRef:"" + vm.id}};
699 9ce969a7 Kostas Papadimitriou
            payload._options = options || {};
700 258235f4 Kostas Papadimitriou
            return this.api_call(this.api_path() + "/action", "create", 
701 8d08f18a Kostas Papadimitriou
                                 {remove:{serverRef:"" + vm.id}},
702 8d08f18a Kostas Papadimitriou
                                 _.bind(function(){
703 8d08f18a Kostas Papadimitriou
                                     this.vms.add_pending_for_remove(vm.id);
704 8d08f18a Kostas Papadimitriou
                                     if (callback) {callback()}
705 9ce969a7 Kostas Papadimitriou
                                 },this), error);
706 8d08f18a Kostas Papadimitriou
        },
707 8d08f18a Kostas Papadimitriou
708 8d08f18a Kostas Papadimitriou
        rename: function(name, callback) {
709 258235f4 Kostas Papadimitriou
            return this.api_call(this.api_path(), "update", {
710 9ffd10ce Kostas Papadimitriou
                network:{name:name}, 
711 9ffd10ce Kostas Papadimitriou
                _options:{
712 9ffd10ce Kostas Papadimitriou
                    critical: false, 
713 9ffd10ce Kostas Papadimitriou
                    error_params:{
714 9ffd10ce Kostas Papadimitriou
                        title: "Network action failed",
715 9ffd10ce Kostas Papadimitriou
                        ns: "Networks",
716 4dabb5cb Kostas Papadimitriou
                        extra_details: {"Network id": this.id}
717 9ffd10ce Kostas Papadimitriou
                    }
718 9ffd10ce Kostas Papadimitriou
                }}, callback);
719 8d08f18a Kostas Papadimitriou
        },
720 8d08f18a Kostas Papadimitriou
721 8d08f18a Kostas Papadimitriou
        get_connectable_vms: function() {
722 8d08f18a Kostas Papadimitriou
            var servers = this.vms.list();
723 3162bebd Kostas Papadimitriou
            return storage.vms.filter(function(vm){
724 3162bebd Kostas Papadimitriou
                return servers.indexOf(vm) == -1 && !vm.in_error_state();
725 3162bebd Kostas Papadimitriou
            })
726 8d08f18a Kostas Papadimitriou
        },
727 8d08f18a Kostas Papadimitriou
728 8d08f18a Kostas Papadimitriou
        state_message: function() {
729 8d08f18a Kostas Papadimitriou
            if (this.get("state") == "NORMAL" && this.is_public()) {
730 8d08f18a Kostas Papadimitriou
                return "Public network";
731 8d08f18a Kostas Papadimitriou
            }
732 8d08f18a Kostas Papadimitriou
733 8d08f18a Kostas Papadimitriou
            return models.Network.STATES[this.get("state")];
734 8d08f18a Kostas Papadimitriou
        },
735 8d08f18a Kostas Papadimitriou
736 8d08f18a Kostas Papadimitriou
        in_progress: function() {
737 8d08f18a Kostas Papadimitriou
            return models.Network.STATES_TRANSITIONS[this.get("state")] != undefined;
738 101e6604 Kostas Papadimitriou
        },
739 101e6604 Kostas Papadimitriou
740 101e6604 Kostas Papadimitriou
        do_all_pending_actions: function(success, error) {
741 101e6604 Kostas Papadimitriou
            var destroy = this.get("actions").has_action("destroy");
742 101e6604 Kostas Papadimitriou
            _.each(this.get("actions").actions, _.bind(function(params, action) {
743 101e6604 Kostas Papadimitriou
                _.each(params, _.bind(function(with_params) {
744 101e6604 Kostas Papadimitriou
                    this.call(action, with_params, success, error);
745 101e6604 Kostas Papadimitriou
                }, this));
746 101e6604 Kostas Papadimitriou
            }, this));
747 8d08f18a Kostas Papadimitriou
        }
748 8d08f18a Kostas Papadimitriou
    });
749 8d08f18a Kostas Papadimitriou
    
750 8d08f18a Kostas Papadimitriou
    models.Network.STATES = {
751 8d08f18a Kostas Papadimitriou
        'NORMAL': 'Private network',
752 8d08f18a Kostas Papadimitriou
        'CONNECTING': 'Connecting...',
753 8d08f18a Kostas Papadimitriou
        'DISCONNECTING': 'Disconnecting...',
754 25b225a5 Kostas Papadimitriou
        'FIREWALLING': 'Firewall update...',
755 25b225a5 Kostas Papadimitriou
        'DESTROY': 'Destroying...'
756 8d08f18a Kostas Papadimitriou
    }
757 8d08f18a Kostas Papadimitriou
758 8d08f18a Kostas Papadimitriou
    models.Network.STATES_TRANSITIONS = {
759 8d08f18a Kostas Papadimitriou
        'CONNECTING': ['NORMAL'],
760 8d08f18a Kostas Papadimitriou
        'DISCONNECTING': ['NORMAL'],
761 8d08f18a Kostas Papadimitriou
        'FIREWALLING': ['NORMAL']
762 8d08f18a Kostas Papadimitriou
    }
763 8d08f18a Kostas Papadimitriou
764 8d08f18a Kostas Papadimitriou
    // Virtualmachine model
765 8d08f18a Kostas Papadimitriou
    models.VM = models.Model.extend({
766 8d08f18a Kostas Papadimitriou
767 8d08f18a Kostas Papadimitriou
        path: 'servers',
768 8d08f18a Kostas Papadimitriou
        has_status: true,
769 8d08f18a Kostas Papadimitriou
        initialize: function(params) {
770 8d08f18a Kostas Papadimitriou
            this.networks = new VMNetworksList();
771 8d08f18a Kostas Papadimitriou
            
772 8d08f18a Kostas Papadimitriou
            this.pending_firewalls = {};
773 8d08f18a Kostas Papadimitriou
            
774 8d08f18a Kostas Papadimitriou
            models.VM.__super__.initialize.apply(this, arguments);
775 8d08f18a Kostas Papadimitriou
776 8d08f18a Kostas Papadimitriou
            this.set({state: params.status || "ERROR"});
777 8d08f18a Kostas Papadimitriou
            this.log = new snf.logging.logger("VM " + this.id);
778 8d08f18a Kostas Papadimitriou
            this.pending_action = undefined;
779 8d08f18a Kostas Papadimitriou
            
780 8d08f18a Kostas Papadimitriou
            // init stats parameter
781 8d08f18a Kostas Papadimitriou
            this.set({'stats': undefined}, {silent: true});
782 8d08f18a Kostas Papadimitriou
            // defaults to not update the stats
783 8d08f18a Kostas Papadimitriou
            // each view should handle this vm attribute 
784 8d08f18a Kostas Papadimitriou
            // depending on if it displays stat images or not
785 8d08f18a Kostas Papadimitriou
            this.do_update_stats = false;
786 8d08f18a Kostas Papadimitriou
            
787 8d08f18a Kostas Papadimitriou
            // interval time
788 8d08f18a Kostas Papadimitriou
            // this will dynamicaly change if the server responds that
789 8d08f18a Kostas Papadimitriou
            // images get refreshed on different intervals
790 8d08f18a Kostas Papadimitriou
            this.stats_update_interval = synnefo.config.STATS_INTERVAL || 5000;
791 96d725ac Kostas Papadimitriou
            this.stats_available = false;
792 8d08f18a Kostas Papadimitriou
793 8d08f18a Kostas Papadimitriou
            // initialize interval
794 8d08f18a Kostas Papadimitriou
            this.init_stats_intervals(this.stats_update_interval);
795 8d08f18a Kostas Papadimitriou
            
796 8d08f18a Kostas Papadimitriou
            this.bind("change:progress", _.bind(this.update_building_progress, this));
797 8d08f18a Kostas Papadimitriou
            this.update_building_progress();
798 8d08f18a Kostas Papadimitriou
799 8d08f18a Kostas Papadimitriou
            this.bind("change:firewalls", _.bind(this.handle_firewall_change, this));
800 8d08f18a Kostas Papadimitriou
            
801 8d08f18a Kostas Papadimitriou
            // default values
802 8d08f18a Kostas Papadimitriou
            this.set({linked_to_nets:this.get("linked_to_nets") || []});
803 8d08f18a Kostas Papadimitriou
            this.set({firewalls:this.get("firewalls") || []});
804 6a3a5bf7 Kostas Papadimitriou
805 96d725ac Kostas Papadimitriou
            this.bind("change:state", _.bind(function(){if (this.state() == "DESTROY") { this.handle_destroy() }}, this))
806 8d08f18a Kostas Papadimitriou
        },
807 8d08f18a Kostas Papadimitriou
808 8d08f18a Kostas Papadimitriou
        handle_firewall_change: function() {
809 8d08f18a Kostas Papadimitriou
810 8d08f18a Kostas Papadimitriou
        },
811 8d08f18a Kostas Papadimitriou
        
812 8d08f18a Kostas Papadimitriou
        set_linked_to_nets: function(data) {
813 8d08f18a Kostas Papadimitriou
            this.set({"linked_to":_.map(data, function(n){ return n.id})});
814 8d08f18a Kostas Papadimitriou
            return data;
815 8d08f18a Kostas Papadimitriou
        },
816 8d08f18a Kostas Papadimitriou
817 8d08f18a Kostas Papadimitriou
        is_connected_to: function(net) {
818 8d08f18a Kostas Papadimitriou
            return _.filter(this.networks.list(), function(n){return n.id == net.id}).length > 0;
819 8d08f18a Kostas Papadimitriou
        },
820 8d08f18a Kostas Papadimitriou
        
821 8d08f18a Kostas Papadimitriou
        status: function(st) {
822 8d08f18a Kostas Papadimitriou
            if (!st) { return this.get("status")}
823 8d08f18a Kostas Papadimitriou
            return this.set({status:st});
824 8d08f18a Kostas Papadimitriou
        },
825 8d08f18a Kostas Papadimitriou
826 8d08f18a Kostas Papadimitriou
        set_status: function(st) {
827 8d08f18a Kostas Papadimitriou
            var new_state = this.state_for_api_status(st);
828 8d08f18a Kostas Papadimitriou
            var transition = false;
829 8d08f18a Kostas Papadimitriou
830 8d08f18a Kostas Papadimitriou
            if (this.state() != new_state) {
831 8d08f18a Kostas Papadimitriou
                if (models.VM.STATES_TRANSITIONS[this.state()]) {
832 8d08f18a Kostas Papadimitriou
                    transition = this.state();
833 8d08f18a Kostas Papadimitriou
                }
834 8d08f18a Kostas Papadimitriou
            }
835 8d08f18a Kostas Papadimitriou
            
836 8d08f18a Kostas Papadimitriou
            // call it silently to avoid double change trigger
837 8d08f18a Kostas Papadimitriou
            this.set({'state': this.state_for_api_status(st)}, {silent: true});
838 8d08f18a Kostas Papadimitriou
            
839 8d08f18a Kostas Papadimitriou
            // trigger transition
840 572dbe3d Kostas Papadimitriou
            if (transition && models.VM.TRANSITION_STATES.indexOf(new_state) == -1) { 
841 572dbe3d Kostas Papadimitriou
                this.trigger("transition", {from:transition, to:new_state}) 
842 572dbe3d Kostas Papadimitriou
            };
843 8d08f18a Kostas Papadimitriou
            return st;
844 8d08f18a Kostas Papadimitriou
        },
845 8d08f18a Kostas Papadimitriou
846 8d08f18a Kostas Papadimitriou
        update_building_progress: function() {
847 8d08f18a Kostas Papadimitriou
            if (this.is_building()) {
848 8d08f18a Kostas Papadimitriou
                var progress = this.get("progress");
849 8d08f18a Kostas Papadimitriou
                if (progress == 0) {
850 8d08f18a Kostas Papadimitriou
                    this.state("BUILD_INIT");
851 8d08f18a Kostas Papadimitriou
                    this.set({progress_message: BUILDING_MESSAGES['INIT']});
852 8d08f18a Kostas Papadimitriou
                }
853 8d08f18a Kostas Papadimitriou
                if (progress > 0 && progress < 99) {
854 8d08f18a Kostas Papadimitriou
                    this.state("BUILD_COPY");
855 c45bed88 Kostas Papadimitriou
                    this.get_copy_details(true, undefined, _.bind(function(details){
856 c45bed88 Kostas Papadimitriou
                        this.set({
857 c45bed88 Kostas Papadimitriou
                            progress_message: BUILDING_MESSAGES['COPY'].format(details.copy, 
858 c45bed88 Kostas Papadimitriou
                                                                               details.size, 
859 c45bed88 Kostas Papadimitriou
                                                                               details.progress)
860 c45bed88 Kostas Papadimitriou
                        });
861 c45bed88 Kostas Papadimitriou
                    }, this));
862 8d08f18a Kostas Papadimitriou
                }
863 8d08f18a Kostas Papadimitriou
                if (progress == 100) {
864 8d08f18a Kostas Papadimitriou
                    this.state("BUILD_FINAL");
865 8d08f18a Kostas Papadimitriou
                    this.set({progress_message: BUILDING_MESSAGES['FINAL']});
866 8d08f18a Kostas Papadimitriou
                }
867 8d08f18a Kostas Papadimitriou
            } else {
868 8d08f18a Kostas Papadimitriou
            }
869 8d08f18a Kostas Papadimitriou
        },
870 8d08f18a Kostas Papadimitriou
871 c45bed88 Kostas Papadimitriou
        get_copy_details: function(human, image, callback) {
872 8d08f18a Kostas Papadimitriou
            var human = human || false;
873 c45bed88 Kostas Papadimitriou
            var image = image || this.get_image(_.bind(function(image){
874 c45bed88 Kostas Papadimitriou
                var progress = this.get('progress');
875 c45bed88 Kostas Papadimitriou
                var size = image.get_size();
876 c45bed88 Kostas Papadimitriou
                var size_copied = (size * progress / 100).toFixed(2);
877 c45bed88 Kostas Papadimitriou
                
878 c45bed88 Kostas Papadimitriou
                if (human) {
879 c45bed88 Kostas Papadimitriou
                    size = util.readablizeBytes(size*1024*1024);
880 c45bed88 Kostas Papadimitriou
                    size_copied = util.readablizeBytes(size_copied*1024*1024);
881 c45bed88 Kostas Papadimitriou
                }
882 8d08f18a Kostas Papadimitriou
883 c45bed88 Kostas Papadimitriou
                callback({'progress': progress, 'size': size, 'copy': size_copied})
884 c45bed88 Kostas Papadimitriou
            }, this));
885 8d08f18a Kostas Papadimitriou
        },
886 8d08f18a Kostas Papadimitriou
887 1f7ea2f5 Kostas Papadimitriou
        start_stats_update: function(force_if_empty) {
888 2c9bfad1 Kostas Papadimitriou
            var prev_state = this.do_update_stats;
889 2c9bfad1 Kostas Papadimitriou
890 2c9bfad1 Kostas Papadimitriou
            this.do_update_stats = true;
891 1f7ea2f5 Kostas Papadimitriou
            
892 2c9bfad1 Kostas Papadimitriou
            // fetcher initialized ??
893 2c9bfad1 Kostas Papadimitriou
            if (!this.stats_fetcher) {
894 2c9bfad1 Kostas Papadimitriou
                this.init_stats_intervals();
895 2c9bfad1 Kostas Papadimitriou
            }
896 2c9bfad1 Kostas Papadimitriou
897 1f7ea2f5 Kostas Papadimitriou
898 2c9bfad1 Kostas Papadimitriou
            // fetcher running ???
899 2c9bfad1 Kostas Papadimitriou
            if (!this.stats_fetcher.running || !prev_state) {
900 2c9bfad1 Kostas Papadimitriou
                this.stats_fetcher.start();
901 2c9bfad1 Kostas Papadimitriou
            }
902 1f7ea2f5 Kostas Papadimitriou
903 1f7ea2f5 Kostas Papadimitriou
            if (force_if_empty && this.get("stats") == undefined) {
904 1f7ea2f5 Kostas Papadimitriou
                this.update_stats(true);
905 1f7ea2f5 Kostas Papadimitriou
            }
906 2c9bfad1 Kostas Papadimitriou
        },
907 2c9bfad1 Kostas Papadimitriou
908 2c9bfad1 Kostas Papadimitriou
        stop_stats_update: function(stop_calls) {
909 2c9bfad1 Kostas Papadimitriou
            this.do_update_stats = false;
910 2c9bfad1 Kostas Papadimitriou
911 2c9bfad1 Kostas Papadimitriou
            if (stop_calls) {
912 2c9bfad1 Kostas Papadimitriou
                this.stats_fetcher.stop();
913 2c9bfad1 Kostas Papadimitriou
            }
914 2c9bfad1 Kostas Papadimitriou
        },
915 2c9bfad1 Kostas Papadimitriou
916 8d08f18a Kostas Papadimitriou
        // clear and reinitialize update interval
917 8d08f18a Kostas Papadimitriou
        init_stats_intervals: function (interval) {
918 96d725ac Kostas Papadimitriou
            this.stats_fetcher = this.get_stats_fetcher(this.stats_update_interval);
919 96d725ac Kostas Papadimitriou
            this.stats_fetcher.start();
920 8d08f18a Kostas Papadimitriou
        },
921 8d08f18a Kostas Papadimitriou
        
922 96d725ac Kostas Papadimitriou
        get_stats_fetcher: function(timeout) {
923 96d725ac Kostas Papadimitriou
            var cb = _.bind(function(data){
924 96d725ac Kostas Papadimitriou
                this.update_stats();
925 96d725ac Kostas Papadimitriou
            }, this);
926 258235f4 Kostas Papadimitriou
            var fetcher = new snf.api.updateHandler({'callback': cb, interval: timeout, id:'stats'});
927 96d725ac Kostas Papadimitriou
            return fetcher;
928 96d725ac Kostas Papadimitriou
        },
929 96d725ac Kostas Papadimitriou
930 8d08f18a Kostas Papadimitriou
        // do the api call
931 8d08f18a Kostas Papadimitriou
        update_stats: function(force) {
932 8d08f18a Kostas Papadimitriou
            // do not update stats if flag not set
933 1f7ea2f5 Kostas Papadimitriou
            if ((!this.do_update_stats && !force) || this.updating_stats) {
934 8d08f18a Kostas Papadimitriou
                return;
935 8d08f18a Kostas Papadimitriou
            }
936 96d725ac Kostas Papadimitriou
937 8d08f18a Kostas Papadimitriou
            // make the api call, execute handle_stats_update on sucess
938 8d08f18a Kostas Papadimitriou
            // TODO: onError handler ???
939 8d08f18a Kostas Papadimitriou
            stats_url = this.url() + "/stats";
940 1f7ea2f5 Kostas Papadimitriou
            this.updating_stats = true;
941 258235f4 Kostas Papadimitriou
            this.sync("read", this, {
942 96d725ac Kostas Papadimitriou
                handles_error:true, 
943 96d725ac Kostas Papadimitriou
                url: stats_url, 
944 96d725ac Kostas Papadimitriou
                refresh:true, 
945 96d725ac Kostas Papadimitriou
                success: _.bind(this.handle_stats_update, this),
946 ec511098 Kostas Papadimitriou
                error: _.bind(this.handle_stats_error, this),
947 1f7ea2f5 Kostas Papadimitriou
                complete: _.bind(function(){this.updating_stats = false;}, this),
948 ec511098 Kostas Papadimitriou
                critical: false,
949 0375f6c5 Kostas Papadimitriou
                log_error: false,
950 0375f6c5 Kostas Papadimitriou
                skips_timeouts: true
951 96d725ac Kostas Papadimitriou
            });
952 96d725ac Kostas Papadimitriou
        },
953 96d725ac Kostas Papadimitriou
954 96d725ac Kostas Papadimitriou
        get_stats_image: function(stat, type) {
955 8d08f18a Kostas Papadimitriou
        },
956 8d08f18a Kostas Papadimitriou
        
957 96d725ac Kostas Papadimitriou
        _set_stats: function(stats) {
958 96d725ac Kostas Papadimitriou
            var silent = silent === undefined ? false : silent;
959 96d725ac Kostas Papadimitriou
            // unavailable stats while building
960 96d725ac Kostas Papadimitriou
            if (this.get("status") == "BUILD") { 
961 96d725ac Kostas Papadimitriou
                this.stats_available = false;
962 96d725ac Kostas Papadimitriou
            } else { this.stats_available = true; }
963 96d725ac Kostas Papadimitriou
964 96d725ac Kostas Papadimitriou
            if (this.get("status") == "DESTROY") { this.stats_available = false; }
965 96d725ac Kostas Papadimitriou
            
966 96d725ac Kostas Papadimitriou
            this.set({stats: stats}, {silent:true});
967 96d725ac Kostas Papadimitriou
            this.trigger("stats:update", stats);
968 96d725ac Kostas Papadimitriou
        },
969 96d725ac Kostas Papadimitriou
970 96d725ac Kostas Papadimitriou
        unbind: function() {
971 96d725ac Kostas Papadimitriou
            models.VM.__super__.unbind.apply(this, arguments);
972 96d725ac Kostas Papadimitriou
        },
973 96d725ac Kostas Papadimitriou
974 96d725ac Kostas Papadimitriou
        handle_stats_error: function() {
975 96d725ac Kostas Papadimitriou
            stats = {};
976 96d725ac Kostas Papadimitriou
            _.each(['cpuBar', 'cpuTimeSeries', 'netBar', 'netTimeSeries'], function(k) {
977 96d725ac Kostas Papadimitriou
                stats[k] = false;
978 96d725ac Kostas Papadimitriou
            });
979 96d725ac Kostas Papadimitriou
980 96d725ac Kostas Papadimitriou
            this.set({'stats': stats});
981 96d725ac Kostas Papadimitriou
        },
982 96d725ac Kostas Papadimitriou
983 8d08f18a Kostas Papadimitriou
        // this method gets executed after a successful vm stats api call
984 8d08f18a Kostas Papadimitriou
        handle_stats_update: function(data) {
985 96d725ac Kostas Papadimitriou
            var self = this;
986 8d08f18a Kostas Papadimitriou
            // avoid browser caching
987 96d725ac Kostas Papadimitriou
            
988 8d08f18a Kostas Papadimitriou
            if (data.stats && _.size(data.stats) > 0) {
989 8d08f18a Kostas Papadimitriou
                var ts = $.now();
990 8d08f18a Kostas Papadimitriou
                var stats = data.stats;
991 96d725ac Kostas Papadimitriou
                var images_loaded = 0;
992 96d725ac Kostas Papadimitriou
                var images = {};
993 96d725ac Kostas Papadimitriou
994 96d725ac Kostas Papadimitriou
                function check_images_loaded() {
995 96d725ac Kostas Papadimitriou
                    images_loaded++;
996 96d725ac Kostas Papadimitriou
997 96d725ac Kostas Papadimitriou
                    if (images_loaded == 4) {
998 96d725ac Kostas Papadimitriou
                        self._set_stats(images);
999 96d725ac Kostas Papadimitriou
                    }
1000 96d725ac Kostas Papadimitriou
                }
1001 8d08f18a Kostas Papadimitriou
                _.each(['cpuBar', 'cpuTimeSeries', 'netBar', 'netTimeSeries'], function(k) {
1002 96d725ac Kostas Papadimitriou
                    
1003 8d08f18a Kostas Papadimitriou
                    stats[k] = stats[k] + "?_=" + ts;
1004 96d725ac Kostas Papadimitriou
                    
1005 96d725ac Kostas Papadimitriou
                    var stat = k.slice(0,3);
1006 96d725ac Kostas Papadimitriou
                    var type = k.slice(3,6) == "Bar" ? "bar" : "time";
1007 96d725ac Kostas Papadimitriou
                    var img = $("<img />");
1008 96d725ac Kostas Papadimitriou
                    var val = stats[k];
1009 96d725ac Kostas Papadimitriou
                    
1010 96d725ac Kostas Papadimitriou
                    // load stat image to a temporary dom element
1011 96d725ac Kostas Papadimitriou
                    // update model stats on image load/error events
1012 96d725ac Kostas Papadimitriou
                    img.load(function() {
1013 96d725ac Kostas Papadimitriou
                        images[k] = val;
1014 96d725ac Kostas Papadimitriou
                        check_images_loaded();
1015 96d725ac Kostas Papadimitriou
                    });
1016 96d725ac Kostas Papadimitriou
1017 96d725ac Kostas Papadimitriou
                    img.error(function() {
1018 96d725ac Kostas Papadimitriou
                        images[stat + type] = false;
1019 96d725ac Kostas Papadimitriou
                        check_images_loaded();
1020 96d725ac Kostas Papadimitriou
                    });
1021 96d725ac Kostas Papadimitriou
1022 96d725ac Kostas Papadimitriou
                    img.attr({'src': stats[k]});
1023 8d08f18a Kostas Papadimitriou
                })
1024 8d08f18a Kostas Papadimitriou
                data.stats = stats;
1025 8d08f18a Kostas Papadimitriou
            }
1026 96d725ac Kostas Papadimitriou
1027 8d08f18a Kostas Papadimitriou
            // do we need to change the interval ??
1028 8d08f18a Kostas Papadimitriou
            if (data.stats.refresh * 1000 != this.stats_update_interval) {
1029 8d08f18a Kostas Papadimitriou
                this.stats_update_interval = data.stats.refresh * 1000;
1030 1cc6e94f Kostas Papadimitriou
                this.stats_fetcher.interval = this.stats_update_interval;
1031 1cc6e94f Kostas Papadimitriou
                this.stats_fetcher.maximum_interval = this.stats_update_interval;
1032 96d725ac Kostas Papadimitriou
                this.stats_fetcher.stop();
1033 2c9bfad1 Kostas Papadimitriou
                this.stats_fetcher.start(false);
1034 8d08f18a Kostas Papadimitriou
            }
1035 8d08f18a Kostas Papadimitriou
        },
1036 96d725ac Kostas Papadimitriou
1037 8d08f18a Kostas Papadimitriou
        // helper method that sets the do_update_stats
1038 8d08f18a Kostas Papadimitriou
        // in the future this method could also make an api call
1039 8d08f18a Kostas Papadimitriou
        // immediaetly if needed
1040 8d08f18a Kostas Papadimitriou
        enable_stats_update: function() {
1041 8d08f18a Kostas Papadimitriou
            this.do_update_stats = true;
1042 8d08f18a Kostas Papadimitriou
        },
1043 96d725ac Kostas Papadimitriou
        
1044 96d725ac Kostas Papadimitriou
        handle_destroy: function() {
1045 96d725ac Kostas Papadimitriou
            this.stats_fetcher.stop();
1046 96d725ac Kostas Papadimitriou
        },
1047 122850c5 Kostas Papadimitriou
1048 122850c5 Kostas Papadimitriou
        require_reboot: function() {
1049 122850c5 Kostas Papadimitriou
            if (this.is_active()) {
1050 122850c5 Kostas Papadimitriou
                this.set({'reboot_required': true});
1051 122850c5 Kostas Papadimitriou
            }
1052 122850c5 Kostas Papadimitriou
        },
1053 8d08f18a Kostas Papadimitriou
        
1054 8d08f18a Kostas Papadimitriou
        set_pending_action: function(data) {
1055 8d08f18a Kostas Papadimitriou
            this.pending_action = data;
1056 8d08f18a Kostas Papadimitriou
            return data;
1057 8d08f18a Kostas Papadimitriou
        },
1058 8d08f18a Kostas Papadimitriou
1059 8d08f18a Kostas Papadimitriou
        // machine has pending action
1060 8d08f18a Kostas Papadimitriou
        update_pending_action: function(action, force) {
1061 8d08f18a Kostas Papadimitriou
            this.set({pending_action: action});
1062 8d08f18a Kostas Papadimitriou
        },
1063 8d08f18a Kostas Papadimitriou
1064 8d08f18a Kostas Papadimitriou
        clear_pending_action: function() {
1065 8d08f18a Kostas Papadimitriou
            this.set({pending_action: undefined});
1066 8d08f18a Kostas Papadimitriou
        },
1067 8d08f18a Kostas Papadimitriou
1068 8d08f18a Kostas Papadimitriou
        has_pending_action: function() {
1069 8d08f18a Kostas Papadimitriou
            return this.get("pending_action") ? this.get("pending_action") : false;
1070 8d08f18a Kostas Papadimitriou
        },
1071 8d08f18a Kostas Papadimitriou
        
1072 8d08f18a Kostas Papadimitriou
        // machine is active
1073 8d08f18a Kostas Papadimitriou
        is_active: function() {
1074 8d08f18a Kostas Papadimitriou
            return models.VM.ACTIVE_STATES.indexOf(this.state()) > -1;
1075 8d08f18a Kostas Papadimitriou
        },
1076 8d08f18a Kostas Papadimitriou
        
1077 122850c5 Kostas Papadimitriou
        // machine is building 
1078 8d08f18a Kostas Papadimitriou
        is_building: function() {
1079 8d08f18a Kostas Papadimitriou
            return models.VM.BUILDING_STATES.indexOf(this.state()) > -1;
1080 8d08f18a Kostas Papadimitriou
        },
1081 3162bebd Kostas Papadimitriou
        
1082 3162bebd Kostas Papadimitriou
        in_error_state: function() {
1083 3162bebd Kostas Papadimitriou
            return this.state() === "ERROR"
1084 3162bebd Kostas Papadimitriou
        },
1085 8d08f18a Kostas Papadimitriou
1086 8d08f18a Kostas Papadimitriou
        // user can connect to machine
1087 8d08f18a Kostas Papadimitriou
        is_connectable: function() {
1088 8d08f18a Kostas Papadimitriou
            // check if ips exist
1089 8d08f18a Kostas Papadimitriou
            if (!this.get_addresses().ip4 && !this.get_addresses().ip6) {
1090 8d08f18a Kostas Papadimitriou
                return false;
1091 8d08f18a Kostas Papadimitriou
            }
1092 8d08f18a Kostas Papadimitriou
            return models.VM.CONNECT_STATES.indexOf(this.state()) > -1;
1093 8d08f18a Kostas Papadimitriou
        },
1094 8d08f18a Kostas Papadimitriou
        
1095 8d08f18a Kostas Papadimitriou
        set_firewalls: function(data) {
1096 8d08f18a Kostas Papadimitriou
            _.each(data, _.bind(function(val, key){
1097 8d08f18a Kostas Papadimitriou
                if (this.pending_firewalls && this.pending_firewalls[key] && this.pending_firewalls[key] == val) {
1098 122850c5 Kostas Papadimitriou
                        this.require_reboot();
1099 8d08f18a Kostas Papadimitriou
                        this.remove_pending_firewall(key, val);
1100 8d08f18a Kostas Papadimitriou
                }
1101 8d08f18a Kostas Papadimitriou
            }, this));
1102 8d08f18a Kostas Papadimitriou
            return data;
1103 8d08f18a Kostas Papadimitriou
        },
1104 8d08f18a Kostas Papadimitriou
1105 8d08f18a Kostas Papadimitriou
        remove_pending_firewall: function(net_id, value) {
1106 8d08f18a Kostas Papadimitriou
            if (this.pending_firewalls[net_id] == value) {
1107 8d08f18a Kostas Papadimitriou
                delete this.pending_firewalls[net_id];
1108 8d08f18a Kostas Papadimitriou
                storage.networks.get(net_id).update_state();
1109 8d08f18a Kostas Papadimitriou
            }
1110 8d08f18a Kostas Papadimitriou
        },
1111 8d08f18a Kostas Papadimitriou
            
1112 8d08f18a Kostas Papadimitriou
        remove_meta: function(key, complete, error) {
1113 8d08f18a Kostas Papadimitriou
            var url = this.api_path() + "/meta/" + key;
1114 258235f4 Kostas Papadimitriou
            this.api_call(url, "delete", undefined, complete, error);
1115 8d08f18a Kostas Papadimitriou
        },
1116 8d08f18a Kostas Papadimitriou
1117 8d08f18a Kostas Papadimitriou
        save_meta: function(meta, complete, error) {
1118 8d08f18a Kostas Papadimitriou
            var url = this.api_path() + "/meta/" + meta.key;
1119 8d08f18a Kostas Papadimitriou
            var payload = {meta:{}};
1120 8d08f18a Kostas Papadimitriou
            payload.meta[meta.key] = meta.value;
1121 9ffd10ce Kostas Papadimitriou
            payload._options = {
1122 9ffd10ce Kostas Papadimitriou
                critical:false, 
1123 9ffd10ce Kostas Papadimitriou
                error_params: {
1124 9ffd10ce Kostas Papadimitriou
                    title: "Machine metadata error",
1125 9ffd10ce Kostas Papadimitriou
                    extra_details: {"Machine id": this.id}
1126 9ffd10ce Kostas Papadimitriou
            }};
1127 8d08f18a Kostas Papadimitriou
1128 258235f4 Kostas Papadimitriou
            this.api_call(url, "update", payload, complete, error);
1129 8d08f18a Kostas Papadimitriou
        },
1130 8d08f18a Kostas Papadimitriou
1131 9ce969a7 Kostas Papadimitriou
        set_firewall: function(net_id, value, callback, error, options) {
1132 8d08f18a Kostas Papadimitriou
            if (this.get("firewalls") && this.get("firewalls")[net_id] == value) { return }
1133 122850c5 Kostas Papadimitriou
1134 8d08f18a Kostas Papadimitriou
            this.pending_firewalls[net_id] = value;
1135 8d08f18a Kostas Papadimitriou
            this.trigger("change", this, this);
1136 9ce969a7 Kostas Papadimitriou
            var payload = {"firewallProfile":{"profile":value}};
1137 9ce969a7 Kostas Papadimitriou
            payload._options = _.extend({critical: false}, options);
1138 9ce969a7 Kostas Papadimitriou
            
1139 9ce969a7 Kostas Papadimitriou
            // reset firewall state on error
1140 9ce969a7 Kostas Papadimitriou
            var error_cb = _.bind(function() {
1141 9ce969a7 Kostas Papadimitriou
                thi
1142 9ce969a7 Kostas Papadimitriou
            }, this);
1143 9ce969a7 Kostas Papadimitriou
1144 258235f4 Kostas Papadimitriou
            this.api_call(this.api_path() + "/action", "create", payload, callback, error);
1145 8d08f18a Kostas Papadimitriou
            storage.networks.get(net_id).update_state();
1146 8d08f18a Kostas Papadimitriou
        },
1147 8d08f18a Kostas Papadimitriou
1148 8d08f18a Kostas Papadimitriou
        firewall_pending: function(net_id) {
1149 8d08f18a Kostas Papadimitriou
            return this.pending_firewalls[net_id] != undefined;
1150 8d08f18a Kostas Papadimitriou
        },
1151 8d08f18a Kostas Papadimitriou
        
1152 8d08f18a Kostas Papadimitriou
        // update/get the state of the machine
1153 8d08f18a Kostas Papadimitriou
        state: function() {
1154 8d08f18a Kostas Papadimitriou
            var args = slice.call(arguments);
1155 8d08f18a Kostas Papadimitriou
                
1156 643de8c0 Kostas Papadimitriou
            // TODO: it might not be a good idea to set the state in set_state method
1157 8d08f18a Kostas Papadimitriou
            if (args.length > 0 && models.VM.STATES.indexOf(args[0]) > -1) {
1158 8d08f18a Kostas Papadimitriou
                this.set({'state': args[0]});
1159 8d08f18a Kostas Papadimitriou
            }
1160 8d08f18a Kostas Papadimitriou
1161 8d08f18a Kostas Papadimitriou
            return this.get('state');
1162 8d08f18a Kostas Papadimitriou
        },
1163 8d08f18a Kostas Papadimitriou
        
1164 8d08f18a Kostas Papadimitriou
        // get the state that the api status corresponds to
1165 8d08f18a Kostas Papadimitriou
        state_for_api_status: function(status) {
1166 8d08f18a Kostas Papadimitriou
            return this.state_transition(this.state(), status);
1167 8d08f18a Kostas Papadimitriou
        },
1168 8d08f18a Kostas Papadimitriou
        
1169 8d08f18a Kostas Papadimitriou
        // vm state equals vm api status
1170 8d08f18a Kostas Papadimitriou
        state_is_status: function(state) {
1171 8d08f18a Kostas Papadimitriou
            return models.VM.STATUSES.indexOf(state) != -1;
1172 8d08f18a Kostas Papadimitriou
        },
1173 8d08f18a Kostas Papadimitriou
        
1174 8d08f18a Kostas Papadimitriou
        // get transition state for the corresponging api status
1175 8d08f18a Kostas Papadimitriou
        state_transition: function(state, new_status) {
1176 8d08f18a Kostas Papadimitriou
            var statuses = models.VM.STATES_TRANSITIONS[state];
1177 8d08f18a Kostas Papadimitriou
            if (statuses) {
1178 8d08f18a Kostas Papadimitriou
                if (statuses.indexOf(new_status) > -1) {
1179 8d08f18a Kostas Papadimitriou
                    return new_status;
1180 8d08f18a Kostas Papadimitriou
                } else {
1181 8d08f18a Kostas Papadimitriou
                    return state;
1182 8d08f18a Kostas Papadimitriou
                }
1183 8d08f18a Kostas Papadimitriou
            } else {
1184 8d08f18a Kostas Papadimitriou
                return new_status;
1185 8d08f18a Kostas Papadimitriou
            }
1186 8d08f18a Kostas Papadimitriou
        },
1187 8d08f18a Kostas Papadimitriou
        
1188 8d08f18a Kostas Papadimitriou
        // the current vm state is a transition state
1189 8d08f18a Kostas Papadimitriou
        in_transition: function() {
1190 8d08f18a Kostas Papadimitriou
            return models.VM.TRANSITION_STATES.indexOf(this.state()) > -1 || 
1191 8d08f18a Kostas Papadimitriou
                models.VM.TRANSITION_STATES.indexOf(this.get('status')) > -1;
1192 8d08f18a Kostas Papadimitriou
        },
1193 8d08f18a Kostas Papadimitriou
        
1194 8d08f18a Kostas Papadimitriou
        // get image object
1195 c45bed88 Kostas Papadimitriou
        get_image: function(callback) {
1196 bedfe884 Kostas Papadimitriou
            var image = storage.images.get(this.get('imageRef'));
1197 bedfe884 Kostas Papadimitriou
            if (!image) {
1198 c45bed88 Kostas Papadimitriou
                storage.images.update_unknown_id(this.get('imageRef'), callback);
1199 c45bed88 Kostas Papadimitriou
                return;
1200 bedfe884 Kostas Papadimitriou
            }
1201 c45bed88 Kostas Papadimitriou
            callback(image);
1202 bedfe884 Kostas Papadimitriou
            return image;
1203 8d08f18a Kostas Papadimitriou
        },
1204 8d08f18a Kostas Papadimitriou
        
1205 8d08f18a Kostas Papadimitriou
        // get flavor object
1206 8d08f18a Kostas Papadimitriou
        get_flavor: function() {
1207 bedfe884 Kostas Papadimitriou
            var flv = storage.flavors.get(this.get('flavorRef'));
1208 bedfe884 Kostas Papadimitriou
            if (!flv) {
1209 bedfe884 Kostas Papadimitriou
                storage.flavors.update_unknown_id(this.get('flavorRef'));
1210 bedfe884 Kostas Papadimitriou
                flv = storage.flavors.get(this.get('flavorRef'));
1211 bedfe884 Kostas Papadimitriou
            }
1212 bedfe884 Kostas Papadimitriou
            return flv;
1213 8d08f18a Kostas Papadimitriou
        },
1214 8d08f18a Kostas Papadimitriou
1215 8d08f18a Kostas Papadimitriou
        // retrieve the metadata object
1216 df251d55 Kostas Papadimitriou
        get_meta: function(key) {
1217 8d08f18a Kostas Papadimitriou
            try {
1218 df251d55 Kostas Papadimitriou
                return _.escape(this.get('metadata').values[key]);
1219 8d08f18a Kostas Papadimitriou
            } catch (err) {
1220 8d08f18a Kostas Papadimitriou
                return {};
1221 8d08f18a Kostas Papadimitriou
            }
1222 8d08f18a Kostas Papadimitriou
        },
1223 8d08f18a Kostas Papadimitriou
        
1224 8d08f18a Kostas Papadimitriou
        // get metadata OS value
1225 8d08f18a Kostas Papadimitriou
        get_os: function() {
1226 df251d55 Kostas Papadimitriou
            return this.get_meta('OS') || (this.get_image(function(){}) ? 
1227 d5ba5588 Kostas Papadimitriou
                                          this.get_image(function(){}).get_os() || "okeanos" : "okeanos");
1228 8d08f18a Kostas Papadimitriou
        },
1229 258235f4 Kostas Papadimitriou
1230 8d08f18a Kostas Papadimitriou
        // get public ip addresses
1231 8d08f18a Kostas Papadimitriou
        // TODO: public network is always the 0 index ???
1232 8d08f18a Kostas Papadimitriou
        get_addresses: function(net_id) {
1233 8d08f18a Kostas Papadimitriou
            var net_id = net_id || "public";
1234 8d08f18a Kostas Papadimitriou
            
1235 8d08f18a Kostas Papadimitriou
            var info = this.get_network_info(net_id);
1236 8d08f18a Kostas Papadimitriou
            if (!info) { return {} };
1237 8d08f18a Kostas Papadimitriou
            addrs = {};
1238 8d08f18a Kostas Papadimitriou
            _.each(info.values, function(addr) {
1239 8d08f18a Kostas Papadimitriou
                addrs["ip" + addr.version] = addr.addr;
1240 8d08f18a Kostas Papadimitriou
            });
1241 8d08f18a Kostas Papadimitriou
            return addrs
1242 8d08f18a Kostas Papadimitriou
        },
1243 8d08f18a Kostas Papadimitriou
1244 8d08f18a Kostas Papadimitriou
        get_network_info: function(net_id) {
1245 8d08f18a Kostas Papadimitriou
            var net_id = net_id || "public";
1246 8d08f18a Kostas Papadimitriou
            
1247 8d08f18a Kostas Papadimitriou
            if (!this.networks.network_ids.length) { return {} };
1248 8d08f18a Kostas Papadimitriou
1249 8d08f18a Kostas Papadimitriou
            var addresses = this.networks.get();
1250 8d08f18a Kostas Papadimitriou
            try {
1251 8d08f18a Kostas Papadimitriou
                return _.select(addresses, function(net, key){return key == net_id })[0];
1252 8d08f18a Kostas Papadimitriou
            } catch (err) {
1253 8d08f18a Kostas Papadimitriou
                //this.log.debug("Cannot find network {0}".format(net_id))
1254 8d08f18a Kostas Papadimitriou
            }
1255 8d08f18a Kostas Papadimitriou
        },
1256 8d08f18a Kostas Papadimitriou
1257 8d08f18a Kostas Papadimitriou
        firewall_profile: function(net_id) {
1258 8d08f18a Kostas Papadimitriou
            var net_id = net_id || "public";
1259 8d08f18a Kostas Papadimitriou
            var firewalls = this.get("firewalls");
1260 8d08f18a Kostas Papadimitriou
            return firewalls[net_id];
1261 8d08f18a Kostas Papadimitriou
        },
1262 8d08f18a Kostas Papadimitriou
1263 8d08f18a Kostas Papadimitriou
        has_firewall: function(net_id) {
1264 8d08f18a Kostas Papadimitriou
            var net_id = net_id || "public";
1265 8d08f18a Kostas Papadimitriou
            return ["ENABLED","PROTECTED"].indexOf(this.firewall_profile()) > -1;
1266 8d08f18a Kostas Papadimitriou
        },
1267 8d08f18a Kostas Papadimitriou
    
1268 8d08f18a Kostas Papadimitriou
        // get actions that the user can execute
1269 8d08f18a Kostas Papadimitriou
        // depending on the vm state/status
1270 8d08f18a Kostas Papadimitriou
        get_available_actions: function() {
1271 8d08f18a Kostas Papadimitriou
            return models.VM.AVAILABLE_ACTIONS[this.state()];
1272 8d08f18a Kostas Papadimitriou
        },
1273 8d08f18a Kostas Papadimitriou
1274 8d08f18a Kostas Papadimitriou
        set_profile: function(profile, net_id) {
1275 8d08f18a Kostas Papadimitriou
        },
1276 8d08f18a Kostas Papadimitriou
        
1277 8d08f18a Kostas Papadimitriou
        // call rename api
1278 8d08f18a Kostas Papadimitriou
        rename: function(new_name) {
1279 8d08f18a Kostas Papadimitriou
            //this.set({'name': new_name});
1280 8d08f18a Kostas Papadimitriou
            this.sync("update", this, {
1281 9ffd10ce Kostas Papadimitriou
                critical: true,
1282 8d08f18a Kostas Papadimitriou
                data: {
1283 8d08f18a Kostas Papadimitriou
                    'server': {
1284 8d08f18a Kostas Papadimitriou
                        'name': new_name
1285 8d08f18a Kostas Papadimitriou
                    }
1286 8d08f18a Kostas Papadimitriou
                }, 
1287 8d08f18a Kostas Papadimitriou
                // do the rename after the method succeeds
1288 8d08f18a Kostas Papadimitriou
                success: _.bind(function(){
1289 8d08f18a Kostas Papadimitriou
                    //this.set({name: new_name});
1290 8d08f18a Kostas Papadimitriou
                    snf.api.trigger("call");
1291 8d08f18a Kostas Papadimitriou
                }, this)
1292 8d08f18a Kostas Papadimitriou
            });
1293 8d08f18a Kostas Papadimitriou
        },
1294 8d08f18a Kostas Papadimitriou
        
1295 8d08f18a Kostas Papadimitriou
        get_console_url: function(data) {
1296 8d08f18a Kostas Papadimitriou
            var url_params = {
1297 8d08f18a Kostas Papadimitriou
                machine: this.get("name"),
1298 8d08f18a Kostas Papadimitriou
                host_ip: this.get_addresses().ip4,
1299 8d08f18a Kostas Papadimitriou
                host_ip_v6: this.get_addresses().ip6,
1300 8d08f18a Kostas Papadimitriou
                host: data.host,
1301 8d08f18a Kostas Papadimitriou
                port: data.port,
1302 8d08f18a Kostas Papadimitriou
                password: data.password
1303 8d08f18a Kostas Papadimitriou
            }
1304 8d08f18a Kostas Papadimitriou
            return '/machines/console?' + $.param(url_params);
1305 8d08f18a Kostas Papadimitriou
        },
1306 8d08f18a Kostas Papadimitriou
1307 8d08f18a Kostas Papadimitriou
        // action helper
1308 8d08f18a Kostas Papadimitriou
        call: function(action_name, success, error) {
1309 8d08f18a Kostas Papadimitriou
            var id_param = [this.id];
1310 8d08f18a Kostas Papadimitriou
1311 8d08f18a Kostas Papadimitriou
            success = success || function() {};
1312 8d08f18a Kostas Papadimitriou
            error = error || function() {};
1313 8d08f18a Kostas Papadimitriou
1314 8d08f18a Kostas Papadimitriou
            var self = this;
1315 8d08f18a Kostas Papadimitriou
1316 8d08f18a Kostas Papadimitriou
            switch(action_name) {
1317 8d08f18a Kostas Papadimitriou
                case 'start':
1318 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.get_action_url(), // vm actions url
1319 8d08f18a Kostas Papadimitriou
                                         "create", // create so that sync later uses POST to make the call
1320 8d08f18a Kostas Papadimitriou
                                         {start:{}}, // payload
1321 8d08f18a Kostas Papadimitriou
                                         function() {
1322 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1323 8d08f18a Kostas Papadimitriou
                                             self.state("START"); 
1324 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments);
1325 8d08f18a Kostas Papadimitriou
                                             snf.api.trigger("call");
1326 8d08f18a Kostas Papadimitriou
                                         },  
1327 6a3a5bf7 Kostas Papadimitriou
                                         error, 'start');
1328 8d08f18a Kostas Papadimitriou
                    break;
1329 8d08f18a Kostas Papadimitriou
                case 'reboot':
1330 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.get_action_url(), // vm actions url
1331 8d08f18a Kostas Papadimitriou
                                         "create", // create so that sync later uses POST to make the call
1332 8d08f18a Kostas Papadimitriou
                                         {reboot:{type:"HARD"}}, // payload
1333 8d08f18a Kostas Papadimitriou
                                         function() {
1334 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1335 8d08f18a Kostas Papadimitriou
                                             self.state("REBOOT"); 
1336 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments)
1337 8d08f18a Kostas Papadimitriou
                                             snf.api.trigger("call");
1338 122850c5 Kostas Papadimitriou
                                             self.set({'reboot_required': false});
1339 8d08f18a Kostas Papadimitriou
                                         },
1340 6a3a5bf7 Kostas Papadimitriou
                                         error, 'reboot');
1341 8d08f18a Kostas Papadimitriou
                    break;
1342 8d08f18a Kostas Papadimitriou
                case 'shutdown':
1343 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.get_action_url(), // vm actions url
1344 8d08f18a Kostas Papadimitriou
                                         "create", // create so that sync later uses POST to make the call
1345 8d08f18a Kostas Papadimitriou
                                         {shutdown:{}}, // payload
1346 8d08f18a Kostas Papadimitriou
                                         function() {
1347 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1348 8d08f18a Kostas Papadimitriou
                                             self.state("SHUTDOWN"); 
1349 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments)
1350 8d08f18a Kostas Papadimitriou
                                             snf.api.trigger("call");
1351 8d08f18a Kostas Papadimitriou
                                         },  
1352 6a3a5bf7 Kostas Papadimitriou
                                         error, 'shutdown');
1353 8d08f18a Kostas Papadimitriou
                    break;
1354 8d08f18a Kostas Papadimitriou
                case 'console':
1355 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.url() + "/action", "create", {'console': {'type':'vnc'}}, function(data) {
1356 8d08f18a Kostas Papadimitriou
                        var cons_data = data.console;
1357 8d08f18a Kostas Papadimitriou
                        success.apply(this, [cons_data]);
1358 6a3a5bf7 Kostas Papadimitriou
                    }, undefined, 'console')
1359 8d08f18a Kostas Papadimitriou
                    break;
1360 8d08f18a Kostas Papadimitriou
                case 'destroy':
1361 8d08f18a Kostas Papadimitriou
                    this.__make_api_call(this.url(), // vm actions url
1362 8d08f18a Kostas Papadimitriou
                                         "delete", // create so that sync later uses POST to make the call
1363 8d08f18a Kostas Papadimitriou
                                         undefined, // payload
1364 8d08f18a Kostas Papadimitriou
                                         function() {
1365 8d08f18a Kostas Papadimitriou
                                             // set state after successful call
1366 8d08f18a Kostas Papadimitriou
                                             self.state('DESTROY');
1367 8d08f18a Kostas Papadimitriou
                                             success.apply(this, arguments)
1368 8d08f18a Kostas Papadimitriou
                                         },  
1369 6a3a5bf7 Kostas Papadimitriou
                                         error, 'destroy');
1370 8d08f18a Kostas Papadimitriou
                    break;
1371 8d08f18a Kostas Papadimitriou
                default:
1372 8d08f18a Kostas Papadimitriou
                    throw "Invalid VM action ("+action_name+")";
1373 8d08f18a Kostas Papadimitriou
            }
1374 8d08f18a Kostas Papadimitriou
        },
1375 8d08f18a Kostas Papadimitriou
        
1376 edd1d565 Kostas Papadimitriou
        __make_api_call: function(url, method, data, success, error, action) {
1377 8d08f18a Kostas Papadimitriou
            var self = this;
1378 8d08f18a Kostas Papadimitriou
            error = error || function(){};
1379 8d08f18a Kostas Papadimitriou
            success = success || function(){};
1380 8d08f18a Kostas Papadimitriou
1381 8d08f18a Kostas Papadimitriou
            var params = {
1382 8d08f18a Kostas Papadimitriou
                url: url,
1383 8d08f18a Kostas Papadimitriou
                data: data,
1384 8d08f18a Kostas Papadimitriou
                success: function(){ self.handle_action_succeed.apply(self, arguments); success.apply(this, arguments)},
1385 edd1d565 Kostas Papadimitriou
                error: function(){ self.handle_action_fail.apply(self, arguments); error.apply(this, arguments)},
1386 edd1d565 Kostas Papadimitriou
                error_params: { ns: "Machines actions", 
1387 9ffd10ce Kostas Papadimitriou
                                title: "'" + this.get("name") + "'" + " " + action + " failed", 
1388 6a3a5bf7 Kostas Papadimitriou
                                extra_details: { 'Machine ID': this.id, 'URL': url, 'Action': action || "undefined" },
1389 6a3a5bf7 Kostas Papadimitriou
                                allow_reload: false
1390 6a3a5bf7 Kostas Papadimitriou
                              },
1391 9ce969a7 Kostas Papadimitriou
                display: false,
1392 9ce969a7 Kostas Papadimitriou
                critical: false
1393 8d08f18a Kostas Papadimitriou
            }
1394 8d08f18a Kostas Papadimitriou
            this.sync(method, this, params);
1395 8d08f18a Kostas Papadimitriou
        },
1396 8d08f18a Kostas Papadimitriou
1397 8d08f18a Kostas Papadimitriou
        handle_action_succeed: function() {
1398 8d08f18a Kostas Papadimitriou
            this.trigger("action:success", arguments);
1399 8d08f18a Kostas Papadimitriou
        },
1400 6a3a5bf7 Kostas Papadimitriou
        
1401 6a3a5bf7 Kostas Papadimitriou
        reset_action_error: function() {
1402 6a3a5bf7 Kostas Papadimitriou
            this.action_error = false;
1403 6a3a5bf7 Kostas Papadimitriou
            this.trigger("action:fail:reset", this.action_error);
1404 6a3a5bf7 Kostas Papadimitriou
        },
1405 8d08f18a Kostas Papadimitriou
1406 8d08f18a Kostas Papadimitriou
        handle_action_fail: function() {
1407 6a3a5bf7 Kostas Papadimitriou
            this.action_error = arguments;
1408 8d08f18a Kostas Papadimitriou
            this.trigger("action:fail", arguments);
1409 8d08f18a Kostas Papadimitriou
        },
1410 8d08f18a Kostas Papadimitriou
1411 8d08f18a Kostas Papadimitriou
        get_action_url: function(name) {
1412 8d08f18a Kostas Papadimitriou
            return this.url() + "/action";
1413 1c922789 Kostas Papadimitriou
        },
1414 1c922789 Kostas Papadimitriou
1415 1c922789 Kostas Papadimitriou
        get_connection_info: function(host_os, success, error) {
1416 1c922789 Kostas Papadimitriou
            var url = "/machines/connect";
1417 1c922789 Kostas Papadimitriou
            params = {
1418 1c922789 Kostas Papadimitriou
                ip_address: this.get_addresses().ip4,
1419 1c922789 Kostas Papadimitriou
                os: this.get_os(),
1420 1c922789 Kostas Papadimitriou
                host_os: host_os,
1421 1c922789 Kostas Papadimitriou
                srv: this.id
1422 1c922789 Kostas Papadimitriou
            }
1423 1c922789 Kostas Papadimitriou
1424 1c922789 Kostas Papadimitriou
            url = url + "?" + $.param(params);
1425 1c922789 Kostas Papadimitriou
1426 1c922789 Kostas Papadimitriou
            var ajax = snf.api.sync("read", undefined, { url: url, 
1427 1c922789 Kostas Papadimitriou
                                                         error:error, 
1428 1c922789 Kostas Papadimitriou
                                                         success:success, 
1429 1c922789 Kostas Papadimitriou
                                                         handles_error:1});
1430 8d08f18a Kostas Papadimitriou
        }
1431 8d08f18a Kostas Papadimitriou
    })
1432 8d08f18a Kostas Papadimitriou
    
1433 8d08f18a Kostas Papadimitriou
    models.VM.ACTIONS = [
1434 8d08f18a Kostas Papadimitriou
        'start',
1435 8d08f18a Kostas Papadimitriou
        'shutdown',
1436 8d08f18a Kostas Papadimitriou
        'reboot',
1437 0f7214b3 Kostas Papadimitriou
        'console',
1438 8d08f18a Kostas Papadimitriou
        'destroy'
1439 8d08f18a Kostas Papadimitriou
    ]
1440 8d08f18a Kostas Papadimitriou
1441 8d08f18a Kostas Papadimitriou
    models.VM.AVAILABLE_ACTIONS = {
1442 8d08f18a Kostas Papadimitriou
        'UNKNWON'       : ['destroy'],
1443 8d08f18a Kostas Papadimitriou
        'BUILD'         : ['destroy'],
1444 8d08f18a Kostas Papadimitriou
        'REBOOT'        : ['shutdown', 'destroy', 'console'],
1445 8d08f18a Kostas Papadimitriou
        'STOPPED'       : ['start', 'destroy'],
1446 8d08f18a Kostas Papadimitriou
        'ACTIVE'        : ['shutdown', 'destroy', 'reboot', 'console'],
1447 8d08f18a Kostas Papadimitriou
        'ERROR'         : ['destroy'],
1448 643de8c0 Kostas Papadimitriou
        'DELETED'        : [],
1449 8d08f18a Kostas Papadimitriou
        'DESTROY'       : [],
1450 8d08f18a Kostas Papadimitriou
        'BUILD_INIT'    : ['destroy'],
1451 8d08f18a Kostas Papadimitriou
        'BUILD_COPY'    : ['destroy'],
1452 8d08f18a Kostas Papadimitriou
        'BUILD_FINAL'   : ['destroy'],
1453 8d08f18a Kostas Papadimitriou
        'SHUTDOWN'      : ['destroy'],
1454 8d08f18a Kostas Papadimitriou
        'START'         : [],
1455 8d08f18a Kostas Papadimitriou
        'CONNECT'       : [],
1456 8d08f18a Kostas Papadimitriou
        'DISCONNECT'    : []
1457 8d08f18a Kostas Papadimitriou
    }
1458 8d08f18a Kostas Papadimitriou
1459 8d08f18a Kostas Papadimitriou
    // api status values
1460 8d08f18a Kostas Papadimitriou
    models.VM.STATUSES = [
1461 8d08f18a Kostas Papadimitriou
        'UNKNWON',
1462 8d08f18a Kostas Papadimitriou
        'BUILD',
1463 8d08f18a Kostas Papadimitriou
        'REBOOT',
1464 8d08f18a Kostas Papadimitriou
        'STOPPED',
1465 8d08f18a Kostas Papadimitriou
        'ACTIVE',
1466 8d08f18a Kostas Papadimitriou
        'ERROR',
1467 643de8c0 Kostas Papadimitriou
        'DELETED'
1468 8d08f18a Kostas Papadimitriou
    ]
1469 8d08f18a Kostas Papadimitriou
1470 8d08f18a Kostas Papadimitriou
    // api status values
1471 8d08f18a Kostas Papadimitriou
    models.VM.CONNECT_STATES = [
1472 8d08f18a Kostas Papadimitriou
        'ACTIVE',
1473 8d08f18a Kostas Papadimitriou
        'REBOOT',
1474 df12e032 Kostas Papadimitriou
        'SHUTDOWN'
1475 8d08f18a Kostas Papadimitriou
    ]
1476 8d08f18a Kostas Papadimitriou
1477 8d08f18a Kostas Papadimitriou
    // vm states
1478 8d08f18a Kostas Papadimitriou
    models.VM.STATES = models.VM.STATUSES.concat([
1479 8d08f18a Kostas Papadimitriou
        'DESTROY',
1480 8d08f18a Kostas Papadimitriou
        'BUILD_INIT',
1481 8d08f18a Kostas Papadimitriou
        'BUILD_COPY',
1482 8d08f18a Kostas Papadimitriou
        'BUILD_FINAL',
1483 8d08f18a Kostas Papadimitriou
        'SHUTDOWN',
1484 8d08f18a Kostas Papadimitriou
        'START',
1485 8d08f18a Kostas Papadimitriou
        'CONNECT',
1486 8d08f18a Kostas Papadimitriou
        'DISCONNECT',
1487 8d08f18a Kostas Papadimitriou
        'FIREWALL'
1488 8d08f18a Kostas Papadimitriou
    ]);
1489 8d08f18a Kostas Papadimitriou
    
1490 8d08f18a Kostas Papadimitriou
    models.VM.STATES_TRANSITIONS = {
1491 643de8c0 Kostas Papadimitriou
        'DESTROY' : ['DELETED'],
1492 8d08f18a Kostas Papadimitriou
        'SHUTDOWN': ['ERROR', 'STOPPED', 'DESTROY'],
1493 8d08f18a Kostas Papadimitriou
        'STOPPED': ['ERROR', 'ACTIVE', 'DESTROY'],
1494 8d08f18a Kostas Papadimitriou
        'ACTIVE': ['ERROR', 'STOPPED', 'REBOOT', 'SHUTDOWN', 'DESTROY'],
1495 8d08f18a Kostas Papadimitriou
        'START': ['ERROR', 'ACTIVE', 'DESTROY'],
1496 8d08f18a Kostas Papadimitriou
        'REBOOT': ['ERROR', 'ACTIVE', 'STOPPED', 'DESTROY'],
1497 8d08f18a Kostas Papadimitriou
        'BUILD': ['ERROR', 'ACTIVE', 'DESTROY'],
1498 8d08f18a Kostas Papadimitriou
        'BUILD_COPY': ['ERROR', 'ACTIVE', 'BUILD_FINAL', 'DESTROY'],
1499 8d08f18a Kostas Papadimitriou
        'BUILD_FINAL': ['ERROR', 'ACTIVE', 'DESTROY'],
1500 8d08f18a Kostas Papadimitriou
        'BUILD_INIT': ['ERROR', 'ACTIVE', 'BUILD_COPY', 'BUILD_FINAL', 'DESTROY']
1501 8d08f18a Kostas Papadimitriou
    }
1502 8d08f18a Kostas Papadimitriou
1503 8d08f18a Kostas Papadimitriou
    models.VM.TRANSITION_STATES = [
1504 8d08f18a Kostas Papadimitriou
        'DESTROY',
1505 8d08f18a Kostas Papadimitriou
        'SHUTDOWN',
1506 8d08f18a Kostas Papadimitriou
        'START',
1507 8d08f18a Kostas Papadimitriou
        'REBOOT',
1508 8d08f18a Kostas Papadimitriou
        'BUILD'
1509 8d08f18a Kostas Papadimitriou
    ]
1510 8d08f18a Kostas Papadimitriou
1511 8d08f18a Kostas Papadimitriou
    models.VM.ACTIVE_STATES = [
1512 8d08f18a Kostas Papadimitriou
        'BUILD', 'REBOOT', 'ACTIVE',
1513 8d08f18a Kostas Papadimitriou
        'BUILD_INIT', 'BUILD_COPY', 'BUILD_FINAL',
1514 4e365467 Kostas Papadimitriou
        'SHUTDOWN', 'CONNECT', 'DISCONNECT'
1515 8d08f18a Kostas Papadimitriou
    ]
1516 8d08f18a Kostas Papadimitriou
1517 8d08f18a Kostas Papadimitriou
    models.VM.BUILDING_STATES = [
1518 8d08f18a Kostas Papadimitriou
        'BUILD', 'BUILD_INIT', 'BUILD_COPY', 'BUILD_FINAL'
1519 8d08f18a Kostas Papadimitriou
    ]
1520 8d08f18a Kostas Papadimitriou
1521 8d08f18a Kostas Papadimitriou
    models.Networks = models.Collection.extend({
1522 8d08f18a Kostas Papadimitriou
        model: models.Network,
1523 8d08f18a Kostas Papadimitriou
        path: 'networks',
1524 8d08f18a Kostas Papadimitriou
        details: true,
1525 8d08f18a Kostas Papadimitriou
        //noUpdate: true,
1526 8d08f18a Kostas Papadimitriou
        defaults: {'linked_to':[]},
1527 8d08f18a Kostas Papadimitriou
1528 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1529 8d08f18a Kostas Papadimitriou
            // FIXME: depricated global var
1530 8d08f18a Kostas Papadimitriou
            if (!resp) { return []};
1531 8d08f18a Kostas Papadimitriou
               
1532 8d08f18a Kostas Papadimitriou
            var data = _.map(resp.networks.values, _.bind(this.parse_net_api_data, this));
1533 8d08f18a Kostas Papadimitriou
            return data;
1534 8d08f18a Kostas Papadimitriou
        },
1535 8d08f18a Kostas Papadimitriou
1536 101e6604 Kostas Papadimitriou
        reset_pending_actions: function() {
1537 101e6604 Kostas Papadimitriou
            this.each(function(net) {
1538 101e6604 Kostas Papadimitriou
                net.get("actions").reset();
1539 101e6604 Kostas Papadimitriou
            })
1540 101e6604 Kostas Papadimitriou
        },
1541 101e6604 Kostas Papadimitriou
1542 101e6604 Kostas Papadimitriou
        do_all_pending_actions: function() {
1543 101e6604 Kostas Papadimitriou
            this.each(function(net) {
1544 101e6604 Kostas Papadimitriou
                net.do_all_pending_actions();
1545 101e6604 Kostas Papadimitriou
            })
1546 101e6604 Kostas Papadimitriou
        },
1547 101e6604 Kostas Papadimitriou
1548 8d08f18a Kostas Papadimitriou
        parse_net_api_data: function(data) {
1549 8d08f18a Kostas Papadimitriou
            if (data.servers && data.servers.values) {
1550 8d08f18a Kostas Papadimitriou
                data['linked_to'] = data.servers.values;
1551 8d08f18a Kostas Papadimitriou
            }
1552 8d08f18a Kostas Papadimitriou
            return data;
1553 8d08f18a Kostas Papadimitriou
        },
1554 8d08f18a Kostas Papadimitriou
1555 8d08f18a Kostas Papadimitriou
        create: function (name, callback) {
1556 258235f4 Kostas Papadimitriou
            return this.api_call(this.path, "create", {network:{name:name}}, callback);
1557 8d08f18a Kostas Papadimitriou
        }
1558 8d08f18a Kostas Papadimitriou
    })
1559 8d08f18a Kostas Papadimitriou
1560 8d08f18a Kostas Papadimitriou
    models.Images = models.Collection.extend({
1561 8d08f18a Kostas Papadimitriou
        model: models.Image,
1562 8d08f18a Kostas Papadimitriou
        path: 'images',
1563 8d08f18a Kostas Papadimitriou
        details: true,
1564 8d08f18a Kostas Papadimitriou
        noUpdate: true,
1565 16392650 Kostas Papadimitriou
        supportIncUpdates: false,
1566 8d08f18a Kostas Papadimitriou
        meta_keys_as_attrs: ["OS", "description", "kernel", "size", "GUI"],
1567 258235f4 Kostas Papadimitriou
        read_method: 'read',
1568 8d08f18a Kostas Papadimitriou
1569 bedfe884 Kostas Papadimitriou
        // update collection model with id passed
1570 1420aae4 Kostas Papadimitriou
        // making a direct call to the image
1571 bedfe884 Kostas Papadimitriou
        // api url
1572 c45bed88 Kostas Papadimitriou
        update_unknown_id: function(id, callback) {
1573 bedfe884 Kostas Papadimitriou
            var url = getUrl.call(this) + "/" + id;
1574 c45bed88 Kostas Papadimitriou
            this.api_call(this.path + "/" + id, this.read_method, {_options:{async:true, skip_api_error:true}}, undefined, 
1575 bedfe884 Kostas Papadimitriou
            _.bind(function() {
1576 327f0d58 Kostas Papadimitriou
                if (!this.get(id)) {
1577 d7612b6e Kostas Papadimitriou
                            if (this.fallback_service) {
1578 d7612b6e Kostas Papadimitriou
                        // if current service has fallback_service attribute set
1579 d7612b6e Kostas Papadimitriou
                        // use this service to retrieve the missing image model
1580 d7612b6e Kostas Papadimitriou
                        var tmpservice = new this.fallback_service();
1581 d7612b6e Kostas Papadimitriou
                        tmpservice.update_unknown_id(id, _.bind(function(img){
1582 d7612b6e Kostas Papadimitriou
                            img.attributes.status = "DELETED";
1583 d7612b6e Kostas Papadimitriou
                            this.add(img.attributes);
1584 d7612b6e Kostas Papadimitriou
                            callback(this.get(id));
1585 d7612b6e Kostas Papadimitriou
                        }, this));
1586 d7612b6e Kostas Papadimitriou
                    } else {
1587 d7612b6e Kostas Papadimitriou
                        // else add a dummy DELETED state image entry
1588 d7612b6e Kostas Papadimitriou
                        this.add({id:id, name:"Unknown image", size:-1, 
1589 d7612b6e Kostas Papadimitriou
                                  progress:100, status:"DELETED"});
1590 d7612b6e Kostas Papadimitriou
                        callback(this.get(id));
1591 d7612b6e Kostas Papadimitriou
                    }   
1592 d7612b6e Kostas Papadimitriou
                } else {
1593 d7612b6e Kostas Papadimitriou
                    callback(this.get(id));
1594 327f0d58 Kostas Papadimitriou
                }
1595 258235f4 Kostas Papadimitriou
            }, this), _.bind(function(image, msg, xhr) {
1596 f70c8d47 Kostas Papadimitriou
                if (!image) {
1597 f70c8d47 Kostas Papadimitriou
                    this.add({id:id, name:"Unknown image", size:-1, 
1598 f70c8d47 Kostas Papadimitriou
                              progress:100, status:"DELETED"});
1599 f70c8d47 Kostas Papadimitriou
                    callback(this.get(id));
1600 f70c8d47 Kostas Papadimitriou
                    return;
1601 f70c8d47 Kostas Papadimitriou
                }
1602 258235f4 Kostas Papadimitriou
                var img_data = this._read_image_from_request(image, msg, xhr);
1603 258235f4 Kostas Papadimitriou
                this.add(img_data);
1604 c45bed88 Kostas Papadimitriou
                callback(this.get(id));
1605 bedfe884 Kostas Papadimitriou
            }, this));
1606 bedfe884 Kostas Papadimitriou
        },
1607 bedfe884 Kostas Papadimitriou
1608 258235f4 Kostas Papadimitriou
        _read_image_from_request: function(image, msg, xhr) {
1609 258235f4 Kostas Papadimitriou
            return image.image;
1610 258235f4 Kostas Papadimitriou
        },
1611 258235f4 Kostas Papadimitriou
1612 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1613 8d08f18a Kostas Papadimitriou
            // FIXME: depricated global var
1614 8d08f18a Kostas Papadimitriou
            var data = _.map(resp.images.values, _.bind(this.parse_meta, this));
1615 8d08f18a Kostas Papadimitriou
            return resp.images.values;
1616 8d08f18a Kostas Papadimitriou
        },
1617 8d08f18a Kostas Papadimitriou
1618 8d08f18a Kostas Papadimitriou
        get_meta_key: function(img, key) {
1619 8d08f18a Kostas Papadimitriou
            if (img.metadata && img.metadata.values && img.metadata.values[key]) {
1620 df251d55 Kostas Papadimitriou
                return _.escape(img.metadata.values[key]);
1621 8d08f18a Kostas Papadimitriou
            }
1622 8d08f18a Kostas Papadimitriou
            return undefined;
1623 8d08f18a Kostas Papadimitriou
        },
1624 8d08f18a Kostas Papadimitriou
1625 ccb14ad0 Kostas Papadimitriou
        comparator: function(img) {
1626 ccb14ad0 Kostas Papadimitriou
            return -img.get_sort_order("sortorder") || 1000 * img.id;
1627 ccb14ad0 Kostas Papadimitriou
        },
1628 ccb14ad0 Kostas Papadimitriou
1629 8d08f18a Kostas Papadimitriou
        parse_meta: function(img) {
1630 8d08f18a Kostas Papadimitriou
            _.each(this.meta_keys_as_attrs, _.bind(function(key){
1631 258235f4 Kostas Papadimitriou
                if (img[key]) { return };
1632 2a5ae934 Kostas Papadimitriou
                img[key] = this.get_meta_key(img, key) || "";
1633 8d08f18a Kostas Papadimitriou
            }, this));
1634 8d08f18a Kostas Papadimitriou
            return img;
1635 bedfe884 Kostas Papadimitriou
        },
1636 bedfe884 Kostas Papadimitriou
1637 bedfe884 Kostas Papadimitriou
        active: function() {
1638 bedfe884 Kostas Papadimitriou
            return this.filter(function(img){return img.get('status') != "DELETED"});
1639 2cee7cb0 Kostas Papadimitriou
        },
1640 2cee7cb0 Kostas Papadimitriou
1641 2cee7cb0 Kostas Papadimitriou
        predefined: function() {
1642 2cee7cb0 Kostas Papadimitriou
            return _.filter(this.active(), function(i) { return !i.get("serverRef")});
1643 948042ca Kostas Papadimitriou
        },
1644 948042ca Kostas Papadimitriou
        
1645 948042ca Kostas Papadimitriou
        fetch_for_type: function(type, complete, error) {
1646 948042ca Kostas Papadimitriou
            this.fetch({update:true, 
1647 948042ca Kostas Papadimitriou
                        success: complete, 
1648 948042ca Kostas Papadimitriou
                        error: error, 
1649 948042ca Kostas Papadimitriou
                        skip_api_error: true });
1650 948042ca Kostas Papadimitriou
        },
1651 948042ca Kostas Papadimitriou
        
1652 948042ca Kostas Papadimitriou
        get_images_for_type: function(type) {
1653 948042ca Kostas Papadimitriou
            if (this['get_{0}_images'.format(type)]) {
1654 948042ca Kostas Papadimitriou
                return this['get_{0}_images'.format(type)]();
1655 948042ca Kostas Papadimitriou
            }
1656 948042ca Kostas Papadimitriou
1657 948042ca Kostas Papadimitriou
            return this.active();
1658 948042ca Kostas Papadimitriou
        },
1659 948042ca Kostas Papadimitriou
1660 948042ca Kostas Papadimitriou
        update_images_for_type: function(type, onStart, onComplete, onError, force_load) {
1661 948042ca Kostas Papadimitriou
            var load = false;
1662 948042ca Kostas Papadimitriou
            error = onError || function() {};
1663 948042ca Kostas Papadimitriou
            function complete(collection) { 
1664 948042ca Kostas Papadimitriou
                onComplete(collection.get_images_for_type(type)); 
1665 948042ca Kostas Papadimitriou
            }
1666 948042ca Kostas Papadimitriou
            
1667 948042ca Kostas Papadimitriou
            // do we need to fetch/update current collection entries
1668 948042ca Kostas Papadimitriou
            if (load) {
1669 948042ca Kostas Papadimitriou
                onStart();
1670 948042ca Kostas Papadimitriou
                this.fetch_for_type(type, complete, error);
1671 948042ca Kostas Papadimitriou
            } else {
1672 948042ca Kostas Papadimitriou
                // fallback to complete
1673 948042ca Kostas Papadimitriou
                complete(this);
1674 948042ca Kostas Papadimitriou
            }
1675 8d08f18a Kostas Papadimitriou
        }
1676 8d08f18a Kostas Papadimitriou
    })
1677 8d08f18a Kostas Papadimitriou
1678 8d08f18a Kostas Papadimitriou
    models.Flavors = models.Collection.extend({
1679 8d08f18a Kostas Papadimitriou
        model: models.Flavor,
1680 8d08f18a Kostas Papadimitriou
        path: 'flavors',
1681 8d08f18a Kostas Papadimitriou
        details: true,
1682 8d08f18a Kostas Papadimitriou
        noUpdate: true,
1683 16392650 Kostas Papadimitriou
        supportIncUpdates: false,
1684 bedfe884 Kostas Papadimitriou
        // update collection model with id passed
1685 bedfe884 Kostas Papadimitriou
        // making a direct call to the flavor
1686 bedfe884 Kostas Papadimitriou
        // api url
1687 c45bed88 Kostas Papadimitriou
        update_unknown_id: function(id, callback) {
1688 bedfe884 Kostas Papadimitriou
            var url = getUrl.call(this) + "/" + id;
1689 258235f4 Kostas Papadimitriou
            this.api_call(this.path + "/" + id, "read", {_options:{async:false, skip_api_error:true}}, undefined, 
1690 bedfe884 Kostas Papadimitriou
            _.bind(function() {
1691 bedfe884 Kostas Papadimitriou
                this.add({id:id, cpu:"", ram:"", disk:"", name: "", status:"DELETED"})
1692 bedfe884 Kostas Papadimitriou
            }, this), _.bind(function(flv) {
1693 bedfe884 Kostas Papadimitriou
                if (!flv.flavor.status) { flv.flavor.status = "DELETED" };
1694 bedfe884 Kostas Papadimitriou
                this.add(flv.flavor);
1695 bedfe884 Kostas Papadimitriou
            }, this));
1696 bedfe884 Kostas Papadimitriou
        },
1697 8d08f18a Kostas Papadimitriou
1698 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1699 8d08f18a Kostas Papadimitriou
            // FIXME: depricated global var
1700 d965e6dc Kostas Papadimitriou
            return _.map(resp.flavors.values, function(o) { o.disk_template = o['SNF:disk_template']; return o});
1701 8d08f18a Kostas Papadimitriou
        },
1702 8d08f18a Kostas Papadimitriou
1703 ccb14ad0 Kostas Papadimitriou
        comparator: function(flv) {
1704 ccb14ad0 Kostas Papadimitriou
            return flv.get("disk") * flv.get("cpu") * flv.get("ram");
1705 ccb14ad0 Kostas Papadimitriou
        },
1706 ccb14ad0 Kostas Papadimitriou
1707 820ef2f0 Kostas Papadimitriou
        unavailable_values_for_image: function(img, flavors) {
1708 820ef2f0 Kostas Papadimitriou
            var flavors = flavors || this.active();
1709 820ef2f0 Kostas Papadimitriou
            var size = img.get_size();
1710 820ef2f0 Kostas Papadimitriou
            
1711 820ef2f0 Kostas Papadimitriou
            var index = {cpu:[], disk:[], ram:[]};
1712 820ef2f0 Kostas Papadimitriou
1713 820ef2f0 Kostas Papadimitriou
            _.each(this.active(), function(el) {
1714 820ef2f0 Kostas Papadimitriou
                var img_size = size;
1715 820ef2f0 Kostas Papadimitriou
                var flv_size = el.get_disk_size();
1716 820ef2f0 Kostas Papadimitriou
                if (flv_size < img_size) {
1717 820ef2f0 Kostas Papadimitriou
                    if (index.disk.indexOf(flv_size) == -1) {
1718 820ef2f0 Kostas Papadimitriou
                        index.disk.push(flv_size);
1719 820ef2f0 Kostas Papadimitriou
                    }
1720 820ef2f0 Kostas Papadimitriou
                };
1721 820ef2f0 Kostas Papadimitriou
            });
1722 820ef2f0 Kostas Papadimitriou
            
1723 820ef2f0 Kostas Papadimitriou
            return index;
1724 8d08f18a Kostas Papadimitriou
        },
1725 820ef2f0 Kostas Papadimitriou
1726 d965e6dc Kostas Papadimitriou
        get_flavor: function(cpu, mem, disk, disk_template, filter_list) {
1727 8d08f18a Kostas Papadimitriou
            if (!filter_list) { filter_list = this.models };
1728 d965e6dc Kostas Papadimitriou
            
1729 8d08f18a Kostas Papadimitriou
            return this.select(function(flv){
1730 8d08f18a Kostas Papadimitriou
                if (flv.get("cpu") == cpu + "" &&
1731 8d08f18a Kostas Papadimitriou
                   flv.get("ram") == mem + "" &&
1732 8d08f18a Kostas Papadimitriou
                   flv.get("disk") == disk + "" &&
1733 d965e6dc Kostas Papadimitriou
                   flv.get("disk_template") == disk_template &&
1734 820ef2f0 Kostas Papadimitriou
                   filter_list.indexOf(flv) > -1) { return true; }
1735 9ce969a7 Kostas Papadimitriou
            })[0];
1736 8d08f18a Kostas Papadimitriou
        },
1737 820ef2f0 Kostas Papadimitriou
        
1738 8d08f18a Kostas Papadimitriou
        get_data: function(lst) {
1739 8d08f18a Kostas Papadimitriou
            var data = {'cpu': [], 'mem':[], 'disk':[]};
1740 820ef2f0 Kostas Papadimitriou
1741 8d08f18a Kostas Papadimitriou
            _.each(lst, function(flv) {
1742 820ef2f0 Kostas Papadimitriou
                if (data.cpu.indexOf(flv.get("cpu")) == -1) {
1743 820ef2f0 Kostas Papadimitriou
                    data.cpu.push(flv.get("cpu"));
1744 8d08f18a Kostas Papadimitriou
                }
1745 820ef2f0 Kostas Papadimitriou
                if (data.mem.indexOf(flv.get("ram")) == -1) {
1746 820ef2f0 Kostas Papadimitriou
                    data.mem.push(flv.get("ram"));
1747 8d08f18a Kostas Papadimitriou
                }
1748 820ef2f0 Kostas Papadimitriou
                if (data.disk.indexOf(flv.get("disk")) == -1) {
1749 820ef2f0 Kostas Papadimitriou
                    data.disk.push(flv.get("disk"));
1750 8d08f18a Kostas Papadimitriou
                }
1751 8d08f18a Kostas Papadimitriou
            })
1752 820ef2f0 Kostas Papadimitriou
            
1753 8d08f18a Kostas Papadimitriou
            return data;
1754 bedfe884 Kostas Papadimitriou
        },
1755 bedfe884 Kostas Papadimitriou
1756 bedfe884 Kostas Papadimitriou
        active: function() {
1757 bedfe884 Kostas Papadimitriou
            return this.filter(function(flv){return flv.get('status') != "DELETED"});
1758 8d08f18a Kostas Papadimitriou
        }
1759 8d08f18a Kostas Papadimitriou
            
1760 8d08f18a Kostas Papadimitriou
    })
1761 8d08f18a Kostas Papadimitriou
1762 8d08f18a Kostas Papadimitriou
    models.VMS = models.Collection.extend({
1763 8d08f18a Kostas Papadimitriou
        model: models.VM,
1764 8d08f18a Kostas Papadimitriou
        path: 'servers',
1765 8d08f18a Kostas Papadimitriou
        details: true,
1766 8d08f18a Kostas Papadimitriou
        copy_image_meta: true,
1767 8d08f18a Kostas Papadimitriou
        
1768 8d08f18a Kostas Papadimitriou
        parse: function (resp, xhr) {
1769 8d08f18a Kostas Papadimitriou
            // FIXME: depricated after refactoring
1770 8d08f18a Kostas Papadimitriou
            var data = resp;
1771 8d08f18a Kostas Papadimitriou
            if (!resp) { return [] };
1772 820ef2f0 Kostas Papadimitriou
            data = _.filter(_.map(resp.servers.values, _.bind(this.parse_vm_api_data, this)), function(v){return v});
1773 8d08f18a Kostas Papadimitriou
            return data;
1774 8d08f18a Kostas Papadimitriou
        },
1775 122850c5 Kostas Papadimitriou
        
1776 122850c5 Kostas Papadimitriou
        get_reboot_required: function() {
1777 122850c5 Kostas Papadimitriou
            return this.filter(function(vm){return vm.get("reboot_required") == true})
1778 122850c5 Kostas Papadimitriou
        },
1779 122850c5 Kostas Papadimitriou
1780 122850c5 Kostas Papadimitriou
        has_pending_actions: function() {
1781 122850c5 Kostas Papadimitriou
            return this.filter(function(vm){return vm.pending_action}).length > 0;
1782 122850c5 Kostas Papadimitriou
        },
1783 8d08f18a Kostas Papadimitriou
1784 8d08f18a Kostas Papadimitriou
        reset_pending_actions: function() {
1785 8d08f18a Kostas Papadimitriou
            this.each(function(vm) {
1786 8d08f18a Kostas Papadimitriou
                vm.clear_pending_action();
1787 8d08f18a Kostas Papadimitriou
            })
1788 8d08f18a Kostas Papadimitriou
        },
1789 101e6604 Kostas Papadimitriou
1790 101e6604 Kostas Papadimitriou
        do_all_pending_actions: function(success, error) {
1791 101e6604 Kostas Papadimitriou
            this.each(function(vm) {
1792 101e6604 Kostas Papadimitriou
                if (vm.has_pending_action()) {
1793 101e6604 Kostas Papadimitriou
                    vm.call(vm.pending_action, success, error);
1794 101e6604 Kostas Papadimitriou
                    vm.clear_pending_action();
1795 101e6604 Kostas Papadimitriou
                }
1796 101e6604 Kostas Papadimitriou
            })
1797 101e6604 Kostas Papadimitriou
        },
1798 101e6604 Kostas Papadimitriou
        
1799 101e6604 Kostas Papadimitriou
        do_all_reboots: function(success, error) {
1800 101e6604 Kostas Papadimitriou
            this.each(function(vm) {
1801 101e6604 Kostas Papadimitriou
                if (vm.get("reboot_required")) {
1802 101e6604 Kostas Papadimitriou
                    vm.call("reboot", success, error);
1803 101e6604 Kostas Papadimitriou
                }
1804 101e6604 Kostas Papadimitriou
            });
1805 101e6604 Kostas Papadimitriou
        },
1806 101e6604 Kostas Papadimitriou
1807 101e6604 Kostas Papadimitriou
        reset_reboot_required: function() {
1808 101e6604 Kostas Papadimitriou
            this.each(function(vm) {
1809 101e6604 Kostas Papadimitriou
                vm.set({'reboot_required': undefined});
1810 101e6604 Kostas Papadimitriou
            })
1811 101e6604 Kostas Papadimitriou
        },
1812 2c9bfad1 Kostas Papadimitriou
        
1813 2c9bfad1 Kostas Papadimitriou
        stop_stats_update: function(exclude) {
1814 2c9bfad1 Kostas Papadimitriou
            var exclude = exclude || [];
1815 96d725ac Kostas Papadimitriou
            this.each(function(vm) {
1816 2c9bfad1 Kostas Papadimitriou
                if (exclude.indexOf(vm) > -1) {
1817 2c9bfad1 Kostas Papadimitriou
                    return;
1818 2c9bfad1 Kostas Papadimitriou
                }
1819 2c9bfad1 Kostas Papadimitriou
                vm.stop_stats_update();
1820 96d725ac Kostas Papadimitriou
            })
1821 96d725ac Kostas Papadimitriou
        },
1822 8d08f18a Kostas Papadimitriou
        
1823 8d08f18a Kostas Papadimitriou
        has_meta: function(vm_data) {
1824 8d08f18a Kostas Papadimitriou
            return vm_data.metadata && vm_data.metadata.values
1825 8d08f18a Kostas Papadimitriou
        },
1826 8d08f18a Kostas Papadimitriou
1827 8d08f18a Kostas Papadimitriou
        has_addresses: function(vm_data) {
1828 8d08f18a Kostas Papadimitriou
            return vm_data.metadata && vm_data.metadata.values
1829 8d08f18a Kostas Papadimitriou
        },
1830 8d08f18a Kostas Papadimitriou
1831 8d08f18a Kostas Papadimitriou
        parse_vm_api_data: function(data) {
1832 820ef2f0 Kostas Papadimitriou
            // do not add non existing DELETED entries
1833 820ef2f0 Kostas Papadimitriou
            if (data.status && data.status == "DELETED") {
1834 820ef2f0 Kostas Papadimitriou
                if (!this.get(data.id)) {
1835 820ef2f0 Kostas Papadimitriou
                    return false;
1836 820ef2f0 Kostas Papadimitriou
                }
1837 820ef2f0 Kostas Papadimitriou
            }
1838 820ef2f0 Kostas Papadimitriou
1839 8d08f18a Kostas Papadimitriou
            // OS attribute
1840 8d08f18a Kostas Papadimitriou
            if (this.has_meta(data)) {
1841 c3f0d25f Kostas Papadimitriou
                data['OS'] = data.metadata.values.OS || "okeanos";
1842 8d08f18a Kostas Papadimitriou
            }
1843 8d08f18a Kostas Papadimitriou
            
1844 8d08f18a Kostas Papadimitriou
            data['firewalls'] = {};
1845 8d08f18a Kostas Papadimitriou
            if (data['addresses'] && data['addresses'].values) {
1846 8d08f18a Kostas Papadimitriou
                data['linked_to_nets'] = data['addresses'].values;
1847 8d08f18a Kostas Papadimitriou
                _.each(data['addresses'].values, function(f){
1848 8d08f18a Kostas Papadimitriou
                    if (f['firewallProfile']) {
1849 8d08f18a Kostas Papadimitriou
                        data['firewalls'][f['id']] = f['firewallProfile']
1850 8d08f18a Kostas Papadimitriou
                    }
1851 8d08f18a Kostas Papadimitriou
                });
1852 8d08f18a Kostas Papadimitriou
            }
1853 8d08f18a Kostas Papadimitriou
            
1854 8d08f18a Kostas Papadimitriou
            // if vm has no metadata, no metadata object
1855 8d08f18a Kostas Papadimitriou
            // is in json response, reset it to force
1856 8d08f18a Kostas Papadimitriou
            // value update
1857 8d08f18a Kostas Papadimitriou
            if (!data['metadata']) {
1858 8d08f18a Kostas Papadimitriou
                data['metadata'] = {values:{}};
1859 8d08f18a Kostas Papadimitriou
            }
1860 8d08f18a Kostas Papadimitriou
1861 8d08f18a Kostas Papadimitriou
            return data;
1862 8d08f18a Kostas Papadimitriou
        },
1863 8d08f18a Kostas Papadimitriou
1864 8d08f18a Kostas Papadimitriou
        create: function (name, image, flavor, meta, extra, callback) {
1865 8d08f18a Kostas Papadimitriou
            if (this.copy_image_meta) {
1866 d5ba5588 Kostas Papadimitriou
                if (image.get("OS")) {
1867 d5ba5588 Kostas Papadimitriou
                    meta['OS'] = image.get("OS");
1868 d5ba5588 Kostas Papadimitriou
                }
1869 8d08f18a Kostas Papadimitriou
           }
1870 8d08f18a Kostas Papadimitriou
            
1871 8d08f18a Kostas Papadimitriou
            opts = {name: name, imageRef: image.id, flavorRef: flavor.id, metadata:meta}
1872 8d08f18a Kostas Papadimitriou
            opts = _.extend(opts, extra);
1873 8d08f18a Kostas Papadimitriou
1874 ce93b80c Kostas Papadimitriou
            this.api_call(this.path, "create", {'server': opts}, undefined, undefined, callback, {critical: true});
1875 8d08f18a Kostas Papadimitriou
        }
1876 8d08f18a Kostas Papadimitriou
1877 8d08f18a Kostas Papadimitriou
    })
1878 c4fff449 Kostas Papadimitriou
1879 c4fff449 Kostas Papadimitriou
    models.PublicKey = models.Model.extend({
1880 859a4609 Kostas Papadimitriou
        path: 'keys',
1881 859a4609 Kostas Papadimitriou
        base_url: '/ui/userdata',
1882 859a4609 Kostas Papadimitriou
        details: false,
1883 859a4609 Kostas Papadimitriou
        noUpdate: true,
1884 859a4609 Kostas Papadimitriou
1885 859a4609 Kostas Papadimitriou
1886 859a4609 Kostas Papadimitriou
        get_public_key: function() {
1887 859a4609 Kostas Papadimitriou
            return cryptico.publicKeyFromString(this.get("content"));
1888 859a4609 Kostas Papadimitriou
        },
1889 859a4609 Kostas Papadimitriou
1890 859a4609 Kostas Papadimitriou
        get_filename: function() {
1891 859a4609 Kostas Papadimitriou
            return "{0}.pub".format(this.get("name"));
1892 859a4609 Kostas Papadimitriou
        },
1893 859a4609 Kostas Papadimitriou
1894 859a4609 Kostas Papadimitriou
        identify_type: function() {
1895 859a4609 Kostas Papadimitriou
            try {
1896 859a4609 Kostas Papadimitriou
                var cont = snf.util.validatePublicKey(this.get("content"));
1897 859a4609 Kostas Papadimitriou
                var type = cont.split(" ")[0];
1898 859a4609 Kostas Papadimitriou
                return synnefo.util.publicKeyTypesMap[type];
1899 859a4609 Kostas Papadimitriou
            } catch (err) { return false };
1900 859a4609 Kostas Papadimitriou
        }
1901 859a4609 Kostas Papadimitriou
1902 c4fff449 Kostas Papadimitriou
    })
1903 c4fff449 Kostas Papadimitriou
    
1904 c4fff449 Kostas Papadimitriou
    models.PublicKeys = models.Collection.extend({
1905 859a4609 Kostas Papadimitriou
        model: models.PublicKey,
1906 859a4609 Kostas Papadimitriou
        details: false,
1907 859a4609 Kostas Papadimitriou
        path: 'keys',
1908 859a4609 Kostas Papadimitriou
        base_url: '/ui/userdata',
1909 859a4609 Kostas Papadimitriou
        noUpdate: true,
1910 859a4609 Kostas Papadimitriou
1911 556dcd88 Kostas Papadimitriou
        generate_new: function(success, error) {
1912 386481eb Kostas Papadimitriou
            snf.api.sync('create', undefined, {
1913 556dcd88 Kostas Papadimitriou
                url: getUrl.call(this, this.base_url) + "/generate", 
1914 556dcd88 Kostas Papadimitriou
                success: success, 
1915 556dcd88 Kostas Papadimitriou
                error: error,
1916 556dcd88 Kostas Papadimitriou
                skip_api_error: true
1917 556dcd88 Kostas Papadimitriou
            });
1918 859a4609 Kostas Papadimitriou
        },
1919 859a4609 Kostas Papadimitriou
1920 859a4609 Kostas Papadimitriou
        add_crypto_key: function(key, success, error, options) {
1921 859a4609 Kostas Papadimitriou
            var options = options || {};
1922 859a4609 Kostas Papadimitriou
            var m = new models.PublicKey();
1923 556dcd88 Kostas Papadimitriou
1924 556dcd88 Kostas Papadimitriou
            // guess a name
1925 859a4609 Kostas Papadimitriou
            var name_tpl = "public key";
1926 859a4609 Kostas Papadimitriou
            var name = name_tpl;
1927 859a4609 Kostas Papadimitriou
            var name_count = 1;
1928 859a4609 Kostas Papadimitriou
            
1929 859a4609 Kostas Papadimitriou
            while(this.filter(function(m){ return m.get("name") == name }).length > 0) {
1930 859a4609 Kostas Papadimitriou
                name = name_tpl + " " + name_count;
1931 859a4609 Kostas Papadimitriou
                name_count++;
1932 859a4609 Kostas Papadimitriou
            }
1933 556dcd88 Kostas Papadimitriou
            
1934 859a4609 Kostas Papadimitriou
            m.set({name: name});
1935 556dcd88 Kostas Papadimitriou
            m.set({content: key});
1936 859a4609 Kostas Papadimitriou
            
1937 859a4609 Kostas Papadimitriou
            options.success = function () { return success(m) };
1938 859a4609 Kostas Papadimitriou
            options.errror = error;
1939 c72a830d Kostas Papadimitriou
            options.skip_api_error = true;
1940 859a4609 Kostas Papadimitriou
            
1941 859a4609 Kostas Papadimitriou
            this.create(m.attributes, options);
1942 859a4609 Kostas Papadimitriou
        }
1943 c4fff449 Kostas Papadimitriou
    })
1944 8d08f18a Kostas Papadimitriou
    
1945 8d08f18a Kostas Papadimitriou
    // storage initialization
1946 8d08f18a Kostas Papadimitriou
    snf.storage.images = new models.Images();
1947 8d08f18a Kostas Papadimitriou
    snf.storage.flavors = new models.Flavors();
1948 8d08f18a Kostas Papadimitriou
    snf.storage.networks = new models.Networks();
1949 8d08f18a Kostas Papadimitriou
    snf.storage.vms = new models.VMS();
1950 c4fff449 Kostas Papadimitriou
    snf.storage.keys = new models.PublicKeys();
1951 8d08f18a Kostas Papadimitriou
1952 8d08f18a Kostas Papadimitriou
    //snf.storage.vms.fetch({update:true});
1953 8d08f18a Kostas Papadimitriou
    //snf.storage.images.fetch({update:true});
1954 8d08f18a Kostas Papadimitriou
    //snf.storage.flavors.fetch({update:true});
1955 8d08f18a Kostas Papadimitriou
1956 8d08f18a Kostas Papadimitriou
})(this);