mirror of https://github.com/minio/minio.git
splitNetPath: Add support for windows paths including volumeNames e.g ip:C:\network\path
This commit is contained in:
parent
0bce3d6d63
commit
7c7eb1475d
|
@ -56,18 +56,21 @@ func fsHouseKeeping(storageDisk StorageAPI) error {
|
|||
// Check if a network path is local to this node.
|
||||
func isLocalStorage(networkPath string) bool {
|
||||
if idx := strings.LastIndex(networkPath, ":"); idx != -1 {
|
||||
// e.g 10.0.0.1:9000:/mnt/networkPath
|
||||
netAddr, _ := splitNetPath(networkPath)
|
||||
var netHost string
|
||||
var err error
|
||||
netHost, _, err = net.SplitHostPort(netAddr)
|
||||
// e.g 10.0.0.1:/mnt/networkPath
|
||||
netAddr, _, err := splitNetPath(networkPath)
|
||||
if err != nil {
|
||||
netHost = netAddr
|
||||
errorIf(err, "Splitting into ip and path failed")
|
||||
return false
|
||||
}
|
||||
// netAddr will only be set if this is not a local path.
|
||||
if netAddr == "" {
|
||||
return true
|
||||
}
|
||||
// Resolve host to address to check if the IP is loopback.
|
||||
// If address resolution fails, assume it's a non-local host.
|
||||
addrs, err := net.LookupHost(netHost)
|
||||
addrs, err := net.LookupHost(netAddr)
|
||||
if err != nil {
|
||||
errorIf(err, "Failed to lookup host")
|
||||
return false
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
|
@ -77,12 +80,14 @@ func isLocalStorage(networkPath string) bool {
|
|||
}
|
||||
iaddrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
errorIf(err, "Unable to list interface addresses")
|
||||
return false
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
for _, iaddr := range iaddrs {
|
||||
ip, _, err := net.ParseCIDR(iaddr.String())
|
||||
if err != nil {
|
||||
errorIf(err, "Unable to parse CIDR")
|
||||
return false
|
||||
}
|
||||
if ip.String() == addr {
|
||||
|
|
|
@ -36,14 +36,6 @@ const (
|
|||
storageRPCPath = reservedBucket + "/storage"
|
||||
)
|
||||
|
||||
// splits network path into its components Address and Path.
|
||||
func splitNetPath(networkPath string) (netAddr, netPath string) {
|
||||
index := strings.LastIndex(networkPath, ":")
|
||||
netAddr = networkPath[:index]
|
||||
netPath = networkPath[index+1:]
|
||||
return netAddr, netPath
|
||||
}
|
||||
|
||||
// Converts rpc.ServerError to underlying error. This function is
|
||||
// written so that the storageAPI errors are consistent across network
|
||||
// disks as well.
|
||||
|
@ -111,7 +103,10 @@ func newRPCClient(networkPath string) (StorageAPI, error) {
|
|||
}
|
||||
|
||||
// TODO validate netAddr and netPath.
|
||||
netAddr, netPath := splitNetPath(networkPath)
|
||||
netAddr, netPath, err := splitNetPath(networkPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Dial minio rpc storage http path.
|
||||
rpcPath := path.Join(storageRPCPath, netPath)
|
||||
|
|
25
cmd/utils.go
25
cmd/utils.go
|
@ -21,9 +21,12 @@ import (
|
|||
"encoding/xml"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
@ -43,6 +46,28 @@ func cloneHeader(h http.Header) http.Header {
|
|||
return h2
|
||||
}
|
||||
|
||||
// splits network path into its components Address and Path.
|
||||
func splitNetPath(networkPath string) (netAddr, netPath string, err error) {
|
||||
if runtime.GOOS == "windows" {
|
||||
if volumeName := filepath.VolumeName(networkPath); volumeName != "" {
|
||||
return "", networkPath, nil
|
||||
}
|
||||
}
|
||||
networkParts := strings.SplitN(networkPath, ":", 2)
|
||||
switch len(networkParts) {
|
||||
case 1:
|
||||
return "", networkPath, nil
|
||||
case 2:
|
||||
if networkParts[1] == "" {
|
||||
return "", "", &net.AddrError{Err: "missing path in network path", Addr: networkPath}
|
||||
} else if networkParts[0] == "" {
|
||||
return "", "", &net.AddrError{Err: "missing address in network path", Addr: networkPath}
|
||||
}
|
||||
return networkParts[0], networkParts[1], nil
|
||||
}
|
||||
return networkParts[0], networkParts[1], nil
|
||||
}
|
||||
|
||||
// xmlDecoder provide decoded value in xml.
|
||||
func xmlDecoder(body io.Reader, v interface{}, size int64) error {
|
||||
var lbody io.Reader
|
||||
|
|
|
@ -43,6 +43,10 @@ func newClient(node, rpcPath string) *RPCClient {
|
|||
func (rpcClient *RPCClient) Close() error {
|
||||
rpcClient.Lock()
|
||||
defer rpcClient.Unlock()
|
||||
// If rpc client has not connected yet there is nothing to close.
|
||||
if rpcClient.rpc == nil {
|
||||
return nil
|
||||
}
|
||||
// Reset rpcClient.rpc to allow for subsequent calls to use a new
|
||||
// (socket) connection.
|
||||
clnt := rpcClient.rpc
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test for splitNetPath
|
||||
func TestSplitNetPath(t *testing.T) {
|
||||
testCases := []struct {
|
||||
networkPath string
|
||||
netAddr string
|
||||
netPath string
|
||||
err error
|
||||
}{
|
||||
{"10.1.10.1:", "", "", &net.AddrError{Err: "missing path in network path", Addr: "10.1.10.1:"}},
|
||||
{"10.1.10.1", "", "10.1.10.1", nil},
|
||||
{"10.1.10.1://", "10.1.10.1", "//", nil},
|
||||
{"10.1.10.1:/disk/1", "10.1.10.1", "/disk/1", nil},
|
||||
{"10.1.10.1:\\path\\test", "10.1.10.1", "\\path\\test", nil},
|
||||
}
|
||||
|
||||
for i, test := range testCases {
|
||||
receivedAddr, receivedPath, receivedErr := splitNetPath(test.networkPath)
|
||||
if receivedAddr != test.netAddr {
|
||||
t.Errorf("Test case %d: Expected: %s, Received: %s", i+1, test.netAddr, receivedAddr)
|
||||
}
|
||||
if receivedPath != test.netPath {
|
||||
t.Errorf("Test case %d: Expected: %s, Received: %s", i+1, test.netPath, receivedPath)
|
||||
}
|
||||
if test.err != nil {
|
||||
if receivedErr == nil || receivedErr.Error() != test.err.Error() {
|
||||
t.Errorf("Test case %d: Expected: %v, Received: %v", i+1, test.err, receivedErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
// +build windows
|
||||
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test for splitNetPath
|
||||
func TestSplitNetPath(t *testing.T) {
|
||||
testCases := []struct {
|
||||
networkPath string
|
||||
netAddr string
|
||||
netPath string
|
||||
err error
|
||||
}{
|
||||
{"10.1.10.1:C:\\path\\test", "10.1.10.1", "C:\\path\\test", nil},
|
||||
{"10.1.10.1:C:", "10.1.10.1", "C:", nil},
|
||||
{":C:", "", "", &net.AddrError{Err: "missing address in network path", Addr: ":C:"}},
|
||||
{"C:\\path\\test", "", "C:\\path\\test", nil},
|
||||
{"10.1.10.1::C:\\path\\test", "10.1.10.1", ":C:\\path\\test", nil},
|
||||
}
|
||||
|
||||
for i, test := range testCases {
|
||||
receivedAddr, receivedPath, receivedErr := splitNetPath(test.networkPath)
|
||||
if receivedAddr != test.netAddr {
|
||||
t.Errorf("Test case %d: Expected: %s, Received: %s", i+1, test.netAddr, receivedAddr)
|
||||
}
|
||||
if receivedPath != test.netPath {
|
||||
t.Errorf("Test case %d: Expected: %s, Received: %s", i+1, test.netPath, receivedPath)
|
||||
}
|
||||
if test.err != nil {
|
||||
if receivedErr == nil || receivedErr.Error() != test.err.Error() {
|
||||
t.Errorf("Test case %d: Expected: %v, Received: %v", i+1, test.err, receivedErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue