Merge "Mend list_cells call"
diff --git a/README.rst b/README.rst
index c5606e8..6d9c848 100644
--- a/README.rst
+++ b/README.rst
@@ -920,6 +920,33 @@
 You can read more about injecting the administrator password here:
     https://docs.openstack.org/nova/queens/admin/admin-password-injection.html
 
+Enable libvirt control channel over TLS
+---------------------
+
+By default TLS is disabled.
+
+Enable TLS transport.
+
+  compute:
+    libvirt:
+      tls:
+        enabled: True
+
+You able to set custom certificates in pillar:
+
+  nova:
+    compute:
+      libvirt:
+        tls:
+          key: (certificate content)
+          cert: (certificate content)
+          cacert: (certificate content)
+          client:
+            key: (certificate content)
+            cert: (certificate content)
+
+You can read more about live migration over TLS here:
+    https://wiki.libvirt.org/page/TLSCreateServerCerts
 
 Documentation and Bugs
 ======================
diff --git a/nova/compute.sls b/nova/compute.sls
index 33d30de..5a13581 100644
--- a/nova/compute.sls
+++ b/nova/compute.sls
@@ -138,6 +138,74 @@
 {%- endif %}
 {%- endif %}
 
+{%- if compute.libvirt.get('tls',{}).get('enabled',False)  %}
+{%- set ca_file=compute.libvirt.tls.get('ca_file') %}
+{%- set key_file=compute.libvirt.tls.get('key_file') %}
+{%- set cert_file=compute.libvirt.tls.get('cert_file') %}
+{%- set client_key_file=compute.libvirt.tls.client.get('key_file') %}
+{%- set client_cert_file=compute.libvirt.tls.client.get('cert_file') %}
+
+libvirt_ca_nova_compute:
+{%- if compute.libvirt.tls.cacert is defined %}
+  file.managed:
+    - name: {{ ca_file }}
+    - contents_pillar: nova:compute:libvirt:tls:cacert
+    - mode: 444
+    - makedirs: true
+{%- else %}
+  file.exists:
+   - name: {{ ca_file }}
+{%- endif %}
+
+libvirt_public_cert:
+{%- if compute.libvirt.tls.cert is defined %}
+  file.managed:
+    - name: {{ cert_file }}
+    - contents_pillar: nova:compute:libvirt:tls:cert
+    - mode: 440
+    - makedirs: true
+{%- else %}
+  file.exists:
+   - name: {{ cert_file }}
+{%- endif %}
+
+libvirt_private_key:
+{%- if compute.libvirt.tls.key is defined %}
+  file.managed:
+    - name: {{ key_file }}
+    - contents_pillar: nova:compute:libvirt:tls:key
+    - mode: 400
+    - makedirs: true
+{%- else %}
+  file.exists:
+   - name: {{ key_file }}
+{%- endif %}
+
+libvirt_client_public_cert:
+{%- if compute.libvirt.tls.client.cert is defined %}
+  file.managed:
+    - name: {{ client_cert_file }}
+    - contents_pillar: nova:compute:libvirt:tls:client:cert
+    - mode: 440
+    - makedirs: true
+{%- else %}
+  file.exists:
+   - name: {{ client_cert_file }}
+{%- endif %}
+
+libvirt_client_key:
+{%- if compute.libvirt.tls.client.key is defined %}
+  file.managed:
+    - name: {{ client_key_file }}
+    - contents_pillar: nova:compute:libvirt:tls:client:key
+    - mode: 400
+    - makedirs: true
+{%- else %}
+  file.exists:
+   - name: {{ client_key_file }}
+{%- endif %}
+{%- endif %}
+
 nova_compute_services:
   service.running:
   - enable: true
diff --git a/nova/files/grafana_dashboards/nova_prometheus.json b/nova/files/grafana_dashboards/nova_prometheus.json
index e866b9f..8ec0841 100644
--- a/nova/files/grafana_dashboards/nova_prometheus.json
+++ b/nova/files/grafana_dashboards/nova_prometheus.json
@@ -3303,7 +3303,7 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_used_vcpus)",
+              "expr": "sum(system_load15 and on (host) label_replace(openstack_nova_vcpus, \"host\", \"$1\", \"hostname\", \"(.*)\"))",
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
@@ -3381,7 +3381,13 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_used_disk)",
+              {%- endraw %}
+              {%- if parameters is defined and parameters.get('nova_compute_ceph_ephemeral', False) == True %}
+              "expr": "max(avg(openstack_nova_used_disk) by (instance))",
+              {%- else %}
+              "expr": "max(sum(openstack_nova_used_disk) by (instance))",
+              {%- endif %}
+              {%- raw %}
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
@@ -3459,7 +3465,7 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_used_ram)",
+              "expr": "max(sum(openstack_nova_used_ram) by (instance))",
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
@@ -3537,7 +3543,7 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_free_vcpus)",
+              "expr": "sum(label_replace(openstack_nova_vcpus, \"host\", \"$1\", \"hostname\", \"(.*)\") - on (host) system_load15)",
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
@@ -3615,7 +3621,13 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_free_disk)",
+              {%- endraw %}
+              {%- if parameters is defined and parameters.get('nova_compute_ceph_ephemeral', False) == True %}
+              "expr": "max(avg(openstack_nova_disk_available) by (instance))",
+              {%- else %}
+              "expr": "max(sum(openstack_nova_disk - openstack_nova_used_disk) by (instance))",
+              {%- endif %}
+              {%- raw %}
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
@@ -3693,7 +3705,7 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_free_ram)",
+              "expr": "max(sum(openstack_nova_ram - openstack_nova_used_ram) by (instance))",
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
diff --git a/nova/files/grafana_dashboards/nova_prometheus_fluentd.json b/nova/files/grafana_dashboards/nova_prometheus_fluentd.json
index 6f9dea0..978f951 100644
--- a/nova/files/grafana_dashboards/nova_prometheus_fluentd.json
+++ b/nova/files/grafana_dashboards/nova_prometheus_fluentd.json
@@ -3127,7 +3127,7 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_used_vcpus)",
+              "expr": "sum(system_load15 and on (host) label_replace(openstack_nova_vcpus, \"host\", \"$1\", \"hostname\", \"(.*)\"))",
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
@@ -3205,7 +3205,13 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_used_disk)",
+              {%- endraw %}
+              {%- if parameters is defined and parameters.get('nova_compute_ceph_ephemeral', False) == True %}
+              "expr": "max(avg(openstack_nova_used_disk) by (instance))",
+              {%- else %}
+              "expr": "max(sum(openstack_nova_used_disk) by (instance))",
+              {%- endif %}
+              {%- raw %}
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
@@ -3283,7 +3289,7 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_used_ram)",
+              "expr": "max(sum(openstack_nova_used_ram) by (instance))",
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
@@ -3361,7 +3367,7 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_free_vcpus)",
+              "expr": "sum(label_replace(openstack_nova_vcpus, \"host\", \"$1\", \"hostname\", \"(.*)\") - on (host) system_load15)",
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
@@ -3439,7 +3445,13 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_free_disk)",
+              {%- endraw %}
+              {%- if parameters is defined and parameters.get('nova_compute_ceph_ephemeral', False) == True %}
+              "expr": "max(avg(openstack_nova_disk_available) by (instance))",
+              {%- else %}
+              "expr": "max(sum(openstack_nova_disk - openstack_nova_used_disk) by (instance))",
+              {%- endif %}
+              {%- raw %}
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
@@ -3517,7 +3529,7 @@
           "tableColumn": "",
           "targets": [
             {
-              "expr": "max(openstack_nova_total_free_ram)",
+              "expr": "max(sum(openstack_nova_ram - openstack_nova_used_ram) by (instance))",
               "format": "time_series",
               "intervalFactor": 2,
               "legendFormat": "",
diff --git a/nova/files/pike/libvirtd.conf.Debian b/nova/files/pike/libvirtd.conf.Debian
index 6f4afb9..0f6b341 100644
--- a/nova/files/pike/libvirtd.conf.Debian
+++ b/nova/files/pike/libvirtd.conf.Debian
@@ -22,11 +22,17 @@
 # This is enabled by default, uncomment this to disable it
 #listen_tls = 0
 
-
+{%- if compute.libvirt.tls.get('enabled', False) %}
+listen_tcp = 0
+listen_tls = 1
+key_file = {{compute.libvirt.tls.key_file|yaml_squote}}
+cert_file = {{compute.libvirt.tls.cert_file|yaml_squote}}
+ca_file = {{compute.libvirt.tls.ca_file|yaml_squote}}
+{% else %}
 listen_tls = 0
 listen_tcp = 1
 auth_tcp = "none"
-
+{% endif %}
 
 # Listen for unencrypted TCP connections on the public TCP/IP port.
 # NB, must pass the --listen flag to the libvirtd process for this to
diff --git a/nova/files/pike/nova-compute.conf.Debian b/nova/files/pike/nova-compute.conf.Debian
index e604d72..5427ce6 100644
--- a/nova/files/pike/nova-compute.conf.Debian
+++ b/nova/files/pike/nova-compute.conf.Debian
@@ -6009,10 +6009,14 @@
 {%- endif %}
 {%- endif %}
 
+{%- if compute.libvirt.tls.get('enabled', False) %}
+live_migration_scheme="tls"
+{%- else %}
 {%- if compute.get('libvirt', {}).uri is defined %}
 connection_uri={{ compute.libvirt.uri }}
 {%- endif %}
-#
+{%- endif %}
+
 # The ID of the image to boot from to rescue data from a corrupted instance.
 #
 # If the rescue REST API operation doesn't provide an ID of an image to
diff --git a/nova/files/queens/libvirtd.conf.Debian b/nova/files/queens/libvirtd.conf.Debian
index 6f4afb9..0f6b341 100644
--- a/nova/files/queens/libvirtd.conf.Debian
+++ b/nova/files/queens/libvirtd.conf.Debian
@@ -22,11 +22,17 @@
 # This is enabled by default, uncomment this to disable it
 #listen_tls = 0
 
-
+{%- if compute.libvirt.tls.get('enabled', False) %}
+listen_tcp = 0
+listen_tls = 1
+key_file = {{compute.libvirt.tls.key_file|yaml_squote}}
+cert_file = {{compute.libvirt.tls.cert_file|yaml_squote}}
+ca_file = {{compute.libvirt.tls.ca_file|yaml_squote}}
+{% else %}
 listen_tls = 0
 listen_tcp = 1
 auth_tcp = "none"
-
+{% endif %}
 
 # Listen for unencrypted TCP connections on the public TCP/IP port.
 # NB, must pass the --listen flag to the libvirtd process for this to
diff --git a/nova/files/queens/nova-compute.conf.Debian b/nova/files/queens/nova-compute.conf.Debian
index ba41a41..bf5f809 100644
--- a/nova/files/queens/nova-compute.conf.Debian
+++ b/nova/files/queens/nova-compute.conf.Debian
@@ -3357,7 +3357,7 @@
 {%- endif %}
 
 {%- set _data = compute.message_queue %}
-{%- include "oslo_templates/files/queens/oslo/_messaging_default.conf" %}
+{%- include "oslo_templates/files/queens/oslo/messaging/_default.conf" %}
 
 [api]
 #
@@ -3712,9 +3712,9 @@
 
 [api_database]
 {%- set _data = {} %}
-{%- do _data.update(controller.database) %}
+{%- do _data.update(compute.database) %}
 {%- do _data.update({'name': 'nova_api'}) %}
-{%- if _data.ssl is defined and 'cacert_file' not in _data.get('ssl', {}).keys() %}{% do _data['ssl'].update({'cacert_file': controller.cacert_file}) %}{% endif %}
+{%- if _data.ssl is defined and 'cacert_file' not in _data.get('ssl', {}).keys() %}{% do _data['ssl'].update({'cacert_file': compute.cacert_file}) %}{% endif %}
 {%- include "oslo_templates/files/queens/oslo/_database.conf" %}
 
 {%- if compute.get('barbican', {}).get('enabled', False) %}
@@ -4379,6 +4379,7 @@
 # * endpoint_template - Setting this option will override catalog_info
 #  (string value)
 #catalog_info = volumev3:cinderv3:publicURL
+catalog_info = volumev3:cinderv3:publicURL
 
 #
 # If this option is set then it will override service catalog lookup
@@ -6253,9 +6254,13 @@
 {%- endif %}
 {%- endif %}
 
+{%- if compute.libvirt.tls.get('enabled', False) %}
+live_migration_scheme="tls"
+{%- else %}
 {%- if compute.get('libvirt', {}).uri is defined %}
 connection_uri={{ compute.libvirt.uri }}
 {%- endif %}
+{%- endif %}
 
 #
 # The ID of the image to boot from to rescue data from a corrupted
diff --git a/nova/map.jinja b/nova/map.jinja
index e9282b7..f5b55ec 100644
--- a/nova/map.jinja
+++ b/nova/map.jinja
@@ -127,6 +127,14 @@
   libvirt:
     inject_partition: '-2'
     inject_password: False
+    tls:
+      enabled: False
+      key_file: '/etc/pki/libvirt/private/serverkey.pem'
+      cert_file: '/etc/pki/libvirt/servercert.pem'
+      ca_file: '/etc/pki/CA/cacert.pem'
+      client:
+        key_file: '/etc/pki/libvirt/private/clientkey.pem'
+        cert_file: '/etc/pki/libvirt/clientcert.pem'
   instances_path: "$state_path/instances"
   notification: false
   availability_zone:
@@ -163,6 +171,14 @@
   libvirt:
     inject_partition: '-2'
     inject_password: False
+    tls:
+      enabled: False
+      key_file: '/etc/pki/libvirt/private/serverkey.pem'
+      cert_file: '/etc/pki/libvirt/servercert.pem'
+      ca_file: '/etc/pki/CA/cacert.pem'
+      client:
+        key_file: '/etc/pki/libvirt/private/clientkey.pem'
+        cert_file: '/etc/pki/libvirt/clientcert.pem'
   notification: false
   availability_zone:
   identity:
@@ -193,12 +209,8 @@
         'services_failed_critical_threshold_percent': 0.6,
         'computes_failed_warning_threshold_percent': 0.25,
         'computes_failed_critical_threshold_percent': 0.5,
-        'allocated_vcpus_minor_threshold': 0.9,
-        'allocated_vcpus_major_threshold': 0.97,
-        'allocated_ram_minor_threshold': 0.9,
-        'allocated_ram_major_threshold': 0.97,
-        'allocated_disk_minor_threshold': 0.9,
-        'allocated_disk_major_threshold': 0.97,
+        'cpu_minor_threshold': 0.85,
+        'cpu_major_threshold': 0.95,
         'ram_major_threshold': 0.85,
         'ram_critical_threshold': 0.95,
         'disk_major_threshold': 0.85,
diff --git a/nova/meta/grafana.yml b/nova/meta/grafana.yml
index 7ebae7c..1276f54 100644
--- a/nova/meta/grafana.yml
+++ b/nova/meta/grafana.yml
@@ -1,3 +1,8 @@
+{%- from "nova/map.jinja" import compute with context %}
+parameters:
+  {%- if compute is defined and compute.get('enabled', False) and compute.get('ceph', {}).get('ephemeral', False) %}
+  nova_compute_ceph_ephemeral: True
+  {%- endif %}
 dashboard:
 {%- if pillar.get('fluentd', {}).get('agent', {}).get('enabled', False) %}
   nova_prometheus:
diff --git a/nova/meta/prometheus.yml b/nova/meta/prometheus.yml
index f701acd..532b3d5 100644
--- a/nova/meta/prometheus.yml
+++ b/nova/meta/prometheus.yml
@@ -153,76 +153,31 @@
           All {{ $labels.binary }} services are down.
 {%- endraw -%}
 
-{%- set cpu_ratio = controller.get('cpu_allocation_ratio', 16.0) %}
-{%- set ram_ratio = controller.get('ram_allocation_ratio', 1.5) %}
-{%- set disk_ratio = controller.get('disk_allocation_ratio', 1.0) -%}
-
-{%- set alloc_cpu_minor_threshold = monitoring.allocated_vcpus_minor_threshold|float %}
-{%- set alloc_cpu_major_threshold = monitoring.allocated_vcpus_major_threshold|float %}
-{%- set alloc_ram_minor_threshold = monitoring.allocated_ram_minor_threshold|float %}
-{%- set alloc_ram_major_threshold = monitoring.allocated_ram_major_threshold|float %}
-{%- set alloc_disk_minor_threshold = monitoring.allocated_disk_minor_threshold|float %}
-{%- set alloc_disk_major_threshold = monitoring.allocated_disk_major_threshold|float -%}
-
+{%- set cpu_minor_threshold = monitoring.cpu_minor_threshold|float %}
+{%- set cpu_major_threshold = monitoring.cpu_major_threshold|float %}
 {%- set ram_major_threshold = monitoring.ram_major_threshold|float %}
 {%- set ram_critical_threshold = monitoring.ram_critical_threshold|float %}
 {%- set disk_major_threshold = monitoring.disk_major_threshold|float %}
 {%- set disk_critical_threshold = monitoring.disk_critical_threshold|float -%}
 
-    NovaHypervisorAllocatedVCPUsFullMinor:
+    NovaHypervisorVCPUsFullMinor:
       if: >-
-        openstack_nova_used_vcpus >= openstack_nova_vcpus * {{ cpu_ratio }} * {{ alloc_cpu_minor_threshold }}
+        label_replace(system_load15, "hostname", "$1", "host", "(.*)") >= on (hostname) openstack_nova_vcpus * {{ cpu_minor_threshold }}
       labels:
         severity: minor
         service: nova
       annotations:
-        summary: "{{ alloc_cpu_minor_threshold * 100 }}% of hypervisor VCPUs were allocated"
-        description: "{% raw %}{{ $value }} VCPUs on the {{ $labels.hostname }}{% endraw %} node were allocated (at least {{ alloc_cpu_minor_threshold * 100 }}%)."
-    NovaHypervisorAllocatedVCPUsFullMajor:
+        summary: "{{ cpu_minor_threshold * 100 }}% of hypervisor VCPUs were used"
+        description: "{% raw %}{{ $value }} VCPUs on the {{ $labels.hostname }}{% endraw %} node were used (at least {{ cpu_minor_threshold * 100 }}%)."
+    NovaHypervisorVCPUsFullMajor:
       if: >-
-        openstack_nova_used_vcpus >= openstack_nova_vcpus * {{ cpu_ratio }} * {{ alloc_cpu_major_threshold }}
+        label_replace(system_load15, "hostname", "$1", "host", "(.*)") >= on (hostname) openstack_nova_vcpus * {{ cpu_major_threshold }}
       labels:
         severity: major
         service: nova
       annotations:
-        summary: "{{ alloc_cpu_major_threshold * 100 }}% of hypervisor VCPUs were allocated"
-        description: "{% raw %}{{ $value }} VCPUs on the {{ $labels.hostname }}{% endraw %} node were allocated (at least {{ alloc_cpu_major_threshold * 100 }}%)."
-    NovaHypervisorAllocatedVCPUsFullCritical:
-      if: >-
-        openstack_nova_used_vcpus >= openstack_nova_vcpus * {{ cpu_ratio }}
-      labels:
-        severity: critical
-        service: nova
-      annotations:
-        summary: "No VCPUs available for allocation"
-        description: "All available VCPUs on the {% raw %}{{ $labels.hostname }}{% endraw %} node were allocated."
-    NovaHypervisorAllocatedMemoryFullMinor:
-      if: >-
-        openstack_nova_ram - openstack_nova_free_ram >= openstack_nova_ram * {{ ram_ratio }} * {{ alloc_ram_minor_threshold }}
-      labels:
-        severity: minor
-        service: nova
-      annotations:
-        summary: "{{ alloc_ram_minor_threshold * 100 }}% of hypervisor RAM was allocated"
-        description: "{% raw %}{{ $value }}MB of RAM on the {{ $labels.hostname }}{% endraw %} node was allocated (at least {{ alloc_ram_minor_threshold * 100 }}%)."
-    NovaHypervisorAllocatedMemoryFullMajor:
-      if: >-
-        openstack_nova_ram - openstack_nova_free_ram >= openstack_nova_ram * {{ ram_ratio }} * {{ alloc_ram_major_threshold }}
-      labels:
-        severity: major
-        service: nova
-      annotations:
-        summary: "{{ alloc_ram_major_threshold * 100 }}% of hypervisor RAM was allocated"
-        description: "{% raw %}{{ $value }}MB of RAM on the {{ $labels.hostname }}{% endraw %} node was allocated (at least {{ alloc_ram_major_threshold * 100 }}%)."
-    NovaHypervisorAllocatedMemoryFullCritical:
-      if: >-
-        openstack_nova_ram - openstack_nova_free_ram >= openstack_nova_ram * {{ ram_ratio }}
-      labels:
-        severity: critical
-        service: nova
-      annotations:
-        summary: "No RAM available for allocation"
-        description: "All available RAM on the {% raw %}{{ $labels.hostname }}{% endraw %} node was allocated."
+        summary: "{{ cpu_major_threshold * 100 }}% of hypervisor VCPUs were used"
+        description: "{% raw %}{{ $value }} VCPUs on the {{ $labels.hostname }}{% endraw %} node were used (at least {{ cpu_major_threshold * 100 }}%)."
     NovaHypervisorMemoryFullMajor:
       if: >-
         openstack_nova_used_ram >= openstack_nova_ram * {{ ram_major_threshold }}
@@ -241,33 +196,6 @@
       annotations:
         summary: "{{ ram_critical_threshold * 100 }}% of hypervisor RAM was used"
         description: "{% raw %}{{ $value }}MB of RAM on the {{ $labels.hostname }}{% endraw %} node was used (at least {{ ram_critical_threshold * 100 }}%)."
-    NovaHypervisorAllocatedDiskFullMinor:
-      if: >-
-        openstack_nova_disk - openstack_nova_free_disk >= openstack_nova_disk * {{ disk_ratio }} * {{ alloc_disk_minor_threshold }}
-      labels:
-        severity: minor
-        service: nova
-      annotations:
-        summary: "{{ alloc_disk_minor_threshold * 100 }}% of hypervisor disk space was allocated"
-        description: "{% raw %}{{ $value }}GB of disk space on the {{ $labels.hostname }}{% endraw %} node was allocated (at least {{ alloc_disk_minor_threshold * 100 }}%)."
-    NovaHypervisorAllocatedDiskFullMajor:
-      if: >-
-        openstack_nova_disk - openstack_nova_free_disk >= openstack_nova_disk * {{ disk_ratio }} * {{ alloc_disk_major_threshold }}
-      labels:
-        severity: major
-        service: nova
-      annotations:
-        summary: "{{ alloc_disk_major_threshold * 100 }}% of hypervisor disk space was allocated"
-        description: "{% raw %}{{ $value }}GB of disk space on the {{ $labels.hostname }}{% endraw %} node was allocated (at least {{ alloc_disk_major_threshold * 100 }}%)."
-    NovaHypervisorAllocatedDiskFullCritical:
-      if: >-
-        openstack_nova_disk - openstack_nova_free_disk >= openstack_nova_disk * {{ disk_ratio }}
-      labels:
-        severity: critical
-        service: nova
-      annotations:
-        summary: "No disk space available for allocation"
-        description: "All available disk space on the {% raw %}{{ $labels.hostname }}{% endraw %} node was allocated."
     NovaHypervisorDiskFullMajor:
       if: >-
         openstack_nova_used_disk >= openstack_nova_disk * {{ disk_major_threshold }}
@@ -286,60 +214,6 @@
       annotations:
         summary: "{{ disk_critical_threshold * 100 }}% of hypervisor disk space was used"
         description: "{% raw %}{{ $value }}GB of disk space on the {{ $labels.hostname }}{% endraw %} node was used (at least {{ disk_critical_threshold * 100 }}%)."
-    NovaAggregateAllocatedVCPUsFullMinor:
-      if: >-
-        openstack_nova_aggregate_used_vcpus >= openstack_nova_aggregate_vcpus * {{ cpu_ratio }} * {{ alloc_cpu_minor_threshold }}
-      labels:
-        severity: minor
-        service: nova
-      annotations:
-        summary: "{{ alloc_cpu_minor_threshold * 100 }}% of aggregate VCPUs were allocated"
-        description: "{% raw %}{{ $value }} VCPUs on the {{ $labels.aggregate }}{% endraw %} aggregate were allocated (at least {{ alloc_cpu_minor_threshold * 100 }}%)."
-    NovaAggregateAllocatedVCPUsFullMajor:
-      if: >-
-        openstack_nova_aggregate_used_vcpus >= openstack_nova_aggregate_vcpus * {{ cpu_ratio }} * {{ alloc_cpu_major_threshold }}
-      labels:
-        severity: major
-        service: nova
-      annotations:
-        summary: "{{ alloc_cpu_major_threshold * 100 }}% of aggregate VCPUs were allocated"
-        description: "{% raw %}{{ $value }} VCPUs on the {{ $labels.aggregate }}{% endraw %} aggregate were allocated (at least {{ alloc_cpu_major_threshold * 100 }}%)."
-    NovaAggregateAllocatedVCPUsFullCritical:
-      if: >-
-        openstack_nova_aggregate_used_vcpus >= openstack_nova_aggregate_vcpus * {{ cpu_ratio }}
-      labels:
-        severity: critical
-        service: nova
-      annotations:
-        summary: "No VCPUs available for allocation"
-        description: "All available VCPUs on the {% raw %}{{ $labels.aggregate }}{% endraw %} aggregate were allocated."
-    NovaAggregateAllocatedMemoryFullMinor:
-      if: >-
-        openstack_nova_aggregate_ram - openstack_nova_aggregate_free_ram >= openstack_nova_aggregate_ram * {{ ram_ratio }} * {{ alloc_ram_minor_threshold }}
-      labels:
-        severity: minor
-        service: nova
-      annotations:
-        summary: "{{ alloc_ram_minor_threshold * 100 }}% of aggregate RAM was allocated"
-        description: "{% raw %}{{ $value }}MB of RAM on the {{ $labels.aggregate }}{% endraw %} aggregate was allocated (at least {{ alloc_ram_minor_threshold * 100 }}%)."
-    NovaAggregateAllocatedMemoryFullMajor:
-      if: >-
-        openstack_nova_aggregate_ram - openstack_nova_aggregate_free_ram >= openstack_nova_aggregate_ram * {{ ram_ratio }} * {{ alloc_ram_major_threshold }}
-      labels:
-        severity: major
-        service: nova
-      annotations:
-        summary: "{{ alloc_ram_major_threshold * 100 }}% of aggregate RAM was allocated"
-        description: "{% raw %}{{ $value }}MB of RAM on the {{ $labels.aggregate }}{% endraw %} aggregate was allocated (at least {{ alloc_ram_major_threshold * 100 }}%)."
-    NovaAggregateAllocatedMemoryFullCritical:
-      if: >-
-        openstack_nova_aggregate_ram - openstack_nova_aggregate_free_ram >= openstack_nova_aggregate_ram * {{ ram_ratio }}
-      labels:
-        severity: critical
-        service: nova
-      annotations:
-        summary: "No RAM available for allocation"
-        description: "All available RAM on the {% raw %}{{ $labels.aggregate }}{% endraw %} aggregate was allocated."
     NovaAggregateMemoryFullMajor:
       if: >-
         openstack_nova_aggregate_used_ram >= openstack_nova_aggregate_ram * {{ ram_major_threshold }}
@@ -358,33 +232,6 @@
       annotations:
         summary: "{{ ram_critical_threshold * 100 }}% of aggregate RAM was used"
         description: "{% raw %}{{ $value }}MB of RAM on the {{ $labels.aggregate }}{% endraw %} aggregate was used (at least {{ ram_critical_threshold * 100 }}%)."
-    NovaAggregateAllocatedDiskFullMinor:
-      if: >-
-        openstack_nova_aggregate_disk - openstack_nova_aggregate_free_disk >= openstack_nova_aggregate_disk * {{ disk_ratio }} * {{ alloc_disk_minor_threshold }}
-      labels:
-        severity: minor
-        service: nova
-      annotations:
-        summary: "{{ alloc_disk_minor_threshold * 100 }}% of aggregate disk space was allocated"
-        description: "{% raw %}{{ $value }}GB of disk space on the {{ $labels.aggregate }}{% endraw %} aggregate was allocated (at least {{ alloc_disk_minor_threshold * 100 }}%)."
-    NovaAggregateAllocatedDiskFullMajor:
-      if: >-
-        openstack_nova_aggregate_disk - openstack_nova_aggregate_free_disk >= openstack_nova_aggregate_disk * {{ disk_ratio }} * {{ alloc_disk_major_threshold }}
-      labels:
-        severity: major
-        service: nova
-      annotations:
-        summary: "{{ alloc_disk_major_threshold * 100 }}% of aggregate disk space was allocated"
-        description: "{% raw %}{{ $value }}GB of disk space on the {{ $labels.aggregate }}{% endraw %} aggregate was allocated (at least {{ alloc_disk_major_threshold * 100 }}%)."
-    NovaAggregateAllocatedDiskFullCritical:
-      if: >-
-        openstack_nova_aggregate_disk - openstack_nova_aggregate_free_disk >= openstack_nova_aggregate_disk * {{ disk_ratio }}
-      labels:
-        severity: critical
-        service: nova
-      annotations:
-        summary: "No disk space available for allocation"
-        description: "All available disk space on the {% raw %}{{ $labels.aggregate }}{% endraw %} aggregate was allocated."
     NovaAggregateDiskFullMajor:
       if: >-
         openstack_nova_aggregate_used_disk >= openstack_nova_aggregate_disk * {{ disk_major_threshold }}
@@ -403,60 +250,24 @@
       annotations:
         summary: "{{ disk_critical_threshold * 100 }}% of aggregate disk space was used"
         description: "{% raw %}{{ $value }}GB of disk space on the {{ $labels.aggregate }}{% endraw %} aggregate was used (at least {{ disk_critical_threshold * 100 }}%)."
-    NovaTotalAllocatedVCPUsFullMinor:
+    NovaTotalVCPUsFullMinor:
       if: >-
-        openstack_nova_total_used_vcpus >= openstack_nova_total_vcpus * {{ cpu_ratio }} * {{ alloc_cpu_minor_threshold }}
+        sum(label_replace(system_load15, "hostname", "$1", "host", "(.*)") and on (hostname) openstack_nova_vcpus) >= max(sum(openstack_nova_vcpus) by (instance)) * {{ cpu_minor_threshold }}
       labels:
         severity: minor
         service: nova
       annotations:
-        summary: "{{ alloc_cpu_minor_threshold * 100 }}% of cloud VCPUs were allocated"
-        description: "{% raw %}{{ $value }}{% endraw %} VCPUs in the cloud were allocated (at least {{ alloc_cpu_minor_threshold * 100 }}%)."
-    NovaTotalAllocatedVCPUsFullMajor:
+        summary: "{{ cpu_minor_threshold * 100 }}% of cloud VCPUs were used"
+        description: "{% raw %}{{ $value }}{% endraw %} VCPUs in the cloud were used (at least {{ cpu_minor_threshold * 100 }}%)."
+    NovaTotalVCPUsFullMajor:
       if: >-
-        openstack_nova_total_used_vcpus >= openstack_nova_total_vcpus * {{ cpu_ratio }} * {{ alloc_cpu_major_threshold }}
+        sum(label_replace(system_load15, "hostname", "$1", "host", "(.*)") and on (hostname) openstack_nova_vcpus) >= max(sum(openstack_nova_vcpus) by (instance)) * {{ cpu_major_threshold }}
       labels:
         severity: major
         service: nova
       annotations:
-        summary: "{{ alloc_cpu_major_threshold * 100 }}% of cloud VCPUs were allocated"
-        description: "{% raw %}{{ $value }}{% endraw %} VCPUs in the cloud were allocated (at least {{ alloc_cpu_major_threshold * 100 }}%)."
-    NovaTotalAllocatedVCPUsFullCritical:
-      if: >-
-        openstack_nova_total_used_vcpus >= openstack_nova_total_vcpus * {{ cpu_ratio }}
-      labels:
-        severity: critical
-        service: nova
-      annotations:
-        summary: "No VCPUs available for allocation"
-        description: "All available VCPUs in the cloud were allocated."
-    NovaTotalAllocatedMemoryFullMinor:
-      if: >-
-        openstack_nova_total_ram - openstack_nova_total_free_ram >= openstack_nova_total_ram * {{ ram_ratio }} * {{ alloc_ram_minor_threshold }}
-      labels:
-        severity: minor
-        service: nova
-      annotations:
-        summary: "{{ alloc_ram_minor_threshold * 100 }}% of cloud RAM was allocated"
-        description: "{% raw %}{{ $value }}MB{% endraw %} of RAM in the cloud was allocated (at least {{ alloc_ram_minor_threshold * 100 }}%)."
-    NovaTotalAllocatedMemoryFullMajor:
-      if: >-
-        openstack_nova_total_ram - openstack_nova_total_free_ram >= openstack_nova_total_ram * {{ ram_ratio }} * {{ alloc_ram_major_threshold }}
-      labels:
-        severity: major
-        service: nova
-      annotations:
-        summary: "{{ alloc_ram_major_threshold * 100 }}% of cloud RAM was allocated"
-        description: "{% raw %}{{ $value }}MB{% endraw %} of RAM in the cloud was allocated (at least {{ alloc_ram_major_threshold * 100 }}%)."
-    NovaTotalAllocatedMemoryFullCritical:
-      if: >-
-        openstack_nova_total_ram - openstack_nova_total_free_ram >= openstack_nova_total_ram * {{ ram_ratio }}
-      labels:
-        severity: critical
-        service: nova
-      annotations:
-        summary: "No RAM available for allocation"
-        description: "All available RAM in the cloud was allocated."
+        summary: "{{ cpu_major_threshold * 100 }}% of cloud VCPUs were used"
+        description: "{% raw %}{{ $value }}{% endraw %} VCPUs in the cloud were used (at least {{ cpu_major_threshold * 100 }}%)."
     NovaTotalMemoryFullMajor:
       if: >-
         openstack_nova_total_used_ram >= openstack_nova_total_ram * {{ ram_major_threshold }}
@@ -475,33 +286,6 @@
       annotations:
         summary: "{{ ram_critical_threshold * 100 }}% of cloud RAM was used"
         description: "{% raw %}{{ $value }}MB{% endraw %} of RAM in the cloud was used (at least {{ ram_critical_threshold * 100 }}%)."
-    NovaTotalAllocatedDiskFullMinor:
-      if: >-
-        openstack_nova_total_disk - openstack_nova_total_free_disk >= openstack_nova_total_disk * {{ disk_ratio }} * {{ alloc_disk_minor_threshold }}
-      labels:
-        severity: minor
-        service: nova
-      annotations:
-        summary: "{{ alloc_disk_minor_threshold * 100 }}% of cloud disk space was allocated"
-        description: "{% raw %}{{ $value }}GB{% endraw %} of disk space in the cloud was allocated (at least {{ alloc_disk_minor_threshold * 100 }}%)."
-    NovaTotalAllocatedDiskFullMajor:
-      if: >-
-        openstack_nova_total_disk - openstack_nova_total_free_disk >= openstack_nova_total_disk * {{ disk_ratio }} * {{ alloc_disk_major_threshold }}
-      labels:
-        severity: major
-        service: nova
-      annotations:
-        summary: "{{ alloc_disk_major_threshold * 100 }}% of cloud disk space was allocated"
-        description: "{% raw %}{{ $value }}GB{% endraw %} of disk space in the cloud was allocated (at least {{ alloc_disk_major_threshold * 100 }}%)."
-    NovaTotalAllocatedDiskFullCritical:
-      if: >-
-        openstack_nova_total_disk - openstack_nova_total_free_disk >= openstack_nova_total_disk * {{ disk_ratio }}
-      labels:
-        severity: critical
-        service: nova
-      annotations:
-        summary: "No disk space available for allocation"
-        description: "All available disk space in the cloud was allocated."
     NovaTotalDiskFullMajor:
       if: >-
         openstack_nova_total_used_disk >= openstack_nova_total_disk * {{ disk_major_threshold }}