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,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,10 @@
1
+
2
+ module OMF::SFA::Resource
3
+
4
+ class ComponentLease
5
+ include DataMapper::Resource
6
+
7
+ belongs_to :lease, :model => 'OLease', :key => true
8
+ belongs_to :component, :model => 'OComponent', :key => true
9
+ end
10
+ end
@@ -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
+