forked from ubccr/iquota
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathonefs.go
153 lines (124 loc) · 3.33 KB
/
onefs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2015 iquota Authors. All rights reserved.
// Use of this source code is governed by a BSD style
// license that can be found in the LICENSE file.
// Package iquota provides a Go client for the Isilon OneFS API and command
// line tools for reporting SmartQuotas
package iquota
import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"regexp"
)
const (
SERVICE_PLATFORM = "platform"
SERVICE_NAMESPACE = "namespace"
RESOURCE_SESSION = "/session/1/session"
)
var (
isiSessionPattern = regexp.MustCompile(`^isisessid=([0-9a-zA-Z\-]+);`)
)
// OneFS Client
type Client struct {
host string
port int
session string
user string
passwd string
certPool *x509.CertPool
}
// OneFS API error
type IsiError struct {
Code string `json:"code"`
Message string `json:"message"`
}
func (e *IsiError) Error() string {
return fmt.Sprintf("OneFS API Error: %s - %s", e.Code, e.Message)
}
// Create new OneFS api client
func NewClient(host string, port int, user, passwd, cacert string) *Client {
c := &Client{host: host, port: port, user: user, passwd: passwd}
if c.port == 0 {
c.port = 8080
}
if len(c.host) == 0 {
c.host = "localhost"
}
pem, err := ioutil.ReadFile(cacert)
if err == nil {
c.certPool = x509.NewCertPool()
if !c.certPool.AppendCertsFromPEM(pem) {
c.certPool = nil
}
}
return c
}
// Return URL for OneFS api given a resource
func (c *Client) Url(resource string) string {
return fmt.Sprintf("https://%s:%d%s", c.host, c.port, resource)
}
// Return new http client
func (c *Client) httpClient() *http.Client {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
//TLSClientConfig: &tls.Config{RootCAs: c.certPool}}
client := &http.Client{Transport: tr}
return client
}
// Return new http get request
func (c *Client) getRequest(url string) (*http.Request, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", "application/json")
if len(c.session) > 0 {
req.Header.Set("Cookie", fmt.Sprintf("isisessid==%s", c.session))
} else if len(c.user) > 0 && len(c.passwd) > 0 {
req.SetBasicAuth(c.user, c.passwd)
}
return req, nil
}
// Authenticate to OneFS API and create a session for multiple requests over a
// period of time.
func (c *Client) NewSession() (string, error) {
apiUrl := c.Url(RESOURCE_SESSION)
payload := map[string]interface{}{
"username": c.user,
"password": c.passwd,
"services": []string{SERVICE_PLATFORM, SERVICE_NAMESPACE}}
b, err := json.Marshal(payload)
if err != nil {
return "", err
}
req, err := http.NewRequest("POST", apiUrl, bytes.NewBuffer(b))
req.Header.Set("Content-Type", "application/json")
client := c.httpClient()
res, err := client.Do(req)
if err != nil {
return "", err
}
defer res.Body.Close()
if res.StatusCode != 201 {
return "", fmt.Errorf("OneFS login failed with HTTP status code: %d", res.StatusCode)
}
cookie := res.Header.Get("Set-Cookie")
if len(cookie) == 0 {
return "", errors.New("OneFS login failed emtpy set-cookie header")
}
session := ""
matches := isiSessionPattern.FindStringSubmatch(cookie)
if len(matches) == 2 {
session = matches[1]
}
if len(session) == 0 {
return "", errors.New("OneFS login failed invalid set-cookie header")
}
c.session = session
return session, nil
}