Statistics
| Branch: | Tag: | Revision:

root / ui / static / snf / js / ui / web / ui_icon_view.js @ 9ce969a7

History | View | Annotate | Download (26.7 kB)

1
;(function(root){
2

    
3
    // root
4
    var root = root;
5
    
6
    // setup namepsaces
7
    var snf = root.synnefo = root.synnefo || {};
8
    var models = snf.models = snf.models || {}
9
    var storage = snf.storage = snf.storage || {};
10
    var ui = snf.ui = snf.ui || {};
11
    var util = snf.util = snf.util || {};
12

    
13
    var views = snf.views = snf.views || {}
14

    
15
    // shortcuts
16
    var bb = root.Backbone;
17
    
18
    // handle extended info toggler
19
    views.VMActionErrorView = views.View.extend({
20
    
21
        initialize: function (vm, view) {
22
            this.vm = vm;
23
            this.view = view;
24
            this.vm_view = this.view.vm(vm);
25

    
26
            this.has_error = false;
27
            
28
            this.error = this.vm_view.find(".action-error");
29
            this.close = this.vm_view.find(".close-action-error");
30
            this.show_btn = this.vm_view.find(".show-action-error");
31

    
32
            this.init_handlers();
33
            this.update_layout();
34
        },
35

    
36
        init_handlers: function() {
37
            // action call failed notify the user
38
            this.vm.bind("action:fail", _.bind(function(args){
39
                if (this.vm.action_error) {
40
                    this.has_error = true;
41
                    var action = "undefined";
42
                    try {
43
                        action = _.last(args).error_params.extra_details['Action'];
44
                    } catch (err) {console.log(err)};
45
                    
46
                    this.error.find(".action").text(action);
47
                    this.error.show();
48
                }
49
            }, this));
50
            
51
            // show error overlay
52
            this.show_btn.click(_.bind(function() {
53
                if (this.vm.action_error) {
54
                    this.show_error_overlay(this.vm.action_error);
55
                }
56
                this.vm.reset_action_error();
57
            }, this));
58
            
59
            // user requests to forget about the error
60
            this.close.click(_.bind(_.bind(function() {
61
                this.error.hide();
62
                this.vm.reset_action_error();
63
            }, this)));
64
            
65
            // hide error message if action fail get reset
66
            this.vm.bind("action:fail:reset", _.bind(function(){
67
                this.error.hide();
68
            }, this));
69
        },
70

    
71
        show_error_overlay: function(args) {
72
            var args = util.parse_api_error.apply(util, args);
73
            
74
            // force logout if UNAUTHORIZED request arrives
75
            if (args.code == 401) { snf.ui.logout(); return };
76
            
77
            var error_entry = [args.ns, args.code, args.message, args.type, args.details, args];
78
            ui.main.error_view.show_error.apply(ui.main.error_view, error_entry);
79
        },
80

    
81
        update_layout: function() {
82
            if (this.vm.action_error) {
83
                this.error.show();
84
            }
85
        }
86
    });
87

    
88
    // handle extended info toggler
89
    views.IconInfoView = views.View.extend({
90
    
91
        initialize: function (vm, view) {
92
            this.vm = vm;
93
            this.view = view;
94
            this.vm_view = this.view.vm(vm);
95
            
96
            this.info_link = $(".toggler", this.vm_view);
97
            this.el = $("div.info-content", this.vm_view);
98
            this.toggler = $(".toggler", this.vm_view);
99
            this.label = $(".label", this.vm_view);
100

    
101
            this.set_handlers();
102
        },
103

    
104
        set_handlers: function() {
105
            this.info_link.click(_.bind(function(){
106
                this.el.slideToggle();
107
                this.view.vm(this.vm).toggleClass("light-background");
108

    
109
                if (this.toggler.hasClass("open")) {
110
                    this.toggler.removeClass("open");
111
                    this.vm.do_update_stats = false;
112
                } else {
113
                    this.toggler.addClass("open");
114
                    this.vm.do_update_stats = true;
115
                }
116
                
117
                var self = this;
118
                window.setTimeout(function() {$(self.view).trigger("resize")}, 300);
119
            }, this));
120

    
121
            this.$(".stats-report").click(_.bind(function(){
122
                snf.ui.main.show_vm_details(this.vm);
123
            }, this))
124
        }
125
    
126
    })
127

    
128
    // rename handler view
129
    // only icon view contains rename capability
130
    views.IconRenameView = views.View.extend({
131
        
132
        initialize: function(vm, view) {
133
            this.vm = vm;
134
            this.view = view;
135
            // name container
136
            this.el = $('div#' + this.view.id_tpl + vm.id + " div.name").get(0);
137
            // name inline element
138
            this.name = this.$('span.name');
139
            // rename button
140
            this.rename = this.$('span.rename');
141
            // save button
142
            this.save = this.$('.save');
143
            // cancel rename button
144
            this.cancel = this.$('.cancel');
145
            // where to place the input field
146
            this.edit_cont = this.$(".namecontainer");
147
            // buttons container
148
            this.buttons = this.$(".editbuttons");
149
            // current state
150
            this.renaming = false;
151
            // init event handlers
152
            this.set_handlers();
153
            // paint
154
            this.update_layout();
155
            views.IconRenameView.__super__.initialize.call(this);
156
        },
157
        
158
        // update elements visibility/state
159
        update_layout: function() {
160
            // if in renaming state
161
            if (this.renaming) {
162
                // if name is hidden we are already in renaming state
163
                // dont do nothing
164
                if (this.name.is(":hidden")){return}
165
                
166
                // hide name element to make space for the 
167
                // text input
168
                this.name.hide();
169
                this.rename.hide();
170
                // show confirm/cancel buttons
171
                this.buttons.show();
172
                // create text element
173
                this.create_input();
174
            } else {
175
                // name is visible not in edit mode
176
                if (this.name.is(":visible")){return}
177

    
178
                this.name.show();
179
                this.rename.show();
180
                this.buttons.hide();
181
                this.remove_input();
182
            }
183
        },
184
        
185
        // create rename input field and set appropriate 
186
        // event handlers
187
        create_input: function() {
188
            var self = this;
189
            this.edit_cont.append('<input class="vm-rename nametextbox" type="text" />');
190
            this.$('input').val(this.vm.get('name'));
191
            // give edit focus
192
            this.$('input').focus();
193
            // handle enter press
194
            this.$('input').keypress(function(ev){
195
                if (ev.charCode == 13) {
196
                    self.submit();
197
                }
198
            })
199
        },
200
        
201
        // remove input element
202
        remove_input: function() {
203
            this.$('input').remove();
204
        },
205
        
206
        // initialize event handlers
207
        set_handlers: function() {
208
            var self = this;
209
            // start rename when rename button is pressed
210
            this.rename.click(function() {
211
                self.renaming = true;
212
                self.update_layout();
213
            });
214
            
215
            // double click on name
216
            $(this.el).dblclick(function() {
217
                self.renaming = true;
218
                self.update_layout();
219
            });
220

    
221
            // cancel rename
222
            this.cancel.click(function() {
223
                self.renaming = false;
224
                self.update_layout();
225
            })
226
            
227
            // apply the rename
228
            // TODO: check if name is equal than the previous value
229
            this.save.click(function() {
230
                self.submit();
231
            })
232
        },
233

    
234
        submit: function() {
235
            var value = _(self.$('input').val()).trim();
236
            if (value == "") { return };
237
            this.renaming = false;
238
            this.vm.rename(self.$('input').val());
239
            this.update_layout();
240
        }
241
    });
242
    
243
    // VM connect interaction view
244
    views.IconVMConnectView = views.View.extend({
245
        
246
        initialize: function(vm, view) {
247
            // parent view (single, icon, list)
248
            this.parent = view;
249
            this.vm = vm;
250
            this.el = view.vm(vm);
251
            this.set_handlers();
252
            views.IconVMConnectView.__super__.initialize.call(this);
253
        },
254
        
255
        // set the appropriate handlers
256
        set_handlers: function() {
257
            // setup connect handler on vm icon interaction
258
            var el = this.el;
259
            var vm = this.vm;
260

    
261
            // element that triggers the connect handler
262
            var connect = el.find("div.connect-arrow, .logo");
263
            // connect status handler
264
            var handler = _.bind(this.connect_handler, {vm:vm, el:el, view:this.parent});
265
            $(connect).bind({'mouseover': handler, 'mouseleave': handler, 
266
                            'mousedown': handler, 'mouseup': handler,
267
                            'click': handler });
268
            
269
            // setup connect arrow display handlers 
270
            // while hovering vm container
271
            el.bind("mouseover", function(){
272
                if (vm.is_connectable()) {
273
                    el.find(".connect-border").show();
274
                    el.find(".connect-arrow").show();
275
                    el.find(".logo").css({cursor:"pointer"});
276
                } else {
277
                    el.find(".connect-border").hide();
278
                    el.find(".connect-arrow").hide();
279
                    el.find(".logo").css({cursor: "default"});
280
                }
281
            }).bind("mouseleave", function(){
282
                el.find(".connect-border").hide();
283
                el.find(".connect-arrow").hide();
284
            });
285
        },
286
        
287
        // connect arrow interaction handlers
288
        // BEWARE, this function has different context
289
        // than the View object itself, see set_vm_handlers
290
        connect_handler: function(event) {
291
            // nothing to do if we cannot connect to the vm
292
            if (!this.vm.is_connectable()) {return}
293
            
294
            var logo = this.el.find(".logo");
295
            var arrow = this.el.find(".connect-arrow");
296
            var border = this.el.find(".connect-border");
297
            
298
            // clear icon states
299
            logo.removeClass('single-image-state1 single-image-state2 single-image-state3 single-image-state4');
300
            
301
            // append the appropriate state class
302
            switch (event.type) {
303
                case "mouseover":       
304
                    logo.addClass('single-image-state4');
305
                    arrow.addClass('border-hover');
306
                    break;
307
                
308
                case "mouseleave":
309
                    logo.addClass('single-image-state1');
310
                    arrow.removeClass('border-hover');
311
                    break;
312

    
313
                case "mouseup":
314
                    logo.addClass('single-image-state4');
315
                    this.view.connect_overlay.show(this.vm);
316
                    break;
317

    
318
                case "mousedown":
319
                    logo.addClass('single-image-state2');
320
                    break;
321

    
322
                case "click":
323
                    //logo.addCLass('single-image-state4');
324
                    //this.view.connect_to_console(vm);
325
                    this.view.connect_overlay.show(this.vm);
326
                    break;
327

    
328
                default:
329
                    ;
330
            }
331
        },
332
        
333
        update_layout: function() {
334
        }
335

    
336
    });
337
    
338
    // vm metadata subview for icon and single view
339
    views.VMTagsView = views.View.extend({
340
        view_id: 'vm_tags',
341
        // metadata container selector
342
        el_sel: '.vm-metadata',
343
        // metadata row template
344
        tag_tpl: '<span class="tag-item"><span class="key">{0}</span><span class="value">{1}</span></span>',
345
        // how many tags to show
346
        tag_limit: 4,
347
        // truncate options (because container has different size on icon/single views)
348
        tag_key_truncate: 7,
349
        tag_value_truncate: 15,
350

    
351
        initialize: function(vm, view, toggle, limit, tag_key_truncate, tag_value_truncate) {
352
            this.tag_limit = limit || this.tag_limit;
353

    
354
            this.tag_key_truncate = tag_key_truncate || this.tag_key_truncate;
355
            this.tag_value_truncate = tag_value_truncate || this.tag_value_truncate;
356

    
357
            // does the view toggles the metadata container (single view)
358
            this.toggle = toggle || false;
359
            // parent view
360
            this.parent = view;
361
            this.vm = vm;
362
            this.el = this.parent.vm(vm);
363
            this.view_id = this.view_id + "_" + vm.id;
364

    
365
            // link to raise the metadata manager overlay
366
            this.link = this.$('a.manage-metadata');
367

    
368
            views.VMTagsView.__super__.initialize.call(this);
369
            this.set_handlers();
370
            this.update_layout();
371
        },
372
        
373
        // set the appropriate handlers
374
        set_handlers: function() {
375
            var self = this;
376
            // show the metadata editor overlay
377
            this.link.click(_.bind(function(ev) {
378
                ev.preventDefault();
379
                this.parent.metadata_view.show(this.vm);
380
            }, this));
381

    
382
            // tags have show/hide control ? bind events for them
383
            var self = this;
384
            if (this.toggle) {
385
                $(this.el).find(".tags-header").click(_.bind(function(){
386
                    $(self.el).find(".tags-content").slideToggle(600);
387
                    var toggler = $(this.el).find(".tags-header .cont-toggler");
388
                    
389
                    if (toggler.hasClass("open")) {
390
                        toggler.removeClass("open");
391
                    } else {
392
                        toggler.addClass("open");
393
                    }
394
                }, this));
395
                $(self.el).find(".tags-content").hide();
396
            }
397
        },
398
        
399
        // update metadata container and data
400
        update_layout: function() {
401

    
402
            // api metadata object
403
            var meta =  this.vm.get_meta();
404

    
405
            var i = 0;
406
            var cont = $(this.el).find(".items");
407

    
408
            // clear existing items
409
            cont.find(".tag-item").remove();
410
            
411
            // create tag elements
412
            _.each(meta, function(value, key){
413
                // respect the limit
414
                if (i > this.tag_limit) {
415
                    return;
416
                }
417
                
418
                // create element
419
                var new_el = $(this.tag_tpl.format(util.truncate(key, this.tag_key_truncate), 
420
                                                 util.truncate(": " + value, this.tag_value_truncate)));
421

    
422
                // add title attributes, improve accesibility
423
                // truncated values
424
                new_el.find("span.key").attr("title", key);
425
                new_el.find("span.value").attr("title", value);
426

    
427
                cont.append(new_el);
428
            }, this);
429
        }
430
    });
431
    
432

    
433
    // stats subview for single/icon views
434
    views.VMStatsView = views.View.extend({
435

    
436
        initialize: function(vm, view, options) {
437
            if (!options) {options = {}};
438
            this.vm = vm;
439
            this.parent = view;
440
            this.sel = options.el || this.el_sel || ".lower";
441
            this.el = this.parent.vm(vm).find(this.sel);
442
            
443
            // elements shortcuts
444
            this.cpu_loading = this.el.find(".cpu-graph .stat-busy");
445
            this.cpu_error = this.el.find(".cpu-graph .stat-error");
446
            this.cpu_img = this.el.find(".cpu-graph .stat-img");
447
            this.net_loading = this.el.find(".network-graph .stat-busy");
448
            this.net_error = this.el.find(".network-graph .stat-error");
449
            this.net_img = this.el.find(".network-graph .stat-img");
450

    
451
            this.loading = this.el.find(".stat-busy");
452
            this.error = this.el.find(".stat-error");
453
            this.img = this.el.find(".stat-img");
454
            
455
            // initial state paremeters
456
            this.stats = this.vm.get("stats");
457

    
458
            // timeseries or bar images ?
459
            this.stats_type = options.stats_type || "bar";
460

    
461
            views.VMStatsView.__super__.initialize.apply(this, arguments);
462
            this.set_handlers();
463
            this.update_layout();
464

    
465
            this.net_loading.show();
466
            this.net_error.hide();
467
            this.cpu_loading.show();
468
            this.cpu_error.hide();
469

    
470
            this.net_img.hide();
471
            this.cpu_img.hide();
472
        },
473

    
474
        
475
        set_handlers: function() {
476
            // update view state when vm stats update gets triggered
477
            this.vm.bind("stats:update", _.bind(function(){
478
                // update the layout
479
                this.update_layout();
480
            }, this));
481
        },
482
        
483
        get_images: function (type) {
484
            if (type == "bar") {
485
                return {'cpu': this.stats.cpuBar, 'net': this.stats.netBar };
486
            } else {
487
                return {'cpu': this.stats.cpuTimeSeries, 'net': this.stats.netTimeSeries };
488
            }
489
        },
490

    
491
        update_layout: function() {
492
            if (!this.vm.stats_available) {
493
                this.loading.show();
494
                this.img.hide();
495
                this.error.hide();
496
            } else {
497
                this.loading.hide();
498
                this.stats = this.vm.get("stats");
499
                var images = this.get_images(this.stats_type);
500

    
501
                if (images.cpu) {
502
                    this.cpu_img.attr({src:images.cpu}).show();
503
                    this.cpu_error.hide();
504
                } else {
505
                    this.cpu_img.hide();
506
                    this.cpu_error.show();
507
                }
508

    
509
                if (images.net) {
510
                    this.net_img.attr({src:images.net}).show();
511
                    this.net_error.hide();
512
                } else {
513
                    this.net_img.hide();
514
                    this.net_error.show();
515
                }
516
            }
517
            $(window).trigger("resize");
518
        }
519
    });
520

    
521
    views.VMDetailsView = views.View.extend({
522
        view_id: "vm_details",
523
        el_sel: '.vm-details',
524
        
525

    
526
        selectors: {
527
            'cpu': '.cpu-data',
528
            'ram': '.ram-data',
529
            'disk': '.disk-data',
530
            'image_name': '.image-data',
531
            'image_size': '.image-size-data'
532
        },
533

    
534
        initialize: function(vm, view) {
535
            this.parent = view;
536
            this.vm = vm;
537
            this.el = $(this.parent.vm(vm)).find(this.el_sel).get(0);
538
            this.view_id = "vm_{0}_details".format(vm.id);
539

    
540
            views.VMDetailsView.__super__.initialize.call(this);
541
            this.update_layout();
542
        },
543

    
544
        update_layout: function() {
545
            var image = this.vm.get_image();
546
            var flavor = this.vm.get_flavor();
547
            if (!flavor || !image) {
548
                return;
549
            }
550

    
551
            this.sel('image_name').text(util.truncate(image.get('name'), 13)).attr("title", image.get('name'));
552
            this.sel('image_size').text(image.get('metadata').values.size).attr('title', image.get('metadata').values.size);
553

    
554
            this.sel('cpu').text(flavor.get('cpu'));
555
            this.sel('ram').text(flavor.get('ram'));
556
            this.sel('disk').text(flavor.get('disk'));
557
        }
558
    });
559
    
560
    // VMs icon view
561
    views.IconView = views.VMListView.extend({
562
        
563
        // view id (this could be used to identify 
564
        // the view object from global context
565
        view_id: 'vm_icon',
566

    
567
        el: '#machinesview-icon',
568
        id_tpl: 'icon-vm-',
569

    
570
        selectors: {
571
            'vms': '.machine-container',
572
            'vm': '#icon-vm-{0}',
573
            'view': '#machinesview-icon',
574
            'tpl': '#machinesview-icon.standard #machine-container-template',
575
            'spinner': '.large-spinner',
576
            'vm_spinner': '.machine-container#icon-vm-{0} .state .spinner',
577
            'vm_wave': '.machine-container#icon-vm-{0} .wave',
578
            'vm_cont_active': '#machinesview-icon.standard .running',
579
            'vm_cont_terminated': '#machinesview-icon.standard .terminated'
580
        },
581
            
582
        reset: function() {},
583
        // overload show function
584
        show_view: function() {
585
            $(this.el).show();
586
            this.__update_layout();
587
        },
588

    
589
        post_update_vm: function(vm) {
590
        },
591

    
592
        // identify vm model instance id based on DOM element
593
        vm_id_for_element: function(el) {
594
            return el.attr('id').replace("icon-vm-","");
595
        },
596
        
597
        // set generic view handlers
598
        set_handlers: function() {
599
        },  
600
        
601
        // stuff to do when a new vm has been created.
602
        // - create vm subviews
603
        post_add: function(vm) {
604
            // rename views index
605
            this.rename_views = this.rename_views || {};
606
            this.stats_views = this.stats_views || {};
607
            this.connect_views = this.connect_views || {};
608
            this.tags_views = this.tags_views || {};
609
            this.details_views = this.details_views || {};
610
            this.info_views = this.info_views || {};
611
            this.action_error_views = this.action_error_views || {};
612
            this.action_views = this.action_views || {};
613

    
614
            this.action_views[vm.id] = new views.VMActionsView(vm, this, this.vm(vm), this.hide_actions);
615
            this.rename_views[vm.id] = new views.IconRenameView(vm, this);
616
            this.stats_views[vm.id] = new views.VMStatsView(vm, this, {el:'.vm-stats'});
617
            this.connect_views[vm.id] = new views.IconVMConnectView(vm, this);
618
            this.tags_views[vm.id] = new views.VMTagsView(vm, this);
619
            this.details_views[vm.id] = new views.VMDetailsView(vm, this);
620
            this.info_views[vm.id] = new views.IconInfoView(vm, this);
621
            this.action_error_views[vm.id] = new views.VMActionErrorView(vm, this);
622
        },
623
        
624
        // vm specific event handlers
625
        set_vm_handlers: function(vm) {
626
            var el = this.vm(vm);
627

    
628
        },
629

    
630
        check_terminated_is_empty: function() {
631
            // hide/show terminated container
632
            if (this.$(".terminated .machine-container").length == 0) {
633
                this.$(".terminated").hide()
634
            } else {
635
                this.$(".terminated").show()
636
            }
637

    
638
            $(window).trigger("resize");
639
        },
640
        
641
        // generic stuff to do on each view update
642
        // called once after each vm has been updated
643
        update_layout: function() {
644
            // TODO: why do we do this ??
645
            if (storage.vms.models.length > 0) {
646
                this.$(".running").removeClass("disabled");
647
            } else {
648
                this.$(".running").addClass("disabled");
649
            }
650
            
651
            this.check_terminated_is_empty();
652
    
653
            // FIXME: code from old js api
654
            this.$("div.separator").show();
655
            this.$("div.machine-container:last-child").find("div.separator").hide();
656
            fix_v6_addresses();
657
        },
658

    
659
        // update vm details
660
        update_details: function(vm) {
661
            var el = this.vm(vm);
662
            // truncate name
663
            el.find("span.name").text(util.truncate(vm.get("name"), 40));
664
            // set ips
665
            el.find(".ipv4-text").text(vm.get_addresses().ip4 || "undefined");
666
            // TODO: fix ipv6 truncates and tooltip handler
667
            el.find(".ipv6-text").text(vm.get_addresses().ip6 || "undefined");
668
            // set the state (i18n ??)
669
            el.find(".status").text(STATE_TEXTS[vm.state()]);
670
            // set state class
671
            el.find(".state").removeClass().addClass(views.IconView.STATE_CLASSES[vm.state()].join(" "));
672
            // os icon
673
            el.find(".logo").css({'background-image': "url(" + this.get_vm_icon_path(vm, "medium") + ")"});
674
            
675
            el.removeClass("connectable");
676
            if (vm.is_connectable()) {
677
                el.addClass("connectable");
678
            }
679
            
680
            if (vm.get('status') == 'BUILD') {
681
                // update bulding progress
682
                el.find(".machine-ips").hide();
683
                el.find(".build-progress").show().text(vm.get('progress_message'));
684
            } else {
685
                // hide building progress
686
                el.find(".machine-ips").show()
687
                el.find(".build-progress").hide();
688
            }
689

    
690
            if (vm.state() == "DESTROY") {
691
                el.find(".machine-ips").hide();
692
                el.find(".build-progress").show().text("Terminating...");
693
            }
694

    
695
            icon_state = vm.is_active() ? "on" : "off";
696
            set_machine_os_image(el, "icon", icon_state, this.get_vm_icon_os(vm));
697
            
698
            // update subviews
699
            this.rename_views[vm.id].update_layout();
700
            this.stats_views[vm.id].update_layout();
701
            this.connect_views[vm.id].update_layout();
702
            this.tags_views[vm.id].update_layout();
703
            this.details_views[vm.id].update_layout();
704
        },
705

    
706
        post_remove_vm: function(vm) {
707
            this.check_terminated_is_empty();
708
            $(window).trigger("resize");
709
        },
710
            
711
        get_vm_icon_os: function(vm) {
712
            var os = vm.get_os();
713
            var icons = window.os_icons || views.IconView.VM_OS_ICONS;
714

    
715
            if (icons.indexOf(os) == -1) {
716
                os = "unknown";
717
            }
718

    
719
            return os;
720
        },
721

    
722
        // TODO: move to views.utils (the method and the VM_OS_ICON vars)
723
        get_vm_icon_path: function(vm, icon_type) {
724
            var os = vm.get_os();
725
            var icons = window.os_icons || views.IconView.VM_OS_ICONS;
726

    
727
            if (icons.indexOf(os) == -1) {
728
                os = "unknown";
729
            }
730

    
731
            return views.IconView.VM_OS_ICON_TPLS[icon_type].format(os);
732
        }
733
    })
734

    
735
    views.IconView.VM_OS_ICON_TPLS = {
736
        "medium": "/static/icons/machines/medium/{0}-sprite.png"
737
    }
738

    
739
    views.IconView.VM_OS_ICONS = window.os_icons || [];
740

    
741
    views.IconView.STATE_CLASSES = {
742
        'UNKNOWN':          ['state', 'error-state'],
743
        'BUILD':            ['state', 'build-state'],
744
        'REBOOT':           ['state', 'rebooting-state'],
745
        'STOPPED':          ['state', 'terminated-state'],
746
        'ACTIVE':           ['state', 'running-state'],
747
        'ERROR':            ['state', 'error-state'],
748
        'DELETED':           ['state', 'destroying-state'],
749
        'DESTROY':          ['state', 'destroying-state'],
750
        'BUILD_INIT':       ['state', 'build-state'], 
751
        'BUILD_COPY':       ['state', 'build-state'],
752
        'BUILD_FINAL':      ['state', 'build-state'],
753
        'SHUTDOWN':         ['state', 'shutting-state'],
754
        'START':            ['state', 'starting-state'],
755
        'CONNECT':          ['state', 'connecting-state'],
756
        'DISCONNECT':       ['state', 'disconnecting-state']
757
    };
758

    
759
})(this);