diff --git a/pkg/cloud/cloud.go b/pkg/cloud/cloud.go index 19109a3..cc90d63 100644 --- a/pkg/cloud/cloud.go +++ b/pkg/cloud/cloud.go @@ -26,6 +26,7 @@ import ( "errors" "github.com/apache/cloudstack-go/v2/cloudstack" + "k8s.io/klog/v2" ) // Interface is the CloudStack client interface. @@ -70,6 +71,7 @@ type Volume struct { DeviceID string } +// Volume represents a CloudStack snapshot. type Snapshot struct { ID string Name string @@ -99,12 +101,19 @@ var ( // client is the implementation of Interface. type client struct { *cloudstack.CloudStackClient - projectID string + projectID string // Used by some specific cloudstack api calls } // New creates a new cloud connector, given its configuration. func New(config *Config) Interface { csClient := cloudstack.NewAsyncClient(config.APIURL, config.APIKey, config.SecretKey, config.VerifySSL) + // Set the project id to every request that support options. + // This is possible because we also could work in one project only with the previous implementation. + if config.ProjectID != "" { + csClient.DefaultOptions(cloudstack.WithProject(config.ProjectID)) + klog.Background().V(2).Info("Set projectID to cloud connector", "projectID", config.ProjectID) + } + return &client{csClient, config.ProjectID} } diff --git a/pkg/cloud/snapshots.go b/pkg/cloud/snapshots.go index fe2451f..ea1b1b7 100644 --- a/pkg/cloud/snapshots.go +++ b/pkg/cloud/snapshots.go @@ -30,46 +30,29 @@ import ( func (c *client) GetSnapshotByID(ctx context.Context, snapshotID string) (*Snapshot, error) { logger := klog.FromContext(ctx) - p := c.Snapshot.NewListSnapshotsParams() - if snapshotID != "" { - p.SetId(snapshotID) - } - if c.projectID != "" { - p.SetProjectid(c.projectID) - } - logger.V(2).Info("CloudStack API call", "command", "ListSnapshots", "params", map[string]string{ - "id": snapshotID, - "projectid": c.projectID, + logger.V(2).Info("CloudStack API call", "command", "GetSnapshotByID", "params", map[string]string{ + "id": snapshotID, }) - l, err := c.Snapshot.ListSnapshots(p) + + snapshot, _, err := c.Snapshot.GetSnapshotByID(snapshotID) if err != nil { return nil, err } - if l.Count == 0 { - return nil, ErrNotFound - } - if l.Count > 1 { - return nil, ErrTooManyResults - } - snapshot := l.Snapshots[0] - s := Snapshot{ + + return &Snapshot{ ID: snapshot.Id, Name: snapshot.Name, DomainID: snapshot.Domainid, ProjectID: snapshot.Projectid, ZoneID: snapshot.Zoneid, VolumeID: snapshot.Volumeid, - } - - return &s, nil + }, nil } func (c *client) CreateSnapshot(ctx context.Context, volumeID, name string) (*Snapshot, error) { logger := klog.FromContext(ctx) p := c.Snapshot.NewCreateSnapshotParams(volumeID) - if name != "" { - p.SetName(name) - } + p.SetName(name) logger.V(2).Info("CloudStack API call", "command", "CreateSnapshot", "params", map[string]string{ "volumeid": volumeID, "name": name, @@ -80,7 +63,7 @@ func (c *client) CreateSnapshot(ctx context.Context, volumeID, name string) (*Sn return nil, status.Errorf(codes.Internal, "Error %v", err) } - snap := Snapshot{ + return &Snapshot{ ID: snapshot.Id, Name: snapshot.Name, Size: snapshot.Virtualsize, @@ -89,9 +72,7 @@ func (c *client) CreateSnapshot(ctx context.Context, volumeID, name string) (*Sn ZoneID: snapshot.Zoneid, VolumeID: snapshot.Volumeid, CreatedAt: snapshot.Created, - } - - return &snap, nil + }, nil } func (c *client) DeleteSnapshot(_ context.Context, snapshotID string) error { @@ -107,30 +88,15 @@ func (c *client) DeleteSnapshot(_ context.Context, snapshotID string) error { func (c *client) GetSnapshotByName(ctx context.Context, name string) (*Snapshot, error) { logger := klog.FromContext(ctx) - if name == "" { - return nil, ErrNotFound - } - p := c.Snapshot.NewListSnapshotsParams() - p.SetName(name) - if c.projectID != "" { - p.SetProjectid(c.projectID) - } - logger.V(2).Info("CloudStack API call", "command", "ListSnapshots", "params", map[string]string{ - "name": name, - "projectid": c.projectID, + logger.V(2).Info("CloudStack API call", "command", "GetSnapshotByName", "params", map[string]string{ + "name": name, }) - l, err := c.Snapshot.ListSnapshots(p) + snapshot, _, err := c.Snapshot.GetSnapshotByName(name) if err != nil { return nil, err } - if l.Count == 0 { - return nil, ErrNotFound - } - if l.Count > 1 { - return nil, ErrTooManyResults - } - snapshot := l.Snapshots[0] - s := Snapshot{ + + return &Snapshot{ ID: snapshot.Id, Name: snapshot.Name, DomainID: snapshot.Domainid, @@ -138,27 +104,29 @@ func (c *client) GetSnapshotByName(ctx context.Context, name string) (*Snapshot, ZoneID: snapshot.Zoneid, VolumeID: snapshot.Volumeid, CreatedAt: snapshot.Created, - } - - return &s, nil + }, nil } func (c *client) ListSnapshots(ctx context.Context, volumeID, snapshotID string) ([]*Snapshot, error) { logger := klog.FromContext(ctx) p := c.Snapshot.NewListSnapshotsParams() + // snapshotID is optional: csi.ListSnapshotsRequest if snapshotID != "" { p.SetId(snapshotID) } + // volumeID is optional: csi.ListSnapshotsRequest if volumeID != "" { p.SetVolumeid(volumeID) } + + // There is no list function that uses the client default project id if c.projectID != "" { p.SetProjectid(c.projectID) } + logger.V(2).Info("CloudStack API call", "command", "ListSnapshots", "params", map[string]string{ - "id": snapshotID, - "volumeid": volumeID, - "projectid": c.projectID, + "id": snapshotID, + "volumeid": volumeID, }) l, err := c.Snapshot.ListSnapshots(p) if err != nil { diff --git a/pkg/cloud/vms.go b/pkg/cloud/vms.go index 2df3c7f..52ac6be 100644 --- a/pkg/cloud/vms.go +++ b/pkg/cloud/vms.go @@ -27,27 +27,14 @@ import ( func (c *client) GetVMByID(ctx context.Context, vmID string) (*VM, error) { logger := klog.FromContext(ctx) - p := c.VirtualMachine.NewListVirtualMachinesParams() - p.SetId(vmID) - if c.projectID != "" { - p.SetProjectid(c.projectID) - } - logger.V(2).Info("CloudStack API call", "command", "ListVirtualMachines", "params", map[string]string{ - "id": vmID, - "projectID": c.projectID, + logger.V(2).Info("CloudStack API call", "command", "GetVirtualMachineByID", "params", map[string]string{ + "id": vmID, }) - l, err := c.VirtualMachine.ListVirtualMachines(p) + + vm, _, err := c.VirtualMachine.GetVirtualMachineByID(vmID) if err != nil { return nil, err } - if l.Count == 0 { - return nil, ErrNotFound - } - if l.Count > 1 { - return nil, ErrTooManyResults - } - vm := l.VirtualMachines[0] - logger.V(2).Info("Returning VM", "vmID", vm.Id, "zoneID", vm.Zoneid) return &VM{ ID: vm.Id, @@ -57,22 +44,14 @@ func (c *client) GetVMByID(ctx context.Context, vmID string) (*VM, error) { func (c *client) getVMByName(ctx context.Context, name string) (*VM, error) { logger := klog.FromContext(ctx) - p := c.VirtualMachine.NewListVirtualMachinesParams() - p.SetName(name) - logger.V(2).Info("CloudStack API call", "command", "ListVirtualMachines", "params", map[string]string{ + logger.V(2).Info("CloudStack API call", "command", "GetVirtualMachineByName", "params", map[string]string{ "name": name, }) - l, err := c.VirtualMachine.ListVirtualMachines(p) + + vm, _, err := c.VirtualMachine.GetVirtualMachineByName(name) if err != nil { return nil, err } - if l.Count == 0 { - return nil, ErrNotFound - } - if l.Count > 1 { - return nil, ErrTooManyResults - } - vm := l.VirtualMachines[0] return &VM{ ID: vm.Id, diff --git a/pkg/cloud/volumes.go b/pkg/cloud/volumes.go index caaa7a3..de7901e 100644 --- a/pkg/cloud/volumes.go +++ b/pkg/cloud/volumes.go @@ -31,19 +31,8 @@ import ( "github.com/cloudstack/cloudstack-csi-driver/pkg/util" ) -func (c *client) listVolumes(p *cloudstack.ListVolumesParams) (*Volume, error) { - l, err := c.Volume.ListVolumes(p) - if err != nil { - return nil, err - } - if l.Count == 0 { - return nil, ErrNotFound - } - if l.Count > 1 { - return nil, ErrTooManyResults - } - vol := l.Volumes[0] - v := Volume{ +func mapVolume(vol *cloudstack.Volume) *Volume { + return &Volume{ ID: vol.Id, Name: vol.Name, Size: vol.Size, @@ -54,34 +43,36 @@ func (c *client) listVolumes(p *cloudstack.ListVolumesParams) (*Volume, error) { VirtualMachineID: vol.Virtualmachineid, DeviceID: strconv.FormatInt(vol.Deviceid, 10), } - - return &v, nil } func (c *client) GetVolumeByID(ctx context.Context, volumeID string) (*Volume, error) { logger := klog.FromContext(ctx) - p := c.Volume.NewListVolumesParams() - p.SetId(volumeID) - if c.projectID != "" { - p.SetProjectid(c.projectID) - } - logger.V(2).Info("CloudStack API call", "command", "ListVolumes", "params", map[string]string{ - "id": volumeID, - "projectid": c.projectID, + logger.V(2).Info("CloudStack API call", "command", "GetVolumeByID", "params", map[string]string{ + "id": volumeID, }) - return c.listVolumes(p) + volume, _, err := c.Volume.GetVolumeByID(volumeID) + if err != nil { + return nil, err + } + + return mapVolume(volume), nil } func (c *client) GetVolumeByName(ctx context.Context, name string) (*Volume, error) { logger := klog.FromContext(ctx) p := c.Volume.NewListVolumesParams() p.SetName(name) - logger.V(2).Info("CloudStack API call", "command", "ListVolumes", "params", map[string]string{ + logger.V(2).Info("CloudStack API call", "command", "GetVolumeByName", "params", map[string]string{ "name": name, }) - return c.listVolumes(p) + volume, _, err := c.Volume.GetVolumeByName(name) + if err != nil { + return nil, err + } + + return mapVolume(volume), nil } func (c *client) CreateVolume(ctx context.Context, diskOfferingID, zoneID, name string, sizeInGB int64) (string, error) { @@ -91,6 +82,7 @@ func (c *client) CreateVolume(ctx context.Context, diskOfferingID, zoneID, name p.SetZoneid(zoneID) p.SetName(name) p.SetSize(sizeInGB) + // There is no create function that uses the client default project id if c.projectID != "" { p.SetProjectid(c.projectID) } @@ -99,7 +91,6 @@ func (c *client) CreateVolume(ctx context.Context, diskOfferingID, zoneID, name "zoneid": zoneID, "name": name, "size": strconv.FormatInt(sizeInGB, 10), - "projectid": c.projectID, }) vol, err := c.Volume.CreateVolume(p) if err != nil { @@ -199,7 +190,6 @@ func (c *client) CreateVolumeFromSnapshot(ctx context.Context, zoneID, name, pro "name": name, "size": strconv.FormatInt(sizeInGB, 10), "snapshotid": snapshotID, - "projectid": projectID, "zoneid": zoneID, }) // Execute the API call to create volume from snapshot @@ -209,7 +199,7 @@ func (c *client) CreateVolumeFromSnapshot(ctx context.Context, zoneID, name, pro return nil, fmt.Errorf("failed to create volume from snapshot '%s': %w", snapshotID, err) } - v := Volume{ + return &Volume{ ID: vol.Id, Name: vol.Name, Size: vol.Size, @@ -219,7 +209,5 @@ func (c *client) CreateVolumeFromSnapshot(ctx context.Context, zoneID, name, pro ZoneID: vol.Zoneid, VirtualMachineID: vol.Virtualmachineid, DeviceID: strconv.FormatInt(vol.Deviceid, 10), - } - - return &v, nil + }, nil }