cpee-model-management 1.0.18 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0f20ba70c3f8b275794d93cc37318ea2c9a2f6cac142b97955b7df37bf19c78
4
- data.tar.gz: 727d1d7684b81ce572a09fb6afa63365e74c7f9d40d231fb8495d7797f3f2057
3
+ metadata.gz: 2407951bdeabf8fad81810a6c56b3ce1f8a28d17e583d6c32207424cdc11334a
4
+ data.tar.gz: 9286ff4e9aa86127c7ce19ab0bd0da71b596b6ef035a99b48bea5bc4e85f1383
5
5
  SHA512:
6
- metadata.gz: 6d765472f0d8e08bbc6a43e2e6fb779065ee86606cd5030ff82a9e69134f29a01afcad618c81d089a66d06b893f6f64133555ef578ed2a9e9c1504faedd8f65f
7
- data.tar.gz: 522152b30e278e976ae047cd4a355f40f73e19d8abf7ddb809e1385bd39007e9f6b1904b3f98d8334dd031f1d1fb30af4952581978128219f521741c401669f4
6
+ metadata.gz: 27df5a985c2441e656cfaefcb72377bbf720d04fe21c49fb9866c2b1b42d314af515f3dba981e8afb4fb616d2a9cdc897af8fd048d7547f57cfac594cac0ab1c
7
+ data.tar.gz: 076150342b2320ac0103a245f2162e7c03450970c9d078cd1446b1f400996dea35f4350a0aacbeed696344d3d996337531e7a25daa42ab9e755b3c8687ef05cb
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cpee-model-management"
3
- s.version = "1.0.18"
3
+ s.version = "1.1.0"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.license = "LGPL-3.0"
6
6
  s.summary = "(Lifecycle) manage your process models in a directory or git repo."
@@ -25,6 +25,7 @@ require 'fileutils'
25
25
  require 'pathname'
26
26
  require 'shellwords'
27
27
  require 'securerandom'
28
+ require 'cpee/redis'
28
29
 
29
30
  module CPEE
30
31
  module ModelManagement
@@ -507,6 +508,26 @@ module CPEE
507
508
  nil
508
509
  end
509
510
  end #}}}
511
+ class ShowUrl < Riddl::Implementation #{{{
512
+ def response
513
+ show = @a[0]
514
+ @status = 302
515
+ @headers << Riddl::Header.new('Location',show + @p.first.value)
516
+ end
517
+ end #}}}
518
+ class AbandonUrl < Riddl::Implementation #{{{
519
+ def response
520
+ aba = @p.first.value
521
+ res1 = Typhoeus.get(File.join(aba,'properties','state','/'))
522
+ if res1.success?
523
+ if res1.response_body == 'ready' || res1.response_body == 'stopped'
524
+ Typhoeus.put(File.join(aba,'properties','state','/'), headers: {'Content-Type' => 'application/x-www-form-urlencoded'}, body: "value=abandoned")
525
+ end
526
+ end
527
+ nil
528
+ end
529
+ end #}}}
530
+
510
531
  class MoveItem < Riddl::Implementation #{{{
511
532
  def response
512
533
  where = @a[0] == :main ? '' : Riddl::Protocols::Utils::unescape(@r[-2])
@@ -606,7 +627,7 @@ module CPEE
606
627
  end
607
628
  end #}}}
608
629
 
609
- class Active < Riddl::SSEImplementation #{{{
630
+ class ManagementSend < Riddl::SSEImplementation #{{{
610
631
  def onopen
611
632
  @conns = @a[0]
612
633
  @conns << self
@@ -616,31 +637,244 @@ module CPEE
616
637
  end
617
638
  end #}}}
618
639
 
640
+ class StatSend < Riddl::SSEImplementation #{{{
641
+ def onopen
642
+ @conns = @a[0]
643
+ @conns << self
644
+ end
645
+ def onclose
646
+ @conns.delete(self)
647
+ end
648
+ end #}}}
649
+
650
+ class StatReceive < Riddl::Implementation #{{{
651
+ def response
652
+ redis = @a[0]
653
+ receivers = @a[1]
654
+ topic = @p[1].value
655
+ event_name = @p[2].value
656
+ notification = JSON.parse(@p[3].value.read)
657
+
658
+ instancenr = notification['instance']
659
+ content = notification['content']
660
+ attr = content['attributes']
661
+ engine = notification['cpee']
662
+
663
+ prefix = File.join(engine,notification['instance-uuid'].to_s)
664
+
665
+ if topic == 'state' && event_name == 'change'
666
+ if %w{abandoned finished}.include?(content['state'])
667
+ parent = redis.get(File.join(prefix,'parent'))
668
+ oldstate = redis.get(File.join(prefix,'state'))
669
+ children = redis.lrange(File.join(prefix,'children'),0,-1)
670
+ redis.multi do |multi|
671
+ multi.decr(File.join(engine,oldstate)) rescue nil
672
+ multi.incr(File.join(engine,'total_' + content['state']))
673
+ multi.lrem(File.join(engine,'instances'),0,notification['instance-uuid'])
674
+ multi.del(File.join(prefix,'instance-url'))
675
+ multi.del(File.join(prefix,'author'))
676
+ multi.del(File.join(prefix,'path'))
677
+ multi.del(File.join(prefix,'name'))
678
+ multi.del(File.join(prefix,'state'))
679
+ multi.del(File.join(prefix,'cpu'))
680
+ multi.del(File.join(prefix,'mem'))
681
+ children.each do |child|
682
+ if parent
683
+ multi.set(File.join(engine,child,'parent'),parent)
684
+ else
685
+ multi.del(File.join(engine,child,'parent'))
686
+ end
687
+ end
688
+ multi.del(File.join(prefix,'children'))
689
+ multi.del(File.join(prefix,'parent'))
690
+ if parent
691
+ multi.lrem(File.join(engine,parent,'children'),0,notification['instance-uuid'].to_s)
692
+ end
693
+ end
694
+ elsif %w{ready}.include?(content['state'])
695
+ exi = true if redis.lrange(File.join(engine,'instances'),0,-1).include?(notification['instance-uuid'])
696
+ redis.multi do |multi|
697
+ unless exi
698
+ multi.incr(File.join(engine,'total_created'))
699
+ multi.incr(File.join(engine,'ready'))
700
+ multi.rpush(File.join(engine,'instances'),notification['instance-uuid'])
701
+ end
702
+ multi.set(File.join(prefix,'instance-url'),notification['instance-url'])
703
+ multi.set(File.join(prefix,'author'),attr['author'])
704
+ multi.set(File.join(prefix,'state'),content['state'])
705
+ multi.set(File.join(prefix,'path'),File.join(attr['design_dir'],attr['info']+'.xml')) unless attr['design_dir'].nil? || attr['info'].nil?
706
+ multi.set(File.join(prefix,'name'),attr['info'])
707
+ multi.set(File.join(prefix,'cpu'),0)
708
+ multi.set(File.join(prefix,'mem'),0)
709
+ end
710
+ elsif %w{stopping}.include?(content['state'])
711
+ redis.set(File.join(prefix,'state'),content['state'])
712
+ elsif %w{stopped}.include?(content['state'])
713
+ redis.multi do |multi|
714
+ multi.decr(File.join(engine,'running'))
715
+ multi.incr(File.join(engine,'stopped'))
716
+ multi.set(File.join(prefix,'state'),content['state'])
717
+ multi.set(File.join(prefix,'cpu'),0)
718
+ multi.set(File.join(prefix,'mem'),0)
719
+ end
720
+ elsif %w{running}.include?(content['state'])
721
+ oldstate = redis.get(File.join(prefix,'state'))
722
+ redis.multi do |multi|
723
+ multi.decr(File.join(engine,oldstate)) rescue nil
724
+ multi.incr(File.join(engine,'running'))
725
+ multi.set(File.join(prefix,'state'),content['state'])
726
+ end
727
+ end
728
+
729
+ url, author, path, name, state, parent = redis.mget(
730
+ File.join(prefix,'instance-url'),
731
+ File.join(prefix,'author'),
732
+ File.join(prefix,'path'),
733
+ File.join(prefix,'name'),
734
+ File.join(prefix,'state'),
735
+ File.join(prefix,'parent')
736
+ )
737
+ receivers.each do |conn|
738
+ conn.send JSON::generate(:topic => topic, :event => event_name, :engine => engine, :uuid => notification['instance-uuid'], :url => url, :author => author, :path => path.to_s, :name => name, :state => content['state'], :parent => parent.to_s)
739
+ end
740
+ elsif topic == 'task' && event_name == 'instantiation'
741
+ redis.multi do |multi|
742
+ multi.rpush(File.join(engine,notification['instance-uuid'],'children'),content['received']['CPEE-INSTANCE-UUID'])
743
+ multi.set(File.join(engine,content['received']['CPEE-INSTANCE-UUID'],'parent'),notification['instance-uuid'])
744
+ end
745
+ prefix = File.join(engine,content['received']['CPEE-INSTANCE-UUID'].to_s)
746
+ url, author, path, name, state, parent = redis.mget(
747
+ File.join(prefix,'instance-url'),
748
+ File.join(prefix,'author'),
749
+ File.join(prefix,'path'),
750
+ File.join(prefix,'name'),
751
+ File.join(prefix,'state'),
752
+ File.join(prefix,'parent')
753
+ )
754
+ receivers.each do |conn|
755
+ conn.send JSON::generate(:topic => 'state', :event => 'change', :engine => engine, :uuid => content['received']['CPEE-INSTANCE-UUID'], :url => url, :author => author, :path => path.to_s, :name => name, :state => state, :parent => parent.to_s)
756
+ end
757
+ elsif topic == 'status' && event_name == 'resource_utilization'
758
+ redis.multi do |multi|
759
+ multi.set(File.join(prefix,'cpu'),content['utime'] + content['stime'])
760
+ multi.set(File.join(prefix,'mem'),content['mib'])
761
+ end
762
+ receivers.each do |conn|
763
+ conn.send JSON::generate(:topic => topic, :event => event_name, :engine => engine, :uuid => notification['instance-uuid'], :cpu => content['utime'] + content['stime'], :mem => content['mib'])
764
+ end
765
+ elsif topic == 'node' && event_name == 'resource_utilization'
766
+ redis.multi do |multi|
767
+ multi.set(File.join(engine,'cpu_usage'),content['cpu_usage'])
768
+ multi.set(File.join(engine,'mem_free'),content['mem_free'])
769
+ multi.set(File.join(engine,'mem_total'),content['mem_total'])
770
+ multi.set(File.join(engine,'mem_available'),content['mem_available'])
771
+ end
772
+ receivers.each do |conn|
773
+ conn.send JSON::generate(:topic => topic, :event => event_name, :engine => engine, :cpu_usage => content['cpu_usage'], :mem_free => content['mem_free'], :mem_total => content['mem_total'], :mem_available => content['mem_available'])
774
+ end
775
+ end
776
+ end
777
+ end #}}}
778
+
779
+ class StatGet < Riddl::Implementation #{{{
780
+ def response
781
+ redis = @a[0]
782
+ engine = @p[0].value
783
+ res = redis.mapped_mget(
784
+ File.join(engine,'total_created'),
785
+ File.join(engine,'total_finished'),
786
+ File.join(engine,'total_abandoned'),
787
+ File.join(engine,'ready'),
788
+ File.join(engine,'stopped'),
789
+ File.join(engine,'running')
790
+ ).transform_keys{ |k| File.basename(k) }.transform_values(&:to_i)
791
+ Riddl::Parameter::Complex.new('stats','application/json',JSON::pretty_generate(res || []))
792
+ end
793
+ end #}}}
794
+ class InstancesGet < Riddl::Implementation #{{{
795
+ def response
796
+ redis = @a[0]
797
+ engine = @p[0].value
798
+ doc = XML::Smart.string('<instances/>')
799
+ redis.lrange(File.join(engine,'instances'),0,-1).each do |i|
800
+ prefix = File.join(engine,i.to_s)
801
+ url, author, path, name, state, cpu, mem, parent = redis.mget(
802
+ File.join(prefix,'instance-url'),
803
+ File.join(prefix,'author'),
804
+ File.join(prefix,'path'),
805
+ File.join(prefix,'name'),
806
+ File.join(prefix,'state'),
807
+ File.join(prefix,'cpu'),
808
+ File.join(prefix,'mem'),
809
+ File.join(prefix,'parent')
810
+ )
811
+ doc.root.add('instance', :uuid => i, :url => url, :author => author, :path => path, :name => name, :state => state, :cpu => cpu, :mem => mem, :parent => parent)
812
+ end
813
+ Riddl::Parameter::Complex.new('tree','text/xml',doc.to_s)
814
+ end
815
+ end #}}}
816
+ class InstanceGet < Riddl::Implementation #{{{
817
+ def response
818
+ redis = @a[0]
819
+ engine = @p[0].value
820
+ uuid = @r[-1]
821
+ prefix = File.join(engine,uuid.to_s)
822
+ url, author, path, name, state, cpu, mem, parent = redis.mget(
823
+ File.join(prefix,'instance-url'),
824
+ File.join(prefix,'author'),
825
+ File.join(prefix,'path'),
826
+ File.join(prefix,'name'),
827
+ File.join(prefix,'state'),
828
+ File.join(prefix,'cpu'),
829
+ File.join(prefix,'mem'),
830
+ File.join(prefix,'parent')
831
+ )
832
+ Riddl::Parameter::Complex.new('instance','application/json',JSON.generate(:uuid => uuid, :url => url, :author => author, :path => path, :name => name, :state => state, :cpu => cpu, :mem => mem, :parent => parent))
833
+ end
834
+ end #}}}
835
+
836
+
619
837
  def self::implementation(opts)
620
- opts[:connections] = []
838
+ opts[:management_receivers] = []
839
+ opts[:stat_receivers] = []
840
+
841
+ ### set redis_cmd to nil if you want to do global
842
+ ### at least redis_path or redis_url and redis_db have to be set if you do global
843
+ opts[:redis_path] ||= 'redis.sock' # use e.g. /tmp/redis.sock for global stuff. Look it up in your redis config
844
+ opts[:redis_db] ||= 0
845
+ ### optional redis stuff
846
+ opts[:redis_url] ||= nil
847
+ opts[:redis_cmd] ||= 'redis-server --port 0 --unixsocket #redis_path# --unixsocketperm 600 --pidfile #redis_pid# --dir #redis_db_dir# --dbfilename #redis_db_name# --databases 1 --save 900 1 --save 300 10 --save 60 10000 --rdbcompression yes --daemonize yes'
848
+ opts[:redis_pid] ||= 'redis.pid' # use e.g. /var/run/redis.pid if you do global. Look it up in your redis config
849
+ opts[:redis_db_name] ||= 'redis.rdb' # use e.g. /var/lib/redis.rdb for global stuff. Look it up in your redis config
850
+
851
+ CPEE::redis_connect opts, 'Server Main'
621
852
 
622
853
  Proc.new do
623
- on resource do
854
+ interface 'events' do
855
+ run StatReceive, opts[:redis], opts[:stat_receivers] if post 'event'
856
+ end
857
+ interface 'implementation' do
624
858
  run GetList, :main, opts[:views], opts[:models] if get 'stage'
625
859
  run GetListFull, opts[:views], opts[:models] if get 'full'
626
860
  run GetStages, opts[:themes] if get 'stages'
627
- run Create, :main, :cre, opts[:views], opts[:connections], opts[:templates], opts[:models] if post 'item'
628
- run Create, :main, :dup, opts[:views], opts[:connections], opts[:templates], opts[:models] if post 'duplicate'
629
- run CreateDir, opts[:connections], opts[:models] if post 'dir'
630
- run Active, opts[:connections] if sse
861
+ run Create, :main, :cre, opts[:views], opts[:management_receivers], opts[:templates], opts[:models] if post 'item'
862
+ run Create, :main, :dup, opts[:views], opts[:management_receivers], opts[:templates], opts[:models] if post 'duplicate'
863
+ run CreateDir, opts[:management_receivers], opts[:models] if post 'dir'
864
+ run ManagementSend, opts[:management_receivers] if sse
631
865
  on resource '[a-zA-Z0-9öäüÖÄÜ _-]+\.dir' do
632
866
  run GetList, :sub, opts[:views], opts[:models] if get 'stage'
633
- run Create, :sub, :cre, opts[:views], opts[:connections], opts[:templates], opts[:models] if post 'item'
634
- run Create, :sub, :dup, opts[:views], opts[:connections], opts[:templates], opts[:models] if post 'duplicate'
635
- run DeleteDir, opts[:connections], opts[:models] if delete
636
- run RenameDir, opts[:connections], opts[:models] if put 'name'
867
+ run Create, :sub, :cre, opts[:views], opts[:management_receivers], opts[:templates], opts[:models] if post 'item'
868
+ run Create, :sub, :dup, opts[:views], opts[:management_receivers], opts[:templates], opts[:models] if post 'duplicate'
869
+ run DeleteDir, opts[:management_receivers], opts[:models] if delete
870
+ run RenameDir, opts[:management_receivers], opts[:models] if put 'name'
637
871
  on resource '[a-zA-Z0-9öäüÖÄÜ _-]+\.xml' do
638
- run DeleteItem, :sub, opts[:connections], opts[:models] if delete
872
+ run DeleteItem, :sub, opts[:management_receivers], opts[:models] if delete
639
873
  run GetItem, :sub, opts[:models] if get
640
- run PutItem, :sub, opts[:connections], opts[:models] if put 'content'
641
- run RenameItem, :sub, opts[:connections], opts[:models] if put 'name'
642
- run MoveItem, :sub, opts[:connections], opts[:models] if put 'dirname'
643
- run ShiftItem, :sub, opts[:connections], opts[:themes], opts[:models] if put 'newstage'
874
+ run PutItem, :sub, opts[:management_receivers], opts[:models] if put 'content'
875
+ run RenameItem, :sub, opts[:management_receivers], opts[:models] if put 'name'
876
+ run MoveItem, :sub, opts[:management_receivers], opts[:models] if put 'dirname'
877
+ run ShiftItem, :sub, opts[:management_receivers], opts[:themes], opts[:models] if put 'newstage'
644
878
  on resource 'open' do
645
879
  run OpenItem, :sub, opts[:instantiate], opts[:cockpit], opts[:views], false, opts[:models] if get 'stage'
646
880
  end
@@ -650,12 +884,12 @@ module CPEE
650
884
  end
651
885
  end
652
886
  on resource '[a-zA-Z0-9öäüÖÄÜ _-]+\.xml' do
653
- run DeleteItem, :main, opts[:connections], opts[:models] if delete
887
+ run DeleteItem, :main, opts[:management_receivers], opts[:models] if delete
654
888
  run GetItem, :main, opts[:models] if get
655
- run PutItem, :main, opts[:connections], opts[:models] if put 'content'
656
- run RenameItem, :main, opts[:connections], opts[:models] if put 'name'
657
- run MoveItem, :main, opts[:connections], opts[:models] if put 'dirname'
658
- run ShiftItem, :main, opts[:connections], opts[:themes], opts[:models] if put 'newstage'
889
+ run PutItem, :main, opts[:management_receivers], opts[:models] if put 'content'
890
+ run RenameItem, :main, opts[:management_receivers], opts[:models] if put 'name'
891
+ run MoveItem, :main, opts[:management_receivers], opts[:models] if put 'dirname'
892
+ run ShiftItem, :main, opts[:management_receivers], opts[:themes], opts[:models] if put 'newstage'
659
893
  on resource 'open' do
660
894
  run OpenItem, :main, opts[:instantiate], opts[:cockpit], opts[:views], false, opts[:models] if get 'stage'
661
895
  end
@@ -663,6 +897,26 @@ module CPEE
663
897
  run OpenItem, :main, opts[:instantiate], opts[:cockpit], opts[:views], true, opts[:models] if get 'stage'
664
898
  end
665
899
  end
900
+ on resource 'dash' do
901
+ on resource 'show' do
902
+ run ShowUrl, opts[:show] if get 'url'
903
+ end
904
+ on resource 'abandon' do
905
+ run AbandonUrl if put 'url'
906
+ end
907
+ on resource 'events' do
908
+ run StatSend, opts[:stat_receivers] if sse
909
+ end
910
+ on resource 'instances' do
911
+ run InstancesGet, opts[:redis] if get 'engine'
912
+ on resource do
913
+ run InstanceGet, opts[:redis] if get 'engine'
914
+ end
915
+ end
916
+ on resource 'stats' do
917
+ run StatGet, opts[:redis] if get 'engine'
918
+ end
919
+ end
666
920
  end
667
921
  end
668
922
  end
@@ -0,0 +1,133 @@
1
+ <description xmlns="http://riddl.org/ns/description/1.0" xmlns:ann="http://riddl.org/ns/annotation/1.0" xmlns:xi="http://www.w3.org/2001/XInclude" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
2
+ <message name="url">
3
+ <parameter name="url" type="string"/>
4
+ </message>
5
+ <message name="engine">
6
+ <parameter name="engine" type="string"/>
7
+ </message>
8
+ <message name="stats">
9
+ <parameter name="stats" mimetype="application/json"/>
10
+ </message>
11
+ <message name="tree">
12
+ <parameter name="tree" mimetype="text/xml"/>
13
+ </message>
14
+ <message name="instance">
15
+ <parameter name="instance" mimetype="application/json"/>
16
+ </message>
17
+ <message name="item">
18
+ <parameter name="stage" type="string">
19
+ <xi:include href="stages"/>
20
+ </parameter>
21
+ <parameter name="new" type="string">
22
+ <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+</param>
23
+ </parameter>
24
+ </message>
25
+ <message name="name">
26
+ <parameter name="new" type="string">
27
+ <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+</param>
28
+ </parameter>
29
+ </message>
30
+ <message name="dir">
31
+ <parameter name="dir" type="string">
32
+ <param name="pattern">([a-zA-Z0-9öäüÖÄÜ _-]+)|</param>
33
+ </parameter>
34
+ </message>
35
+ <message name="dirname">
36
+ <parameter name="dir" type="string">
37
+ <param name="pattern">([a-zA-Z0-9öäüÖÄÜ _-]+)\.dir|</param>
38
+ </parameter>
39
+ </message>
40
+ <message name="duplicate">
41
+ <parameter name="new" type="string">
42
+ <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+</param>
43
+ </parameter>
44
+ <parameter name="old" type="string">
45
+ <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+\.xml</param>
46
+ </parameter>
47
+ </message>
48
+ <message name="stages">
49
+ <parameter name="stages" type="string"/>
50
+ </message>
51
+ <message name="newstage">
52
+ <parameter name="stage" type="string">
53
+ <xi:include href="stages"/>
54
+ </parameter>
55
+ </message>
56
+ <message name="stage">
57
+ <optional>
58
+ <parameter name="stage" type="string">
59
+ <xi:include href="stages"/>
60
+ </parameter>
61
+ </optional>
62
+ </message>
63
+ <message name="full">
64
+ <parameter name="full" type="string"/>
65
+ <optional>
66
+ <parameter name="stage" type="string">
67
+ <xi:include href="stages"/>
68
+ </parameter>
69
+ </optional>
70
+ </message>
71
+ <message name="list">
72
+ <parameter name="list" mimetype="application/json"/>
73
+ </message>
74
+ <message name="content">
75
+ <parameter name="content" mimetype="application/xml"/>
76
+ </message>
77
+ <resource>
78
+ <post in="item"/>
79
+ <post in="dir"/>
80
+ <post in="duplicate"/>
81
+ <get in="stage" out="list"/>
82
+ <get in="full" out="list"/>
83
+ <get in="stages" out="list"/>
84
+ <sse/>
85
+ <resource relative="[a-zA-Z0-9&#xF6;&#xE4;&#xFC;&#xD6;&#xC4;&#xDC; _-]+\.dir">
86
+ <post in="item"/>
87
+ <post in="duplicate"/>
88
+ <get in="stage" out="list"/>
89
+ <delete/>
90
+ <put in="name"/> <!-- rename -->
91
+ <resource relative="[a-zA-Z0-9&#xF6;&#xE4;&#xFC;&#xD6;&#xC4;&#xDC; _-]+\.xml">
92
+ <get out='content'/>
93
+ <delete/>
94
+ <put in="content"/>
95
+ <put in="name"/> <!-- rename -->
96
+ <put in="dirname"/> <!-- move -->
97
+ <put in="newstage"/> <!-- shift -->
98
+ <resource relative="open"><get in="stage"/></resource>
99
+ <resource relative="open-new"><get in="stage"/></resource>
100
+ </resource>
101
+ </resource>
102
+ <resource relative="[a-zA-Z0-9&#xF6;&#xE4;&#xFC;&#xD6;&#xC4;&#xDC; _-]+\.xml">
103
+ <get out='content'/>
104
+ <delete/>
105
+ <put in="content"/>
106
+ <put in="name"/> <!-- rename -->
107
+ <put in="dirname"/> <!-- move -->
108
+ <put in="newstage"/> <!-- shift -->
109
+ <resource relative="open"><get in="stage"/></resource>
110
+ <resource relative="open-new"><get in="stage"/></resource>
111
+ </resource>
112
+ <resource relative="dash">
113
+ <resource relative="show">
114
+ <get in="url"/>
115
+ </resource>
116
+ <resource relative="abandon">
117
+ <put in="url"/>
118
+ </resource>
119
+ <resource relative="events">
120
+ <sse/>
121
+ </resource>
122
+ <resource relative="instances">
123
+ <get in="engine" out="tree"/>
124
+ <resource>
125
+ <get in="engine" out="instance"/>
126
+ </resource>
127
+ </resource>
128
+ <resource relative="stats">
129
+ <get in="engine" out="stats"/>
130
+ </resource>
131
+ </resource>
132
+ </resource>
133
+ </description>
@@ -1,98 +1,19 @@
1
- <description xmlns="http://riddl.org/ns/description/1.0" xmlns:ann="http://riddl.org/ns/annotation/1.0" xmlns:xi="http://www.w3.org/2001/XInclude" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
2
- <message name="item">
3
- <parameter name="stage" type="string">
4
- <xi:include href="stages"/>
5
- </parameter>
6
- <parameter name="new" type="string">
7
- <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+</param>
8
- </parameter>
9
- </message>
10
- <message name="name">
11
- <parameter name="new" type="string">
12
- <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+</param>
13
- </parameter>
14
- </message>
15
- <message name="dir">
16
- <parameter name="dir" type="string">
17
- <param name="pattern">([a-zA-Z0-9öäüÖÄÜ _-]+)|</param>
18
- </parameter>
19
- </message>
20
- <message name="dirname">
21
- <parameter name="dir" type="string">
22
- <param name="pattern">([a-zA-Z0-9öäüÖÄÜ _-]+)\.dir|</param>
23
- </parameter>
24
- </message>
25
- <message name="duplicate">
26
- <parameter name="new" type="string">
27
- <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+</param>
28
- </parameter>
29
- <parameter name="old" type="string">
30
- <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+\.xml</param>
31
- </parameter>
32
- </message>
33
- <message name="stages">
34
- <parameter name="stages" type="string"/>
35
- </message>
36
- <message name="newstage">
37
- <parameter name="stage" type="string">
38
- <xi:include href="stages"/>
39
- </parameter>
40
- </message>
41
- <message name="stage">
42
- <optional>
43
- <parameter name="stage" type="string">
44
- <xi:include href="stages"/>
45
- </parameter>
46
- </optional>
47
- </message>
48
- <message name="full">
49
- <parameter name="full" type="string"/>
50
- <optional>
51
- <parameter name="stage" type="string">
52
- <xi:include href="stages"/>
53
- </parameter>
54
- </optional>
55
- </message>
56
- <message name="list">
57
- <parameter name="list" mimetype="application/json"/>
58
- </message>
59
- <message name="content">
60
- <parameter name="content" mimetype="application/xml"/>
61
- </message>
62
- <resource>
63
- <post in="item"/>
64
- <post in="dir"/>
65
- <post in="duplicate"/>
66
- <get in="stage" out="list"/>
67
- <get in="full" out="list"/>
68
- <get in="stages" out="list"/>
69
- <sse/>
70
- <resource relative="[a-zA-Z0-9&#xF6;&#xE4;&#xFC;&#xD6;&#xC4;&#xDC; _-]+\.dir">
71
- <post in="item"/>
72
- <post in="duplicate"/>
73
- <get in="stage" out="list"/>
74
- <delete/>
75
- <put in="name"/> <!-- rename -->
76
- <resource relative="[a-zA-Z0-9&#xF6;&#xE4;&#xFC;&#xD6;&#xC4;&#xDC; _-]+\.xml">
77
- <get out='content'/>
78
- <delete/>
79
- <put in="content"/>
80
- <put in="name"/> <!-- rename -->
81
- <put in="dirname"/> <!-- move -->
82
- <put in="newstage"/> <!-- shift -->
83
- <resource relative="open"><get in="stage"/></resource>
84
- <resource relative="open-new"><get in="stage"/></resource>
85
- </resource>
86
- </resource>
87
- <resource relative="[a-zA-Z0-9&#xF6;&#xE4;&#xFC;&#xD6;&#xC4;&#xDC; _-]+\.xml">
88
- <get out='content'/>
89
- <delete/>
90
- <put in="content"/>
91
- <put in="name"/> <!-- rename -->
92
- <put in="dirname"/> <!-- move -->
93
- <put in="newstage"/> <!-- shift -->
94
- <resource relative="open"><get in="stage"/></resource>
95
- <resource relative="open-new"><get in="stage"/></resource>
96
- </resource>
97
- </resource>
98
- </description>
1
+ <declaration xmlns="http://riddl.org/ns/declaration/1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
2
+ <interface name="implementation">
3
+ <xi:include href="implementation.xml"/>
4
+ </interface>
5
+ <interface name="events">
6
+ <xi:include href="http://www.riddl.org/ns/common-patterns/notifications-consumer/2.0/consumer.xml"/>
7
+ </interface>
8
+
9
+ <facade>
10
+ <tile>
11
+ <layer name="implementation">
12
+ <apply-to>/</apply-to>
13
+ </layer>
14
+ <layer name="events">
15
+ <apply-to>/dash/events</apply-to>
16
+ </layer>
17
+ </tile>
18
+ </facade>
19
+ </declaration>
data/server/moma.conf CHANGED
@@ -2,6 +2,7 @@
2
2
  :models: models
3
3
  :location: https://cpee.org/design/server/
4
4
  :instantiate: https://cpee.org/flow/start/
5
+ :show: https://cpee.org/flow/index.html?monitor=
5
6
  :cockpit:
6
7
  draft: https://cpee.org/flow/model.html?monitor=
7
8
  development: https://cpee.org/flow/edit.html?monitor=
data/ui/css/design.css CHANGED
@@ -26,6 +26,11 @@ ui-behind {
26
26
  color: #d0d0d0;
27
27
  }
28
28
 
29
+ ui-area > *:first-child {
30
+ padding-top: 0;
31
+ margin-top: 0;
32
+ }
33
+
29
34
  ui-behind span {
30
35
  cursor: pointer;
31
36
  }
data/ui/css/stats.css ADDED
@@ -0,0 +1,55 @@
1
+ #resources h1 {
2
+ font-size: 1.2em;
3
+ border-bottom: 0.1em solid var(--x-ui-border-color);
4
+ }
5
+
6
+ #resources table {
7
+ margin-left: 1.3em;
8
+ }
9
+
10
+ #instances h1 {
11
+ font-size: 1.2em;
12
+ border-bottom: 0.1em solid var(--x-ui-border-color);
13
+ }
14
+
15
+ .instances .text {
16
+ white-space: nowrap;
17
+ }
18
+ .instances .text > td {
19
+ display: inline-block;
20
+ white-space: nowrap;
21
+ overflow: hidden;
22
+ text-overflow: ellipsis;
23
+ padding-right: 0.5em;
24
+ padding-left: 0.5em;
25
+ }
26
+
27
+ .instances .name {
28
+ width: 12em;
29
+ }
30
+ .instances .state {
31
+ width: 7em
32
+ }
33
+ .instances .state:not([data-state=ready]):not([data-state=stopped]) > span.abandon {
34
+ display: none;
35
+ }
36
+ .instances .author {
37
+ width: 12em
38
+ }
39
+
40
+ .instances tr.sub, .instances tr.sub > td {
41
+ margin:0;
42
+ padding:0;
43
+ }
44
+
45
+ .instances .sub table {
46
+ margin-left: 0.8em;
47
+ }
48
+ .instances .sub table > tr.text > td:first-child::before {
49
+ content: '⤷';
50
+ margin-right: 0.5em;
51
+ }
52
+
53
+ .instances tr.text.even td {
54
+ background-color: var(--x-ui-content-light-background);
55
+ }
@@ -0,0 +1,7 @@
1
+ [is="x-ui-"] {
2
+ padding: 1em;
3
+ }
4
+ [is="x-ui-"] *:first-child {
5
+ padding-top: 0;
6
+ margin-top: 0;
7
+ }
data/ui/index.html CHANGED
@@ -35,6 +35,7 @@
35
35
  <script type="text/javascript" src="/js_libs/underscore.min.js"></script>
36
36
  <script type="text/javascript" src="/js_libs/jquery.caret.min.js"></script>
37
37
  <script type="text/javascript" src="/js_libs/jquery.cookie.js"></script>
38
+ <script type="text/javascript" src="/js_libs/plotly.min.js"></script>
38
39
 
39
40
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
40
41
 
@@ -52,20 +53,22 @@
52
53
 
53
54
  <!-- custom stuff, play arround -->
54
55
  <link rel="stylesheet" href="css/design.css" type="text/css"/>
56
+ <link rel="stylesheet" href="css/stats.css" type="text/css"/>
55
57
  <script type="text/javascript" src="js/design.js"></script>
58
+ <script type="text/javascript" src="js/stats.js"></script>
56
59
  </head>
57
60
  <body is="x-ui-">
58
61
  <ui-rest id="main">
59
62
  <ui-tabbar>
60
- <ui-before ></ui-before>
61
- <ui-tab class="" data-tab="models" >Models</ui-tab>
62
- <ui-tab class="inactive" data-tab="newmodel">New Model</ui-tab>
63
- <ui-tab class="inactive" data-tab="newdir" >New Dir</ui-tab>
64
- <ui-space ></ui-space>
65
- <ui-tab class="inactive" data-tab="running" >Running</ui-tab>
66
- <ui-tab class="inactive" data-tab="stopped" >Stopped</ui-tab>
67
- <ui-behind ><span></span></ui-behind>
68
- <ui-last ><a class="logo" href=".."></a></ui-last>
63
+ <ui-before ></ui-before>
64
+ <ui-tab class="" data-tab="models" >Models</ui-tab>
65
+ <ui-tab class="inactive" data-tab="newmodel" >New Model</ui-tab>
66
+ <ui-tab class="inactive" data-tab="newdir" >New Dir</ui-tab>
67
+ <ui-space ></ui-space>
68
+ <ui-tab class="inactive" data-tab="instances">Instances</ui-tab>
69
+ <ui-tab class="inactive" data-tab="resources">Resources</ui-tab>
70
+ <ui-behind ><span></span></ui-behind>
71
+ <ui-last ><a class="logo" href=".."></a></ui-last>
69
72
  </ui-tabbar>
70
73
  <ui-content class="noselect">
71
74
  <ui-area data-belongs-to-tab="models">
@@ -160,7 +163,63 @@
160
163
  <p>
161
164
  <button>New Directory</button>
162
165
  </p>
163
- </id>
166
+ </form>
167
+ </ui-area>
168
+ <ui-area data-belongs-to-tab="instances" class="inactive">
169
+ <p>
170
+ Show ready, running and stopped instances.
171
+ </p>
172
+ <template id="stats_instances">
173
+ <h1 class="stats_title">Engine: </h1>
174
+ <table class='instances'></table>
175
+ </template>
176
+ <template id="stats_instance">
177
+ <tr class="text">
178
+ <td class="name"><a href='' target='_blank'><em>no name</em></a></td>
179
+ <td class="num">(<span></span>)</td>
180
+ <td class="state"><span class='value'></span> <span class='abandon'>[<a href='#' title='abandon'>a</a>]</span></td>
181
+ <td class="author"><em>unknown</em></td>
182
+ <td class="cpu"></td>
183
+ <td>/</td>
184
+ <td class="mem"></em></td>
185
+ </tr>
186
+ <tr class="sub">
187
+ <td colspan="6"><table></table></td>
188
+ </tr>
189
+ </template>
190
+ <div id='instances'></div>
191
+ </ui-area>
192
+ <ui-area data-belongs-to-tab="resources" class="inactive">
193
+ <p>
194
+ Show statistics about instances per server, and metrics about the health of the environment.
195
+ </p>
196
+ <template id="stats_engine">
197
+ <h1 class="stats_title">Engine: </h1>
198
+ <div class="stats_plot"></div>
199
+ <div class="stats_text">
200
+ <table>
201
+ <tbody>
202
+ <tr>
203
+ <td>Total Instances <strong>Created</strong> / <strong>Finished</strong> / <strong>Abandoned</strong>:</td>
204
+ <td class='total_created'></td>
205
+ <td>/</td>
206
+ <td class='total_finished'></td>
207
+ <td>/</td>
208
+ <td class='total_abandoned'></td>
209
+ </tr>
210
+ <tr>
211
+ <td>Instances Currently <strong>Ready</strong> / <strong>Running</strong> / <strong>Stopped</strong>:</td>
212
+ <td class='current_ready'></td>
213
+ <td>/</td>
214
+ <td class='current_running'></td>
215
+ <td>/</td>
216
+ <td class='current_stopped'></td>
217
+ </tr>
218
+ </tbody>
219
+ </table>
220
+ </div>
221
+ </template>
222
+ <div id='resources'></div>
164
223
  </ui-area>
165
224
  </ui-content>
166
225
  </ui-rest>
data/ui/instances.html ADDED
@@ -0,0 +1,84 @@
1
+ <!--
2
+ This file is part of CPEE-MODEL-MANAGEMENT.
3
+
4
+ CPEE-MODEL-MANAGEMENT is free software: you can redistribute it and/or
5
+ modify it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or (at your
7
+ option) any later version.
8
+
9
+ CPEE-MODEL-MANAGEMENT is distributed in the hope that it will be useful, but
10
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
+ more details.
13
+
14
+ You should have received a copy of the GNU General Public License along with
15
+ CPEE-MODEL-MANAGEMENT (file LICENSE in the main directory). If not, see
16
+ <http://www.gnu.org/licenses/>.
17
+ -->
18
+
19
+ <!DOCTYPE html>
20
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
21
+ <head>
22
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
23
+ <title>Instances</title>
24
+
25
+ <!-- libs, do not modify. When local than load local libs. -->
26
+ <script type="text/javascript" src="/js_libs/jquery.min.js"></script>
27
+ <script type="text/javascript" src="/js_libs/jquery.browser.js"></script>
28
+ <script type="text/javascript" src="/js_libs/jquery.svg.min.js"></script>
29
+ <script type="text/javascript" src="/js_libs/jquery.svgdom.min.js"></script>
30
+ <script type="text/javascript" src="/js_libs/vkbeautify.js"></script>
31
+ <script type="text/javascript" src="/js_libs/util.js"></script>
32
+ <script type="text/javascript" src="/js_libs/printf.js"></script>
33
+ <script type="text/javascript" src="/js_libs/strftime.min.js"></script>
34
+ <script type="text/javascript" src="/js_libs/parsequery.js"></script>
35
+ <script type="text/javascript" src="/js_libs/underscore.min.js"></script>
36
+ <script type="text/javascript" src="/js_libs/jquery.caret.min.js"></script>
37
+ <script type="text/javascript" src="/js_libs/jquery.cookie.js"></script>
38
+ <script type="text/javascript" src="/js_libs/plotly.min.js"></script>
39
+
40
+ <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
41
+
42
+ <script type="text/javascript" src="/js_libs/relaxngui.js"></script>
43
+
44
+ <script type="text/javascript" src="/js_libs/uidash.js"></script>
45
+ <script type="text/javascript" src="/js_libs/custommenu.js"></script>
46
+
47
+ <link rel="stylesheet" href="/js_libs/custommenu.css" type="text/css"/>
48
+ <link rel="stylesheet" href="/js_libs/uidash.css" type="text/css"/>
49
+
50
+ <link rel="stylesheet" href="/global_ui/ui.css" type="text/css"/>
51
+
52
+ <link rel="stylesheet" href="/js_libs/relaxngui.css" type="text/css"/>
53
+
54
+ <!-- custom stuff, play arround -->
55
+ <link rel="stylesheet" href="css/design.css" type="text/css"/>
56
+ <link rel="stylesheet" href="css/stats.css" type="text/css"/>
57
+ <link rel="stylesheet" href="css/stats_standalone.css" type="text/css"/>
58
+ <script type="text/javascript" src="js/stats.js"></script>
59
+ </head>
60
+ <body is="x-ui-">
61
+ <p>
62
+ Show ready, running and stopped instances.
63
+ </p>
64
+ <template id="stats_instances">
65
+ <h1 class="stats_title">Engine: </h1>
66
+ <table class='instances'></table>
67
+ </template>
68
+ <template id="stats_instance">
69
+ <tr class="text">
70
+ <td class="name"><a href='' target='_blank'><em>no name</em></a></td>
71
+ <td class="num">(<span></span>)</td>
72
+ <td class="state"><span class='value'></span> <span class='abandon'>[<a href='#' title='abandon'>a</a>]</span></td>
73
+ <td class="author"><em>unknown</em></td>
74
+ <td class="cpu"></td>
75
+ <td>/</td>
76
+ <td class="mem"></em></td>
77
+ </tr>
78
+ <tr class="sub">
79
+ <td colspan="6"><table></table></td>
80
+ </tr>
81
+ </template>
82
+ <div id='instances'></div>
83
+ </body>
84
+ </html>
data/ui/js/design.js CHANGED
@@ -44,17 +44,17 @@ function delete_it(name) {
44
44
  }
45
45
  }
46
46
 
47
- function es_init(gdir,gstage) {
47
+ function design_init(gdir,gstage) {
48
48
  var es = new EventSource('server/');
49
49
  es.onopen = function() {
50
- console.log('es open');
50
+ console.log('design open');
51
51
  };
52
52
  es.onmessage = function(e) {
53
53
  paint(gdir,gstage);
54
54
  };
55
55
  es.onerror = function() {
56
- console.log('es error');
57
- // es_init();
56
+ console.log('design error');
57
+ // design_init();
58
58
  };
59
59
  }
60
60
 
@@ -114,7 +114,7 @@ $(document).ready(function() {
114
114
  gstage = urlParams.get('stage') || 'draft';
115
115
  gdir = urlParams.get('dir') ? (urlParams.get('dir') + '/').replace(/\/+/,'/') : '';
116
116
 
117
- es_init(gdir,gstage);
117
+ design_init(gdir,gstage);
118
118
 
119
119
  var shifts = []
120
120
  $.ajax({
data/ui/js/stats.js ADDED
@@ -0,0 +1,223 @@
1
+ var value_count = 100
2
+
3
+ function resource_update(ename) {
4
+ var iname = ename.replace(/[^a-z0-9A-Z]/g,'-').replace(/-$/,'')
5
+ $.get('server/dash/stats/',{ engine: ename },function(data){
6
+ $('#resource_utilization_text_' + iname + ' .total_created').text(data.total_created)
7
+ $('#resource_utilization_text_' + iname + ' .total_finished').text(data.total_finished)
8
+ $('#resource_utilization_text_' + iname + ' .total_abandoned').text(data.total_abandoned)
9
+ $('#resource_utilization_text_' + iname + ' .current_ready').text(data.ready)
10
+ $('#resource_utilization_text_' + iname + ' .current_running').text(data.running)
11
+ $('#resource_utilization_text_' + iname + ' .current_stopped').text(data.stopped)
12
+ });
13
+ }
14
+
15
+ function resource_add(ename) {
16
+ let inode = document.importNode($("#stats_engine")[0].content,true);
17
+ var iname = ename.replace(/[^a-z0-9A-Z]/g,'-').replace(/-$/,'')
18
+ $('.stats_title',inode).text($('.stats_title',inode).text() + ename)
19
+ $('.stats_plot',inode).attr('id','resource_utilization_plot_'+iname)
20
+ $('.stats_text',inode).attr('id','resource_utilization_text_'+iname)
21
+
22
+ $('#resources').append(inode)
23
+
24
+ resource_update(ename);
25
+
26
+ var trace1 = {
27
+ y: Array(value_count).fill(0),
28
+ type: 'scatter',
29
+ name: '% CPU'
30
+ };
31
+
32
+ var trace2 = {
33
+ y: Array(value_count).fill(0),
34
+ type: 'scatter',
35
+ name: '% Mem Used'
36
+ };
37
+
38
+ var layout = {
39
+ margin: {t:0,r:0,b:0,l:20},
40
+ height: 200,
41
+ width: 700,
42
+ yaxis: {
43
+ range: [-5, 105]
44
+ },
45
+ xaxis: {
46
+ showticklabels: false,
47
+ fixedrange: true
48
+ }
49
+ };
50
+
51
+ var data = [trace1, trace2];
52
+
53
+ Plotly.newPlot('resource_utilization_plot_' + iname, data, layout, {displayModeBar: false});
54
+ }
55
+
56
+ function instance_change(d) {
57
+ const ename = d.engine
58
+ const iname = d.engine.replace(/[^a-z0-9A-Z]/g,'-').replace(/-$/,'')
59
+
60
+ if (d.state == "ready") {
61
+ if ($('[data-id=' + d.uuid + ']').length > 0) {
62
+ if ($('[data-id=' + d.uuid + ']').attr('data-parent') != parent) {
63
+ $('[data-id=' + d.uuid + ']').remove()
64
+ instance_add(iname,d.uuid,d.url,d.name,d.state,d.author,0,0,d.parent)
65
+ } else {
66
+ instance_upd(d.uuid,d.name,d.state,d.author,0,0,d.parent)
67
+ }
68
+ } else {
69
+ instance_add(iname,d.uuid,d.url,d.name,d.state,d.author,0,0,d.parent)
70
+ }
71
+ } else if (d.state == 'abandoned' || d.state == 'finished') {
72
+ if ($('tr.sub[data-id=' + d.uuid + '] > td > table > tr').length > 0) {
73
+ $('tr.text[data-id=' + d.uuid + ']').replaceWith($('tr.sub[data-id=' + d.uuid + '] > td > table > tr'))
74
+ }
75
+ $('[data-id=' + d.uuid + ']').remove()
76
+ instances_striping(iname)
77
+ } else {
78
+ if ($('tr.sub[data-id=' + d.uuid + ']').attr('data-parent') != d.parent) {
79
+ $('[data-id=' + d.uuid + ']').remove()
80
+ instance_add(iname,d.uuid,d.url,d.name,d.state,d.author,0,0,d.parent)
81
+ } else {
82
+ instance_upd(d.uuid,d.name,d.state,d.author,0,0,d.parent)
83
+ }
84
+ }
85
+ }
86
+
87
+ function instance_upd(uuid,name,state,author,cpu,mem,parent) {
88
+ if (name != "") {
89
+ $('[data-id=' + uuid + '] > .name a').text(name)
90
+ }
91
+ $('[data-id=' + uuid + '] > .state span.value').text(state)
92
+ $('[data-id=' + uuid + '] > .state').attr('data-state',state)
93
+ if (author != "") {
94
+ $('[data-id=' + uuid + '] > .author').text(author)
95
+ }
96
+ instance_res(uuid,cpu,mem)
97
+ }
98
+ function instance_res(uuid,cpu,mem) {
99
+ $('[data-id=' + uuid + '] > .cpu').text($.sprintf('%05.2f',cpu))
100
+ $('[data-id=' + uuid + '] > .mem').text($.sprintf('%05.2f',mem))
101
+ }
102
+ function instance_add(iname,uuid,url,name,state,author,cpu,mem,parent) {
103
+ let inode = document.importNode($("#stats_instance")[0].content,true);
104
+ $('.sub',inode).attr('id',uuid)
105
+ $('.sub',inode).attr('data-id',uuid)
106
+ $('.sub',inode).attr('data-parent',parent)
107
+ $('.text',inode).attr('data-id',uuid)
108
+ $('.text',inode).attr('data-url',url)
109
+ $('.name a',inode).attr('href','server/dash/show?url=' + url)
110
+ $('.num span',inode).text(url.split(/[\\/]/).pop())
111
+ if (name != "") {
112
+ $('.name a',inode).text(name)
113
+ }
114
+ $('.state span.value',inode).text(state)
115
+ $('.state',inode).attr('data-state',state)
116
+ if (author != "") {
117
+ $('.author',inode).text(author)
118
+ }
119
+ $('.cpu',inode).text($.sprintf('%05.2f',cpu))
120
+ $('.mem',inode).text($.sprintf('%05.2f',mem))
121
+ if (parent == "") {
122
+ $('#instances_' + iname).append(inode)
123
+ } else {
124
+ $('#' + parent + ' > td > table').append(inode)
125
+ }
126
+ instances_striping(iname)
127
+ }
128
+
129
+ function instances_striping(iname) {
130
+ let even = true
131
+ $('#instances_' + iname + ' tr.text').removeClass('even')
132
+ $('#instances_' + iname + ' tr.text').each((i,e)=>{
133
+ if (even) {
134
+ $(e).addClass('even')
135
+ }
136
+ even = (even == true ? false : true)
137
+ })
138
+ }
139
+
140
+ function instances_init(ename) {
141
+ const iname = ename.replace(/[^a-z0-9A-Z]/g,'-').replace(/-$/,'')
142
+ let inode = document.importNode($("#stats_instances")[0].content,true);
143
+ $('.stats_title',inode).text($('.stats_title',inode).text() + ename)
144
+ $('table',inode).attr('id','instances_'+iname)
145
+ $('#instances').append(inode)
146
+ $.ajax({
147
+ type: "GET",
148
+ url: 'server/dash/instances',
149
+ data: { engine: ename },
150
+ success: (result) => {
151
+ $('instance',result).each((i,ele)=>{
152
+ const e = $(ele);
153
+ instance_add(iname,e.attr('uuid'),e.attr('url'),e.attr('name'),e.attr('state'),e.attr('author'),e.attr('cpu'),e.attr('mem'),e.attr('parent'))
154
+ })
155
+ }
156
+ })
157
+ }
158
+
159
+ function resource_paint(iname,data,count) {
160
+ count[iname]++
161
+ Plotly.extendTraces('resource_utilization_plot_' + iname, {y: [[data.cpu_usage], [(data.mem_total-data.mem_available)/data.mem_total * 100]]}, [0,1])
162
+ Plotly.relayout('resource_utilization_plot_' + iname, {
163
+ xaxis: {
164
+ range: [count[iname]-value_count,count[iname]],
165
+ showticklabels: false,
166
+ fixedrange: true
167
+ }
168
+ });
169
+ }
170
+
171
+ function stats_init() {
172
+ let es = new EventSource('server/dash/events/');
173
+ let count = {};
174
+ es.onopen = function() {
175
+ console.log('stats open');
176
+ };
177
+ es.onmessage = function(e) {
178
+ let data = JSON.parse(e.data)
179
+ const iname = data.engine.replace(/[^a-z0-9A-Z]/g,'-').replace(/-$/,'')
180
+ if ($('#instances').length > 0) {
181
+ if ($('#instances_' + iname).length == 0) {
182
+ instances_init(data.engine);
183
+ }
184
+ }
185
+ if (data.topic == "node" && data.event == "resource_utilization") {
186
+ if ($('#resources').length > 0) {
187
+ if ($('#resource_utilization_plot_' + iname).length == 0) {
188
+ resource_add(data.engine);
189
+ count[iname] = value_count;
190
+ }
191
+ resource_paint(iname,data,count)
192
+ }
193
+ } else if (data.topic == "state" && data.event == "change") {
194
+ if ($('#resources').length > 0) {
195
+ resource_update(data.engine)
196
+ }
197
+ if ($('#instances').length > 0) {
198
+ instance_change(data)
199
+ }
200
+ } else if (data.topic == "status" && data.event == "resource_utilization") {
201
+ if ($('#instances').length > 0) {
202
+ instance_res(data.uuid,data.cpu,data.mem)
203
+ }
204
+ } else {
205
+ console.log(data);
206
+ }
207
+ };
208
+ es.onerror = function() {
209
+ console.log('stats error');
210
+ }
211
+ }
212
+
213
+ $(document).ready(function() {
214
+ stats_init();
215
+ $('#instances').on('click','.abandon',function(e){
216
+ const par = $(e.target).parents('[data-url]').first()
217
+ $.ajax({
218
+ type: "PUT",
219
+ url: 'server/dash/abandon',
220
+ data: { url: par.attr('data-url') }
221
+ })
222
+ })
223
+ });
data/ui/resources.html ADDED
@@ -0,0 +1,91 @@
1
+ <!--
2
+ This file is part of CPEE-MODEL-MANAGEMENT.
3
+
4
+ CPEE-MODEL-MANAGEMENT is free software: you can redistribute it and/or
5
+ modify it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or (at your
7
+ option) any later version.
8
+
9
+ CPEE-MODEL-MANAGEMENT is distributed in the hope that it will be useful, but
10
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
+ more details.
13
+
14
+ You should have received a copy of the GNU General Public License along with
15
+ CPEE-MODEL-MANAGEMENT (file LICENSE in the main directory). If not, see
16
+ <http://www.gnu.org/licenses/>.
17
+ -->
18
+
19
+ <!DOCTYPE html>
20
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
21
+ <head>
22
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
23
+ <title>Resources</title>
24
+
25
+ <!-- libs, do not modify. When local than load local libs. -->
26
+ <script type="text/javascript" src="/js_libs/jquery.min.js"></script>
27
+ <script type="text/javascript" src="/js_libs/jquery.browser.js"></script>
28
+ <script type="text/javascript" src="/js_libs/jquery.svg.min.js"></script>
29
+ <script type="text/javascript" src="/js_libs/jquery.svgdom.min.js"></script>
30
+ <script type="text/javascript" src="/js_libs/vkbeautify.js"></script>
31
+ <script type="text/javascript" src="/js_libs/util.js"></script>
32
+ <script type="text/javascript" src="/js_libs/printf.js"></script>
33
+ <script type="text/javascript" src="/js_libs/strftime.min.js"></script>
34
+ <script type="text/javascript" src="/js_libs/parsequery.js"></script>
35
+ <script type="text/javascript" src="/js_libs/underscore.min.js"></script>
36
+ <script type="text/javascript" src="/js_libs/jquery.caret.min.js"></script>
37
+ <script type="text/javascript" src="/js_libs/jquery.cookie.js"></script>
38
+ <script type="text/javascript" src="/js_libs/plotly.min.js"></script>
39
+
40
+ <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
41
+
42
+ <script type="text/javascript" src="/js_libs/relaxngui.js"></script>
43
+
44
+ <script type="text/javascript" src="/js_libs/uidash.js"></script>
45
+ <script type="text/javascript" src="/js_libs/custommenu.js"></script>
46
+
47
+ <link rel="stylesheet" href="/js_libs/custommenu.css" type="text/css"/>
48
+ <link rel="stylesheet" href="/js_libs/uidash.css" type="text/css"/>
49
+
50
+ <link rel="stylesheet" href="/global_ui/ui.css" type="text/css"/>
51
+
52
+ <link rel="stylesheet" href="/js_libs/relaxngui.css" type="text/css"/>
53
+
54
+ <!-- custom stuff, play arround -->
55
+ <link rel="stylesheet" href="css/stats.css" type="text/css"/>
56
+ <link rel="stylesheet" href="css/stats_standalone.css" type="text/css"/>
57
+ <script type="text/javascript" src="js/stats.js"></script>
58
+ </head>
59
+ <body is="x-ui-">
60
+ <p>
61
+ Show statistics about instances per server, and metrics about the health of the environment.
62
+ </p>
63
+ <template id="stats_engine">
64
+ <h1 class="stats_title">Engine: </h1>
65
+ <div class="stats_plot"></div>
66
+ <div class="stats_text">
67
+ <table>
68
+ <tbody>
69
+ <tr>
70
+ <td>Total Instances <strong>Created</strong> / <strong>Finished</strong> / <strong>Abandoned</strong>:</td>
71
+ <td class='total_created'></td>
72
+ <td>/</td>
73
+ <td class='total_finished'></td>
74
+ <td>/</td>
75
+ <td class='total_abandoned'></td>
76
+ </tr>
77
+ <tr>
78
+ <td>Instances Currently <strong>Ready</strong> / <strong>Running</strong> / <strong>Stopped</strong>:</td>
79
+ <td class='current_ready'></td>
80
+ <td>/</td>
81
+ <td class='current_running'></td>
82
+ <td>/</td>
83
+ <td class='current_stopped'></td>
84
+ </tr>
85
+ </tbody>
86
+ </table>
87
+ </div>
88
+ </template>
89
+ <div id='resources'></div>
90
+ </body>
91
+ </html>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpee-model-management
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.18
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juergen eTM Mangler
8
8
  autorequire:
9
9
  bindir: tools
10
10
  cert_chain: []
11
- date: 2021-10-28 00:00:00.000000000 Z
11
+ date: 2022-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: riddl
@@ -73,6 +73,7 @@ files:
73
73
  - cpee-model-management.gemspec
74
74
  - lib/cpee-model-management/commit.rb
75
75
  - lib/cpee-model-management/implementation.rb
76
+ - lib/cpee-model-management/implementation.xml
76
77
  - lib/cpee-model-management/moma.xml
77
78
  - lib/cpee-model-management/stages
78
79
  - server/model.xml
@@ -81,8 +82,13 @@ files:
81
82
  - server/testset.xml
82
83
  - tools/cpee-moma
83
84
  - ui/css/design.css
85
+ - ui/css/stats.css
86
+ - ui/css/stats_standalone.css
84
87
  - ui/index.html
88
+ - ui/instances.html
85
89
  - ui/js/design.js
90
+ - ui/js/stats.js
91
+ - ui/resources.html
86
92
  homepage: http://cpee.org/
87
93
  licenses:
88
94
  - LGPL-3.0
@@ -102,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
108
  - !ruby/object:Gem::Version
103
109
  version: '0'
104
110
  requirements: []
105
- rubygems_version: 3.2.22
111
+ rubygems_version: 3.3.7
106
112
  signing_key:
107
113
  specification_version: 4
108
114
  summary: "(Lifecycle) manage your process models in a directory or git repo."