Skip to content

Commit

Permalink
Merge pull request #9 from travisghansen/master
Browse files Browse the repository at this point in the history
support share ID vs lookup
  • Loading branch information
nmaupu authored Aug 22, 2018
2 parents c385f59 + 25234df commit fdc6145
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 65 deletions.
14 changes: 5 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ https://github.com/kubernetes-incubator/external-storage
# Usage
The scope of the provisioner allows for a single instance to service multiple
classes (and/or FreeNAS servers). The provisioner itself can be deployed into
the cluster or ran directly on a FreeNAS server.
the cluster or ran out of cluster, for example, directly on a FreeNAS server.

Each `StorageClass` should have a corresponding `Secret` created which contains
the credentials and host information used to communicate with with FreeNAS API.
Expand Down Expand Up @@ -44,18 +44,19 @@ kubectl apply -f deploy/rbac.yaml -f deploy/deployment.yaml
```

Alternatively, for advanced use-cases you may run the provisioner out of cluster
directly on the FreeNAS server. This is not currently recommended.
including directly on the FreeNAS server if desired. Running out of cluster is
not currently recommended.
```
./bin/freenas-provisioner-freebsd --kubeconfig=/path/to/kubeconfig.yaml
```

## Create `StorageClass` and `Secret`
All the necessary resources are available in the `deploy` folder. At a minimum
`secret.yaml` must be modified (remember to `base64` the values) to reflect the
server details. You may also want to review `class.yaml` to review available
server details. You may also want to read `class.yaml` to review available
`parameters` of the storage class. For instance to set the `datasetParentName`.
```
kubectl apply -f deploy/class.yaml -f deploy/secret.yaml
kubectl apply -f deploy/secret.yaml -f deploy/class.yaml
```

## Example usage
Expand Down Expand Up @@ -102,11 +103,6 @@ spec:
claimName: freenas-test-pvc
```

Create everything:
```
kubectl apply -f deploy/
```

The underlying dataset / NFS share should quickly be appearing up on FreeNAS
side. In case of issue, follow the provisioner's logs using:
```
Expand Down
15 changes: 13 additions & 2 deletions deploy/class.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,18 @@ parameters:
# if enabled provisioner will create parent datasets for each namespace
# otherwise, all datasets will be provisioned in a flat manner
# default: true
#datasetNamespaces:
#datasetEnableNamespaces:

# if datasetEnableNamespaces is enabled, sets a per-namespace quota
# example: 5M | 10G | 1T (M, Mi, MB, MiB, G, Gi, GB, GiB, T, Ti, TB, or TiB)
# default: 0 (no quota)
#datasetNamespaceQuota:

# if datasetEnableNamespaces is enabled, sets a per-namespace reservation
# this should not be greater than the datasetNamespaceQuota
# example: 5M | 10G | 1T (M, Mi, MB, MiB, G, Gi, GB, GiB, T, Ti, TB, or TiB)
# default: 0
#datasetNamespaceReservation:

# if enabled created datasets will adhere to reliable pattern
# if datasetNamespaces == true dataset pattern is: <datasetParentName>/<namespace>/<PVC Name>
Expand Down Expand Up @@ -84,7 +95,7 @@ parameters:

# Determines user mapping for all access (not recommended)
# cannot be used simultaneously with shareMaproot{User,Group}
# default: root:wheel
# default: ""
#shareMapalltUser:
#shareMapallGroup:

Expand Down
2 changes: 1 addition & 1 deletion deploy/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ rules:
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
verbs: ["get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
Expand Down
4 changes: 4 additions & 0 deletions deploy/secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ metadata:
type: Opaque
data:
# all values should be base64 encoded (ie: echo -n 'https' | base64)
#
# note that all values are relative to where the provisioner is running
# ie: if running the provisioner directly on the FreeNAS server 'localhost'
# would be a valid 'host' value

# http|https
# default: http
Expand Down
30 changes: 20 additions & 10 deletions freenas/dataset.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package freenas

import (
"encoding/json"
"errors"
"fmt"
"github.com/golang/glog"
"io/ioutil"
"path/filepath"
)

Expand All @@ -18,6 +18,8 @@ type Dataset struct {
Name string `json:"name"`
Pool string `json:"pool"`
Recordsize int64 `json:"recordsize,omitempty"`
Quota int64 `json:"quota,omitempty"`
Reservation int64 `json:"reservation,omitempty"`
Refquota int64 `json:"refquota,omitempty"`
Refreservation int64 `json:"refreservation,omitempty"`
Refer int64 `json:"refer,omitempty"`
Expand All @@ -37,6 +39,8 @@ func (d *Dataset) CopyFrom(source FreenasResource) error {
d.Name = src.Name
d.Pool = src.Pool
d.Recordsize = src.Recordsize
d.Quota = src.Quota
d.Reservation = src.Reservation
d.Refquota = src.Refquota
d.Refreservation = src.Refreservation
d.Refer = src.Refer
Expand All @@ -50,16 +54,17 @@ func (d *Dataset) CopyFrom(source FreenasResource) error {
func (d *Dataset) Get(server *FreenasServer) error {
endpoint := fmt.Sprintf("/api/v1.0/storage/dataset/%s/", d.Name)
var dataset Dataset
resp, err := server.getSlingConnection().Get(endpoint).ReceiveSuccess(&dataset)
var e interface{}
resp, err := server.getSlingConnection().Get(endpoint).Receive(&dataset, &e)
if err != nil {
glog.Warningln(err)
return err
}
defer resp.Body.Close()

if resp.StatusCode != 200 {
body, _ := ioutil.ReadAll(resp.Body)
return errors.New(fmt.Sprintf("Error getting dataset \"%s\" - message: %v, status: %d", d.Name, body, resp.StatusCode))
body, _ := json.Marshal(e)
return errors.New(fmt.Sprintf("Error getting dataset \"%s\" - message: %v, status: %d", d.Name, string(body), resp.StatusCode))
}

d.CopyFrom(&dataset)
Expand All @@ -70,11 +75,13 @@ func (d *Dataset) Get(server *FreenasServer) error {
func (d *Dataset) Create(server *FreenasServer) error {
parent, dsName := filepath.Split(d.Name)
endpoint := fmt.Sprintf("/api/v1.0/storage/dataset/%s", parent)
var dataset Dataset
var e interface{}

// rewrite Name attribute to support crazy api semantics
d.Name = dsName

resp, err := server.getSlingConnection().Post(endpoint).BodyJSON(d).Receive(nil, nil)
resp, err := server.getSlingConnection().Post(endpoint).BodyJSON(d).Receive(&dataset, &e)

// rewrite Name attribute to support crazy api semantics
d.Name = filepath.Join(parent, dsName)
Expand All @@ -86,25 +93,28 @@ func (d *Dataset) Create(server *FreenasServer) error {
defer resp.Body.Close()

if resp.StatusCode != 201 {
body, _ := ioutil.ReadAll(resp.Body)
return errors.New(fmt.Sprintf("Error creating dataset \"%s\" - message: %v, status: %d", d.Name, body, resp.StatusCode))
body, _ := json.Marshal(e)
return errors.New(fmt.Sprintf("Error creating dataset \"%s\" - message: %v, status: %d", d.Name, string(body), resp.StatusCode))
}

d.CopyFrom(&dataset)

return nil
}

func (d *Dataset) Delete(server *FreenasServer) error {
endpoint := fmt.Sprintf("/api/v1.0/storage/dataset/%s/", d.Name)
resp, err := server.getSlingConnection().Delete(endpoint).Receive(nil, nil)
var e interface{}
resp, err := server.getSlingConnection().Delete(endpoint).Receive(nil, &e)
if err != nil {
glog.Warningln(err)
return err
}
defer resp.Body.Close()

if resp.StatusCode != 204 {
body, _ := ioutil.ReadAll(resp.Body)
return errors.New(fmt.Sprintf("Error deleting dataset \"%s\" - %v", d.Name, body))
body, _ := json.Marshal(e)
return errors.New(fmt.Sprintf("Error deleting dataset \"%s\" - %v", d.Name, string(body)))
}

return nil
Expand Down
57 changes: 49 additions & 8 deletions freenas/nfs.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package freenas

import (
"encoding/json"
"errors"
"fmt"
"github.com/golang/glog"
"io/ioutil"
)

var (
Expand Down Expand Up @@ -49,15 +49,43 @@ func (n *NfsShare) CopyFrom(source FreenasResource) error {
}

func (n *NfsShare) Get(server *FreenasServer) error {
if n.Id > 0 {
endpoint := fmt.Sprintf("/api/v1.0/sharing/nfs/%d/", n.Id)
var nfs NfsShare
var e interface{}
resp, err := server.getSlingConnection().Get(endpoint).Receive(&nfs, &e)
if err != nil {
glog.Warningln(err)
return err
}
defer resp.Body.Close()

if resp.StatusCode != 200 {
body, _ := json.Marshal(e)
return errors.New(fmt.Sprintf("Error getting NFS share \"%s\" - message: %v, status: %d", n.Paths, string(body), resp.StatusCode))
}

n.CopyFrom(&nfs)

return nil
}

endpoint := "/api/v1.0/sharing/nfs/?limit=1000"
var shares []NfsShare
resp, err := server.getSlingConnection().Get(endpoint).ReceiveSuccess(&shares)
var e interface{}
resp, err := server.getSlingConnection().Get(endpoint).Receive(&shares, &e)

if err != nil {
glog.Warningln(err)
return nil
return err
}
defer resp.Body.Close()

if resp.StatusCode != 200 {
body, _ := json.Marshal(e)
return errors.New(fmt.Sprintf("Error getting NFS share \"%s\" - message: %v, status: %d", n.Paths, string(body), resp.StatusCode))
}

for _, share := range shares {
if share.contains(n.Paths[0]) {
n.CopyFrom(&share)
Expand All @@ -81,26 +109,39 @@ func (s *NfsShare) contains(path string) bool {

func (n *NfsShare) Create(server *FreenasServer) error {
endpoint := "/api/v1.0/sharing/nfs/"
resp, err := server.getSlingConnection().Post(endpoint).BodyJSON(n).Receive(nil, nil)
var nfs NfsShare
var e interface{}
resp, err := server.getSlingConnection().Post(endpoint).BodyJSON(n).Receive(&nfs, &e)
if err != nil {
glog.Warningln(err)
return err
}
defer resp.Body.Close()

if resp.StatusCode != 201 {
body, _ := ioutil.ReadAll(resp.Body)
return errors.New(fmt.Sprintf("Error creating NFS share for %+v - %v", *n, body))
body, _ := json.Marshal(e)
return errors.New(fmt.Sprintf("Error creating NFS share for %+v - %v", *n, string(body)))
}

n.CopyFrom(&nfs)

return nil
}

func (n *NfsShare) Delete(server *FreenasServer) error {
endpoint := fmt.Sprintf("/api/v1.0/sharing/nfs/%d/", n.Id)
_, err := server.getSlingConnection().Delete(endpoint).Receive(nil, nil)
var e interface{}
resp, err := server.getSlingConnection().Delete(endpoint).Receive(nil, &e)
if err != nil {
glog.Warningln(err)
return err
}
return err
defer resp.Body.Close()

if resp.StatusCode != 204 {
body, _ := json.Marshal(e)
return errors.New(fmt.Sprintf("Error deleting NFS share \"%s\" - %v", n.Paths, string(body)))
}

return nil
}
9 changes: 5 additions & 4 deletions freenas/permission.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package freenas

import (
"encoding/json"
"errors"
"fmt"
"github.com/golang/glog"
"io/ioutil"
)

type Permission struct {
Expand All @@ -17,16 +17,17 @@ type Permission struct {

func (p *Permission) Put(server *FreenasServer) error {
endpoint := "/api/v1.0/storage/permission/"
resp, err := server.getSlingConnection().Put(endpoint).BodyJSON(p).Receive(nil, nil)
var e interface{}
resp, err := server.getSlingConnection().Put(endpoint).BodyJSON(p).Receive(nil, &e)
if err != nil {
glog.Warningln(err)
return err
}
defer resp.Body.Close()

if resp.StatusCode != 201 {
body, _ := ioutil.ReadAll(resp.Body)
return errors.New(fmt.Sprintf("Error updating permission - message: %v, status: %d", body, resp.StatusCode))
body, _ := json.Marshal(e)
return errors.New(fmt.Sprintf("Error updating permission - message: %v, status: %d", string(body), resp.StatusCode))
}

return nil
Expand Down
6 changes: 4 additions & 2 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 0 additions & 23 deletions pod.yaml

This file was deleted.

Loading

0 comments on commit fdc6145

Please sign in to comment.