omf_sfa 0.1.1

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.
Files changed (152) hide show
  1. data/.gitignore +24 -0
  2. data/Gemfile +6 -0
  3. data/README.md +211 -0
  4. data/Rakefile +23 -0
  5. data/bin/parse_rspec.rb +167 -0
  6. data/etc/omf-sfa/omf-sfa-am.yaml +12 -0
  7. data/examples/exogeni5nodemanifest.rspec +105 -0
  8. data/examples/instageni5nodemanifest.rspec +150 -0
  9. data/lib/omf-sfa/am/am-rest/REST_API.md +301 -0
  10. data/lib/omf-sfa/am/am-rest/account_handler.rb +145 -0
  11. data/lib/omf-sfa/am/am-rest/am_rest_server.rb +255 -0
  12. data/lib/omf-sfa/am/am-rest/api_template.html +48 -0
  13. data/lib/omf-sfa/am/am-rest/config.ru +110 -0
  14. data/lib/omf-sfa/am/am-rest/resource_handler.rb +178 -0
  15. data/lib/omf-sfa/am/am-rest/rest_handler.rb +573 -0
  16. data/lib/omf-sfa/am/am-rest/session_authenticator.rb +130 -0
  17. data/lib/omf-sfa/am/am-rpc/abstract_rpc_service.rb +60 -0
  18. data/lib/omf-sfa/am/am-rpc/am_authorizer.rb +161 -0
  19. data/lib/omf-sfa/am/am-rpc/am_rpc_api.rb +450 -0
  20. data/lib/omf-sfa/am/am-rpc/am_rpc_service.rb +402 -0
  21. data/lib/omf-sfa/am/am_liaison.rb +93 -0
  22. data/lib/omf-sfa/am/am_manager.rb +859 -0
  23. data/lib/omf-sfa/am/am_runner.rb +108 -0
  24. data/lib/omf-sfa/am/am_scheduler.rb +146 -0
  25. data/lib/omf-sfa/am/am_server.rb +194 -0
  26. data/lib/omf-sfa/am/config.ru +122 -0
  27. data/lib/omf-sfa/am/credential.rb +145 -0
  28. data/lib/omf-sfa/am/default_authorizer.rb +44 -0
  29. data/lib/omf-sfa/am/privilege_credential.rb +76 -0
  30. data/lib/omf-sfa/am/signature.rb +37 -0
  31. data/lib/omf-sfa/am/user_credential.rb +56 -0
  32. data/lib/omf-sfa/am.rb +7 -0
  33. data/lib/omf-sfa/model/abstract_prop_description.rb +87 -0
  34. data/lib/omf-sfa/model/model_class_description.rb +145 -0
  35. data/lib/omf-sfa/model/model_data_prop_description.rb +28 -0
  36. data/lib/omf-sfa/model/model_obj_prop_description.rb +49 -0
  37. data/lib/omf-sfa/model/ontology.rb +169 -0
  38. data/lib/omf-sfa/resource/README.md +24 -0
  39. data/lib/omf-sfa/resource/channel.rb +49 -0
  40. data/lib/omf-sfa/resource/comp_group.rb +41 -0
  41. data/lib/omf-sfa/resource/component_lease.rb +10 -0
  42. data/lib/omf-sfa/resource/constants.rb +24 -0
  43. data/lib/omf-sfa/resource/group_component.rb +35 -0
  44. data/lib/omf-sfa/resource/group_membership.rb +17 -0
  45. data/lib/omf-sfa/resource/gurn.rb +187 -0
  46. data/lib/omf-sfa/resource/interface.rb +78 -0
  47. data/lib/omf-sfa/resource/ip.rb +48 -0
  48. data/lib/omf-sfa/resource/link.rb +29 -0
  49. data/lib/omf-sfa/resource/node.rb +75 -0
  50. data/lib/omf-sfa/resource/oaccount.rb +94 -0
  51. data/lib/omf-sfa/resource/ocomponent.rb +134 -0
  52. data/lib/omf-sfa/resource/ogroup.rb +106 -0
  53. data/lib/omf-sfa/resource/olease.rb +61 -0
  54. data/lib/omf-sfa/resource/oproperty.rb +178 -0
  55. data/lib/omf-sfa/resource/oreference.rb +15 -0
  56. data/lib/omf-sfa/resource/oresource.rb +491 -0
  57. data/lib/omf-sfa/resource/project.rb +28 -0
  58. data/lib/omf-sfa/resource/project_membership.rb +13 -0
  59. data/lib/omf-sfa/resource/sfa_base.rb +544 -0
  60. data/lib/omf-sfa/resource/user.rb +25 -0
  61. data/lib/omf-sfa/resource.rb +20 -0
  62. data/lib/omf-sfa/util/create_sample_testbed.rb +68 -0
  63. data/lib/omf-sfa/util/load_from_sfa_xml.rb +65 -0
  64. data/lib/omf-sfa/version.rb +4 -0
  65. data/lib/omf_sfa.rb +5 -0
  66. data/omf_sfa.gemspec +46 -0
  67. data/owl/README +3 -0
  68. data/owl/ben-6509.rdf +1377 -0
  69. data/owl/ben-dell.rdf +586 -0
  70. data/owl/ben-dtn.rdf +1698 -0
  71. data/owl/ben.rdf +1335 -0
  72. data/owl/collections.owl +309 -0
  73. data/owl/compute.owl +1486 -0
  74. data/owl/domain.owl +444 -0
  75. data/owl/dtn.owl +1165 -0
  76. data/owl/ec2.owl +385 -0
  77. data/owl/ethernet.owl +466 -0
  78. data/owl/eucalyptus.owl +431 -0
  79. data/owl/id-mp-Request1.rdf +247 -0
  80. data/owl/itu-grid.owl +147 -0
  81. data/owl/kansei.owl +511 -0
  82. data/owl/layer.owl +645 -0
  83. data/owl/location.owl +117 -0
  84. data/owl/mass.rdf +608 -0
  85. data/owl/nlr.rdf +901 -0
  86. data/owl/orca.owl +181 -0
  87. data/owl/planetlab.owl +124 -0
  88. data/owl/protogeni.owl +467 -0
  89. data/owl/request-6509-2.rdf +150 -0
  90. data/owl/request-6509-3.rdf +158 -0
  91. data/owl/request-6509.rdf +199 -0
  92. data/owl/request.owl +222 -0
  93. data/owl/storage.owl +511 -0
  94. data/owl/topology.owl +608 -0
  95. data/schema/rspec-v3/ad-common.xsd +269 -0
  96. data/schema/rspec-v3/ad-reservation.rnc +12 -0
  97. data/schema/rspec-v3/ad-reservation.rng +28 -0
  98. data/schema/rspec-v3/ad-reservation.xsd +13 -0
  99. data/schema/rspec-v3/ad.rnc +151 -0
  100. data/schema/rspec-v3/ad.xsd +77 -0
  101. data/schema/rspec-v3/any-extension-schema.xsd +38 -0
  102. data/schema/rspec-v3/any-extension.rnc +30 -0
  103. data/schema/rspec-v3/common.rnc +185 -0
  104. data/schema/rspec-v3/manifest-common.xsd +244 -0
  105. data/schema/rspec-v3/manifest-request.xsd +95 -0
  106. data/schema/rspec-v3/manifest.rnc +62 -0
  107. data/schema/rspec-v3/manifest.xsd +34 -0
  108. data/schema/rspec-v3/request-common.xsd +219 -0
  109. data/schema/rspec-v3/request-reservation.rnc +12 -0
  110. data/schema/rspec-v3/request-reservation.xsd +13 -0
  111. data/schema/rspec-v3/request.rnc +118 -0
  112. data/schema/rspec-v3/request.xsd +94 -0
  113. data/share/assets/css/default.css +147 -0
  114. data/share/assets/css/rest_api.css +0 -0
  115. data/share/assets/network.html +28 -0
  116. data/share/assets/network.js +82 -0
  117. data/spec/am/am-rest/common.rb +29 -0
  118. data/spec/am/am-rest/resource_group_handler_XspecX.rb +97 -0
  119. data/spec/am/am-rest/resource_handler_spec.rb +204 -0
  120. data/spec/am/am-rpc/sfa_methods_spec.rb +150 -0
  121. data/spec/am/am_manager_spec.rb +307 -0
  122. data/spec/am/am_scheduler_spec.rb +57 -0
  123. data/spec/am/common.rb +24 -0
  124. data/spec/resource/common.rb +31 -0
  125. data/spec/resource/node_spec.rb +171 -0
  126. data/spec/resource/oaccount_spec.rb +92 -0
  127. data/spec/resource/ocomponent_spec.rb +225 -0
  128. data/spec/resource/ogroup_spec.rb +93 -0
  129. data/spec/resource/oresource_spec.rb +208 -0
  130. data/spec/resource_and_leases_spec.rb +377 -0
  131. data/test/OLD_FILES/assertion1.xml +117 -0
  132. data/test/OLD_FILES/greeter_spec.rb +15 -0
  133. data/test/OLD_FILES/mongo_test.rb +45 -0
  134. data/test/OLD_FILES/req-sfa-2.xml +6 -0
  135. data/test/OLD_FILES/req-sfa-g.xml +8 -0
  136. data/test/OLD_FILES/req-sfa-g2.xml +10 -0
  137. data/test/OLD_FILES/req-sfa-g3.xml +14 -0
  138. data/test/OLD_FILES/req-sfa.xml +6 -0
  139. data/test/OLD_FILES/req1.xml +22 -0
  140. data/test/OLD_FILES/req1b.xml +15 -0
  141. data/test/OLD_FILES/rspec-test.xml +1867 -0
  142. data/test/OLD_FILES/test.rb +67 -0
  143. data/test/OLD_FILES/test2.rb +32 -0
  144. data/test/am/am_manager_rspec_tests.rb +378 -0
  145. data/test/am/am_manager_tests.rb +518 -0
  146. data/test/am/am_scheduler_tests.rb +173 -0
  147. data/test/resource/olease_test.rb +74 -0
  148. data/test/sfa_requests/request.xml +5 -0
  149. data/test/sfa_requests/request1.xml +5 -0
  150. data/test/sfa_requests/request2.xml +5 -0
  151. data/test/sfa_requests/request3.xml +5 -0
  152. metadata +601 -0
@@ -0,0 +1,29 @@
1
+
2
+
3
+ require 'omf-sfa/resource/channel'
4
+ #require 'omf-sfa/resource/link_property'
5
+
6
+ module OMF::SFA::Resource
7
+
8
+ # <link component_id="urn:publicid:IDN+emulab.net+link+link-pc102%3Aeth2-internet%3Aborder" component_name="link-pc102:eth2-internet:border">
9
+ # <component_manager name="urn:publicid:IDN+emulab.net+authority+cm"/>
10
+ # <interface_ref component_id="urn:publicid:IDN+emulab.net+interface+pc102:eth2"/>
11
+ # <interface_ref component_id="urn:publicid:IDN+emulab.net+interface+internet:border"/>
12
+ # <property capacity="100000" dest_id="urn:publicid:IDN+emulab.net+interface+internet:border" latency="0" packet_loss="0" source_id="urn:publicid:IDN+emulab.net+interface+pc102:eth2"/>
13
+ # <property capacity="100000" dest_id="urn:publicid:IDN+emulab.net+interface+pc102:eth2" latency="0" packet_loss="0" source_id="urn:publicid:IDN+emulab.net+interface+internet:border"/>
14
+ # <link_type name="ipv4"/>
15
+ # </link>
16
+
17
+ class Link < Channel
18
+
19
+ oproperty :link_type, String
20
+ #has 2, :interfaces
21
+
22
+ sfa_class 'link'
23
+ sfa :link_type, :content_attribute => :name
24
+ #sfa :properties, LinkProperty, :inline => true, :has_many => true
25
+
26
+ end
27
+
28
+ end # OMF::SFA::Resource
29
+
@@ -0,0 +1,75 @@
1
+
2
+ require 'omf-sfa/resource/ocomponent'
3
+ require 'omf-sfa/resource/interface'
4
+
5
+ module OMF::SFA::Resource
6
+
7
+ class Node < OComponent
8
+
9
+
10
+ oproperty :hardware_type, String, :required => false
11
+ oproperty :available, Boolean, :default => true
12
+ #oproperty :sliver_type, String, :required => false
13
+ oproperty :interfaces, :interface, :functional => false
14
+ oproperty :exclusive, Boolean, :default => true
15
+ #belongs_to :sliver
16
+
17
+ sfa_class 'node'
18
+ sfa :hardware_type, :inline => true, :has_many => true
19
+ sfa :available, :attr_value => 'now' # <available now="true">
20
+ #sfa :sliver_type, :attr_value => 'name'
21
+ sfa :interfaces, :inline => true, :has_many => true
22
+ # sfa :exclusive, :attribute => true
23
+
24
+ # Override xml serialization of 'interface'
25
+ def _to_sfa_property_xml(pname, value, res_el, pdef, obj2id, opts)
26
+ if pname == 'interfaces'
27
+ value.each do |iface|
28
+ iface.to_sfa_ref_xml(res_el, obj2id, opts)
29
+ end
30
+ return
31
+ end
32
+ super
33
+ end
34
+
35
+ def _from_sfa_interfaces_property_xml(resource_el, props, context)
36
+ resource_el.children.each do |el|
37
+ next unless el.is_a? Nokogiri::XML::Element
38
+ next unless el.name == 'interface' # should check namespace as well
39
+ unless client_id_attr = el.attributes['client_id']
40
+ raise "Expected 'client_id' attr for interface in '#{el}'"
41
+ end
42
+ client_id = client_id_attr.value
43
+ interface = self.interfaces.find do |ifs|
44
+ ifs.name == client_id
45
+ end
46
+ unless interface
47
+ # doesn't exist yet, create new one
48
+ interface = context[client_id] = Interface.new(:name => client_id)
49
+ end
50
+ interface.from_sfa(el)
51
+ interface.node = self
52
+ #puts "INTERFACE '#{interface.inspect}'"
53
+ self.interfaces << interface
54
+ end
55
+ end
56
+
57
+ def xx_to_sfa_interfaces_property_hash(interfaces, pdef, href2obj, opts)
58
+ # opts = opts.dup
59
+ # opts[:href_prefix] = (opts[:href_prefix] || '/') + 'interfaces/'
60
+ #interfaces.collect do |o|
61
+ interfaces.map do |o|
62
+ puts "INTERFACE: #{o}"
63
+ #o.to_sfa_hash(href2obj, opts)
64
+ 'hi'
65
+ end
66
+ end
67
+
68
+ before :save do
69
+ resource_type |= 'node'
70
+ end
71
+
72
+ end
73
+
74
+ end # OMF::SFA
75
+
@@ -0,0 +1,94 @@
1
+
2
+ #require 'time'
3
+ require 'omf-sfa/resource/oresource'
4
+ require 'omf-sfa/resource/ocomponent'
5
+ require 'omf-sfa/resource/project'
6
+
7
+ module OMF::SFA::Resource
8
+
9
+ # This class represents a users or team's account. Each resource
10
+ # belongs to an account.
11
+ #
12
+ class OAccount < OGroup
13
+
14
+ @@def_duration = 100 * 86400 # 100 days
15
+
16
+ def self.default_duration=(duration)
17
+ @@def_duration = duration
18
+ end
19
+
20
+ def self.urn_type
21
+ 'account'
22
+ end
23
+
24
+ oproperty :created_at, DataMapper::Property::Time
25
+ oproperty :valid_until, DataMapper::Property::Time
26
+ oproperty :closed_at, DataMapper::Property::Time
27
+
28
+
29
+ oproperty :project, :project, :inverse => :project
30
+ oproperty :active_components, :ocomponent, :functional => false, :inverse => :account
31
+ # has n, :active_components, :model => 'OResource', :child_key => [ :account_id ] #, :required => false
32
+ # belongs_to :project, :required => false
33
+
34
+ def active?
35
+ return false unless self.closed_at.nil?
36
+
37
+ valid_until = self.valid_until
38
+ unless valid_until.kind_of? Time
39
+ valid_until = Time.parse(valid_until) # seem to not be returned as Time
40
+ end
41
+ if Time.now > valid_until
42
+ self.close()
43
+ return false
44
+ end
45
+ true
46
+ end
47
+
48
+ def closed?
49
+ ! active?
50
+ end
51
+
52
+ # Close account
53
+ def close
54
+ self.closed_at = Time.now
55
+ save
56
+ end
57
+
58
+ def initialize(*args)
59
+ super
60
+ props = Hash.new
61
+ args.each do |a|
62
+ props.merge!(a)
63
+ end
64
+ self.created_at = Time.now
65
+ if self.valid_until == nil
66
+ self.valid_until = Time.now + @@def_duration
67
+ end
68
+ end
69
+
70
+ def valid_until
71
+ v = oproperty_get(:valid_until)
72
+ if v && !v.kind_of?(Time)
73
+ oproperty_set(:valid_until, v = Time.parse(v))
74
+ end
75
+ v
76
+ end
77
+
78
+ def resource_type()
79
+ 'account'
80
+ end
81
+
82
+ # def to_hash_long(h, objs, opts = {})
83
+ # super
84
+ # h[:sub_accounts] = h.delete(:resources)
85
+ # href_only = opts[:level] >= opts[:max_level]
86
+ # # h[:active_resources] = self.active_components.map do |r|
87
+ # # href_only ? r.href : r.to_hash(objs, opts)
88
+ # # end
89
+ # h
90
+ # end
91
+
92
+
93
+ end # OAccount
94
+ end # OMF::SFA::Resource
@@ -0,0 +1,134 @@
1
+
2
+ require 'omf-sfa/resource/oresource'
3
+ require 'omf-sfa/resource/ogroup'
4
+ require 'omf-sfa/resource/sfa_base'
5
+ require 'omf-sfa/resource/olease'
6
+
7
+ module OMF::SFA::Resource
8
+
9
+ # Components are resources with a management interface.
10
+ #
11
+ class OComponent < OResource
12
+
13
+ oproperty :domain, String #, readonly => true
14
+ oproperty :exclusive, DataMapper::Property::Boolean
15
+ oproperty :component_manager_gurn, OMF::SFA::Resource::GURN
16
+
17
+ # Status of component. Should be any of configuring, ready, failed, and unknown
18
+ oproperty :status, String, :default => 'unknown'
19
+
20
+ # Beside the set of 'physical' resources, most resources are actually provided
21
+ # by other resources. Currently we assume that to be a one-to-many relation and
22
+ # we maintain links in both directions (A.provides B; B.provided_by A).
23
+ #
24
+ oproperty :provides, self, :functional => false
25
+ oproperty :provided_by, self
26
+
27
+ oproperty :account, :account, :inverse => :active_components
28
+
29
+ has n, :component_leases, :child_key => [:component_id]
30
+ has n, :leases, :model => 'OLease', :through => :component_leases, :via => :lease
31
+
32
+ extend OMF::SFA::Resource::Base::ClassMethods
33
+ include OMF::SFA::Resource::Base::InstanceMethods
34
+
35
+ sfa_add_namespace :omf, 'http://schema.mytestbed.net/sfa/rspec/1'
36
+ #sfa_add_namespace :ol, 'http://nitlab.inf.uth.gr/schema/sfa/rspec/1'
37
+
38
+ sfa :component_id, :attribute => true, :prop_name => :urn # "urn:publicid:IDN+plc:cornell+node+planetlab3-dsl.cs.cornell.edu"
39
+
40
+ sfa :client_id, :attribute => true, :prop_name => :name
41
+ alias_method :client_id, :name
42
+
43
+ sfa :component_manager_id, :attribute => true, :prop_name => :component_manager_gurn # "urn:publicid:IDN+plc+authority+am"
44
+ sfa :component_name, :attribute => true # "plane
45
+ sfa :leases, :inline => true, :has_many => true
46
+
47
+ #def component_id
48
+ # res = oproperty_get(:id)
49
+ #end
50
+
51
+ def component_name
52
+ # the name property may have the full component name including domain and type
53
+ self.name.split('+')[-1]
54
+ end
55
+
56
+ def update_from_xml(modifier_el, opts)
57
+ if modifier_el.children.length > 0
58
+ warn "'update_from_xml' not implememted '#{modifier_el}'"
59
+ end
60
+ end
61
+
62
+ def create_from_xml(modifier_el, opts)
63
+ if modifier_el.children.length > 0
64
+ warn "'update_from_xml' not implememted '#{modifier_el}'"
65
+ end
66
+ end
67
+
68
+ # Return true if this is an independent component or not. Independent
69
+ # components are listed as assignable, reservable resources, while
70
+ # dependent ones are are tied to some other resource and need to
71
+ # 'stick' with their master. Interface is such an example.
72
+ #
73
+ def independent_component?
74
+ true
75
+ end
76
+
77
+ # Override xml serialization of 'leases'
78
+ def _to_sfa_property_xml(pname, value, res_el, pdef, obj2id, opts)
79
+ if pname == 'leases'
80
+ value.each do |lease|
81
+ lease.to_sfa_ref_xml(res_el, obj2id, opts)
82
+ end
83
+ return
84
+ end
85
+ super
86
+ end
87
+
88
+
89
+ def clone
90
+ clone = super
91
+ # we don't want to clone the following attributes
92
+ # from the base resource
93
+ clone.provides = []
94
+ clone.component_leases = []
95
+ clone.leases = []
96
+ clone
97
+ end
98
+
99
+ def destroy
100
+ #debug "OCOMPONENT destroy #{self}"
101
+ if !self.provides.empty?
102
+ raise OMF::SFA::AM::MissingImplementationException.new("Don't know yet how to delete resource which still provides other resources")
103
+ end
104
+ provider = self.provided_by
105
+
106
+ if provider
107
+ pa = provider.provides
108
+ pa.delete self
109
+ provider.provides = pa
110
+ # This assumes that base resources can only provide one virtual resource
111
+ # TODO: This doesn't really test if the provider is a base resource
112
+ provider.available = true
113
+ provider.save
114
+ end
115
+
116
+ self.component_leases.each do |l|
117
+ # unlink the resource with all its leases
118
+ raise "Couldn't unlink resource with lease: #{l}" unless l.destroy
119
+ end
120
+
121
+ super
122
+ end
123
+
124
+ before :save do
125
+ self.urn = GURN.create(self.name, self)
126
+ end
127
+
128
+ def destroy!
129
+ #debug "OCOMPONENT destroy! #{self}"
130
+ #destroy #no need for this. OResource.destroy! will call OComponent.destroy -> OResource.destroy
131
+ super
132
+ end
133
+ end # OComponent
134
+ end # OMF::SFA::Resource
@@ -0,0 +1,106 @@
1
+
2
+ require 'set'
3
+ require 'omf-sfa/resource/oresource'
4
+
5
+ module OMF::SFA::Resource
6
+
7
+ # Groups contain other resources including other groups
8
+ #
9
+ class OGroup < OResource
10
+ #include DataMapper::Resource
11
+ #property :id, Serial
12
+
13
+ has n, :group_memberships, :child_key => [ :group_id ]
14
+ has n, :contains_resources, OResource, :through => :group_memberships, :via => :o_resource
15
+
16
+ # Return true if this resource is a Group
17
+ def group?
18
+ true
19
+ end
20
+
21
+ # Unlink all resources within this group.
22
+ #
23
+ # Note: Maybe should trigger
24
+ # an event for those resources no longer belonging to any group
25
+ #
26
+ def empty_group
27
+ self.group_memberships.each {|m| m.destroy}
28
+ end
29
+
30
+ # Set membership to +member_a+. Removes any existing members which aren't listed
31
+ # in +member_a+.
32
+ #
33
+ def members=(member_a)
34
+ ms = member_a.to_set
35
+ self.group_memberships.each do |m|
36
+ unless ms.delete?(m.o_resource)
37
+ m.destroy # no longer member
38
+ end
39
+ end
40
+ # add remaining, new members
41
+ ms.each do |m| self.contains_resources << m end
42
+ self.contains_resources
43
+ end
44
+
45
+ def members
46
+ self.contains_resources
47
+ end
48
+
49
+ def add_members(member_a)
50
+ member_a.each do |r|
51
+ unless member?(r)
52
+ self.contains_resources << r
53
+ end
54
+ end
55
+ end
56
+
57
+ # Return true if +resource+ is a DIRECT member of this group
58
+ #
59
+ def member?(resource)
60
+ # NOTE: most likely very inefficient
61
+ self.group_memberships.first(:o_resource => resource) != nil
62
+ end
63
+
64
+ def each_resource(&block)
65
+ self.contains_resources().each &block
66
+ end
67
+
68
+ def resource_type
69
+ 'group'
70
+ end
71
+
72
+ # Add this resource and all contained to +set+.
73
+ def all_resources(set = Set.new)
74
+ set << self
75
+ self.each_resource { |r| r.all_resources(set) }
76
+ set
77
+ end
78
+
79
+ def to_hash_long(h, objs, opts = {})
80
+ super
81
+ href_only = opts[:level] >= opts[:max_level]
82
+ h[:resources] = self.contains_resources.map do |r|
83
+ href_only ? r.href : r.to_hash(objs, opts)
84
+ end
85
+ h
86
+ end
87
+
88
+ # def to_hash(objs = {}, opts = {})
89
+ # already_described = objs.key?(self)
90
+ # h = super(objs, opts)
91
+ # return h if already_described
92
+ #
93
+ # # if (prefix = opts[:href_prefix]) && ! self.name.start_with?('_')
94
+ # # opts = opts.dup
95
+ # # opts[:href_prefix] = "#{prefix}/#{self.name}"
96
+ # # end
97
+ # h[:resources] = self.contains_resources.collect do |r|
98
+ # #puts ">>> self: #{self} - child: #{r}"
99
+ # r.to_hash(objs, opts)
100
+ # end
101
+ # h
102
+ # end
103
+
104
+ end
105
+
106
+ end # OMF::SFA
@@ -0,0 +1,61 @@
1
+
2
+ require 'omf-sfa/resource/oresource'
3
+ require 'omf-sfa/resource/ocomponent'
4
+ require 'omf-sfa/resource/component_lease'
5
+
6
+ module OMF::SFA::Resource
7
+
8
+ class OLease < OResource
9
+
10
+ oproperty :valid_from, DataMapper::Property::Time
11
+ oproperty :valid_until, DataMapper::Property::Time
12
+ oproperty :status, DataMapper::Property::Enum[:pending, :accepted, :active, :past, :cancelled], :default => "pending"
13
+
14
+ has n, :component_leases, :child_key => [:lease_id]
15
+ has n, :components, :model => 'OComponent', :through => :component_leases, :via => :component
16
+
17
+ extend OMF::SFA::Resource::Base::ClassMethods
18
+ include OMF::SFA::Resource::Base::InstanceMethods
19
+
20
+ sfa_add_namespace :ol, 'http://nitlab.inf.uth.gr/schema/sfa/rspec/1'
21
+
22
+ sfa_class 'lease', :namespace => :ol
23
+ sfa :name, :attribute => true
24
+ #sfa :uuid, :attribute => true
25
+ sfa :valid_from, :attribute => true
26
+ sfa :valid_until, :attribute => true
27
+
28
+ [:pending, :accepted, :active, :past, :cancelled].each do |s|
29
+ define_method(s.to_s + '?') do
30
+ if self.status.eql?(s.to_s)
31
+ true
32
+ else
33
+ false
34
+ end
35
+ end
36
+ end
37
+
38
+ # def status
39
+ # # puts "status call"
40
+ # s = oproperty_get(:status)
41
+ # if s.nil?
42
+ # # puts "setting"
43
+ # oproperty_set(:status, "pending")
44
+ # else
45
+ # # puts "hmm"
46
+ # s
47
+ # end
48
+ # end
49
+
50
+ def to_sfa_ref_xml(res_el, obj2id, opts)
51
+ if obj2id.key?(self)
52
+ el = res_el.add_child(Nokogiri::XML::Element.new("ol:lease_ref", res_el.document))
53
+ #el.set_attribute('component_id', self.component_id.to_s)
54
+ el.set_attribute('id_ref', self.uuid.to_s)
55
+ else
56
+ self.to_sfa_xml(res_el, obj2id, opts)
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,178 @@
1
+ require 'omf-sfa/resource/oresource'
2
+ require 'json'
3
+ require 'time'
4
+
5
+ # We use the JSON serialization for Time objecs from 'json/add/core' in order to avoid
6
+ # the conflicts with the 'active_support/core_ext' which is included in 'omf_base'
7
+ # and overrides Time objects serialization. We want 'JSON.load' to return actual Time
8
+ # objects instead of Strings.
9
+ #
10
+ class Time
11
+ def to_json(*args)
12
+ {
13
+ JSON.create_id => self.class.name,
14
+ 's' => tv_sec,
15
+ 'n' => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
16
+ }.to_json(*args)
17
+ end
18
+
19
+ def self.json_create(object)
20
+ if usec = object.delete('u') # used to be tv_usec -> tv_nsec
21
+ object['n'] = usec * 1000
22
+ end
23
+ if instance_methods.include?(:tv_nsec)
24
+ at(object['s'], Rational(object['n'], 1000))
25
+ else
26
+ at(object['s'], object['n'] / 1000)
27
+ end
28
+ end
29
+ end
30
+
31
+ raise "JSON deserialisation no longer working - require 'json' early" unless JSON.load(Time.now.to_json).is_a? Time
32
+
33
+ module OMF::SFA::Resource
34
+
35
+ # Each resource will have a few properties.
36
+ #
37
+ #
38
+ class OProperty
39
+ include DataMapper::Resource
40
+ property :id, Serial
41
+
42
+ property :name, String
43
+ property :value, String # actually serialized Object
44
+
45
+ belongs_to :o_resource
46
+
47
+ module ArrayProxy
48
+ def << (val)
49
+ if @on_set_block
50
+ val = @on_set_block.call(val)
51
+ return if val.nil?
52
+ end
53
+ @oproperty << val
54
+ @on_modified_block.call(val, true) if @on_add_block
55
+ super
56
+ end
57
+
58
+ def clear()
59
+ _remove { super }
60
+ end
61
+
62
+ def delete(obj)
63
+ _remove { super }
64
+ end
65
+
66
+ def delete_at(index)
67
+ _remove { super }
68
+ end
69
+
70
+ def delete_if(&block)
71
+ _remove { super }
72
+ end
73
+
74
+ # Callback to support 'reverse' operation
75
+ def on_modified(&block)
76
+ @on_modified_block = block
77
+ end
78
+
79
+ def on_set(&block)
80
+ @on_set_block = block
81
+ end
82
+
83
+ private
84
+ def _remove(&block)
85
+ old = self.dup
86
+ r = block.call()
87
+ removed = old - self
88
+ unless removed.empty?
89
+ if @on_remove_block
90
+ removed.each {|it| @on_modified_block.call(it, false) }
91
+ end
92
+ @oproperty.value = self
93
+ end
94
+ r
95
+ end
96
+ end
97
+
98
+ def value=(val)
99
+ attribute_set(:value, JSON.generate([val]))
100
+ save
101
+ end
102
+
103
+ def value()
104
+ js = attribute_get(:value)
105
+ # http://www.ruby-lang.org/en/news/2013/02/22/json-dos-cve-2013-0269/
106
+ val = JSON.load(js)[0]
107
+ #puts "VALUE: #{js.inspect}-#{val.inspect}-#{val.class}"
108
+ if val.kind_of? Array
109
+ val.tap {|v| v.extend(ArrayProxy).instance_variable_set(:@oproperty, self) }
110
+ end
111
+ val
112
+ end
113
+
114
+ def << (val)
115
+ v = attribute_get(:value)
116
+ v = JSON.load(v)[0]
117
+ v << val
118
+ attribute_set(:value, JSON.generate([v]))
119
+ save
120
+ end
121
+
122
+ #def value()
123
+ # #puts "VALUE() @value_:'#{@value_.inspect}'"
124
+ # unless @value_
125
+ # js = attribute_get(:value)
126
+ # puts "JS #{js.inspect}"
127
+ # if js
128
+ # @value_ = JSON.parse(js)[0]
129
+ # if @value_.kind_of? Array
130
+ # @old_value_ = @value_.dup
131
+ # end
132
+ # end
133
+ # end
134
+ # #puts "VALUE()2 @value_:'#{@value_.inspect}'"
135
+ # @value_
136
+ #end
137
+
138
+ def valid?(context = :default)
139
+ self.name != nil #&& self.value != nil
140
+ end
141
+
142
+ # alias_method :_dirty_attributes, :dirty_attributes
143
+ # def dirty_attributes
144
+ # dirty = _dirty_attributes
145
+ # #puts "DIRTY ATTRIBUTE #{dirty.inspect}"
146
+ # dirty
147
+ # end
148
+
149
+ alias_method :_dirty_self?, :dirty_self?
150
+ def dirty_self?
151
+ #puts "#{object_id} DIRTY CHECK #{@value_dirty}"
152
+ return true if @value_dirty || _dirty_self?
153
+ if @old_value_
154
+ return @old_value_ != @value_
155
+ end
156
+ false
157
+ end
158
+
159
+ def to_s()
160
+ super() + " - name: #{self.name} value: #{self.value}"
161
+ end
162
+
163
+ #before :save do
164
+ # #puts "SAVING BEFORE @value_dirty:'#{@value_dirty}', @old_value_:'#{@old_value_}', @value_:'#{@value_}'"
165
+ # begin
166
+ # if @value_dirty || (@old_value_ ? @old_value_ != @value_ : false)
167
+ # attribute_set(:value, JSON.generate([@value_]))
168
+ # @value_dirty = false
169
+ # end
170
+ # rescue Exception => ex
171
+ # puts ">>>>>>>>> ERROR #{ex}"
172
+ # end
173
+ # #puts "SAVING AFTER @value_dirty:'#{@value_dirty}', @old_value_:'#{@old_value_}', @value_:'#{@value_}'"
174
+ #end
175
+
176
+ end # OProperty
177
+
178
+ end # OMF::SFA::Resource
@@ -0,0 +1,15 @@
1
+
2
+ require 'omf-sfa/resource/oresource'
3
+
4
+ module OMF::SFA::Resource
5
+
6
+ # A reference to a resource held somewhere else.
7
+ #
8
+ class OReference < OResource
9
+ oproperty :href, String
10
+
11
+ def to_hash(objs = {}, opts = {})
12
+ self.href()
13
+ end
14
+ end
15
+ end