|
4 | 4 | "context" |
5 | 5 | "encoding/json" |
6 | 6 | "fmt" |
7 | | - "math/bits" |
8 | 7 | "math/rand" |
9 | 8 | "net" |
10 | 9 | "net/url" |
@@ -587,69 +586,6 @@ func (s *DataStore) ValidateSetting(name, value string) (err error) { |
587 | 586 | } |
588 | 587 | } |
589 | 588 |
|
590 | | - case types.SettingNameDataEngineCPUMask: |
591 | | - definition, ok := types.GetSettingDefinition(types.SettingNameDataEngineCPUMask) |
592 | | - if !ok { |
593 | | - return fmt.Errorf("setting %v is not found", types.SettingNameDataEngineCPUMask) |
594 | | - } |
595 | | - var values map[longhorn.DataEngineType]any |
596 | | - if types.IsJSONFormat(value) { |
597 | | - values, err = types.ParseDataEngineSpecificSetting(definition, value) |
598 | | - } else { |
599 | | - values, err = types.ParseSettingSingleValue(definition, value) |
600 | | - } |
601 | | - if err != nil { |
602 | | - return errors.Wrapf(err, "failed to parse value %v for setting %v", value, types.SettingNameDataEngineCPUMask) |
603 | | - } |
604 | | - |
605 | | - v2DataEngineEnabled, err := s.GetSettingAsBool(types.SettingNameV2DataEngine) |
606 | | - if err != nil { |
607 | | - return errors.Wrapf(err, "failed to get setting %v for setting validation", types.SettingNameV2DataEngine) |
608 | | - } |
609 | | - if !v2DataEngineEnabled { |
610 | | - logrus.Infof("Skipping validating setting %v since v2 data engine is not enabled", types.SettingNameDataEngineCPUMask) |
611 | | - return nil |
612 | | - } |
613 | | - |
614 | | - for dataEngine, raw := range values { |
615 | | - cpuMask, ok := raw.(string) |
616 | | - if !ok { |
617 | | - return fmt.Errorf("setting %v value %v is not a string for data engine %v", types.SettingNameDataEngineCPUMask, raw, dataEngine) |
618 | | - } |
619 | | - |
620 | | - lhNodes, err := s.ListNodesRO() |
621 | | - if err != nil { |
622 | | - return errors.Wrapf(err, "failed to list nodes for %v setting validation for data engine %v", types.SettingNameDataEngineCPUMask, dataEngine) |
623 | | - } |
624 | | - |
625 | | - // Ensure if the CPU mask can be satisfied on each node |
626 | | - for _, lhNode := range lhNodes { |
627 | | - if isUnavailable, err := s.IsNodeDownOrDeletedOrMissingManager(lhNode.Name); err != nil { |
628 | | - return errors.Wrapf(err, "failed to check if node %v is down or deleted", lhNode.Name) |
629 | | - } else if isUnavailable { |
630 | | - continue |
631 | | - } |
632 | | - |
633 | | - kubeNode, err := s.GetKubernetesNodeRO(lhNode.Name) |
634 | | - if err != nil { |
635 | | - if apierrors.IsNotFound(err) { |
636 | | - logrus.Warnf("Kubernetes node %s not found, skipping CPU mask validation for this node for data engine %v", lhNode.Name, dataEngine) |
637 | | - continue |
638 | | - } |
639 | | - return errors.Wrapf(err, "failed to get Kubernetes node %s for %v setting validation for data engine %v", lhNode.Name, types.SettingNameDataEngineCPUMask, dataEngine) |
640 | | - } |
641 | | - |
642 | | - if val, ok := kubeNode.Labels[types.NodeDisableV2DataEngineLabelKey]; ok && val == types.NodeDisableV2DataEngineLabelKeyTrue { |
643 | | - // V2 data engine is disabled on this node, don't worry about cpu mask |
644 | | - continue |
645 | | - } |
646 | | - |
647 | | - if err := s.ValidateCPUMask(kubeNode, cpuMask); err != nil { |
648 | | - return err |
649 | | - } |
650 | | - } |
651 | | - } |
652 | | - |
653 | 589 | case types.SettingNameAutoCleanupSystemGeneratedSnapshot: |
654 | 590 | disablePurgeValue, err := s.GetSettingAsBool(types.SettingNameDisableSnapshotPurge) |
655 | 591 | if err != nil { |
@@ -790,51 +726,6 @@ func (s *DataStore) ValidateV2DataEngineEnabled(dataEngineEnabled bool) (ims []* |
790 | 726 | return |
791 | 727 | } |
792 | 728 |
|
793 | | -func (s *DataStore) ValidateCPUMask(kubeNode *corev1.Node, value string) error { |
794 | | - if value == "" { |
795 | | - return fmt.Errorf("failed to validate CPU mask: cannot be empty") |
796 | | - } |
797 | | - |
798 | | - // CPU mask must start with 0x |
799 | | - cpuMaskRegex := regexp.MustCompile(`^0x[1-9a-fA-F][0-9a-fA-F]*$`) |
800 | | - if !cpuMaskRegex.MatchString(value) { |
801 | | - return fmt.Errorf("invalid CPU mask: %s", value) |
802 | | - } |
803 | | - |
804 | | - maskValue, err := strconv.ParseUint(value[2:], 16, 64) // skip 0x prefix |
805 | | - if err != nil { |
806 | | - return errors.Wrapf(err, "failed to parse CPU mask %v", value) |
807 | | - } |
808 | | - |
809 | | - // Validate the mask value is not larger than the number of available CPUs |
810 | | - numCPUs, err := s.getMinNumCPUsFromAvailableNodes() |
811 | | - if err != nil { |
812 | | - return errors.Wrap(err, "failed to get minimum number of CPUs for CPU mask validation") |
813 | | - } |
814 | | - |
815 | | - maxCPUMaskValue := (1 << numCPUs) - 1 |
816 | | - if maskValue > uint64(maxCPUMaskValue) { |
817 | | - return fmt.Errorf("CPU mask exceeds the maximum allowed value %v for the current system: %s", maxCPUMaskValue, value) |
818 | | - } |
819 | | - |
820 | | - // CPU mask currently only supports v2 data engine |
821 | | - guaranteedInstanceManagerCPUInPercentage, err := s.GetSettingAsFloatByDataEngine(types.SettingNameGuaranteedInstanceManagerCPU, longhorn.DataEngineTypeV2) |
822 | | - if err != nil { |
823 | | - return errors.Wrapf(err, "failed to get %v setting for guaranteed instance manager CPU validation for data engine %v", |
824 | | - types.SettingNameGuaranteedInstanceManagerCPU, longhorn.DataEngineTypeV2) |
825 | | - } |
826 | | - |
827 | | - guaranteedInstanceManagerCPU := float64(kubeNode.Status.Allocatable.Cpu().MilliValue()) * guaranteedInstanceManagerCPUInPercentage / 100 |
828 | | - |
829 | | - numMilliCPUsRequrestedByMaskValue := calculateMilliCPUs(maskValue) |
830 | | - if numMilliCPUsRequrestedByMaskValue > int(guaranteedInstanceManagerCPU) { |
831 | | - return fmt.Errorf("number of CPUs (%v) requested by CPU mask (%v) is larger than the %v setting value (%v)", |
832 | | - numMilliCPUsRequrestedByMaskValue, value, types.SettingNameGuaranteedInstanceManagerCPU, guaranteedInstanceManagerCPU) |
833 | | - } |
834 | | - |
835 | | - return nil |
836 | | -} |
837 | | - |
838 | 729 | func (s *DataStore) getMinNumCPUsFromAvailableNodes() (int64, error) { |
839 | 730 | kubeNodes, err := s.ListKubeNodesRO() |
840 | 731 | if err != nil { |
@@ -873,16 +764,6 @@ func (s *DataStore) getMinNumCPUsFromAvailableNodes() (int64, error) { |
873 | 764 | return minNumCPUs, nil |
874 | 765 | } |
875 | 766 |
|
876 | | -func calculateMilliCPUs(mask uint64) int { |
877 | | - // Count the number of set bits in the mask |
878 | | - setBits := bits.OnesCount64(mask) |
879 | | - |
880 | | - // Each set bit represents 1000 milliCPUs |
881 | | - numMilliCPUsRequestedByMaskValue := setBits * 1000 |
882 | | - |
883 | | - return numMilliCPUsRequestedByMaskValue |
884 | | -} |
885 | | - |
886 | 767 | func (s *DataStore) AreAllRWXVolumesDetached() (bool, error) { |
887 | 768 | volumes, err := s.ListVolumesRO() |
888 | 769 | if err != nil { |
|
0 commit comments