Skip to content

Commit a9d1250

Browse files
committed
feat(storage): add support for SMB/CIFS shares
Signed-off-by: James Neill <[email protected]>
1 parent 57c6090 commit a9d1250

File tree

5 files changed

+215
-2
lines changed

5 files changed

+215
-2
lines changed

fwprovider/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ func (p *proxmoxProvider) Resources(_ context.Context) []func() resource.Resourc
539539
storage.NewLVMThinPoolStorageResource,
540540
storage.NewNFSStorageResource,
541541
storage.NewProxmoxBackupServerStorageResource,
542+
storage.NewCIFSStorageResource,
542543
storage.NewZFSPoolStorageResource,
543544
}
544545
}

fwprovider/storage/model_cifs.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package storage
2+
3+
import (
4+
"context"
5+
6+
"github.com/bpg/terraform-provider-proxmox/proxmox/storage"
7+
proxmox_types "github.com/bpg/terraform-provider-proxmox/proxmox/types"
8+
"github.com/hashicorp/terraform-plugin-framework/types"
9+
)
10+
11+
// CIFSStorageModel maps the Terraform schema for CIFS storage.
12+
type CIFSStorageModel struct {
13+
StorageModelBase
14+
Server types.String `tfsdk:"server"`
15+
Username types.String `tfsdk:"username"`
16+
Password types.String `tfsdk:"password"`
17+
Share types.String `tfsdk:"share"`
18+
Domain types.String `tfsdk:"domain"`
19+
SubDirectory types.String `tfsdk:"subdirectory"`
20+
Preallocation types.String `tfsdk:"preallocation"`
21+
SnapshotsAsVolumeChain types.Bool `tfsdk:"snapshot_as_volume_chain"`
22+
}
23+
24+
func (m *CIFSStorageModel) GetStorageType() types.String {
25+
return types.StringValue("cifs")
26+
}
27+
28+
func (m *CIFSStorageModel) toCreateAPIRequest(ctx context.Context) (interface{}, error) {
29+
request := storage.CIFSStorageCreateRequest{}
30+
request.Type = m.GetStorageType().ValueStringPointer()
31+
32+
if err := m.populateCreateFields(ctx, &request.DataStoreCommonImmutableFields, &request.DataStoreCommonMutableFields); err != nil {
33+
return nil, err
34+
}
35+
36+
request.Server = m.Server.ValueStringPointer()
37+
request.Username = m.Username.ValueStringPointer()
38+
request.Password = m.Password.ValueStringPointer()
39+
request.Share = m.Share.ValueStringPointer()
40+
request.Domain = m.Domain.ValueStringPointer()
41+
request.Subdirectory = m.SubDirectory.ValueStringPointer()
42+
request.Preallocation = m.Preallocation.ValueStringPointer()
43+
request.SnapshotsAsVolumeChain = proxmox_types.CustomBool(m.SnapshotsAsVolumeChain.ValueBool())
44+
45+
return request, nil
46+
}
47+
48+
func (m *CIFSStorageModel) toUpdateAPIRequest(ctx context.Context) (interface{}, error) {
49+
request := storage.CIFSStorageUpdateRequest{}
50+
51+
if err := m.populateUpdateFields(ctx, &request.DataStoreCommonMutableFields); err != nil {
52+
return nil, err
53+
}
54+
55+
request.Preallocation = m.Preallocation.ValueStringPointer()
56+
57+
return request, nil
58+
}
59+
60+
func (m *CIFSStorageModel) fromAPI(ctx context.Context, datastore *storage.DatastoreGetResponseData) error {
61+
if err := m.populateBaseFromAPI(ctx, datastore); err != nil {
62+
return err
63+
}
64+
65+
if datastore.Server != nil {
66+
m.Server = types.StringValue(*datastore.Server)
67+
}
68+
if datastore.Username != nil {
69+
m.Username = types.StringValue(*datastore.Username)
70+
}
71+
if datastore.Share != nil {
72+
m.Share = types.StringValue(*datastore.Share)
73+
}
74+
if datastore.Domain != nil {
75+
m.Domain = types.StringValue(*datastore.Domain)
76+
}
77+
if datastore.SubDirectory != nil {
78+
m.SubDirectory = types.StringValue(*datastore.SubDirectory)
79+
}
80+
if datastore.Preallocation != nil {
81+
m.Preallocation = types.StringValue(*datastore.Preallocation)
82+
}
83+
84+
return nil
85+
}

fwprovider/storage/resource_cifs.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package storage
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-framework/resource"
7+
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
8+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
9+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
10+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
11+
)
12+
13+
// Ensure the implementation satisfies the expected interfaces.
14+
var _ resource.Resource = &smbStorageResource{}
15+
16+
// NewCIFSStorageResource is a helper function to simplify the provider implementation.
17+
func NewCIFSStorageResource() resource.Resource {
18+
return &smbStorageResource{
19+
storageResource: &storageResource[
20+
*CIFSStorageModel,
21+
CIFSStorageModel,
22+
]{
23+
storageType: "smb",
24+
resourceName: "proxmox_virtual_environment_storage_smb",
25+
},
26+
}
27+
}
28+
29+
// smbStorageResource is the resource implementation.
30+
type smbStorageResource struct {
31+
*storageResource[*CIFSStorageModel, CIFSStorageModel]
32+
}
33+
34+
// Metadata returns the resource type name.
35+
func (r *smbStorageResource) Metadata(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) {
36+
resp.TypeName = r.resourceName
37+
}
38+
39+
// Schema defines the schema for the SMB storage resource.
40+
func (r *smbStorageResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
41+
attributes := map[string]schema.Attribute{
42+
"server": schema.StringAttribute{
43+
Description: "The IP address or DNS name of the SMB/CIFS server.",
44+
Required: true,
45+
PlanModifiers: []planmodifier.String{
46+
stringplanmodifier.RequiresReplace(),
47+
},
48+
},
49+
"username": schema.StringAttribute{
50+
Description: "The username for authenticating with the SMB/CIFS server.",
51+
Required: true,
52+
},
53+
"password": schema.StringAttribute{
54+
Description: "The password for authenticating with the SMB/CIFS server.",
55+
Required: true,
56+
Sensitive: true,
57+
},
58+
"share": schema.StringAttribute{
59+
Description: "The name of the SMB/CIFS share.",
60+
Required: true,
61+
PlanModifiers: []planmodifier.String{
62+
stringplanmodifier.RequiresReplace(),
63+
},
64+
},
65+
"domain": schema.StringAttribute{
66+
Description: "The SMB/CIFS domain.",
67+
Optional: true,
68+
},
69+
"subdirectory": schema.StringAttribute{
70+
Description: "A subdirectory to mount within the share.",
71+
Optional: true,
72+
},
73+
"preallocation": schema.StringAttribute{
74+
Description: "The preallocation mode for raw and qcow2 images.",
75+
Optional: true,
76+
},
77+
"snapshot_as_volume_chain": schema.BoolAttribute{
78+
Description: "Enable support for creating snapshots through volume backing-chains.",
79+
Optional: true,
80+
},
81+
"shared": schema.BoolAttribute{
82+
Description: "Whether the storage is shared across all nodes.",
83+
Computed: true,
84+
Default: booldefault.StaticBool(true),
85+
},
86+
}
87+
88+
factory := NewStorageSchemaFactory()
89+
factory.WithAttributes(attributes)
90+
factory.WithDescription("Manages an SMB/CIFS based storage server in Proxmox VE.")
91+
resp.Schema = *factory.Schema
92+
}

proxmox/storage/cifs_types.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package storage
2+
3+
import "github.com/bpg/terraform-provider-proxmox/proxmox/types"
4+
5+
// CIFSStorageMutableFields defines specific options for 'smb'/'cifs' type storage.
6+
type CIFSStorageMutableFields struct {
7+
DataStoreCommonMutableFields
8+
DataStoreWithBackups
9+
Preallocation *string `json:"preallocation,omitempty" url:"preallocation,omitempty"`
10+
}
11+
12+
type CIFSStorageImmutableFields struct {
13+
Server *string `json:"server" url:"server"`
14+
Username *string `json:"username" url:"username"`
15+
Password *string `json:"password" url:"password"`
16+
Share *string `json:"share" url:"share"`
17+
Domain *string `json:"domain,omitempty" url:"domain,omitempty"`
18+
Subdirectory *string `json:"subdir,omitempty" url:"subdir,omitempty"`
19+
SnapshotsAsVolumeChain types.CustomBool `json:"snapshot-as-volume-chain,omitempty" url:"snapshot-as-volume-chain,omitempty"`
20+
}
21+
22+
// CIFSStorageCreateRequest defines the request body for creating a new SMB/CIFS storage.
23+
type CIFSStorageCreateRequest struct {
24+
DataStoreCommonImmutableFields
25+
CIFSStorageMutableFields
26+
CIFSStorageImmutableFields
27+
}
28+
29+
// CIFSStorageUpdateRequest defines the request body for updating an existing SMB/CIFS storage.
30+
type CIFSStorageUpdateRequest struct {
31+
CIFSStorageMutableFields
32+
}

proxmox/storage/storage_types.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,14 @@ type DatastoreGetResponseData struct {
5151
Fingerprint *string `json:"fingerprint,omitempty" url:"fingerprint,omitempty"`
5252
EncryptionKey *string `json:"keyring,omitempty" url:"keyring,omitempty"`
5353
ZFSPool *string `json:"pool,omitempty" url:"pool,omitempty"`
54-
ThinProvision *types.CustomBool `json:"sparse,omitempty" url:"sparse,omitempty"`
54+
ThinProvision *types.CustomBool `json:"sparse,omitempty" url:"sparse,omitempty,int"`
5555
Blocksize *string `json:"blocksize,omitempty" url:"blocksize,omitempty"`
5656
VolumeGroup *string `json:"vgname,omitempty" url:"vgname,omitempty"`
57-
WipeRemovedVolumes *types.CustomBool `json:"saferemove,omitempty" url:"saferemove,omitempty"`
57+
WipeRemovedVolumes *types.CustomBool `json:"saferemove,omitempty" url:"saferemove,omitempty,int"`
5858
ThinPool *string `json:"thinpool,omitempty" url:"thinpool,omitempty"`
59+
Share *string `json:"share,omitempty" url:"share,omitempty"`
60+
Domain *string `json:"domain,omitempty" url:"domain,omitempty"`
61+
SubDirectory *string `json:"subdir,omitempty" url:"subdir,omitempty"`
5962
}
6063

6164
type DatastoreCreateResponse struct {

0 commit comments

Comments
 (0)