11package system
22
33import (
4- "encoding/json"
54 "fmt"
6- "os/exec"
7- "strings"
85
6+ "github.com/kubernetes-csi/csi-proxy/pkg/cim"
7+ "github.com/kubernetes-csi/csi-proxy/pkg/server/system/impl"
98 "github.com/kubernetes-csi/csi-proxy/pkg/utils"
9+ "github.com/microsoft/wmi/pkg/base/query"
10+ "github.com/microsoft/wmi/server2019/root/cimv2"
1011)
1112
1213// Implements the System OS API calls. All code here should be very simple
@@ -25,52 +26,97 @@ type ServiceInfo struct {
2526 Status uint32 `json:"Status"`
2627}
2728
29+ var (
30+ startModeMappings = map [string ]uint32 {
31+ "Boot" : impl .START_TYPE_BOOT ,
32+ "System" : impl .START_TYPE_SYSTEM ,
33+ "Auto" : impl .START_TYPE_AUTOMATIC ,
34+ "Manual" : impl .START_TYPE_MANUAL ,
35+ "Disabled" : impl .START_TYPE_DISABLED ,
36+ }
37+
38+ statusMappings = map [string ]uint32 {
39+ "Unknown" : impl .SERVICE_STATUS_UNKNOWN ,
40+ "Stopped" : impl .SERVICE_STATUS_STOPPED ,
41+ "Start Pending" : impl .SERVICE_STATUS_START_PENDING ,
42+ "Stop Pending" : impl .SERVICE_STATUS_STOP_PENDING ,
43+ "Running" : impl .SERVICE_STATUS_RUNNING ,
44+ "Continue Pending" : impl .SERVICE_STATUS_CONTINUE_PENDING ,
45+ "Pause Pending" : impl .SERVICE_STATUS_PAUSE_PENDING ,
46+ "Paused" : impl .SERVICE_STATUS_PAUSED ,
47+ }
48+ )
49+
50+ func serviceStartModeToStartType (startMode string ) uint32 {
51+ return startModeMappings [startMode ]
52+ }
53+
54+ func serviceState (status string ) uint32 {
55+ return statusMappings [status ]
56+ }
57+
2858type APIImplementor struct {}
2959
3060func New () APIImplementor {
3161 return APIImplementor {}
3262}
3363
3464func (APIImplementor ) GetBIOSSerialNumber () (string , error ) {
35- // Taken from Kubernetes vSphere cloud provider
36- // https://github.com/kubernetes/kubernetes/blob/103e926604de6f79161b78af3e792d0ed282bc06/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere_util_windows.go#L28
37- result , err := exec .Command ("wmic" , "bios" , "get" , "serialnumber" ).Output ()
65+ biosQuery := query .NewWmiQueryWithSelectList ("CIM_BIOSElement" , []string {"SerialNumber" })
66+ instances , err := cim .QueryInstances ("" , biosQuery )
3867 if err != nil {
3968 return "" , err
4069 }
41- lines := strings .FieldsFunc (string (result ), func (r rune ) bool {
42- switch r {
43- case '\n' , '\r' :
44- return true
45- default :
46- return false
47- }
48- })
49- if len (lines ) != 2 {
50- return "" , fmt .Errorf ("received unexpected value retrieving host uuid: %q" , string (result ))
70+
71+ bios , err := cimv2 .NewCIM_BIOSElementEx1 (instances [0 ])
72+ if err != nil {
73+ return "" , fmt .Errorf ("failed to get BIOS element: %w" , err )
74+ }
75+
76+ sn , err := bios .GetPropertySerialNumber ()
77+ if err != nil {
78+ return "" , fmt .Errorf ("failed to get BIOS serial number property: %w" , err )
5179 }
52- return lines [1 ], nil
80+
81+ return sn , nil
5382}
5483
5584func (APIImplementor ) GetService (name string ) (* ServiceInfo , error ) {
56- script := `Get-Service -Name $env:ServiceName | Select-Object DisplayName, Status, StartType | ` +
57- `ConvertTo-JSON`
58- cmdEnv := fmt .Sprintf ("ServiceName=%s" , name )
59- out , err := utils .RunPowershellCmd (script , cmdEnv )
85+ serviceQuery := query .NewWmiQueryWithSelectList ("Win32_Service" , []string {"DisplayName" , "State" , "StartMode" }, "Name" , name )
86+ instances , err := cim .QueryInstances ("" , serviceQuery )
6087 if err != nil {
61- return nil , fmt . Errorf ( "error querying service name=%s. cmd: %s, output: %s, error: %v" , name , script , string ( out ), err )
88+ return nil , err
6289 }
6390
64- var serviceInfo ServiceInfo
65- err = json .Unmarshal (out , & serviceInfo )
91+ service , err := cimv2 .NewWin32_ServiceEx1 (instances [0 ])
6692 if err != nil {
67- return nil , err
93+ return nil , fmt .Errorf ("failed to get service %s: %w" , name , err )
94+ }
95+
96+ displayName , err := service .GetPropertyDisplayName ()
97+ if err != nil {
98+ return nil , fmt .Errorf ("failed to get displayName property of service %s: %w" , name , err )
99+ }
100+
101+ state , err := service .GetPropertyState ()
102+ if err != nil {
103+ return nil , fmt .Errorf ("failed to get state property of service %s: %w" , name , err )
104+ }
105+
106+ startMode , err := service .GetPropertyStartMode ()
107+ if err != nil {
108+ return nil , fmt .Errorf ("failed to get startMode property of service %s: %w" , name , err )
68109 }
69110
70- return & serviceInfo , nil
111+ return & ServiceInfo {
112+ DisplayName : displayName ,
113+ StartType : serviceStartModeToStartType (startMode ),
114+ Status : serviceState (state ),
115+ }, nil
71116}
72117
73118func (APIImplementor ) StartService (name string ) error {
119+ // Note: both StartService and StopService are not implemented by WMI
74120 script := `Start-Service -Name $env:ServiceName`
75121 cmdEnv := fmt .Sprintf ("ServiceName=%s" , name )
76122 out , err := utils .RunPowershellCmd (script , cmdEnv )
0 commit comments