2017-01-05 14:03:21 -08:00
|
|
|
/*
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2018-08-31 13:39:02 -06:00
|
|
|
|
2018-05-18 14:32:20 -07:00
|
|
|
package ceph
|
2017-01-05 14:03:21 -08:00
|
|
|
|
|
|
|
|
import (
|
2021-11-13 15:24:05 +09:00
|
|
|
"context"
|
2020-02-25 13:31:46 -07:00
|
|
|
"encoding/json"
|
2017-06-02 13:44:54 -07:00
|
|
|
"os"
|
2022-12-13 16:13:20 -07:00
|
|
|
"path"
|
2021-11-23 18:49:43 +01:00
|
|
|
"strconv"
|
2020-08-27 21:43:02 +05:30
|
|
|
"strings"
|
2017-03-23 17:14:05 -07:00
|
|
|
|
2019-09-05 16:39:41 +05:30
|
|
|
"k8s.io/client-go/kubernetes"
|
|
|
|
|
|
2019-10-08 12:51:36 +02:00
|
|
|
"github.com/pkg/errors"
|
2018-05-18 14:32:20 -07:00
|
|
|
"github.com/rook/rook/cmd/rook/rook"
|
2023-06-22 09:59:34 +05:30
|
|
|
cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
|
2024-01-08 15:35:45 +05:30
|
|
|
"github.com/rook/rook/pkg/daemon/ceph/client"
|
2018-09-05 10:42:08 -06:00
|
|
|
osddaemon "github.com/rook/rook/pkg/daemon/ceph/osd"
|
2019-01-08 17:12:36 -07:00
|
|
|
"github.com/rook/rook/pkg/operator/ceph/cluster/mon"
|
2018-05-18 14:32:20 -07:00
|
|
|
oposd "github.com/rook/rook/pkg/operator/ceph/cluster/osd"
|
|
|
|
|
osdcfg "github.com/rook/rook/pkg/operator/ceph/cluster/osd/config"
|
2020-04-17 18:40:54 +02:00
|
|
|
opcontroller "github.com/rook/rook/pkg/operator/ceph/controller"
|
2017-09-22 17:54:03 -07:00
|
|
|
"github.com/rook/rook/pkg/operator/k8sutil"
|
2017-01-05 14:03:21 -08:00
|
|
|
"github.com/rook/rook/pkg/util/flags"
|
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var osdCmd = &cobra.Command{
|
2019-02-21 23:35:23 +05:30
|
|
|
Use: "osd",
|
|
|
|
|
Short: "Provisions and runs the osd daemon",
|
2018-06-11 17:41:32 -07:00
|
|
|
}
|
2018-07-31 14:39:53 -06:00
|
|
|
var osdConfigCmd = &cobra.Command{
|
2019-02-21 23:35:23 +05:30
|
|
|
Use: "init",
|
|
|
|
|
Short: "Updates ceph.conf for the osd",
|
2018-07-31 14:39:53 -06:00
|
|
|
}
|
2018-06-11 17:41:32 -07:00
|
|
|
var provisionCmd = &cobra.Command{
|
2019-02-21 23:35:23 +05:30
|
|
|
Use: "provision",
|
|
|
|
|
Short: "Generates osd config and prepares an osd for runtime",
|
2018-06-11 17:41:32 -07:00
|
|
|
}
|
2018-11-01 17:26:23 -06:00
|
|
|
var osdStartCmd = &cobra.Command{
|
2019-02-21 23:35:23 +05:30
|
|
|
Use: "start",
|
|
|
|
|
Short: "Starts the osd daemon", // OSDs that were provisioned by ceph-volume
|
2018-11-01 17:26:23 -06:00
|
|
|
}
|
2020-08-27 21:43:02 +05:30
|
|
|
var osdRemoveCmd = &cobra.Command{
|
|
|
|
|
Use: "remove",
|
|
|
|
|
Short: "Removes a set of OSDs from the cluster",
|
|
|
|
|
}
|
2019-09-03 15:34:17 +05:30
|
|
|
|
2017-01-19 13:31:22 -08:00
|
|
|
var (
|
2019-11-05 11:01:04 +09:00
|
|
|
osdDataDeviceFilter string
|
|
|
|
|
osdDataDevicePathFilter string
|
|
|
|
|
ownerRefID string
|
2021-02-12 17:41:40 -07:00
|
|
|
clusterName string
|
2019-11-05 11:01:04 +09:00
|
|
|
osdID int
|
2023-06-22 09:59:34 +05:30
|
|
|
replaceOSDID int
|
2019-11-05 11:01:04 +09:00
|
|
|
osdStoreType string
|
|
|
|
|
osdStringID string
|
|
|
|
|
osdUUID string
|
|
|
|
|
osdIsDevice bool
|
|
|
|
|
pvcBackedOSD bool
|
2020-01-13 16:58:51 +01:00
|
|
|
blockPath string
|
2019-10-25 15:47:47 +09:00
|
|
|
lvBackedPV bool
|
2020-08-27 21:43:02 +05:30
|
|
|
osdIDsToRemove string
|
2021-11-23 18:49:43 +01:00
|
|
|
preservePVC string
|
|
|
|
|
forceOSDRemoval string
|
2017-01-19 13:31:22 -08:00
|
|
|
)
|
2017-01-05 14:03:21 -08:00
|
|
|
|
2022-12-13 16:13:20 -07:00
|
|
|
const (
|
|
|
|
|
//#nosec G101 -- This is only an env var name
|
|
|
|
|
fallbackCephSecretEnvVar = "ROOK_CEPH_SECRET"
|
|
|
|
|
)
|
|
|
|
|
|
2017-03-30 12:45:11 -07:00
|
|
|
func addOSDFlags(command *cobra.Command) {
|
2018-07-31 14:39:53 -06:00
|
|
|
addOSDConfigFlags(osdConfigCmd)
|
|
|
|
|
addOSDConfigFlags(provisionCmd)
|
|
|
|
|
|
|
|
|
|
// flags specific to provisioning
|
2023-06-22 09:59:34 +05:30
|
|
|
provisionCmd.Flags().IntVar(&replaceOSDID, "replace-osd", -1, "osd to be destroyed")
|
2018-06-11 17:41:32 -07:00
|
|
|
provisionCmd.Flags().StringVar(&cfg.devices, "data-devices", "", "comma separated list of devices to use for storage")
|
|
|
|
|
provisionCmd.Flags().StringVar(&osdDataDeviceFilter, "data-device-filter", "", "a regex filter for the device names to use, or \"all\"")
|
2019-11-05 11:01:04 +09:00
|
|
|
provisionCmd.Flags().StringVar(&osdDataDevicePathFilter, "data-device-path-filter", "", "a regex filter for the device path names to use")
|
2018-06-11 17:41:32 -07:00
|
|
|
provisionCmd.Flags().StringVar(&cfg.metadataDevice, "metadata-device", "", "device to use for metadata (e.g. a high performance SSD/NVMe device)")
|
|
|
|
|
provisionCmd.Flags().BoolVar(&cfg.forceFormat, "force-format", false,
|
2017-03-30 12:45:11 -07:00
|
|
|
"true to force the format of any specified devices, even if they already have a filesystem. BE CAREFUL!")
|
2019-07-02 10:42:58 +05:30
|
|
|
provisionCmd.Flags().BoolVar(&cfg.pvcBacked, "pvc-backed-osd", false, "true to specify a block mode pvc is backing the OSD")
|
2018-09-20 15:04:03 -06:00
|
|
|
// flags for generating the osd config
|
2018-07-31 14:39:53 -06:00
|
|
|
osdConfigCmd.Flags().IntVar(&osdID, "osd-id", -1, "osd id for which to generate config")
|
2018-11-01 17:26:23 -06:00
|
|
|
osdConfigCmd.Flags().BoolVar(&osdIsDevice, "is-device", false, "whether the osd is a device")
|
2018-11-01 11:47:11 -06:00
|
|
|
|
2018-11-01 17:26:23 -06:00
|
|
|
// flags for running osds that were provisioned by ceph-volume
|
|
|
|
|
osdStartCmd.Flags().StringVar(&osdStringID, "osd-id", "", "the osd ID")
|
|
|
|
|
osdStartCmd.Flags().StringVar(&osdUUID, "osd-uuid", "", "the osd UUID")
|
2021-05-04 15:15:20 -06:00
|
|
|
osdStartCmd.Flags().StringVar(&osdStoreType, "osd-store-type", "", "the osd store type such as bluestore")
|
2019-07-02 10:42:58 +05:30
|
|
|
osdStartCmd.Flags().BoolVar(&pvcBackedOSD, "pvc-backed-osd", false, "Whether the OSD backing store in PVC or not")
|
2020-01-13 16:58:51 +01:00
|
|
|
osdStartCmd.Flags().StringVar(&blockPath, "block-path", "", "Block path for the OSD created by ceph-volume")
|
2019-10-25 15:47:47 +09:00
|
|
|
osdStartCmd.Flags().BoolVar(&lvBackedPV, "lv-backed-pv", false, "Whether the PV located on LV")
|
2018-11-01 17:26:23 -06:00
|
|
|
|
2020-08-27 21:43:02 +05:30
|
|
|
// flags for removing OSDs that are unhealthy or otherwise should be purged from the cluster
|
|
|
|
|
osdRemoveCmd.Flags().StringVar(&osdIDsToRemove, "osd-ids", "", "OSD IDs to remove from the cluster")
|
2021-11-23 18:49:43 +01:00
|
|
|
osdRemoveCmd.Flags().StringVar(&preservePVC, "preserve-pvc", "false", "Whether PVCs for OSDs will be deleted")
|
|
|
|
|
osdRemoveCmd.Flags().StringVar(&forceOSDRemoval, "force-osd-removal", "false", "Whether to force remove the OSD")
|
2020-08-27 21:43:02 +05:30
|
|
|
|
2018-06-11 17:41:32 -07:00
|
|
|
// add the subcommands to the parent osd command
|
2019-02-21 23:35:23 +05:30
|
|
|
osdCmd.AddCommand(osdConfigCmd,
|
|
|
|
|
provisionCmd,
|
2020-08-27 21:43:02 +05:30
|
|
|
osdStartCmd,
|
|
|
|
|
osdRemoveCmd)
|
2018-07-31 14:39:53 -06:00
|
|
|
}
|
2018-06-11 17:41:32 -07:00
|
|
|
|
2018-07-31 14:39:53 -06:00
|
|
|
func addOSDConfigFlags(command *cobra.Command) {
|
2021-02-12 17:41:40 -07:00
|
|
|
command.Flags().StringVar(&ownerRefID, "cluster-id", "", "the UID of the cluster CR that owns this cluster")
|
|
|
|
|
command.Flags().StringVar(&clusterName, "cluster-name", "", "the name of the cluster CR that owns this cluster")
|
2018-07-31 14:39:53 -06:00
|
|
|
command.Flags().StringVar(&cfg.location, "location", "", "location of this node for CRUSH placement")
|
|
|
|
|
command.Flags().StringVar(&cfg.nodeName, "node-name", os.Getenv("HOSTNAME"), "the host name of the node")
|
|
|
|
|
|
|
|
|
|
// OSD store config flags
|
|
|
|
|
command.Flags().IntVar(&cfg.storeConfig.WalSizeMB, "osd-wal-size", osdcfg.WalDefaultSizeMB, "default size (MB) for OSD write ahead log (WAL) (bluestore)")
|
2019-08-28 18:06:39 -06:00
|
|
|
command.Flags().IntVar(&cfg.storeConfig.DatabaseSizeMB, "osd-database-size", 0, "default size (MB) for OSD database (bluestore)")
|
2018-12-04 14:57:22 -07:00
|
|
|
command.Flags().IntVar(&cfg.storeConfig.OSDsPerDevice, "osds-per-device", 1, "the number of OSDs per device")
|
2018-12-07 08:28:47 -07:00
|
|
|
command.Flags().BoolVar(&cfg.storeConfig.EncryptedDevice, "encrypted-device", false, "whether to encrypt the OSD with dmcrypt")
|
2020-12-10 17:11:48 -07:00
|
|
|
command.Flags().StringVar(&cfg.storeConfig.DeviceClass, "osd-crush-device-class", "", "The device class for all OSDs configured on this node")
|
2021-03-30 11:11:41 +03:00
|
|
|
command.Flags().StringVar(&cfg.storeConfig.InitialWeight, "osd-crush-initial-weight", "", "The initial weight of OSD in TiB units")
|
2023-06-22 09:59:34 +05:30
|
|
|
command.Flags().StringVar(&cfg.storeConfig.StoreType, "osd-store-type", string(cephv1.StoreTypeBlueStore), "the osd store type such as bluestore")
|
2017-03-30 12:45:11 -07:00
|
|
|
}
|
|
|
|
|
|
2017-01-05 14:03:21 -08:00
|
|
|
func init() {
|
2017-03-30 12:45:11 -07:00
|
|
|
addOSDFlags(osdCmd)
|
|
|
|
|
addCephFlags(osdCmd)
|
2018-05-18 14:32:20 -07:00
|
|
|
flags.SetFlagsFromEnv(osdCmd.Flags(), rook.RookEnvVarPrefix)
|
2018-07-31 14:39:53 -06:00
|
|
|
flags.SetFlagsFromEnv(osdConfigCmd.Flags(), rook.RookEnvVarPrefix)
|
2018-06-11 17:41:32 -07:00
|
|
|
flags.SetFlagsFromEnv(provisionCmd.Flags(), rook.RookEnvVarPrefix)
|
2018-11-01 17:26:23 -06:00
|
|
|
flags.SetFlagsFromEnv(osdStartCmd.Flags(), rook.RookEnvVarPrefix)
|
2020-08-27 21:43:02 +05:30
|
|
|
flags.SetFlagsFromEnv(osdRemoveCmd.Flags(), rook.RookEnvVarPrefix)
|
2017-02-15 14:13:12 -08:00
|
|
|
|
2018-07-31 14:39:53 -06:00
|
|
|
osdConfigCmd.RunE = writeOSDConfig
|
2018-06-11 17:41:32 -07:00
|
|
|
provisionCmd.RunE = prepareOSD
|
2018-11-01 17:26:23 -06:00
|
|
|
osdStartCmd.RunE = startOSD
|
2020-08-27 21:43:02 +05:30
|
|
|
osdRemoveCmd.RunE = removeOSDs
|
2018-11-01 17:26:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start the osd daemon if provisioned by ceph-volume
|
|
|
|
|
func startOSD(cmd *cobra.Command, args []string) error {
|
2020-01-13 16:58:51 +01:00
|
|
|
required := []string{"osd-id", "osd-uuid"}
|
2018-11-01 17:26:23 -06:00
|
|
|
if err := flags.VerifyRequiredFlags(osdStartCmd, required); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
commonOSDInit(osdStartCmd)
|
|
|
|
|
|
|
|
|
|
context := createContext()
|
2019-09-26 15:59:51 +02:00
|
|
|
|
|
|
|
|
// Run OSD start sequence
|
2020-01-13 16:58:51 +01:00
|
|
|
err := osddaemon.StartOSD(context, osdStoreType, osdStringID, osdUUID, blockPath, pvcBackedOSD, lvBackedPV, args)
|
2018-06-11 17:41:32 -07:00
|
|
|
if err != nil {
|
|
|
|
|
rook.TerminateFatal(err)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-31 14:39:53 -06:00
|
|
|
func verifyConfigFlags(configCmd *cobra.Command) error {
|
2018-06-11 17:41:32 -07:00
|
|
|
required := []string{"cluster-id", "node-name"}
|
2018-07-31 14:39:53 -06:00
|
|
|
if err := flags.VerifyRequiredFlags(configCmd, required); err != nil {
|
2018-06-11 17:41:32 -07:00
|
|
|
return err
|
|
|
|
|
}
|
2022-12-13 16:13:20 -07:00
|
|
|
required = []string{"mon-endpoints", "ceph-username"}
|
2017-08-01 22:33:00 -07:00
|
|
|
if err := flags.VerifyRequiredFlags(osdCmd, required); err != nil {
|
2017-01-05 14:03:21 -08:00
|
|
|
return err
|
|
|
|
|
}
|
2018-07-31 14:39:53 -06:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func writeOSDConfig(cmd *cobra.Command, args []string) error {
|
|
|
|
|
if err := verifyConfigFlags(osdConfigCmd); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if osdID == -1 {
|
2019-10-08 12:51:36 +02:00
|
|
|
return errors.New("osd id not specified")
|
2018-07-31 14:39:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
commonOSDInit(osdConfigCmd)
|
2019-01-08 11:48:44 -07:00
|
|
|
|
2018-11-01 11:47:11 -06:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-31 14:39:53 -06:00
|
|
|
// Provision a device or directory for an OSD
|
|
|
|
|
func prepareOSD(cmd *cobra.Command, args []string) error {
|
2023-06-22 09:59:34 +05:30
|
|
|
|
2018-07-31 14:39:53 -06:00
|
|
|
if err := verifyConfigFlags(provisionCmd); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2017-01-05 14:03:21 -08:00
|
|
|
|
2022-12-13 16:13:20 -07:00
|
|
|
if err := readCephSecret(path.Join(mon.CephSecretMountPath, mon.CephSecretFilename)); err != nil {
|
|
|
|
|
rook.TerminateFatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-21 13:13:59 -06:00
|
|
|
var (
|
|
|
|
|
dataDevices []osddaemon.DesiredDevice
|
|
|
|
|
deviceFilter string
|
|
|
|
|
metaDevice string
|
|
|
|
|
)
|
|
|
|
|
|
2017-03-23 17:14:05 -07:00
|
|
|
if osdDataDeviceFilter != "" {
|
2019-11-05 11:01:04 +09:00
|
|
|
if cfg.devices != "" || osdDataDevicePathFilter != "" {
|
2019-10-08 12:51:36 +02:00
|
|
|
return errors.New("only one of --data-devices, --data-device-filter and --data-device-path-filter can be specified")
|
2017-03-23 17:14:05 -07:00
|
|
|
}
|
|
|
|
|
|
2018-12-04 14:57:22 -07:00
|
|
|
dataDevices = []osddaemon.DesiredDevice{
|
2019-02-26 16:11:25 -07:00
|
|
|
{Name: osdDataDeviceFilter, IsFilter: true, OSDsPerDevice: cfg.storeConfig.OSDsPerDevice},
|
2018-12-04 14:57:22 -07:00
|
|
|
}
|
2023-04-21 13:13:59 -06:00
|
|
|
|
|
|
|
|
deviceFilter = osdDataDeviceFilter
|
2019-11-05 11:01:04 +09:00
|
|
|
} else if osdDataDevicePathFilter != "" {
|
|
|
|
|
if cfg.devices != "" {
|
2019-10-08 12:51:36 +02:00
|
|
|
return errors.New("only one of --data-devices, --data-device-filter and --data-device-path-filter can be specified")
|
2019-11-05 11:01:04 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dataDevices = []osddaemon.DesiredDevice{
|
|
|
|
|
{Name: osdDataDevicePathFilter, IsDevicePathFilter: true, OSDsPerDevice: cfg.storeConfig.OSDsPerDevice},
|
|
|
|
|
}
|
2017-03-23 17:14:05 -07:00
|
|
|
} else {
|
2018-12-04 14:57:22 -07:00
|
|
|
var err error
|
|
|
|
|
dataDevices, err = parseDevices(cfg.devices)
|
|
|
|
|
if err != nil {
|
2019-10-08 12:51:36 +02:00
|
|
|
rook.TerminateFatal(errors.Wrapf(err, "failed to parse device list (%q)", cfg.devices))
|
2018-12-04 14:57:22 -07:00
|
|
|
}
|
2017-03-23 17:14:05 -07:00
|
|
|
}
|
|
|
|
|
|
2017-09-22 17:54:03 -07:00
|
|
|
context := createContext()
|
2018-06-11 17:41:32 -07:00
|
|
|
commonOSDInit(provisionCmd)
|
2021-11-13 15:24:05 +09:00
|
|
|
crushLocation, topologyAffinity, err := getLocation(cmd.Context(), context.Clientset)
|
2017-10-25 15:20:50 -07:00
|
|
|
if err != nil {
|
2019-09-05 16:39:41 +05:30
|
|
|
rook.TerminateFatal(err)
|
2017-10-25 15:20:50 -07:00
|
|
|
}
|
2019-09-05 16:39:41 +05:30
|
|
|
logger.Infof("crush location of osd: %s", crushLocation)
|
2017-10-25 15:20:50 -07:00
|
|
|
|
2017-01-19 13:31:22 -08:00
|
|
|
forceFormat := false
|
2021-02-18 13:10:11 +00:00
|
|
|
|
2021-02-12 17:41:40 -07:00
|
|
|
ownerRef := opcontroller.ClusterOwnerRef(clusterName, ownerRefID)
|
2021-02-18 13:10:11 +00:00
|
|
|
ownerInfo := k8sutil.NewOwnerInfoWithOwnerRef(&ownerRef, clusterInfo.Namespace)
|
|
|
|
|
clusterInfo.OwnerInfo = ownerInfo
|
2021-11-13 15:24:05 +09:00
|
|
|
clusterInfo.Context = cmd.Context()
|
2021-02-18 13:10:11 +00:00
|
|
|
kv := k8sutil.NewConfigMapKVStore(clusterInfo.Namespace, context.Clientset, ownerInfo)
|
2023-06-22 09:59:34 +05:30
|
|
|
|
2024-01-08 15:35:45 +05:30
|
|
|
if err := client.WriteCephConfig(context, &clusterInfo); err != nil {
|
|
|
|
|
return errors.Wrap(err, "failed to generate ceph config")
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-22 09:59:34 +05:30
|
|
|
// destroy the OSD using the OSD ID
|
2023-09-15 21:49:33 +08:00
|
|
|
var replaceOSD *oposd.OSDReplaceInfo
|
2023-06-22 09:59:34 +05:30
|
|
|
if replaceOSDID != -1 {
|
2023-08-22 15:31:31 +05:30
|
|
|
logger.Infof("destroying osd.%d and cleaning its backing device", replaceOSDID)
|
|
|
|
|
replaceOSD, err = osddaemon.DestroyOSD(context, &clusterInfo, replaceOSDID, cfg.pvcBacked, cfg.storeConfig.EncryptedDevice)
|
2023-06-22 09:59:34 +05:30
|
|
|
if err != nil {
|
2023-08-22 15:31:31 +05:30
|
|
|
rook.TerminateFatal(errors.Wrapf(err, "failed to destroy OSD %d.", replaceOSDID))
|
2023-06-22 09:59:34 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-22 14:04:56 -07:00
|
|
|
agent := osddaemon.NewAgent(context, dataDevices, cfg.metadataDevice, forceFormat,
|
2023-06-22 09:59:34 +05:30
|
|
|
cfg.storeConfig, &clusterInfo, cfg.nodeName, kv, replaceOSD, cfg.pvcBacked)
|
2017-01-17 13:23:03 -08:00
|
|
|
|
2023-04-21 13:13:59 -06:00
|
|
|
if cfg.metadataDevice != "" {
|
|
|
|
|
metaDevice = cfg.metadataDevice
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = osddaemon.Provision(context, agent, crushLocation, topologyAffinity, deviceFilter, metaDevice)
|
2017-06-02 13:44:54 -07:00
|
|
|
if err != nil {
|
2017-12-21 19:41:50 -08:00
|
|
|
// something failed in the OSD orchestration, update the status map with failure details
|
|
|
|
|
status := oposd.OrchestrationStatus{
|
2019-07-02 10:42:58 +05:30
|
|
|
Status: oposd.OrchestrationStatusFailed,
|
|
|
|
|
Message: err.Error(),
|
|
|
|
|
PvcBackedOSD: cfg.pvcBacked,
|
2017-12-21 19:41:50 -08:00
|
|
|
}
|
2021-12-11 11:17:12 +09:00
|
|
|
oposd.UpdateNodeOrPVCStatus(clusterInfo.Context, kv, cfg.nodeName, status)
|
2017-12-21 19:41:50 -08:00
|
|
|
|
2018-05-18 14:32:20 -07:00
|
|
|
rook.TerminateFatal(err)
|
2017-06-02 13:44:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
2017-01-05 14:03:21 -08:00
|
|
|
}
|
2018-06-11 17:41:32 -07:00
|
|
|
|
2020-08-27 21:43:02 +05:30
|
|
|
// Purge the desired OSDs from the cluster
|
|
|
|
|
func removeOSDs(cmd *cobra.Command, args []string) error {
|
|
|
|
|
required := []string{"osd-ids"}
|
|
|
|
|
if err := flags.VerifyRequiredFlags(osdRemoveCmd, required); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2022-12-13 16:13:20 -07:00
|
|
|
required = []string{"mon-endpoints", "ceph-username"}
|
2020-08-27 21:43:02 +05:30
|
|
|
if err := flags.VerifyRequiredFlags(osdCmd, required); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-13 16:13:20 -07:00
|
|
|
if err := readCephSecret(path.Join(mon.CephSecretMountPath, mon.CephSecretFilename)); err != nil {
|
|
|
|
|
rook.TerminateFatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-27 21:43:02 +05:30
|
|
|
commonOSDInit(osdRemoveCmd)
|
|
|
|
|
|
|
|
|
|
context := createContext()
|
|
|
|
|
|
2021-11-13 15:24:05 +09:00
|
|
|
clusterInfo.Context = cmd.Context()
|
2021-10-19 12:06:42 -06:00
|
|
|
|
2021-11-23 18:49:43 +01:00
|
|
|
// We use strings instead of bool since the flag package has issues with parsing bools, or
|
|
|
|
|
// perhaps it's the translation between YAML and code... It's unclear but see:
|
|
|
|
|
// starting Rook v1.7.0-alpha.0.660.gb13faecc8 with arguments '/usr/local/bin/rook ceph osd remove --preserve-pvc false --force-osd-removal false --osd-ids 1'
|
|
|
|
|
// flag values: --force-osd-removal=true, --help=false, --log-level=DEBUG, --operator-image=,
|
|
|
|
|
// --osd-ids=1, --preserve-pvc=true, --service-account=
|
|
|
|
|
//
|
|
|
|
|
// Bools are false but they are interpreted true by the flag package.
|
|
|
|
|
|
|
|
|
|
forceOSDRemovalBool, err := strconv.ParseBool(forceOSDRemoval)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.Wrapf(err, "failed to parse --force-osd-removal flag")
|
|
|
|
|
}
|
|
|
|
|
preservePVCBool, err := strconv.ParseBool(preservePVC)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.Wrapf(err, "failed to parse --preserve-pvc flag")
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-27 21:43:02 +05:30
|
|
|
// Run OSD remove sequence
|
2023-12-07 20:57:36 +05:30
|
|
|
err = osddaemon.RemoveOSDs(context, &clusterInfo, strings.Split(osdIDsToRemove, ","), preservePVCBool, forceOSDRemovalBool)
|
2020-08-27 21:43:02 +05:30
|
|
|
if err != nil {
|
|
|
|
|
rook.TerminateFatal(err)
|
|
|
|
|
}
|
2021-11-23 18:49:43 +01:00
|
|
|
|
2020-08-27 21:43:02 +05:30
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-11 17:41:32 -07:00
|
|
|
func commonOSDInit(cmd *cobra.Command) {
|
|
|
|
|
rook.SetLogLevel()
|
|
|
|
|
rook.LogStartupInfo(cmd.Flags())
|
|
|
|
|
|
2023-07-19 20:40:57 +01:00
|
|
|
clusterInfo.Monitors = opcontroller.ParseMonEndpoints(cfg.monEndpoints)
|
2018-06-11 17:41:32 -07:00
|
|
|
}
|
2018-12-04 14:57:22 -07:00
|
|
|
|
2020-01-10 23:41:11 -07:00
|
|
|
// use zone/region/hostname labels in the crushmap
|
2021-11-13 15:24:05 +09:00
|
|
|
func getLocation(ctx context.Context, clientset kubernetes.Interface) (string, string, error) {
|
2020-01-10 23:41:11 -07:00
|
|
|
// get the value the operator instructed to use as the host name in the CRUSH map
|
|
|
|
|
hostNameLabel := os.Getenv("ROOK_CRUSHMAP_HOSTNAME")
|
2021-01-25 17:20:02 -07:00
|
|
|
|
2020-05-14 11:58:23 +02:00
|
|
|
rootLabel := os.Getenv(oposd.CrushRootVarName)
|
2020-01-10 23:41:11 -07:00
|
|
|
|
2021-11-13 15:24:05 +09:00
|
|
|
loc, topologyAffinity, err := oposd.GetLocationWithNode(ctx, clientset, os.Getenv(k8sutil.NodeNameEnvVar), rootLabel, hostNameLabel)
|
2020-01-11 05:41:35 +05:30
|
|
|
if err != nil {
|
2021-02-17 15:12:28 -07:00
|
|
|
return "", "", err
|
2020-01-10 23:41:11 -07:00
|
|
|
}
|
2021-02-17 15:12:28 -07:00
|
|
|
return loc, topologyAffinity, nil
|
2019-09-05 16:39:41 +05:30
|
|
|
}
|
|
|
|
|
|
2020-07-14 14:10:45 -06:00
|
|
|
// Parse the devices, which are sent as a JSON-marshalled list of device IDs with a StorageConfig spec
|
2018-12-04 14:57:22 -07:00
|
|
|
func parseDevices(devices string) ([]osddaemon.DesiredDevice, error) {
|
2021-06-09 21:55:34 +04:00
|
|
|
if devices == "" {
|
|
|
|
|
return []osddaemon.DesiredDevice{}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-14 14:10:45 -06:00
|
|
|
configuredDevices := []osdcfg.ConfiguredDevice{}
|
|
|
|
|
err := json.Unmarshal([]byte(devices), &configuredDevices)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, errors.Wrapf(err, "failed to JSON unmarshal configured devices (%q)", devices)
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-04 14:57:22 -07:00
|
|
|
var result []osddaemon.DesiredDevice
|
2020-07-14 14:10:45 -06:00
|
|
|
for _, cd := range configuredDevices {
|
|
|
|
|
d := osddaemon.DesiredDevice{
|
|
|
|
|
Name: cd.ID,
|
2018-12-04 14:57:22 -07:00
|
|
|
}
|
2020-07-14 14:10:45 -06:00
|
|
|
d.OSDsPerDevice = cd.StoreConfig.OSDsPerDevice
|
|
|
|
|
d.DatabaseSizeMB = cd.StoreConfig.DatabaseSizeMB
|
|
|
|
|
d.DeviceClass = cd.StoreConfig.DeviceClass
|
2021-03-30 11:11:41 +03:00
|
|
|
d.InitialWeight = cd.StoreConfig.InitialWeight
|
2020-07-14 14:10:45 -06:00
|
|
|
d.MetadataDevice = cd.StoreConfig.MetadataDevice
|
|
|
|
|
|
|
|
|
|
if d.OSDsPerDevice < 1 {
|
|
|
|
|
return nil, errors.Errorf("osds per device should be greater than 0 (%q)", d.OSDsPerDevice)
|
2019-05-20 10:12:21 -04:00
|
|
|
}
|
2020-07-14 14:10:45 -06:00
|
|
|
|
2018-12-04 14:57:22 -07:00
|
|
|
result = append(result, d)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logger.Infof("desired devices to configure osds: %+v", result)
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
2022-12-13 16:13:20 -07:00
|
|
|
|
|
|
|
|
// Populate the ceph admin secret from a file
|
|
|
|
|
// This is more secret than using an environment variable for the secret
|
|
|
|
|
// since environment variables are easier to access than a file inside the container.
|
|
|
|
|
func readCephSecret(path string) error {
|
|
|
|
|
secret, err := os.ReadFile(path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
// For backward compatibility we need to check if the env var is still set
|
|
|
|
|
adminSecretEnv := os.Getenv(fallbackCephSecretEnvVar)
|
|
|
|
|
if adminSecretEnv == "" {
|
|
|
|
|
// Go ahead and fail since neither the file could be loaded nor is the env var set
|
|
|
|
|
return errors.Wrapf(err, "failed to read ceph secret file from %q", mon.CephSecretMountPath)
|
|
|
|
|
}
|
|
|
|
|
logger.Warningf("loaded admin secret from env var %s instead of from file", fallbackCephSecretEnvVar)
|
|
|
|
|
secret = []byte(adminSecretEnv)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clusterInfo.CephCred.Secret = string(secret)
|
|
|
|
|
if clusterInfo.CephCred.Secret == "" {
|
|
|
|
|
return errors.New("ceph admin secret not found")
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|