Repository: gophercloud/gophercloud

Issue:
nova: absent hypervisor cpu_info.topology.cells report
### What happened?

On some hardware CPU Info has extra field - `cells` and other fields are adjusted to that topology.
Unfortunately i cannot find doc where it's defined, but here is the code from 2024.1:

https://github.com/openstack/nova/blob/stable/2024.1/nova/virt/libvirt/driver.py#L8478-L8482

So i got result like that:
```yaml
# nova api microversion 2.87
cpu_info:
  arch: x86_64
  model: Cascadelake-Server-noTSX
  vendor: Intel
  topology:
    cells: 2
    sockets: 1
    cores: 20
    threads: 2
  features:
...
```


Related issue: https://github.com/openstack-exporter/openstack-exporter/issues/494

### Version

v2 (current)

Discussion:

Solution patch:
diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml
index 341060fbb..802e88690 100644
--- a/.github/workflows/functional-baremetal.yaml
+++ b/.github/workflows/functional-baremetal.yaml
@@ -13,19 +13,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: "24.04"
-            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: Ironic on OpenStack ${{ matrix.name }}
     steps:
@@ -100,7 +93,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml
index 70acbf376..7cc97ce2e 100644
--- a/.github/workflows/functional-basic.yaml
+++ b/.github/workflows/functional-basic.yaml
@@ -13,19 +13,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:
@@ -54,7 +47,7 @@ jobs:
         uses: gophercloud/devstack-action@60ca1042045c0c9e3e001c64575d381654ffcba1
         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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml
index 86f7de367..4e88bcf39 100644
--- a/.github/workflows/functional-blockstorage.yaml
+++ b/.github/workflows/functional-blockstorage.yaml
@@ -13,19 +13,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:
@@ -60,7 +53,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml
index 5322a8640..c798e9c5b 100644
--- a/.github/workflows/functional-compute.yaml
+++ b/.github/workflows/functional-compute.yaml
@@ -13,19 +13,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:
@@ -60,7 +53,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml
index 6172dccb0..c672171b4 100644
--- a/.github/workflows/functional-containerinfra.yaml
+++ b/.github/workflows/functional-containerinfra.yaml
@@ -22,10 +22,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
@@ -35,21 +34,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:
@@ -90,7 +80,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml
index ee5751220..e4aa1e8ca 100644
--- a/.github/workflows/functional-dns.yaml
+++ b/.github/workflows/functional-dns.yaml
@@ -19,19 +19,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:
@@ -68,7 +61,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml
index 5e2cadc27..4d722a5d5 100644
--- a/.github/workflows/functional-fwaas_v2.yaml
+++ b/.github/workflows/functional-fwaas_v2.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: FWaaS_v2 on OpenStack ${{ matrix.name }}
     steps:
@@ -83,7 +76,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml
index 37622af36..7ad9b1cc2 100644
--- a/.github/workflows/functional-identity.yaml
+++ b/.github/workflows/functional-identity.yaml
@@ -13,19 +13,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:
@@ -58,7 +51,7 @@ jobs:
         uses: gophercloud/devstack-action@60ca1042045c0c9e3e001c64575d381654ffcba1
         with:
           branch: ${{ matrix.openstack_version }}
-          enabled_services: "${{ matrix.additional_services }}"
+          enabled_services: "openstack-cli-server"
 
       - name: Checkout go
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-image.yaml b/.github/workflows/functional-image.yaml
index c05fad1e8..1730a3e89 100644
--- a/.github/workflows/functional-image.yaml
+++ b/.github/workflows/functional-image.yaml
@@ -13,19 +13,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:
@@ -58,7 +51,7 @@ jobs:
         uses: gophercloud/devstack-action@60ca1042045c0c9e3e001c64575d381654ffcba1
         with:
           branch: ${{ matrix.openstack_version }}
-          enabled_services: "${{ matrix.additional_services }}"
+          enabled_services: "openstack-cli-server"
 
       - name: Checkout go
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml
index 44d960706..cbc2ddbc1 100644
--- a/.github/workflows/functional-keymanager.yaml
+++ b/.github/workflows/functional-keymanager.yaml
@@ -19,25 +19,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:
@@ -74,7 +67,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml
index 3f7343603..448b3b94f 100644
--- a/.github/workflows/functional-loadbalancer.yaml
+++ b/.github/workflows/functional-loadbalancer.yaml
@@ -19,19 +19,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:
@@ -69,7 +62,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml
index 0222956e8..3dc6ee7e3 100644
--- a/.github/workflows/functional-messaging.yaml
+++ b/.github/workflows/functional-messaging.yaml
@@ -13,19 +13,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:
@@ -61,7 +54,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml
index 28107f4fc..7403f829b 100644
--- a/.github/workflows/functional-networking.yaml
+++ b/.github/workflows/functional-networking.yaml
@@ -13,19 +13,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:
@@ -78,7 +71,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml
index fb71022fb..7cae7e920 100644
--- a/.github/workflows/functional-objectstorage.yaml
+++ b/.github/workflows/functional-objectstorage.yaml
@@ -13,19 +13,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:
@@ -64,7 +57,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml
index 45859d2fa..10b811570 100644
--- a/.github/workflows/functional-orchestration.yaml
+++ b/.github/workflows/functional-orchestration.yaml
@@ -13,19 +13,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:
@@ -60,7 +53,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml
index 2219c99a0..418a1945f 100644
--- a/.github/workflows/functional-placement.yaml
+++ b/.github/workflows/functional-placement.yaml
@@ -13,19 +13,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:
@@ -58,7 +51,7 @@ jobs:
         uses: gophercloud/devstack-action@60ca1042045c0c9e3e001c64575d381654ffcba1
         with:
           branch: ${{ matrix.openstack_version }}
-          enabled_services: "${{ matrix.additional_services }}"
+          enabled_services: "openstack-cli-server"
 
       - name: Checkout go
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml
index cac6da18d..05ab3337a 100644
--- a/.github/workflows/functional-sharedfilesystems.yaml
+++ b/.github/workflows/functional-sharedfilesystems.yaml
@@ -19,19 +19,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:
@@ -82,7 +75,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/.github/workflows/functional-workflow.yaml b/.github/workflows/functional-workflow.yaml
index 4ac0dde74..5a2735e1f 100644
--- a/.github/workflows/functional-workflow.yaml
+++ b/.github/workflows/functional-workflow.yaml
@@ -14,22 +14,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:
@@ -64,7 +56,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
         if: ${{ fromJSON(steps.changed-files.outputs.matches) }}
diff --git a/openstack/compute/v2/hypervisors/results.go b/openstack/compute/v2/hypervisors/results.go
index cb442a9b6..a6a5d8602 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 2685c1c96..25595a28f 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 0552dc285..260aa153c 100644
--- a/openstack/identity/v3/roles/requests.go
+++ b/openstack/identity/v3/roles/requests.go
@@ -94,6 +94,9 @@ 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:"-"`
 
@@ -141,9 +144,12 @@ 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:"-"`
 
diff --git a/openstack/identity/v3/roles/results.go b/openstack/identity/v3/roles/results.go
index b2e348df0..cf9d1cb99 100644
--- a/openstack/identity/v3/roles/results.go
+++ b/openstack/identity/v3/roles/results.go
@@ -21,6 +21,9 @@ 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:"-"`
 



Test patch:
diff --git a/internal/acceptance/openstack/identity/v3/roles_test.go b/internal/acceptance/openstack/identity/v3/roles_test.go
index 96337dc4c..753736843 100644
--- a/internal/acceptance/openstack/identity/v3/roles_test.go
+++ b/internal/acceptance/openstack/identity/v3/roles_test.go
@@ -58,10 +58,11 @@ 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,
@@ -96,10 +97,11 @@ 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,
@@ -112,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/openstack/identity/v3/roles/testing/fixtures_test.go b/openstack/identity/v3/roles/testing/fixtures_test.go
index 3fa6171c1..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,7 +53,10 @@ const GetOutput = `
             "self": "https://example.com/identity/v3/roles/9fe1d3"
         },
         "name": "support",
-        "description": "read-only support role"
+        "description": "read-only support role",
+		"extra": {
+			"test": "this is for the test"
+		} 
     }
 }
 `
@@ -70,6 +74,9 @@ const GetOutputWithOptions = `
         "description": "read-only support role",
 		"options": {
 			"immutable": true
+		},
+		"extra": {
+			"test": "this is for the test"
 		}
     }
 }
@@ -81,7 +88,8 @@ const CreateRequest = `
     "role": {
         "domain_id": "1789d1",
         "name": "support",
-		"description": "read-only support role"
+		"description": "read-only support role",
+		"test": "this is for the test"
 	}
 }
 `
@@ -93,6 +101,7 @@ const CreateRequestWithOptions = `
         "domain_id": "1789d1",
         "name": "support",
 		"description": "read-only support role",
+		"test": "this is for the test",
 		"options": {
 			"immutable": true
 		}
@@ -354,9 +363,10 @@ 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",
 	},
 }
 
@@ -367,9 +377,10 @@ var SecondRoleWithOptions = 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",
 	},
 	Options: map[roles.Option]any{
 		roles.Immutable: true,
diff --git a/openstack/identity/v3/roles/testing/requests_test.go b/openstack/identity/v3/roles/testing/requests_test.go
index 88da0a4b4..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",
 		},
 	}
 
@@ -110,13 +111,14 @@ func TestCreateWithOptionsRole(t *testing.T) {
 	HandleCreateWithOptionsRoleSuccessfully(t, fakeServer)
 
 	createOpts := roles.CreateOpts{
-		Name:     "support",
-		DomainID: "1789d1",
+		Name:        "support",
+		DomainID:    "1789d1",
+		Description: "read-only support role",
 		Options: map[roles.Option]any{
 			roles.Immutable: true,
 		},
 		Extra: map[string]any{
-			"description": "read-only support role",
+			"test": "this is for the test",
 		},
 	}