rbd: use blocklist range cmd, fallback if it fails

This commit adds blocklist range cmd feature,
while fallbacks to old blocklist one ip at a
time if the cmd is invalid(not available).

Signed-off-by: Rakshith R <rar@redhat.com>
This commit is contained in:
Rakshith R 2022-09-13 15:43:21 +05:30 committed by mergify[bot]
parent 3d04065d00
commit a57859dfa4

View File

@ -18,6 +18,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"strings"
"github.com/ceph/ceph-csi/internal/util" "github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log" "github.com/ceph/ceph-csi/internal/util/log"
@ -25,7 +26,10 @@ import (
"github.com/csi-addons/spec/lib/go/fence" "github.com/csi-addons/spec/lib/go/fence"
) )
const blocklistTime = "157784760" const (
blocklistTime = "157784760"
invalidCommandStr = "invalid command"
)
// NetworkFence contains the CIDR blocks to be blocked. // NetworkFence contains the CIDR blocks to be blocked.
type NetworkFence struct { type NetworkFence struct {
@ -65,7 +69,7 @@ func NewNetworkFence(
} }
// addCephBlocklist adds an IP to ceph osd blocklist. // addCephBlocklist adds an IP to ceph osd blocklist.
func (nf *NetworkFence) addCephBlocklist(ctx context.Context, ip string) error { func (nf *NetworkFence) addCephBlocklist(ctx context.Context, ip string, useRange bool) error {
arg := []string{ arg := []string{
"--id", nf.cr.ID, "--id", nf.cr.ID,
"--keyfile=" + nf.cr.KeyFile, "--keyfile=" + nf.cr.KeyFile,
@ -77,11 +81,18 @@ func (nf *NetworkFence) addCephBlocklist(ctx context.Context, ip string) error {
// represent infinity from ceph-csi side. // represent infinity from ceph-csi side.
// At any point in this time, the IPs can be unblocked by an UnfenceClusterReq. // At any point in this time, the IPs can be unblocked by an UnfenceClusterReq.
// This needs to be updated once ceph provides functionality for the same. // This needs to be updated once ceph provides functionality for the same.
cmd := []string{"osd", "blocklist", "add", ip, blocklistTime} cmd := []string{"osd", "blocklist"}
if useRange {
cmd = append(cmd, "range")
}
cmd = append(cmd, "add", ip, blocklistTime)
cmd = append(cmd, arg...) cmd = append(cmd, arg...)
_, _, err := util.ExecCommand(ctx, "ceph", cmd...) _, stdErr, err := util.ExecCommand(ctx, "ceph", cmd...)
if err != nil { if err != nil {
return fmt.Errorf("failed to blocklist IP %q: %w", ip, err) return fmt.Errorf("failed to blocklist IP %q: %w stderr: %q", ip, err, stdErr)
}
if stdErr != "" {
return fmt.Errorf("failed to blocklist IP %q: %q", ip, stdErr)
} }
log.DebugLog(ctx, "blocklisted IP %q successfully", ip) log.DebugLog(ctx, "blocklisted IP %q successfully", ip)
@ -91,8 +102,21 @@ func (nf *NetworkFence) addCephBlocklist(ctx context.Context, ip string) error {
// AddNetworkFence blocks access for all the IPs in the IP range mentioned via the CIDR block // AddNetworkFence blocks access for all the IPs in the IP range mentioned via the CIDR block
// using a network fence. // using a network fence.
func (nf *NetworkFence) AddNetworkFence(ctx context.Context) error { func (nf *NetworkFence) AddNetworkFence(ctx context.Context) error {
hasBlocklistRangeSupport := true
// for each CIDR block, convert it into a range of IPs so as to perform blocklisting operation. // for each CIDR block, convert it into a range of IPs so as to perform blocklisting operation.
for _, cidr := range nf.Cidr { for _, cidr := range nf.Cidr {
// try range blocklist cmd, if invalid fallback to
// iterating through IP range.
if hasBlocklistRangeSupport {
err := nf.addCephBlocklist(ctx, cidr, true)
if err == nil {
continue
}
if !strings.Contains(err.Error(), invalidCommandStr) {
return fmt.Errorf("failed to add blocklist range %q: %w", cidr, err)
}
hasBlocklistRangeSupport = false
}
// fetch the list of IPs from a CIDR block // fetch the list of IPs from a CIDR block
hosts, err := getIPRange(cidr) hosts, err := getIPRange(cidr)
if err != nil { if err != nil {
@ -101,7 +125,7 @@ func (nf *NetworkFence) AddNetworkFence(ctx context.Context) error {
// add ceph blocklist for each IP in the range mentioned by the CIDR // add ceph blocklist for each IP in the range mentioned by the CIDR
for _, host := range hosts { for _, host := range hosts {
err = nf.addCephBlocklist(ctx, host) err = nf.addCephBlocklist(ctx, host, false)
if err != nil { if err != nil {
return err return err
} }
@ -154,19 +178,26 @@ func GetCIDR(cidrs Cidrs) ([]string, error) {
} }
// removeCephBlocklist removes an IP from ceph osd blocklist. // removeCephBlocklist removes an IP from ceph osd blocklist.
func (nf *NetworkFence) removeCephBlocklist(ctx context.Context, ip string) error { func (nf *NetworkFence) removeCephBlocklist(ctx context.Context, ip string, useRange bool) error {
arg := []string{ arg := []string{
"--id", nf.cr.ID, "--id", nf.cr.ID,
"--keyfile=" + nf.cr.KeyFile, "--keyfile=" + nf.cr.KeyFile,
"-m", nf.Monitors, "-m", nf.Monitors,
} }
cmd := []string{"osd", "blocklist", "rm", ip} cmd := []string{"osd", "blocklist"}
if useRange {
cmd = append(cmd, "range")
}
cmd = append(cmd, "rm", ip)
cmd = append(cmd, arg...) cmd = append(cmd, arg...)
_, stdErr, err := util.ExecCommand(ctx, "ceph", cmd...) _, stdErr, err := util.ExecCommand(ctx, "ceph", cmd...)
if err != nil { if err != nil {
return fmt.Errorf("failed to unblock IP %q: %v %w", ip, stdErr, err) return fmt.Errorf("failed to unblock IP %q: %v %w", ip, stdErr, err)
} }
if stdErr != "" {
return fmt.Errorf("failed to unblock IP %q: %q", ip, stdErr)
}
log.DebugLog(ctx, "unblocked IP %q successfully", ip) log.DebugLog(ctx, "unblocked IP %q successfully", ip)
return nil return nil
@ -175,8 +206,21 @@ func (nf *NetworkFence) removeCephBlocklist(ctx context.Context, ip string) erro
// RemoveNetworkFence unblocks access for all the IPs in the IP range mentioned via the CIDR block // RemoveNetworkFence unblocks access for all the IPs in the IP range mentioned via the CIDR block
// using a network fence. // using a network fence.
func (nf *NetworkFence) RemoveNetworkFence(ctx context.Context) error { func (nf *NetworkFence) RemoveNetworkFence(ctx context.Context) error {
hasBlocklistRangeSupport := true
// for each CIDR block, convert it into a range of IPs so as to undo blocklisting operation. // for each CIDR block, convert it into a range of IPs so as to undo blocklisting operation.
for _, cidr := range nf.Cidr { for _, cidr := range nf.Cidr {
// try range blocklist cmd, if invalid fallback to
// iterating through IP range.
if hasBlocklistRangeSupport {
err := nf.removeCephBlocklist(ctx, cidr, true)
if err == nil {
continue
}
if !strings.Contains(err.Error(), invalidCommandStr) {
return fmt.Errorf("failed to remove blocklist range %q: %w", cidr, err)
}
hasBlocklistRangeSupport = false
}
// fetch the list of IPs from a CIDR block // fetch the list of IPs from a CIDR block
hosts, err := getIPRange(cidr) hosts, err := getIPRange(cidr)
if err != nil { if err != nil {
@ -184,7 +228,7 @@ func (nf *NetworkFence) RemoveNetworkFence(ctx context.Context) error {
} }
// remove ceph blocklist for each IP in the range mentioned by the CIDR // remove ceph blocklist for each IP in the range mentioned by the CIDR
for _, host := range hosts { for _, host := range hosts {
err := nf.removeCephBlocklist(ctx, host) err := nf.removeCephBlocklist(ctx, host, false)
if err != nil { if err != nil {
return err return err
} }