Skip to content

Commit 8af504f

Browse files
committed
VMware vSphere Driver
This patch introduces the new VMware vSphere VMDK Driver - "vmdk". The driver uses VMCI Sockets (https://www.vmware.com/support/developer/vmci-sdk/) to communicate directly with a vSphere host, removing the need for the sizeable VMware SDK for Go library dependency.
1 parent c676347 commit 8af504f

13 files changed

Lines changed: 571 additions & 54 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*.d
88
*.out
99
got
10+
gob
1011
libstorage.paw
1112
.site/
1213
site/
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// +build linux darwin
2+
// +build !libstorage_storage_executor libstorage_storage_executor_vmdk
3+
4+
package executor
5+
6+
import (
7+
gofig "github.com/akutz/gofig/types"
8+
9+
"github.com/codedellemc/libstorage/api/registry"
10+
"github.com/codedellemc/libstorage/api/types"
11+
12+
"github.com/codedellemc/libstorage/drivers/storage/vmdk"
13+
)
14+
15+
type driver struct {
16+
config gofig.Config
17+
}
18+
19+
func init() {
20+
registry.RegisterStorageExecutor(vmdk.Name, newDriver)
21+
}
22+
23+
func newDriver() types.StorageExecutor {
24+
return &driver{}
25+
}
26+
27+
func (d *driver) Name() string {
28+
return vmdk.Name
29+
}
30+
31+
func (d *driver) Supported(
32+
ctx types.Context,
33+
opts types.Store) (bool, error) {
34+
35+
return true, nil
36+
}
37+
38+
func (d *driver) Init(ctx types.Context, config gofig.Config) error {
39+
d.config = config
40+
return nil
41+
}
42+
43+
// InstanceID returns the local system's InstanceID.
44+
func (d *driver) InstanceID(
45+
ctx types.Context,
46+
opts types.Store) (*types.InstanceID, error) {
47+
48+
iid := &types.InstanceID{Driver: vmdk.Name}
49+
iid.ID = vmdk.Name
50+
return iid, nil
51+
}
52+
53+
// NextDevice returns the next available device.
54+
func (d *driver) NextDevice(
55+
ctx types.Context,
56+
opts types.Store) (string, error) {
57+
58+
return "", nil
59+
}
60+
61+
// LocalDevices returns a map of the system's local devices.
62+
func (d *driver) LocalDevices(
63+
ctx types.Context,
64+
opts *types.LocalDevicesOpts) (*types.LocalDevices, error) {
65+
66+
return &types.LocalDevices{DeviceMap: map[string]string{}}, nil
67+
}
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
// +build !libstorage_storage_driver libstorage_storage_driver_vmdk
2+
3+
package storage
4+
5+
import (
6+
"fmt"
7+
"regexp"
8+
"strconv"
9+
"sync"
10+
11+
gofig "github.com/akutz/gofig/types"
12+
13+
"github.com/codedellemc/libstorage/api/registry"
14+
"github.com/codedellemc/libstorage/api/types"
15+
16+
"github.com/codedellemc/libstorage/drivers/storage/vmdk"
17+
"github.com/vmware/docker-volume-vsphere/vmdk_plugin/drivers/vmdk/vmdkops"
18+
)
19+
20+
const (
21+
minSizeGiB = 1
22+
)
23+
24+
type driver struct {
25+
ctx types.Context
26+
config gofig.Config
27+
ops vmdkops.VmdkOps
28+
}
29+
30+
func init() {
31+
registry.RegisterStorageDriver(vmdk.Name, newDriver)
32+
}
33+
34+
func newDriver() types.StorageDriver {
35+
return &driver{}
36+
}
37+
38+
func (d *driver) Name() string {
39+
return vmdk.Name
40+
}
41+
42+
func (d *driver) Type(ctx types.Context) (types.StorageType, error) {
43+
return types.Block, nil
44+
}
45+
46+
func (d *driver) Init(ctx types.Context, config gofig.Config) error {
47+
d.ctx = ctx
48+
d.config = config
49+
d.ops = vmdkops.VmdkOps{Cmd: vmdkops.EsxVmdkCmd{Mtx: &sync.Mutex{}}}
50+
return nil
51+
}
52+
53+
func (d *driver) NextDeviceInfo(
54+
ctx types.Context) (*types.NextDeviceInfo, error) {
55+
return &types.NextDeviceInfo{
56+
Ignore: true,
57+
}, nil
58+
}
59+
60+
func (d *driver) InstanceInspect(
61+
ctx types.Context,
62+
opts types.Store) (*types.Instance, error) {
63+
64+
return nil, nil
65+
}
66+
67+
func (d *driver) Volumes(
68+
ctx types.Context,
69+
opts *types.VolumesOpts) ([]*types.Volume, error) {
70+
71+
data, err := d.ops.List()
72+
if err != nil {
73+
return nil, err
74+
}
75+
76+
vols := []*types.Volume{}
77+
for _, v := range data {
78+
vols = append(vols, &types.Volume{
79+
Name: v.Name,
80+
Fields: v.Attributes,
81+
})
82+
}
83+
84+
return vols, nil
85+
}
86+
87+
func (d *driver) VolumeInspect(
88+
ctx types.Context,
89+
volumeID string,
90+
opts *types.VolumeInspectOpts) (*types.Volume, error) {
91+
92+
data, err := d.ops.Get(volumeID)
93+
if err != nil {
94+
return nil, err
95+
}
96+
97+
vol := &types.Volume{
98+
ID: volumeID,
99+
Name: volumeID,
100+
Fields: map[string]string{},
101+
}
102+
103+
for k, v := range data {
104+
switch k {
105+
case "datastore":
106+
if v, ok := v.(string); ok {
107+
vol.Type = v
108+
}
109+
case "capacity":
110+
if v, ok := v.(map[string]interface{}); ok {
111+
if v, ok := v["size"].(string); ok {
112+
if v == "0" {
113+
vol.Size = 0
114+
} else if sz, ok := isGB(v); ok {
115+
vol.Size = sz * 1024 * 1024 * 1024
116+
} else if sz, ok := isMB(v); ok {
117+
vol.Size = sz * 1024 * 1024
118+
} else if sz, ok := isKB(v); ok {
119+
vol.Size = sz * 1024
120+
}
121+
}
122+
}
123+
default:
124+
vol.Fields[k] = fmt.Sprintf("%v", v)
125+
}
126+
}
127+
128+
return vol, nil
129+
}
130+
131+
func isSize(rx *regexp.Regexp, s string) (int64, bool) {
132+
m := rx.FindStringSubmatch(s)
133+
if len(m) == 0 {
134+
return 0, false
135+
}
136+
i, err := strconv.Atoi(m[1])
137+
if err != nil {
138+
return 0, false
139+
}
140+
return int64(i), true
141+
}
142+
143+
var rxIsKB = regexp.MustCompile(`(?i)^([\d,\.]+)\s*KB\s*$`)
144+
145+
func isKB(s string) (int64, bool) {
146+
return isSize(rxIsKB, s)
147+
}
148+
149+
var rxIsMB = regexp.MustCompile(`(?i)^([\d,\.]+)\s*MB\s*$`)
150+
151+
func isMB(s string) (int64, bool) {
152+
return isSize(rxIsMB, s)
153+
}
154+
155+
var rxIsGB = regexp.MustCompile(`(?i)^([\d,\.]+)\s*GB\s*$`)
156+
157+
func isGB(s string) (int64, bool) {
158+
return isSize(rxIsGB, s)
159+
}
160+
161+
func (d *driver) VolumeCreate(
162+
ctx types.Context,
163+
name string,
164+
opts *types.VolumeCreateOpts) (*types.Volume, error) {
165+
166+
if opts.Type != nil && *opts.Type != "" {
167+
name = fmt.Sprintf("%s@%s", name, *opts.Type)
168+
}
169+
170+
createOpts := map[string]string{}
171+
if opts.Size != nil {
172+
createOpts["size"] = fmt.Sprintf("%dgb", *opts.Size)
173+
}
174+
175+
if err := d.ops.Create(name, createOpts); err != nil {
176+
return nil, err
177+
}
178+
179+
return d.VolumeInspect(ctx, name, nil)
180+
}
181+
182+
func (d *driver) VolumeCreateFromSnapshot(
183+
ctx types.Context,
184+
snapshotID, volumeName string,
185+
opts *types.VolumeCreateOpts) (*types.Volume, error) {
186+
187+
return nil, types.ErrNotImplemented
188+
}
189+
190+
func (d *driver) VolumeCopy(
191+
ctx types.Context,
192+
volumeID, volumeName string,
193+
opts types.Store) (*types.Volume, error) {
194+
195+
return nil, types.ErrNotImplemented
196+
}
197+
198+
func (d *driver) VolumeSnapshot(
199+
ctx types.Context,
200+
volumeID, snapshotName string,
201+
opts types.Store) (*types.Snapshot, error) {
202+
203+
return nil, types.ErrNotImplemented
204+
}
205+
206+
func (d *driver) VolumeRemove(
207+
ctx types.Context,
208+
volumeID string,
209+
opts *types.VolumeRemoveOpts) error {
210+
211+
return d.ops.Remove(volumeID, map[string]string{})
212+
}
213+
214+
func (d *driver) VolumeAttach(
215+
ctx types.Context,
216+
volumeID string,
217+
opts *types.VolumeAttachOpts) (*types.Volume, string, error) {
218+
219+
dev, err := d.ops.Attach(volumeID, nil)
220+
if err != nil {
221+
return nil, "", err
222+
}
223+
224+
var vol *types.Volume
225+
if vol, err = d.VolumeInspect(ctx, volumeID, nil); err != nil {
226+
return nil, "", err
227+
}
228+
229+
return vol, string(dev), nil
230+
}
231+
232+
func (d *driver) VolumeDetach(
233+
ctx types.Context,
234+
volumeID string,
235+
opts *types.VolumeDetachOpts) (*types.Volume, error) {
236+
237+
if err := d.ops.Detach(volumeID, nil); err != nil {
238+
return nil, err
239+
}
240+
241+
vol, err := d.VolumeInspect(ctx, volumeID, nil)
242+
if err != nil {
243+
return nil, err
244+
}
245+
246+
return vol, nil
247+
}
248+
249+
func (d *driver) Snapshots(
250+
ctx types.Context,
251+
opts types.Store) ([]*types.Snapshot, error) {
252+
253+
return nil, types.ErrNotImplemented
254+
}
255+
256+
func (d *driver) SnapshotInspect(
257+
ctx types.Context,
258+
snapshotID string,
259+
opts types.Store) (*types.Snapshot, error) {
260+
261+
return nil, types.ErrNotImplemented
262+
}
263+
264+
func (d *driver) SnapshotCopy(
265+
ctx types.Context,
266+
snapshotID, snapshotName, destinationID string,
267+
opts types.Store) (*types.Snapshot, error) {
268+
269+
return nil, types.ErrNotImplemented
270+
}
271+
272+
func (d *driver) SnapshotRemove(
273+
ctx types.Context,
274+
snapshotID string,
275+
opts types.Store) error {
276+
277+
return types.ErrNotImplemented
278+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
VMDK_COVERPKG := $(ROOT_IMPORT_PATH)/drivers/storage/vmdk
2+
TEST_COVERPKG_./drivers/storage/vmdk/tests := $(VMDK_COVERPKG),$(VMDK_COVERPKG)/executor

0 commit comments

Comments
 (0)