Skip to content

Commit

Permalink
Merge pull request #139 from madhanrm/failoverCluster
Browse files Browse the repository at this point in the history
Add failover cluster wrapper
  • Loading branch information
madhanrm authored Nov 8, 2024
2 parents c346085 + 1ffa531 commit cfb76bb
Show file tree
Hide file tree
Showing 23 changed files with 1,191 additions and 0 deletions.
58 changes: 58 additions & 0 deletions pkg/cluster/compute/affinityrule/affinityrule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package affinityrule

import (
"github.com/microsoft/wmi/pkg/base/host"
"github.com/microsoft/wmi/pkg/base/instance"
"github.com/microsoft/wmi/pkg/base/query"
"github.com/microsoft/wmi/pkg/constant"
wmi "github.com/microsoft/wmi/pkg/wmiinstance"
fc "github.com/microsoft/wmi/server2019/root/mscluster"
)

type AffinityRule struct {
*fc.MSCluster_AffinityRule
}

// NewAffinityRule
func NewAffinityRule(instance *wmi.WmiInstance) (*AffinityRule, error) {
wmiafRule, err := fc.NewMSCluster_AffinityRuleEx1(instance)
if err != nil {
return nil, err
}
return &AffinityRule{wmiafRule}, nil
}

// GetAffinityRule gets an existing virtual machine
// Make sure to call Close once done using this instance
func GetAffinityRules(whost *host.WmiHost) (caffinityRulecollection AffinityRuleCollection, err error) {
query := query.NewWmiQuery("MSCluster_AffinityRule")
instances, err := instance.GetWmiInstancesFromHost(whost, string(constant.FailoverCluster), query)
if err != nil {
return
}

defer func() {
if err != nil {
instances.Close()
}
}()

caffinityRulecollection, err = NewAffinityRuleCollection(instances)
return
}

// GetAffinityRule gets an existing virtual machine
// Make sure to call Close once done using this instance
func GetAffinityRule(whost *host.WmiHost, affinityRuleName string) (caffinityRule *AffinityRule, err error) {
creds := whost.GetCredential()
query := query.NewWmiQuery("MSCluster_AffinityRule", "Name", affinityRuleName)
wmiafRule, err := fc.NewMSCluster_AffinityRuleEx6(whost.HostName, string(constant.FailoverCluster), creds.UserName, creds.Password, creds.Domain, query)
if err != nil {
return
}
caffinityRule = &AffinityRule{wmiafRule}
return
}
46 changes: 46 additions & 0 deletions pkg/cluster/compute/affinityrule/affinityrule_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package affinityrule

import (
"github.com/microsoft/wmi/pkg/base/host"
_ "github.com/microsoft/wmi/pkg/base/session"
"testing"
)

var (
whost *host.WmiHost
)

func init() {
whost = host.NewWmiLocalHost()
}

func TestGetAffinityRule(t *testing.T) {
cn, err := GetAffinityRule(whost, "Cloud Agent-CNO")
if err != nil {
t.Fatal("Failed " + err.Error())
return
}
defer cn.Close()
}

func TestGetAffinityRules(t *testing.T) {
nc, err := GetAffinityRules(whost)
if err != nil {
t.Fatal("Failed " + err.Error())
return
}
defer nc.Close()
t.Logf("Nodes returned %d\n", len(nc))

for _, affinityRule := range nc {
affinityRuleName, err := affinityRule.GetPropertyName()
if err != nil {
t.Fatal("Failed " + err.Error())
return
}
t.Logf("NoodeName : %s\n", affinityRuleName)
}
}
33 changes: 33 additions & 0 deletions pkg/cluster/compute/affinityrule/affinityrulecollection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package affinityrule

import (
wmi "github.com/microsoft/wmi/pkg/wmiinstance"
)

type AffinityRuleCollection []*AffinityRule

func NewAffinityRuleCollection(instances []*wmi.WmiInstance) (col AffinityRuleCollection, err error) {
for _, inst := range instances {
na, err1 := NewAffinityRule(inst)
if err1 != nil {
err = err1
return
}
col = append(col, na)
}
return
}

func (instances *AffinityRuleCollection) Close() (err error) {
for _, value := range *instances {
value.Close()
}
return nil
}

func (instances *AffinityRuleCollection) String() string {
return ""
}
48 changes: 48 additions & 0 deletions pkg/cluster/compute/cluster/cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package cluster

import (
"github.com/microsoft/wmi/pkg/base/host"
"github.com/microsoft/wmi/pkg/base/query"
fcconstant "github.com/microsoft/wmi/pkg/cluster/constant"
"github.com/microsoft/wmi/pkg/constant"
wmi "github.com/microsoft/wmi/pkg/wmiinstance"
fc "github.com/microsoft/wmi/server2019/root/mscluster"
)

type Cluster struct {
*fc.MSCluster_Cluster
}

// NewCluster
func NewCluster(instance *wmi.WmiInstance) (*Cluster, error) {
wmicluster, err := fc.NewMSCluster_ClusterEx1(instance)
if err != nil {
return nil, err
}
return &Cluster{wmicluster}, nil
}

// GetCluster gets an existing cluster
// Make sure to call Close once done using this instance
func GetCluster(whost *host.WmiHost) (ccluster *Cluster, err error) {
creds := whost.GetCredential()
query := query.NewWmiQuery("MSCluster_Cluster")
wmicluster, err := fc.NewMSCluster_ClusterEx6(whost.HostName, string(constant.FailoverCluster), creds.UserName, creds.Password, creds.Domain, query)
if err != nil {
return
}
return &Cluster{wmicluster}, nil
}

// IsNodeClusterStateRunning get the cluster health status
func (c *Cluster) IsNodeClusterStateRunning() (status bool) {
state, err := c.InvokeMethodWithReturn("GetNodeClusterState")
if err != nil {
return false
}

return (state == fcconstant.ClusterStateRunning)
}
38 changes: 38 additions & 0 deletions pkg/cluster/compute/cluster/cluster_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package cluster

import (
"github.com/microsoft/wmi/pkg/base/host"
_ "github.com/microsoft/wmi/pkg/base/session"
"testing"
)

var (
whost *host.WmiHost
)

func init() {
whost = host.NewWmiLocalHost()
}

func TestGetCluster(t *testing.T) {
cn, err := GetCluster(whost)
if err != nil {
t.Fatal("Failed " + err.Error())
return
}
defer cn.Close()
}

func TestGetCluster_IsHealthy(t *testing.T) {
cn, err := GetCluster(whost)
if err != nil {
t.Fatal("Failed " + err.Error())
return
}
defer cn.Close()

cn.IsNodeClusterStateRunning()
}
116 changes: 116 additions & 0 deletions pkg/cluster/compute/clusternode/clusternode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package clusternode

import (
"os"

"github.com/microsoft/wmi/pkg/base/host"
"github.com/microsoft/wmi/pkg/base/instance"
"github.com/microsoft/wmi/pkg/base/query"
fcconstant "github.com/microsoft/wmi/pkg/cluster/constant"
"github.com/microsoft/wmi/pkg/constant"
wmi "github.com/microsoft/wmi/pkg/wmiinstance"
fc "github.com/microsoft/wmi/server2019/root/mscluster"

"github.com/microsoft/wmi/pkg/errors"
"reflect"
)

type ClusterNode struct {
*fc.MSCluster_Node
}

// NewClusterNode
func NewClusterNode(instance *wmi.WmiInstance) (*ClusterNode, error) {
wmivm, err := fc.NewMSCluster_NodeEx1(instance)
if err != nil {
return nil, err
}
return &ClusterNode{wmivm}, nil
}

// GetClusterNodes gets an existing virtual machine
// Make sure to call Close once done using this instance
func GetClusterNodes(whost *host.WmiHost) (cnodecollection ClusterNodeCollection, err error) {
query := query.NewWmiQuery("MSCluster_Node")
instances, err := instance.GetWmiInstancesFromHost(whost, string(constant.FailoverCluster), query)
if err != nil {
return
}

defer func() {
if err != nil {
instances.Close()
}
}()

cnodecollection, err = NewClusterNodeCollection(instances)
return
}

// GetClusterNode gets an existing virtual machine
// Make sure to call Close once done using this instance
func GetClusterNode(whost *host.WmiHost, nodeName string) (cnode *ClusterNode, err error) {
creds := whost.GetCredential()
query := query.NewWmiQuery("MSCluster_Node", "Name", nodeName)
wmivm, err := fc.NewMSCluster_NodeEx6(whost.HostName, string(constant.FailoverCluster), creds.UserName, creds.Password, creds.Domain, query)
if err != nil {
return
}
cnode = &ClusterNode{wmivm}
return
}

// GetLocalClusterNode gets an existing virtual machine
// Make sure to call Close once done using this instance
func GetLocalClusterNode(whost *host.WmiHost) (cnode *ClusterNode, err error) {
hostname, err := os.Hostname()
if err != nil {
return
}
return GetClusterNode(whost, hostname)
}

// State gets the value of FaultState for the instance
func (c *ClusterNode) State() (value int32, err error) {
retValue, err := c.GetProperty("State")
if err != nil {
return
}
if retValue == nil {
// Doesn't have any value. Return empty
return
}

value, ok := retValue.(int32)
if !ok {
err = errors.Wrapf(errors.InvalidType, " int32 is Invalid. Expected %s", reflect.TypeOf(retValue))
return
}

return
}

// IsUp get the cluster health status
func (c *ClusterNode) IsUp() (status bool, err error) {
state, err := c.State()
if err != nil {
return
}

status = (state == fcconstant.CLUSTER_NODE_STATE_UP)
return
}

// IsPaused get the cluster health status
func (c *ClusterNode) IsPaused() (status bool, err error) {
state, err := c.State()
if err != nil {
return
}

status = (state == fcconstant.CLUSTER_NODE_STATE_PAUSED)
return
}
Loading

0 comments on commit cfb76bb

Please sign in to comment.