volume_types.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. from typing import TYPE_CHECKING
  2. if TYPE_CHECKING:
  3. from render import Render
  4. from storage import IxStorageNfsConfig, IxStorageCifsConfig, IxStorageVolumeConfig
  5. try:
  6. from .error import RenderError
  7. from .formatter import escape_dollar
  8. from .validations import valid_fs_path_or_raise
  9. except ImportError:
  10. from error import RenderError
  11. from formatter import escape_dollar
  12. from validations import valid_fs_path_or_raise
  13. class NfsVolume:
  14. def __init__(self, render_instance: "Render", config: "IxStorageNfsConfig"):
  15. self._render_instance = render_instance
  16. if not config:
  17. raise RenderError("Expected [nfs_config] to be set for [nfs] type")
  18. required_keys = ["server", "path"]
  19. for key in required_keys:
  20. if not config.get(key):
  21. raise RenderError(f"Expected [{key}] to be set for [nfs] type")
  22. opts = [f"addr={config['server']}"]
  23. cfg_options = config.get("options")
  24. if cfg_options:
  25. if not isinstance(cfg_options, list):
  26. raise RenderError("Expected [nfs_config.options] to be a list for [nfs] type")
  27. tracked_keys: set[str] = set()
  28. disallowed_opts = ["addr"]
  29. for opt in cfg_options:
  30. if not isinstance(opt, str):
  31. raise RenderError("Options for [nfs] type must be a list of strings.")
  32. key = opt.split("=")[0]
  33. if key in tracked_keys:
  34. raise RenderError(f"Option [{key}] already added for [nfs] type.")
  35. if key in disallowed_opts:
  36. raise RenderError(f"Option [{key}] is not allowed for [nfs] type.")
  37. opts.append(opt)
  38. tracked_keys.add(key)
  39. opts.sort()
  40. path = valid_fs_path_or_raise(config["path"].rstrip("/"))
  41. self.volume_spec = {
  42. "driver_opts": {
  43. "type": "nfs",
  44. "device": f":{path}",
  45. "o": f"{','.join([escape_dollar(opt) for opt in opts])}",
  46. },
  47. }
  48. def get(self):
  49. return self.volume_spec
  50. class CifsVolume:
  51. def __init__(self, render_instance: "Render", config: "IxStorageCifsConfig"):
  52. self._render_instance = render_instance
  53. self.volume_spec: dict = {}
  54. if not config:
  55. raise RenderError("Expected [cifs_config] to be set for [cifs] type")
  56. required_keys = ["server", "path", "username", "password"]
  57. for key in required_keys:
  58. if not config.get(key):
  59. raise RenderError(f"Expected [{key}] to be set for [cifs] type")
  60. opts = [
  61. "noperm",
  62. f"user={config['username']}",
  63. f"password={config['password']}",
  64. ]
  65. domain = config.get("domain")
  66. if domain:
  67. opts.append(f"domain={domain}")
  68. cfg_options = config.get("options")
  69. if cfg_options:
  70. if not isinstance(cfg_options, list):
  71. raise RenderError("Expected [cifs_config.options] to be a list for [cifs] type")
  72. tracked_keys: set[str] = set()
  73. disallowed_opts = ["user", "password", "domain", "noperm"]
  74. for opt in cfg_options:
  75. if not isinstance(opt, str):
  76. raise RenderError("Options for [cifs] type must be a list of strings.")
  77. key = opt.split("=")[0]
  78. if key in tracked_keys:
  79. raise RenderError(f"Option [{key}] already added for [cifs] type.")
  80. if key in disallowed_opts:
  81. raise RenderError(f"Option [{key}] is not allowed for [cifs] type.")
  82. for disallowed in disallowed_opts:
  83. if key == disallowed:
  84. raise RenderError(f"Option [{key}] is not allowed for [cifs] type.")
  85. opts.append(opt)
  86. tracked_keys.add(key)
  87. opts.sort()
  88. server = config["server"].lstrip("/")
  89. path = config["path"].strip("/")
  90. path = valid_fs_path_or_raise("/" + path).lstrip("/")
  91. self.volume_spec = {
  92. "driver_opts": {
  93. "type": "cifs",
  94. "device": f"//{server}/{path}",
  95. "o": f"{','.join([escape_dollar(opt) for opt in opts])}",
  96. },
  97. }
  98. def get(self):
  99. return self.volume_spec
  100. class DockerVolume:
  101. def __init__(self, render_instance: "Render", config: "IxStorageVolumeConfig"):
  102. self._render_instance = render_instance
  103. self.volume_spec: dict = {}
  104. def get(self):
  105. return self.volume_spec