Skip to content

Commit

Permalink
Use WMI instead of PowerShell for OS operations
Browse files Browse the repository at this point in the history
  • Loading branch information
laozc committed Oct 22, 2024
1 parent 07be14d commit 40de367
Show file tree
Hide file tree
Showing 12 changed files with 1,398 additions and 384 deletions.
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
module github.com/kubernetes-csi/csi-proxy

go 1.20
go 1.22

toolchain go1.22.3

require (
github.com/Microsoft/go-winio v0.6.1
github.com/go-ole/go-ole v1.3.0
github.com/google/go-cmp v0.6.0
github.com/iancoleman/strcase v0.3.0
github.com/kubernetes-csi/csi-proxy/client v0.0.0-00010101000000-000000000000
github.com/microsoft/wmi v0.23.0
github.com/pkg/errors v0.9.1
github.com/sergi/go-diff v1.3.1
github.com/spf13/pflag v1.0.5
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down Expand Up @@ -50,6 +52,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mauriciopoppe/gengo v0.0.0-20210525224835-9c78f58f3486 h1:+l047vEi0SyAzdVToIaAcfoY5DwwGW+OyqTdH/P3TTg=
github.com/mauriciopoppe/gengo v0.0.0-20210525224835-9c78f58f3486/go.mod h1:xXv3T4UXTLta31wMhVezwVkc26OLei4hMbLeBJbPmxc=
github.com/microsoft/wmi v0.23.0 h1:EbgjakKBOfb4QaTJNiGkfKrb2RWv7wpyicI2g3DHWkw=
github.com/microsoft/wmi v0.23.0/go.mod h1:PNc5VFG7cpB7VOb3ILZNuWMWsqFfYLPyzpoiFkA6fAQ=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down Expand Up @@ -85,10 +89,12 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
52 changes: 52 additions & 0 deletions pkg/cim/disk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package cim

import (
"fmt"
"strconv"

"github.com/microsoft/wmi/pkg/base/query"

Check failure on line 7 in pkg/cim/disk.go

View workflow job for this annotation

GitHub Actions / integration_tests (1.20, windows-latest)

cannot find module providing package github.com/microsoft/wmi/pkg/base/query: import lookup disabled by -mod=vendor
"github.com/microsoft/wmi/server2019/root/microsoft/windows/storage"

Check failure on line 8 in pkg/cim/disk.go

View workflow job for this annotation

GitHub Actions / integration_tests (1.20, windows-latest)

cannot find module providing package github.com/microsoft/wmi/server2019/root/microsoft/windows/storage: import lookup disabled by -mod=vendor
)

const (
PartitionStyleUnknown = 0
PartitionStyleGPT = 2

GPTPartitionTypeBasicData = "{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}"
GPTPartitionTypeMicrosoftReserved = "{e3c9e316-0b5c-4db8-817d-f92df00215ae}"
)

func QueryDiskByNumber(diskNumber uint32, selectorList []string) (*storage.MSFT_Disk, error) {
diskQuery := query.NewWmiQueryWithSelectList("MSFT_Disk", selectorList, "Number", strconv.Itoa(int(diskNumber)))
instances, err := QueryInstances(WMINamespaceStorage, diskQuery)
if err != nil {
return nil, err
}

disk, err := storage.NewMSFT_DiskEx1(instances[0])
if err != nil {
return nil, fmt.Errorf("failed to query disk %d. error: %v", diskNumber, err)
}

return disk, nil
}

func ListDisks(selectorList []string) ([]*storage.MSFT_Disk, error) {
diskQuery := query.NewWmiQueryWithSelectList("MSFT_Disk", selectorList)
instances, err := QueryInstances(WMINamespaceStorage, diskQuery)
if IgnoreNotFound(err) != nil {
return nil, err
}

var disks []*storage.MSFT_Disk
for _, instance := range instances {
disk, err := storage.NewMSFT_DiskEx1(instance)
if err != nil {
return nil, fmt.Errorf("failed to query disk %v. error: %v", instance, err)
}

disks = append(disks, disk)
}

return disks, nil
}
249 changes: 249 additions & 0 deletions pkg/cim/iscsi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
package cim

import (
"fmt"
"github.com/microsoft/wmi/pkg/base/query"
cim "github.com/microsoft/wmi/pkg/wmiinstance"

Check failure on line 6 in pkg/cim/iscsi.go

View workflow job for this annotation

GitHub Actions / integration_tests (1.20, windows-latest)

cannot find module providing package github.com/microsoft/wmi/pkg/wmiinstance: import lookup disabled by -mod=vendor
"github.com/microsoft/wmi/server2019/root/microsoft/windows/storage"
"strconv"
)

func ListISCSITargetPortals(selectorList []string) ([]*storage.MSFT_iSCSITargetPortal, error) {
q := query.NewWmiQueryWithSelectList("MSFT_IscsiTargetPortal", selectorList)
instances, err := QueryInstances(WMINamespaceStorage, q)
if IgnoreNotFound(err) != nil {
return nil, err
}

var targetPortals []*storage.MSFT_iSCSITargetPortal
for _, instance := range instances {
portal, err := storage.NewMSFT_iSCSITargetPortalEx1(instance)
if err != nil {
return nil, fmt.Errorf("failed to query iSCSI target portal %v. error: %v", instance, err)
}

targetPortals = append(targetPortals, portal)
}

return targetPortals, nil
}

func QueryISCSITargetPortal(address string, port uint32, selectorList []string) (*storage.MSFT_iSCSITargetPortal, error) {
portalQuery := query.NewWmiQueryWithSelectList(
"MSFT_iSCSITargetPortal", selectorList,
"TargetPortalAddress", address,
"TargetPortalPortNumber", strconv.Itoa(int(port)))
instances, err := QueryInstances(WMINamespaceStorage, portalQuery)
if err != nil {
return nil, err
}

targetPortal, err := storage.NewMSFT_iSCSITargetPortalEx1(instances[0])
if err != nil {
return nil, fmt.Errorf("failed to query iSCSI target portal at (%s:%d). error: %v", address, port, err)
}

return targetPortal, nil
}

func NewISCSITargetPortal(targetPortalAddress string,
targetPortalPortNumber uint32,
initiatorInstanceName *string,
initiatorPortalAddress *string,
isHeaderDigest *bool,
isDataDigest *bool) (*storage.MSFT_iSCSITargetPortal, error) {
params := map[string]interface{}{
"TargetPortalAddress": targetPortalAddress,
"TargetPortalPortNumber": targetPortalPortNumber,
}
if initiatorInstanceName != nil {
params["InitiatorInstanceName"] = *initiatorInstanceName
}
if initiatorPortalAddress != nil {
params["InitiatorPortalAddress"] = *initiatorPortalAddress
}
if isHeaderDigest != nil {
params["IsHeaderDigest"] = *isHeaderDigest
}
if isDataDigest != nil {
params["IsDataDigest"] = *isDataDigest
}
result, _, err := InvokeCimMethod(WMINamespaceStorage, "MSFT_iSCSITargetPortal", "New", params)
if err != nil {
return nil, fmt.Errorf("failed to create iSCSI target portal with %v. result: %d, error: %v", params, result, err)
}

return QueryISCSITargetPortal(targetPortalAddress, targetPortalPortNumber, nil)
}

var (
mappingISCSIiTargetIndexer = mappingObjectRefIndexer("iSCSITarget", "MSFT_iSCSITarget", "NodeAddress")
mappingISCSITargetPortalIndexer = mappingObjectRefIndexer("iSCSITargetPortal", "MSFT_iSCSITargetPortal", "TargetPortalAddress")
mappingISCSIConnectionIndexer = mappingObjectRefIndexer("iSCSIConnection", "MSFT_iSCSIConnection", "ConnectionIdentifier")
mappingISCSISessionIndexer = mappingObjectRefIndexer("iSCSISession", "MSFT_iSCSISession", "SessionIdentifier")

iscsiTargetIndexer = stringPropertyIndexer("NodeAddress")
iscsiTargetPortalIndexer = stringPropertyIndexer("TargetPortalAddress")
iscsiConnectionIndexer = stringPropertyIndexer("ConnectionIdentifier")
iscsiSessionIndexer = stringPropertyIndexer("SessionIdentifier")
)

func ListISCSITargetToISCSITargetPortalMapping() (map[string]string, error) {
return ListWMIInstanceMappings(WMINamespaceStorage, "MSFT_iSCSITargetToiSCSITargetPortal", nil, mappingISCSIiTargetIndexer, mappingISCSITargetPortalIndexer)
}

func ListISCSIConnectionToISCSITargetMapping() (map[string]string, error) {
return ListWMIInstanceMappings(WMINamespaceStorage, "MSFT_iSCSITargetToiSCSIConnection", nil, mappingISCSIConnectionIndexer, mappingISCSIiTargetIndexer)
}

func ListISCSISessionToISCSITargetMapping() (map[string]string, error) {
return ListWMIInstanceMappings(WMINamespaceStorage, "MSFT_iSCSITargetToiSCSISession", nil, mappingISCSISessionIndexer, mappingISCSIiTargetIndexer)
}

func ListDiskToISCSIConnectionMapping() (map[string]string, error) {
return ListWMIInstanceMappings(WMINamespaceStorage, "MSFT_iSCSIConnectionToDisk", nil, mappingObjectRefIndexer("Disk", "MSFT_Disk", "ObjectId"), mappingISCSIConnectionIndexer)
}

func ListISCSITargetByTargetPortalWithFilters(targetSelectorList []string, portals []*storage.MSFT_iSCSITargetPortal, filters ...*query.WmiQueryFilter) ([]*storage.MSFT_iSCSITarget, error) {
targetQuery := query.NewWmiQueryWithSelectList("MSFT_iSCSITarget", targetSelectorList)
targetQuery.Filters = append(targetQuery.Filters, filters...)
instances, err := QueryInstances(WMINamespaceStorage, targetQuery)
if err != nil {
return nil, err
}

var portalInstances []*cim.WmiInstance
for _, portal := range portals {
portalInstances = append(portalInstances, portal.WmiInstance)
}

targetToTargetPortalMapping, err := ListISCSITargetToISCSITargetPortalMapping()
if err != nil {
return nil, err
}

targetInstances, err := FindInstancesByMapping(instances, iscsiTargetIndexer, portalInstances, iscsiTargetPortalIndexer, targetToTargetPortalMapping)
if err != nil {
return nil, err
}

var targets []*storage.MSFT_iSCSITarget
for _, instance := range targetInstances {
target, err := storage.NewMSFT_iSCSITargetEx1(instance)
if err != nil {
return nil, fmt.Errorf("failed to query iSCSI target %v. %v", instance, err)
}

targets = append(targets, target)
}

return targets, nil
}

func QueryISCSITarget(address string, port uint32, nodeAddress string, selectorList []string) (*storage.MSFT_iSCSITarget, error) {
portal, err := QueryISCSITargetPortal(address, port, nil)
if err != nil {
return nil, err
}

targets, err := ListISCSITargetByTargetPortalWithFilters(selectorList, []*storage.MSFT_iSCSITargetPortal{portal},
query.NewWmiQueryFilter("NodeAddress", nodeAddress, query.Equals))
if err != nil {
return nil, err
}

return targets[0], nil
}

func QueryISCSISessionByTarget(target *storage.MSFT_iSCSITarget, selectorList []string) (*storage.MSFT_iSCSISession, error) {
sessionQuery := query.NewWmiQueryWithSelectList("MSFT_iSCSISession", selectorList)
sessionInstances, err := QueryInstances(WMINamespaceStorage, sessionQuery)
if err != nil {
return nil, err
}

targetToTargetSessionMapping, err := ListISCSISessionToISCSITargetMapping()
if err != nil {
return nil, err
}

filtered, err := FindInstancesByMapping(sessionInstances, iscsiSessionIndexer, []*cim.WmiInstance{target.WmiInstance}, iscsiTargetIndexer, targetToTargetSessionMapping)
if err != nil {
return nil, err
}

session, err := storage.NewMSFT_iSCSISessionEx1(filtered[0])
return session, err
}

func ListDisksByTarget(target *storage.MSFT_iSCSITarget, selectorList []string) ([]*storage.MSFT_Disk, error) {
// list connections to the given iSCSI target
connectionQuery := query.NewWmiQueryWithSelectList("MSFT_iSCSIConnection", selectorList)
connectionInstances, err := QueryInstances(WMINamespaceStorage, connectionQuery)
if err != nil {
return nil, err
}

connectionToTargetMapping, err := ListISCSIConnectionToISCSITargetMapping()
if err != nil {
return nil, err
}

connectionsToTarget, err := FindInstancesByMapping(connectionInstances, iscsiConnectionIndexer, []*cim.WmiInstance{target.WmiInstance}, iscsiTargetIndexer, connectionToTargetMapping)
if err != nil {
return nil, err
}

disks, err := ListDisks(selectorList)
if err != nil {
return nil, err
}

var diskInstances []*cim.WmiInstance
for _, disk := range disks {
diskInstances = append(diskInstances, disk.WmiInstance)
}

diskToConnectionMapping, err := ListDiskToISCSIConnectionMapping()
if err != nil {
return nil, err
}

filtered, err := FindInstancesByMapping(diskInstances, objectIDPropertyIndexer, connectionsToTarget, iscsiConnectionIndexer, diskToConnectionMapping)
if err != nil {
return nil, err
}

var filteredDisks []*storage.MSFT_Disk
for _, instance := range filtered {
disk, err := storage.NewMSFT_DiskEx1(instance)
if err != nil {
return nil, fmt.Errorf("failed to query disk %v. error: %v", disk, err)
}

filteredDisks = append(filteredDisks, disk)
}
return filteredDisks, err
}

func ConnectISCSITarget(portalAddress string, portalPortNumber uint32, nodeAddress string, authType string, chapUsername *string, chapSecret *string) (int, map[string]interface{}, error) {
inParams := map[string]interface{}{
"NodeAddress": nodeAddress,
"TargetPortalAddress": portalAddress,
"TargetPortalPortNumber": int(portalPortNumber),
"AuthenticationType": authType,
}
// InitiatorPortalAddress
// IsDataDigest
// IsHeaderDigest
// ReportToPnP
if chapUsername != nil {
inParams["ChapUsername"] = *chapUsername
}
if chapSecret != nil {
inParams["ChapSecret"] = *chapSecret
}

result, outParams, err := InvokeCimMethod(WMINamespaceStorage, "MSFT_iSCSITarget", "Connect", inParams)
return result, outParams, err
}
Loading

0 comments on commit 40de367

Please sign in to comment.