Skip to content

Commit

Permalink
✨ Add distributed virtual switches and portgroups
Browse files Browse the repository at this point in the history
This adds these to the vShere datacenter

Signed-off-by: Christian Zunker <[email protected]>
  • Loading branch information
czunker committed Nov 5, 2024
1 parent 8e42171 commit d5b3444
Show file tree
Hide file tree
Showing 7 changed files with 374 additions and 2 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ require (
github.com/spdx/tools-golang v0.5.5
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/spf13/pflag v1.0.6-0.20201009195203-85dd5c8bc61c
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
github.com/toravir/csd v0.0.0-20200911003203-13ae77ad849c
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -862,8 +862,9 @@ github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6-0.20201009195203-85dd5c8bc61c h1:zqmyTlQyufRC65JnImJ6H1Sf7BDj8bG31EV919NVEQc=
github.com/spf13/pflag v1.0.6-0.20201009195203-85dd5c8bc61c/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
Expand Down
87 changes: 87 additions & 0 deletions providers/vsphere/resources/datacenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package resources

import (
"context"
"fmt"

"github.com/vmware/govmomi/object"
Expand Down Expand Up @@ -178,3 +179,89 @@ func (v *mqlVsphereDatacenter) vms() ([]interface{}, error) {

return mqlVms, nil
}

func (v *mqlVsphereDatacenter) distributedSwitches() ([]interface{}, error) {
conn := v.MqlRuntime.Connection.(*connection.VsphereConnection)
client := getClientInstance(conn)

if v.InventoryPath.Error != nil {
return nil, v.InventoryPath.Error
}
path := v.InventoryPath.Data
if path == "" {
path = "/"
}

vswitches, err := client.GetDistributedVirtualSwitches(context.Background(), path)
if err != nil {
return nil, err
}

mqlVswitches := make([]interface{}, len(vswitches))
for i, s := range vswitches {

config, err := client.GetDistributedVirtualSwitchConfig(context.Background(), s)
if err != nil {
return nil, err
}
configMap, err := resourceclient.DistributedVirtualSwitchConfig(config)
if err != nil {
return nil, err
}

mqlVswitch, err := CreateResource(v.MqlRuntime, "vsphere.vswitch.dvs", map[string]*llx.RawData{
"name": llx.StringData(s.Name()),
"properties": llx.DictData(configMap),
})
if err != nil {
return nil, err
}

// store host inventory path, so that sub resources can use that to quickly query more
r := mqlVswitch.(*mqlVsphereVswitchDvs)
r.hostInventoryPath = s.InventoryPath

mqlVswitches[i] = mqlVswitch
}

return mqlVswitches, nil
}

func (v *mqlVsphereDatacenter) distributedPortgroups() ([]interface{}, error) {
if v.InventoryPath.Error != nil {
return nil, v.InventoryPath.Error
}
path := v.InventoryPath.Data
conn := v.MqlRuntime.Connection.(*connection.VsphereConnection)
client := resourceclient.New(conn.Client())

distPGs, err := client.GetDistributedVirtualPortgroups(context.Background(), path)
if err != nil {
return nil, err
}

mqlPGs := []interface{}{}
for _, distPG := range distPGs {
config, err := client.GetDistributedVirtualPortgroupConfig(context.Background(), distPG)
if err != nil {
return nil, err
}

configMap, err := resourceclient.DistributedVirtualPortgroupConfig(config)
if err != nil {
return nil, err
}

mqlDistPG, err := CreateResource(v.MqlRuntime, "vsphere.vswitch.portgroup", map[string]*llx.RawData{
"name": llx.StringData(distPG.Name()),
"properties": llx.DictData(configMap),
})
if err != nil {
return nil, err
}

mqlPGs = append(mqlPGs, mqlDistPG)
}

return mqlPGs, nil
}
137 changes: 137 additions & 0 deletions providers/vsphere/resources/resourceclient/network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package resourceclient

import (
"context"
"errors"
"strings"

"github.com/rs/zerolog/log"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
)

func (c *Client) GetDistributedVirtualSwitches(ctx context.Context, path string) ([]*object.DistributedVirtualSwitch, error) {
finder := find.NewFinder(c.Client.Client, true)
mos, err := finder.ManagedObjectListChildren(ctx, path)
if err != nil {
return nil, err
}
if len(mos) == 0 {
return nil, nil
}

var dvSwitches []*object.DistributedVirtualSwitch
for _, item := range mos {
if !strings.HasSuffix(item.Path, "/network") {
continue
}
log.Debug().Str("object", item.String()).Msg("???")
ref := item.Object.Reference()
log.Debug().Str("ref", ref.Type).Msg("???")
networkMos, err := finder.ManagedObjectListChildren(ctx, item.Path)
if err != nil {
return nil, err
}
for _, networkMo := range networkMos {
log.Debug().Str("networkMo", networkMo.String()).Msg("???")
if networkMo.Object.Reference().Type == "DistributedVirtualSwitch" || networkMo.Object.Reference().Type == "VmwareDistributedVirtualSwitch" {
dvpg, err := finder.Network(ctx, networkMo.Path)
if err != nil {
return nil, err
}
casted, ok := dvpg.(*object.DistributedVirtualSwitch)
if !ok {
return nil, errors.New("not a DistributedVirtualSwitch reference")
}
dvSwitches = append(dvSwitches, casted)
}
}
}

return dvSwitches, nil
}

func (c *Client) GetDistributedVirtualSwitchConfig(ctx context.Context, obj *object.DistributedVirtualSwitch) (*mo.DistributedVirtualSwitch, error) {
var moDvSwitch mo.DistributedVirtualSwitch
err := obj.Properties(ctx, obj.Reference(), nil, &moDvSwitch)
if err != nil {
return nil, err
}

return &moDvSwitch, nil
}

func DistributedVirtualSwitchConfig(dvSwitch *mo.DistributedVirtualSwitch) (map[string]interface{}, error) {
return PropertiesToDict(dvSwitch)
}

func (c *Client) GetDistributedVirtualPortgroups(ctx context.Context, path string) ([]*object.DistributedVirtualPortgroup, error) {
finder := find.NewFinder(c.Client.Client, true)
pathParts := strings.Split(path, "/")
if len(pathParts) == 0 {
return nil, nil
}
dcPath := "/" + pathParts[1]
dc, err := c.Datacenter(dcPath)
if err != nil {
return nil, err
}
finder.SetDatacenter(dc)

mos, err := finder.ManagedObjectListChildren(ctx, dcPath)
if err != nil {
return nil, err
}
if len(mos) == 0 {
return nil, nil
}

var pgs []*object.DistributedVirtualPortgroup
for _, item := range mos {
if !strings.HasSuffix(item.Path, "/network") {
continue
}
log.Debug().Str("object", item.String()).Msg("???")
ref := item.Object.Reference()
log.Debug().Str("ref", ref.Type).Msg("???")
networkMos, err := finder.ManagedObjectListChildren(ctx, item.Path)
if err != nil {
return nil, err
}
for _, networkMo := range networkMos {
log.Debug().Str("networkMo", networkMo.String()).Msg("???")
if networkMo.Object.Reference().Type == "DistributedVirtualPortgroup" {
dvpg, err := finder.Network(ctx, networkMo.Path)
if err != nil {
return nil, err
}
casted, ok := dvpg.(*object.DistributedVirtualPortgroup)
if !ok {
return nil, errors.New("not a DistributedVirtualPortgroup reference")
}

pgs = append(pgs, casted)
}
}
}

return pgs, nil
}

func (c *Client) GetDistributedVirtualPortgroupConfig(ctx context.Context, obj *object.DistributedVirtualPortgroup) (*mo.DistributedVirtualPortgroup, error) {
var moDvpg mo.DistributedVirtualPortgroup
err := obj.Properties(ctx, obj.Reference(), nil, &moDvpg)
if err != nil {
return nil, err
}

return &moDvpg, nil
}

func DistributedVirtualPortgroupConfig(dvpg *mo.DistributedVirtualPortgroup) (map[string]interface{}, error) {
return PropertiesToDict(dvpg)
}
12 changes: 12 additions & 0 deletions providers/vsphere/resources/vsphere.lr
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ private vsphere.datacenter @defaults("moid name") {
vms() []vsphere.vm
// Clusters in the datacenter
clusters() []vsphere.cluster
// Distributed virtual switches
distributedSwitches() []vsphere.vswitch.dvs
// List of distributed virtual port groups
distributedPortgroups() []vsphere.vswitch.portgroup

Check warning on line 138 in providers/vsphere/resources/vsphere.lr

View workflow job for this annotation

GitHub Actions / Run spell check

`portgroup` is not a recognized word. (unrecognized-spelling)
}

// vSphere cluster resource
Expand Down Expand Up @@ -224,6 +228,14 @@ private vsphere.vswitch.dvs @defaults("name") {
uplinks() []vsphere.vmnic
}

// vSphere distributed virtual port group
private vsphere.vswitch.portgroup @defaults("name") {

Check warning on line 232 in providers/vsphere/resources/vsphere.lr

View workflow job for this annotation

GitHub Actions / Run spell check

`portgroup` is not a recognized word. (unrecognized-spelling)
// Port group name
name string
// Port group properties
properties dict
}

// vSphere ESXi physical network interface resource
private vsphere.vmnic @defaults("name") {
// NIC name
Expand Down
Loading

0 comments on commit d5b3444

Please sign in to comment.