Statistics
| Branch: | Tag: | Revision:

root / ui / static / snf / js / ui / web / ui_icon_view.js @ 96d725ac

History | View | Annotate | Download (26.5 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
                    action = args[0].ajax.error_params.extra_details['Action'];
42
                    this.error.find(".action").text(action);
43
                    this.error.show();
44
                }
45
            }, this));
46
            
47
            // show error overlay
48
            this.show_btn.click(_.bind(function() {
49
                this.show_error_overlay(this.vm.action_error);
50
                this.vm.reset_action_error();
51
            }, this));
52
            
53
            // user requests to forget about the error
54
            this.close.click(_.bind(_.bind(function() {
55
                this.error.hide();
56
                this.vm.reset_action_error();
57
            }, this)));
58
            
59
            // hide error message if action fail get reset
60
            this.vm.bind("action:fail:reset", _.bind(function(){
61
                this.error.hide();
62
            }, this));
63
        },
64

    
65
        show_error_overlay: function(arguments) {
66
            var xhr = arguments[0];
67
            var args = util.parse_api_error(arguments);
68
            
69
            // force logout if UNAUTHORIZED request arrives
70
            if (args.code == 401) { snf.ui.logout(); return };
71

    
72
            var error_entry = [args.ns, args.code, args.message, args.type, args.details, args];
73
            ui.main.error_view.show_error.apply(ui.main.error_view, error_entry);
74
        },
75

    
76
        update_layout: function() {
77
            if (this.vm.action_error) {
78
                this.error.show();
79
            }
80
        }
81
    });
82

    
83
    // handle extended info toggler
84
    views.IconInfoView = views.View.extend({
85
    
86
        initialize: function (vm, view) {
87
            this.vm = vm;
88
            this.view = view;
89
            this.vm_view = this.view.vm(vm);
90
            
91
            this.info_link = $(".toggler", this.vm_view);
92
            this.el = $("div.info-content", this.vm_view);
93
            this.toggler = $(".toggler", this.vm_view);
94
            this.label = $(".label", this.vm_view);
95

    
96
            this.set_handlers();
97
        },
98

    
99
        set_handlers: function() {
100
            this.info_link.click(_.bind(function(){
101
                this.el.slideToggle();
102
                this.view.vm(this.vm).toggleClass("light-background");
103

    
104
                if (this.toggler.hasClass("open")) {
105
                    this.toggler.removeClass("open");
106
                    this.vm.do_update_stats = false;
107
                } else {
108
                    this.toggler.addClass("open");
109
                    this.vm.do_update_stats = true;
110
                }
111
                
112
                var self = this;
113
                window.setTimeout(function() {$(self.view).trigger("resize")}, 300);
114
            }, this));
115

    
116
            this.$(".stats-report").click(_.bind(function(){
117
                snf.ui.main.show_vm_details(this.vm);
118
            }, this))
119
        }
120
    
121
    })
122

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

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

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

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

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

    
308
                case "mouseup":
309
                    logo.addClass('single-image-state4');
310
                    machine_connect([machine_connect, this.vm.id]);
311
                    break;
312

    
313
                case "mousedown":
314
                    logo.addClass('single-image-state2');
315
                    break;
316

    
317
                case "click":
318
                    //logo.addCLass('single-image-state4');
319
                    //this.view.connect_to_console(vm);
320
                    this.view.connect_overlay.show(this.vm);
321
                    break;
322

    
323
                default:
324
                    ;
325
            }
326
        },
327
        
328
        update_layout: function() {
329
        }
330

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

    
346
        initialize: function(vm, view, toggle, limit, tag_key_truncate, tag_value_truncate) {
347
            this.tag_limit = limit || this.tag_limit;
348

    
349
            this.tag_key_truncate = tag_key_truncate || this.tag_key_truncate;
350
            this.tag_value_truncate = tag_value_truncate || this.tag_value_truncate;
351

    
352
            // does the view toggles the metadata container (single view)
353
            this.toggle = toggle || false;
354
            // parent view
355
            this.parent = view;
356
            this.vm = vm;
357
            this.el = this.parent.vm(vm);
358
            this.view_id = this.view_id + "_" + vm.id;
359

    
360
            // link to raise the metadata manager overlay
361
            this.link = this.$('a.manage-metadata');
362

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

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

    
397
            // api metadata object
398
            var meta =  this.vm.get_meta();
399

    
400
            var i = 0;
401
            var cont = $(this.el).find(".items");
402

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

    
417
                // add title attributes, improve accesibility
418
                // truncated values
419
                new_el.find("span.key").attr("title", key);
420
                new_el.find("span.value").attr("title", value);
421

    
422
                cont.append(new_el);
423
            }, this);
424
        }
425
    });
426
    
427

    
428
    // stats subview for single/icon views
429
    views.VMStatsView = views.View.extend({
430

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

    
446
            this.loading = this.el.find(".stat-busy");
447
            this.error = this.el.find(".stat-error");
448
            this.img = this.el.find(".stat-img");
449
            
450
            // initial state paremeters
451
            this.stats = this.vm.get("stats");
452

    
453
            // timeseries or bar images ?
454
            this.stats_type = options.stats_type || "bar";
455

    
456
            views.VMStatsView.__super__.initialize.apply(this, arguments);
457
            this.set_handlers();
458
            this.update_layout();
459

    
460
            this.net_loading.show();
461
            this.net_error.hide();
462
            this.cpu_loading.show();
463
            this.cpu_error.hide();
464

    
465
            this.net_img.hide();
466
            this.cpu_img.hide();
467
        },
468

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

    
486
        update_layout: function() {
487
            if (!this.vm.stats_available) {
488
                this.loading.show();
489
                this.img.hide();
490
                this.error.hide();
491
            } else {
492
                this.loading.hide();
493
                this.stats = this.vm.get("stats");
494
                var images = this.get_images(this.stats_type);
495

    
496
                if (images.cpu) {
497
                    this.cpu_img.attr({src:images.cpu}).show();
498
                    this.cpu_error.hide();
499
                } else {
500
                    this.cpu_img.hide();
501
                    this.cpu_error.show();
502
                }
503

    
504
                if (images.net) {
505
                    this.net_img.attr({src:images.net}).show();
506
                    this.net_error.hide();
507
                } else {
508
                    this.net_img.hide();
509
                    this.net_error.show();
510
                }
511
            }
512
            $(window).trigger("resize");
513
        }
514
    });
515

    
516
    views.VMDetailsView = views.View.extend({
517
        view_id: "vm_details",
518
        el_sel: '.vm-details',
519
        
520

    
521
        selectors: {
522
            'cpu': '.cpu-data',
523
            'ram': '.ram-data',
524
            'disk': '.disk-data',
525
            'image_name': '.image-data',
526
            'image_size': '.image-size-data'
527
        },
528

    
529
        initialize: function(vm, view) {
530
            this.parent = view;
531
            this.vm = vm;
532
            this.el = $(this.parent.vm(vm)).find(this.el_sel).get(0);
533
            this.view_id = "vm_{0}_details".format(vm.id);
534

    
535
            views.VMDetailsView.__super__.initialize.call(this);
536
            this.update_layout();
537
        },
538

    
539
        update_layout: function() {
540
            var image = this.vm.get_image();
541
            var flavor = this.vm.get_flavor();
542
            if (!flavor || !image) {
543
                return;
544
            }
545

    
546
            this.sel('image_name').text(util.truncate(image.get('name'), 13)).attr("title", image.get('name'));
547
            this.sel('image_size').text(image.get('metadata').values.size).attr('title', image.get('metadata').values.size);
548

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

    
562
        el: '#machinesview-icon',
563
        id_tpl: 'icon-vm-',
564

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

    
584
        post_update_vm: function(vm) {
585
        },
586

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

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

    
623
        },
624

    
625
        check_terminated_is_empty: function() {
626
            // hide/show terminated container
627
            if (this.$(".terminated .machine-container").length == 0) {
628
                this.$(".terminated").hide()
629
            } else {
630
                this.$(".terminated").show()
631
            }
632

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

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

    
685
            if (vm.state() == "DESTROY") {
686
                el.find(".machine-ips").hide();
687
                el.find(".build-progress").show().text("Terminating...");
688
            }
689

    
690
            icon_state = vm.is_active() ? "on" : "off";
691
            set_machine_os_image(el, "icon", icon_state, this.get_vm_icon_os(vm));
692
            
693
            // update subviews
694
            this.rename_views[vm.id].update_layout();
695
            this.stats_views[vm.id].update_layout();
696
            this.connect_views[vm.id].update_layout();
697
            this.tags_views[vm.id].update_layout();
698
            this.details_views[vm.id].update_layout();
699
        },
700

    
701
        post_remove_vm: function(vm) {
702
            this.check_terminated_is_empty();
703
            $(window).trigger("resize");
704
        },
705
            
706
        get_vm_icon_os: function(vm) {
707
            var os = vm.get_os();
708
            var icons = window.os_icons || views.IconView.VM_OS_ICONS;
709

    
710
            if (icons.indexOf(os) == -1) {
711
                os = "unknown";
712
            }
713

    
714
            return os;
715
        },
716

    
717
        // TODO: move to views.utils (the method and the VM_OS_ICON vars)
718
        get_vm_icon_path: function(vm, icon_type) {
719
            var os = vm.get_os();
720
            var icons = window.os_icons || views.IconView.VM_OS_ICONS;
721

    
722
            if (icons.indexOf(os) == -1) {
723
                os = "unknown";
724
            }
725

    
726
            return views.IconView.VM_OS_ICON_TPLS[icon_type].format(os);
727
        }
728
    })
729

    
730
    views.IconView.VM_OS_ICON_TPLS = {
731
        "medium": "/static/icons/machines/medium/{0}-sprite.png"
732
    }
733

    
734
    views.IconView.VM_OS_ICONS = window.os_icons || [];
735

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

    
754
})(this);