cpee-model-management 1.0.18 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/cpee-model-management.gemspec +1 -1
- data/lib/cpee-model-management/implementation.rb +275 -21
- data/lib/cpee-model-management/implementation.xml +133 -0
- data/lib/cpee-model-management/moma.xml +19 -98
- data/server/moma.conf +1 -0
- data/ui/css/design.css +5 -0
- data/ui/css/stats.css +55 -0
- data/ui/css/stats_standalone.css +7 -0
- data/ui/index.html +69 -10
- data/ui/instances.html +84 -0
- data/ui/js/design.js +5 -5
- data/ui/js/stats.js +223 -0
- data/ui/resources.html +91 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2407951bdeabf8fad81810a6c56b3ce1f8a28d17e583d6c32207424cdc11334a
|
4
|
+
data.tar.gz: 9286ff4e9aa86127c7ce19ab0bd0da71b596b6ef035a99b48bea5bc4e85f1383
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27df5a985c2441e656cfaefcb72377bbf720d04fe21c49fb9866c2b1b42d314af515f3dba981e8afb4fb616d2a9cdc897af8fd048d7547f57cfac594cac0ab1c
|
7
|
+
data.tar.gz: 076150342b2320ac0103a245f2162e7c03450970c9d078cd1446b1f400996dea35f4350a0aacbeed696344d3d996337531e7a25daa42ab9e755b3c8687ef05cb
|
@@ -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
|
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[:
|
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
|
-
|
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[:
|
628
|
-
run Create, :main, :dup, opts[:views], opts[:
|
629
|
-
run CreateDir, opts[:
|
630
|
-
run
|
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[:
|
634
|
-
run Create, :sub, :dup, opts[:views], opts[:
|
635
|
-
run DeleteDir, opts[:
|
636
|
-
run RenameDir, opts[:
|
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[:
|
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[:
|
641
|
-
run RenameItem, :sub, opts[:
|
642
|
-
run MoveItem, :sub, opts[:
|
643
|
-
run ShiftItem, :sub, opts[:
|
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[:
|
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[:
|
656
|
-
run RenameItem, :main, opts[:
|
657
|
-
run MoveItem, :main, opts[:
|
658
|
-
run ShiftItem, :main, opts[:
|
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öäüÖÄÜ _-]+\.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öäüÖÄÜ _-]+\.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öäüÖÄÜ _-]+\.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
|
-
<
|
2
|
-
<
|
3
|
-
<
|
4
|
-
|
5
|
-
|
6
|
-
<
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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öäüÖÄÜ _-]+\.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öäüÖÄÜ _-]+\.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öäüÖÄÜ _-]+\.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
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
|
+
}
|
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
|
61
|
-
<ui-tab class="" data-tab="models"
|
62
|
-
<ui-tab class="inactive" data-tab="newmodel">New Model</ui-tab>
|
63
|
-
<ui-tab class="inactive" data-tab="newdir"
|
64
|
-
<ui-space
|
65
|
-
<ui-tab class="inactive" data-tab="
|
66
|
-
<ui-tab class="inactive" data-tab="
|
67
|
-
<ui-behind
|
68
|
-
<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
|
-
</
|
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
|
47
|
+
function design_init(gdir,gstage) {
|
48
48
|
var es = new EventSource('server/');
|
49
49
|
es.onopen = function() {
|
50
|
-
console.log('
|
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('
|
57
|
-
//
|
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
|
-
|
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
|
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:
|
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.
|
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."
|