github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/cmd/ndm_daemonset/filter/pathfilter.go (about)

     1  /*
     2  Copyright 2018 The OpenEBS Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package filter
    18  
    19  import (
    20  	"github.com/openebs/node-disk-manager/blockdevice"
    21  	libudevwrapper "github.com/openebs/node-disk-manager/pkg/udev"
    22  
    23  	"strings"
    24  
    25  	"github.com/openebs/node-disk-manager/cmd/ndm_daemonset/controller"
    26  	"github.com/openebs/node-disk-manager/pkg/util"
    27  )
    28  
    29  const (
    30  	pathFilterKey = "path-filter"
    31  )
    32  
    33  var (
    34  	pathFilterName  = "path filter"  // filter device paths
    35  	pathFilterState = defaultEnabled // filter state
    36  	includePaths    = ""
    37  	excludePaths    = "loop"
    38  )
    39  
    40  // pathFilterRegister contains registration process of PathFilter
    41  var pathFilterRegister = func() {
    42  	ctrl := <-controller.ControllerBroadcastChannel
    43  	if ctrl == nil {
    44  		return
    45  	}
    46  	if ctrl.NDMConfig != nil {
    47  		for _, filterConfig := range ctrl.NDMConfig.FilterConfigs {
    48  			if filterConfig.Key == pathFilterKey {
    49  				pathFilterName = filterConfig.Name
    50  				pathFilterState = util.CheckTruthy(filterConfig.State)
    51  				includePaths = filterConfig.Include
    52  				excludePaths = filterConfig.Exclude
    53  				break
    54  			}
    55  		}
    56  	}
    57  	var fi controller.FilterInterface = newPathFilter(ctrl)
    58  	newRegisterFilter := &registerFilter{
    59  		name:       pathFilterName,
    60  		state:      pathFilterState,
    61  		fi:         fi,
    62  		controller: ctrl,
    63  	}
    64  	newRegisterFilter.register()
    65  }
    66  
    67  // pathFilter contains controller and include and exclude keywords
    68  type pathFilter struct {
    69  	controller   *controller.Controller
    70  	excludePaths []string
    71  	includePaths []string
    72  }
    73  
    74  // newPathFilter returns new pointer PathFilter
    75  func newPathFilter(ctrl *controller.Controller) *pathFilter {
    76  	return &pathFilter{
    77  		controller: ctrl,
    78  	}
    79  }
    80  
    81  // Start sets include and exclude path keywords list
    82  func (pf *pathFilter) Start() {
    83  	pf.includePaths = make([]string, 0)
    84  	pf.excludePaths = make([]string, 0)
    85  	if includePaths != "" {
    86  		pf.includePaths = strings.Split(includePaths, ",")
    87  	}
    88  	if excludePaths != "" {
    89  		pf.excludePaths = strings.Split(excludePaths, ",")
    90  	}
    91  }
    92  
    93  // Include returns true if the disk path matches with given list
    94  // of keywords
    95  func (pf *pathFilter) Include(blockDevice *blockdevice.BlockDevice) bool {
    96  	if len(pf.includePaths) == 0 {
    97  		return true
    98  	}
    99  	if util.Contains(blockdevice.DeviceMapperDeviceTypes,
   100  		blockDevice.DeviceAttributes.DeviceType) {
   101  		if util.MatchIgnoredCase(pf.includePaths, blockDevice.DMInfo.DevMapperPath) {
   102  			return true
   103  		}
   104  	}
   105  	if util.MatchIgnoredCase(pf.includePaths, blockDevice.DevPath) {
   106  		return true
   107  	}
   108  	for _, link := range blockDevice.DevLinks {
   109  		if link.Kind == libudevwrapper.SYMLINK {
   110  			for _, symlink := range link.Links {
   111  				if util.Contains(pf.includePaths, symlink) {
   112  					return true
   113  				}
   114  			}
   115  		}
   116  	}
   117  	return false
   118  }
   119  
   120  // Exclude returns true if the disk path does not match any given
   121  // keywords
   122  func (pf *pathFilter) Exclude(blockDevice *blockdevice.BlockDevice) bool {
   123  	if len(pf.excludePaths) == 0 {
   124  		return true
   125  	}
   126  	// for DM devices, need to check both the devpath and device mapper path
   127  	if util.Contains(blockdevice.DeviceMapperDeviceTypes,
   128  		blockDevice.DeviceAttributes.DeviceType) {
   129  		if util.MatchIgnoredCase(pf.excludePaths, blockDevice.DMInfo.DevMapperPath) {
   130  			return false
   131  		}
   132  	}
   133  	if util.MatchIgnoredCase(pf.excludePaths, blockDevice.DevPath) {
   134  		return false
   135  	}
   136  	for _, link := range blockDevice.DevLinks {
   137  		if link.Kind == libudevwrapper.SYMLINK {
   138  			for _, symlink := range link.Links {
   139  				if util.Contains(pf.excludePaths, symlink) {
   140  					return false
   141  				}
   142  			}
   143  		}
   144  	}
   145  	return true
   146  }