mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 06:54:01 +00:00
Updates godep for pkg/volume/flocker
Supports additional options for CreateDataset and DeleteDataset for dynamic provisioning. Bugfix for timeouts during CreateDataset
This commit is contained in:
parent
1c11047ffb
commit
6f2af39021
8
Godeps/Godeps.json
generated
8
Godeps/Godeps.json
generated
@ -65,10 +65,6 @@
|
|||||||
"Comment": "v7.0.6-4-g2492d97",
|
"Comment": "v7.0.6-4-g2492d97",
|
||||||
"Rev": "2492d97b402e00797833c03ac5fa1c572c7bb29a"
|
"Rev": "2492d97b402e00797833c03ac5fa1c572c7bb29a"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ImportPath": "github.com/ClusterHQ/flocker-go",
|
|
||||||
"Rev": "1c0a791b33bdc01d062b376612aa04e27eed7eb3"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/Microsoft/go-winio",
|
"ImportPath": "github.com/Microsoft/go-winio",
|
||||||
"Comment": "v0.1.0",
|
"Comment": "v0.1.0",
|
||||||
@ -331,6 +327,10 @@
|
|||||||
"Comment": "1.2.0",
|
"Comment": "1.2.0",
|
||||||
"Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30"
|
"Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/clusterhq/flocker-go",
|
||||||
|
"Rev": "2b8b7259d3139c96c4a6871031355808ab3fd3b3"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/codegangsta/negroni",
|
"ImportPath": "github.com/codegangsta/negroni",
|
||||||
"Comment": "v0.1.0-62-g8d75e11",
|
"Comment": "v0.1.0-62-g8d75e11",
|
||||||
|
4
Godeps/LICENSES
generated
4
Godeps/LICENSES
generated
@ -9231,7 +9231,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
= vendor/github.com/ClusterHQ/flocker-go licensed under: =
|
= vendor/github.com/clusterhq/flocker-go licensed under: =
|
||||||
|
|
||||||
Apache License
|
Apache License
|
||||||
Version 2.0, January 2004
|
Version 2.0, January 2004
|
||||||
@ -9424,7 +9424,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
= vendor/github.com/ClusterHQ/flocker-go/LICENSE d8103d9796cd0e951379d0834edad066 -
|
= vendor/github.com/clusterhq/flocker-go/LICENSE d8103d9796cd0e951379d0834edad066 -
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
16
vendor/github.com/clusterhq/flocker-go/circle.yml
generated
vendored
Normal file
16
vendor/github.com/clusterhq/flocker-go/circle.yml
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
machine:
|
||||||
|
timezone:
|
||||||
|
America/Los_Angeles
|
||||||
|
|
||||||
|
# Output the test output to circle.
|
||||||
|
test:
|
||||||
|
pre:
|
||||||
|
- go get -u github.com/jstemmer/go-junit-report
|
||||||
|
override:
|
||||||
|
- go test -coverprofile=coverage.out -v -race ./... > test.out
|
||||||
|
- cat test.out | go-junit-report > report.xml
|
||||||
|
- go tool cover -func=coverage.out
|
||||||
|
post:
|
||||||
|
- mv test.out $CIRCLE_ARTIFACTS/
|
||||||
|
- mv report.xml $CIRCLE_TEST_REPORTS/
|
||||||
|
|
@ -34,12 +34,15 @@ var (
|
|||||||
|
|
||||||
// Clientable exposes the needed methods to implement your own Flocker Client.
|
// Clientable exposes the needed methods to implement your own Flocker Client.
|
||||||
type Clientable interface {
|
type Clientable interface {
|
||||||
CreateDataset(metaName string) (*DatasetState, error)
|
CreateDataset(options *CreateDatasetOptions) (*DatasetState, error)
|
||||||
|
DeleteDataset(datasetID string) error
|
||||||
|
|
||||||
GetDatasetState(datasetID string) (*DatasetState, error)
|
GetDatasetState(datasetID string) (*DatasetState, error)
|
||||||
GetDatasetID(metaName string) (datasetID string, err error)
|
GetDatasetID(metaName string) (datasetID string, err error)
|
||||||
GetPrimaryUUID() (primaryUUID string, err error)
|
GetPrimaryUUID() (primaryUUID string, err error)
|
||||||
|
|
||||||
|
ListNodes() (nodes []NodeState, err error)
|
||||||
|
|
||||||
UpdatePrimaryForDataset(primaryUUID, datasetID string) (*DatasetState, error)
|
UpdatePrimaryForDataset(primaryUUID, datasetID string) (*DatasetState, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +60,8 @@ type Client struct {
|
|||||||
maximumSize json.Number
|
maximumSize json.Number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Clientable = &Client{}
|
||||||
|
|
||||||
// NewClient creates a wrapper over http.Client to communicate with the flocker control service.
|
// NewClient creates a wrapper over http.Client to communicate with the flocker control service.
|
||||||
func NewClient(host string, port int, clientIP string, caCertPath, keyPath, certPath string) (*Client, error) {
|
func NewClient(host string, port int, clientIP string, caCertPath, keyPath, certPath string) (*Client, error) {
|
||||||
client, err := newTLSClient(caCertPath, keyPath, certPath)
|
client, err := newTLSClient(caCertPath, keyPath, certPath)
|
||||||
@ -110,6 +115,11 @@ func (c Client) post(url string, payload interface{}) (*http.Response, error) {
|
|||||||
return c.request("POST", url, payload)
|
return c.request("POST", url, payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// delete performs a delete request with the indicated payload
|
||||||
|
func (c Client) delete(url string, payload interface{}) (*http.Response, error) {
|
||||||
|
return c.request("DELETE", url, payload)
|
||||||
|
}
|
||||||
|
|
||||||
// get performs a get request
|
// get performs a get request
|
||||||
func (c Client) get(url string) (*http.Response, error) {
|
func (c Client) get(url string) (*http.Response, error) {
|
||||||
return c.request("GET", url, nil)
|
return c.request("GET", url, nil)
|
||||||
@ -128,6 +138,13 @@ type configurationPayload struct {
|
|||||||
Metadata metadataPayload `json:"metadata,omitempty"`
|
Metadata metadataPayload `json:"metadata,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CreateDatasetOptions struct {
|
||||||
|
Primary string `json:"primary"`
|
||||||
|
DatasetID string `json:"dataset_id,omitempty"`
|
||||||
|
MaximumSize int64 `json:"maximum_size,omitempty"`
|
||||||
|
Metadata map[string]string `json:"metadata,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type metadataPayload struct {
|
type metadataPayload struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
}
|
}
|
||||||
@ -143,7 +160,7 @@ type datasetStatePayload struct {
|
|||||||
*DatasetState
|
*DatasetState
|
||||||
}
|
}
|
||||||
|
|
||||||
type nodeStatePayload struct {
|
type NodeState struct {
|
||||||
UUID string `json:"uuid"`
|
UUID string `json:"uuid"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
}
|
}
|
||||||
@ -163,25 +180,54 @@ func (c Client) findIDInConfigurationsPayload(body io.ReadCloser, name string) (
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListNodes returns a list of dataset agent nodes from Flocker Control Service
|
||||||
|
func (c *Client) ListNodes() (nodes []NodeState, err error) {
|
||||||
|
resp, err := c.get(c.getURL("state/nodes"))
|
||||||
|
if err != nil {
|
||||||
|
return []NodeState{}, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode >= 300 {
|
||||||
|
return []NodeState{}, fmt.Errorf("Expected: {1,2}xx listing nodes, got: %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&nodes)
|
||||||
|
if err != nil {
|
||||||
|
return []NodeState{}, err
|
||||||
|
}
|
||||||
|
return nodes, err
|
||||||
|
}
|
||||||
|
|
||||||
// GetPrimaryUUID returns the UUID of the primary Flocker Control Service for
|
// GetPrimaryUUID returns the UUID of the primary Flocker Control Service for
|
||||||
// the given host.
|
// the given host.
|
||||||
func (c Client) GetPrimaryUUID() (uuid string, err error) {
|
func (c Client) GetPrimaryUUID() (uuid string, err error) {
|
||||||
resp, err := c.get(c.getURL("state/nodes"))
|
states, err := c.ListNodes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var states []nodeStatePayload
|
|
||||||
if err = json.NewDecoder(resp.Body).Decode(&states); err == nil {
|
|
||||||
for _, s := range states {
|
for _, s := range states {
|
||||||
if s.Host == c.clientIP {
|
if s.Host == c.clientIP {
|
||||||
return s.UUID, nil
|
return s.UUID, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", errStateNotFound
|
return "", fmt.Errorf("No node found with IP '%s', available nodes %+v", c.clientIP, states)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDataset performs a delete request to the given datasetID
|
||||||
|
func (c *Client) DeleteDataset(datasetID string) error {
|
||||||
|
url := c.getURL(fmt.Sprintf("configuration/datasets/%s", datasetID))
|
||||||
|
resp, err := c.delete(url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return "", err
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode >= 300 {
|
||||||
|
return fmt.Errorf("Expected: {1,2}xx deleting the dataset %s, got: %d", datasetID, resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDatasetState performs a get request to get the state of the given datasetID, if
|
// GetDatasetState performs a get request to get the state of the given datasetID, if
|
||||||
@ -213,34 +259,30 @@ returns the dataset id.
|
|||||||
This process is a little bit complex but follows this flow:
|
This process is a little bit complex but follows this flow:
|
||||||
|
|
||||||
1. Find the Flocker Control Service UUID
|
1. Find the Flocker Control Service UUID
|
||||||
2. Try to create the dataset
|
2. If it already exists an error is returned
|
||||||
3. If it already exists an error is returned
|
3. If it didn't previously exist, wait for it to be ready
|
||||||
4. If it didn't previously exist, wait for it to be ready
|
|
||||||
*/
|
*/
|
||||||
func (c Client) CreateDataset(metaName string) (*DatasetState, error) {
|
func (c *Client) CreateDataset(options *CreateDatasetOptions) (datasetState *DatasetState, err error) {
|
||||||
// 1) Find the primary Flocker UUID
|
// 1) Find the primary Flocker UUID
|
||||||
// Note: it could be cached, but doing this query we health check it
|
// Note: it could be cached, but doing this query we health check it
|
||||||
primary, err := c.GetPrimaryUUID()
|
if options.Primary == "" {
|
||||||
|
options.Primary, err = c.GetPrimaryUUID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) Try to create the dataset in the given Primary
|
|
||||||
payload := configurationPayload{
|
|
||||||
Primary: primary,
|
|
||||||
MaximumSize: json.Number(c.maximumSize),
|
|
||||||
Metadata: metadataPayload{
|
|
||||||
Name: metaName,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := c.post(c.getURL("configuration/datasets"), payload)
|
if options.MaximumSize == 0 {
|
||||||
|
options.MaximumSize, _ = c.maximumSize.Int64()
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := c.post(c.getURL("configuration/datasets"), options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// 3) Return if the dataset was previously created
|
// 2) Return if the dataset was previously created
|
||||||
if resp.StatusCode == http.StatusConflict {
|
if resp.StatusCode == http.StatusConflict {
|
||||||
return nil, errVolumeAlreadyExists
|
return nil, errVolumeAlreadyExists
|
||||||
}
|
}
|
||||||
@ -254,21 +296,31 @@ func (c Client) CreateDataset(metaName string) (*DatasetState, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4) Wait until the dataset is ready for usage. In case it never gets
|
// 3) Wait until the dataset is ready for usage. In case it never gets
|
||||||
// ready there is a timeoutChan that will return an error
|
// ready there is a timeoutChan that will return an error
|
||||||
timeoutChan := time.NewTimer(timeoutWaitingForVolume).C
|
timeoutChan := time.NewTimer(timeoutWaitingForVolume).C
|
||||||
tickChan := time.NewTicker(tickerWaitingForVolume).C
|
tickChan := time.NewTicker(tickerWaitingForVolume).C
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if s, err := c.GetDatasetState(p.DatasetID); err == nil {
|
var strErrDel string
|
||||||
|
s, err := c.GetDatasetState(p.DatasetID)
|
||||||
|
if err == nil {
|
||||||
return s, nil
|
return s, nil
|
||||||
} else if err != errStateNotFound {
|
} else if err != errStateNotFound {
|
||||||
return nil, err
|
errDel := c.DeleteDataset(p.DatasetID)
|
||||||
|
if errDel != nil {
|
||||||
|
strErrDel = fmt.Sprintf(", deletion of dataset failed with %s", errDel)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("Flocker API error during dataset creation (datasetID %s): %s%s", p.DatasetID, err, strErrDel)
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-timeoutChan:
|
case <-timeoutChan:
|
||||||
return nil, err
|
errDel := c.DeleteDataset(p.DatasetID)
|
||||||
|
if errDel != nil {
|
||||||
|
strErrDel = fmt.Sprintf(", deletion of dataset failed with %s", errDel)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("Flocker API timeout during dataset creation (datasetID %s): %s%s", p.DatasetID, err, strErrDel)
|
||||||
case <-tickChan:
|
case <-tickChan:
|
||||||
break
|
break
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user