Skip to content

Commit aaba2be

Browse files
committed
Collect host hardware info on mac
1 parent f790669 commit aaba2be

File tree

4 files changed

+148
-1
lines changed

4 files changed

+148
-1
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Unless explicitly stated otherwise all files in this repository are licensed
2+
// under the Apache License Version 2.0.
3+
// This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
// Copyright 2016-present Datadog, Inc.
5+
6+
//go:build darwin
7+
8+
package hardware
9+
10+
/*
11+
#cgo CFLAGS: -x objective-c -fobjc-arc
12+
#cgo LDFLAGS: -framework Foundation -framework IOKit
13+
14+
#include <stdlib.h>
15+
#include "hosthardware_darwin.h"
16+
*/
17+
import "C"
18+
import (
19+
"strings"
20+
"unsafe"
21+
)
22+
23+
func collect() (*SystemHardwareInfo, error) {
24+
cInfo := C.getDeviceInfo()
25+
defer C.free(unsafe.Pointer(cInfo.modelIdentifier))
26+
defer C.free(unsafe.Pointer(cInfo.modelNumber))
27+
defer C.free(unsafe.Pointer(cInfo.productName))
28+
defer C.free(unsafe.Pointer(cInfo.serialNumber))
29+
30+
return &SystemHardwareInfo{
31+
Manufacturer: "Apple Inc.",
32+
Name: C.GoString(cInfo.productName),
33+
Identifier: C.GoString(cInfo.modelIdentifier),
34+
ModelNumber: C.GoString(cInfo.modelNumber),
35+
SerialNumber: C.GoString(cInfo.serialNumber),
36+
ChassisType: getChassisType(C.GoString(cInfo.productName), C.GoString(cInfo.modelIdentifier)),
37+
}, nil
38+
}
39+
40+
func getChassisType(productName string, modelIdentifier string) string {
41+
lowerName := strings.ToLower(productName)
42+
lowerModel := strings.ToLower(modelIdentifier)
43+
44+
// Check for virtual machines first
45+
// VMware VMs have modelIdentifier like "VMware7,1"
46+
// Apple Silicon VMs have modelIdentifier like "VirtualMac2,1" and productName "Apple Virtual Machine 1"
47+
// Parallels VMs have "Parallels" in the modelIdentifier
48+
if strings.Contains(lowerModel, "vmware") ||
49+
strings.Contains(lowerModel, "virtual") ||
50+
strings.Contains(lowerModel, "parallels") ||
51+
strings.Contains(lowerName, "virtual") {
52+
return "Virtual Machine"
53+
}
54+
55+
if strings.HasPrefix(lowerName, "macbook") {
56+
return "Laptop"
57+
}
58+
59+
if strings.HasPrefix(lowerName, "imac") ||
60+
strings.HasPrefix(lowerName, "mac mini") ||
61+
strings.HasPrefix(lowerName, "mac pro") ||
62+
strings.HasPrefix(lowerName, "mac studio") {
63+
return "Desktop"
64+
}
65+
66+
return "Other"
67+
}

pkg/inventory/hardware/collector_nix.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// This product includes software developed at Datadog (https://www.datadoghq.com/).
44
// Copyright 2016-present Datadog, Inc.
55

6-
//go:build !windows
6+
//go:build !windows && !darwin
77

88
package hardware
99

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#import <Foundation/Foundation.h>
2+
#import <IOKit/IOKitLib.h>
3+
#import "hosthardware_darwin.h"
4+
#import <stdlib.h>
5+
#import <string.h>
6+
7+
static NSDictionary *getServiceProperties(CFMutableDictionaryRef matching) {
8+
io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, matching);
9+
if (!service) return nil;
10+
11+
CFMutableDictionaryRef props = NULL;
12+
if (IORegistryEntryCreateCFProperties(service, &props, kCFAllocatorDefault, 0) != KERN_SUCCESS) {
13+
IOObjectRelease(service);
14+
return nil;
15+
}
16+
17+
IOObjectRelease(service);
18+
return (__bridge_transfer NSDictionary *)props;
19+
}
20+
21+
static char *copyStringProperty(NSDictionary *props, NSString *key) {
22+
id value = props[key];
23+
if (!value) return NULL;
24+
25+
if ([value isKindOfClass:[NSString class]]) {
26+
return strdup([value UTF8String]);
27+
} else if ([value isKindOfClass:[NSData class]]) {
28+
const char *bytes = (const char *)[value bytes];
29+
return strndup(bytes, strnlen(bytes, [value length]));
30+
}
31+
return NULL;
32+
}
33+
34+
DeviceInfo getDeviceInfo(void) {
35+
@autoreleasepool {
36+
DeviceInfo info = {0};
37+
38+
NSDictionary *platform = getServiceProperties(IOServiceMatching("IOPlatformExpertDevice"));
39+
if (platform) {
40+
info.found = true;
41+
info.modelIdentifier = copyStringProperty(platform, @"model");
42+
info.serialNumber = copyStringProperty(platform, @"IOPlatformSerialNumber");
43+
44+
char *modelNum = copyStringProperty(platform, @"model-number");
45+
char *region = copyStringProperty(platform, @"region-info");
46+
if (modelNum && region) {
47+
asprintf(&info.modelNumber, "%s%s", modelNum, region);
48+
free(modelNum);
49+
free(region);
50+
} else {
51+
info.modelNumber = modelNum;
52+
free(region);
53+
}
54+
}
55+
56+
NSDictionary *product = getServiceProperties(IOServiceNameMatching("product"));
57+
if (product) {
58+
info.productName = copyStringProperty(product, @"product-name");
59+
}
60+
61+
return info;
62+
}
63+
}
64+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef HOSTHARDWARE_DARWIN_H
2+
#define HOSTHARDWARE_DARWIN_H
3+
4+
#include <stdbool.h>
5+
6+
typedef struct {
7+
bool found;
8+
char *modelIdentifier;
9+
char *modelNumber;
10+
char *productName;
11+
char *serialNumber;
12+
} DeviceInfo;
13+
14+
DeviceInfo getDeviceInfo(void);
15+
16+
#endif

0 commit comments

Comments
 (0)