メインコンテンツへスキップ
  1. Blogs/

pyvmomiで自動化9 -performance情報を取得-

·2157 文字·
Blog VMware VSphere Pyvmomi Python
hiroki
著者
hiroki
クラウドを作るお仕事をしてます。
目次
pyvmomi - 関連記事
9: << この記事 >>

はじめに
#

pyvmomiにはsi.content.PerformanceManagerという機能があります。

これは以下のようなvCenterから取得できるVM/ESXiのperformance情報をpyvmomi経由で取得できるAPIです。

alt text

vCenterのチャート情報はdefaultでは1h以上過ぎたデータは容量削減のため値が丸められてしまいます。(1日前であれば5分間隔、1週間前なら30分間隔) APIで取得して外部に保存しておけばトラブルの切り分け等に役立ちます。

1. PerformanceManagerとは?
#

MOBでsi.content.PerformanceManagerと進むと以下のような項目が見えます。

項目 説明
description 集計方法(average, maximum)の定義が記載
historicalInterval 1day, 1week, 1monthごとのデータ保持数(sampling数)の定義が記載
perfCounter cpu.usage.average,mem.usage.averageのようなperformance情報の定義が記載

alt text

集計期間(historicalInterval)は変更もできますが、vCenterDBを圧迫していくのでおすすめではないようです。公式doc

2. perfCounterとは?
#

pyvmomiでperformance情報を取得する上で重要なのが、perfCounterです。 perfCounterにはperformance情報の定義が3つの属性に分類されて保存されています。

alt text

vCenterの監視(Monitor) → Performance → 詳細のチャートオプションの項目と対応します。 従って欲しいパフォーマンス情報をチャートオプションで確認して、cpu.usage.averageのようにperfCounterの属性を把握しておきましょう。

alt text
<group>.<name>.<rollup>とドットで繋ぐと表記しやすいので以降はこのように記載します。

3. performanceを取得してみる
#

1. perfCounterのKeyを特定する

pyvmomiでは、取得するperformance項目をperfCounterのKeyで指定するので、これを特定します。

# 扱いにくいので、performance情報: Keyという形で保存する
counters_dict = {
    f"{c.groupInfo.key}.{c.nameInfo.key}.{c.rollupType}": c.key
    for c in si.content.perfManager.perfCounter
}
# {'cpu.usage.none': 1,
#  'cpu.usage.average': 2,
#  'cpu.usage.minimum': 3,
#  'cpu.usage.maximum': 4,
#  'cpu.usagemhz.none': 5,
#  'cpu.usagemhz.average': 6,

# performance情報でKeyを検索する
counter_key = counters_dict["cpu.usagemhz.average"]
>>> 6

2. vim.PerformanceManager.QuerySpecを作成して、データを取得

引数は公式doc参照ください。

とは言っても、引数は複雑なので今回はいくつか例を紹介したいと思います。
query = vim.PerformanceManager.QuerySpec(
    maxSample=1,
    entity=host,
    metricId=[
        vim.PerformanceManager.MetricId(
            counterId=6,
            instance="*"
        )
    ],
    intervalId=20
)
res = si.content.perfManager.QueryPerf(querySpec=[query])

4. performance取得例
#

最新のデータを取得する
#

  • intervalId=20はデータの間隔です。1h以内のデータなら20s, 1day以内のデータなら300s等が選べます。
  • maxSample=1はデータの取得数です。2にすれば最新の2つが取得できます。

intervalId=21など、存在しないデータ間隔を選ぶとエラーになります。 とりうる値はこちら

vmodl.fault.InvalidArgument 

msg = 'A specified parameter was not correct:
faultCause = <unset>,
faultMessage = (vmodl.LocalizableMessage) [],
invalidProperty = 'querySpec.interval'

print(
    "{}.{}.{}".format(
        si.content.perfManager.perfCounter[5].groupInfo.key,
        si.content.perfManager.perfCounter[5].nameInfo.key,
        si.content.perfManager.perfCounter[5].rollupType
    )
)
>>> cpu.usagemhz.average

query = vim.PerformanceManager.QuerySpec(
    maxSample=1,
    entity=host,
    metricId=[
        vim.PerformanceManager.MetricId(
            counterId=5,
            instance="*"
        )
    ],
    format="normal",
    intervalId=20
)

res = si.content.perfManager.QueryPerf(querySpec=[query])
res

# (vim.PerformanceManager.EntityMetricBase) [
#    (vim.PerformanceManager.EntityMetric) {
#       dynamicType = <unset>,
#       dynamicProperty = (vmodl.DynamicProperty) [],
#       entity = 'vim.HostSystem:host-14',
#       sampleInfo = (vim.PerformanceManager.SampleInfo) [
#          (vim.PerformanceManager.SampleInfo) {
#             dynamicType = <unset>,
#             dynamicProperty = (vmodl.DynamicProperty) [],
#             timestamp = 2024-07-09T09:18:20Z,
#             interval = 20
#          }
#       ],
#       value = (vim.PerformanceManager.MetricSeries) [
#          (vim.PerformanceManager.IntSeries) {
#             dynamicType = <unset>,
#             dynamicProperty = (vmodl.DynamicProperty) [],
#             id = (vim.PerformanceManager.MetricId) {
#                dynamicType = <unset>,
#                dynamicProperty = (vmodl.DynamicProperty) [],
#                counterId = 5,
#                instance = ''
#             },
#             value = (long) [
#                2033
#             ]
#          }
#       ]
#    }
# ]

時間を指定して取得する
#

  • startTimeendTimeで範囲を指定できる
  • maxSampleはこの時間の範囲でなるべく最新のデータを取得する
from datetime import datetime, timedelta

print(
    "{}.{}.{}".format(
        si.content.perfManager.perfCounter[5].groupInfo.key,
        si.content.perfManager.perfCounter[5].nameInfo.key,
        si.content.perfManager.perfCounter[5].rollupType
    )
)
# cpu.usagemhz.average

query = vim.PerformanceManager.QuerySpec(
    maxSample=10,
    entity=host,
    metricId=[
        vim.PerformanceManager.MetricId(
            counterId=5,
            instance="*"
        )
    ],
    intervalId=20,
    startTime=datetime.now() - timedelta(minutes=20),
    endTime=datetime.now() - timedelta(minutes=10)
)

res = si.content.perfManager.QueryPerf(querySpec=[query])
res

# (vim.PerformanceManager.EntityMetricBase) [
#    (vim.PerformanceManager.EntityMetric) {
#       dynamicType = <unset>,
#       dynamicProperty = (vmodl.DynamicProperty) [],
#       entity = 'vim.HostSystem:host-14',
#       sampleInfo = (vim.PerformanceManager.SampleInfo) [
#          (vim.PerformanceManager.SampleInfo) {
#             dynamicType = <unset>,
#             dynamicProperty = (vmodl.DynamicProperty) [],
#             timestamp = 2024-07-09T09:28:00Z,
#             interval = 20
#          },
#          (vim.PerformanceManager.SampleInfo) {
#             dynamicType = <unset>,
#             dynamicProperty = (vmodl.DynamicProperty) [],
#             timestamp = 2024-07-09T09:28:20Z,
#             interval = 20
#          },
#          (vim.PerformanceManager.SampleInfo) {
#             dynamicType = <unset>,
#             dynamicProperty = (vmodl.DynamicProperty) [],
#             timestamp = 2024-07-09T09:28:40Z,
#             interval = 20
#          },

intervalId=20のデータは1h以内しか残っていないのに、1日前のqueryで指定するなど、存在しないデータをqueryすると空が返ってくるの注意

query = vim.PerformanceManager.QuerySpec(
    # 省略
    intervalId=20,
    startTime=datetime.now() - timedelta(day=2),
    endTime=datetime.now() - timedelta(day=1)
)

si.content.perfManager.QueryPerf(querySpec=[query])
>>>(vim.PerformanceManager.EntityMetricBase) []

instanceが複数ある場合
#

  • cpu.usage.averageのようにcore毎にperformance情報が取得できるものがある。
  • この時instance="*"としていると、全データが取得できる。

alt text

print(
    "{}.{}.{}".format(
        si.content.perfManager.perfCounter[1].groupInfo.key,
        si.content.perfManager.perfCounter[1].nameInfo.key,
        si.content.perfManager.perfCounter[1].rollupType
    )
)
# >>> cpu.usage.average


query = vim.PerformanceManager.QuerySpec(
    maxSample=1,
    entity=host,
    metricId=[
        vim.PerformanceManager.MetricId(
            counterId=1,
            instance="*"
        )
    ],
    format="normal",
    intervalId=20
)

res = si.content.perfManager.QueryPerf(querySpec=[query])
res

# (vim.PerformanceManager.IntSeries) {
# dynamicType = <unset>,
# dynamicProperty = (vmodl.DynamicProperty) [],
# id = (vim.PerformanceManager.MetricId) {
#     dynamicType = <unset>,
#     dynamicProperty = (vmodl.DynamicProperty) [],
#     counterId = 1,
#     instance = '4' # cpu4個目のデータ
# },
# value = (long) [
#     234
# ]
# },
# (vim.PerformanceManager.IntSeries) {
# dynamicType = <unset>,
# dynamicProperty = (vmodl.DynamicProperty) [],
# id = (vim.PerformanceManager.MetricId) {
#     dynamicType = <unset>,
#     dynamicProperty = (vmodl.DynamicProperty) [],
#     counterId = 1,
#     instance = '11' # cpu11個目のデータ
# },
# value = (long) [
#     538
# ]
# },
# 省略...

csv形式で取得
#

  • format="csv"にするとcsv形式で出力される。データ数が多い場合に有用
print(
    "{}.{}.{}".format(
        si.content.perfManager.perfCounter[5].groupInfo.key,
        si.content.perfManager.perfCounter[5].nameInfo.key,
        si.content.perfManager.perfCounter[5].rollupType
    )
)

query = vim.PerformanceManager.QuerySpec(
    maxSample=10,
    entity=host,
    metricId=[
        vim.PerformanceManager.MetricId(
            counterId=5,
            instance="*"
        )
    ],
    format="csv",
    intervalId=20
)

res = si.content.perfManager.QueryPerf(querySpec=[query])
res

# (vim.PerformanceManager.EntityMetricBase) [
#    (vim.PerformanceManager.EntityMetricCSV) {
#       dynamicType = <unset>,
#       dynamicProperty = (vmodl.DynamicProperty) [],
#       entity = 'vim.HostSystem:host-14',
#       sampleInfoCSV = '20,2024-07-09T09:27:00Z,20,2024-07-09T09:27:20Z,20,2024-07-09T09:27:40Z,20,2024-07-09T09:28:00Z,20,2024-07-09T09:28:20Z,20,2024-07-09T09:28:40Z,20,2024-07-09T09:29:00Z,20,2024-07-09T09:29:20Z,20,2024-07-09T09:29:40Z,20,2024-07-09T09:30:00Z',
#       value = (vim.PerformanceManager.MetricSeriesCSV) [
#          (vim.PerformanceManager.MetricSeriesCSV) {
#             dynamicType = <unset>,
#             dynamicProperty = (vmodl.DynamicProperty) [],
#             id = (vim.PerformanceManager.MetricId) {
#                dynamicType = <unset>,
#                dynamicProperty = (vmodl.DynamicProperty) [],
#                counterId = 5,
#                instance = ''
#             },
#             value = '1989,2126,2005,1898,1915,1816,1804,2179,2520,2623'
#          }
#       ]
#    }
# ]
pyvmomi - 関連記事
9: << この記事 >>

Related

pyvmomiで自動化8 -情報をまとめて取得-
·2484 文字
Blog VMware VSphere Pyvmomi Python
pyvmomiで自動化7 -HoLを使った検証環境の用意-
·1189 文字
Blog VMware VSphere Pyvmomi Python
pyvmomiで自動化6 -便利なツール群-
·1898 文字
Blog VMware VSphere Pyvmomi Python