Commit cc71b0ae authored by Silvan Kaiser's avatar Silvan Kaiser

Adding Tenant to QuobyteVolumeSource

Adds the tenant id to the QuobyteVolumeSource type and updates the quobyte api client to support looking up volume ids.
parent 54dc9db1
......@@ -2990,8 +2990,8 @@
},
{
"ImportPath": "github.com/quobyte/api",
"Comment": "v0.1.1-4-g206ef832283c1a",
"Rev": "206ef832283c1a0144bbc762be2634d49987b5ff"
"Comment": "v0.1.2",
"Rev": "9cfd29338dd9fdaaf956b7082e5550aab5fe3841"
},
{
"ImportPath": "github.com/rancher/go-rancher/client",
......
......@@ -88245,6 +88245,10 @@
"description": "Registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes",
"type": "string"
},
"tenant": {
"description": "Tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin",
"type": "string"
},
"user": {
"description": "User to map volume access to Defaults to serivceaccount user",
"type": "string"
......@@ -918,6 +918,11 @@ type QuobyteVolumeSource struct {
// Default is no group
// +optional
Group string
// Tenant owning the given Quobyte volume in the Backend
// Used with dynamically provisioned Quobyte volumes, value is set by the plugin
// +optional
Tenant string
}
// Represents a Glusterfs mount that lasts the lifetime of a pod.
......
......@@ -5989,6 +5989,7 @@ func autoConvert_v1_QuobyteVolumeSource_To_core_QuobyteVolumeSource(in *v1.Quoby
out.ReadOnly = in.ReadOnly
out.User = in.User
out.Group = in.Group
out.Tenant = in.Tenant
return nil
}
......@@ -6003,6 +6004,7 @@ func autoConvert_core_QuobyteVolumeSource_To_v1_QuobyteVolumeSource(in *core.Quo
out.ReadOnly = in.ReadOnly
out.User = in.User
out.Group = in.Group
out.Tenant = in.Tenant
return nil
}
......
......@@ -873,6 +873,10 @@ func validateQuobyteVolumeSource(quobyte *core.QuobyteVolumeSource, fldPath *fie
allErrs := field.ErrorList{}
if len(quobyte.Registry) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("registry"), "must be a host:port pair or multiple pairs separated by commas"))
} else if len(quobyte.Tenant) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("tenant"), "must be a UUID provided by the configuration and may not be omitted "))
} else if len(quobyte.Tenant) >= 65 {
allErrs = append(allErrs, field.Required(fldPath.Child("tenant"), "must be a UUID and may not exceed a length of 64 characters"))
} else {
for _, hostPortPair := range strings.Split(quobyte.Registry, ",") {
if _, _, err := net.SplitHostPort(hostPortPair); err != nil {
......
......@@ -3379,6 +3379,7 @@ func TestValidateVolumes(t *testing.T) {
ReadOnly: false,
User: "root",
Group: "root",
Tenant: "ThisIsSomeTenantUUID",
},
},
},
......@@ -3390,6 +3391,7 @@ func TestValidateVolumes(t *testing.T) {
VolumeSource: core.VolumeSource{
Quobyte: &core.QuobyteVolumeSource{
Volume: "/test",
Tenant: "ThisIsSomeTenantUUID",
},
},
},
......@@ -3406,6 +3408,7 @@ func TestValidateVolumes(t *testing.T) {
Quobyte: &core.QuobyteVolumeSource{
Registry: "registry7861",
Volume: "/test",
Tenant: "ThisIsSomeTenantUUID",
},
},
},
......@@ -3422,6 +3425,7 @@ func TestValidateVolumes(t *testing.T) {
Quobyte: &core.QuobyteVolumeSource{
Registry: "registry:7861,reg2",
Volume: "/test",
Tenant: "ThisIsSomeTenantUUID",
},
},
},
......@@ -3437,6 +3441,7 @@ func TestValidateVolumes(t *testing.T) {
VolumeSource: core.VolumeSource{
Quobyte: &core.QuobyteVolumeSource{
Registry: "registry:7861",
Tenant: "ThisIsSomeTenantUUID",
},
},
},
......@@ -3445,6 +3450,40 @@ func TestValidateVolumes(t *testing.T) {
field: "quobyte.volume",
}},
},
{
name: "empty tenant quobyte",
vol: core.Volume{
Name: "quobyte",
VolumeSource: core.VolumeSource{
Quobyte: &core.QuobyteVolumeSource{
Registry: "registry:7861,reg2",
Volume: "/test",
Tenant: "",
},
},
},
errs: []verr{{
etype: field.ErrorTypeRequired,
field: "quobyte.tenant",
}},
},
{
name: "too long tenant quobyte",
vol: core.Volume{
Name: "quobyte",
VolumeSource: core.VolumeSource{
Quobyte: &core.QuobyteVolumeSource{
Registry: "registry:7861,reg2",
Volume: "/test",
Tenant: "this is too long to be a valid uuid so this test has to fail on the maximum length validation of the tenant.",
},
},
},
errs: []verr{{
etype: field.ErrorTypeRequired,
field: "quobyte.tenant",
}},
},
// AzureDisk
{
name: "valid AzureDisk",
......
......@@ -326,6 +326,7 @@ func (plugin *quobytePlugin) newDeleterInternal(spec *volume.Spec) (volume.Delet
group: source.Group,
volume: source.Volume,
plugin: plugin,
tenant: source.Tenant,
},
registry: source.Registry,
readOnly: readOnly,
......@@ -424,6 +425,7 @@ func (provisioner *quobyteVolumeProvisioner) Provision(selectedNode *v1.Node, al
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)),
}
pv.Spec.MountOptions = provisioner.options.MountOptions
pv.Spec.PersistentVolumeSource.Quobyte.Tenant = provisioner.tenant
return pv, nil
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -3421,6 +3421,11 @@ message QuobyteVolumeSource {
// Default is no group
// +optional
optional string group = 5;
// Tenant owning the given Quobyte volume in the Backend
// Used with dynamically provisioned Quobyte volumes, value is set by the plugin
// +optional
optional string tenant = 6;
}
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
......
......@@ -955,6 +955,11 @@ type QuobyteVolumeSource struct {
// Default is no group
// +optional
Group string `json:"group,omitempty" protobuf:"bytes,5,opt,name=group"`
// Tenant owning the given Quobyte volume in the Backend
// Used with dynamically provisioned Quobyte volumes, value is set by the plugin
// +optional
Tenant string `json:"tenant,omitempty" protobuf:"bytes,6,opt,name=tenant"`
}
// FlexPersistentVolumeSource represents a generic persistent volume resource that is
......
......@@ -1678,6 +1678,7 @@ var map_QuobyteVolumeSource = map[string]string{
"readOnly": "ReadOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false.",
"user": "User to map volume access to Defaults to serivceaccount user",
"group": "Group to map volume access to Default is no group",
"tenant": "Tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin",
}
func (QuobyteVolumeSource) SwaggerDoc() map[string]string {
......
......@@ -2,7 +2,6 @@
package quobyte
import (
"log"
"net/http"
"regexp"
)
......@@ -15,6 +14,8 @@ const (
RetryOncePerTarget string = "ONCE_PER_TARGET"
)
var UUIDValidator = regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
type QuobyteClient struct {
client *http.Client
url string
......@@ -45,22 +46,48 @@ func NewQuobyteClient(url string, username string, password string) *QuobyteClie
// CreateVolume creates a new Quobyte volume. Its root directory will be owned by given user and group
func (client QuobyteClient) CreateVolume(request *CreateVolumeRequest) (string, error) {
var response volumeUUID
tenantUUID, err := client.GetTenantUUID(request.TenantID)
if err != nil {
return "", err
}
request.TenantID = tenantUUID
if err = client.sendRequest("createVolume", request, &response); err != nil {
return "", err
}
if request.TenantID != "" && !IsValidUUID(request.TenantID) {
log.Printf("Tenant name resolution: Resolving %s to UUID\n", request.TenantID)
tenantUUID, err := client.ResolveTenantNameToUUID(request.TenantID)
return response.VolumeUUID, nil
}
// GetVolumeUUID resolves the volumeUUID for the given volume and tenant name.
// This method should be used when it is not clear if the given string is volume UUID or Name.
func (client QuobyteClient) GetVolumeUUID(volume, tenant string) (string, error) {
if len(volume) != 0 && !IsValidUUID(volume) {
tenantUUID, err := client.GetTenantUUID(tenant)
if err != nil {
return "", err
}
volUUID, err := client.ResolveVolumeNameToUUID(volume, tenantUUID)
if err != nil {
return "", err
}
request.TenantID = tenantUUID
return volUUID, nil
}
return volume, nil
}
if err := client.sendRequest("createVolume", request, &response); err != nil {
return "", err
// GetTenantUUID resolves the tenatnUUID for the given name
// This method should be used when it is not clear if the given string is Tenant UUID or Name.
func (client QuobyteClient) GetTenantUUID(tenant string) (string, error) {
if len(tenant) != 0 && !IsValidUUID(tenant) {
tenantUUID, err := client.ResolveTenantNameToUUID(tenant)
if err != nil {
return "", err
}
return tenantUUID, nil
}
return response.VolumeUUID, nil
return tenant, nil
}
// ResolveVolumeNameToUUID resolves a volume name to a UUID
......@@ -77,6 +104,18 @@ func (client *QuobyteClient) ResolveVolumeNameToUUID(volumeName, tenant string)
return response.VolumeUUID, nil
}
// DeleteVolumeByResolvingNamesToUUID deletes the volume by resolving the volume name and tenant name to
// respective UUID if required.
// This method should be used if the given volume, tenant information is name or UUID.
func (client *QuobyteClient) DeleteVolumeByResolvingNamesToUUID(volume, tenant string) error {
volumeUUID, err := client.GetVolumeUUID(volume, tenant)
if err != nil {
return err
}
return client.DeleteVolume(volumeUUID)
}
// DeleteVolume deletes a Quobyte volume
func (client *QuobyteClient) DeleteVolume(UUID string) error {
return client.sendRequest(
......@@ -182,10 +221,9 @@ func (client *QuobyteClient) SetTenant(tenantName string) (string, error) {
return response.TenantID, nil
}
// IsValidUUID Validates given uuid
// IsValidUUID Validates the given uuid
func IsValidUUID(uuid string) bool {
r := regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
return r.MatchString(uuid)
return UUIDValidator.MatchString(uuid)
}
// ResolveTenantNameToUUID Returns UUID for given name, error if not found.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment