You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 lines
10 KiB

  1. #!/usr/bin/env python
  2. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  3. # not use this file except in compliance with the License. You may obtain
  4. # a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software
  9. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  10. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  11. # License for the specific language governing permissions and limitations
  12. # under the License.
  13. import json
  14. import random
  15. import uuid
  16. from oslo_config import cfg
  17. from oslo_log import log
  18. from prettytable import PrettyTable
  19. import requests
  20. from faafo import version
  21. LOG = log.getLogger('faafo.client')
  22. CONF = cfg.CONF
  23. def get_random_task():
  24. random.seed()
  25. if CONF.command.width:
  26. width = int(CONF.command.width)
  27. else:
  28. width = random.randint(int(CONF.command.min_width),
  29. int(CONF.command.max_width))
  30. if CONF.command.height:
  31. height = int(CONF.command.height)
  32. else:
  33. height = random.randint(int(CONF.command.min_height),
  34. int(CONF.command.max_height))
  35. if CONF.command.iterations:
  36. iterations = int(CONF.command.iterations)
  37. else:
  38. iterations = random.randint(int(CONF.command.min_iterations),
  39. int(CONF.command.max_iterations))
  40. if CONF.command.xa:
  41. xa = float(CONF.command.xa)
  42. else:
  43. xa = random.uniform(float(CONF.command.min_xa),
  44. float(CONF.command.max_xa))
  45. if CONF.command.xb:
  46. xb = float(CONF.command.xb)
  47. else:
  48. xb = random.uniform(float(CONF.command.min_xb),
  49. float(CONF.command.max_xb))
  50. if CONF.command.ya:
  51. ya = float(CONF.command.ya)
  52. else:
  53. ya = random.uniform(float(CONF.command.min_ya),
  54. float(CONF.command.max_ya))
  55. if CONF.command.yb:
  56. yb = float(CONF.command.yb)
  57. else:
  58. yb = random.uniform(float(CONF.command.min_yb),
  59. float(CONF.command.max_yb))
  60. task = {
  61. 'data': {
  62. 'type': 'fractal',
  63. 'attributes': {
  64. 'uuid': str(uuid.uuid4()),
  65. 'width': width,
  66. 'height': height,
  67. 'iterations': iterations,
  68. 'xa': xa,
  69. 'xb': xb,
  70. 'ya': ya,
  71. 'yb': yb
  72. }
  73. }
  74. }
  75. return task
  76. def do_get_fractal():
  77. LOG.error("command 'download' not yet implemented")
  78. def do_show_fractal():
  79. LOG.info("showing fractal %s" % CONF.command.uuid)
  80. headers = {'Content-Type': 'application/vnd.api+json',
  81. 'Accept': 'application/vnd.api+json'}
  82. result = requests.get("%s/v1/fractal/%s" %
  83. (CONF.endpoint_url, CONF.command.uuid),
  84. headers=headers)
  85. LOG.debug("result: %s" % result.text)
  86. if result.status_code == 200:
  87. data = json.loads(result.text)
  88. fractal_data = data['data']['attributes']
  89. output = PrettyTable(["Parameter", "Value"])
  90. output.align["Parameter"] = "l"
  91. output.align["Value"] = "l"
  92. output.add_row(["uuid", fractal_data['uuid']])
  93. output.add_row(["duration", "%f seconds" % fractal_data['duration']])
  94. output.add_row(["dimensions", "%d x %d pixels" %
  95. (fractal_data['width'], fractal_data['height'])])
  96. output.add_row(["iterations", fractal_data['iterations']])
  97. output.add_row(["xa", fractal_data['xa']])
  98. output.add_row(["xb", fractal_data['xb']])
  99. output.add_row(["ya", fractal_data['ya']])
  100. output.add_row(["yb", fractal_data['yb']])
  101. output.add_row(["size", "%d bytes" % fractal_data['size']])
  102. output.add_row(["checksum", fractal_data['checksum']])
  103. output.add_row(["generated_by", fractal_data['generated_by']])
  104. print(output)
  105. else:
  106. LOG.error("fractal '%s' not found" % CONF.command.uuid)
  107. def do_list_fractals():
  108. LOG.info("listing all fractals")
  109. fractals = get_fractals()
  110. output = PrettyTable(["UUID", "Dimensions", "Filesize"])
  111. for fractal in fractals:
  112. fractal_data = fractal['attributes']
  113. output.add_row([
  114. fractal_data["uuid"],
  115. "%d x %d pixels" % (fractal_data["width"], fractal_data["height"]),
  116. "%d bytes" % (fractal_data["size"] or 0),
  117. ])
  118. print(output)
  119. def get_fractals(page=1):
  120. headers = {'Content-Type': 'application/vnd.api+json',
  121. 'Accept': 'application/vnd.api+json'}
  122. result = requests.get("%s/v1/fractal?page=%d&page[size]=10" %
  123. (CONF.endpoint_url, page),
  124. headers=headers)
  125. LOG.debug("result: %s" % result.text)
  126. fractals = []
  127. if result.status_code == 200:
  128. data = json.loads(result.text)
  129. if (page * 10) < data['meta']['total']:
  130. fractals = data['data'] + get_fractals(page + 1)
  131. else:
  132. return data['data']
  133. return fractals
  134. def do_delete_fractal():
  135. LOG.info("deleting fractal %s" % CONF.command.uuid)
  136. headers = {'Content-Type': 'application/vnd.api+json',
  137. 'Accept': 'application/vnd.api+json'}
  138. result = requests.delete("%s/v1/fractal/%s" %
  139. (CONF.endpoint_url, CONF.command.uuid),
  140. headers=headers)
  141. LOG.debug("result: %s" % result.text)
  142. def do_create_fractal():
  143. random.seed()
  144. if CONF.command.tasks:
  145. number = int(CONF.command.tasks)
  146. else:
  147. number = random.randint(int(CONF.command.min_tasks),
  148. int(CONF.command.max_tasks))
  149. LOG.info("generating %d task(s)" % number)
  150. for i in range(0, number):
  151. task = get_random_task()
  152. LOG.debug("created task %s" % task)
  153. headers = {'Content-Type': 'application/vnd.api+json',
  154. 'Accept': 'application/vnd.api+json'}
  155. resp = requests.post("%s/v1/fractal" % CONF.endpoint_url,
  156. json.dumps(task), headers=headers)
  157. LOG.debug("resp: %s" % resp.text)
  158. def add_command_parsers(subparsers):
  159. parser = subparsers.add_parser('create')
  160. parser.set_defaults(func=do_create_fractal)
  161. parser.add_argument("--height", default=None,
  162. help="The height of the generate image.")
  163. parser.add_argument("--min-height", default=256,
  164. help="The minimum height of the generate image.")
  165. parser.add_argument("--max-height", default=1024,
  166. help="The maximum height of the generate image.")
  167. parser.add_argument("--width", default=None,
  168. help="The width of the generated image.")
  169. parser.add_argument("--min-width", default=256,
  170. help="The minimum width of the generated image.")
  171. parser.add_argument("--max-width", default=1024,
  172. help="The maximum width of the generated image.")
  173. parser.add_argument("--iterations", default=None,
  174. help="The number of iterations.")
  175. parser.add_argument("--min-iterations", default=128,
  176. help="The minimum number of iterations.")
  177. parser.add_argument("--max-iterations", default=512,
  178. help="The maximum number of iterations.")
  179. parser.add_argument("--tasks", default=None,
  180. help="The number of generated fractals.")
  181. parser.add_argument("--min-tasks", default=1,
  182. help="The minimum number of generated fractals.")
  183. parser.add_argument("--max-tasks", default=10,
  184. help="The maximum number of generated fractals.")
  185. parser.add_argument("--xa", default=None,
  186. help="The value for the parameter 'xa'.")
  187. parser.add_argument("--min-xa", default=-1.0,
  188. help="The minimum value for the parameter 'xa'.")
  189. parser.add_argument("--max-xa", default=-4.0,
  190. help="The maximum value for the parameter 'xa'.")
  191. parser.add_argument("--xb", default=None,
  192. help="The value for the parameter 'xb'.")
  193. parser.add_argument("--min-xb", default=1.0,
  194. help="The minimum value for the parameter 'xb'.")
  195. parser.add_argument("--max-xb", default=4.0,
  196. help="The maximum value for the parameter 'xb'.")
  197. parser.add_argument("--ya", default=None,
  198. help="The value for the parameter 'ya'.")
  199. parser.add_argument("--min-ya", default=-0.5,
  200. help="The minimum value for the parameter 'ya'.")
  201. parser.add_argument("--max-ya", default=-3,
  202. help="The maximum value for the parameter 'ya'.")
  203. parser.add_argument("--yb", default=None,
  204. help="The value for the parameter 'yb'.")
  205. parser.add_argument("--min-yb", default=0.5,
  206. help="The minimum value for the parameter 'yb'.")
  207. parser.add_argument("--max-yb", default=3,
  208. help="The maximum value for the parameter 'yb'.")
  209. parser = subparsers.add_parser('delete')
  210. parser.set_defaults(func=do_delete_fractal)
  211. parser.add_argument("uuid", help="Fractal to delete.")
  212. parser = subparsers.add_parser('show')
  213. parser.set_defaults(func=do_show_fractal)
  214. parser.add_argument("uuid", help="Fractal to show.")
  215. parser = subparsers.add_parser('get')
  216. parser.set_defaults(func=do_get_fractal)
  217. parser.add_argument("uuid", help="Fractal to download.")
  218. parser = subparsers.add_parser('list')
  219. parser.set_defaults(func=do_list_fractals)
  220. client_commands = cfg.SubCommandOpt('command', title='Commands',
  221. help='Show available commands.',
  222. handler=add_command_parsers)
  223. CONF.register_cli_opts([client_commands])
  224. client_cli_opts = [
  225. cfg.StrOpt('endpoint-url',
  226. default='http://localhost',
  227. help='API connection URL')
  228. ]
  229. CONF.register_cli_opts(client_cli_opts)
  230. if __name__ == '__main__':
  231. log.register_options(CONF)
  232. log.set_defaults()
  233. CONF(project='client', prog='faafo-client',
  234. version=version.version_info.version_string())
  235. log.setup(CONF, 'client',
  236. version=version.version_info.version_string())
  237. CONF.command.func()