How To Implement User-Based Quotas in CloudBolt CMP

Overview

This KBA helps you execute your use case, where you want to implement user-based quotas in CloudBolt. Currently, the UI allows you to set Quotas per group. There is no UI way of setting quotas per user. This is because CloudBolt provides the ability to orchestrate your environment by using one of the important capabilities called 'orchestration actions'. In addition, it is a very general approach to apply RBAC or any limitations on users by grouping them into a single group.

To execute your user case, add a CloudBolt plug-in at the Admin-> Orchestration actions -> order -> Order Submission ->

Procedure

Creating the Plugin

  1. Navigate to Admin → Orchestration Actions → Order Submission

  2. Create a new plugin

  3. Replace the plug-in code with this code:

    # Sample script to apply qouta on a server.
    from orders.models import Order
    from infrastructure.models import Server
    from utilities.logger import ThreadLogger
    from accounts.models import Group
    
    SERVER_THRESHOLD = 5
    
    """
    "Order Approval" 
    This decides approval on whether the order exceeds a set number of servers provisioned.
    
    If the order is below the threshold, the order is auto-approved by this plug-in.
    
    If the order exceeds that threshold, this plug-in adds a comment to the order indicating that it
    is rejected and saves the order until another server can be deleted.
    
    `order`: the order to be approved or denied.
    `job`: always None in this context.
    `logger`: write messages to the log for this action.
    """
    
    
    def run(order, job=None, logger=None):
        if order.status != 'PENDING':
            logger.info(f"Order approval plugin skipped because order is not pending approval (it is {order.status}).")
    
            return '', '', ''
        else:
            orderowner = order.owner_id
            development_group_ID = Group.objects.all().filter(name__contains="Development").last().id
            if (order.group_id != development_group_ID):
               order.comment = 'Approval from Plugin'
               order.approve()
    
               return '', '', ''
    
            activecount = Server.objects.filter(owner_id=orderowner).filter(
                status="ACTIVE").filter(group=development_group_ID).count()
            provcount = Server.objects.filter(
                owner_id=orderowner).filter(status="PROV").count()
    
            ordercount = order.net_usage()['vm_cnt']
            # ordercount = Order.objects.filter(id=order.id).last().orderitem_set.all().first().get_servers().count()
            decomcount = order.decom_server_count()
    
            for orderitem in order.orderitem_set.all():
                logger.debug(f"order count through order item={orderitem.cast().net_usage()['vm_cnt']}")
    
            logger.debug(f"This is for services debugging --- activecount={activecount}, provcount={provcount}, "
                         f"ordercount={ordercount}, decomcount={decomcount}, order.id={order.id} ")
    
            if (decomcount - provcount) > 0:
                order.comment = 'Approval from Plugin'
                order.approve()
    
                return '', '', ''
    
            if ((activecount + ordercount + provcount) - decomcount) > SERVER_THRESHOLD:
                 reason = 'Server count exceeds server limit.'
                 order.comment = reason
                 order.deny()
                 order.denied_reason = reason
                 order.save()
    
                 return '', '', ''
    
            else:
                order.comment = 'Approval from Plugin'
                order.approve()
    
                return '', '', ''
    
    
    if __name__ == "__main__":
        if len(sys.argv) != 2:
            sys.stderr.write(f"usage: {sys.argv[0]} <CloudBolt Order ID>\n")
            sys.exit(2)
        order_id = sys.argv[1]
        order = Order.objects.get(pk=order_id)
        logger = ThreadLogger(__name__)
        status, msg, err = run(order, logger=logger)
        logger.info(f"Status: {status}, msg: {msg}, err: {err}")
    

4. Edit the script and make sure to add your group name in line

development_group_ID = Group.objects.all().filter(name__contains="Development")

5. Make sure to de-select the auto-approval checkbox of the group your user belongs to and the user is trying to provision a new server.

Adding User Quota Logic

The sample script checks for the number of servers that a user already has and is trying to provision a server in the 'Development' group. The script checks if the number of the servers exceeds 5, the provisioning order should not be approved.

Additional information

https://docs.cloudbolt.io/articles/#!cloudbolt-latest-docs/plug-in-examples/q/plug-in/qid/17057/qp/3

Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.