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,169 @@
|
|
|
1
|
+
|
|
2
|
+
# This file is parsing OWL and RDF files and is generating data
|
|
3
|
+
# modesl from it.
|
|
4
|
+
#
|
|
5
|
+
require 'nokogiri'
|
|
6
|
+
require "omf_common/lobject"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
module OMF; module SFA; end end
|
|
10
|
+
|
|
11
|
+
require 'omf-sfa/model/model_class_description'
|
|
12
|
+
require 'omf-sfa/model/model_obj_prop_description'
|
|
13
|
+
require 'omf-sfa/model/model_data_prop_description'
|
|
14
|
+
|
|
15
|
+
module OMF::SFA
|
|
16
|
+
module Model
|
|
17
|
+
|
|
18
|
+
OWL_NS = "http://www.w3.org/2002/07/owl#"
|
|
19
|
+
RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# Return a fully qualified name. Specifically, if +name+
|
|
23
|
+
# starts with '#', the default namespace of +context_el+ is
|
|
24
|
+
# going to prepended.
|
|
25
|
+
#
|
|
26
|
+
def xml_full_name(name, context_el)
|
|
27
|
+
if name.start_with? '#'
|
|
28
|
+
name = context_el.namespaces["xmlns"] + name
|
|
29
|
+
name.gsub!('##', '#') # remove '##' if ns also ends in '#'
|
|
30
|
+
end
|
|
31
|
+
name
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class Ontology < OMF::Base::LObject
|
|
35
|
+
|
|
36
|
+
# URL prefix which we serve from local directory
|
|
37
|
+
LOCAL_PREFIX = 'http://geni-orca.renci.org/owl/'
|
|
38
|
+
LOCAL_DIR = "#{File.dirname(__FILE__)}/../../../owl/"
|
|
39
|
+
|
|
40
|
+
@@uri2inst = {}
|
|
41
|
+
|
|
42
|
+
def self.import(uri)
|
|
43
|
+
unless onto = @@uri2inst[uri]
|
|
44
|
+
info "Loading ontology '#{uri}'"
|
|
45
|
+
if uri.kind_of?(String) && uri.start_with?(LOCAL_PREFIX)
|
|
46
|
+
file_name = uri.gsub(LOCAL_PREFIX, LOCAL_DIR)
|
|
47
|
+
begin
|
|
48
|
+
onto = @@uri2inst[uri] = self.new(file_name, true)
|
|
49
|
+
rescue Errno::ENOENT
|
|
50
|
+
puts ">>>> Unknown ontology '#{uri}'"
|
|
51
|
+
end
|
|
52
|
+
else
|
|
53
|
+
raise "don't know how to import '#{uri}'"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
onto
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def initialize(uri, is_file = false)
|
|
60
|
+
@uri = uri
|
|
61
|
+
if is_file
|
|
62
|
+
f = File.open(uri)
|
|
63
|
+
@doc = Nokogiri::XML(f) do |config|
|
|
64
|
+
config.strict.noent.noblanks
|
|
65
|
+
end
|
|
66
|
+
f.close
|
|
67
|
+
else
|
|
68
|
+
raise "don't know how to import '#{uri}'"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
parse()
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def parse()
|
|
75
|
+
def_ns = @doc.namespaces["xmlns"]
|
|
76
|
+
|
|
77
|
+
@doc.root.children.each do |el|
|
|
78
|
+
case el.node_name
|
|
79
|
+
when 'Ontology'
|
|
80
|
+
parse_onotology(el)
|
|
81
|
+
when 'Class'
|
|
82
|
+
ModelClassDescription.create_from_xml(el)
|
|
83
|
+
when 'comment'
|
|
84
|
+
# ignore
|
|
85
|
+
when 'ObjectProperty'
|
|
86
|
+
ModelObjectPropertyDescription.create_from_xml(el)
|
|
87
|
+
when 'DatatypeProperty'
|
|
88
|
+
ModelDataPropertyDescription.create_from_xml(el)
|
|
89
|
+
when 'AnnotationProperty'
|
|
90
|
+
# ignore
|
|
91
|
+
else
|
|
92
|
+
warn "Unknown element '#{el.node_name}' in '#{@uri}'"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# @doc.xpath('//owl:Class', 'owl' => OWL_NS).each do |cel|
|
|
98
|
+
# debug ModelClassDescription.create_from_xml(cel)
|
|
99
|
+
# #debug c.attribute_with_ns('about', RDF_NS)
|
|
100
|
+
# #debug c.namespaces["xmlns"].inspect #def_ns
|
|
101
|
+
# #debug c.inspect
|
|
102
|
+
# #exit
|
|
103
|
+
# end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
# <owl:Ontology rdf:about="">
|
|
109
|
+
# <rdfs:label rdf:datatype="&xsd;string"
|
|
110
|
+
# >Collections v. 1.2</rdfs:label>
|
|
111
|
+
# <owl:versionInfo rdf:datatype="&xsd;string">1.2</owl:versionInfo>
|
|
112
|
+
# <dc:date rdf:datatype="&xsd;string"
|
|
113
|
+
# >January 14, 2009</dc:date>
|
|
114
|
+
# <dc:contributor rdf:datatype="&xsd;string">Marco Ocana</dc:contributor>
|
|
115
|
+
# <dc:contributor rdf:datatype="&xsd;string">Paolo Ciccarese</dc:contributor>
|
|
116
|
+
# <dc:format rdf:datatype="&xsd;string">rdf/xml</dc:format>
|
|
117
|
+
# <dc:language>en</dc:language>
|
|
118
|
+
# <dc:title xml:lang="en"
|
|
119
|
+
# >Collections ontology</dc:title>
|
|
120
|
+
# </owl:Ontology>
|
|
121
|
+
#
|
|
122
|
+
|
|
123
|
+
def parse_onotology(el)
|
|
124
|
+
el.children.each do |el|
|
|
125
|
+
case el.node_name
|
|
126
|
+
when 'imports'
|
|
127
|
+
res = el.attribute_with_ns('resource', RDF_NS)
|
|
128
|
+
self.class.import(res.value)
|
|
129
|
+
else
|
|
130
|
+
#warn "Unknown eleement '#{el.node_name}' in 'owl:Ontology'"
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end # Model
|
|
137
|
+
end # OMF::SFA
|
|
138
|
+
|
|
139
|
+
if $0 == __FILE__
|
|
140
|
+
OMF::Base::Loggable.init_log 'owl'
|
|
141
|
+
include OMF::SFA::Model
|
|
142
|
+
|
|
143
|
+
#f = "#{File.dirname(__FILE__)}/../../../owl/topology.owl"
|
|
144
|
+
|
|
145
|
+
['topology', 'domain', 'storage', 'compute'].each do |o|
|
|
146
|
+
u = "http://geni-orca.renci.org/owl/#{o}.owl"
|
|
147
|
+
Ontology.import(u)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
AbstractPropertyDescription.each do |p|
|
|
151
|
+
p.validate
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
ModelClassDescription.each do |c|
|
|
155
|
+
c.validate
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
roots = ModelClassDescription.models.select do |c|
|
|
159
|
+
c.superklass.nil?
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
roots.each do |c|
|
|
163
|
+
c.describe
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
@startuml
|
|
2
|
+
hide members
|
|
3
|
+
|
|
4
|
+
OResource <|-- OComponent
|
|
5
|
+
OResource <|-- OGroup
|
|
6
|
+
OGroup <|-- OAccount
|
|
7
|
+
OResource <|-- OLease
|
|
8
|
+
OResource <|-- OProject
|
|
9
|
+
OResource <|-- User
|
|
10
|
+
@enduml
|
|
11
|
+
|
|
12
|
+
@startuml
|
|
13
|
+
hide members
|
|
14
|
+
|
|
15
|
+
OGroup "*" -- "*" OComponent : contains >
|
|
16
|
+
OGroup "1" -- "*" OGroup : contains >
|
|
17
|
+
OComponent "*" -- "1" OAccount : charged_to >
|
|
18
|
+
OComponent "1" -- "*" OComponent : provided_by >
|
|
19
|
+
OLease "*" -- "0,1" OComponent: < leased_by
|
|
20
|
+
OProject "1" -- "1" OAccount : account >
|
|
21
|
+
OProject "*" -- "*" User: member >
|
|
22
|
+
OAccount "*" -- "1" OLease : holds_lease >
|
|
23
|
+
OProject "*" -- "1" OProject: parent_project >
|
|
24
|
+
@enduml
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
require 'omf-sfa/resource/ocomponent'
|
|
3
|
+
|
|
4
|
+
module OMF::SFA::Resource
|
|
5
|
+
|
|
6
|
+
class Channel < OComponent
|
|
7
|
+
|
|
8
|
+
oproperty :interface, :interface, :functional => false
|
|
9
|
+
oproperty :number, Integer
|
|
10
|
+
oproperty :frequency, String
|
|
11
|
+
|
|
12
|
+
# we have already added that in olease
|
|
13
|
+
#sfa_add_namespace :ol, 'http://nitlab.inf.uth.gr/schema/sfa/rspec/1'
|
|
14
|
+
|
|
15
|
+
sfa_class 'channel', :namespace => :ol
|
|
16
|
+
sfa :number, :attribute => true
|
|
17
|
+
sfa :frequency, :attribute => true
|
|
18
|
+
sfa :interfaces, :inline => true, :has_many => true
|
|
19
|
+
|
|
20
|
+
def _from_sfa_interfaces_property_xml(resource_el, props, context)
|
|
21
|
+
resource_el.children.each do |el|
|
|
22
|
+
next unless el.is_a? Nokogiri::XML::Element
|
|
23
|
+
next unless el.name == 'interface_ref' # should check namespace as well
|
|
24
|
+
|
|
25
|
+
unless client_id_attr = el.attributes['client_id']
|
|
26
|
+
raise "Expected 'client_id' attr in '#{el}'"
|
|
27
|
+
end
|
|
28
|
+
unless interface = context[client_id_attr.value]
|
|
29
|
+
raise "Referencing unknown interface '#{client_id_attr.value} in '#{el}'"
|
|
30
|
+
end
|
|
31
|
+
#puts "INTERFACE '#{client_id_attr.value}' => '#{interface}'"
|
|
32
|
+
self.interfaces << interface
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Override xml serialization of 'interface'
|
|
37
|
+
def _to_sfa_property_xml(pname, value, res_el, pdef, obj2id, opts)
|
|
38
|
+
if pname == 'interfaces'
|
|
39
|
+
value.each do |iface|
|
|
40
|
+
iface.to_sfa_ref_xml(res_el, obj2id, opts)
|
|
41
|
+
end
|
|
42
|
+
return
|
|
43
|
+
end
|
|
44
|
+
super
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end # OMF::SFA
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
require 'omf-sfa/resource/ogroup'
|
|
4
|
+
require 'omf-sfa/resource/sfa_base'
|
|
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
|
+
# This class defines a group of resources which can be described through
|
|
18
|
+
# an extension of RSpec
|
|
19
|
+
#
|
|
20
|
+
class CompGroup < OGroup
|
|
21
|
+
extend OMF::SFA::Resource::Base::ClassMethods
|
|
22
|
+
include OMF::SFA::Resource::Base::InstanceMethods
|
|
23
|
+
|
|
24
|
+
sfa_class 'omf:group'
|
|
25
|
+
|
|
26
|
+
sfa :component_id, :attribute => true # "urn:publicid:IDN+plc:cornell+node+planetlab3-dsl.cs.cornell.edu"
|
|
27
|
+
sfa :component_manager_id, :attribute => true # "urn:publicid:IDN+plc+authority+am"
|
|
28
|
+
sfa :component_name, :attribute => true # "plane
|
|
29
|
+
|
|
30
|
+
def to_sfa_xml(parent, obj2id = {}, opts = {})
|
|
31
|
+
gel = _to_sfa_xml(parent, obj2id, opts)
|
|
32
|
+
self.each_resource do |r|
|
|
33
|
+
puts "CHILD #{r}"
|
|
34
|
+
r.to_sfa_xml(gel, obj2id, opts)
|
|
35
|
+
end
|
|
36
|
+
parent
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end # OMF::SFA::Resource
|
|
41
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
module OMF::SFA::Resource
|
|
3
|
+
module Constants
|
|
4
|
+
|
|
5
|
+
@@default_domain = "omf:nitos"
|
|
6
|
+
@@default_component_manager_id = GURN.create("authority+am").to_s
|
|
7
|
+
|
|
8
|
+
def self.default_domain=(dname)
|
|
9
|
+
@@default_domain = dname
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.default_domain()
|
|
13
|
+
@@default_domain
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.default_component_manager_id=(gurn)
|
|
17
|
+
@@default_component_manager_id = GURN.create(gurn).to_s
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.default_component_manager_id()
|
|
21
|
+
@@default_component_manager_id
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'omf-sfa/resource/ogroup'
|
|
2
|
+
require 'omf-sfa/resource/sfa_base'
|
|
3
|
+
|
|
4
|
+
module OMF::SFA::Resource
|
|
5
|
+
|
|
6
|
+
# A +GroupComponent+ is a group with a component interface. This allows it
|
|
7
|
+
# to be addressed and used in an SFA context.
|
|
8
|
+
#
|
|
9
|
+
class GroupComponent < OGroup
|
|
10
|
+
extend OMF::SFA::Resource::Base::ClassMethods
|
|
11
|
+
include OMF::SFA::Resource::Base::InstanceMethods
|
|
12
|
+
|
|
13
|
+
sfa_class 'group'
|
|
14
|
+
sfa :component_id, :attribute => true # "urn:publicid:IDN+plc:cornell+node+planetlab3-dsl.cs.cornell.edu"
|
|
15
|
+
sfa :component_manager_id, :attribute => true # "urn:publicid:IDN+plc+authority+am"
|
|
16
|
+
sfa :component_name, :attribute => true # "plane
|
|
17
|
+
|
|
18
|
+
sfa :components, :has_many => true, :include_level => 0 # only include components when top group
|
|
19
|
+
|
|
20
|
+
def components
|
|
21
|
+
self.contains_resources
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def _to_sfa_components_property_hash(resources, pdef, href2obj, opts)
|
|
25
|
+
opts = opts.dup
|
|
26
|
+
# TODO: What was that used for? Does this assume that prefix include slice name?
|
|
27
|
+
#opts[:href_prefix] = (opts[:href_prefix] || '/') + 'resources/'
|
|
28
|
+
resources.collect do |o|
|
|
29
|
+
o.to_sfa_hash(href2obj, opts)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end # OMF::SFA::Resource
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
module OMF::SFA::Resource
|
|
4
|
+
|
|
5
|
+
# Provides a many-to-many relationship
|
|
6
|
+
# between resources and groups
|
|
7
|
+
#
|
|
8
|
+
class GroupMembership
|
|
9
|
+
include DataMapper::Resource
|
|
10
|
+
|
|
11
|
+
belongs_to :o_resource
|
|
12
|
+
belongs_to :o_group
|
|
13
|
+
#has n, :groups
|
|
14
|
+
|
|
15
|
+
property :id, Serial
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
|
|
2
|
+
require 'omf_base/lobject'
|
|
3
|
+
|
|
4
|
+
module OMF::SFA::Resource
|
|
5
|
+
#
|
|
6
|
+
class GURN #< OMF::Base::MObject
|
|
7
|
+
|
|
8
|
+
@@def_domain = 'omf:nitos'
|
|
9
|
+
@@name2obj = {}
|
|
10
|
+
|
|
11
|
+
# Create a GURN
|
|
12
|
+
#
|
|
13
|
+
# @param [String] name Name of GURN
|
|
14
|
+
# @param [Hash] opts options to further describe GURN components
|
|
15
|
+
# @option opts [String] :type GURN's type
|
|
16
|
+
# @option opts [Class] :model Class responding to either :sfa_class or :urn_type
|
|
17
|
+
# @option opts [String] :domain GURN's domain
|
|
18
|
+
#
|
|
19
|
+
def self.create(name, opts = {})
|
|
20
|
+
return name if name.kind_of? self
|
|
21
|
+
#puts "GUID: #{name}###{opts}"
|
|
22
|
+
|
|
23
|
+
obj = @@name2obj[name]
|
|
24
|
+
return obj if obj
|
|
25
|
+
|
|
26
|
+
if name.start_with?('urn')
|
|
27
|
+
return parse(name)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
unless type = opts[:type]
|
|
31
|
+
model = opts[:model]
|
|
32
|
+
if model && model.respond_to?(:sfa_class)
|
|
33
|
+
type = model.sfa_class
|
|
34
|
+
elsif model && model.respond_to?(:resource_type)
|
|
35
|
+
type = model.resource_type
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
domain = opts[:domain] || @@def_domain
|
|
39
|
+
return @@name2obj[name] = self.new(name, type, domain)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.sfa_create(name, context = nil)
|
|
43
|
+
return create(name, :model => context)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Create a GURN object from +urn_str+.
|
|
47
|
+
#
|
|
48
|
+
def self.parse(urn_str)
|
|
49
|
+
if urn_str.start_with? 'urn:publicid:IDN'
|
|
50
|
+
a = urn_str.split('+')
|
|
51
|
+
a.delete_at(0) # get rid of "urn:publicid:IDN"
|
|
52
|
+
if a.length == 3
|
|
53
|
+
prefix, type, name = a
|
|
54
|
+
elsif a.length == 2
|
|
55
|
+
prefix, name = a
|
|
56
|
+
type = nil
|
|
57
|
+
else
|
|
58
|
+
raise "unknown format '#{urn_str}' for GURN (#{a.inspect})."
|
|
59
|
+
end
|
|
60
|
+
@@name2obj[urn_str] = self.new(name, type, prefix)
|
|
61
|
+
else
|
|
62
|
+
raise "unknown format '#{urn_str}' for GURN - expected it to start with 'urn:publicid:IDN'."
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def self.default_domain=(domain)
|
|
67
|
+
@@def_domain = domain
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.default_domain()
|
|
71
|
+
@@def_domain
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# This class maintains a cache between object name and it's GURN.
|
|
75
|
+
# As this may get in the way of testing, this method provides a way
|
|
76
|
+
# of clear that cache
|
|
77
|
+
#
|
|
78
|
+
def self.clear_cache
|
|
79
|
+
@@name2obj.clear
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
attr_reader :name, :short_name, :type, :domain, :urn
|
|
83
|
+
|
|
84
|
+
def initialize(short_name, type = nil, domain = nil)
|
|
85
|
+
@short_name = short_name
|
|
86
|
+
@domain = domain || @@def_domain
|
|
87
|
+
if type
|
|
88
|
+
@type = type
|
|
89
|
+
@name = "#{@domain}+#{type}+#{short_name}"
|
|
90
|
+
else
|
|
91
|
+
@name = "#{@domain}+#{short_name}"
|
|
92
|
+
end
|
|
93
|
+
@urn = 'urn:publicid:IDN+' + name
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def uuid
|
|
97
|
+
unless @uuid
|
|
98
|
+
@uuid = UUIDTools::UUID.parse(short_name)
|
|
99
|
+
end
|
|
100
|
+
@uuid
|
|
101
|
+
rescue ArgumentError
|
|
102
|
+
@uuid = nil
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def to_s
|
|
106
|
+
@urn
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end # GURN
|
|
110
|
+
end # OMF::SFA
|
|
111
|
+
|
|
112
|
+
require 'dm-core'
|
|
113
|
+
|
|
114
|
+
module DataMapper
|
|
115
|
+
class Property
|
|
116
|
+
class GURN < DataMapper::Property::String
|
|
117
|
+
|
|
118
|
+
# Maximum length chosen based on recommendation:
|
|
119
|
+
length 256
|
|
120
|
+
|
|
121
|
+
def custom?
|
|
122
|
+
true
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def primitive?(value)
|
|
126
|
+
value.kind_of?(OMF::SFA::Resource::GURN)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def valid?(value, negated = false)
|
|
130
|
+
super || primitive?(value) #|| value.kind_of?(::String)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# We don't want this to be called, but the Model::Property calls
|
|
134
|
+
# this one first before calling #set! on this instance again with
|
|
135
|
+
# the value returned here. Hopefully this is the only place this
|
|
136
|
+
# happens. Therefore, we just return +value+ unchanged and take care
|
|
137
|
+
# of casting in +load2+
|
|
138
|
+
#
|
|
139
|
+
def load(value)
|
|
140
|
+
if value
|
|
141
|
+
if value.start_with?('urn')
|
|
142
|
+
return OMF::SFA::Resource::GURN.create(value)
|
|
143
|
+
end
|
|
144
|
+
raise "BUG: Shouldn't be called anymore (#{value})"
|
|
145
|
+
end
|
|
146
|
+
nil
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def load2(value, context_class)
|
|
150
|
+
if value
|
|
151
|
+
#puts "LOAD #{value}||#{value.class}||#{context.inspect}"
|
|
152
|
+
return OMF::SFA::Resource::GURN.create(value, context_class)
|
|
153
|
+
end
|
|
154
|
+
nil
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def dump(value)
|
|
158
|
+
value.to_s unless value.nil?
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Typecasts an arbitrary value to a GURN
|
|
162
|
+
#
|
|
163
|
+
# @param [Hash, #to_mash, #to_s] value
|
|
164
|
+
# value to be typecast
|
|
165
|
+
#
|
|
166
|
+
# @return [GURN]
|
|
167
|
+
# GURN constructed from value
|
|
168
|
+
#
|
|
169
|
+
# @api private
|
|
170
|
+
def typecast_to_primitive(value)
|
|
171
|
+
raise "BUG: Shouldn't be called anymore"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# @override
|
|
175
|
+
def set(resource, value)
|
|
176
|
+
#puts ">>> SET: #{resource}"
|
|
177
|
+
set!(resource, load2(value, resource.class))
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
end # class GURN
|
|
183
|
+
end # class Property
|
|
184
|
+
end #module DataMapper
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'omf-sfa/resource/ocomponent'
|
|
2
|
+
require 'omf-sfa/resource/ip'
|
|
3
|
+
|
|
4
|
+
module OMF::SFA::Resource
|
|
5
|
+
|
|
6
|
+
class Interface < OComponent
|
|
7
|
+
|
|
8
|
+
#property :hardware_type, String
|
|
9
|
+
oproperty :role, String
|
|
10
|
+
oproperty :node, :node
|
|
11
|
+
oproperty :channel, :channel
|
|
12
|
+
oproperty :ip_addresses, OMF::SFA::Resource::Ip, :functional => false
|
|
13
|
+
|
|
14
|
+
has 1, :ip
|
|
15
|
+
|
|
16
|
+
def sliver
|
|
17
|
+
node.sliver
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
sfa_class 'interface'
|
|
21
|
+
|
|
22
|
+
#sfa :hardware_type, String, :attr_value => :name, :has_many => true
|
|
23
|
+
#sfa :public_ipv4, :ip4, :attribute => true
|
|
24
|
+
sfa :role, :attribute => true
|
|
25
|
+
sfa :ip
|
|
26
|
+
|
|
27
|
+
# @see IComponent
|
|
28
|
+
#
|
|
29
|
+
def independent_component?
|
|
30
|
+
false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def to_sfa_ref_xml(res_el, obj2id, opts)
|
|
34
|
+
if obj2id.key?(self)
|
|
35
|
+
el = res_el.add_child(Nokogiri::XML::Element.new('interface_ref', res_el.document))
|
|
36
|
+
el.set_attribute('component_id', self.component_id.to_s)
|
|
37
|
+
el.set_attribute('id_ref', self.uuid.to_s)
|
|
38
|
+
else
|
|
39
|
+
self.to_sfa_xml(res_el, obj2id, opts)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#Override xml serialization of 'ip'
|
|
44
|
+
def _to_sfa_property_xml(pname, value, res_el, pdef, obj2id, opts)
|
|
45
|
+
if pname == 'ip'
|
|
46
|
+
value.to_sfa_xml(res_el, obj2id, opts)
|
|
47
|
+
return
|
|
48
|
+
end
|
|
49
|
+
super
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def _from_sfa_ip_property_xml(resource_el, props, context)
|
|
53
|
+
resource_el.children.each do |el|
|
|
54
|
+
next unless el.is_a? Nokogiri::XML::Element
|
|
55
|
+
next unless el.name == 'ip' # should check namespace as well
|
|
56
|
+
|
|
57
|
+
unless address_attr = el.attributes['address']
|
|
58
|
+
raise "Expected 'address' attr for ip in '#{el}'"
|
|
59
|
+
end
|
|
60
|
+
address = address_attr.value
|
|
61
|
+
ip = self.ip_addresses.find do |r|
|
|
62
|
+
r.address == address
|
|
63
|
+
end
|
|
64
|
+
unless ip
|
|
65
|
+
# doesn't exist yet, create new one
|
|
66
|
+
ip = Ip.new(:interface => self)
|
|
67
|
+
end
|
|
68
|
+
#puts "IP -----"
|
|
69
|
+
ip.from_sfa(el)
|
|
70
|
+
#puts "IP '#{ip.inspect}'"
|
|
71
|
+
self.ip_addresses << ip
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
end # Interface
|
|
77
|
+
|
|
78
|
+
end # OMF::SFA::Resource
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'omf-sfa/resource/sfa_base'
|
|
2
|
+
|
|
3
|
+
module OMF::SFA::Resource
|
|
4
|
+
|
|
5
|
+
class Ip < OResource
|
|
6
|
+
|
|
7
|
+
oproperty :address, String
|
|
8
|
+
oproperty :netmask, String
|
|
9
|
+
oproperty :ip_type, String
|
|
10
|
+
|
|
11
|
+
belongs_to :interface, :required => false
|
|
12
|
+
|
|
13
|
+
extend OMF::SFA::Resource::Base::ClassMethods
|
|
14
|
+
include OMF::SFA::Resource::Base::InstanceMethods
|
|
15
|
+
|
|
16
|
+
sfa_class 'ip_address'
|
|
17
|
+
sfa :address, :attribute => true
|
|
18
|
+
sfa :netmask, :attribute => true
|
|
19
|
+
sfa :ip_type, :attribute => true, :attribute_name => 'type' # we need to override 'type' with 'ip_type' because there is conflict with 'type' property of OResource
|
|
20
|
+
|
|
21
|
+
# override xml serialization of "ip_type" to "type"
|
|
22
|
+
def _to_sfa_property_xml(pname, value, res_el, pdef, obj2id, opts)
|
|
23
|
+
if pname == 'ip_type'
|
|
24
|
+
res_el.set_attribute('type', value.to_s)
|
|
25
|
+
else
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# def _from_sfa_ip_type_property_xml(resource_el, props, context)
|
|
31
|
+
# puts ">>>>> ADDRESSE #{resource_el}"
|
|
32
|
+
# end
|
|
33
|
+
|
|
34
|
+
def to_hash(objs = {}, opts = {})
|
|
35
|
+
h = {}
|
|
36
|
+
uuid = h[:uuid] = self.uuid.to_s
|
|
37
|
+
objs[self] = true
|
|
38
|
+
to_hash_long(h, objs.merge(brief: true), opts)
|
|
39
|
+
h
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def to_hash_brief(opts = {})
|
|
43
|
+
to_hash(opts)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end # OMF::SFA::Resource
|
|
48
|
+
|