动态轮询子系统介绍¶
动态轮询功能允许系统管理员动态创建/更新 REST API 轮询器(无需更改代码)。系统读取在 pollsters_definitions_dirs 参数中找到的 YAML 配置文件,该参数的默认值为 /etc/ceilometer/pollsters.d。操作员可以使用单个文件来定义每个动态轮询器,也可以在单个文件中定义多个动态轮询器。
动态轮询系统的当前限制¶
当前,动态轮询系统不支持以下类型的 API
租户 API:租户 API 是需要在租户级别轮询的 API。此功能“很好”,但当前尚未实现。
动态轮询系统配置(针对 OpenStack API)¶
动态轮询功能中的每个 YAML 文件可以使用以下属性来定义一个动态轮询器
警告
警告:Ceilometer 不接受 value 和 metadata 配置的复杂值数据结构。因此,如果您正在提取复杂的数据结构(对象、列表、映射或其他),可以使用 Operations on extracted attributes 功能将对象转换为简单值(字符串或数字)
name:必填字段。它指定动态轮询器的名称/键。例如,用于 magnum 的轮询器可以使用名称dynamic.magnum.cluster;sample_type:必填字段;它定义了样本类型。它必须是以下值之一:gauge、delta、cumulative;unit:必填字段;定义正在收集的指标的单位。例如,对于 magnum,可以使用cluster作为单位,或者其他有意义的字符串值;value_attribute:必填属性;定义轮询组件的 URL 响应中的属性。我们还接受嵌套值字典。要使用嵌套值,只需使用attribute1.attribute2.<asMuchAsNeeded>.lastattribute。也可以使用"." (点)引用样本本身;当属性可能不存在时,样本的自引用很有趣。因此,可以结合操作选项,先检查它是否存在,然后再检索它(例如:". | value['some_field'] if 'some_field' in value else ''")。在 magnum 示例中,可以使用status作为值属性;endpoint_type:必填字段;定义用于发现要监视的组件的基本 URL 的端点类型;对于 magnum,可以使用container-infra。接受其他值,例如 cinder 端点的volume,swift 的object-store,依此类推;url_path:必填属性。它定义了我们在端点上执行请求以收集数据的路径。例如,要从 magnum 收集数据,可以使用v1/clusters/detail;metadata_fields:可选字段。它是要从使用url_path执行的请求的响应中检索的所有字段的列表。要使用嵌套值,只需使用attribute1.attribute2.<asMuchAsNeeded>.lastattribute。例如,对于 magnum,可以使用以下值
metadata_fields: - "labels" - "updated_at" - "keypair" - "master_flavor_id" - "api_address" - "master_addresses" - "node_count" - "docker_volume_size" - "master_count" - "node_addresses" - "status_reason" - "coe_version" - "cluster_template_id" - "name" - "stack_id" - "created_at" - "discovery_url" - "container_version"
skip_sample_values:可选字段。它定义了我们想要忽略的可能出现在value_attribute中的值。例如,对于 magnum,可以忽略集群的一些状态。因此,不会为处于定义的狀態的集群收集数据。
skip_sample_values: - "CREATE_FAILED" - "DELETE_FAILED"
value_mapping:可选属性。它定义了动态轮询器处理的值的映射。这是发送到 Gnocchi 或其他后端中的实际值。如果没有指定映射,我们将使用使用value_attribute获取的原始值。magnum 的一个例子是
value_mapping: CREATE_IN_PROGRESS: "0" CREATE_FAILED: "1" CREATE_COMPLETE: "2" UPDATE_IN_PROGRESS: "3" UPDATE_FAILED: "4" UPDATE_COMPLETE: "5" DELETE_IN_PROGRESS: "6" DELETE_FAILED: "7" DELETE_COMPLETE: "8" RESUME_COMPLETE: "9" RESUME_FAILED: "10" RESTORE_COMPLETE: "11" ROLLBACK_IN_PROGRESS: "12" ROLLBACK_FAILED: "13" ROLLBACK_COMPLETE: "14" SNAPSHOT_COMPLETE: "15" CHECK_COMPLETE: "16" ADOPT_COMPLETE: "17"
default_value:可选参数。如果变量值接收到的数据未映射到value_mapping配置中的任何内容,则为值映射的默认值。仅当定义了value_mapping时才使用此属性。此外,其默认值为-1。metadata_mapping:可选参数。用于创建新的元数据字段的映射。该键是请求响应中存在的元数据名称,此映射的值是使用我们映射的元数据内容将创建的新所需的元数据字段。可以按如下方式创建metadata_mapping
metadata_mapping: name: "display_name" some_attribute: "new_attribute_name"
preserve_mapped_metadata:可选参数。它指示在映射到新名称时是否保留旧元数据名称。默认值为True。response_entries_key:可选参数。此值用于定义将在动态轮询器处理中使用时查找条目的响应的“键”。如果操作员未告知response_entries_key,我们将使用找到的第一个。此外,如果响应包含一个列表,而不是一个属性是条目列表的对象,我们将直接使用该列表。因此,当 API 直接返回要处理的条目/数组列表时,将忽略此选项。我们还接受嵌套值字典。要使用嵌套值,只需使用attribute1.attribute2.<asMuchAsNeeded>.lastattributeuser_id_attribute:可选参数。默认值为user_id。在从response_entries_key元素处理的条目中,将映射到发送到 Gnocchi 的user_id属性的属性名称。project_id_attribute:可选参数。默认值为project_id。在从response_entries_key元素处理的条目中,将映射到发送到 Gnocchi 的project_id属性的属性名称。resource_id_attribute:可选参数。默认值为id。在从response_entries_key元素处理的条目中,将映射到发送到 Gnocchi 的id属性的属性名称。headers:可选参数。它是一个键值映射(类似于 metadata_mapping),可用于自定义对 URL 执行请求的标头。此配置适用于 OpenStack 和非 OpenStack 动态轮询器配置。
headers: "x-openstack-nova-api-version": "2.46"
timeout:可选参数。定义动态轮询器执行请求以收集数据的请求超时时间。默认超时值为 30 秒。如果设置为 None,这意味着客户端请求永远不会超时。因此,如果服务器永远不关闭连接,可能会出现问题。轮询器按顺序执行,一个接一个。因此,如果请求挂起,所有轮询器(包括非动态轮询器)都将停止执行。namespaces:可选参数。定义将实例化轮询器的命名空间(运行 Ceilometer 实例)。此参数接受单个字符串值或字符串列表。默认值为 central。
用于收集 Magnum 数据的完整 YAML 配置(已用作示例)如下
---
- name: "dynamic.magnum.cluster"
sample_type: "gauge"
unit: "cluster"
value_attribute: "status"
endpoint_type: "container-infra"
url_path: "v1/clusters/detail"
metadata_fields:
- "labels"
- "updated_at"
- "keypair"
- "master_flavor_id"
- "api_address"
- "master_addresses"
- "node_count"
- "docker_volume_size"
- "master_count"
- "node_addresses"
- "status_reason"
- "coe_version"
- "cluster_template_id"
- "name"
- "stack_id"
- "created_at"
- "discovery_url"
- "container_version"
value_mapping:
CREATE_IN_PROGRESS: "0"
CREATE_FAILED: "1"
CREATE_COMPLETE: "2"
UPDATE_IN_PROGRESS: "3"
UPDATE_FAILED: "4"
UPDATE_COMPLETE: "5"
DELETE_IN_PROGRESS: "6"
DELETE_FAILED: "7"
DELETE_COMPLETE: "8"
RESUME_COMPLETE: "9"
RESUME_FAILED: "10"
RESTORE_COMPLETE: "11"
ROLLBACK_IN_PROGRESS: "12"
ROLLBACK_FAILED: "13"
ROLLBACK_COMPLETE: "14"
SNAPSHOT_COMPLETE: "15"
CHECK_COMPLETE: "16"
ADOPT_COMPLETE: "17"
我们还可以复制和增强一些硬编码的轮询器。例如,收集 VPN 连接的轮询器。当前,它始终为找到的所有 VPN 连接持久化 1。但是,VPN 连接可以具有多种状态,我们通常仅应为活动资源计费,而不应为处于 ERROR 状态的资源计费。收集 VPN 连接数据的示例如下(这只是一个示例,可以根据需要进行调整和配置)
---
- name: "dynamic.network.services.vpn.connection"
sample_type: "gauge"
unit: "ipsec_site_connection"
value_attribute: "status"
endpoint_type: "network"
url_path: "v2.0/vpn/ipsec-site-connections"
metadata_fields:
- "name"
- "vpnservice_id"
- "description"
- "status"
- "peer_address"
value_mapping:
ACTIVE: "1"
metadata_mapping:
name: "display_name"
default_value: 0
response_handlers:可选参数。定义用于处理响应的响应处理程序。目前,支持的值是json:此处理程序将把响应解释为 JSON 并将其转换为 字典,可以使用操作选项来操作它--- - name: "dynamic.json.response" sample_type: "gauge" [...] response_handlers: - json
要处理的响应
{ "test": { "list": [1, 2, 3] } }
已处理的响应
{ 'test': { 'list': [1, 2, 3] } }
xml:此处理程序将把响应解释为 XML 并将其转换为 字典,可以使用操作选项来操作它--- - name: "dynamic.json.response" sample_type: "gauge" [...] response_handlers: - xml
要处理的响应
<test> <list>1</list> <list>2</list> <list>3</list> </test>
已处理的响应
{ 'test': { 'list': [1, 2, 3] } }
text:此处理程序将把响应解释为 纯文本 并将其转换为 字典,可以使用操作选项来操作它--- - name: "dynamic.json.response" sample_type: "gauge" [...] response_handlers: - text
要处理的响应
Plain text response
已处理的响应
{ 'out': "Plain text response" }
可以一起或单独使用它们。如果未定义,则 默认 值为 json。如果您设置 2 个或多个响应处理程序,将使用配置的第一个处理程序来尝试处理响应,如果不可能,将显示 DEBUG 日志消息,然后使用下一个处理程序,依此类推。如果未配置的处理程序能够处理响应,将返回一个空字典,并显示 WARNING 日志以警告操作员无法通过任何配置的处理程序处理响应。
动态轮询系统配置(针对非 OpenStack API)¶
动态轮询系统也可用于非 OpenStack API。要配置非 OpenStack API,可以使用动态轮询系统的所有属性,但一个属性除外。不支持的属性是 endpoint_type。当使用配置 module 时,会自动激活用于非 OpenStack API 的动态轮询系统。
在使用非 OpenStack 动态轮询子子系统时,可用的额外参数(除了原始参数)如下
module:必需参数。它是 Ceilometer 在对 API 执行请求时必须加载的 Python 模块名称。例如,如果想要创建轮询器来收集来自 RadosGW 的数据,可以使用awsauthPython 模块。authentication_object:必需参数。我们在module中可以找到的类名称,Ceilometer 将在请求中使用它作为身份验证对象。例如,当使用awsauthPython 模块从 RadosGW 收集数据时,可以使用身份验证对象作为S3Auth。authentication_parameters:可选参数。它是一个逗号分隔的值,将用于实例化authentication_object。例如,如果从 RadosGW 收集数据,并使用S3Auth类,则可以将authentication_parameters配置为<rados_gw_access_key>, rados_gw_secret_key, rados_gw_host_name。barbican_secret_id: 可选参数。Barbican 密钥 ID,Ceilometer 可以从中检索逗号分隔的authentication_parameters值。
以下我们展示一个将 radosgw.api.request 指标的硬编码 pollster 转换为动态 pollster 模型的方法示例
---
- name: "dynamic.radosgw.api.request"
sample_type: "gauge"
unit: "request"
value_attribute: "total.ops"
url_path: "http://rgw.service.stage.i.ewcs.ch/admin/usage"
module: "awsauth"
authentication_object: "S3Auth"
authentication_parameters: "<access_key>,<secret_key>,<rados_gateway_server>"
user_id_attribute: "user"
project_id_attribute: "user"
resource_id_attribute: "user"
response_entries_key: "summary"
我们可以进一步扩展该示例,并使用 successful_ops,而不是收集 total .ops 变量,后者统计所有请求(包括不成功的请求)。
---
- name: "dynamic.radosgw.api.request.successful_ops"
sample_type: "gauge"
unit: "request"
value_attribute: "total.successful_ops"
url_path: "http://rgw.service.stage.i.ewcs.ch/admin/usage"
module: "awsauth"
authentication_object: "S3Auth"
authentication_parameters: "<access_key>, <secret_key>,<rados_gateway_server>"
user_id_attribute: "user"
project_id_attribute: "user"
resource_id_attribute: "user"
response_entries_key: "summary"
动态 pollsters 系统配置(适用于本地主机命令)¶
动态 pollster 系统也可以用于本地主机命令,这些命令必须安装在运行 Ceilometer 计算代理的系统中。要配置本地主机命令,可以使用动态 pollster 系统除以下两个属性之外的所有属性。不支持的属性是 endpoint_type 和 url_path。当使用配置 host_command 时,动态 pollster 系统会自动激活。
在使用本地主机命令动态 pollster 子子系统时,除了原始参数之外,还可以使用以下额外参数
host_command: 必需参数。它是在 Ceilometer 动态 pollster 代理运行的主机上执行的主机命令。该命令的输出将被 pollster 处理并存储在配置的后端中。
以下我们展示一个如何使用本地主机命令的示例
---
- name: "dynamic.host.command"
sample_type: "gauge"
unit: "request"
value_attribute: "value"
response_entries_key: "test"
host_command: "echo '<test><user_id>id1_u</user_id><project_id>id1_p</project_id><id>id1</id><meta>meta-data-to-store</meta><value>1</value></test>'"
metadata_fields:
- "meta"
response_handlers:
- xml
要执行多页主机命令,next_sample_url_attribute 必须生成下一个示例命令,如下例所示
---
- name: "dynamic.s3.objects.size"
sample_type: "gauge"
unit: "request"
value_attribute: "Size"
project_id_attribute: "Owner.ID"
user_id_attribute: "Owner.ID"
resource_id_attribute: "Key"
response_entries_key: "Contents"
host_command: "aws s3api list-objects"
next_sample_url_attribute: NextToken | 'aws s3api list-objects --starting-token "' + value + '"'
提取属性上的操作¶
动态 pollster 系统可以执行 Python 操作来转换从系统处理的 JSON 响应中提取的属性。
一个用例示例是 RadosGW,它将 <project_id$project_id> 作为用户名(通常映射到 Gnocchi resource_id)。借助此功能(提取属性上的操作),可以在动态 pollster 中创建配置以清理/规范化该变量。就像定义 resource_id_attribute: “user | value.split(‘$’)[0].strip()” 这样简单。
操作之间用 | 符号分隔。表达式的第一个元素是从 JSON 对象中检索的键。其他元素可以应用于 value 变量的操作。value 变量是我们用来保存提取数据的变量。前面的示例可以重写为:resource_id_attribute: “user | value.split (‘$’) | value[0] | value.strip()”
以下我们展示一个用于删除 $ 符号并获取字符串第一部分的 RadosGW 动态 pollster 的完整配置。
---
- name: "dynamic.radosgw.api.request.successful_ops"
sample_type: "gauge"
unit: "request"
value_attribute: "total.successful_ops"
url_path: "http://rgw.service.stage.i.ewcs.ch/admin/usage"
module: "awsauth"
authentication_object: "S3Auth"
authentication_parameters: "<access_key>,<secret_key>,<rados_gateway_server>"
user_id_attribute: "user | value.split ('$') | value[0]"
project_id_attribute: "user | value.split ('$') | value[0]"
resource_id_attribute: "user | value.split ('$') | value[0]"
response_entries_key: "summary"
支持此功能的动态 pollster 配置选项如下
value_attribute
response_entries_key
user_id_attribute
project_id_attribute
resource_id_attribute
多指标动态 pollsters(处理具有对象列表的属性值)¶
此功能的初始想法来自我们在 RadosGW API 的 summary 对象中可以找到的 categories 字段。每个用户在响应中都有一个 categories 属性;在 categories 列表中,我们可以找到以粒状方式呈现不同 RadosGW API 操作(例如 GET、PUT、POST 等)消耗的对象。
以下我们展示一个这样的 JSON 响应示例。
{
"entries": [
{
"buckets": [
{
"bucket": "",
"categories": [
{
"bytes_received": 0,
"bytes_sent": 40,
"category": "list_buckets",
"ops": 2,
"successful_ops": 2
}
],
"epoch": 1572969600,
"owner": "user",
"time": "2019-11-21 00:00:00.000000Z"
},
{
"bucket": "-",
"categories": [
{
"bytes_received": 0,
"bytes_sent": 0,
"category": "get_obj",
"ops": 1,
"successful_ops": 0
}
],
"epoch": 1572969600,
"owner": "someOtherUser",
"time": "2019-11-21 00:00:00.000000Z"
}
]
}
]
"summary": [
{
"categories": [
{
"bytes_received": 0,
"bytes_sent": 0,
"category": "create_bucket",
"ops": 2,
"successful_ops": 2
},
{
"bytes_received": 0,
"bytes_sent": 2120428,
"category": "get_obj",
"ops": 46,
"successful_ops": 46
},
{
"bytes_received": 0,
"bytes_sent": 21484,
"category": "list_bucket",
"ops": 8,
"successful_ops": 8
},
{
"bytes_received": 6889056,
"bytes_sent": 0,
"category": "put_obj",
"ops": 46,
"successful_ops": 46
}
],
"total": {
"bytes_received": 6889056,
"bytes_sent": 2141912,
"ops": 102,
"successful_ops": 102
},
"user": "user"
},
{
"categories": [
{
"bytes_received": 0,
"bytes_sent": 0,
"category": "create_bucket",
"ops": 1,
"successful_ops": 1
},
{
"bytes_received": 0,
"bytes_sent": 0,
"category": "delete_obj",
"ops": 23,
"successful_ops": 23
},
{
"bytes_received": 0,
"bytes_sent": 5371,
"category": "list_bucket",
"ops": 2,
"successful_ops": 2
},
{
"bytes_received": 3444350,
"bytes_sent": 0,
"category": "put_obj",
"ops": 23,
"successful_ops": 23
}
],
"total": {
"bytes_received": 3444350,
"bytes_sent": 5371,
"ops": 49,
"successful_ops": 49
},
"user": "someOtherUser"
}
]
}
在这种情况下,并且考虑到我们拥有具有类似数据结构的 API,我们开发了动态 pollster 的扩展,该扩展支持为单个 pollster 处理多指标。它的工作方式如下。
pollster 名称将包含用于标识“子指标”的变量的占位符。例如 dynamic.radosgw.api.request.{category}。占位符 {category} 指示列表中对象的属性,我们使用它来加载子指标名称。然后,我们必须在 value_attribute 配置中使用一种特殊表示法来指示我们正在处理一个对象列表。这通过 [](方括号)实现;例如,在 dynamic.radosgw.api.request.{category} 中,我们可以使用 [categories].ops 作为 value_attribute。这表示我们检索到的值是一个对象列表,并且当动态 pollster 处理它时,我们希望它(pollster)为正在生成的子指标加载 ops 值。
以下是创建处理来自 RadosGW API 数据的多指标 pollster 的示例
---
- name: "dynamic.radosgw.api.request.{category}"
sample_type: "gauge"
unit: "request"
value_attribute: "[categories].ops"
url_path: "http://rgw.service.stage.i.ewcs.ch/admin/usage"
module: "awsauth"
authentication_object: "S3Auth"
authentication_parameters: "<access_key>, <secret_key>,<rados_gateway_server>"
user_id_attribute: "user | value.split('$')[0]"
project_id_attribute: "user | value.split('$') | value[0]"
resource_id_attribute: "user | value.split('$') | value[0]"
response_entries_key: "summary"
- name: "dynamic.radosgw.api.request.successful_ops.{category}"
sample_type: "gauge"
unit: "request"
value_attribute: "[categories].successful_ops"
url_path: "http://rgw.service.stage.i.ewcs.ch/admin/usage"
module: "awsauth"
authentication_object: "S3Auth"
authentication_parameters: "<access_key>, <secret_key>,<rados_gateway_server>"
user_id_attribute: "user | value.split('$')[0]"
project_id_attribute: "user | value.split('$') | value[0]"
resource_id_attribute: "user | value.split('$') | value[0]"
response_entries_key: "summary"
- name: "dynamic.radosgw.api.bytes_sent.{category}"
sample_type: "gauge"
unit: "request"
value_attribute: "[categories].bytes_sent"
url_path: "http://rgw.service.stage.i.ewcs.ch/admin/usage"
module: "awsauth"
authentication_object: "S3Auth"
authentication_parameters: "<access_key>, <secret_key>,<rados_gateway_server>"
user_id_attribute: "user | value.split('$')[0]"
project_id_attribute: "user | value.split('$') | value[0]"
resource_id_attribute: "user | value.split('$') | value[0]"
response_entries_key: "summary"
- name: "dynamic.radosgw.api.bytes_received.{category}"
sample_type: "gauge"
unit: "request"
value_attribute: "[categories].bytes_received"
url_path: "http://rgw.service.stage.i.ewcs.ch/admin/usage"
module: "awsauth"
authentication_object: "S3Auth"
authentication_parameters: "<access_key>, <secret_key>,<rados_gateway_server>"
user_id_attribute: "user | value.split('$')[0]"
project_id_attribute: "user | value.split('$') | value[0]"
resource_id_attribute: "user | value.split('$') | value[0]"
response_entries_key: "summary"
处理链接的 API 响应¶
如果消耗的 API 返回一个链接响应,其中包含指向下一个响应集(页面)的链接,则动态 pollsters 可以配置为跟踪这些链接并将所有链接的响应合并到一个响应中。
要启用此行为,操作员需要配置参数 next_sample_url_attribute,该参数必须包含一个映射器,用于映射到包含指向下一个响应页面的链接的响应属性。此参数还支持与其他 *_attribute 动态 pollster 参数类似的操作。
以下是创建处理链接 API 响应的 pollster 的示例
一个简单的链接响应示例
API 响应
{ "server_link": "http://test.com/v1/test-volumes/marker=c3", "servers": [ { "volume": [ { "name": "a", "tmp": "ra" } ], "id": 1, "name": "a1" }, { "volume": [ { "name": "b", "tmp": "rb" } ], "id": 2, "name": "b2" }, { "volume": [ { "name": "c", "tmp": "rc" } ], "id": 3, "name": "c3" } ] }
Pollster 配置
--- - name: "dynamic.linked.response" sample_type: "gauge" unit: "request" value_attribute: "[volume].tmp" url_path: "v1/test-volumes" response_entries_key: "servers" next_sample_url_attribute: "server_link"
一个复杂的链接响应示例
API 响应
{ "server_link": [ { "href": "http://test.com/v1/test-volumes/marker=c3", "rel": "next" }, { "href": "http://test.com/v1/test-volumes/marker=b1", "rel": "prev" } ], "servers": [ { "volume": [ { "name": "a", "tmp": "ra" } ], "id": 1, "name": "a1" }, { "volume": [ { "name": "b", "tmp": "rb" } ], "id": 2, "name": "b2" }, { "volume": [ { "name": "c", "tmp": "rc" } ], "id": 3, "name": "c3" } ] }
Pollster 配置
--- - name: "dynamic.linked.response" sample_type: "gauge" unit: "request" value_attribute: "[volume].tmp" url_path: "v1/test-volumes" response_entries_key: "servers" next_sample_url_attribute: "server_link | filter(lambda v: v.get('rel') == 'next', value) | list(value) | value[0] | value.get('href')"
OpenStack 动态 pollsters 元数据丰富,包含其他 OpenStack API 的数据¶
有时我们想要/需要为 Ceilometer 动态 pollsters 处理的样本添加/收集额外的元数据,例如项目名称、域 ID、域名称和其他并非始终可通过收集样本的 OpenStack 组件访问的元数据。
例如,当我们从 Nova 收集虚拟机 (VM) 的状态时,我们只有 tenant_id,必须将其用作 project_id。但是,对于计费和后续开票,可能需要/想要项目名称、域 ID 和 Keystone 中可用的其他元数据(以及可能散布在其他组件中的一些元数据)。要实现这一点,可以使用 OpenStack 元数据丰富选项。以下我们展示一个动态 pollster 配置示例,用于收集虚拟机 (VM) 状态,并使用 Keystone 和本地主机通过 extra_metadata_fields 选项收集的项目名称、域 ID 和域名称来丰富推送到存储后端(例如 Gnocchi)的数据。
--- - name: "dynamic_pollster.instance.status" next_sample_url_attribute: "server_links | filter(lambda v: v.get('rel') == 'next', value) | list(value) | value[0] | value.get('href') | value.replace('http:', 'https:')" sample_type: "gauge" unit: "server" value_attribute: "status" endpoint_type: "compute" url_path: "/v2.1/servers/detail?all_tenants=true" headers: "Openstack-API-Version": "compute 2.65" project_id_attribute: "tenant_id" metadata_fields: - "status" - "name" - "flavor.vcpus" - "flavor.ram" - "flavor.disk" - "flavor.ephemeral" - "flavor.swap" - "flavor.original_name" - "image | value or { 'id': '' } | value['id']" - "OS-EXT-AZ:availability_zone" - "OS-EXT-SRV-ATTR:host" - "user_id" - "tags | ','.join(value)" - "locked" value_mapping: ACTIVE: "1" default_value: 0 metadata_mapping: "OS-EXT-AZ:availability_zone": "dynamic_availability_zone" "OS-EXT-SRV-ATTR:host": "dynamic_host" "flavor.original_name": "dynamic_flavor_name" "flavor.vcpus": "dynamic_flavor_vcpus" "flavor.ram": "dynamic_flavor_ram" "flavor.disk": "dynamic_flavor_disk" "flavor.ephemeral": "dynamic_flavor_ephemeral" "flavor.swap": "dynamic_flavor_swap" "image | value or { 'id': '' } | value['id']": "dynamic_image_ref" "name": "dynamic_display_name" "locked": "dynamic_locked" "tags | ','.join(value)": "dynamic_tags" extra_metadata_fields_cache_seconds: 3600 extra_metadata_fields_skip: - value: '1' metadata: dynamic_flavor_vcpus: 4 - value: '1' metadata: dynamic_flavor_vcpus: 2 extra_metadata_fields: - name: "project_name" endpoint_type: "identity" url_path: "'/v3/projects/' + str(sample['project_id'])" headers: "Openstack-API-Version": "identity latest" value: "name" extra_metadata_fields_cache_seconds: 1800 # overriding the default cache policy metadata_fields: - id - name: "domain_id" endpoint_type: "identity" url_path: "'/v3/projects/' + str(sample['project_id'])" headers: "Openstack-API-Version": "identity latest" value: "domain_id" metadata_fields: - id - name: "domain_name" endpoint_type: "identity" url_path: "'/v3/domains/' + str(extra_metadata_captured['domain_id'])" headers: "Openstack-API-Version": "identity latest" value: "name" metadata_fields: - id - name: "operating-system" host_command: "'get-vm --vm-name ' + str(extra_metadata_by_name['project_name']['metadata']['id'])" value: "os"
上述示例可用于收集和持久化到后端的 VM 状态。如果 VM 的状态为 ACTIVE,它将在每个收集周期将 1 持久化到后端,否则将持久化 0。这对于为 CloudKitty 中的运行 VM 创建哈希映射评级规则非常有用。然后,为了丰富存储后端中的资源,我们正在添加通过 extra_metadata_fields 选项在 Keystone 和本地主机收集的额外元数据。如果您有多个 extra_metadata_fields 定义相同的 metadata_field,则最后一个非 None 元数据值将被使用。
要操作 extra_metadata_fields 中的值,您可以访问 3 个本地变量
sample: 这是一个字典,其中包含当前根样本的数据。根样本是最终将持久化到配置存储后端中的样本。extra_metadata_captured: 这是一个字典,其中包含在此之前处理的所有 extra_metadata_fields 的当前数据。如果您有多个 extra_metadata_fields 定义相同的 metadata_field,则最后一个非 None 元数据值将被使用。extra_metadata_by_name: 这是一个字典,其中包含在此之前处理的所有 extra_metadata_fields 的数据。此变量中不会覆盖任何数据。要使用此变量访问特定的 extra_metadata_field,您可以执行 extra_metadata_by_name[‘<extra_metadata_field_name>’][‘value’] 以获取其值,或 extra_metadata_by_name[‘<extra_metadata_field_name>’][‘metadata’][‘<metadata>’] 以获取其元数据。
元数据丰富功能具有以下选项
extra_metadata_fields_cache_seconds: 可选参数。定义额外的元数据请求的响应缓存。一些请求,例如针对 Keystone 检索额外元数据的请求,相对静态。因此,无需不断重新执行请求。这就是我们缓存此类请求的响应的原因。默认情况下,响应的生存时间 (TTL) 为 3600 秒。但是,可以增加或减少此值。extra_metadata_fields: 可选参数。此选项是对象列表或单个对象,其中每个元素都是一个动态 pollster 配置集。每个额外的元数据定义都可以拥有动态 pollster 中定义的相同选项,包括 extra_metadata_fields 选项,因此此选项是一个多级选项。定义后,收集的数据结果将合并到最终样本资源元数据中。如果 extra_metadata_fields 中未设置所需的动态 pollster 配置,将使用父 pollster 配置,但 name 除外。extra_metadata_fields_skip: 可选参数。此选项是对象列表或单个对象,其中每个元素都是一组键/值对。定义后,如果任何一组键/值对是收集样本的子集,则将跳过此样本的 extra_metadata_fields 收集。