mirror of
https://github.com/oracle/zfssa-csi-driver.git
synced 2025-07-17 23:21:06 +00:00
Reload ZFSSA certificate and reset https client config when failed to verify certificate
This commit is contained in:
parent
0c8642ed58
commit
d4631059de
@ -6,11 +6,11 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/oracle/zfssa-csi-driver/pkg/utils"
|
|
||||||
"github.com/oracle/zfssa-csi-driver/pkg/zfssarest"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||||
|
"github.com/oracle/zfssa-csi-driver/pkg/utils"
|
||||||
|
"github.com/oracle/zfssa-csi-driver/pkg/zfssarest"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
@ -28,9 +28,9 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Default Log Level
|
// Default Log Level
|
||||||
DefaultLogLevel = "3"
|
DefaultLogLevel = "3"
|
||||||
DefaultCertPath = "/mnt/certs/zfssa.crt"
|
DefaultCertPath = "/mnt/certs/zfssa.crt"
|
||||||
DefaultCredPath = "/mnt/zfssa/zfssa.yaml"
|
DefaultCredPath = "/mnt/zfssa/zfssa.yaml"
|
||||||
DefaultConfigPath = "/mnt/config/config.yaml"
|
DefaultConfigPath = "/mnt/config/config.yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,15 +49,15 @@ type ZFSSADriver struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
Appliance string
|
Appliance string
|
||||||
User string
|
User string
|
||||||
endpoint string
|
endpoint string
|
||||||
HostIp string
|
HostIp string
|
||||||
NodeName string
|
NodeName string
|
||||||
PodIp string
|
PodIp string
|
||||||
Secure bool
|
Secure bool
|
||||||
logLevel string
|
logLevel string
|
||||||
Certificate []byte
|
Certificate []byte
|
||||||
CertLocation string
|
CertLocation string
|
||||||
CredLocation string
|
CredLocation string
|
||||||
}
|
}
|
||||||
@ -73,8 +73,8 @@ type accessType int
|
|||||||
// NonBlocking server
|
// NonBlocking server
|
||||||
|
|
||||||
type nonBlockingGRPCServer struct {
|
type nonBlockingGRPCServer struct {
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
server *grpc.Server
|
server *grpc.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -86,7 +86,7 @@ const (
|
|||||||
Tib int64 = Gib * 1024
|
Tib int64 = Gib * 1024
|
||||||
Tib100 int64 = Tib * 100
|
Tib100 int64 = Tib * 100
|
||||||
|
|
||||||
DefaultVolumeSizeBytes int64 = 50 * Gib
|
DefaultVolumeSizeBytes int64 = 50 * Gib
|
||||||
|
|
||||||
mountAccess accessType = iota
|
mountAccess accessType = iota
|
||||||
blockAccess
|
blockAccess
|
||||||
@ -94,7 +94,7 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
UsernamePattern string = `^[a-zA-Z][a-zA-Z0-9_\-\.]*$`
|
UsernamePattern string = `^[a-zA-Z][a-zA-Z0-9_\-\.]*$`
|
||||||
UsernameLength int = 255
|
UsernameLength int = 255
|
||||||
)
|
)
|
||||||
|
|
||||||
type ZfssaBlockVolume struct {
|
type ZfssaBlockVolume struct {
|
||||||
@ -122,7 +122,7 @@ func NewZFSSADriver(driverName, version string) (*ZFSSADriver, error) {
|
|||||||
|
|
||||||
utils.InitLogs(zd.config.logLevel, zd.name, version, zd.config.NodeName)
|
utils.InitLogs(zd.config.logLevel, zd.name, version, zd.config.NodeName)
|
||||||
|
|
||||||
err = zfssarest.InitREST(zd.config.Appliance, zd.config.Certificate, zd.config.Secure)
|
err = zfssarest.InitREST(zd.config.Appliance, zd.config.CertLocation, zd.config.Secure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -175,8 +175,8 @@ func getConfig(zd *ZFSSADriver) error {
|
|||||||
return errors.New(fmt.Sprintf("Cannot get ZFSSA username: %s", err))
|
return errors.New(fmt.Sprintf("Cannot get ZFSSA username: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get ZFSSA_TARGET from the mounted config file if available
|
// Get ZFSSA_TARGET from the mounted config file if available
|
||||||
zfssaHost, _ := utils.GetValueFromYAML(DefaultConfigPath,"ZFSSA_TARGET")
|
zfssaHost, _ := utils.GetValueFromYAML(DefaultConfigPath, "ZFSSA_TARGET")
|
||||||
appliance := getEnvFallback("ZFSSA_TARGET", zfssaHost)
|
appliance := getEnvFallback("ZFSSA_TARGET", zfssaHost)
|
||||||
zd.config.Appliance = strings.TrimSpace(appliance)
|
zd.config.Appliance = strings.TrimSpace(appliance)
|
||||||
if zd.config.Appliance == "not-set" {
|
if zd.config.Appliance == "not-set" {
|
||||||
@ -189,7 +189,7 @@ func getConfig(zd *ZFSSADriver) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
zd.config.endpoint = getEnvFallback("CSI_ENDPOINT", "")
|
zd.config.endpoint = getEnvFallback("CSI_ENDPOINT", "")
|
||||||
if zd.config.endpoint == "" {
|
if zd.config.endpoint == "" {
|
||||||
return errors.New("endpoint is required")
|
return errors.New("endpoint is required")
|
||||||
} else {
|
} else {
|
||||||
if !strings.HasPrefix(zd.config.endpoint, "unix://") {
|
if !strings.HasPrefix(zd.config.endpoint, "unix://") {
|
||||||
@ -204,8 +204,10 @@ func getConfig(zd *ZFSSADriver) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch strings.ToLower(strings.TrimSpace(getEnvFallback("ZFSSA_INSECURE", "False"))) {
|
switch strings.ToLower(strings.TrimSpace(getEnvFallback("ZFSSA_INSECURE", "False"))) {
|
||||||
case "true": zd.config.Secure = false
|
case "true":
|
||||||
case "false": zd.config.Secure = true
|
zd.config.Secure = false
|
||||||
|
case "false":
|
||||||
|
zd.config.Secure = true
|
||||||
default:
|
default:
|
||||||
return errors.New("ZFSSA_INSECURE value is invalid")
|
return errors.New("ZFSSA_INSECURE value is invalid")
|
||||||
}
|
}
|
||||||
@ -219,6 +221,7 @@ func getConfig(zd *ZFSSADriver) error {
|
|||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return errors.New("certificate does not exits")
|
return errors.New("certificate does not exits")
|
||||||
}
|
}
|
||||||
|
zd.config.CertLocation = certfile
|
||||||
zd.config.Certificate, err = ioutil.ReadFile(certfile)
|
zd.config.Certificate, err = ioutil.ReadFile(certfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to read certificate")
|
return errors.New("failed to read certificate")
|
||||||
@ -238,7 +241,7 @@ func getConfig(zd *ZFSSADriver) error {
|
|||||||
// Starts the CSI driver. This includes registering the different servers (Identity, Controller and Node) with
|
// Starts the CSI driver. This includes registering the different servers (Identity, Controller and Node) with
|
||||||
// the CSI framework and starting listening on the UNIX socket.
|
// the CSI framework and starting listening on the UNIX socket.
|
||||||
|
|
||||||
var sigList = []os.Signal {
|
var sigList = []os.Signal{
|
||||||
syscall.SIGTERM,
|
syscall.SIGTERM,
|
||||||
syscall.SIGHUP,
|
syscall.SIGHUP,
|
||||||
syscall.SIGINT,
|
syscall.SIGINT,
|
||||||
@ -344,7 +347,7 @@ func (s *nonBlockingGRPCServer) serve(endpoint string,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := []grpc.ServerOption{ grpc.UnaryInterceptor(interceptorGRPC) }
|
opts := []grpc.ServerOption{grpc.UnaryInterceptor(interceptorGRPC)}
|
||||||
|
|
||||||
server := grpc.NewServer(opts...)
|
server := grpc.NewServer(opts...)
|
||||||
s.server = server
|
s.server = server
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -25,35 +26,35 @@ import (
|
|||||||
|
|
||||||
// Use RESTapi v2 as it returns scriptable and consistent values
|
// Use RESTapi v2 as it returns scriptable and consistent values
|
||||||
const (
|
const (
|
||||||
zAppliance string = "https://%s:215"
|
zAppliance string = "https://%s:215"
|
||||||
zServices = zAppliance + "/api/access/v2"
|
zServices = zAppliance + "/api/access/v2"
|
||||||
zStorage = zAppliance + "/api/storage/v2"
|
zStorage = zAppliance + "/api/storage/v2"
|
||||||
zSan = zAppliance + "/api/san/v2"
|
zSan = zAppliance + "/api/san/v2"
|
||||||
zPools = zStorage + "/pools"
|
zPools = zStorage + "/pools"
|
||||||
zPool = zPools + "/%s"
|
zPool = zPools + "/%s"
|
||||||
zAllProjects = zStorage + "/projects"
|
zAllProjects = zStorage + "/projects"
|
||||||
zProjects = zPool + "/projects"
|
zProjects = zPool + "/projects"
|
||||||
zProject = zProjects + "/%s"
|
zProject = zProjects + "/%s"
|
||||||
zAllFilesystems = zStorage + "/filesystems"
|
zAllFilesystems = zStorage + "/filesystems"
|
||||||
zFilesystems = zProject + "/filesystems"
|
zFilesystems = zProject + "/filesystems"
|
||||||
zFilesystem = zFilesystems + "/%s"
|
zFilesystem = zFilesystems + "/%s"
|
||||||
zAllLUNs = zStorage + "/luns"
|
zAllLUNs = zStorage + "/luns"
|
||||||
zLUNs = zProject + "/luns"
|
zLUNs = zProject + "/luns"
|
||||||
zLUN = zLUNs + "/%s"
|
zLUN = zLUNs + "/%s"
|
||||||
zAllSnapshots = zStorage + "/snapshots"
|
zAllSnapshots = zStorage + "/snapshots"
|
||||||
zSnapshots = zProject + "/snapshots"
|
zSnapshots = zProject + "/snapshots"
|
||||||
zSnapshot = zSnapshots + "/%s"
|
zSnapshot = zSnapshots + "/%s"
|
||||||
zFilesystemSnapshots = zFilesystem + "/snapshots"
|
zFilesystemSnapshots = zFilesystem + "/snapshots"
|
||||||
zFilesystemSnapshot = zFilesystemSnapshots + "/%s"
|
zFilesystemSnapshot = zFilesystemSnapshots + "/%s"
|
||||||
zCloneFilesystemSnapshot = zFilesystemSnapshot + "/clone"
|
zCloneFilesystemSnapshot = zFilesystemSnapshot + "/clone"
|
||||||
zLUNSnapshots = zLUN + "/snapshots"
|
zLUNSnapshots = zLUN + "/snapshots"
|
||||||
zLUNSnapshot = zLUNSnapshots + "/%s"
|
zLUNSnapshot = zLUNSnapshots + "/%s"
|
||||||
zFilesystemDependents = zFilesystemSnapshot + "/dependents"
|
zFilesystemDependents = zFilesystemSnapshot + "/dependents"
|
||||||
zLUNDependents = zLUNSnapshot + "/dependents"
|
zLUNDependents = zLUNSnapshot + "/dependents"
|
||||||
zTargetGroups = zSan + "/%s/target-groups"
|
zTargetGroups = zSan + "/%s/target-groups"
|
||||||
zTargetGroup = zTargetGroups + "/%s"
|
zTargetGroup = zTargetGroups + "/%s"
|
||||||
zProperties = zAppliance + "/api/storage/v2/schema"
|
zProperties = zAppliance + "/api/storage/v2/schema"
|
||||||
zProperty = zProperties + "/%s"
|
zProperty = zProperties + "/%s"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -63,68 +64,88 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Token struct {
|
type Token struct {
|
||||||
Name string
|
Name string
|
||||||
cv *sync.Cond
|
cv *sync.Cond
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
user string
|
user string
|
||||||
password string
|
password string
|
||||||
state int
|
state int
|
||||||
xAuthSession string
|
xAuthSession string
|
||||||
xAuthName string
|
xAuthName string
|
||||||
}
|
}
|
||||||
|
|
||||||
type tokenList struct {
|
type tokenList struct {
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
list map[string]*Token
|
list map[string]*Token
|
||||||
}
|
}
|
||||||
|
|
||||||
type faultInfo struct {
|
type faultInfo struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
Name string `json:"Name"`
|
Name string `json:"Name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type faultResponse struct {
|
type faultResponse struct {
|
||||||
Fault faultInfo `json:"fault"`
|
Fault faultInfo `json:"fault"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var httpTransport = http.Transport{TLSClientConfig: &tls.Config{}}
|
var httpTransport = http.Transport{TLSClientConfig: &tls.Config{}}
|
||||||
var httpClient = &http.Client{Transport: &httpTransport}
|
var httpClient = &http.Client{Transport: &httpTransport}
|
||||||
var zServicesURL string
|
var zServicesURL string
|
||||||
var zName string
|
var zName string
|
||||||
var tokens tokenList
|
var tokens tokenList
|
||||||
|
var zfssaCertLocation string
|
||||||
|
|
||||||
// Initializes the ZFSSA REST API interface
|
// Initializes the ZFSSA REST API interface
|
||||||
//
|
func InitREST(name string, certLocation string, secure bool) error {
|
||||||
func InitREST(name string, certs []byte, secure bool) error {
|
|
||||||
|
|
||||||
if secure {
|
|
||||||
// set TLSv1.2 for the minimum version of supporting TLS
|
|
||||||
httpTransport.TLSClientConfig.MinVersion = tls.VersionTLS12
|
|
||||||
|
|
||||||
// Get the SystemCertPool, continue with an empty pool on error
|
|
||||||
httpTransport.TLSClientConfig.RootCAs, _ = x509.SystemCertPool()
|
|
||||||
if httpTransport.TLSClientConfig.RootCAs == nil {
|
|
||||||
httpTransport.TLSClientConfig.RootCAs = x509.NewCertPool()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok := httpTransport.TLSClientConfig.RootCAs.AppendCertsFromPEM(certs); !ok {
|
|
||||||
return errors.New("failed to append the certificate")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
httpTransport.TLSClientConfig.InsecureSkipVerify = !secure
|
httpTransport.TLSClientConfig.InsecureSkipVerify = !secure
|
||||||
httpTransport.MaxConnsPerHost = 16
|
httpTransport.MaxConnsPerHost = 16
|
||||||
httpTransport.MaxIdleConnsPerHost = 16
|
httpTransport.MaxIdleConnsPerHost = 16
|
||||||
httpTransport.IdleConnTimeout = 30 * time.Second
|
httpTransport.IdleConnTimeout = 30 * time.Second
|
||||||
|
|
||||||
tokens.list = make(map[string]*Token)
|
zfssaCertLocation = certLocation
|
||||||
|
|
||||||
|
err := resetHttpTlsClient(nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
zServicesURL = fmt.Sprintf(zServices, name)
|
zServicesURL = fmt.Sprintf(zServices, name)
|
||||||
zName = name
|
zName = name
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resetHttpTlsClient(ctx context.Context) error {
|
||||||
|
if httpTransport.TLSClientConfig.InsecureSkipVerify {
|
||||||
|
utils.GetLogREST(ctx, 2).Println("resetHttpTransport skipped")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// set TLSv1.2 for the minimum version of supporting TLS
|
||||||
|
httpTransport.TLSClientConfig.MinVersion = tls.VersionTLS12
|
||||||
|
|
||||||
|
// Get the SystemCertPool, continue with an empty pool on error
|
||||||
|
utils.GetLogREST(ctx, 2).Println("loading RootCAs")
|
||||||
|
httpTransport.TLSClientConfig.RootCAs, _ = x509.SystemCertPool()
|
||||||
|
if httpTransport.TLSClientConfig.RootCAs == nil {
|
||||||
|
httpTransport.TLSClientConfig.RootCAs = x509.NewCertPool()
|
||||||
|
}
|
||||||
|
|
||||||
|
certs, err := ioutil.ReadFile(zfssaCertLocation)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("failed to read ZFSSA certificate")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok := httpTransport.TLSClientConfig.RootCAs.AppendCertsFromPEM(certs); !ok {
|
||||||
|
return errors.New("failed to append the certificate")
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens.list = make(map[string]*Token)
|
||||||
|
utils.GetLogREST(ctx, 5).Println("resetHttpTransport done")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Looks up a token context based on the user name passed in. If one doesn't exist
|
// Looks up a token context based on the user name passed in. If one doesn't exist
|
||||||
// yet, it is created.
|
// yet, it is created.
|
||||||
func LookUpToken(ctx context.Context, user, password string) *Token {
|
func LookUpToken(ctx context.Context, user, password string) *Token {
|
||||||
@ -160,14 +181,14 @@ func LookUpToken(ctx context.Context, user, password string) *Token {
|
|||||||
//
|
//
|
||||||
// The possible return values are:
|
// The possible return values are:
|
||||||
//
|
//
|
||||||
// Code Message X-Auth-Session
|
// Code Message X-Auth-Session
|
||||||
//
|
//
|
||||||
// nil Valid
|
// nil Valid
|
||||||
// codes.Internal "Failure getting token" ""
|
// codes.Internal "Failure getting token" ""
|
||||||
// codes.Internal "Failure creating token" ""
|
// codes.Internal "Failure creating token" ""
|
||||||
//
|
//
|
||||||
// In case of failure, the message logged will provide more information
|
// In case of failure, the message logged will provide more information
|
||||||
// as to where the problem occurred.
|
// as to where the problem occurred.
|
||||||
func getToken(ctx context.Context, token *Token, previous *string) (string, error) {
|
func getToken(ctx context.Context, token *Token, previous *string) (string, error) {
|
||||||
|
|
||||||
token.mtx.Lock()
|
token.mtx.Lock()
|
||||||
@ -223,7 +244,7 @@ func createZfssaSession(ctx context.Context, token *Token) (string, string, erro
|
|||||||
|
|
||||||
httpReq, err := http.NewRequest("POST", zServicesURL, bytes.NewBuffer(nil))
|
httpReq, err := http.NewRequest("POST", zServicesURL, bytes.NewBuffer(nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GetLogREST(ctx,2).Println("Could not build a request to create a token",
|
utils.GetLogREST(ctx, 2).Println("Could not build a request to create a token",
|
||||||
"method", "POST", "url", zServicesURL, "error", err.Error())
|
"method", "POST", "url", zServicesURL, "error", err.Error())
|
||||||
return "", "", grpcStatus.Error(codes.Internal, "Failure creating token")
|
return "", "", grpcStatus.Error(codes.Internal, "Failure creating token")
|
||||||
}
|
}
|
||||||
@ -233,15 +254,18 @@ func createZfssaSession(ctx context.Context, token *Token) (string, string, erro
|
|||||||
|
|
||||||
httpRsp, err := httpClient.Do(httpReq)
|
httpRsp, err := httpClient.Do(httpReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GetLogREST(ctx,2).Println("Token creation failed in Do",
|
utils.GetLogREST(ctx, 2).Println("Token creation failed in Do",
|
||||||
"url", zServicesURL, "error", err.Error())
|
"url", zServicesURL, "error", err.Error())
|
||||||
|
if strings.Contains(err.Error(), "failed to verify certificate") {
|
||||||
|
resetHttpTlsClient(ctx)
|
||||||
|
}
|
||||||
return "", "", grpcStatus.Error(codes.Internal, "Failure creating token")
|
return "", "", grpcStatus.Error(codes.Internal, "Failure creating token")
|
||||||
}
|
}
|
||||||
|
|
||||||
defer httpRsp.Body.Close()
|
defer httpRsp.Body.Close()
|
||||||
|
|
||||||
if httpRsp.StatusCode != http.StatusCreated {
|
if httpRsp.StatusCode != http.StatusCreated {
|
||||||
utils.GetLogREST(ctx,2).Println("Token creation failed in ZFSSA",
|
utils.GetLogREST(ctx, 2).Println("Token creation failed in ZFSSA",
|
||||||
"url", zServicesURL, "StatusCode", httpRsp.StatusCode)
|
"url", zServicesURL, "StatusCode", httpRsp.StatusCode)
|
||||||
return "", "", grpcStatus.Error(codes.Internal, "Failure creating token")
|
return "", "", grpcStatus.Error(codes.Internal, "Failure creating token")
|
||||||
}
|
}
|
||||||
@ -264,7 +288,7 @@ func MakeRequest(ctx context.Context, token *Token, method, url string, reqbody
|
|||||||
func makeRequest(ctx context.Context, token *Token, method, url string, reqbody interface{}, status int,
|
func makeRequest(ctx context.Context, token *Token, method, url string, reqbody interface{}, status int,
|
||||||
rspbody interface{}) (interface{}, int, error) {
|
rspbody interface{}) (interface{}, int, error) {
|
||||||
|
|
||||||
utils.GetLogREST(ctx,5).Println("MakeRequest to ZFSSA",
|
utils.GetLogREST(ctx, 5).Println("MakeRequest to ZFSSA",
|
||||||
"method", method, "url", url, "body", reqbody)
|
"method", method, "url", url, "body", reqbody)
|
||||||
|
|
||||||
xAuthSession, err := getToken(ctx, token, nil)
|
xAuthSession, err := getToken(ctx, token, nil)
|
||||||
@ -274,14 +298,14 @@ func makeRequest(ctx context.Context, token *Token, method, url string, reqbody
|
|||||||
|
|
||||||
reqjson, err := json.Marshal(reqbody)
|
reqjson, err := json.Marshal(reqbody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GetLogREST(ctx,2).Println("json.Marshal call failed",
|
utils.GetLogREST(ctx, 2).Println("json.Marshal call failed",
|
||||||
"method", method, "url", url, "body", reqbody, "error", err.Error())
|
"method", method, "url", url, "body", reqbody, "error", err.Error())
|
||||||
return nil, 0, grpcStatus.Error(codes.Unknown, "json.Marshal call failed")
|
return nil, 0, grpcStatus.Error(codes.Unknown, "json.Marshal call failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
reqhttp, err := http.NewRequest(method, url, bytes.NewBuffer(reqjson))
|
reqhttp, err := http.NewRequest(method, url, bytes.NewBuffer(reqjson))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GetLogREST(ctx,2).Println("http.NewRequest call failed",
|
utils.GetLogREST(ctx, 2).Println("http.NewRequest call failed",
|
||||||
"method", method, "url", url, "body", reqbody, "error", err.Error())
|
"method", method, "url", url, "body", reqbody, "error", err.Error())
|
||||||
return nil, 0, grpcStatus.Error(codes.Unknown, "http.NewRequest call failed")
|
return nil, 0, grpcStatus.Error(codes.Unknown, "http.NewRequest call failed")
|
||||||
}
|
}
|
||||||
@ -292,8 +316,15 @@ func makeRequest(ctx context.Context, token *Token, method, url string, reqbody
|
|||||||
|
|
||||||
rsphttp, err := httpClient.Do(reqhttp)
|
rsphttp, err := httpClient.Do(reqhttp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GetLogREST(ctx,2).Println("client.do call failed",
|
utils.GetLogREST(ctx, 2).Println("client.do call failed",
|
||||||
"method", method, "url", url, "error", err.Error())
|
"method", method, "url", url, "error", err.Error())
|
||||||
|
if strings.Contains(err.Error(), "failed to verify certificate") {
|
||||||
|
utils.GetLogREST(ctx, 2).Println("mark token as invalid")
|
||||||
|
token.state = zfssaTokenInvalid
|
||||||
|
resetHttpTlsClient(ctx)
|
||||||
|
|
||||||
|
return nil, http.StatusUnauthorized, err
|
||||||
|
}
|
||||||
return nil, 0, grpcStatus.Error(codes.Unknown, "client.do call failed")
|
return nil, 0, grpcStatus.Error(codes.Unknown, "client.do call failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,23 +337,23 @@ func makeRequest(ctx context.Context, token *Token, method, url string, reqbody
|
|||||||
// read json http response
|
// read json http response
|
||||||
rspjson, err := ioutil.ReadAll(rsphttp.Body)
|
rspjson, err := ioutil.ReadAll(rsphttp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GetLogREST(ctx,2).Println("ioutil.ReadAll call failed",
|
utils.GetLogREST(ctx, 2).Println("ioutil.ReadAll call failed",
|
||||||
"method", method, "url", url, "code", rsphttp.StatusCode,
|
"method", method, "url", url, "code", rsphttp.StatusCode,
|
||||||
"status", rsphttp.Status, "error", err.Error())
|
"status", rsphttp.Status, "error", err.Error())
|
||||||
return nil, rsphttp.StatusCode, grpcStatus.Error(codes.Unknown,"ioutil.ReadAll call failed")
|
return nil, rsphttp.StatusCode, grpcStatus.Error(codes.Unknown, "ioutil.ReadAll call failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
if rsphttp.StatusCode == status {
|
if rsphttp.StatusCode == status {
|
||||||
if rspbody != nil {
|
if rspbody != nil {
|
||||||
err = json.Unmarshal(rspjson, rspbody)
|
err = json.Unmarshal(rspjson, rspbody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GetLogREST(ctx,2).Println("json.Unmarshal call failed",
|
utils.GetLogREST(ctx, 2).Println("json.Unmarshal call failed",
|
||||||
"\nmethod", method, "\nurl", url, "\ncode", rsphttp.StatusCode,
|
"\nmethod", method, "\nurl", url, "\ncode", rsphttp.StatusCode,
|
||||||
"\nstatus", rsphttp.Status, "\nbody", rspjson, "\nerror", err)
|
"\nstatus", rsphttp.Status, "\nbody", rspjson, "\nerror", err)
|
||||||
return nil, rsphttp.StatusCode, grpcStatus.Error(codes.Unknown, "json.Unmarshal call failed")
|
return nil, rsphttp.StatusCode, grpcStatus.Error(codes.Unknown, "json.Unmarshal call failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
utils.GetLogREST(ctx,5).Println("Successful response from ZFSSA",
|
utils.GetLogREST(ctx, 5).Println("Successful response from ZFSSA",
|
||||||
"method", method, "url", url, "result", rsphttp.StatusCode)
|
"method", method, "url", url, "result", rsphttp.StatusCode)
|
||||||
return rspbody, rsphttp.StatusCode, nil
|
return rspbody, rsphttp.StatusCode, nil
|
||||||
}
|
}
|
||||||
@ -335,7 +366,7 @@ func makeRequest(ctx context.Context, token *Token, method, url string, reqbody
|
|||||||
}
|
}
|
||||||
|
|
||||||
// status code was not what the user expected, attempt to unpack
|
// status code was not what the user expected, attempt to unpack
|
||||||
utils.GetLogREST(ctx,2).Println("MakeRequest to ZFSSA resulted in an unexpected status",
|
utils.GetLogREST(ctx, 2).Println("MakeRequest to ZFSSA resulted in an unexpected status",
|
||||||
"method", method, "url", url, "expected", status, "code", rsphttp.StatusCode,
|
"method", method, "url", url, "expected", status, "code", rsphttp.StatusCode,
|
||||||
"status", rsphttp.Status)
|
"status", rsphttp.Status)
|
||||||
|
|
||||||
@ -343,7 +374,7 @@ func makeRequest(ctx context.Context, token *Token, method, url string, reqbody
|
|||||||
err = json.Unmarshal(rspjson, failure)
|
err = json.Unmarshal(rspjson, failure)
|
||||||
var responseString string
|
var responseString string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GetLogREST(ctx,2).Println("Failure from ZFSSA could not be un-marshalled",
|
utils.GetLogREST(ctx, 2).Println("Failure from ZFSSA could not be un-marshalled",
|
||||||
"method", method, "url", url, "code", rsphttp.StatusCode,
|
"method", method, "url", url, "code", rsphttp.StatusCode,
|
||||||
"status", rsphttp.Status, "body", rspjson)
|
"status", rsphttp.Status, "body", rspjson)
|
||||||
responseString = string(rspjson)
|
responseString = string(rspjson)
|
||||||
@ -353,7 +384,7 @@ func makeRequest(ctx context.Context, token *Token, method, url string, reqbody
|
|||||||
|
|
||||||
switch rsphttp.StatusCode {
|
switch rsphttp.StatusCode {
|
||||||
case http.StatusNotFound:
|
case http.StatusNotFound:
|
||||||
err = grpcStatus.Errorf(codes.NotFound, "Resource not found on target appliance: %s", responseString)
|
err = grpcStatus.Errorf(codes.NotFound, "Resource not found on target appliance: %s", responseString)
|
||||||
default:
|
default:
|
||||||
err = grpcStatus.Errorf(codes.Unknown, "Unknown Error Occurred on target appliance: %s", responseString)
|
err = grpcStatus.Errorf(codes.Unknown, "Unknown Error Occurred on target appliance: %s", responseString)
|
||||||
}
|
}
|
||||||
@ -366,9 +397,9 @@ type services struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
URI string `json:"uri"`
|
URI string `json:"uri"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetServices(ctx context.Context, token *Token) (*[]Service, error) {
|
func GetServices(ctx context.Context, token *Token) (*[]Service, error) {
|
||||||
@ -386,22 +417,20 @@ func GetServices(ctx context.Context, token *Token) (*[]Service, error) {
|
|||||||
// Unmarshalling of a "List" structure. This structure is the ZFSSA response to
|
// Unmarshalling of a "List" structure. This structure is the ZFSSA response to
|
||||||
// the http request:
|
// the http request:
|
||||||
//
|
//
|
||||||
// GET /api/access/v1 HTTP/1.1
|
// GET /api/access/v1 HTTP/1.1
|
||||||
// Host: zfs-storage.example.com
|
// Host: zfs-storage.example.com
|
||||||
// X-Auth-User: admin
|
// X-Auth-User: admin
|
||||||
// X-Auth-Key: password
|
// X-Auth-Key: password
|
||||||
//
|
|
||||||
func (l *services) UnmarshalJSON(b []byte) error {
|
func (l *services) UnmarshalJSON(b []byte) error {
|
||||||
return zfssaUnmarshalList(b, &l.List)
|
return zfssaUnmarshalList(b, &l.List)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshalling of a List sent by the ZFSSA
|
// Unmarshalling of a List sent by the ZFSSA
|
||||||
//
|
|
||||||
func zfssaUnmarshalList(b []byte, l interface{}) error {
|
func zfssaUnmarshalList(b []byte, l interface{}) error {
|
||||||
|
|
||||||
// 'b' starts and ends like this:
|
// 'b' starts and ends like this:
|
||||||
// {List:[{...},...,{...}]}
|
// {List:[{...},...,{...}]}
|
||||||
b = b[0:len(b) - 1]
|
b = b[0 : len(b)-1]
|
||||||
for i := 1; i < len(b); i++ {
|
for i := 1; i < len(b); i++ {
|
||||||
if b[i] == '[' {
|
if b[i] == '[' {
|
||||||
b = b[i:]
|
b = b[i:]
|
||||||
|
Loading…
Reference in New Issue
Block a user