omf_sfa 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+