Repository: gophercloud/gophercloud

Issue:
Enable quota deletion for network and loadbalancer quotas


Hints from issue comments:

Solution patch:
diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml
index 58952951c..587f803f1 100644
--- a/.github/workflows/codeql-analysis.yaml
+++ b/.github/workflows/codeql-analysis.yaml
@@ -27,12 +27,12 @@ jobs:
         cache: true
 
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@v3
+      uses: github/codeql-action/init@v4
       with:
         languages: ${{ matrix.language }}
 
     - name: Autobuild
-      uses: github/codeql-action/autobuild@v3
+      uses: github/codeql-action/autobuild@v4
 
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v3
+      uses: github/codeql-action/analyze@v4
diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml
index bf350e9ae..9bc2a44a5 100644
--- a/.github/workflows/functional-baremetal.yaml
+++ b/.github/workflows/functional-baremetal.yaml
@@ -22,19 +22,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Ironic on OpenStack ${{ matrix.name }}
     steps:
@@ -80,7 +73,7 @@ jobs:
             IRONIC_ENABLED_DEPLOY_INTERFACES=direct,fake
             SWIFT_ENABLE_TEMPURLS=True
             SWIFT_TEMPURL_KEY=secretkey
-          enabled_services: "ir-api,ir-cond,s-account,s-container,s-object,s-proxy,q-svc,q-agt,q-dhcp,q-l3,q-meta,-cinder,-c-sch,-c-api,-c-vol,-c-bak,-ovn,-ovn-controller,-ovn-northd,-q-ovn-metadata-agent,${{ matrix.additional_services }}"
+          enabled_services: "ir-api,ir-cond,s-account,s-container,s-object,s-proxy,q-svc,q-agt,q-dhcp,q-l3,q-meta,-cinder,-c-sch,-c-api,-c-vol,-c-bak,-ovn,-ovn-controller,-ovn-northd,-q-ovn-metadata-agent,openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml
index 9ee87e2ed..4f0175b5d 100644
--- a/.github/workflows/functional-basic.yaml
+++ b/.github/workflows/functional-basic.yaml
@@ -17,19 +17,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: basic tests on OpenStack ${{ matrix.name }}
     steps:
@@ -39,7 +32,7 @@ jobs:
         uses: gophercloud/devstack-action@v0.19
         with:
           branch: ${{ matrix.openstack_version }}
-          enabled_services: 's-account,s-container,s-object,s-proxy,${{ matrix.additional_services }}'
+          enabled_services: 's-account,s-container,s-object,s-proxy,openstack-cli-server'
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml
index 663213e1b..fa64f8a1c 100644
--- a/.github/workflows/functional-blockstorage.yaml
+++ b/.github/workflows/functional-blockstorage.yaml
@@ -22,19 +22,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Cinder on OpenStack ${{ matrix.name }}
     steps:
@@ -46,7 +39,7 @@ jobs:
           branch: ${{ matrix.openstack_version }}
           conf_overrides: |
             CINDER_ISCSI_HELPER=lioadm
-          enabled_services: "s-account,s-container,s-object,s-proxy,c-bak,${{ matrix.additional_services }}"
+          enabled_services: "s-account,s-container,s-object,s-proxy,c-bak,openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml
index da091393f..a82177740 100644
--- a/.github/workflows/functional-compute.yaml
+++ b/.github/workflows/functional-compute.yaml
@@ -22,19 +22,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Nova on OpenStack ${{ matrix.name }}
     steps:
@@ -46,7 +39,7 @@ jobs:
           branch: ${{ matrix.openstack_version }}
           conf_overrides: |
             CINDER_ISCSI_HELPER=lioadm
-          enabled_services: "${{ matrix.additional_services }}"
+          enabled_services: "openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml
index 66bbda418..088c97ae4 100644
--- a/.github/workflows/functional-containerinfra.yaml
+++ b/.github/workflows/functional-containerinfra.yaml
@@ -31,10 +31,9 @@ jobs:
 
               enable_plugin magnum https://github.com/openstack/magnum master
               MAGNUMCLIENT_BRANCH=master
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
+            ubuntu_version: "24.04"
             devstack_conf_overrides: |
               # ensure we're using a working version of setuptools
               if [ -n "\$TOP_DIR" ]; then
@@ -44,21 +43,12 @@ jobs:
 
               enable_plugin magnum https://github.com/openstack/magnum stable/2025.1
               MAGNUMCLIENT_BRANCH=stable/2025.1
-            additional_services: "openstack-cli-server"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
             devstack_conf_overrides: |
               enable_plugin magnum https://github.com/openstack/magnum stable/2024.2
               MAGNUMCLIENT_BRANCH=stable/2024.2
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            devstack_conf_overrides: |
-              enable_plugin magnum https://github.com/openstack/magnum stable/2024.1
-              MAGNUMCLIENT_BRANCH=stable/2024.1
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Magnum on OpenStack ${{ matrix.name }}
     steps:
@@ -76,7 +66,7 @@ jobs:
             KEYSTONE_ADMIN_ENDPOINT=true
 
             ${{ matrix.devstack_conf_overrides }}
-          enabled_services: "h-eng,h-api,h-api-cfn,h-api-cw,${{ matrix.additional_services }}"
+          enabled_services: "h-eng,h-api,h-api-cfn,h-api-cw,openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml
index fb7c325f1..d5f3cac51 100644
--- a/.github/workflows/functional-dns.yaml
+++ b/.github/workflows/functional-dns.yaml
@@ -28,19 +28,12 @@ jobs:
                 sed -i 's/setuptools\[core\]$/setuptools[core]==79.0.1/g' \$TOP_DIR/lib/infra \$TOP_DIR/inc/python
                 sed -i 's/pip_install "-U" "pbr"/pip_install "-U" "pbr" "setuptools[core]==79.0.1"/g' \$TOP_DIR/lib/infra
               fi
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Designate on OpenStack ${{ matrix.name }}
     steps:
@@ -54,7 +47,7 @@ jobs:
             enable_plugin designate https://github.com/openstack/designate ${{ matrix.openstack_version }}
 
             ${{ matrix.devstack_conf_overrides }}
-          enabled_services: "designate,designate-central,designate-api,designate-worker,designate-producer,designate-mdns,${{ matrix.additional_services }}"
+          enabled_services: "designate,designate-central,designate-api,designate-worker,designate-producer,designate-mdns,openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml
index ab0b620fd..a9f603430 100644
--- a/.github/workflows/functional-fwaas_v2.yaml
+++ b/.github/workflows/functional-fwaas_v2.yaml
@@ -26,19 +26,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: FWaaS_v2 on OpenStack ${{ matrix.name }}
     steps:
@@ -67,7 +60,7 @@ jobs:
             [[post-config|\$NEUTRON_CONF]]
             [oslo_policy]
             policy_dirs = /tmp/neutron-policies
-          enabled_services: 'q-svc,q-agt,q-dhcp,q-l3,q-meta,q-fwaas-v2,-cinder,-horizon,-tempest,-swift,-c-sch,-c-api,-c-vol,-c-bak,-ovn,-ovn-controller,-ovn-northd,-q-ovn-metadata-agent,${{ matrix.additional_services }}'
+          enabled_services: 'q-svc,q-agt,q-dhcp,q-l3,q-meta,q-fwaas-v2,-cinder,-horizon,-tempest,-swift,-c-sch,-c-api,-c-vol,-c-bak,-ovn,-ovn-controller,-ovn-northd,-q-ovn-metadata-agent,openstack-cli-server'
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml
index 543837208..bbbe99b44 100644
--- a/.github/workflows/functional-identity.yaml
+++ b/.github/workflows/functional-identity.yaml
@@ -22,19 +22,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Keystone on OpenStack ${{ matrix.name }}
     steps:
@@ -44,7 +37,7 @@ jobs:
         uses: gophercloud/devstack-action@v0.19
         with:
           branch: ${{ matrix.openstack_version }}
-          enabled_services: "${{ matrix.additional_services }}"
+          enabled_services: "openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-image.yaml b/.github/workflows/functional-image.yaml
index b20d7584f..39a3dd681 100644
--- a/.github/workflows/functional-image.yaml
+++ b/.github/workflows/functional-image.yaml
@@ -22,19 +22,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Glance on OpenStack ${{ matrix.name }}
     steps:
@@ -44,7 +37,7 @@ jobs:
         uses: gophercloud/devstack-action@v0.19
         with:
           branch: ${{ matrix.openstack_version }}
-          enabled_services: "${{ matrix.additional_services }}"
+          enabled_services: "openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml
index bac49fef6..01e57bd3e 100644
--- a/.github/workflows/functional-keymanager.yaml
+++ b/.github/workflows/functional-keymanager.yaml
@@ -28,25 +28,18 @@ jobs:
                 sed -i 's/setuptools\[core\]$/setuptools[core]==79.0.1/g' \$TOP_DIR/lib/infra \$TOP_DIR/inc/python
                 sed -i 's/pip_install "-U" "pbr"/pip_install "-U" "pbr" "setuptools[core]==79.0.1"/g' \$TOP_DIR/lib/infra
               fi
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
+            ubuntu_version: "24.04"
             devstack_conf_overrides: |
               # ensure we're using a working version of setuptools
               if [ -n "\$TOP_DIR" ]; then
                 sed -i 's/setuptools\[core\]$/setuptools[core]==79.0.1/g' \$TOP_DIR/lib/infra \$TOP_DIR/inc/python
                 sed -i 's/pip_install "-U" "pbr"/pip_install "-U" "pbr" "setuptools[core]==79.0.1"/g' \$TOP_DIR/lib/infra
               fi
-            additional_services: "openstack-cli-server"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Barbican on OpenStack ${{ matrix.name }}
     steps:
@@ -60,7 +53,7 @@ jobs:
             enable_plugin barbican https://github.com/openstack/barbican ${{ matrix.openstack_version }}
 
             ${{ matrix.devstack_conf_overrides }}
-          enabled_services: "barbican-svc,barbican-retry,barbican-keystone-listener,${{ matrix.additional_services }}"
+          enabled_services: "barbican-svc,barbican-retry,barbican-keystone-listener,openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml
index b1a4f5d2d..7880244f0 100644
--- a/.github/workflows/functional-loadbalancer.yaml
+++ b/.github/workflows/functional-loadbalancer.yaml
@@ -28,19 +28,12 @@ jobs:
                 sed -i 's/setuptools\[core\]$/setuptools[core]==79.0.1/g' \$TOP_DIR/lib/infra \$TOP_DIR/inc/python
                 sed -i 's/pip_install "-U" "pbr"/pip_install "-U" "pbr" "setuptools[core]==79.0.1"/g' \$TOP_DIR/lib/infra
               fi
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Octavia on OpenStack ${{ matrix.name }}
     steps:
@@ -55,7 +48,7 @@ jobs:
             enable_plugin neutron https://github.com/openstack/neutron ${{ matrix.openstack_version }}
 
             ${{ matrix.devstack_conf_overrides }}
-          enabled_services: "octavia,o-api,o-cw,o-hk,o-hm,o-da,neutron-qos,${{ matrix.additional_services }}"
+          enabled_services: "octavia,o-api,o-cw,o-hk,o-hm,o-da,neutron-qos,openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml
index 55c0566df..0f099084a 100644
--- a/.github/workflows/functional-messaging.yaml
+++ b/.github/workflows/functional-messaging.yaml
@@ -22,19 +22,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Zaqar on OpenStack ${{ matrix.name }}
     steps:
@@ -47,7 +40,7 @@ jobs:
           conf_overrides: |
             enable_plugin zaqar https://github.com/openstack/zaqar ${{ matrix.openstack_version }}
             ZAQARCLIENT_BRANCH=${{ matrix.openstack_version }}
-          enabled_services: "${{ matrix.additional_services }}"
+          enabled_services: "openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml
index c8a3282ff..efe7743a1 100644
--- a/.github/workflows/functional-networking.yaml
+++ b/.github/workflows/functional-networking.yaml
@@ -22,19 +22,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Neutron on OpenStack ${{ matrix.name }}
     steps:
@@ -62,7 +55,7 @@ jobs:
             [[post-config|\$NEUTRON_CONF]]
             [oslo_policy]
             policy_dirs = /tmp/neutron-policies
-          enabled_services: "neutron-dns,neutron-qos,neutron-segments,neutron-trunk,neutron-uplink-status-propagation,neutron-network-segment-range,neutron-port-forwarding,${{ matrix.additional_services }}"
+          enabled_services: "neutron-dns,neutron-qos,neutron-segments,neutron-trunk,neutron-uplink-status-propagation,neutron-network-segment-range,neutron-port-forwarding,openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml
index 80d286591..d1b357d3b 100644
--- a/.github/workflows/functional-objectstorage.yaml
+++ b/.github/workflows/functional-objectstorage.yaml
@@ -22,19 +22,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Swift on OpenStack ${{ matrix.name }}
     steps:
@@ -50,7 +43,7 @@ jobs:
             [[post-config|\$SWIFT_CONFIG_PROXY_SERVER]]
             [filter:versioned_writes]
             allow_object_versioning = true
-          enabled_services: 's-account,s-container,s-object,s-proxy,${{ matrix.additional_services }}'
+          enabled_services: 's-account,s-container,s-object,s-proxy,openstack-cli-server'
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml
index f29c5f1f0..402a21c33 100644
--- a/.github/workflows/functional-orchestration.yaml
+++ b/.github/workflows/functional-orchestration.yaml
@@ -22,19 +22,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Heat on OpenStack ${{ matrix.name }}
     steps:
@@ -46,7 +39,7 @@ jobs:
           branch: ${{ matrix.openstack_version }}
           conf_overrides: |
             enable_plugin heat https://github.com/openstack/heat ${{ matrix.openstack_version }}
-          enabled_services: 'h-eng,h-api,h-api-cfn,h-api-cw,${{ matrix.additional_services }}'
+          enabled_services: 'h-eng,h-api,h-api-cfn,h-api-cw,openstack-cli-server'
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml
index 8ef04ac17..4b14c2a2d 100644
--- a/.github/workflows/functional-placement.yaml
+++ b/.github/workflows/functional-placement.yaml
@@ -22,19 +22,12 @@ jobs:
           - name: "master"
             openstack_version: "master"
             ubuntu_version: "24.04"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Placement on OpenStack ${{ matrix.name }}
     steps:
@@ -44,7 +37,7 @@ jobs:
         uses: gophercloud/devstack-action@v0.19
         with:
           branch: ${{ matrix.openstack_version }}
-          enabled_services: "${{ matrix.additional_services }}"
+          enabled_services: "openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml
index 59b9d360e..5a9b55d41 100644
--- a/.github/workflows/functional-sharedfilesystems.yaml
+++ b/.github/workflows/functional-sharedfilesystems.yaml
@@ -28,19 +28,12 @@ jobs:
                 sed -i 's/setuptools\[core\]$/setuptools[core]==79.0.1/g' \$TOP_DIR/lib/infra \$TOP_DIR/inc/python
                 sed -i 's/pip_install "-U" "pbr"/pip_install "-U" "pbr" "setuptools[core]==79.0.1"/g' \$TOP_DIR/lib/infra
               fi
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
+            ubuntu_version: "24.04"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Manila on OpenStack ${{ matrix.name }}
     steps:
@@ -68,7 +61,7 @@ jobs:
             MANILA_INSTALL_TEMPEST_PLUGIN_SYSTEMWIDE=false
 
             ${{ matrix.devstack_conf_overrides }}
-          enabled_services: "${{ matrix.additional_services }}"
+          enabled_services: "openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/.github/workflows/functional-workflow.yaml b/.github/workflows/functional-workflow.yaml
index 47f45bae7..b690d7f07 100644
--- a/.github/workflows/functional-workflow.yaml
+++ b/.github/workflows/functional-workflow.yaml
@@ -23,22 +23,14 @@ jobs:
             openstack_version: "master"
             ubuntu_version: "24.04"
             mistral_plugin_version: "master"
-            additional_services: "openstack-cli-server"
           - name: "epoxy"
             openstack_version: "stable/2025.1"
-            ubuntu_version: "22.04"
+            ubuntu_version: "24.04"
             mistral_plugin_version: "stable/2025.1"
-            additional_services: "openstack-cli-server"
           - name: "dalmatian"
             openstack_version: "stable/2024.2"
             ubuntu_version: "22.04"
             mistral_plugin_version: "stable/2024.2"
-            additional_services: "openstack-cli-server"
-          - name: "caracal"
-            openstack_version: "stable/2024.1"
-            ubuntu_version: "22.04"
-            mistral_plugin_version: "stable/2024.1"
-            additional_services: ""
     runs-on: ubuntu-${{ matrix.ubuntu_version }}
     name: Mistral on Deploy OpenStack ${{ matrix.name }}
     steps:
@@ -50,7 +42,7 @@ jobs:
           branch: ${{ matrix.openstack_version }}
           conf_overrides: |
             enable_plugin mistral https://github.com/openstack/mistral ${{ matrix.mistral_plugin_version }}
-          enabled_services: "mistral,mistral-api,mistral-engine,mistral-executor,mistral-event-engine,${{ matrix.additional_services }}"
+          enabled_services: "mistral,mistral-api,mistral-engine,mistral-executor,mistral-event-engine,openstack-cli-server"
       - name: Checkout go
         uses: actions/setup-go@v5
         with:
diff --git a/docs/contributor-tutorial/step-04-acceptance-testing.md b/docs/contributor-tutorial/step-04-acceptance-testing.md
index fe8271743..a6708ee5f 100644
--- a/docs/contributor-tutorial/step-04-acceptance-testing.md
+++ b/docs/contributor-tutorial/step-04-acceptance-testing.md
@@ -17,9 +17,13 @@ And, to be frank, submitting untested code will inevitably cause someone else
 to have to spend time fixing it.
 
 If you don't have an OpenStack environment to test with, we have lots of
-documentation [here](/acceptance) to help you build your own small OpenStack
+documentation [here](/internal/acceptance) to help you build your own small OpenStack
 environment for testing.
 
+If you add new API calls/actions e.g. also make sure to include them into the
+respective [acceptance tests](/internal/acceptance/openstack) for the code to be
+validated against all the supported OpenStack versions.
+
 ---
 
 Once you've confirmed you are able to test your code, proceed to
diff --git a/docs/contributor-tutorial/step-05-pull-requests.md b/docs/contributor-tutorial/step-05-pull-requests.md
index cb340a92c..1f5373bc5 100644
--- a/docs/contributor-tutorial/step-05-pull-requests.md
+++ b/docs/contributor-tutorial/step-05-pull-requests.md
@@ -99,7 +99,10 @@ generate your own fixtures using the OpenStack environment you're
 Since unit tests are not run against an actual OpenStack environment,
 acceptance tests can arguably be more important. The acceptance tests that you
 include in your Pull Request should confirm that your implemented code works
-as intended with an actual OpenStack environment.
+as intended with an actual OpenStack environment. We run our functional jobs
+against all supported Skip Level Upgrade Release Process (SLURP) releases as
+well as `master`. This information is sourced from
+[releases.openstack.org](https://releases.openstack.org/).
 
 ### Documentation
 
diff --git a/openstack/compute/v2/hypervisors/results.go b/openstack/compute/v2/hypervisors/results.go
index 0a35dfdf0..c73f239cd 100644
--- a/openstack/compute/v2/hypervisors/results.go
+++ b/openstack/compute/v2/hypervisors/results.go
@@ -11,6 +11,7 @@ import (
 
 // Topology represents a CPU Topology.
 type Topology struct {
+	Cells   int `json:"cells"`
 	Sockets int `json:"sockets"`
 	Cores   int `json:"cores"`
 	Threads int `json:"threads"`
diff --git a/openstack/compute/v2/servers/results.go b/openstack/compute/v2/servers/results.go
index 385001c8d..bfecce29e 100644
--- a/openstack/compute/v2/servers/results.go
+++ b/openstack/compute/v2/servers/results.go
@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"net/url"
 	"path"
+	"strconv"
 	"time"
 
 	"github.com/gophercloud/gophercloud/v2"
@@ -283,6 +284,9 @@ type Server struct {
 	// Locked indicates the lock status of the server
 	// This requires microversion 2.9 or later
 	Locked *bool `json:"locked"`
+
+	// ConfigDrive enables metadata injection through a configuration drive.
+	ConfigDrive bool `json:"-"`
 }
 
 type AttachedVolume struct {
@@ -343,6 +347,7 @@ func (r *Server) UnmarshalJSON(b []byte) error {
 		Image        any                             `json:"image"`
 		LaunchedAt   gophercloud.JSONRFC3339MilliNoZ `json:"OS-SRV-USG:launched_at"`
 		TerminatedAt gophercloud.JSONRFC3339MilliNoZ `json:"OS-SRV-USG:terminated_at"`
+		ConfigDrive  any                             `json:"config_drive"`
 	}
 	err := json.Unmarshal(b, &s)
 	if err != nil {
@@ -364,6 +369,24 @@ func (r *Server) UnmarshalJSON(b []byte) error {
 	r.LaunchedAt = time.Time(s.LaunchedAt)
 	r.TerminatedAt = time.Time(s.TerminatedAt)
 
+	switch t := s.ConfigDrive.(type) {
+	case nil:
+		r.ConfigDrive = false
+	case bool:
+		r.ConfigDrive = t
+	case string:
+		if t == "" {
+			r.ConfigDrive = false
+		} else {
+			r.ConfigDrive, err = strconv.ParseBool(t)
+			if err != nil {
+				return fmt.Errorf("failed to parse ConfigDrive %q: %v", t, err)
+			}
+		}
+	default:
+		return fmt.Errorf("unknown type for ConfigDrive: %T (value: %v)", t, t)
+	}
+
 	return err
 }
 
diff --git a/openstack/identity/v3/roles/requests.go b/openstack/identity/v3/roles/requests.go
index 2e40e93d6..260aa153c 100644
--- a/openstack/identity/v3/roles/requests.go
+++ b/openstack/identity/v3/roles/requests.go
@@ -9,6 +9,14 @@ import (
 	"github.com/gophercloud/gophercloud/v2/pagination"
 )
 
+// Option is a specific option defined at the API to enable features
+// on a role.
+type Option string
+
+const (
+	Immutable Option = "immutable"
+)
+
 // ListOptsBuilder allows extensions to add additional parameters to
 // the List request
 type ListOptsBuilder interface {
@@ -86,8 +94,14 @@ type CreateOpts struct {
 	// DomainID is the ID of the domain the role belongs to.
 	DomainID string `json:"domain_id,omitempty"`
 
+	// Description is the description of the new role.
+	Description string `json:"description,omitempty"`
+
 	// Extra is free-form extra key/value pairs to describe the role.
 	Extra map[string]any `json:"-"`
+
+	// Options are defined options in the API to enable certain features.
+	Options map[Option]any `json:"options,omitempty"`
 }
 
 // ToRoleCreateMap formats a CreateOpts into a create request.
@@ -130,11 +144,17 @@ type UpdateOptsBuilder interface {
 
 // UpdateOpts provides options for updating a role.
 type UpdateOpts struct {
-	// Name is the name of the new role.
+	// Name is an updated name for the role.
 	Name string `json:"name,omitempty"`
 
+	// Description is an updated description for the role.
+	Description *string `json:"description,omitempty"`
+
 	// Extra is free-form extra key/value pairs to describe the role.
 	Extra map[string]any `json:"-"`
+
+	// Options are defined options in the API to enable certain features.
+	Options map[Option]any `json:"options,omitempty"`
 }
 
 // ToRoleUpdateMap formats a UpdateOpts into an update request.
diff --git a/openstack/identity/v3/roles/results.go b/openstack/identity/v3/roles/results.go
index 075e3cbe7..4c51e5f60 100644
--- a/openstack/identity/v3/roles/results.go
+++ b/openstack/identity/v3/roles/results.go
@@ -21,8 +21,14 @@ type Role struct {
 	// Name is the role name
 	Name string `json:"name"`
 
+	// Description is the description of the role.
+	Description string `json:"description"`
+
 	// Extra is a collection of miscellaneous key/values.
 	Extra map[string]any `json:"-"`
+
+	// Options are a set of defined options that allow certain features for a role
+	Options map[Option]any `json:"options"`
 }
 
 func (r *Role) UnmarshalJSON(b []byte) error {
diff --git a/openstack/loadbalancer/v2/quotas/doc.go b/openstack/loadbalancer/v2/quotas/doc.go
index c2c63512c..77c560022 100644
--- a/openstack/loadbalancer/v2/quotas/doc.go
+++ b/openstack/loadbalancer/v2/quotas/doc.go
@@ -30,5 +30,15 @@ Example to Update project quotas
 	    }
 
 	    fmt.Printf("quotas: %#v\n", quotasInfo)
+
+Example to Delete project quotas
+
+	projectID = "23d5d3f79dfa4f73b72b8b0b0063ec55"
+	err := quotas.Delete(context.TODO(), networkClient, projectID).ExtractErr()
+	if err != nil {
+	    log.Fatal(err)
+	}
+
+	fmt.Printf("Deleted quotas for project: %s\n", projectID)
 */
 package quotas
diff --git a/openstack/loadbalancer/v2/quotas/requests.go b/openstack/loadbalancer/v2/quotas/requests.go
index 8b7771eea..f07f9392e 100644
--- a/openstack/loadbalancer/v2/quotas/requests.go
+++ b/openstack/loadbalancer/v2/quotas/requests.go
@@ -63,3 +63,9 @@ func Update(ctx context.Context, c *gophercloud.ServiceClient, projectID string,
 	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
 	return
 }
+
+func Delete(ctx context.Context, c *gophercloud.ServiceClient, projectID string) (r DeleteResult) {
+	resp, err := c.Delete(ctx, deleteURL(c, projectID), nil)
+	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+	return
+}
diff --git a/openstack/loadbalancer/v2/quotas/results.go b/openstack/loadbalancer/v2/quotas/results.go
index e1ef38598..5487d7a84 100644
--- a/openstack/loadbalancer/v2/quotas/results.go
+++ b/openstack/loadbalancer/v2/quotas/results.go
@@ -96,3 +96,9 @@ func (r *Quota) UnmarshalJSON(b []byte) error {
 
 	return nil
 }
+
+// DeleteResult is the response from a Delete operation. Call its ExtractErr
+// method to determine if the request succeeded or failed.
+type DeleteResult struct {
+	gophercloud.ErrResult
+}
diff --git a/openstack/loadbalancer/v2/quotas/urls.go b/openstack/loadbalancer/v2/quotas/urls.go
index 0365d9c8a..545e83230 100644
--- a/openstack/loadbalancer/v2/quotas/urls.go
+++ b/openstack/loadbalancer/v2/quotas/urls.go
@@ -15,3 +15,7 @@ func getURL(c *gophercloud.ServiceClient, projectID string) string {
 func updateURL(c *gophercloud.ServiceClient, projectID string) string {
 	return resourceURL(c, projectID)
 }
+
+func deleteURL(c *gophercloud.ServiceClient, projectID string) string {
+	return getURL(c, projectID)
+}
diff --git a/openstack/networking/v2/extensions/quotas/doc.go b/openstack/networking/v2/extensions/quotas/doc.go
index fe1cc2631..5e5ec3e58 100644
--- a/openstack/networking/v2/extensions/quotas/doc.go
+++ b/openstack/networking/v2/extensions/quotas/doc.go
@@ -43,5 +43,15 @@ Example to Update project quotas
 	}
 
 	fmt.Printf("quotas: %#v\n", quotasInfo)
+
+Example to Delete project quotas
+
+	projectID = "23d5d3f79dfa4f73b72b8b0b0063ec55"
+	err := quotas.Delete(context.TODO(), networkClient, projectID).ExtractErr()
+	if err != nil {
+	    log.Fatal(err)
+	}
+
+	fmt.Printf("Deleted quotas for project: %s\n", projectID)
 */
 package quotas
diff --git a/openstack/networking/v2/extensions/quotas/requests.go b/openstack/networking/v2/extensions/quotas/requests.go
index 859c552ce..628936884 100644
--- a/openstack/networking/v2/extensions/quotas/requests.go
+++ b/openstack/networking/v2/extensions/quotas/requests.go
@@ -78,3 +78,9 @@ func Update(ctx context.Context, c *gophercloud.ServiceClient, projectID string,
 	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
 	return
 }
+
+func Delete(ctx context.Context, c *gophercloud.ServiceClient, projectID string) (r DeleteResult) {
+	resp, err := c.Delete(ctx, deleteURL(c, projectID), nil)
+	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+	return
+}
diff --git a/openstack/networking/v2/extensions/quotas/results.go b/openstack/networking/v2/extensions/quotas/results.go
index 8b1ae8a95..7e3931220 100644
--- a/openstack/networking/v2/extensions/quotas/results.go
+++ b/openstack/networking/v2/extensions/quotas/results.go
@@ -171,3 +171,9 @@ func (q *QuotaDetail) UnmarshalJSON(b []byte) error {
 
 	return nil
 }
+
+// DeleteResult is the response from a Delete operation. Call its ExtractErr
+// method to determine if the request succeeded or failed.
+type DeleteResult struct {
+	gophercloud.ErrResult
+}
diff --git a/openstack/networking/v2/extensions/quotas/urls.go b/openstack/networking/v2/extensions/quotas/urls.go
index 94cbe2388..726c4da8e 100644
--- a/openstack/networking/v2/extensions/quotas/urls.go
+++ b/openstack/networking/v2/extensions/quotas/urls.go
@@ -24,3 +24,7 @@ func getDetailURL(c *gophercloud.ServiceClient, projectID string) string {
 func updateURL(c *gophercloud.ServiceClient, projectID string) string {
 	return resourceURL(c, projectID)
 }
+
+func deleteURL(c *gophercloud.ServiceClient, projectID string) string {
+	return getURL(c, projectID)
+}



Test patch:
diff --git a/internal/acceptance/openstack/identity/v3/roles_test.go b/internal/acceptance/openstack/identity/v3/roles_test.go
index b17ecd904..753736843 100644
--- a/internal/acceptance/openstack/identity/v3/roles_test.go
+++ b/internal/acceptance/openstack/identity/v3/roles_test.go
@@ -58,10 +58,14 @@ func TestRolesCRUD(t *testing.T) {
 	th.AssertNoErr(t, err)
 
 	createOpts := roles.CreateOpts{
-		Name:     "testrole",
-		DomainID: "default",
+		Name:        "role-test",
+		DomainID:    "default",
+		Description: "test description",
 		Extra: map[string]any{
-			"description": "test role description",
+			"email": "testrole@example.com",
+		},
+		Options: map[roles.Option]any{
+			"immutable": false,
 		},
 	}
 
@@ -93,10 +97,14 @@ func TestRolesCRUD(t *testing.T) {
 	}
 
 	th.AssertEquals(t, found, true)
-
+	description := "updated role test"
 	updateOpts := roles.UpdateOpts{
+		Description: &description,
 		Extra: map[string]any{
-			"description": "updated test role description",
+			"email": "updatedtestrole@example.com",
+		},
+		Options: map[roles.Option]any{
+			"immutable": nil,
 		},
 	}
 
@@ -106,7 +114,9 @@ func TestRolesCRUD(t *testing.T) {
 	tools.PrintResource(t, newRole)
 	tools.PrintResource(t, newRole.Extra)
 
-	th.AssertEquals(t, newRole.Extra["description"], "updated test role description")
+	th.AssertEquals(t, newRole.Description, description)
+	th.AssertEquals(t, newRole.Extra["email"], "updatedtestrole@example.com")
+
 }
 
 func TestRolesFilterList(t *testing.T) {
diff --git a/internal/acceptance/openstack/loadbalancer/v2/quotas_test.go b/internal/acceptance/openstack/loadbalancer/v2/quotas_test.go
index cc778e540..87f9d7621 100644
--- a/internal/acceptance/openstack/loadbalancer/v2/quotas_test.go
+++ b/internal/acceptance/openstack/loadbalancer/v2/quotas_test.go
@@ -80,3 +80,13 @@ func TestQuotasUpdate(t *testing.T) {
 
 	tools.PrintResource(t, restoredQuotas)
 }
+
+func TestQuotasDelete(t *testing.T) {
+	clients.RequireAdmin(t)
+
+	client, err := clients.NewLoadBalancerV2Client()
+	th.AssertNoErr(t, err)
+
+	err = quotas.Delete(context.TODO(), client, os.Getenv("OS_PROJECT_NAME")).ExtractErr()
+	th.AssertNoErr(t, err)
+}
diff --git a/internal/acceptance/openstack/networking/v2/extensions/quotas/quotas_test.go b/internal/acceptance/openstack/networking/v2/extensions/quotas/quotas_test.go
index 3eaf7d232..06b228079 100644
--- a/internal/acceptance/openstack/networking/v2/extensions/quotas/quotas_test.go
+++ b/internal/acceptance/openstack/networking/v2/extensions/quotas/quotas_test.go
@@ -63,3 +63,13 @@ func TestQuotasUpdate(t *testing.T) {
 
 	tools.PrintResource(t, restoredQuotas)
 }
+
+func TestQuotasDelete(t *testing.T) {
+	clients.RequireAdmin(t)
+
+	client, err := clients.NewNetworkV2Client()
+	th.AssertNoErr(t, err)
+
+	err = quotas.Delete(context.TODO(), client, os.Getenv("OS_PROJECT_NAME")).ExtractErr()
+	th.AssertNoErr(t, err)
+}
diff --git a/openstack/identity/v3/roles/testing/fixtures_test.go b/openstack/identity/v3/roles/testing/fixtures_test.go
index 1e8403eb6..7cb374d2d 100644
--- a/openstack/identity/v3/roles/testing/fixtures_test.go
+++ b/openstack/identity/v3/roles/testing/fixtures_test.go
@@ -34,8 +34,9 @@ const ListOutput = `
                 "self": "https://example.com/identity/v3/roles/9fe1d3"
             },
             "name": "support",
+			"description": "read-only support role",
             "extra": {
-                "description": "read-only support role"
+                "test": "this is for the test"
             }
         }
     ]
@@ -52,9 +53,31 @@ const GetOutput = `
             "self": "https://example.com/identity/v3/roles/9fe1d3"
         },
         "name": "support",
-        "extra": {
-            "description": "read-only support role"
-        }
+        "description": "read-only support role",
+		"extra": {
+			"test": "this is for the test"
+		} 
+    }
+}
+`
+
+// GetOutputWithOptions provides a Get result of a role with options.
+const GetOutputWithOptions = `
+{
+    "role": {
+        "domain_id": "1789d1",
+        "id": "9fe1d3",
+        "links": {
+            "self": "https://example.com/identity/v3/roles/9fe1d3"
+        },
+        "name": "support",
+        "description": "read-only support role",
+		"options": {
+			"immutable": true
+		},
+		"extra": {
+			"test": "this is for the test"
+		}
     }
 }
 `
@@ -65,8 +88,24 @@ const CreateRequest = `
     "role": {
         "domain_id": "1789d1",
         "name": "support",
-        "description": "read-only support role"
-    }
+		"description": "read-only support role",
+		"test": "this is for the test"
+	}
+}
+`
+
+// CreateRequestWithOptions provides the input to a Create request with Options.
+const CreateRequestWithOptions = `
+{
+    "role": {
+        "domain_id": "1789d1",
+        "name": "support",
+		"description": "read-only support role",
+		"test": "this is for the test",
+		"options": {
+			"immutable": true
+		}
+	}
 }
 `
 
@@ -74,7 +113,10 @@ const CreateRequest = `
 const UpdateRequest = `
 {
     "role": {
-        "description": "admin read-only support role"
+        "description": "admin read-only support role",
+		"options": {
+			"immutable": false
+		}
     }
 }
 `
@@ -91,7 +133,10 @@ const UpdateOutput = `
         "name": "support",
         "extra": {
             "description": "admin read-only support role"
-        }
+        },
+		"options": {
+			"immutable": false
+		}
     }
 }
 `
@@ -318,9 +363,27 @@ var SecondRole = roles.Role{
 	Links: map[string]any{
 		"self": "https://example.com/identity/v3/roles/9fe1d3",
 	},
-	Name: "support",
+	Name:        "support",
+	Description: "read-only support role",
 	Extra: map[string]any{
-		"description": "read-only support role",
+		"test": "this is for the test",
+	},
+}
+
+// SecondRoleWithOptions is the second role in the List request
+var SecondRoleWithOptions = roles.Role{
+	DomainID: "1789d1",
+	ID:       "9fe1d3",
+	Links: map[string]any{
+		"self": "https://example.com/identity/v3/roles/9fe1d3",
+	},
+	Name:        "support",
+	Description: "read-only support role",
+	Extra: map[string]any{
+		"test": "this is for the test",
+	},
+	Options: map[roles.Option]any{
+		roles.Immutable: true,
 	},
 }
 
@@ -335,6 +398,9 @@ var SecondRoleUpdated = roles.Role{
 	Extra: map[string]any{
 		"description": "admin read-only support role",
 	},
+	Options: map[roles.Option]any{
+		roles.Immutable: false,
+	},
 }
 
 // ExpectedRolesSlice is the slice of roles expected to be returned from ListOutput.
@@ -381,6 +447,19 @@ func HandleCreateRoleSuccessfully(t *testing.T, fakeServer th.FakeServer) {
 	})
 }
 
+// HandleCreateRoleWithOptionsSuccessfully creates an HTTP handler at `/roles` on the
+// test handler mux that tests role creation.
+func HandleCreateWithOptionsRoleSuccessfully(t *testing.T, fakeServer th.FakeServer) {
+	fakeServer.Mux.HandleFunc("/roles", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "POST")
+		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+		th.TestJSONRequest(t, r, CreateRequestWithOptions)
+
+		w.WriteHeader(http.StatusCreated)
+		fmt.Fprint(w, GetOutputWithOptions)
+	})
+}
+
 // HandleUpdateRoleSuccessfully creates an HTTP handler at `/roles` on the
 // test handler mux that tests role update.
 func HandleUpdateRoleSuccessfully(t *testing.T, fakeServer th.FakeServer) {
diff --git a/openstack/identity/v3/roles/testing/requests_test.go b/openstack/identity/v3/roles/testing/requests_test.go
index fb3021064..7ef508590 100644
--- a/openstack/identity/v3/roles/testing/requests_test.go
+++ b/openstack/identity/v3/roles/testing/requests_test.go
@@ -40,7 +40,7 @@ func TestListRolesAllPages(t *testing.T) {
 	actual, err := roles.ExtractRoles(allPages)
 	th.AssertNoErr(t, err)
 	th.CheckDeepEquals(t, ExpectedRolesSlice, actual)
-	th.AssertEquals(t, ExpectedRolesSlice[1].Extra["description"], "read-only support role")
+	th.AssertEquals(t, ExpectedRolesSlice[1].Extra["test"], "this is for the test")
 }
 
 func TestListUsersFiltersCheck(t *testing.T) {
@@ -92,10 +92,11 @@ func TestCreateRole(t *testing.T) {
 	HandleCreateRoleSuccessfully(t, fakeServer)
 
 	createOpts := roles.CreateOpts{
-		Name:     "support",
-		DomainID: "1789d1",
+		Name:        "support",
+		DomainID:    "1789d1",
+		Description: "read-only support role",
 		Extra: map[string]any{
-			"description": "read-only support role",
+			"test": "this is for the test",
 		},
 	}
 
@@ -104,6 +105,28 @@ func TestCreateRole(t *testing.T) {
 	th.CheckDeepEquals(t, SecondRole, *actual)
 }
 
+func TestCreateWithOptionsRole(t *testing.T) {
+	fakeServer := th.SetupHTTP()
+	defer fakeServer.Teardown()
+	HandleCreateWithOptionsRoleSuccessfully(t, fakeServer)
+
+	createOpts := roles.CreateOpts{
+		Name:        "support",
+		DomainID:    "1789d1",
+		Description: "read-only support role",
+		Options: map[roles.Option]any{
+			roles.Immutable: true,
+		},
+		Extra: map[string]any{
+			"test": "this is for the test",
+		},
+	}
+
+	actual, err := roles.Create(context.TODO(), client.ServiceClient(fakeServer), createOpts).Extract()
+	th.AssertNoErr(t, err)
+	th.CheckDeepEquals(t, SecondRoleWithOptions, *actual)
+}
+
 func TestUpdateRole(t *testing.T) {
 	fakeServer := th.SetupHTTP()
 	defer fakeServer.Teardown()
@@ -113,6 +136,9 @@ func TestUpdateRole(t *testing.T) {
 		Extra: map[string]any{
 			"description": "admin read-only support role",
 		},
+		Options: map[roles.Option]any{
+			roles.Immutable: false,
+		},
 	}
 
 	actual, err := roles.Update(context.TODO(), client.ServiceClient(fakeServer), "9fe1d3", updateOpts).Extract()
diff --git a/openstack/loadbalancer/v2/quotas/testing/fixtures_test.go b/openstack/loadbalancer/v2/quotas/testing/fixtures_test.go
index e5185b201..e4609aa86 100644
--- a/openstack/loadbalancer/v2/quotas/testing/fixtures_test.go
+++ b/openstack/loadbalancer/v2/quotas/testing/fixtures_test.go
@@ -1,6 +1,13 @@
 package testing
 
-import "github.com/gophercloud/gophercloud/v2/openstack/loadbalancer/v2/quotas"
+import (
+	"net/http"
+	"testing"
+
+	"github.com/gophercloud/gophercloud/v2/openstack/loadbalancer/v2/quotas"
+	fake "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/common"
+	th "github.com/gophercloud/gophercloud/v2/testhelper"
+)
 
 const GetResponseRaw_1 = `
 {
@@ -77,3 +84,12 @@ var UpdateResponse = quotas.Quota{
 	L7Policy:      50,
 	L7Rule:        100,
 }
+
+func MockDeleteResponse(t *testing.T, fakeServer th.FakeServer) {
+	fakeServer.Mux.HandleFunc("/v2.0/quotas/0a73845280574ad389c292f6a74afa76", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "DELETE")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		w.WriteHeader(http.StatusNoContent)
+	})
+}
diff --git a/openstack/loadbalancer/v2/quotas/testing/requests_test.go b/openstack/loadbalancer/v2/quotas/testing/requests_test.go
index ccf8e51f3..ab3ba6a17 100644
--- a/openstack/loadbalancer/v2/quotas/testing/requests_test.go
+++ b/openstack/loadbalancer/v2/quotas/testing/requests_test.go
@@ -105,3 +105,13 @@ func TestUpdate_2(t *testing.T) {
 	th.AssertNoErr(t, err)
 	th.AssertDeepEquals(t, q, &UpdateResponse)
 }
+
+func TestDelete(t *testing.T) {
+	fakeServer := th.SetupHTTP()
+	defer fakeServer.Teardown()
+
+	MockDeleteResponse(t, fakeServer)
+
+	res := quotas.Delete(context.TODO(), fake.ServiceClient(fakeServer), "0a73845280574ad389c292f6a74afa76")
+	th.AssertNoErr(t, res.Err)
+}
diff --git a/openstack/networking/v2/extensions/quotas/testing/fixtures_test.go b/openstack/networking/v2/extensions/quotas/testing/fixtures_test.go
index a4a7703c8..1f34dead1 100644
--- a/openstack/networking/v2/extensions/quotas/testing/fixtures_test.go
+++ b/openstack/networking/v2/extensions/quotas/testing/fixtures_test.go
@@ -1,7 +1,12 @@
 package testing
 
 import (
+	"net/http"
+	"testing"
+
+	fake "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/common"
 	"github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/quotas"
+	th "github.com/gophercloud/gophercloud/v2/testhelper"
 )
 
 const GetResponseRaw = `
@@ -140,3 +145,12 @@ var UpdateResponse = quotas.Quota{
 	SubnetPool:        0,
 	Trunk:             5,
 }
+
+func MockDeleteResponse(t *testing.T, fakeServer th.FakeServer) {
+	fakeServer.Mux.HandleFunc("/v2.0/quotas/0a73845280574ad389c292f6a74afa76", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "DELETE")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		w.WriteHeader(http.StatusNoContent)
+	})
+}
diff --git a/openstack/networking/v2/extensions/quotas/testing/requests_test.go b/openstack/networking/v2/extensions/quotas/testing/requests_test.go
index 597edd485..e4550c11f 100644
--- a/openstack/networking/v2/extensions/quotas/testing/requests_test.go
+++ b/openstack/networking/v2/extensions/quotas/testing/requests_test.go
@@ -80,3 +80,13 @@ func TestUpdate(t *testing.T) {
 	th.AssertNoErr(t, err)
 	th.AssertDeepEquals(t, q, &UpdateResponse)
 }
+
+func TestDelete(t *testing.T) {
+	fakeServer := th.SetupHTTP()
+	defer fakeServer.Teardown()
+
+	MockDeleteResponse(t, fakeServer)
+
+	res := quotas.Delete(context.TODO(), fake.ServiceClient(fakeServer), "0a73845280574ad389c292f6a74afa76")
+	th.AssertNoErr(t, res.Err)
+}