Quota check during dialog

Is there a way to get a users used quota during the dialog portion of a request? I would like to be able to show the user there current quota and possible even limit the flavors the user can select so they do have to submit a request that they don’t have quota for for it just to fail.

If you’re using tenant quotas then this should be quite simple, the current allocated/provisioned values are virtual columns on the tenant object, for example:

$evm.root['tenant'].allocated_memory = 48318382080   (type: Fixnum)
$evm.root['tenant'].allocated_storage = 498216206336   (type: Fixnum)
$evm.root['tenant'].allocated_vcpu = 23   (type: Fixnum)
$evm.root['tenant'].provisioned_storage = 546534588416   (type: Fixnum)

You might possibly be able to call/use the functionality of the existing System/CommonMethods/QuotaMethods/used method which does the calculations for the quota checking workflow. This is already doing the heavy lifting of finding out the existing usage, including checking in-flight provisions.

Hope this helps,
pemcg

Hi @pemcg thanks for the reply. We were able to use the existing code from the quota methods to get the allocated usage for the user and then pull the max quota tags assign to the user or if none were defined pull the default quota settings for the region. The tricky part was getting the id for the user for the proper region as we have a multi region setup and a user id is created per region. We currently have this working and are in the process of disabling dialog fields based on the users remaining quota. If you would like details let me know and i can provide the code we setup so far.

Thanks,

Hello @Opereira
can you please quote some of the code as like you said this is not easy. We try to run a single miq instance with multiple providers and tenants, and in dialogs our users can choose provider and tenant, and I have not found a good way to get the allocated_vcpu yet for instance. I am getting the provisioned cpu count etc but allocated is something else!
Thanks!

Just a note to say this isn’t an ideal setup for ManageIQ. Ideally you should use a separate zone per provider, and for a production/HA installation you should really have a minimum of 2 appliances per zone for resilience.

Hope this helps,
pemcg

Hi @miq_man

Here is some of the code we use to get the allocated resources. This is a bit messy as i am not a true developer but it works for us. Keep in mind we have multiple regions reporting back to a master region where all users actually deploy resources from so the trick for us was finding the region the user was deploying to and getting the resource for that region. Hope this is useful to you.

#------------------------Get users comsumed count---------------------------------------------------

> def consumption(source)
>   {
>     :cpu                 => source.allocated_vcpu,
>     :memory              => source.allocated_memory,
>     :vms                 => source.vms.count { |vm| vm.id unless vm.archived },
>     :storage             => source.allocated_storage,
>     :provisioned_storage => source.provisioned_storage
>   }
> end
> 
>     #------------------------Get the user id for the required region------------------------------------
> 
>     if !$evm.object['service_template'].nil?
>       serviceid = 	$evm.object['service_template'].id
>     else  
>       serviceid = $evm.object['dialog_ems_dropdown']
>     end
>     $evm.log(:info, " this is my serviceid: [#{serviceid}]")
>     myserviceid = serviceid.to_s.chars.first(2).join.to_i
>     $evm.log(:info, " this is my myserviceid: [#{myserviceid}]")
>     username = $evm.root['user'].name
>     $evm.log(:info, " this is my username: [#{username}]")
> 
> 
>     my_user = $evm.vmdb('user').where(["name = ? and CAST(id AS TEXT) LIKE ? ", "#{username}", "#{myserviceid}%"])
>     my_quota = $evm.vmdb('user').find_by_id(my_user.map{|x| x[:id]}[0])
> 
>     if my_quota.nil?
>      	myserviceid = 99
>     	my_user = $evm.vmdb('user').where(["name = ? and CAST(id AS TEXT) LIKE ? ", "#{username}", "#{myserviceid}%"])
>       	my_quota = $evm.vmdb('user').find_by_id(my_user.map{|x| x[:id]}[0])
>     end
>     #------------------------Set the quota source-------------------------------------------------------
> 
>     $evm.root['quota_source'] = my_quota
>     test_quota = $evm.root['quota_source']
>     $evm.log(:info, " this is my username: [#{test_quota.inspect}]")
> 
>     #------------------------Get the default quotas-----------------------------------------------------
> 
>     my_limit_quotas = $evm.instantiate('MyCompany/System/CommonMethods/QuotaStateMachine/quota_limit_region_5')
>     my_limit_quota = my_limit_quotas.attributes
> 
>     default_max_cpu = my_limit_quota['max_cpu']
>     default_max_memory = (my_limit_quota['max_memory']) * 1024 * 1024 # In megabytes
>     default_max_vms = my_limit_quota['max_vms']
>     default_max_storage = (my_limit_quota['max_storage']) * 1024 * 1024 # In megabytes
> 
>     $evm.log(:info, " this is my default_max_storage: [#{default_max_storage}]")
>     $evm.log(:info, " this is my default_max_cpu: [#{default_max_cpu}]")
>     $evm.log(:info, " this is my default_max_vms: [#{default_max_vms}]")
>     $evm.log(:info, " this is my default_max_memory: [#{default_max_memory}]")
> 
>     #------------------------Quota Used-----------------------------------------------------------------
> 
>     $evm.root['quota_used'] = consumption($evm.root['quota_source']) if $evm.root['quota_source']
>     my_used_quota = $evm.root['quota_used']
> 
>     my_used_cpu = my_used_quota[:cpu].to_i
>     my_used_memory = my_used_quota[:memory].to_i # In bytes
>     my_used_vms = my_used_quota[:vms].to_i
>     my_used_storage = my_used_quota[:storage].to_i # In bytes
> 
>     $evm.log(:info, " this is my used_storage: [#{my_used_storage}]")
>     $evm.log(:info, " this is my used_cpu: [#{my_used_cpu}]")
>     $evm.log(:info, " this is my used_vms: [#{my_used_vms}]")
>     $evm.log(:info, " this is my used_memory: [#{my_used_memory}]")
> 
>     #------------------------Assigned tagged quotas-----------------------------------------------------
> 
>     my_max_storage = (test_quota.tags("quota_max_storage").first.to_i) * 1024 * 1024 * 1024 # In gigabytes
>     my_max_cpu = test_quota.tags("quota_max_cpu").first.to_i
>     my_max_vms = test_quota.tags("quota_max_vms").first.to_i
>     my_max_memory = (test_quota.tags("quota_max_memory").first.to_i) * 1024 * 1024 # In megabytes
> 
>     $evm.log(:info, " this is my max_storage: [#{my_max_storage}]")
>     $evm.log(:info, " this is my max_cpu: [#{my_max_cpu}]")
>     $evm.log(:info, " this is my max_vms: [#{my_max_vms}]")
>     $evm.log(:info, " this is my max_memory: [#{my_max_memory}]")
> 
>     #------------------------Determine which quota to use-----------------------------------------------
> 
>     my_max_storage == 0 ? my_storage_quota = default_max_storage : my_storage_quota = my_max_storage
>     my_max_cpu == 0 ? my_cpu_quota = default_max_cpu : my_cpu_quota = my_max_cpu
>     my_max_vms == 0 ? my_vms_quota = default_max_vms : my_vms_quota = my_max_vms
>     my_max_memory == 0 ? my_memory_quota = default_max_memory : my_memory_quota = my_max_memory
> 
>     $evm.log(:info, " this is my my_storage_quota: [#{my_storage_quota}]")
>     $evm.log(:info, " this is my my_cpu_quota: [#{my_cpu_quota}]")
>     $evm.log(:info, " this is my my_vms_quota: [#{my_vms_quota}]")
>     $evm.log(:info, " this is my my_memory_quota: [#{my_memory_quota}]")
> 
>     #------------------------Calculated remaining quota-------------------------------------------------
> 
>     my_storage_left = (my_storage_quota - my_used_storage)
>     my_cpu_left = my_cpu_quota - my_used_cpu
>     my_vms_left = my_vms_quota - my_used_vms
>     my_memory_left = my_memory_quota - my_used_memory
> 
>     my_storage_left > 0 ? my_storage_left = (((my_storage_left / 1024) / 1024) / 1024) : my_storage_left = 0
>     my_cpu_left > 0 ? my_cpu_left = my_cpu_left : my_cpu_left = 0
>     my_vms_left> 0 ? my_vms_left = my_vms_left : my_vms_left = 0
>     my_memory_left > 0 ? my_memory_left = (((my_memory_left / 1024) / 1024) / 1024) : my_memory_left = 0
> 
>     $evm.log(:info, " this is my storage_left: [#{my_storage_left}]")
>     $evm.log(:info, " this is my cpu_left: [#{my_cpu_left}]")
>     $evm.log(:info, " this is my vms_left: [#{my_vms_left}]")
>     $evm.log(:info, " this is my memory_left: [#{my_memory_left}]")

Interesting, I guess we have a different concept.

First our dialog has a few fields, the user can then choose where to deploy.
Field ‘provider’ is calling an expression that shows a list of active Cloud Providers. (Cloud Providers: Active = true)
Next we have a field Tenant. Technically this is the cloud_tennant. This is also an expression method, where Cloud Tenant: EMS needs to be the same as the input on the dialog_provider. So for this we supply arg1, string, ${/#dialog_provider}

The crux for us is to now acquire the tenant for this cloud tenant object.
And after that we can use the tenant object and methods to get the allocated_vcpu.

myCTenant = $evm.root[‘dialog_cloud_tenant’]
myTenant = $evm.vmdb(‘CloudTenant’, myCTenant.to_i)
tenName = myTenant.name
tenID = myTenant.id
$evm.log(“debug”, “tenName = #{tenName}”)
$evm.log(“debug”, “tenID = #{tenID}”)
cpuAllocated = 0
$evm.vmdb(:tenant).all.each do |t|
if t.name == tenName and t.source_id == tenID
cpuAllocated = t.allocated_vcpu
break
end
end

$evm.log(“debug”, “Allocated vCPU = #{cpuAllocated}”)
field_to_update = $evm.object
field_to_update[‘value’] = cpuAllocated.to_i
return MIQ_OK

I’m sure there may be a more condensed way to do this but it seemed fair and easy to follow in logical steps. In reality we’re not so happy CloudTenant has no such method so we had to go around the issue by digging into the DB and tables and put the dots together.
It may be too simplistic too, we have not gone into depth with the product so far, no multiple regions and zones. But I think this is normal, we get something working and then build on from there. And we have really tried many many different ways and expressions but somehow it was never providing us the right answer. Or even ‘an’ answer.