/ConfigurationSystem/scripts/dirac-configuration-shell.py

https://github.com/jpbaud/DIRAC · Python · 228 lines · 151 code · 38 blank · 39 comment · 49 complexity · 280516367be52c4fa32d8bdd48845043 MD5 · raw file

  1. #!/usr/bin/env python
  2. """
  3. Script that emulates the behaviour of a shell to edit the CS config.
  4. """
  5. import sys
  6. import os.path
  7. import cmd
  8. from DIRAC.Core.Utilities.ColorCLI import colorize
  9. from DIRAC.Core.Base import Script
  10. from DIRAC.ConfigurationSystem.private.Modificator import Modificator
  11. from DIRAC.ConfigurationSystem.Client.ConfigurationData import gConfigurationData
  12. from DIRAC.Core.DISET.RPCClient import RPCClient
  13. Script.parseCommandLine()
  14. # Invariants:
  15. # * root does not end with "/" or root is "/"
  16. # * root starts with "/"
  17. class CSShellCmd(cmd.Cmd):
  18. def __init__(self):
  19. cmd.Cmd.__init__(self)
  20. self.serverURL = ""
  21. self.serverName = ""
  22. self.modificator = None
  23. self.connected = False
  24. self.dirty = False
  25. self.root = "/"
  26. self.do_connect("")
  27. def update_prompt(self):
  28. if self.connected:
  29. self.prompt = "[" + colorize(self.serverName, "green") + ":" + self.root + " ]% "
  30. else:
  31. self.prompt = "[" + colorize("disconnected", "red") + ":" + self.root + " ]% "
  32. def do_connect(self, line):
  33. """connect
  34. Connect to the CS
  35. Usage: connect <URL> (Connect to the CS at the specified URL)
  36. connect (Connect to the default CS URL of your config)
  37. """
  38. if line == "":
  39. self.serverURL = gConfigurationData.getMasterServer()
  40. self.serverName = gConfigurationData.getName()
  41. else:
  42. self.serverURL = self.serverName = line
  43. if self.serverURL == None:
  44. print "Unable to connect to the default server. Maybe you don't have a proxy ?"
  45. return self.do_disconnect("")
  46. print "Trying to connect to " + self.serverURL + "...",
  47. self.modificator = Modificator(RPCClient(self.serverURL))
  48. rv = self.modificator.loadFromRemote()
  49. rv2 = self.modificator.loadCredentials()
  50. if rv['OK'] == False or rv2['OK'] == False:
  51. print "failed: ",
  52. if rv['OK'] == False: print rv['Message']
  53. else: print rv2['Message']
  54. self.connected = False
  55. self.update_prompt()
  56. else:
  57. self.connected = True
  58. self.update_prompt()
  59. print "done."
  60. def do_disconnect(self, _line):
  61. """Disconnect from CS"""
  62. if self.connected and self.dirty:
  63. res = raw_input("Do you want to commit your changes into the CS ? [y/N] ")
  64. if res.lower() in ["y", "yes"]:
  65. self.do_commit("")
  66. self.serverURL = self.serverName = ""
  67. self.modificator = None
  68. self.connected = False
  69. self.update_prompt()
  70. def do_ls(self, line):
  71. """ls
  72. List the sections and options of CS of the current root"""
  73. if self.connected:
  74. secs = self.modificator.getSections(self.root)
  75. opts = self.modificator.getOptions(self.root)
  76. if line.startswith("-") and "l" in line:
  77. for i in secs:
  78. print colorize(i, "blue") + " "
  79. for i in opts:
  80. print i + " "
  81. else:
  82. for i in secs:
  83. print colorize(i, "blue") + " ",
  84. for i in opts:
  85. print i + " ",
  86. print ""
  87. def do_cd(self, line):
  88. """cd
  89. Go one directory deeper in the CS"""
  90. # Check if invariant holds
  91. if self.connected:
  92. assert(self.root == "/" or not self.root.endswith("/"))
  93. assert(self.root.startswith("/"))
  94. secs = self.modificator.getSections(self.root)
  95. if line == "..":
  96. self.root = os.path.dirname(self.root)
  97. self.update_prompt()
  98. else:
  99. if os.path.normpath(line) in secs:
  100. if self.root == "/":
  101. self.root = self.root + os.path.normpath(line)
  102. else:
  103. self.root = self.root + "/" + os.path.normpath(line)
  104. self.update_prompt()
  105. else:
  106. print "cd: no such section: " + line
  107. def complete_cd(self, text, _line, _begidx, _endidx):
  108. secs = self.modificator.getSections(self.root)
  109. return [(s + "/") for s in secs if s.startswith(text)]
  110. def do_cat(self, line):
  111. """cat
  112. Read the content of an option in the CS"""
  113. if self.connected:
  114. opts = self.modificator.getOptionsDict(self.root)
  115. if line in opts.keys():
  116. print opts[line]
  117. else:
  118. print "cat: No such option"
  119. def complete_cat(self, text, _line, _begidx, _endidx):
  120. opts = self.modificator.getOptions(self.root)
  121. return [o for o in opts if o.startswith(text)]
  122. do_less = do_cat
  123. complete_less = complete_cat
  124. def do_mkdir(self, line):
  125. """mkdir
  126. Create a new section in the CS"""
  127. if self.connected:
  128. self.modificator.createSection(self.root + "/" + line)
  129. self.dirty = True
  130. complete_mkdir = complete_cd
  131. def do_rmdir(self, line):
  132. """rmdir
  133. Delete a section in the CS"""
  134. if self.connected:
  135. self.modificator.removeSection(self.root + "/" + line)
  136. self.dirty = True
  137. complete_rmdir = complete_cd
  138. def do_rm(self, line):
  139. """rm
  140. Delete an option in the CS"""
  141. if self.connected:
  142. self.modificator.removeOption(self.root + "/" + line)
  143. self.dirty = True
  144. complete_rm = complete_cat
  145. def do_set(self, line):
  146. """set
  147. Set an option in the CS (or create it if it does not exists)
  148. Usage: set <str> to set a string option (will be stored as a string in CS)
  149. set <str>,<str>,... to set a list option (will be stored as a list in CS)
  150. """
  151. if self.connected:
  152. line = line.split(" ", 2)
  153. if len(line) != 2:
  154. print "Usage: set <key> <value>"
  155. else:
  156. self.modificator.setOptionValue(self.root + "/" + line[0], line[1])
  157. self.dirty = True
  158. complete_set = complete_cat
  159. def do_unset(self, line):
  160. """unset
  161. Unset an option in the CS: Making the option equal to the
  162. empty string."""
  163. if self.connected:
  164. self.modificator.setOptionValue(self.root + "/" + line, "")
  165. self.dirty = True
  166. complete_unset = complete_cat
  167. def do_commit(self, _line):
  168. """commit
  169. Commit the modifications to the CS"""
  170. if self.connected and self.dirty:
  171. self.modificator.commit()
  172. def default(self, line):
  173. """Override [Cmd.default(line)] function."""
  174. if line == "EOF":
  175. if self.prompt:
  176. print
  177. return self.do_quit(line)
  178. else:
  179. cmd.Cmd.default(self, line)
  180. def do_quit(self, _line):
  181. """quit
  182. Quit"""
  183. self.do_disconnect("")
  184. return True
  185. do_exit = do_quit
  186. def main():
  187. shell = CSShellCmd()
  188. shell.cmdloop()
  189. if __name__ == "__main__":
  190. sys.exit(main())