Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / static / snf / js / models.js @ 6a0915f7

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