-
Notifications
You must be signed in to change notification settings - Fork 453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
r/virtual_machine: Add support for remote backed CDROMs #421
Changes from 1 commit
52e17d0
ddcffe3
e22deb6
724d71a
048a0fe
f133ca8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,14 +20,20 @@ func CdromSubresourceSchema() map[string]*schema.Schema { | |
// VirtualDeviceFileBackingInfo | ||
"datastore_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
Optional: true, | ||
Description: "The datastore ID the ISO is located on.", | ||
}, | ||
"path": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
Optional: true, | ||
Description: "The path to the ISO file on the datastore.", | ||
}, | ||
// VirtualCdromRemoteAtapiBackingInfo | ||
"client_device": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Description: "Indicates whether the device should be backed by remote client device", | ||
}, | ||
} | ||
structure.MergeSchema(s, subresourceSchema()) | ||
return s | ||
|
@@ -378,6 +384,25 @@ func CdromPostCloneOperation(d *schema.ResourceData, c *govmomi.Client, l object | |
return l, spec, nil | ||
} | ||
|
||
// ValidateCdromConfig takes a CdromSubresource and ensures that the associated configuration is valid | ||
func (r *CdromSubresource) ValidateCdromConfig() error { | ||
log.Printf("[DEBUG] ValidateCdromConfig: Beginning CDROM configuration validation") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Subresource debug lines should include the specific resource address. For this log entry, this means it would look like:
Function does not necessarily need to be referenced here. |
||
dsID := r.Get("datastore_id").(string) | ||
path := r.Get("path").(string) | ||
clientDevice := r.Get("client_device").(bool) | ||
if clientDevice { | ||
if dsID != "" || path != "" { | ||
return fmt.Errorf("ValidateCdromConfig: Cannot have both client_device parameter and ISO file parameters (datastore_id, path) set") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we remove the function name from these error messages? They will be exposed to the user during regular output. |
||
} | ||
} else { | ||
if dsID == "" || path == "" { | ||
return fmt.Errorf("ValidateCdromConfig: Either client_device or datastore_id and path must be set") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per above |
||
} | ||
} | ||
log.Printf("[DEBUG] ValidateCdromConfig: Config validation complete") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line should follow the same kind of formatting as the starting line, example:
|
||
return nil | ||
} | ||
|
||
// Create creates a vsphere_virtual_machine cdrom sub-resource. | ||
func (r *CdromSubresource) Create(l object.VirtualDeviceList) ([]types.BaseVirtualDeviceConfigSpec, error) { | ||
log.Printf("[DEBUG] %s: Running create", r) | ||
|
@@ -389,30 +414,40 @@ func (r *CdromSubresource) Create(l object.VirtualDeviceList) ([]types.BaseVirtu | |
} | ||
|
||
// We now have the controller on which we can create our device on. | ||
dsID := r.Get("datastore_id").(string) | ||
path := r.Get("path").(string) | ||
ds, err := datastore.FromID(r.client, dsID) | ||
if err != nil { | ||
return nil, fmt.Errorf("cannot find datastore: %s", err) | ||
} | ||
dsProps, err := datastore.Properties(ds) | ||
err = r.ValidateCdromConfig() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if err != nil { | ||
return nil, fmt.Errorf("could not get properties for datastore: %s", err) | ||
} | ||
dsName := dsProps.Name | ||
|
||
dsPath := &object.DatastorePath{ | ||
Datastore: dsName, | ||
Path: path, | ||
return nil, err | ||
} | ||
|
||
dsID := r.Get("datastore_id").(string) | ||
path := r.Get("path").(string) | ||
clientDevice := r.Get("client_device").(bool) | ||
device, err := l.CreateCdrom(ctlr.(*types.VirtualIDEController)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
device = l.InsertIso(device, dsPath.String()) | ||
l.Connect(device) | ||
|
||
if dsID != "" && path != "" { | ||
// If the datastore ID and path are both set, the CDROM will be backed by a file on a datastore | ||
ds, err := datastore.FromID(r.client, dsID) | ||
if err != nil { | ||
return nil, fmt.Errorf("cannot find datastore: %s", err) | ||
} | ||
dsProps, err := datastore.Properties(ds) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not get properties for datastore: %s", err) | ||
} | ||
dsName := dsProps.Name | ||
dsPath := &object.DatastorePath{ | ||
Datastore: dsName, | ||
Path: path, | ||
} | ||
device = l.InsertIso(device, dsPath.String()) | ||
l.Connect(device) | ||
} else if clientDevice { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's try to avoid This actually can be written as a switch: switch {
case dsID != "" && path != "":
...
case clientDevice == true:
// You might want to use the full-form boolean expression above to be specific about intent
...
default:
// This would be where your "else" goes, if you had one
} |
||
// If set to use the client device, then the CDROM will be backed by a remote device | ||
device.Backing = &types.VirtualCdromRemoteAtapiBackingInfo{ | ||
VirtualDeviceRemoteDeviceBackingInfo: types.VirtualDeviceRemoteDeviceBackingInfo{}, | ||
} | ||
} | ||
// Done here. Save IDs, push the device to the new device list and return. | ||
if err := r.SaveDevIDs(device, ctlr); err != nil { | ||
return nil, err | ||
|
@@ -438,9 +473,10 @@ func (r *CdromSubresource) Read(l object.VirtualDeviceList) error { | |
if !ok { | ||
return fmt.Errorf("device at %q is not a virtual CDROM device", l.Name(d)) | ||
} | ||
if backing, ok := device.Backing.(*types.VirtualCdromIsoBackingInfo); ok { | ||
// Only read backing info if it's available. If not, this is a host | ||
// device/client mapping that is not managed by TF and needs to be deleted. | ||
// Only read backing info if it's available. | ||
if _, ok := device.Backing.(*types.VirtualCdromRemoteAtapiBackingInfo); ok { | ||
r.Set("client_device", true) | ||
} else if backing, ok := device.Backing.(*types.VirtualCdromIsoBackingInfo); ok { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above, let's try to avoid Instead, write this as a type switch backing := device.Backing.(type) {
case *types.VirtualCdromRemoteAtapiBackingInfo:
r.Set("client_device", true)
case *types.VirtualCdromIsoBackingInfo:
...
default:
return nil, fmt.Errorf("device at %q is not a virtual CDROM device", l.Name(d))
} |
||
dp := &object.DatastorePath{} | ||
if ok := dp.FromString(backing.FileName); !ok { | ||
return fmt.Errorf("could not read datastore path in backing %q", backing.FileName) | ||
|
@@ -472,27 +508,39 @@ func (r *CdromSubresource) Update(l object.VirtualDeviceList) ([]types.BaseVirtu | |
return nil, fmt.Errorf("device at %q is not a virtual CDROM device", l.Name(d)) | ||
} | ||
|
||
// To update, we just re-insert the ISO as per create, and send it as an edit. | ||
dsID := r.Get("datastore_id").(string) | ||
path := r.Get("path").(string) | ||
ds, err := datastore.FromID(r.client, dsID) | ||
clientDevice := r.Get("client_device").(bool) | ||
err = r.ValidateCdromConfig() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per the comment in validation being in |
||
if err != nil { | ||
return nil, fmt.Errorf("cannot find datastore: %s", err) | ||
} | ||
dsProps, err := datastore.Properties(ds) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not get properties for datastore: %s", err) | ||
} | ||
dsName := dsProps.Name | ||
|
||
dsPath := &object.DatastorePath{ | ||
Datastore: dsName, | ||
Path: path, | ||
return nil, err | ||
} | ||
|
||
device = l.InsertIso(device, dsPath.String()) | ||
l.Connect(device) | ||
if dsID != "" && path != "" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might be a good candidate for a unexported helper as this code looks pretty much the same as it does in |
||
// If the datastore ID and path are both set, the CDROM will be backed by a file on a datastore | ||
// To update, we just re-insert the ISO as per create, and send it as an edit. | ||
ds, err := datastore.FromID(r.client, dsID) | ||
if err != nil { | ||
return nil, fmt.Errorf("cannot find datastore: %s", err) | ||
} | ||
dsProps, err := datastore.Properties(ds) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not get properties for datastore: %s", err) | ||
} | ||
dsName := dsProps.Name | ||
|
||
dsPath := &object.DatastorePath{ | ||
Datastore: dsName, | ||
Path: path, | ||
} | ||
device = l.InsertIso(device, dsPath.String()) | ||
l.Connect(device) | ||
} else if clientDevice { | ||
// If set to use the client device, then the CDROM will be backed by a remote device | ||
device.Backing = &types.VirtualCdromRemoteAtapiBackingInfo{ | ||
VirtualDeviceRemoteDeviceBackingInfo: types.VirtualDeviceRemoteDeviceBackingInfo{}, | ||
} | ||
} | ||
spec, err := object.VirtualDeviceList{device}.ConfigSpec(types.VirtualDeviceConfigSpecOperationEdit) | ||
if err != nil { | ||
return nil, err | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor can we edit this so it reads: