diff --git a/README.md b/README.md index ff1eac6..9842392 100644 --- a/README.md +++ b/README.md @@ -47,33 +47,36 @@ $ systemctl enable docker-quobyte-plugin $ systemctl status docker-quobyte-plugin ``` +### Configuration + +Configuration is done mainly through the systemd environment file: + +``` +# Maximum number of filesystem checks when a Volume is created before returning an error +MAX_FS_CHECKS=5 +# Maximum wait time for filesystem checks to complete when a Volume is created before returning an error +MAX_WAIT_TIME=30 +# Group to create the unix socket +SOCKET_GROUP=root +QUOBYTE_API_URL=http://localhost:7860 +QUOBYTE_API_PASSWORD=quobyte +QUOBYTE_API_USER=admin +QUOBYTE_MOUNT_PATH=/run/docker/quobyte/mnt +QUOBYTE_MOUNT_OPTIONS=-o user_xattr +QUOBYTE_REGISTRY=localhost:7861 +# ID of the Quobyte tenant in whose domain volumes are managed by this plugin +QUOBYTE_TENANT_ID=replace_me +# Default volume config for new volumes, can be overridden via --opt flag 'configuration_name' +QUOBYTE_VOLUME_CONFIG_NAME=BASE +``` + ### Usage +The cli is faily simple: + ``` $ bin/docker-quobyte-plugin -h Usage of bin/docker-quobyte-plugin: - -api string - URL to the API server(s) in the form http(s)://host[:port][,host:port] or SRV record name (default "http://localhost:7860") - -configuration_name string - Name of the volume configuration of new volumes (default "BASE") - -group string - Group to create the unix socket (default "root") - -max-fs-checks int - Maximimum number of filesystem checks when a Volume is created before returning an error (default 5) - -max-wait-time float - Maximimum wait time for filesystem checks to complete when a Volume is created before returning an error (default 30) - -options string - Fuse options to be used when Quobyte is mounted (default "-o user_xattr") - -password string - Password for the user to connect to the Quobyte API server (default "quobyte") - -path string - Path where Quobyte is mounted on the host (default "/run/docker/quobyte/mnt") - -registry string - URL to the registry server(s) in the form of host[:port][,host:port] or SRV record name (default "localhost:7861") - -tenant_id string - Id of the Quobyte tenant in whose domain the operation takes place (default "no default") - -user string - User to connect to the Quobyte API server (default "root") -version Shows version string ``` @@ -83,13 +86,15 @@ Usage of bin/docker-quobyte-plugin: ### Create a volume ``` -$ docker volume create --driver quobyte --name --opt tenant_id= -# Set user and group of the volume -$ docker volume create --driver quobyte --name --opt user=docker --opt group=docker --opt tenant_id= +$ docker volume create --driver quobyte --name +# Set user, group and specific volume configuration for the new volume +$ docker volume create --driver quobyte --name --opt user=docker --opt group=docker --opt configuration_name=SSD_ONLY ``` ### Delete a volume +__Important__: Be careful when using this. The volume removal allows removing any volume accessible in the configured tenant! + ``` $ docker volume rm ``` diff --git a/main.go b/main.go index 6e94daa..599e7a5 100644 --- a/main.go +++ b/main.go @@ -4,11 +4,14 @@ import ( "flag" "log" "os" + "strconv" "github.com/docker/go-plugins-helpers/volume" ) -const quobyteID string = "quobyte" +const ( + quobyteID string = "quobyte" +) var ( version string @@ -16,42 +19,52 @@ var ( ) func main() { - quobyteMountPath := flag.String("path", "/run/docker/quobyte/mnt", "Path where Quobyte is mounted on the host") - quobyteMountOptions := flag.String("options", "-o user_xattr", "Fuse options to be used when Quobyte is mounted") - - quobyteUser := flag.String("user", "root", "User to connect to the Quobyte API server") - quobytePassword := flag.String("password", "quobyte", "Password for the user to connect to the Quobyte API server") - quobyteConfigName := flag.String("configuration_name", "BASE", "Name of the volume configuration of new volumes") - quobyteAPIURL := flag.String("api", "http://localhost:7860", "URL to the API server(s) in the form http(s)://host[:port][,host:port] or SRV record name") - quobyteRegistry := flag.String("registry", "localhost:7861", "URL to the registry server(s) in the form of host[:port][,host:port] or SRV record name") - quobyteTenantId := flag.String("tenant_id", "no default", "Id of the Quobyte tenant in whose domain the operation takes place") - - group := flag.String("group", "root", "Group to create the unix socket") - maxWaitTime := flag.Float64("max-wait-time", 30, "Maximimum wait time for filesystem checks to complete when a Volume is created before returning an error") - maxFSChecks := flag.Int("max-fs-checks", 5, "Maximimum number of filesystem checks when a Volume is created before returning an error") showVersion := flag.Bool("version", false, "Shows version string") + flag.Parse() + maxFSChecks, _ := strconv.Atoi(os.Getenv("MAX_FS_CHECKS")) + maxWaitTime, _ := strconv.ParseFloat(os.Getenv("MAX_WAIT_TIME"), 64) + socketGroup := os.Getenv("SOCKET_GROUP") + + quobyteAPIURL := os.Getenv("QUOBYTE_API_URL") + quobyteAPIPassword := os.Getenv("QUOBYTE_API_PASSWORD") + quobyteAPIUser := os.Getenv("QUOBYTE_API_USER") + quobyteMountPath := os.Getenv("QUOBYTE_MOUNT_PATH") + quobyteMountOptions := os.Getenv("QUOBYTE_MOUNT_OPTIONS") + quobyteRegistry := os.Getenv("QUOBYTE_REGISTRY") + quobyteTenantID := os.Getenv("QUOBYTE_TENANT_ID") + quobyteVolConfigName := os.Getenv("QUOBYTE_VOLUME_CONFIG_NAME") + log.Printf("\nVariables read from environment:\n"+ + "MAX_FS_CHECKS: %v\nMAX_WAIT_TIME: %v\nSOCKET_GROUP: %s\n"+ + "QUOBYTE_API_URL: %s\nQUOBYTE_API_USER: %s\nQUOBYTE_MOUNT_PATH:"+ + " %s\nQUOBYTE_MOUNT_OPTIONS: %s\nQUOBYTE_REGISTRY: %s\nQUOBYTE_TENANT_ID: "+ + " %s\nQUOBYTE_VOLUME_CONFIG_NAME: %s\n", maxFSChecks, maxWaitTime, + socketGroup, quobyteAPIURL, quobyteAPIUser, + quobyteMountPath, quobyteMountOptions, quobyteRegistry, quobyteTenantID, + quobyteVolConfigName) + if *showVersion { - log.Printf("Version: %s - Revision: %s\n", version, revision) + log.Printf("\nVersion: %s - Revision: %s\n", version, revision) return } - if err := validateAPIURL(*quobyteAPIURL); err != nil { + if err := validateAPIURL(quobyteAPIURL); err != nil { log.Fatalln(err) } - if err := os.MkdirAll(*quobyteMountPath, 0555); err != nil { + if err := os.MkdirAll(quobyteMountPath, 0555); err != nil { log.Println(err.Error()) } - if !isMounted(*quobyteMountPath) { - log.Printf("Mounting Quobyte namespace in %s", *quobyteMountPath) - mountAll(*quobyteMountOptions, *quobyteRegistry, *quobyteMountPath) + if !isMounted(quobyteMountPath) { + log.Printf("Mounting Quobyte namespace in %s", quobyteMountPath) + mountAll(quobyteMountOptions, quobyteRegistry, quobyteMountPath) } - qDriver := newQuobyteDriver(*quobyteAPIURL, *quobyteUser, *quobytePassword, *quobyteMountPath, *maxFSChecks, *maxWaitTime, *quobyteConfigName, *quobyteTenantId) + qDriver := newQuobyteDriver(quobyteAPIURL, quobyteAPIUser, quobyteAPIPassword, + quobyteMountPath, maxFSChecks, maxWaitTime, quobyteVolConfigName, quobyteTenantID) handler := volume.NewHandler(qDriver) - log.Println(handler.ServeUnix(*group, quobyteID)) + log.Println(handler.ServeUnix(socketGroup, quobyteID)) } diff --git a/quobyte_driver.go b/quobyte_driver.go index bf6553e..8aa2aa9 100644 --- a/quobyte_driver.go +++ b/quobyte_driver.go @@ -44,28 +44,20 @@ func (driver quobyteDriver) Create(request volume.Request) volume.Response { defer driver.m.Unlock() user, group := "root", "root" - configurationName := "BASE" + configurationName := driver.configName retryPolicy := "INTERACTIVE" - tenantID := "default" + tenantID := driver.tenantID if usr, ok := request.Options["user"]; ok { user = usr } - if grp, ok := request.Options["group"]; ok { group = grp } - if conf, ok := request.Options["configuration_name"]; ok { configurationName = conf } - if tenant, ok := request.Options["tenant_id"]; ok { - tenantID = tenant - } else { - return volume.Response{Err: "No tenant_id given, cannot create a new volume."} - } - if _, err := driver.client.CreateVolume(&quobyte_api.CreateVolumeRequest{ Name: request.Name, RootUserID: user, @@ -122,7 +114,7 @@ func (driver quobyteDriver) Remove(request volume.Request) volume.Response { driver.m.Lock() defer driver.m.Unlock() - if err := driver.client.DeleteVolumeByName(request.Name, ""); err != nil { + if err := driver.client.DeleteVolumeByName(request.Name, driver.tenantID); err != nil { log.Println(err) return volume.Response{Err: err.Error()} } diff --git a/systemd/docker-quobyte-plugin.service b/systemd/docker-quobyte-plugin.service index d58d6c7..17fa943 100644 --- a/systemd/docker-quobyte-plugin.service +++ b/systemd/docker-quobyte-plugin.service @@ -7,7 +7,7 @@ Requires=docker.service [Service] EnvironmentFile=/etc/quobyte/docker-quobyte.env -ExecStart=/usr/local/bin/docker-quobyte-plugin --user ${QUOBYTE_API_USER} --password ${QUOBYTE_API_PASSWORD} --api ${QUOBYTE_API_URL} --registry ${QUOBYTE_REGISTRY} --configuration_name ${QUOBYTE_CONFIGURATION_NAME} +ExecStart=/usr/local/bin/docker-quobyte-plugin [Install] WantedBy=multi-user.target diff --git a/systemd/docker-quobyte.env.sample b/systemd/docker-quobyte.env.sample index 43aca89..b121064 100644 --- a/systemd/docker-quobyte.env.sample +++ b/systemd/docker-quobyte.env.sample @@ -1,4 +1,16 @@ -QUOBYTE_API_USER=admin -QUOBYTE_API_PASSWORD=quobyte +# Maximum number of filesystem checks when a Volume is created before returning an error +MAX_FS_CHECKS=5 +# Maximum wait time for filesystem checks to complete when a Volume is created before returning an error +MAX_WAIT_TIME=30 +# Group to create the unix socket +SOCKET_GROUP=root QUOBYTE_API_URL=http://localhost:7860 +QUOBYTE_API_PASSWORD=quobyte +QUOBYTE_API_USER=admin +QUOBYTE_MOUNT_PATH=/run/docker/quobyte/mnt +QUOBYTE_MOUNT_OPTIONS=-o user_xattr QUOBYTE_REGISTRY=localhost:7861 +# ID of the Quobyte tenant in whose domain volumes are managed by this plugin +QUOBYTE_TENANT_ID=replace_me +# Default volume config for new volumes, can be overridden via --opt flag 'configuration_name' +QUOBYTE_VOLUME_CONFIG_NAME=BASE