2 description: Resource Management for Virtualized Infrastructure
3 author: Peter K. Lee <peter@intercloud.net>
5 homepage: http://wiki.opnfv.org/promise
6 repository: git://github.com/opnfv/promise.git
22 schema: !yang schema/opnfv-promise.yang
24 # below config provides default parameters
25 # NOTE: uncomment locally for testing with pre-existing data
26 #config: !json config/demo.json
29 access-control-models: !yang schema/access-control-models.yang
30 nfv-infrastructure: !yang schema/nfv-infrastructure.yang
32 # MODULE model active bindings
35 # rebind to be a computed property
36 promise.capacity.total: !coffee/function |
37 (prev) -> @computed (->
39 for k, v of b.capacity when v?
44 .filter (entry) -> entry.active is true
47 # rebind to be a computed property
48 promise.capacity.reserved: !coffee/function |
49 (prev) -> @computed (->
51 for k, v of b.remaining when v?
55 (@parent.get 'reservations')
56 .filter (entry) -> entry.active is true
59 # rebind to be a computed property
60 promise.capacity.usage: !coffee/function |
61 (prev) -> @computed (->
63 for k, v of b.capacity when v?
67 (@parent.get 'allocations')
68 .filter (entry) -> entry.active is true
71 # rebind to be a computed property
72 promise.capacity.available: !coffee/function |
73 (prev) -> @computed (->
75 reserved = @get 'reserved'
77 for k, v of total when v?
78 total[k] -= reserved[k] if reserved[k]?
79 total[k] -= usage[k] if usage[k]?
83 # RPC definitions (INTENT interfaces)
84 rpc: !require spec/promise-intents.coffee
86 # COMPLEX-TYPE model active bindings (controller logic)
90 id: !coffee/function |
91 (prev) -> prev.set 'default', -> @uuid()
95 start: !coffee/function |
96 (prev) -> prev.set 'default', -> (new Date).toJSON()
98 active: !coffee/function |
99 (prev) -> @computed (->
101 start = new Date (@get 'start')
103 when (@get 'end')? then new Date (@get 'end')
105 (@get 'enabled') and (start <= now <= end)
109 end: !coffee/function |
110 (prev) -> prev.set 'default', ->
111 end = (new Date @get 'start')
112 max = @parent.get 'promise.policy.reservation.max-duration'
114 end.setTime (end.getTime() + (max*60*60*1000))
117 allocations: !coffee/function |
118 (prev) -> @computed (->
119 res = (@store.find 'ResourceAllocation', reservation: @id)
120 res.map (x) -> x.get 'id'
123 remaining: !coffee/function |
124 (prev) -> @computed (->
125 total = @get 'capacity'
126 records = @store.find 'ResourceAllocation', id: (@get 'allocations'), active: true
128 usage = entry.get 'capacity'
135 validate: !coffee/function |
136 (prev) -> (value={}, resolve, reject) ->
137 # validate that request contains sufficient data
138 for k, v of value.capacity when v? and !!v
140 if (not hasCapacity) and value.elements.length is 0
141 return reject "unable to validate reservation record without anything being reserved"
142 # time range verifications
144 start = (new Date value.start) if value.start?
145 end = (new Date value.end) if value.end?
146 # if start? and start < now
147 # return reject "requested start time #{value.start} cannot be in the past"
148 if end? and end < now
149 return reject "requested end time #{value.end} cannot be in the past"
150 if start? and end? and start > end
151 retun reject "requested start time must be earlier than end time"
154 update: !coffee/function |
155 (prev) -> (req, resolve, reject) ->
156 req.start ?= @get 'start'
157 req.end ?= @get 'end'
159 # TODO: should validate here...
160 @parent.invoke 'query-capacity',
163 capacity: 'available'
166 collections = res.get 'collections'
167 unless collections.length > 0
168 return reject 'no resource capacity available during requested start/end time'
170 pools = collections.filter (e) -> /^ResourcePool/.test e
171 # should do some policy or check to see if more than one pool acceptable to reservee
173 entries = res.get 'utilization'
174 start = new Date req.start
175 end = new Date req.end
177 for x in [0..entries.length-1]
178 t1 = new Date entries[x].timestamp
179 break unless t1 < end
181 if x < entries.length-1
182 t2 = new Date entries[x+1].timestamp
183 continue unless t2 > start
185 available = entries[x].capacity
186 for k, v of req.capacity when v? and !!v
187 unless available[k] >= v
188 return reject "requested #{k}=#{v} exceeds available #{available[k]} between #{t1} and #{t2}"
193 .catch (err) -> reject err
195 save: !coffee/function |
196 (prev) -> (resolve, reject) ->
197 @invoke 'validate', @get()
199 # should do something about this reservation record...
200 now = (new Date).toJSON()
201 unless (res.get 'created-on')?
202 res.set 'created-on', now
203 res.set 'modified-on', now
205 .catch (e) -> reject e
209 priority: !coffee/function |
210 (prev) -> @computed (->
212 when not (@get 'reservation')? then 3
213 when not (@get 'active') then 2
218 save: !coffee/function |
219 (prev) -> (resolve, reject) ->
220 # validate that record contains sufficient data
223 for k, v of value.capacity when v? and !!v
225 if (not hasCapacity) and value.elements.length is 0
226 return reject "unable to save pool record without any capacity values"
232 token: !coffee/function |
233 (prev) -> prev.set 'private', true
235 pools: !coffee/function |
236 (prev) -> @computed (->
237 (@store.find 'ResourcePool', source: (@get 'name')).map (x) -> x.get 'id'
241 # XXX - this method is OpenStack-specific only, will need to revise later
242 update: !coffee/function |
243 (prev) -> (services=[], resolve, reject) ->
244 return reject "unable to update provider without list of services" unless services.length
245 request = @store.parent.require 'superagent'
246 services.forEach (service) =>
249 url = service.endpoints[0].publicURL
250 @set 'services.compute.endpoint', url
253 .set 'X-Auth-Token', @get 'token'
254 .set 'Accept', 'application/json'
257 console.warn "request to discover capacity limits failed"
260 capacity = res.body.limits?.absolute
261 #console.log "\ndiscovered capacity:"
262 #console.log capacity
264 (@access 'capacity').set {
265 cores: capacity.maxTotalCores
266 ram: capacity.maxTotalRAMSize
267 instances: capacity.maxTotalInstances
268 addresses: capacity.maxTotalFloatingIps
271 .get "#{url}/flavors/detail"
272 .set 'X-Auth-Token', @get 'token'
273 .set 'Accept', 'application/json'
276 console.warn "request to discover compute flavors failed"
279 flavors = res.body.flavors
280 # console.log "\ndiscovered flavors:"
281 # console.log flavors
283 flavors = flavors.map (x) -> ResourceFlavor: x
284 (@access 'services.compute.flavors').push flavors...
286 console.warn "failed to update flavors into the provider due to validation errors"
288 # XXX - update should do promise.all