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,859 @@
|
|
|
1
|
+
|
|
2
|
+
require 'omf_base/lobject'
|
|
3
|
+
require 'omf-sfa/resource'
|
|
4
|
+
require 'omf-sfa/resource/comp_group'
|
|
5
|
+
require 'nokogiri'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
module OMF::SFA::AM
|
|
9
|
+
|
|
10
|
+
class AMManagerException < Exception; end
|
|
11
|
+
class UnknownResourceException < AMManagerException; end
|
|
12
|
+
class UnavailableResourceException < AMManagerException; end
|
|
13
|
+
class UnknownAccountException < AMManagerException; end
|
|
14
|
+
class FormatException < AMManagerException; end
|
|
15
|
+
class ClosedAccountException < AMManagerException; end
|
|
16
|
+
class InsufficientPrivilegesException < AMManagerException; end
|
|
17
|
+
class UnavailablePropertiesException < AMManagerException; end
|
|
18
|
+
class MissingImplementationException < Exception; end
|
|
19
|
+
class UknownLeaseException < Exception; end
|
|
20
|
+
|
|
21
|
+
OL_NAMESPACE = "http://nitlab.inf.uth.gr/schema/sfa/rspec/1"
|
|
22
|
+
|
|
23
|
+
# The manager is where all the AM related policies and
|
|
24
|
+
# resource management is concentrated. Testbeds with their own
|
|
25
|
+
# ways of dealing with resources and components should only
|
|
26
|
+
# need to extend this class.
|
|
27
|
+
#
|
|
28
|
+
class AMManager < OMF::Base::LObject
|
|
29
|
+
|
|
30
|
+
# Create an instance of this manager
|
|
31
|
+
#
|
|
32
|
+
# @param [Scheduler] scheduler to use for creating new resource
|
|
33
|
+
#
|
|
34
|
+
def initialize(scheduler)
|
|
35
|
+
@scheduler = scheduler
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
### MANAGEMENT INTERFACE: adding and removing from the AM's control
|
|
39
|
+
|
|
40
|
+
# Register a resource to be managed by this AM.
|
|
41
|
+
#
|
|
42
|
+
# @param [OResource] resource to have managed by this manager
|
|
43
|
+
#
|
|
44
|
+
def manage_resource(resource)
|
|
45
|
+
unless resource.is_a?(OMF::SFA::Resource::OResource)
|
|
46
|
+
raise "Resource '#{resource}' needs to be of type 'OResource', but is '#{resource.class}'"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
null_account = _get_nil_account
|
|
50
|
+
resource.account = null_account
|
|
51
|
+
resource.save
|
|
52
|
+
# rg = get_root_group_for_account(def_account)
|
|
53
|
+
# rg.contains_resources << resource
|
|
54
|
+
# rg.save
|
|
55
|
+
resource
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Register an array of resources to be managed by this AM.
|
|
59
|
+
#
|
|
60
|
+
# @param [Array] array of resources
|
|
61
|
+
#
|
|
62
|
+
def manage_resources(resources)
|
|
63
|
+
resources.map {|r| manage_resource(r) }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
### ACCOUNTS: creating, finding, and releasing accounts
|
|
67
|
+
|
|
68
|
+
# Return the account described by +account_descr+. Create if it doesn't exist.
|
|
69
|
+
#
|
|
70
|
+
# @param [Hash] properties of account
|
|
71
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
72
|
+
# @return [OAccount] The requested account
|
|
73
|
+
# @raise [UnknownResourceException] if requested account cannot be created
|
|
74
|
+
# @raise [InsufficientPrivilegesException] if permission is not granted
|
|
75
|
+
#
|
|
76
|
+
def find_or_create_account(account_descr, authorizer)
|
|
77
|
+
debug "find_or_create_account: '#{account_descr.inspect}'"
|
|
78
|
+
begin
|
|
79
|
+
return find_account(account_descr, authorizer)
|
|
80
|
+
rescue UnavailableResourceException
|
|
81
|
+
end
|
|
82
|
+
authorizer.can_create_account?
|
|
83
|
+
account = OMF::SFA::Resource::OAccount.create(account_descr)
|
|
84
|
+
# We have an 1-to-1 relationship between account and project for the moment
|
|
85
|
+
project = OMF::SFA::Resource::Project.create
|
|
86
|
+
account.project = project
|
|
87
|
+
account.save
|
|
88
|
+
raise UnavailableResourceException.new "Cannot create '#{account_descr.inspect}'" unless account
|
|
89
|
+
account
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Return the account described by +account_descr+. Create if it doesn't exist.
|
|
93
|
+
#
|
|
94
|
+
# @param [Hash] properties of account
|
|
95
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
96
|
+
# @return [OAccount] The requested account
|
|
97
|
+
# @raise [UnknownResourceException] if requested account cannot be found
|
|
98
|
+
# @raise [InsufficientPrivilegesException] if permission is not granted
|
|
99
|
+
#
|
|
100
|
+
def find_account(account_descr, authorizer)
|
|
101
|
+
unless account = OMF::SFA::Resource::OAccount.first(account_descr)
|
|
102
|
+
raise UnavailableResourceException.new "Unknown account '#{account_descr.inspect}'"
|
|
103
|
+
end
|
|
104
|
+
authorizer.can_view_account?(account)
|
|
105
|
+
account
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Return all accounts visible to the requesting user
|
|
109
|
+
#
|
|
110
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
111
|
+
# @return [Array<OAccount>] The visible accounts (maybe empty)
|
|
112
|
+
#
|
|
113
|
+
def find_all_accounts(authorizer)
|
|
114
|
+
accounts = OMF::SFA::Resource::OAccount.all()
|
|
115
|
+
nil_account = _get_nil_account()
|
|
116
|
+
accounts.map do |a|
|
|
117
|
+
next if a == nil_account
|
|
118
|
+
begin
|
|
119
|
+
authorizer.can_view_account?(a)
|
|
120
|
+
a
|
|
121
|
+
rescue InsufficientPrivilegesException
|
|
122
|
+
nil
|
|
123
|
+
end
|
|
124
|
+
end.compact
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Return the account described by +account_descr+ if it is active.
|
|
128
|
+
#
|
|
129
|
+
# @param [Hash] properties of account
|
|
130
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
131
|
+
# @return [OAccount] The requested account
|
|
132
|
+
# @raise [UnknownResourceException] if requested account cannot be found
|
|
133
|
+
# @raise [UnavailableResourceException] if requested account is closed
|
|
134
|
+
# @raise [InsufficientPrivilegesException] if permission is not granted
|
|
135
|
+
#
|
|
136
|
+
def find_active_account(account_descr, authorizer)
|
|
137
|
+
account = find_account(account_descr, authorizer)
|
|
138
|
+
if account.closed?
|
|
139
|
+
raise UnavailableResourceException.new "Account '#{account.inspect}' is closed"
|
|
140
|
+
end
|
|
141
|
+
account
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Renew account described by +account_descr+ hash until +expiration_time+.
|
|
145
|
+
# ALready closed or expired accounts can't be renewed.
|
|
146
|
+
#
|
|
147
|
+
# @param [Hash] properties of account
|
|
148
|
+
# @param [Time] time until account should remain valid
|
|
149
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
150
|
+
# @return [OAccount] The requested account
|
|
151
|
+
# @raise [UnknownResourceException] if requested account cannot be found
|
|
152
|
+
# @raise [UnavailableResourceException] if requested account is closed
|
|
153
|
+
# @raise [InsufficientPrivilegesException] if permission is not granted
|
|
154
|
+
#
|
|
155
|
+
def renew_account_until(account_descr, expiration_time, authorizer)
|
|
156
|
+
account = find_active_account(account_descr, authorizer)
|
|
157
|
+
authorizer.can_renew_account?(account, expiration_time)
|
|
158
|
+
account.valid_until = expiration_time
|
|
159
|
+
account.save
|
|
160
|
+
account
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Close the account described by +account+ hash.
|
|
164
|
+
#
|
|
165
|
+
# Make sure that all associated resources are freed as well
|
|
166
|
+
#
|
|
167
|
+
# @param [Hash] properties of account
|
|
168
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
169
|
+
# @return [OAccount] The closed account
|
|
170
|
+
# @raise [UnknownResourceException] if requested account cannot be found
|
|
171
|
+
# @raise [UnavailableResourceException] if requested account is closed
|
|
172
|
+
# @raise [InsufficientPrivilegesException] if permission is not granted
|
|
173
|
+
#
|
|
174
|
+
def close_account(account_descr, authorizer)
|
|
175
|
+
account = find_account(account_descr, authorizer)
|
|
176
|
+
authorizer.can_close_account?(account)
|
|
177
|
+
# TODO: Free all resources associated with this account!!!!
|
|
178
|
+
# OMF::SFA::Resource::OComponent.all(:account => account).each do |c|
|
|
179
|
+
# c.account = def_account
|
|
180
|
+
# c.save
|
|
181
|
+
# end
|
|
182
|
+
account.close
|
|
183
|
+
account.save
|
|
184
|
+
account
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
### USERS
|
|
188
|
+
|
|
189
|
+
# Return the user described by +user_descr+. Create if it doesn't exist.
|
|
190
|
+
#
|
|
191
|
+
# Note: This is an unprivileged operation as creating a user doesn't imply anything
|
|
192
|
+
# else beyond opening a record.
|
|
193
|
+
#
|
|
194
|
+
# @param [Hash] properties of user
|
|
195
|
+
# @return [User] The requested user
|
|
196
|
+
# @raise [UnknownResourceException] if requested user cannot be created
|
|
197
|
+
#
|
|
198
|
+
def find_or_create_user(user_descr)
|
|
199
|
+
debug "find_or_create_user: '#{user_descr.inspect}'"
|
|
200
|
+
begin
|
|
201
|
+
return find_user(user_descr)
|
|
202
|
+
rescue UnavailableResourceException
|
|
203
|
+
end
|
|
204
|
+
user = OMF::SFA::Resource::User.create(user_descr)
|
|
205
|
+
raise UnavailableResourceException.new "Cannot create '#{user_descr.inspect}'" unless user
|
|
206
|
+
user
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Return the user described by +user_descr+.
|
|
210
|
+
#
|
|
211
|
+
# Note: This is an unprivileged operation as creating a user doesn't imply anything
|
|
212
|
+
# else beyond opening a record.
|
|
213
|
+
#
|
|
214
|
+
# @param [Hash] properties of user
|
|
215
|
+
# @return [User] The requested user
|
|
216
|
+
# @raise [UnknownResourceException] if requested user cannot be found
|
|
217
|
+
#
|
|
218
|
+
def find_user(user_descr)
|
|
219
|
+
unless user = OMF::SFA::Resource::User.first(user_descr)
|
|
220
|
+
raise UnavailableResourceException.new "Unknown user '#{user_descr.inspect}'"
|
|
221
|
+
end
|
|
222
|
+
user
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
### LEASES: creating, finding, and releasing leases
|
|
226
|
+
|
|
227
|
+
# Return the lease described by +lease_descr+. Create if it doesn't exist.
|
|
228
|
+
#
|
|
229
|
+
# @param [Hash] lease_descr properties of lease
|
|
230
|
+
# @param [Hash] lease oproperties like ":valid_from" and ":valid_until"
|
|
231
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
232
|
+
# @return [OLease] The requested lease
|
|
233
|
+
# @raise [UnknownResourceException] if requested lease cannot be created
|
|
234
|
+
# @raise [InsufficientPrivilegesException] if permission is not granted
|
|
235
|
+
#
|
|
236
|
+
def find_or_create_lease(lease_descr, lease_oproperties, authorizer)
|
|
237
|
+
debug "find_or_create_lease: '#{lease_descr.inspect}', '#{lease_oproperties.inspect}'"
|
|
238
|
+
begin
|
|
239
|
+
return find_lease(lease_descr, lease_oproperties, authorizer)
|
|
240
|
+
rescue UnavailableResourceException
|
|
241
|
+
end
|
|
242
|
+
unless lease_oproperties.has_key?(:valid_from) && lease_oproperties.has_key?(:valid_until)
|
|
243
|
+
raise UnavailablePropertiesException.new "Cannot create lease without ':valid_from' and 'valid_until' oproperties #{lease_oproperties.inspect}"
|
|
244
|
+
end
|
|
245
|
+
lease = create_resource(lease_descr, 'OLease', lease_oproperties, authorizer)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Return the lease described by +lease_descr+.
|
|
249
|
+
#
|
|
250
|
+
# @param [Hash] properties of lease
|
|
251
|
+
# @param [Hash] lease oproperties like ":valid_from" and ":valid_until"
|
|
252
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
253
|
+
# @return [OLease] The requested lease
|
|
254
|
+
# @raise [UnknownResourceException] if requested lease cannot be found
|
|
255
|
+
# @raise [InsufficientPrivilegesException] if permission is not granted
|
|
256
|
+
#
|
|
257
|
+
def find_lease(lease_descr, lease_oproperties, authorizer)
|
|
258
|
+
if lease_oproperties.empty?
|
|
259
|
+
lease = OMF::SFA::Resource::OLease.first(lease_descr)
|
|
260
|
+
raise UnavailableResourceException.new "Unknown lease '#{lease_descr.inspect}'" if lease.nil?
|
|
261
|
+
authorizer.can_view_lease?(lease)
|
|
262
|
+
return lease
|
|
263
|
+
end
|
|
264
|
+
leases = OMF::SFA::Resource::OLease.all(lease_descr)
|
|
265
|
+
leases.each do |l|
|
|
266
|
+
if (l[:valid_from] == lease_oproperties[:valid_from] &&
|
|
267
|
+
l[:valid_until] == lease_oproperties[:valid_until])
|
|
268
|
+
authorizer.can_view_lease?(l)
|
|
269
|
+
return l
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
raise UnavailableResourceException.new "Unknown lease '#{lease_descr.inspect}'"
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Return all leases of the specified account
|
|
276
|
+
#
|
|
277
|
+
# @param [OAccount] Account for which to find all associated leases
|
|
278
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
279
|
+
# @return [Array<OLease>] The account's leases (maybe empty)
|
|
280
|
+
#
|
|
281
|
+
def find_all_leases_for_account(account, authorizer)
|
|
282
|
+
debug "find_all_leases_for_account: account:'#{account.inspect}' authorizer:'#{authorizer.inspect}'"
|
|
283
|
+
leases = OMF::SFA::Resource::OLease.all(:account => account)
|
|
284
|
+
leases.map do |l|
|
|
285
|
+
begin
|
|
286
|
+
authorizer.can_view_lease?(l)
|
|
287
|
+
l
|
|
288
|
+
rescue InsufficientPrivilegesException
|
|
289
|
+
nil
|
|
290
|
+
end
|
|
291
|
+
end.compact
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def find_all_leases(authorizer)
|
|
295
|
+
leases = OMF::SFA::Resource::OLease.all
|
|
296
|
+
leases.map do |l|
|
|
297
|
+
begin
|
|
298
|
+
authorizer.can_view_lease?(l)
|
|
299
|
+
l
|
|
300
|
+
rescue InsufficientPrivilegesException
|
|
301
|
+
nil
|
|
302
|
+
end
|
|
303
|
+
end.compact
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Modify lease described by +lease_descr+ hash
|
|
307
|
+
#
|
|
308
|
+
# @param [Hash] lease oproperties like ":valid_from" and ":valid_until"
|
|
309
|
+
# @param [OLease] lease to modify
|
|
310
|
+
# @param [Authorizer] Authorization context
|
|
311
|
+
# @return [OLease] The requested lease
|
|
312
|
+
#
|
|
313
|
+
def modify_lease(lease_oproperties, lease, authorizer)
|
|
314
|
+
authorizer.can_modify_lease?(lease)
|
|
315
|
+
lease.valid_from = lease_oproperties[:valid_from]
|
|
316
|
+
lease.valid_until = lease_oproperties[:valid_until]
|
|
317
|
+
lease.save
|
|
318
|
+
lease
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# cancel +lease+
|
|
322
|
+
#
|
|
323
|
+
# This implementation simply frees the lease record.
|
|
324
|
+
#
|
|
325
|
+
# @param [OLease] lease to release
|
|
326
|
+
# @param [Authorizer] Authorization context
|
|
327
|
+
#
|
|
328
|
+
def release_lease(lease, authorizer)
|
|
329
|
+
debug "release_lease: lease:'#{lease.inspect}' authorizer:'#{authorizer.inspect}'"
|
|
330
|
+
authorizer.can_release_lease?(lease)
|
|
331
|
+
|
|
332
|
+
lease.component_leases.each do |l|
|
|
333
|
+
l.destroy # unlink the lease with the corresponding components
|
|
334
|
+
end
|
|
335
|
+
lease.status = :cancelled
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
#
|
|
339
|
+
# Create or Modify leases through RSpecs
|
|
340
|
+
#
|
|
341
|
+
# When a uuid is provided, then the corresponding lease is modified. Otherwise a new
|
|
342
|
+
# lease is created with the properties described in the RSpecs.
|
|
343
|
+
#
|
|
344
|
+
# @param [Nokogiri::XML::Node] RSpec fragment describing lease and its properties
|
|
345
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
346
|
+
# @return [OLease] The requested lease
|
|
347
|
+
# @raise [UnavailableResourceException] if no matching resource can be found or created
|
|
348
|
+
# @raise [FormatException] if RSpec elements are not known
|
|
349
|
+
#
|
|
350
|
+
def update_lease_from_rspec(lease_el, authorizer)
|
|
351
|
+
|
|
352
|
+
lease_properties = {:valid_from => Time.parse(lease_el[:valid_from]), :valid_until => Time.parse(lease_el[:valid_until])}
|
|
353
|
+
|
|
354
|
+
begin
|
|
355
|
+
raise UnavailableResourceException unless UUID.validate(lease_el[:id])
|
|
356
|
+
lease = find_lease({:uuid => lease_el[:id]}, {}, authorizer)
|
|
357
|
+
if lease.valid_from != lease_properties[:valid_from] || lease.valid_until != lease_properties[:valid_until]
|
|
358
|
+
lease = modify_lease(lease_properties, lease, authorizer)
|
|
359
|
+
return { lease_el[:id] => lease }
|
|
360
|
+
else
|
|
361
|
+
return { lease_el[:id] => lease }
|
|
362
|
+
end
|
|
363
|
+
rescue UnavailableResourceException
|
|
364
|
+
lease_descr = {:name => authorizer.account.name}
|
|
365
|
+
lease = find_or_create_lease(lease_descr, lease_properties, authorizer)
|
|
366
|
+
return { lease_el[:id] => lease }
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
#unless lease_el[:uuid].nil?
|
|
370
|
+
# lease = find_lease({:uuid => lease_el[:uuid]}, {}, authorizer)
|
|
371
|
+
# raise UnavailableResourceException.new "Unknown lease uuid'#{lease_el[:uuid]}'" unless lease
|
|
372
|
+
# if lease.valid_from != lease_properties[:valid_from] || lease.valid_until != lease_properties[:valid_until]
|
|
373
|
+
# lease = modify_lease(lease_properties, lease, authorizer)
|
|
374
|
+
# { lease_el[:leaseID] => lease }
|
|
375
|
+
# else
|
|
376
|
+
# { lease_el[:leaseID] => lease }
|
|
377
|
+
# end
|
|
378
|
+
#else
|
|
379
|
+
# lease_descr = {:name => authorizer.account.name}
|
|
380
|
+
# lease = find_or_create_lease(lease_descr, lease_properties, authorizer)
|
|
381
|
+
# { lease_el[:leaseID] => lease }
|
|
382
|
+
#end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# Update the leases described in +leases+. Any lease not already assigned to the
|
|
386
|
+
# requesting account will be added. If +clean_state+ is true, the state of all described leases
|
|
387
|
+
# is set to the state described with all other properties set to their default values. Any leases
|
|
388
|
+
# not mentioned are canceled. Returns the list
|
|
389
|
+
# of leases requested or throw an error if ANY of the requested leases isn't available.
|
|
390
|
+
#
|
|
391
|
+
# @param [Element] RSpec fragment describing leases and their properties
|
|
392
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
393
|
+
# @return [Hash{String => OLease}] The leases requested
|
|
394
|
+
# @raise [UnknownResourceException] if no matching lease can be found
|
|
395
|
+
# @raise [FormatException] if RSpec elements are not known
|
|
396
|
+
#
|
|
397
|
+
def update_leases_from_rspec(leases, authorizer)
|
|
398
|
+
debug "update_leases_from_rspec: leases:'#{leases.inspect}' authorizer:'#{authorizer.inspect}'"
|
|
399
|
+
leases_hash = {}
|
|
400
|
+
unless leases.empty?
|
|
401
|
+
leases.each do |lease|
|
|
402
|
+
l = update_lease_from_rspec(lease, authorizer)
|
|
403
|
+
leases_hash.merge!(l)
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
leases_hash
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
### RESOURCES creating, finding, and releasing resources
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
# Find a resource. If it doesn't exist throws +UnknownResourceException+
|
|
414
|
+
# If it's not visible to requester throws +InsufficientPrivilegesException+
|
|
415
|
+
#
|
|
416
|
+
# @param [Hash, String, OResource] describing properties of the requested resource, or the
|
|
417
|
+
# resource's UUID
|
|
418
|
+
# @param [Boolean] If true, throw exception if not already assigned to requester
|
|
419
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
420
|
+
# @return [OResource] The resource requested
|
|
421
|
+
# @raise [UnknownResourceException] if no matching resource can be found
|
|
422
|
+
# @raise [FormatException] if the resource description is not String, UUID or OResource class/subclass
|
|
423
|
+
# @raise [InsufficientPrivilegesException] if the resource is not visible to the requester
|
|
424
|
+
#
|
|
425
|
+
# @note This will assign the resource automatically to the requesting account
|
|
426
|
+
#
|
|
427
|
+
def find_resource(resource_descr, authorizer)
|
|
428
|
+
debug "find_resource: descr: '#{resource_descr.inspect}'"
|
|
429
|
+
if resource_descr.kind_of? OMF::SFA::Resource::OResource
|
|
430
|
+
resource = resource_descr
|
|
431
|
+
elsif resource_descr.kind_of? Hash
|
|
432
|
+
resource = OMF::SFA::Resource::OResource.first(resource_descr)
|
|
433
|
+
elsif resource_descr.kind_of? String
|
|
434
|
+
# assume to be UUID
|
|
435
|
+
begin
|
|
436
|
+
uuid = UUIDTools::UUID.parse(resource_descr)
|
|
437
|
+
descr = {:uuid => uuid}
|
|
438
|
+
rescue ArgumentError
|
|
439
|
+
# doesn't seem to be a UUID, try it as a name - be aware of non-uniqueness
|
|
440
|
+
descr = {:name => resource_descr}
|
|
441
|
+
end
|
|
442
|
+
resource = OMF::SFA::Resource::OResource.first(descr)
|
|
443
|
+
else
|
|
444
|
+
raise FormatException.new "Unknown resource description type '#{resource_descr.class}' (#{resource_descr})"
|
|
445
|
+
end
|
|
446
|
+
unless resource
|
|
447
|
+
raise UnknownResourceException.new "Resource '#{resource_descr.inspect}' is not available or doesn't exist"
|
|
448
|
+
end
|
|
449
|
+
authorizer.can_view_resource?(resource)
|
|
450
|
+
resource
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
# Find a resource which has been assigned to the authorizer's account.
|
|
454
|
+
# If it doesn't exist, or is not visible to requester
|
|
455
|
+
# throws +UnknownResourceException+.
|
|
456
|
+
#
|
|
457
|
+
# @param [Hash, String] describing properties of the requested resource, or the
|
|
458
|
+
# resource's UUID
|
|
459
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
460
|
+
# @return [OResource] The resource requested
|
|
461
|
+
# @raise [UnknownResourceException] if no matching resource can be found
|
|
462
|
+
#
|
|
463
|
+
# @note This will assign the resource automatically to the requesting account
|
|
464
|
+
#
|
|
465
|
+
def find_resource_for_account(resource_descr, authorizer)
|
|
466
|
+
rdescr = resource_descr.dup
|
|
467
|
+
rdescr[:account] = authorizer.account
|
|
468
|
+
find_resource(rdescr, authorizer)
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
# Find all resources for a specific account.
|
|
473
|
+
#
|
|
474
|
+
# @param [OAccount] Account for which to find all associated resources
|
|
475
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
476
|
+
# @return [Array<OResource>] The resource requested
|
|
477
|
+
#
|
|
478
|
+
def find_all_resources_for_account(account = _get_nil_account, authorizer)
|
|
479
|
+
debug "find_all_resources_for_account: #{account.inspect}"
|
|
480
|
+
res = OMF::SFA::Resource::OResource.all(:account => account)
|
|
481
|
+
res.map do |r|
|
|
482
|
+
begin
|
|
483
|
+
authorizer.can_view_resource?(r)
|
|
484
|
+
r
|
|
485
|
+
rescue InsufficientPrivilegesException
|
|
486
|
+
nil
|
|
487
|
+
end
|
|
488
|
+
end.compact
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
# Find all components for a specific account.
|
|
492
|
+
#
|
|
493
|
+
# @param [OAccount] Account for which to find all associated component
|
|
494
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
495
|
+
# @return [Array<OComponent>] The component requested
|
|
496
|
+
#
|
|
497
|
+
def find_all_components_for_account(account, authorizer)
|
|
498
|
+
res = OMF::SFA::Resource::OComponent.all(:account => account)
|
|
499
|
+
res.map do |r|
|
|
500
|
+
begin
|
|
501
|
+
authorizer.can_view_resource?(r)
|
|
502
|
+
r
|
|
503
|
+
rescue InsufficientPrivilegesException
|
|
504
|
+
nil
|
|
505
|
+
end
|
|
506
|
+
end.compact
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
# Find all components
|
|
510
|
+
#
|
|
511
|
+
# @return [Array<OComponent>] The components requested
|
|
512
|
+
#
|
|
513
|
+
#def find_all_components
|
|
514
|
+
# res = OMF::SFA::Resource::OComponent.all
|
|
515
|
+
# res
|
|
516
|
+
#end
|
|
517
|
+
|
|
518
|
+
def find_or_create_resource(resource_descr, type_to_create, oproperties, authorizer)
|
|
519
|
+
debug "find_or_create_resource: resource '#{resource_descr.inspect}' type: '#{type_to_create}'"
|
|
520
|
+
unless resource_descr.is_a? Hash
|
|
521
|
+
raise FormatException.new "Unknown resource description '#{resource_descr.inspect}'"
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
begin
|
|
525
|
+
return find_resource(resource_descr, authorizer)
|
|
526
|
+
rescue UnknownResourceException
|
|
527
|
+
end
|
|
528
|
+
create_resource(resource_descr, type_to_create, oproperties, authorizer)
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
# Create a resource
|
|
532
|
+
#
|
|
533
|
+
# @param [Hash] Describing properties of the requested resource
|
|
534
|
+
# @param [String] Type to create
|
|
535
|
+
# @param [Hash] A hash with all the OProperty values of the requested resource
|
|
536
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
537
|
+
# @return [OResource] The resource requested
|
|
538
|
+
# @raise [UnknownResourceException] if no resource can be created
|
|
539
|
+
#
|
|
540
|
+
def create_resource(resource_descr, type_to_create, oproperties, authorizer)
|
|
541
|
+
authorizer.can_create_resource?(resource_descr, type_to_create)
|
|
542
|
+
unless resource = @scheduler.create_resource(resource_descr, type_to_create, oproperties, authorizer)
|
|
543
|
+
raise UnknownResourceException.new "Resource '#{resource_descr.inspect}' cannot be created"
|
|
544
|
+
end
|
|
545
|
+
resource
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
# Find or create a resource for authorizer's account. If it doesn't exist,
|
|
549
|
+
# is already assigned to
|
|
550
|
+
# someone else, or cannot be created, throws +UnknownResourceException+.
|
|
551
|
+
#
|
|
552
|
+
# @param [Hash] describing properties of the requested resource
|
|
553
|
+
# @param [String] Type to create if not already exist
|
|
554
|
+
# @param [Hash] A hash with all the OProperty values of the requested resource
|
|
555
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
556
|
+
# @return [OResource] The resource requested
|
|
557
|
+
# @raise [UnknownResourceException] if no matching resource can be found
|
|
558
|
+
#
|
|
559
|
+
def find_or_create_resource_for_account(resource_descr, type_to_create, oproperties, authorizer)
|
|
560
|
+
debug "find_or_create_resource_for_account: r_descr:'#{resource_descr}' type:'#{type_to_create}' authorizer:'#{authorizer.inspect}'"
|
|
561
|
+
rdescr = resource_descr.dup
|
|
562
|
+
rdescr[:account] = authorizer.account
|
|
563
|
+
find_or_create_resource(rdescr, type_to_create, oproperties, authorizer)
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
# def _create_resource(resource_descr, type_to_create, authorizer)
|
|
567
|
+
# # OK, let's check if a group was requested. They are cheap to make
|
|
568
|
+
# #
|
|
569
|
+
# # if type_to_create == 'group'
|
|
570
|
+
# # copts = resource_descr.kind_of?(Hash) ? resource_descr : {}
|
|
571
|
+
# # copts[:account] ||= authorizer.account
|
|
572
|
+
# # debug "_create_resource:create group: description '#{copts.keys.inspect}'"
|
|
573
|
+
# # return create_group_resource(copts)
|
|
574
|
+
# # end
|
|
575
|
+
#
|
|
576
|
+
# # Let's see if this is a basic resource in which case we create a copy
|
|
577
|
+
# #
|
|
578
|
+
# # begin
|
|
579
|
+
# # #resource_descr[:account] = _get_nil_account()
|
|
580
|
+
# # #r = find_resource(resource_descr, false, authorizer)
|
|
581
|
+
# # return @scheduler.create_resource(resource_descr, authorizer)
|
|
582
|
+
# # rescue UnknownResourceException
|
|
583
|
+
# # end
|
|
584
|
+
# unless @scheduler.create_resource(resource_descr, type_to_create, authorizer)
|
|
585
|
+
# raise UnknownResourceException.new "Resource '#{resource_descr.inspect}' cannot be created"
|
|
586
|
+
# end
|
|
587
|
+
# end
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
# Update the resources described in +resource_el+. Any resource not already assigned to the
|
|
591
|
+
# requesting account will be added. If +clean_state+ is true, the state of all described resources
|
|
592
|
+
# is set to the state described with all other properties set to their default values. Any resources
|
|
593
|
+
# not mentioned are released. Returns the list
|
|
594
|
+
# of resources requested or throw an error if ANY of the requested resources isn't available.
|
|
595
|
+
#
|
|
596
|
+
# Find or create a resource. If it doesn't exist, is already assigned to
|
|
597
|
+
# someone else, or cannot be created, throws +UnknownResourceException+.
|
|
598
|
+
#
|
|
599
|
+
# @param [Element] RSpec fragment describing resource and their properties
|
|
600
|
+
# @param [Boolean] Set all properties not mentioned to their defaults
|
|
601
|
+
# @param [Authorizer] Defines context for authorization decisions
|
|
602
|
+
# @return [OResource] The resource requested
|
|
603
|
+
# @raise [UnknownResourceException] if no matching resource can be found
|
|
604
|
+
# @raise [FormatException] if RSpec elements are not known
|
|
605
|
+
#
|
|
606
|
+
# @note Throws exception if a contained resource doesn't exist, but will not roll back any
|
|
607
|
+
# already performed modifications performed on other resources.
|
|
608
|
+
#
|
|
609
|
+
def update_resources_from_rspec(descr_el, clean_state, authorizer)
|
|
610
|
+
debug "update_resources_from_rspec: descr_el:'#{descr_el}' clean_state:'#{clean_state}' authorizer:'#{authorizer}'"
|
|
611
|
+
if !descr_el.nil? && descr_el.name.downcase == 'rspec'
|
|
612
|
+
xsd_path = File.join(File.dirname(__FILE__), '../../../schema/rspec-v3', 'request.xsd')
|
|
613
|
+
schema = Nokogiri::XML::Schema(File.open(xsd_path))
|
|
614
|
+
|
|
615
|
+
res = schema.validate(descr_el.document)
|
|
616
|
+
raise FormatException.new("RSpec format is not valid: '#{res}'") unless res.empty?
|
|
617
|
+
|
|
618
|
+
unless descr_el.xpath('//ol:*', 'ol' => OL_NAMESPACE).empty?
|
|
619
|
+
#TODO: make proper schemas and validate them
|
|
620
|
+
#lease_xsd_path = File.join(File.dirname(__FILE__), '../../../schema/rspec-v3', 'request-reservation.xsd')
|
|
621
|
+
#lease_rng_path = File.join(File.dirname(__FILE__), '../../../schema/rspec-v3', 'request-reservation.rng')
|
|
622
|
+
#lease_schema = Nokogiri::XML::Schema(File.open(lease_xsd_path))
|
|
623
|
+
#lease_schema = Nokogiri::XML::RelaxNG(File.open(lease_rng_path))
|
|
624
|
+
|
|
625
|
+
#res = lease_schema.validate(descr_el.document)
|
|
626
|
+
#raise FormatException.new("RSpec format is not valid: '#{res}'") unless res.empty?
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
if descr_el.namespaces.values.include?(OL_NAMESPACE)
|
|
631
|
+
#leases = descr_el.xpath('/rspec//ol:lease', 'ol' => OL_NAMESPACE)
|
|
632
|
+
leases = descr_el.xpath('/xmlns:rspec/ol:lease', 'ol' => OL_NAMESPACE, 'xmlns' => "http://www.geni.net/resources/rspec/3")
|
|
633
|
+
leases = update_leases_from_rspec(leases, authorizer)
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
resources = descr_el.xpath('//xmlns:node').collect do |el|
|
|
638
|
+
#debug "create_resources_from_xml::EL: #{el.inspect}"
|
|
639
|
+
if el.kind_of?(Nokogiri::XML::Element)
|
|
640
|
+
# ignore any text elements
|
|
641
|
+
#if el[:lease_name].nil?
|
|
642
|
+
# update_resource_from_rspec(el, nil, clean_state, authorizer)
|
|
643
|
+
#else # This node has a lease
|
|
644
|
+
# lease = leases.find { |l| l[:name].eql?(el[:lease_name]) }
|
|
645
|
+
#leases = el.xpath('child::ol:lease', 'ol' => OL_NAMESPACE)
|
|
646
|
+
#leases = update_leases_from_rspec(leases, authorizer)
|
|
647
|
+
update_resource_from_rspec(el, leases, clean_state, authorizer)
|
|
648
|
+
#end
|
|
649
|
+
end
|
|
650
|
+
end.compact
|
|
651
|
+
|
|
652
|
+
# channel reservation
|
|
653
|
+
#resources = descr_el.xpath('/xmlns:rspec/ol:channel', 'ol' => OL_NAMESPACE, 'xmlns' => "http://www.geni.net/resources/rspec/3").collect do |el|
|
|
654
|
+
# update_resource_from_rspec(el, leases, clean_state, authorizer)
|
|
655
|
+
#end.compact
|
|
656
|
+
|
|
657
|
+
# TODO: release the unused leases. The leases we have created but we never managed
|
|
658
|
+
# to attach them to a resource because the scheduler denied it.
|
|
659
|
+
if clean_state
|
|
660
|
+
# Now free any leases owned by this account but not contained in +leases+
|
|
661
|
+
all_leases = Set.new
|
|
662
|
+
#leases = descr_el.xpath('//ol:lease', 'ol' => OL_NAMESPACE).collect do |l|
|
|
663
|
+
# update_leases_from_rspec(leases, authorizer)
|
|
664
|
+
#end.compact
|
|
665
|
+
|
|
666
|
+
leases.each {|l| l.all_resources(all_leases)}
|
|
667
|
+
unused = find_all_leases_for_account(authorizer.account, authorizer).to_set - all_leases
|
|
668
|
+
unused.each do |u|
|
|
669
|
+
release_lease(u, authorizer)
|
|
670
|
+
end
|
|
671
|
+
# Now free any resources owned by this account but not contained in +resources+
|
|
672
|
+
rspec_resources = Set.new
|
|
673
|
+
resources.each {|r| r.all_resources(rspec_resources)}
|
|
674
|
+
all_components = find_all_components_for_account(authorizer.account, authorizer)
|
|
675
|
+
unused = all_components.to_set - rspec_resources
|
|
676
|
+
release_resources(unused, authorizer)
|
|
677
|
+
end
|
|
678
|
+
return resources
|
|
679
|
+
else
|
|
680
|
+
raise FormatException.new "Unknown resources description root '#{descr_el}'"
|
|
681
|
+
end
|
|
682
|
+
end
|
|
683
|
+
|
|
684
|
+
# Update a single resource described in +resource_el+. The respective account is
|
|
685
|
+
# extracted from +opts+. Any mentioned resources not already available to the requesting account
|
|
686
|
+
# will be created. If +clean_state+ is set to true, all state of a resource not specifically described
|
|
687
|
+
# will be reset to it's default value. Returns the resource updated.
|
|
688
|
+
#
|
|
689
|
+
def update_resource_from_rspec(resource_el, leases, clean_state, authorizer)
|
|
690
|
+
if uuid_attr = (resource_el.attributes['uuid'] || resource_el.attributes['idref'])
|
|
691
|
+
uuid = UUIDTools::UUID.parse(uuid_attr.value)
|
|
692
|
+
resource = find_resource({:uuid => uuid}, authorizer) # wouldn't know what to create
|
|
693
|
+
elsif comp_id_attr = resource_el.attributes['component_id']
|
|
694
|
+
comp_id = comp_id_attr.value
|
|
695
|
+
comp_gurn = OMF::SFA::Resource::GURN.parse(comp_id)
|
|
696
|
+
#if uuid = comp_gurn.uuid
|
|
697
|
+
# resource_descr = {:uuid => uuid}
|
|
698
|
+
#else
|
|
699
|
+
# resource_descr = {:name => comp_gurn.short_name}
|
|
700
|
+
#end
|
|
701
|
+
resource_descr = {:urn => comp_gurn}
|
|
702
|
+
resource = find_or_create_resource_for_account(resource_descr, comp_gurn.type, {}, authorizer)
|
|
703
|
+
unless resource
|
|
704
|
+
raise UnknownResourceException.new "Resource '#{resource_el.to_s}' is not available or doesn't exist"
|
|
705
|
+
end
|
|
706
|
+
elsif name_attr = resource_el.attributes['component_name']
|
|
707
|
+
# the only resource we can find by a name attribute is a group
|
|
708
|
+
# TODO: Not sure about the 'group' assumption
|
|
709
|
+
name = name_attr.value
|
|
710
|
+
resource = find_or_create_resource_for_account({:name => name}, 'unknown', {}, authorizer)
|
|
711
|
+
else
|
|
712
|
+
raise FormatException.new "Unknown resource description '#{resource_el.attributes.inspect}"
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
leases_el = resource_el.xpath('child::ol:lease_ref', 'ol' => OL_NAMESPACE)
|
|
716
|
+
leases_el.each do |lease_el|
|
|
717
|
+
#TODO: provide the scheduler with the resource and the lease to attach them according to its policy.
|
|
718
|
+
# if the scheduler refuses to attach the lease to the resource, we should release both of them.
|
|
719
|
+
lease_id = lease_el['id_ref']
|
|
720
|
+
lease = leases[lease_id]
|
|
721
|
+
@scheduler.lease_component(lease, resource)
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
if resource.group?
|
|
725
|
+
members = resource_el.children.collect do |el|
|
|
726
|
+
if el.kind_of?(Nokogiri::XML::Element)
|
|
727
|
+
# ignore any text elements
|
|
728
|
+
update_resource_from_rspec(el, clean_state, authorizer)
|
|
729
|
+
end
|
|
730
|
+
end.compact
|
|
731
|
+
debug "update_resource_from_rspec: Creating members '#{members}' for group '#{resource}'"
|
|
732
|
+
|
|
733
|
+
if clean_state
|
|
734
|
+
resource.members = members
|
|
735
|
+
else
|
|
736
|
+
resource.add_members(members)
|
|
737
|
+
end
|
|
738
|
+
else
|
|
739
|
+
if clean_state
|
|
740
|
+
# Set state to what's described in +resource_el+ ONLY
|
|
741
|
+
resource.create_from_xml(resource_el, authorizer)
|
|
742
|
+
else
|
|
743
|
+
resource.update_from_xml(resource_el, authorizer)
|
|
744
|
+
end
|
|
745
|
+
end
|
|
746
|
+
resource.save
|
|
747
|
+
resource
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
# Release an array of resources.
|
|
751
|
+
#
|
|
752
|
+
# @param [Array<OResource>] Resources to release
|
|
753
|
+
# @param [Authorizer] Authorization context
|
|
754
|
+
def release_resources(resources, authorizer)
|
|
755
|
+
resources.each do |r|
|
|
756
|
+
release_resource(r, authorizer)
|
|
757
|
+
end
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
# Release 'resource'.
|
|
761
|
+
#
|
|
762
|
+
# This implementation simply frees the resource record.
|
|
763
|
+
#
|
|
764
|
+
# @param [OResource] Resource to release
|
|
765
|
+
# @param [Authorizer] Authorization context
|
|
766
|
+
#
|
|
767
|
+
def release_resource(resource, authorizer)
|
|
768
|
+
authorizer.can_release_resource?(resource)
|
|
769
|
+
@scheduler.release_resource(resource, authorizer)
|
|
770
|
+
#resource.remove_from_all_groups
|
|
771
|
+
|
|
772
|
+
# if r.kind_of? OMF::SFA::Resource::CompGroup
|
|
773
|
+
# # groups don't go back in the pool, they are created per account
|
|
774
|
+
# r.destroy
|
|
775
|
+
# else
|
|
776
|
+
# r.account = def_account
|
|
777
|
+
# r.save
|
|
778
|
+
# end
|
|
779
|
+
#resource.destroy
|
|
780
|
+
end
|
|
781
|
+
|
|
782
|
+
#
|
|
783
|
+
# This method finds all the components of the specific account and
|
|
784
|
+
# detaches them.
|
|
785
|
+
#
|
|
786
|
+
# @param [OAccount] Account who owns the components
|
|
787
|
+
# @param [Authorizer] Authorization context
|
|
788
|
+
#
|
|
789
|
+
def release_all_components_for_account(account, authorizer)
|
|
790
|
+
components = find_all_components_for_account(account, authorizer)
|
|
791
|
+
release_resources(components, authorizer)
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
# This methods deletes components, or more broadly defined, removes them
|
|
796
|
+
# from a slice.
|
|
797
|
+
#
|
|
798
|
+
# Currently, we simply transfer components to the +default_sliver+
|
|
799
|
+
#
|
|
800
|
+
# def delete_resource(resource_descr, authorizer)
|
|
801
|
+
# resource = find_resource(resource_descr, false, authorizer)
|
|
802
|
+
# if resource.kind_of? OMF::SFA::Resource::OComponent
|
|
803
|
+
# resource.account = _get_nil_account
|
|
804
|
+
# resource.remove_from_all_groups
|
|
805
|
+
# resource.save
|
|
806
|
+
# else
|
|
807
|
+
# resource.destroy
|
|
808
|
+
# end
|
|
809
|
+
# end
|
|
810
|
+
|
|
811
|
+
# This methods deletes components, or more broadly defined, removes them
|
|
812
|
+
# from a slice.
|
|
813
|
+
#
|
|
814
|
+
# Currently, we simply transfer components to the +default_sliver+
|
|
815
|
+
#
|
|
816
|
+
# def delete_resource(resource_descr, opts)
|
|
817
|
+
# resource = find_resource(resource_descr, false, opts)
|
|
818
|
+
# if resource.kind_of? OMF::SFA::Resource::OComponent
|
|
819
|
+
# resource.account = _get_nil_account
|
|
820
|
+
# resource.remove_from_all_groups
|
|
821
|
+
# resource.save
|
|
822
|
+
# else
|
|
823
|
+
# resource.destroy
|
|
824
|
+
# end
|
|
825
|
+
# end
|
|
826
|
+
|
|
827
|
+
# Return the account identified by 'uuid'.
|
|
828
|
+
#
|
|
829
|
+
# @param [String, UUID] UUID of account
|
|
830
|
+
# @return [OAccount]
|
|
831
|
+
#
|
|
832
|
+
# def get_account(uuid, authorizer)
|
|
833
|
+
# unless account = OAccount.first(:uuid => uuid)
|
|
834
|
+
# raise UnknownAccountException.new "Unknown account with uuid '#{uuid}'"
|
|
835
|
+
# end
|
|
836
|
+
# if account.closed?
|
|
837
|
+
# raise ClosedAccountException.new
|
|
838
|
+
# end
|
|
839
|
+
# end
|
|
840
|
+
|
|
841
|
+
# Return a list of resources for a particular +account+. If
|
|
842
|
+
# +account+ is null, return all the resources available at this
|
|
843
|
+
# AM.
|
|
844
|
+
#
|
|
845
|
+
# @param [OAccount] Account for which to find resources
|
|
846
|
+
# @param [Authorizer] Authoization context
|
|
847
|
+
#
|
|
848
|
+
#def get_resources_for_account(account, authorizer)
|
|
849
|
+
# OMF::SFA::Resource::OComponent.all(:account => account)
|
|
850
|
+
#end
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
def _get_nil_account()
|
|
854
|
+
@scheduler.get_nil_account()
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
end # class
|
|
858
|
+
|
|
859
|
+
end # OMF::SFA::AM
|