diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 65a6af33c343..c49f632b2976 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -60,6 +60,7 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff] - Update metrics for the vSphere Host metricset. {pull}40429[40429] - Mark system process metricsets as running if metrics are partially available {pull}40565[40565] - Added back `elasticsearch.node.stats.jvm.mem.pools.*` to the `node_stats` metricset {pull}40571[40571] +- Add support for snapshot in vSphere virtualmachine metricset {pull}40683[40683] *Osquerybeat* diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 953b15b83c0a..0016c4738055 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -67947,7 +67947,7 @@ type: long *`vsphere.virtualmachine.cpu.total.mhz`*:: + -- -Total CPU in Mhz. +Total Reserved CPU in Mhz. type: long @@ -68090,6 +68090,25 @@ type: keyword The uptime of the VM in seconds. +type: long + +-- + + +*`vsphere.virtualmachine.snapshot.info`*:: ++ +-- +Deatils of the snapshots of this virtualmachine. + +type: object + +-- + +*`vsphere.virtualmachine.snapshot.count`*:: ++ +-- +The number of snapshots of this virtualmachine. + type: long -- diff --git a/metricbeat/module/vsphere/fields.go b/metricbeat/module/vsphere/fields.go index 86bbe2a77046..05e29ff253c4 100644 --- a/metricbeat/module/vsphere/fields.go +++ b/metricbeat/module/vsphere/fields.go @@ -32,5 +32,5 @@ func init() { // AssetVsphere returns asset data. // This is the base64 encoded zlib format compressed contents of module/vsphere. func AssetVsphere() string { - return "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" + return "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" } diff --git a/metricbeat/module/vsphere/virtualmachine/_meta/data.json b/metricbeat/module/vsphere/virtualmachine/_meta/data.json index d04a8efb42db..d2917e5e6a9a 100644 --- a/metricbeat/module/vsphere/virtualmachine/_meta/data.json +++ b/metricbeat/module/vsphere/virtualmachine/_meta/data.json @@ -66,7 +66,21 @@ "datastore.names": [ "VxRailtec-Virtual-SAN-Datastore-247df-bc1d-5aad2" ], - "host.id": "host-20" + "host.id": "host-20", + "snapshot.info": [ + { + "Name": "Snapshot_1", + "Description": "Test snapshot 1", + "CreateTime": "2024-09-01T12:34:56Z" + + }, + { + "Name": "Snapshot_2", + "Description": "Test snapshot 2", + "CreateTime": "2024-09-03T2:34:56Z" + } + ], + "snapshot.count": 2 } } } diff --git a/metricbeat/module/vsphere/virtualmachine/_meta/fields.yml b/metricbeat/module/vsphere/virtualmachine/_meta/fields.yml index 6720da187652..fcfe2b9bbb30 100644 --- a/metricbeat/module/vsphere/virtualmachine/_meta/fields.yml +++ b/metricbeat/module/vsphere/virtualmachine/_meta/fields.yml @@ -27,7 +27,7 @@ - name: cpu.total.mhz type: long description: > - Total CPU in Mhz. + Total Reserved CPU in Mhz. - name: cpu.free.mhz type: long description: > @@ -91,5 +91,14 @@ type: long description: > The uptime of the VM in seconds. + - name: snapshot + type: group + fields: + - name: info + type: object + description: Deatils of the snapshots of this virtualmachine. + - name: count + type: long + description: The number of snapshots of this virtualmachine. diff --git a/metricbeat/module/vsphere/virtualmachine/data.go b/metricbeat/module/vsphere/virtualmachine/data.go index 5c814105f90b..69d0bd1df541 100644 --- a/metricbeat/module/vsphere/virtualmachine/data.go +++ b/metricbeat/module/vsphere/virtualmachine/data.go @@ -72,5 +72,10 @@ func (m *MetricSet) mapEvent(data VMData) mapstr.M { if len(data.DatastoreNames) > 0 { event["datastore.names"] = data.DatastoreNames } + if len(data.Snapshots) > 0 { + event["snapshot.info"] = data.Snapshots + event["snapshot.count"] = len(data.Snapshots) + } + return event } diff --git a/metricbeat/module/vsphere/virtualmachine/data_test.go b/metricbeat/module/vsphere/virtualmachine/data_test.go index 351daea7c118..e11d39a81973 100644 --- a/metricbeat/module/vsphere/virtualmachine/data_test.go +++ b/metricbeat/module/vsphere/virtualmachine/data_test.go @@ -19,6 +19,7 @@ package virtualmachine import ( "testing" + "time" "github.com/stretchr/testify/assert" "github.com/vmware/govmomi/vim25/mo" @@ -58,6 +59,22 @@ func TestEventMapping(t *testing.T) { "customField1": "value1", "customField2": "value2", }, + Snapshots: []VMSnapshotData{ + { + ID: 123, + Name: "Snapshot_1", + Description: "Test snapshot 1", + CreateTime: time.Time{}, + State: types.VirtualMachinePowerStatePoweredOff, + }, + { + ID: 745, + Name: "Snapshot_2", + Description: "Test snapshot 2", + CreateTime: time.Time{}, + State: types.VirtualMachinePowerStatePoweredOn, + }, + }, } event := m.mapEvent(data) @@ -108,6 +125,23 @@ func TestEventMapping(t *testing.T) { "network.names": []string{"network-1", "network-2"}, "network_names": []string{"network-1", "network-2"}, "datastore.names": []string{"ds1", "ds2"}, + "snapshot.info": []VMSnapshotData{ + { + ID: 123, + Name: "Snapshot_1", + Description: "Test snapshot 1", + CreateTime: time.Time{}, + State: types.VirtualMachinePowerStatePoweredOff, + }, + { + ID: 745, + Name: "Snapshot_2", + Description: "Test snapshot 2", + CreateTime: time.Time{}, + State: types.VirtualMachinePowerStatePoweredOn, + }, + }, + "snapshot.count": 2, } // Assert that the output event matches the expected event diff --git a/metricbeat/module/vsphere/virtualmachine/virtualmachine.go b/metricbeat/module/vsphere/virtualmachine/virtualmachine.go index 107aabbc4bd3..82c928004102 100644 --- a/metricbeat/module/vsphere/virtualmachine/virtualmachine.go +++ b/metricbeat/module/vsphere/virtualmachine/virtualmachine.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "strings" + "time" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/module/vsphere" @@ -56,6 +57,15 @@ type VMData struct { NetworkNames []string DatastoreNames []string CustomFields mapstr.M + Snapshots []VMSnapshotData +} + +type VMSnapshotData struct { + ID int32 + Name string + Description string + CreateTime time.Time + State types.VirtualMachinePowerState } // New creates a new instance of the MetricSet. @@ -136,6 +146,7 @@ func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { var hostID, hostName string var networkNames, datastoreNames []string var customFields mapstr.M + var snapshots []VMSnapshotData if host := vm.Summary.Runtime.Host; host != nil { hostID = host.Value @@ -179,6 +190,10 @@ func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { } } + if vm.Snapshot != nil { + snapshots = fetchSnapshots(vm.Snapshot.RootSnapshotList) + } + data := VMData{ VM: vm, HostID: hostID, @@ -186,6 +201,7 @@ func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { NetworkNames: networkNames, DatastoreNames: datastoreNames, CustomFields: customFields, + Snapshots: snapshots, } reporter.Event(mb.Event{ @@ -270,3 +286,22 @@ func getHostSystem(ctx context.Context, c *vim25.Client, ref types.ManagedObject } return &hs, nil } + +func fetchSnapshots(snapshotTree []types.VirtualMachineSnapshotTree) []VMSnapshotData { + snapshots := make([]VMSnapshotData, 0, len(snapshotTree)) + for _, snapshot := range snapshotTree { + snapshots = append(snapshots, VMSnapshotData{ + ID: snapshot.Id, + Name: snapshot.Name, + Description: snapshot.Description, + CreateTime: snapshot.CreateTime, + State: snapshot.State, + }) + + // Recursively add child snapshots + if len(snapshot.ChildSnapshotList) > 0 { + snapshots = append(snapshots, fetchSnapshots(snapshot.ChildSnapshotList)...) + } + } + return snapshots +}