PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/app/models/mixins/miq_provision_quota_mixin.rb

https://gitlab.com/aljesusg/manageiqtest
Ruby | 328 lines | 258 code | 43 blank | 27 comment | 40 complexity | 76cfd04ba321902a9eb8c4d0eb75dc30 MD5 | raw file
  1. module MiqProvisionQuotaMixin
  2. # Supported quota types
  3. # vm_by_owner, vm_by_group
  4. # provision_by_owner, provision_by_group
  5. # requset_by_owner, request_by_group
  6. def check_quota(quota_type = :vms_by_owner, options = {})
  7. quota_method = "quota_#{quota_type}"
  8. unless respond_to?(quota_method)
  9. raise _("check_quota called with an invalid provisioning quota method <%{type}>") % {:type => quota_type}
  10. end
  11. send(quota_method, options)
  12. end
  13. # Collect stats about VMs in the same LDAP group as the owner making the request
  14. def quota_vms_by_group(options)
  15. quota_vm_stats(:quota_find_vms_by_group, options)
  16. end
  17. # Collect stats about VMs assigned to the owner making the request
  18. def quota_vms_by_owner(options)
  19. quota_vm_stats(:quota_find_vms_by_owner, options)
  20. end
  21. def quota_vms_by_owner_and_group(options)
  22. quota_vm_stats(:quota_find_vms_by_owner_and_group, options)
  23. end
  24. # Collect stats about retired VMs that have not been deleted and are in the same LDAP group as the owner
  25. # making the request
  26. def quota_retired_vms_by_group(options)
  27. quota_vm_stats(:quota_find_retired_vms_by_group, options)
  28. end
  29. # Collect stats about retired VMs that have not been deleted and are assigned to the owner making the request
  30. def quota_retired_vms_by_owner(options)
  31. quota_vm_stats(:quota_find_retired_vms_by_owner, options)
  32. end
  33. def quota_retired_vms_by_owner_and_group(options)
  34. quota_vm_stats(:quota_find_retired_vms_by_owner_and_group, options)
  35. end
  36. # Collect stats based on provisions running on the same day as this request and
  37. # in the same LDAP group as the owner.
  38. def quota_provisions_by_group(options)
  39. quota_provision_stats(:quota_find_provision_by_group, options)
  40. end
  41. # Collect stats based on provisions running on the same day as this request by
  42. # the same owner.
  43. def quota_provisions_by_owner(options)
  44. quota_provision_stats(:quota_find_provision_by_owner, options)
  45. end
  46. # Collect stats based on provision requests made today by the same LDAP group, regardless
  47. # of when the provision request is scheduled to run.
  48. def quota_requests_by_group(options)
  49. quota_provision_stats(:quota_find_prov_request_by_group, options)
  50. end
  51. # Collect stats based on provision requests made today by the same owner, regardless
  52. # of when the provision request is scheduled to run.
  53. def quota_requests_by_owner(options)
  54. quota_provision_stats(:quota_find_prov_request_by_owner, options)
  55. end
  56. # Collect stats based on currently active provision requests for users in the same LDAP group as the owner.
  57. def quota_active_provisions_by_group(options)
  58. quota_provision_stats(:quota_find_active_prov_request_by_group, options.merge(:nil_vm_id_only => true))
  59. end
  60. # Collect stats based on currently active provision requesets for the same owner.
  61. def quota_active_provisions_by_owner(options)
  62. quota_provision_stats(:quota_find_active_prov_request_by_owner, options.merge(:nil_vm_id_only => true))
  63. end
  64. def quota_active_provisions(options)
  65. quota_provision_stats(:quota_find_active_prov_request, options.merge(:nil_vm_id_only => true))
  66. end
  67. def quota_find_vms_by_group(options)
  68. vms = []
  69. prov_owner = get_owner
  70. unless prov_owner.nil?
  71. vms = Vm.where("miq_group_id = ?", prov_owner.current_group_id).includes(:hardware => :disks)
  72. vms.reject! do |vm|
  73. result = vm.template? || vm.host_id.nil?
  74. # if result is already true we can skip the following checks
  75. unless result == true
  76. result = if options[:retired_vms_only] == true
  77. !vm.retired?
  78. elsif options[:include_retired_vms] == false
  79. # Skip retired VMs by default
  80. vm.retired?
  81. else
  82. result
  83. end
  84. end
  85. result
  86. end
  87. end
  88. vms
  89. end
  90. def quota_find_vms_by_owner_and_group(options)
  91. scope = Vm.not(:host_id => nil)
  92. if options[:retired_vms_only] == true
  93. scope = scope.where(:retired => true)
  94. elsif options[:include_retired_vms] == false
  95. scope = scope.where.not(:retired => true)
  96. end
  97. scope.user_or_group_owned(prov_owner, prov_owner.current_group).includes(:hardware => :disks).to_a
  98. end
  99. def quota_find_vms_by_owner(options)
  100. vms = []
  101. prov_owner = get_owner
  102. unless prov_owner.nil?
  103. cond_str, cond_args = "evm_owner_id = ? AND template = ? AND host_id is not NULL", [prov_owner.id, false]
  104. # Default return includes retired VMs that are still on a host
  105. if options[:retired_vms_only] == true
  106. cond_str += " AND retired = ?"
  107. cond_args << true
  108. elsif options[:include_retired_vms] == false
  109. # Skip retired VMs
  110. cond_str += " AND (retired is NULL OR retired = ?)"
  111. cond_args << false
  112. end
  113. vms = Vm.where(cond_str, *cond_args).includes(:hardware => :disks).to_a
  114. end
  115. vms
  116. end
  117. def quota_find_retired_vms_by_group(options)
  118. quota_find_vms_by_group(options.merge(:retired_vms_only => true))
  119. end
  120. def quota_find_retired_vms_by_owner(options)
  121. quota_find_vms_by_owner(options.merge(:retired_vms_only => true))
  122. end
  123. def quota_find_retired_vms_by_owner_and_group(options)
  124. quota_find_vms_by_owner_and_group(options.merge(:retired_vms_only => true))
  125. end
  126. def quota_vm_stats(vms_method, options)
  127. result = {:count => 0, :memory => 0, :cpu => 0, :snapshot_storage => 0, :used_storage => 0, :allocated_storage => 0, :ids => [], :class_name => Vm.name}
  128. vms = send(vms_method, options)
  129. result[:count] = vms.length
  130. vms.each do |vm|
  131. result[:memory] += vm.ram_size.to_i
  132. result[:cpu] += vm.cpu_total_cores
  133. result[:snapshot_storage] += vm.snapshot_storage
  134. result[:used_storage] += vm.used_disk_storage.to_i + vm.snapshot_storage
  135. result[:allocated_storage] += vm.allocated_disk_storage.to_i
  136. result[:ids] << vm.id
  137. end
  138. result
  139. end
  140. def quota_get_time_range(time = nil)
  141. tz = MiqServer.my_server.server_timezone
  142. ts = time.nil? ? Time.now.in_time_zone(tz) : time.in_time_zone(tz)
  143. [ts.beginning_of_day.utc, ts.end_of_day.utc]
  144. end
  145. def quota_find_provisions(options)
  146. scheduled_range = quota_get_time_range(options[:scheduled_time])
  147. scheduled_today = scheduled_range.first == quota_get_time_range.first
  148. queued_requests = MiqQueue.where(
  149. :class_name => 'MiqProvisionRequest',
  150. :method_name => 'create_provision_instances',
  151. :state => 'ready',
  152. :deliver_on => scheduled_range,
  153. )
  154. # Make sure we skip the current MiqProvisionRequest in the calculation.
  155. skip_id = self.class.name == "MiqProvisionRequest" ? id : miq_provision_request.id
  156. load_ids = queued_requests.pluck(:instance_id)
  157. load_ids.delete(skip_id)
  158. provisions = MiqProvisionRequest.where(:id => load_ids).to_a
  159. # If the schedule is for today we need to add in provisions that ran today (scheduled or immediate)
  160. if scheduled_today
  161. today_range = (scheduled_range.first..scheduled_range.last)
  162. MiqProvisionRequest.where.not(:request_state => 'pending').where(:updated_on => today_range).each do |prov_req|
  163. next if prov_req.id == skip_id
  164. provisions << prov_req if today_range.include?(prov_req.options[:delivered_on])
  165. end
  166. end
  167. provisions
  168. end
  169. def quota_find_provision_by_owner(options)
  170. email = get_option(:owner_email).to_s.strip
  171. sched_type = get_option(:schedule_type).to_s.strip
  172. options[:scheduled_time] = sched_type == 'schedule' ? get_option(:schedule_time) : nil
  173. quota_find_provisions(options).delete_if { |p| email.casecmp(p.get_option(:owner_email).to_s.strip) != 0 }
  174. end
  175. def quota_find_provision_by_group(options)
  176. prov_requests = []
  177. prov_owner = get_owner
  178. unless prov_owner.nil?
  179. group = prov_owner.ldap_group
  180. sched_type = get_option(:schedule_type).to_s.strip
  181. options[:scheduled_time] = sched_type == 'schedule' ? get_option(:schedule_time) : nil
  182. prov_requests = quota_find_provisions(options).delete_if do |p|
  183. prov_req_owner = p.get_owner
  184. prov_req_owner.nil? ? true : group.casecmp(prov_req_owner.ldap_group) != 0
  185. end
  186. end
  187. prov_requests
  188. end
  189. def quota_find_prov_requests(_options)
  190. today_time_range = quota_get_time_range
  191. requests = MiqRequest.where("type = ? and approval_state != ? and (created_on >= ? and created_on < ?)",
  192. MiqProvisionRequest.name, 'denied', *today_time_range)
  193. # Make sure we skip the current MiqProvisionRequest in the calculation.
  194. skip_id = self.class.name == "MiqProvisionRequest" ? id : miq_provision_request.id
  195. requests.collect { |request| request unless request.id == skip_id }.compact
  196. end
  197. def quota_find_prov_request_by_owner(options)
  198. email = get_option(:owner_email).to_s.strip
  199. quota_find_prov_requests(options).delete_if { |p| email.casecmp(p.get_option(:owner_email).to_s.strip) != 0 }
  200. end
  201. def quota_find_prov_request_by_group(options)
  202. prov_requests = []
  203. prov_owner = get_owner
  204. unless prov_owner.nil?
  205. group = prov_owner.ldap_group
  206. prov_requests = quota_find_prov_requests(options).delete_if do |p|
  207. prov_req_owner = p.get_owner
  208. prov_req_owner.nil? ? true : group.casecmp(prov_req_owner.ldap_group) != 0
  209. end
  210. end
  211. prov_requests
  212. end
  213. def quota_find_active_prov_request_by_owner(options)
  214. email = get_option(:owner_email).to_s.strip
  215. quota_find_active_prov_request(options).select { |p| email.casecmp(p.get_option(:owner_email).to_s.strip) == 0 }
  216. end
  217. def quota_find_active_prov_request_by_group(options)
  218. prov_requests = []
  219. prov_owner = get_owner
  220. unless prov_owner.nil?
  221. group = prov_owner.ldap_group
  222. prov_requests = quota_find_active_prov_request(options).select do |p|
  223. prov_req_owner = p.get_owner
  224. prov_req_owner && group.casecmp(prov_req_owner.ldap_group) == 0
  225. end
  226. end
  227. prov_requests
  228. end
  229. def quota_find_active_prov_request(_options)
  230. prov_req_ids = []
  231. MiqQueue
  232. .where(:method_name => 'create_provision_instances', :state => 'dequeue', :class_name => 'MiqProvisionRequest')
  233. .each do |q|
  234. prov_req_ids << q.instance_id
  235. end
  236. prov_ids = []
  237. MiqQueue
  238. .where(:method_name => 'deliver', :state => %w(ready dequeue), :class_name => 'MiqAeEngine')
  239. .where("task_id like ?", '%miq_provision_%')
  240. .each do |q|
  241. if q.args
  242. args = q.args.first
  243. prov_ids << args[:object_id] if args[:object_type] == 'MiqProvision' && !args[:object_id].blank?
  244. end
  245. end
  246. prov_req_ids += MiqProvision.where(:id => prov_ids).pluck("miq_request_id")
  247. MiqProvisionRequest.where(:id => prov_req_ids.compact.uniq)
  248. end
  249. def quota_provision_stats(prov_method, options)
  250. result = {:count => 0, :memory => 0, :cpu => 0, :storage => 0, :ids => [], :class_name => MiqProvisionRequest.name,
  251. :active => {
  252. :class_name => MiqProvision.name, :ids => [], :storage_by_id => Hash.new { |k, v| k[v] = 0 },
  253. :memory_by_host_id => Hash.new { |k, v| k[v] = 0 }, :cpu_by_host_id => Hash.new { |k, v| k[v] = 0 },
  254. :vms_by_storage_id => Hash.new { |k, v| k[v] = [] }
  255. }
  256. }
  257. send(prov_method, options).each do |pr|
  258. num_vms_for_request = pr.get_option(:number_of_vms).to_i
  259. if options[:nil_vm_id_only] == true && pr.miq_request_tasks.length == num_vms_for_request
  260. no_vm = pr.miq_request_tasks.find_all { |p| p.destination_id.nil? && p.state != 'finished' }
  261. num_vms_for_request = no_vm.length
  262. end
  263. unless num_vms_for_request.zero?
  264. new_disk_storage_size = pr.get_new_disks.inject(0) { |s, d| s += d[:sizeInMB].to_i } * 1.megabyte
  265. result[:count] += num_vms_for_request
  266. result[:memory] += pr.get_option(:vm_memory).to_i * num_vms_for_request
  267. result[:cpu] += pr.get_option(:number_of_cpus).to_i * num_vms_for_request
  268. result[:storage] += (pr.vm_template.allocated_disk_storage.to_i + new_disk_storage_size) * num_vms_for_request
  269. result[:ids] << pr.id
  270. # Include a resource breakdown for actively provisioning records
  271. pr.miq_request_tasks.each do |p|
  272. next unless p.state == 'active'
  273. host_id, storage_id = p.get_option(:dest_host).to_i, p.get_option(:dest_storage).to_i
  274. active = result[:active]
  275. active[:memory_by_host_id][host_id] += p.get_option(:vm_memory).to_i
  276. active[:cpu_by_host_id][host_id] += p.get_option(:number_of_cpus).to_i
  277. active[:storage_by_id][storage_id] += p.vm_template.allocated_disk_storage.to_i + new_disk_storage_size
  278. active[:vms_by_storage_id][storage_id] << p.id
  279. active[:ids] << p.id
  280. end
  281. end
  282. end
  283. result
  284. end
  285. end