mirror_config.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #!/usr/bin/env python2
  2. # -*- coding:utf-8 -*-
  3. import os
  4. from datetime import datetime
  5. from .mirror_provider import RsyncProvider, TwoStageRsyncProvider, ShellProvider
  6. from .btrfs_snapshot import BtrfsHook
  7. from .loglimit import LogLimitHook
  8. from .exec_pre_post import CmdExecHook
  9. class MirrorConfig(object):
  10. _valid_providers = set(("rsync", "two-stage-rsync", "shell", ))
  11. def __init__(self, parent, options):
  12. self._parent = parent
  13. self._popt = self._parent._settings
  14. self.options = dict(options.items()) # copy
  15. self._validate()
  16. def _validate(self):
  17. provider = self.options.get("provider", None)
  18. assert provider in self._valid_providers
  19. if provider == "rsync":
  20. assert "upstream" in self.options
  21. elif provider == "shell":
  22. assert "command" in self.options
  23. local_dir_tmpl = self.options.get(
  24. "local_dir", self._popt["global"]["local_dir"])
  25. self.options["local_dir"] = local_dir_tmpl.format(
  26. mirror_root=self._popt["global"]["mirror_root"],
  27. mirror_name=self.name,
  28. )
  29. if "interval" not in self.options:
  30. self.options["interval"] = self._popt["global"]["interval"]
  31. assert isinstance(self.options["interval"], int)
  32. log_dir = self.options.get(
  33. "log_dir", self._popt["global"]["log_dir"])
  34. if "log_file" not in self.options:
  35. self.options["log_file"] = os.path.join(
  36. log_dir, self.name, self.name + "_{date}.log")
  37. self.log_dir = os.path.dirname(self.log_file)
  38. if "use_btrfs" not in self.options:
  39. self.options["use_btrfs"] = self._parent.use_btrfs
  40. assert self.options["use_btrfs"] in (True, False)
  41. if "env" in self.options:
  42. assert isinstance(self.options["env"], dict)
  43. def __getattr__(self, key):
  44. if key in self.__dict__:
  45. return self.__dict__[key]
  46. else:
  47. return self.__dict__["options"].get(key, None)
  48. def to_provider(self, hooks=[], no_delay=False):
  49. kwargs = {
  50. 'name': self.name,
  51. 'upstream_url': self.upstream,
  52. 'local_dir': self.local_dir,
  53. 'log_dir': self.log_dir,
  54. 'log_file': self.log_file,
  55. 'interval': self.interval,
  56. 'env': self.env,
  57. 'hooks': hooks,
  58. }
  59. if self.provider == "rsync":
  60. kwargs.update({
  61. 'useIPv6': self.use_ipv6,
  62. 'password': self.password,
  63. 'exclude_file': self.exclude_file,
  64. })
  65. provider = RsyncProvider(**kwargs)
  66. elif self.provider == "two-stage-rsync":
  67. kwargs.update({
  68. 'useIPv6': self.use_ipv6,
  69. 'password': self.password,
  70. 'exclude_file': self.exclude_file,
  71. })
  72. provider = TwoStageRsyncProvider(**kwargs)
  73. provider.set_stage1_profile(self.stage1_profile)
  74. elif self.options["provider"] == "shell":
  75. kwargs.update({
  76. 'command': self.command,
  77. 'log_stdout': self.options.get("log_stdout", True),
  78. })
  79. provider = ShellProvider(**kwargs)
  80. if not no_delay:
  81. sm = self._parent.status_manager
  82. last_update = sm.get_info(self.name, 'last_update')
  83. if last_update not in (None, '-'):
  84. last_update = datetime.strptime(
  85. last_update, '%Y-%m-%d %H:%M:%S')
  86. delay = int(last_update.strftime("%s")) \
  87. + self.interval * 60 - int(datetime.now().strftime("%s"))
  88. if delay < 0:
  89. delay = 0
  90. provider.set_delay(delay)
  91. return provider
  92. def compare(self, other):
  93. assert self.name == other.name
  94. for key, val in self.options.iteritems():
  95. if other.options.get(key, None) != val:
  96. return False
  97. return True
  98. def hooks(self):
  99. hooks = []
  100. parent = self._parent
  101. if self.options["use_btrfs"]:
  102. working_dir = parent.btrfs_working_dir_tmpl.format(
  103. mirror_root=parent.mirror_root,
  104. mirror_name=self.name
  105. )
  106. service_dir = parent.btrfs_service_dir_tmpl.format(
  107. mirror_root=parent.mirror_root,
  108. mirror_name=self.name
  109. )
  110. gc_dir = parent.btrfs_gc_dir_tmpl.format(
  111. mirror_root=parent.mirror_root,
  112. mirror_name=self.name
  113. )
  114. hooks.append(BtrfsHook(service_dir, working_dir, gc_dir))
  115. hooks.append(LogLimitHook())
  116. if self.exec_pre_sync:
  117. hooks.append(
  118. CmdExecHook(self.exec_pre_sync, CmdExecHook.PRE_SYNC))
  119. if self.exec_post_sync:
  120. hooks.append(
  121. CmdExecHook(self.exec_post_sync, CmdExecHook.POST_SYNC))
  122. return hooks
  123. # vim: ts=4 sw=4 sts=4 expandtab