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.
- data/.gitignore +24 -0
- data/Gemfile +6 -0
- data/README.md +211 -0
- data/Rakefile +23 -0
- data/bin/parse_rspec.rb +167 -0
- data/etc/omf-sfa/omf-sfa-am.yaml +12 -0
- data/examples/exogeni5nodemanifest.rspec +105 -0
- data/examples/instageni5nodemanifest.rspec +150 -0
- data/lib/omf-sfa/am/am-rest/REST_API.md +301 -0
- data/lib/omf-sfa/am/am-rest/account_handler.rb +145 -0
- data/lib/omf-sfa/am/am-rest/am_rest_server.rb +255 -0
- data/lib/omf-sfa/am/am-rest/api_template.html +48 -0
- data/lib/omf-sfa/am/am-rest/config.ru +110 -0
- data/lib/omf-sfa/am/am-rest/resource_handler.rb +178 -0
- data/lib/omf-sfa/am/am-rest/rest_handler.rb +573 -0
- data/lib/omf-sfa/am/am-rest/session_authenticator.rb +130 -0
- data/lib/omf-sfa/am/am-rpc/abstract_rpc_service.rb +60 -0
- data/lib/omf-sfa/am/am-rpc/am_authorizer.rb +161 -0
- data/lib/omf-sfa/am/am-rpc/am_rpc_api.rb +450 -0
- data/lib/omf-sfa/am/am-rpc/am_rpc_service.rb +402 -0
- data/lib/omf-sfa/am/am_liaison.rb +93 -0
- data/lib/omf-sfa/am/am_manager.rb +859 -0
- data/lib/omf-sfa/am/am_runner.rb +108 -0
- data/lib/omf-sfa/am/am_scheduler.rb +146 -0
- data/lib/omf-sfa/am/am_server.rb +194 -0
- data/lib/omf-sfa/am/config.ru +122 -0
- data/lib/omf-sfa/am/credential.rb +145 -0
- data/lib/omf-sfa/am/default_authorizer.rb +44 -0
- data/lib/omf-sfa/am/privilege_credential.rb +76 -0
- data/lib/omf-sfa/am/signature.rb +37 -0
- data/lib/omf-sfa/am/user_credential.rb +56 -0
- data/lib/omf-sfa/am.rb +7 -0
- data/lib/omf-sfa/model/abstract_prop_description.rb +87 -0
- data/lib/omf-sfa/model/model_class_description.rb +145 -0
- data/lib/omf-sfa/model/model_data_prop_description.rb +28 -0
- data/lib/omf-sfa/model/model_obj_prop_description.rb +49 -0
- data/lib/omf-sfa/model/ontology.rb +169 -0
- data/lib/omf-sfa/resource/README.md +24 -0
- data/lib/omf-sfa/resource/channel.rb +49 -0
- data/lib/omf-sfa/resource/comp_group.rb +41 -0
- data/lib/omf-sfa/resource/component_lease.rb +10 -0
- data/lib/omf-sfa/resource/constants.rb +24 -0
- data/lib/omf-sfa/resource/group_component.rb +35 -0
- data/lib/omf-sfa/resource/group_membership.rb +17 -0
- data/lib/omf-sfa/resource/gurn.rb +187 -0
- data/lib/omf-sfa/resource/interface.rb +78 -0
- data/lib/omf-sfa/resource/ip.rb +48 -0
- data/lib/omf-sfa/resource/link.rb +29 -0
- data/lib/omf-sfa/resource/node.rb +75 -0
- data/lib/omf-sfa/resource/oaccount.rb +94 -0
- data/lib/omf-sfa/resource/ocomponent.rb +134 -0
- data/lib/omf-sfa/resource/ogroup.rb +106 -0
- data/lib/omf-sfa/resource/olease.rb +61 -0
- data/lib/omf-sfa/resource/oproperty.rb +178 -0
- data/lib/omf-sfa/resource/oreference.rb +15 -0
- data/lib/omf-sfa/resource/oresource.rb +491 -0
- data/lib/omf-sfa/resource/project.rb +28 -0
- data/lib/omf-sfa/resource/project_membership.rb +13 -0
- data/lib/omf-sfa/resource/sfa_base.rb +544 -0
- data/lib/omf-sfa/resource/user.rb +25 -0
- data/lib/omf-sfa/resource.rb +20 -0
- data/lib/omf-sfa/util/create_sample_testbed.rb +68 -0
- data/lib/omf-sfa/util/load_from_sfa_xml.rb +65 -0
- data/lib/omf-sfa/version.rb +4 -0
- data/lib/omf_sfa.rb +5 -0
- data/omf_sfa.gemspec +46 -0
- data/owl/README +3 -0
- data/owl/ben-6509.rdf +1377 -0
- data/owl/ben-dell.rdf +586 -0
- data/owl/ben-dtn.rdf +1698 -0
- data/owl/ben.rdf +1335 -0
- data/owl/collections.owl +309 -0
- data/owl/compute.owl +1486 -0
- data/owl/domain.owl +444 -0
- data/owl/dtn.owl +1165 -0
- data/owl/ec2.owl +385 -0
- data/owl/ethernet.owl +466 -0
- data/owl/eucalyptus.owl +431 -0
- data/owl/id-mp-Request1.rdf +247 -0
- data/owl/itu-grid.owl +147 -0
- data/owl/kansei.owl +511 -0
- data/owl/layer.owl +645 -0
- data/owl/location.owl +117 -0
- data/owl/mass.rdf +608 -0
- data/owl/nlr.rdf +901 -0
- data/owl/orca.owl +181 -0
- data/owl/planetlab.owl +124 -0
- data/owl/protogeni.owl +467 -0
- data/owl/request-6509-2.rdf +150 -0
- data/owl/request-6509-3.rdf +158 -0
- data/owl/request-6509.rdf +199 -0
- data/owl/request.owl +222 -0
- data/owl/storage.owl +511 -0
- data/owl/topology.owl +608 -0
- data/schema/rspec-v3/ad-common.xsd +269 -0
- data/schema/rspec-v3/ad-reservation.rnc +12 -0
- data/schema/rspec-v3/ad-reservation.rng +28 -0
- data/schema/rspec-v3/ad-reservation.xsd +13 -0
- data/schema/rspec-v3/ad.rnc +151 -0
- data/schema/rspec-v3/ad.xsd +77 -0
- data/schema/rspec-v3/any-extension-schema.xsd +38 -0
- data/schema/rspec-v3/any-extension.rnc +30 -0
- data/schema/rspec-v3/common.rnc +185 -0
- data/schema/rspec-v3/manifest-common.xsd +244 -0
- data/schema/rspec-v3/manifest-request.xsd +95 -0
- data/schema/rspec-v3/manifest.rnc +62 -0
- data/schema/rspec-v3/manifest.xsd +34 -0
- data/schema/rspec-v3/request-common.xsd +219 -0
- data/schema/rspec-v3/request-reservation.rnc +12 -0
- data/schema/rspec-v3/request-reservation.xsd +13 -0
- data/schema/rspec-v3/request.rnc +118 -0
- data/schema/rspec-v3/request.xsd +94 -0
- data/share/assets/css/default.css +147 -0
- data/share/assets/css/rest_api.css +0 -0
- data/share/assets/network.html +28 -0
- data/share/assets/network.js +82 -0
- data/spec/am/am-rest/common.rb +29 -0
- data/spec/am/am-rest/resource_group_handler_XspecX.rb +97 -0
- data/spec/am/am-rest/resource_handler_spec.rb +204 -0
- data/spec/am/am-rpc/sfa_methods_spec.rb +150 -0
- data/spec/am/am_manager_spec.rb +307 -0
- data/spec/am/am_scheduler_spec.rb +57 -0
- data/spec/am/common.rb +24 -0
- data/spec/resource/common.rb +31 -0
- data/spec/resource/node_spec.rb +171 -0
- data/spec/resource/oaccount_spec.rb +92 -0
- data/spec/resource/ocomponent_spec.rb +225 -0
- data/spec/resource/ogroup_spec.rb +93 -0
- data/spec/resource/oresource_spec.rb +208 -0
- data/spec/resource_and_leases_spec.rb +377 -0
- data/test/OLD_FILES/assertion1.xml +117 -0
- data/test/OLD_FILES/greeter_spec.rb +15 -0
- data/test/OLD_FILES/mongo_test.rb +45 -0
- data/test/OLD_FILES/req-sfa-2.xml +6 -0
- data/test/OLD_FILES/req-sfa-g.xml +8 -0
- data/test/OLD_FILES/req-sfa-g2.xml +10 -0
- data/test/OLD_FILES/req-sfa-g3.xml +14 -0
- data/test/OLD_FILES/req-sfa.xml +6 -0
- data/test/OLD_FILES/req1.xml +22 -0
- data/test/OLD_FILES/req1b.xml +15 -0
- data/test/OLD_FILES/rspec-test.xml +1867 -0
- data/test/OLD_FILES/test.rb +67 -0
- data/test/OLD_FILES/test2.rb +32 -0
- data/test/am/am_manager_rspec_tests.rb +378 -0
- data/test/am/am_manager_tests.rb +518 -0
- data/test/am/am_scheduler_tests.rb +173 -0
- data/test/resource/olease_test.rb +74 -0
- data/test/sfa_requests/request.xml +5 -0
- data/test/sfa_requests/request1.xml +5 -0
- data/test/sfa_requests/request2.xml +5 -0
- data/test/sfa_requests/request3.xml +5 -0
- 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
|