forked from rook/rook
move core rados packages under cluster folder move daemons under daemon pkg rename flex crd package to attachment pin dep to k8s 1.8.2
202 lines
6.2 KiB
Go
202 lines
6.2 KiB
Go
/*
|
|
Copyright 2016 The Rook Authors. All rights reserved.
|
|
|
|
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 client
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"github.com/rook/rook/pkg/clusterd"
|
|
)
|
|
|
|
type CephFilesystem struct {
|
|
Name string `json:"name"`
|
|
MetadataPool string `json:"metadata_pool"`
|
|
MetadataPoolID int `json:"metadata_pool_id"`
|
|
DataPools []string `json:"data_pools"`
|
|
DataPoolIDs []int `json:"data_pool_ids"`
|
|
}
|
|
|
|
type CephFilesystemDetails struct {
|
|
ID int `json:"id"`
|
|
MDSMap MDSMap `json:"mdsmap"`
|
|
}
|
|
|
|
type MDSMap struct {
|
|
FilesystemName string `json:"fs_name"`
|
|
Enabled bool `json:"enabled"`
|
|
Root int `json:"root"`
|
|
TableServer int `json:"tableserver"`
|
|
MaxMDS int `json:"max_mds"`
|
|
In []int `json:"in"`
|
|
Up map[string]int `json:"up"`
|
|
MetadataPool int `json:"metadata_pool"`
|
|
DataPools []int `json:"data_pools"`
|
|
Failed []int `json:"failed"`
|
|
Damaged []int `json:"damaged"`
|
|
Stopped []int `json:"stopped"`
|
|
Info map[string]MDSInfo `json:"info"`
|
|
}
|
|
|
|
type MDSInfo struct {
|
|
GID int `json:"gid"`
|
|
Name string `json:"name"`
|
|
Rank int `json:"rank"`
|
|
State string `json:"state"`
|
|
Address string `json:"addr"`
|
|
}
|
|
|
|
func ListFilesystems(context *clusterd.Context, clusterName string) ([]CephFilesystem, error) {
|
|
args := []string{"fs", "ls"}
|
|
buf, err := ExecuteCephCommand(context, clusterName, args)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list filesystems: %+v", err)
|
|
}
|
|
|
|
var filesystems []CephFilesystem
|
|
err = json.Unmarshal(buf, &filesystems)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unmarshal failed: %+v. raw buffer response: %s", err, string(buf))
|
|
}
|
|
|
|
return filesystems, nil
|
|
}
|
|
|
|
func GetFilesystem(context *clusterd.Context, clusterName string, fsName string) (*CephFilesystemDetails, error) {
|
|
args := []string{"fs", "get", fsName}
|
|
buf, err := ExecuteCephCommand(context, clusterName, args)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get file system %s: %+v", fsName, err)
|
|
}
|
|
|
|
var fs CephFilesystemDetails
|
|
err = json.Unmarshal(buf, &fs)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unmarshal failed: %+v. raw buffer response: %s", err, string(buf))
|
|
}
|
|
|
|
return &fs, nil
|
|
}
|
|
|
|
func CreateFilesystem(context *clusterd.Context, clusterName, name, metadataPool string, dataPools []string, activeMDSCount int32) error {
|
|
if len(dataPools) == 0 {
|
|
return fmt.Errorf("at least one data pool is required")
|
|
}
|
|
|
|
// enable multiple file systems in case this is not the first
|
|
args := []string{"fs", "flag", "set", "enable_multiple", "true", confirmFlag}
|
|
_, err := ExecuteCephCommand(context, clusterName, args)
|
|
if err != nil {
|
|
// continue if this fails
|
|
logger.Warning("failed enabling multiple file systems. %+v", err)
|
|
}
|
|
|
|
// create the filesystem
|
|
args = []string{"fs", "new", name, metadataPool, dataPools[0]}
|
|
_, err = ExecuteCephCommand(context, clusterName, args)
|
|
if err != nil {
|
|
return fmt.Errorf("failed enabling ceph fs %s. %+v", name, err)
|
|
}
|
|
|
|
// add each additional pool
|
|
for i := 1; i < len(dataPools); i++ {
|
|
poolName := dataPools[i]
|
|
args = []string{"fs", "add_data_pool", name, poolName}
|
|
_, err = ExecuteCephCommand(context, clusterName, args)
|
|
if err != nil {
|
|
logger.Errorf("failed to add pool %s to file system %s. %+v", poolName, name, err)
|
|
}
|
|
}
|
|
|
|
// set the number of active mds instances
|
|
if activeMDSCount > 1 {
|
|
args = []string{"fs", "set", name, "max_mds", strconv.Itoa(int(activeMDSCount))}
|
|
_, err = ExecuteCephCommand(context, clusterName, args)
|
|
if err != nil {
|
|
logger.Warningf("failed setting active mds count to %d. %+v", activeMDSCount, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func MarkFilesystemAsDown(context *clusterd.Context, clusterName string, fsName string) error {
|
|
args := []string{"fs", "set", fsName, "cluster_down", "true"}
|
|
_, err := ExecuteCephCommand(context, clusterName, args)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to set file system %s to cluster_down: %+v", fsName, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func FailMDS(context *clusterd.Context, clusterName string, gid int) error {
|
|
args := []string{"mds", "fail", strconv.Itoa(gid)}
|
|
_, err := ExecuteCephCommand(context, clusterName, args)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to fail mds %d: %+v", gid, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func RemoveFilesystem(context *clusterd.Context, clusterName, fsName string) error {
|
|
fs, err := GetFilesystem(context, clusterName, fsName)
|
|
if err != nil {
|
|
return fmt.Errorf("filesystem %s not found. %+v", fsName, err)
|
|
}
|
|
|
|
args := []string{"fs", "rm", fsName, confirmFlag}
|
|
_, err = ExecuteCephCommand(context, clusterName, args)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to delete ceph fs %s. err=%+v", fsName, err)
|
|
}
|
|
|
|
err = deleteFSPools(context, clusterName, fs)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete fs %s pools. %+v", fsName, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func deleteFSPools(context *clusterd.Context, clusterName string, fs *CephFilesystemDetails) error {
|
|
poolNames, err := GetPoolNamesByID(context, clusterName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get pool names. %+v", err)
|
|
}
|
|
|
|
// delete the metadata pool
|
|
var lastErr error
|
|
if err := deleteFSPool(context, clusterName, poolNames, fs.MDSMap.MetadataPool); err != nil {
|
|
lastErr = err
|
|
}
|
|
|
|
// delete the data pools
|
|
for _, poolID := range fs.MDSMap.DataPools {
|
|
if err := deleteFSPool(context, clusterName, poolNames, poolID); err != nil {
|
|
lastErr = err
|
|
}
|
|
}
|
|
return lastErr
|
|
}
|
|
|
|
func deleteFSPool(context *clusterd.Context, clusterName string, poolNames map[int]string, id int) error {
|
|
name, ok := poolNames[id]
|
|
if !ok {
|
|
return fmt.Errorf("pool %d not found", id)
|
|
}
|
|
return DeletePool(context, clusterName, name)
|
|
}
|