Skip to content

Commit

Permalink
feat: add volume group API endpoint interaction (#94)
Browse files Browse the repository at this point in the history
Signed-off-by: Moto Ishizawa <[email protected]>
  • Loading branch information
summerwind authored Nov 11, 2024
1 parent 708abda commit d1b27f3
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 13 deletions.
15 changes: 15 additions & 0 deletions api/volume_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package api

import (
"github.com/canonical/gomaasclient/entity"
)

// VolumeGroup is an interface providing API behaviour for
// volume groups
type VolumeGroup interface {
Get(systemID string, id int) (*entity.VolumeGroup, error)
Update(systemID string, id int, params *entity.VolumeGroupUpdateParams) (*entity.VolumeGroup, error)
Delete(systemID string, id int) error
CreateLogicalVolume(systemID string, id int, params *entity.LogicalVolumeParams) (*entity.BlockDevice, error)
DeleteLogicalVolume(ssytemID string, id int, logicalVolumeID int) error
}
12 changes: 12 additions & 0 deletions api/volume_groups.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package api

import (
"github.com/canonical/gomaasclient/entity"
)

// VolumeGroups is an interface for listing and creating
// VolumeGroup records
type VolumeGroups interface {
Get(systemID string) ([]entity.VolumeGroup, error)
Create(systemID string, params *entity.VolumeGroupCreateParams) (*entity.VolumeGroup, error)
}
4 changes: 4 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ func constructClient(apiClient *APIClient) *Client {
RackControllers: &RackControllers{APIClient: *apiClient},
NodeScript: &NodeScript{APIClient: *apiClient},
NodeScripts: &NodeScripts{APIClient: *apiClient},
VolumeGroup: &VolumeGroup{APIClient: *apiClient},
VolumeGroups: &VolumeGroups{APIClient: *apiClient},
}

return &client
Expand Down Expand Up @@ -191,6 +193,8 @@ type Client struct {
RackControllers api.RackControllers
NodeScript api.NodeScript
NodeScripts api.NodeScripts
VolumeGroup api.VolumeGroup
VolumeGroups api.VolumeGroups
}

// GetAPIClient returns a MAAS API client.
Expand Down
77 changes: 77 additions & 0 deletions client/volume_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package client

import (
"encoding/json"
"fmt"
"net/url"
"strconv"

"github.com/canonical/gomaasclient/entity"
"github.com/google/go-querystring/query"
)

// VolumeGroup implements the api.VolumeGroup interface
type VolumeGroup struct {
APIClient APIClient
}

func (v *VolumeGroup) client(systemID string, id int) APIClient {
return v.APIClient.GetSubObject("nodes").GetSubObject(systemID).GetSubObject("volume-groups").GetSubObject(fmt.Sprintf("%v", id))
}

// Get fetches a given VolumeGroup based on the given Node's system_id and VolumeGroup's ID
func (v *VolumeGroup) Get(systemID string, id int) (*entity.VolumeGroup, error) {
volumeGroup := new(entity.VolumeGroup)
err := v.client(systemID, id).Get("", url.Values{}, func(data []byte) error {
return json.Unmarshal(data, volumeGroup)
})

return volumeGroup, err
}

// Update updates a given VolumeGroup
func (v *VolumeGroup) Update(systemID string, id int, params *entity.VolumeGroupUpdateParams) (*entity.VolumeGroup, error) {
qsp, err := query.Values(params)
if err != nil {
return nil, err
}

volumeGroup := new(entity.VolumeGroup)
err = v.client(systemID, id).Put(qsp, func(data []byte) error {
return json.Unmarshal(data, volumeGroup)
})

return volumeGroup, err
}

// Delete deletes a given VolumeGroup
func (v *VolumeGroup) Delete(systemID string, id int) error {
return v.client(systemID, id).Delete()
}

// CreateLogicalVolume creates a new LogicalVolume for a given system_id and VolumeGroup's ID
func (v *VolumeGroup) CreateLogicalVolume(systemID string, id int, params *entity.LogicalVolumeParams) (*entity.BlockDevice, error) {
qsp, err := query.Values(params)
if err != nil {
return nil, err
}

blockDevice := new(entity.BlockDevice)
err = v.client(systemID, id).Post("create_logical_volume", qsp, func(data []byte) error {
return json.Unmarshal(data, blockDevice)
})

return blockDevice, err
}

// DeleteLogicalVolume deletes a given LogicalVolume
func (v *VolumeGroup) DeleteLogicalVolume(systemID string, id int, lvID int) error {
qsp := url.Values{}
qsp.Set("id", strconv.Itoa(lvID))

err := v.client(systemID, id).Post("delete_logical_volume", qsp, func(data []byte) error {
return nil
})

return err
}
44 changes: 44 additions & 0 deletions client/volume_groups.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//nolint:dupl // disable dupl check on client for now
package client

import (
"encoding/json"
"net/url"

"github.com/canonical/gomaasclient/entity"
"github.com/google/go-querystring/query"
)

// VolumeGroups implements the api.VolumeGroups interface
type VolumeGroups struct {
APIClient APIClient
}

func (v *VolumeGroups) client(systemID string) APIClient {
return v.APIClient.GetSubObject("nodes").GetSubObject(systemID).GetSubObject("volume-groups")
}

// Get fetches a list of VolumeGroups for a given system_id
func (v *VolumeGroups) Get(systemID string) ([]entity.VolumeGroup, error) {
volumeGroups := make([]entity.VolumeGroup, 0)
err := v.client(systemID).Get("", url.Values{}, func(data []byte) error {
return json.Unmarshal(data, &volumeGroups)
})

return volumeGroups, err
}

// Create creates a new VolumeGroup for a given system_id
func (v *VolumeGroups) Create(systemID string, params *entity.VolumeGroupCreateParams) (*entity.VolumeGroup, error) {
qsp, err := query.Values(params)
if err != nil {
return nil, err
}

volumeGroup := new(entity.VolumeGroup)
err = v.client(systemID).Post("", qsp, func(data []byte) error {
return json.Unmarshal(data, volumeGroup)
})

return volumeGroup, err
}
56 changes: 43 additions & 13 deletions entity/volume_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,47 @@ package entity

// VolumeGroup represents the MAAS VolumeGroup endpoint.
type VolumeGroup struct {
LogicalVolumes interface{} `json:"logical_volumes,omitempty"`
Devices interface{} `json:"devices,omitempty"`
HumanSize string `json:"human_size,omitempty"`
UUID string `json:"uuid,omitempty"`
HumanAvailableSize string `json:"human_available_size,omitempty"`
SystemID string `json:"system_id,omitempty"`
ResourceURI string `json:"resource_uri,omitempty"`
HumanUsedSize string `json:"human_used_size,omitempty"`
Name string `json:"name,omitempty"`
Size int64 `json:"size,omitempty"`
UsedSize int64 `json:"used_size,omitempty"`
AvailableSize int64 `json:"available_size,omitempty"`
ID int `json:"id,omitempty"`
Devices interface{} `json:"devices,omitempty"`
ResourceURI string `json:"resource_uri,omitempty"`
HumanSize string `json:"human_size,omitempty"`
UUID string `json:"uuid,omitempty"`
HumanAvailableSize string `json:"human_available_size,omitempty"`
SystemID string `json:"system_id,omitempty"`
HumanUsedSize string `json:"human_used_size,omitempty"`
Name string `json:"name,omitempty"`
LogicalVolumes []VirtualBlockDevice `json:"logical_volumes,omitempty"`
Size int64 `json:"size,omitempty"`
UsedSize int64 `json:"used_size,omitempty"`
AvailableSize int64 `json:"available_size,omitempty"`
ID int `json:"id,omitempty"`
}

// VolumeGroupCreateParams enumerates the parameters for the volume group create operation.
type VolumeGroupCreateParams struct {
Name string `url:"name,omitempty"`
UUID string `url:"uuid,omitempty"`
BlockDevices []string `url:"block_devices,omitempty"`
Partitions []string `url:"partitions,omitempty"`
}

// VolumeGroupUpdateParams enumerates the parameters for the volume group update operation.
type VolumeGroupUpdateParams struct {
Name string `url:"name,omitempty"`
UUID string `url:"uuid,omitempty"`
AddBlockDevices []string `url:"add_block_devices,omitempty"`
RemoveBlockDevices []string `url:"remove_block_devices,omitempty"`
AddPartitions []string `url:"add_partitions,omitempty"`
RemovePartitions []string `url:"remove_partitions,omitempty"`
}

// LogicalVolumeParams enumerates the parameters for the logical volume operation.
type LogicalVolumeParams struct {
Name string `url:"name,omitempty"`
UUID string `url:"uuid,omitempty"`
Size int64 `json:"size,omitempty"`
}

// VirtualBlockDevice represents a logical volume and extends BlockDevice.
type VirtualBlockDevice struct {
BlockDevice
}
21 changes: 21 additions & 0 deletions entity/volume_group_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package entity

import (
"testing"

"github.com/canonical/gomaasclient/test/helper"
)

func TestVolumeGroup(t *testing.T) {
volumeGroup := new(VolumeGroup)
volumeGroups := new([]VolumeGroup)

// Unmarshal sample data into the types
if err := helper.TestdataFromJSON("maas/volume_group.json", volumeGroup); err != nil {
t.Fatal(err)
}

if err := helper.TestdataFromJSON("maas/volume_groups.json", volumeGroups); err != nil {
t.Fatal(err)
}
}
36 changes: 36 additions & 0 deletions test/testdata/maas/volume_group.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"used_size": 0,
"uuid": "aa69c453-b713-40fb-8149-c7708619a895",
"name": "vg0",
"human_available_size": "4.8 GB",
"devices": [
{
"uuid": "1d18f4fc-656a-45bf-a831-cb6176d72969",
"size": 4836032512,
"bootable": false,
"tags": [],
"device_id": 3,
"system_id": "6hntar",
"type": "partition",
"id": 2,
"filesystem": {
"fstype": "lvm-pv",
"label": null,
"uuid": "da76be2f-c18e-4bf3-9e16-8aeed6dc42d9",
"mount_point": null,
"mount_options": null
},
"used_for": "LVM volume for vg0",
"path": "/dev/disk/by-dname/sda-part2",
"resource_uri": "/MAAS/api/2.0/nodes/6hntar/blockdevices/3/partition/2"
}
],
"human_used_size": "0 bytes",
"size": 4831838208,
"system_id": "6hntar",
"available_size": 4831838208,
"id": 1,
"human_size": "4.8 GB",
"logical_volumes": [],
"resource_uri": "/MAAS/api/2.0/nodes/6hntar/volume-group/1/"
}
38 changes: 38 additions & 0 deletions test/testdata/maas/volume_groups.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[
{
"used_size": 0,
"uuid": "aa69c453-b713-40fb-8149-c7708619a895",
"name": "vg0",
"human_available_size": "4.8 GB",
"devices": [
{
"uuid": "1d18f4fc-656a-45bf-a831-cb6176d72969",
"size": 4836032512,
"bootable": false,
"tags": [],
"device_id": 3,
"system_id": "6hntar",
"type": "partition",
"id": 2,
"filesystem": {
"fstype": "lvm-pv",
"label": null,
"uuid": "da76be2f-c18e-4bf3-9e16-8aeed6dc42d9",
"mount_point": null,
"mount_options": null
},
"used_for": "LVM volume for vg0",
"path": "/dev/disk/by-dname/sda-part2",
"resource_uri": "/MAAS/api/2.0/nodes/6hntar/blockdevices/3/partition/2"
}
],
"human_used_size": "0 bytes",
"size": 4831838208,
"system_id": "6hntar",
"available_size": 4831838208,
"id": 1,
"human_size": "4.8 GB",
"logical_volumes": [],
"resource_uri": "/MAAS/api/2.0/nodes/6hntar/volume-group/1/"
}
]

0 comments on commit d1b27f3

Please sign in to comment.