Configure nova unified limits quotas

This enables the configuration of nova to use unified limits in
keystone and enforcement in oslo.limit.

Related to blueprint unified-limits-nova

Depends-On: https://review.opendev.org/c/openstack/nova/+/715271

Change-Id: Ifdef3510bc7da3098a71739814e35dbaf612ae34
diff --git a/lib/nova b/lib/nova
index 930529a..9039c6b 100644
--- a/lib/nova
+++ b/lib/nova
@@ -159,6 +159,9 @@
 # image in devstack is CirrOS.
 NOVA_SHUTDOWN_TIMEOUT=${NOVA_SHUTDOWN_TIMEOUT:-0}
 
+# Whether to use Keystone unified limits instead of legacy quota limits.
+NOVA_USE_UNIFIED_LIMITS=$(trueorfalse False NOVA_USE_UNIFIED_LIMITS)
+
 # Functions
 # ---------
 
@@ -384,6 +387,13 @@
             "http://$SERVICE_HOST:$S3_SERVICE_PORT" \
             "http://$SERVICE_HOST:$S3_SERVICE_PORT"
     fi
+
+    # Unified limits
+    if is_service_enabled n-api; then
+        if [[ "$NOVA_USE_UNIFIED_LIMITS" = True ]]; then
+            configure_nova_unified_limits
+        fi
+    fi
 }
 
 # create_nova_conf() - Create a new nova.conf file
@@ -719,6 +729,62 @@
     fi
 }
 
+function configure_nova_unified_limits {
+    # Default limits. Mirror the config-based default values.
+    # Note: disk quota is new in nova as of unified limits.
+    bash -c "unset OS_USERNAME OS_TENANT_NAME OS_PROJECT_NAME;
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit 10 --region $REGION_NAME \
+                    servers; \
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit 20 --region $REGION_NAME \
+                    class:VCPU; \
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit $((50 * 1024)) --region $REGION_NAME \
+                    class:MEMORY_MB; \
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit 20 --region $REGION_NAME \
+                    class:DISK_GB; \
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit 128 --region $REGION_NAME \
+                    server_metadata_items; \
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit 5 --region $REGION_NAME \
+                    server_injected_files; \
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit 10240 --region $REGION_NAME \
+                    server_injected_file_content_bytes; \
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit 255 --region $REGION_NAME \
+                    server_injected_file_path_bytes; \
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit 100 --region $REGION_NAME \
+                    server_key_pairs; \
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit 10 --region $REGION_NAME \
+                    server_groups; \
+        openstack --os-cloud devstack-system-admin registered limit create \
+                    --service nova --default-limit 10 --region $REGION_NAME \
+                    server_group_members"
+
+    # Tell nova to use these limits
+    iniset $NOVA_CONF quota driver "nova.quota.UnifiedLimitsDriver"
+
+    # Configure oslo_limit so it can talk to keystone
+    iniset $NOVA_CONF oslo_limit user_domain_name $SERVICE_DOMAIN_NAME
+    iniset $NOVA_CONF oslo_limit password $SERVICE_PASSWORD
+    iniset $NOVA_CONF oslo_limit username nova
+    iniset $NOVA_CONF oslo_limit auth_type password
+    iniset $NOVA_CONF oslo_limit auth_url $KEYSTONE_SERVICE_URI
+    iniset $NOVA_CONF oslo_limit system_scope "'all'"
+    iniset $NOVA_CONF oslo_limit endpoint_id \
+           $(openstack endpoint list --service nova -f value -c ID)
+
+    # Allow the nova service user to read quotas
+    openstack role add --user nova --user-domain Default --system all \
+              reader
+}
+
 function init_nova_service_user_conf {
     iniset $NOVA_CONF service_user send_service_user_token True
     iniset $NOVA_CONF service_user auth_type password