clonetree_linux.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. //
  2. // Use and distribution licensed under the Apache license version 2.
  3. //
  4. // See the COPYING file in the root project directory for full text.
  5. //
  6. package snapshot
  7. import (
  8. "io/ioutil"
  9. "os"
  10. "path/filepath"
  11. )
  12. func setupScratchDir(scratchDir string) error {
  13. var createPaths = []string{
  14. "sys/block",
  15. }
  16. for _, path := range createPaths {
  17. if err := os.MkdirAll(filepath.Join(scratchDir, path), os.ModePerm); err != nil {
  18. return err
  19. }
  20. }
  21. return createBlockDevices(scratchDir)
  22. }
  23. // ExpectedCloneStaticContent return a slice of glob patterns which represent the pseudofiles
  24. // ghw cares about, and which are independent from host specific topology or configuration,
  25. // thus are safely represented by a static slice - e.g. they don't need to be discovered at runtime.
  26. func ExpectedCloneStaticContent() []string {
  27. return []string{
  28. "/proc/cpuinfo",
  29. "/proc/meminfo",
  30. "/proc/self/mounts",
  31. "/sys/devices/system/cpu/cpu*/cache/index*/*",
  32. "/sys/devices/system/cpu/cpu*/topology/*",
  33. "/sys/devices/system/memory/block_size_bytes",
  34. "/sys/devices/system/memory/memory*/online",
  35. "/sys/devices/system/memory/memory*/state",
  36. "/sys/devices/system/node/has_*",
  37. "/sys/devices/system/node/online",
  38. "/sys/devices/system/node/possible",
  39. "/sys/devices/system/node/node*/cpu*",
  40. "/sys/devices/system/node/node*/distance",
  41. "/sys/devices/system/node/node*/meminfo",
  42. "/sys/devices/system/node/node*/memory*",
  43. "/sys/devices/system/node/node*/hugepages/hugepages-*/*",
  44. }
  45. }
  46. type filterFunc func(string) bool
  47. // cloneContentByClass copies all the content related to a given device class
  48. // (devClass), possibly filtering out devices whose name does NOT pass a
  49. // filter (filterName). Each entry in `/sys/class/$CLASS` is actually a
  50. // symbolic link. We can filter out entries depending on the link target.
  51. // Each filter is a simple function which takes the entry name or the link
  52. // target and must return true if the entry should be collected, false
  53. // otherwise. Last, explicitly collect a list of attributes for each entry,
  54. // given as list of glob patterns as `subEntries`.
  55. // Return the final list of glob patterns to be collected.
  56. func cloneContentByClass(devClass string, subEntries []string, filterName filterFunc, filterLink filterFunc) []string {
  57. var fileSpecs []string
  58. // warning: don't use the context package here, this means not even the linuxpath package.
  59. // TODO(fromani) remove the path duplication
  60. sysClass := filepath.Join("sys", "class", devClass)
  61. entries, err := ioutil.ReadDir(sysClass)
  62. if err != nil {
  63. // we should not import context, hence we can't Warn()
  64. return fileSpecs
  65. }
  66. for _, entry := range entries {
  67. devName := entry.Name()
  68. if !filterName(devName) {
  69. continue
  70. }
  71. devPath := filepath.Join(sysClass, devName)
  72. dest, err := os.Readlink(devPath)
  73. if err != nil {
  74. continue
  75. }
  76. if !filterLink(dest) {
  77. continue
  78. }
  79. // so, first copy the symlink itself
  80. fileSpecs = append(fileSpecs, devPath)
  81. // now we have to clone the content of the actual entry
  82. // related (and found into a subdir of) the backing hardware
  83. // device
  84. devData := filepath.Clean(filepath.Join(sysClass, dest))
  85. for _, subEntry := range subEntries {
  86. fileSpecs = append(fileSpecs, filepath.Join(devData, subEntry))
  87. }
  88. }
  89. return fileSpecs
  90. }
  91. // filterNone allows all content, filtering out none of it
  92. func filterNone(_ string) bool {
  93. return true
  94. }