odoo_resource.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. from django.conf.urls import url
  4. from django.conf import settings
  5. from tastypie.resources import Resource
  6. from tastypie.utils import trailing_slash
  7. from core.models.request import Request
  8. from api.utils.odoo_api import (
  9. normalize_name,
  10. check_name,
  11. randomize_port,
  12. create_folders,
  13. create_configuration,
  14. create_database,
  15. copy_database_seed,
  16. restore_database,
  17. remove_database_seed,
  18. create_odoo_container,
  19. apply_permissions,
  20. get_odoo_internal_ip,
  21. install_modules
  22. )
  23. from api.utils.jwt_token import get_user
  24. from api.utils.jwt_authentication import JWTAuthentication
  25. from api.utils.logger import (
  26. info,
  27. error,
  28. warning
  29. )
  30. from api.utils.email import send_email
  31. from simplejson import JSONDecodeError
  32. import simplejson as json
  33. class OdooResource(Resource):
  34. class Meta:
  35. authentication = JWTAuthentication()
  36. '''
  37. '''
  38. def prepend_urls(self):
  39. return [
  40. url(r'^(?P<resource_name>%s)/create%s$' % (self._meta.resource_name, trailing_slash), self.wrap_view('odoo_create'), name='api_odoo_create'),
  41. url(r'^(?P<resource_name>%s)/install_module%s$' % (self._meta.resource_name, trailing_slash), self.wrap_view('install_odoo_module'), name='api_install_odoo_module'),
  42. ]
  43. '''
  44. '''
  45. def odoo_create(self, request, **kwargs):
  46. info('odoo creation is requested')
  47. self.method_check(request, allowed='post')
  48. self.is_authenticated(request)
  49. authorization_header = request.META.get(settings.JWT_ACCEPT_HEADER)
  50. prefix_length = len(settings.JWT_PREFIX_HEADER)
  51. user = get_user(authorization_header[prefix_length + 1:])
  52. info('%s is authenticated' % user.username)
  53. name = None
  54. try:
  55. data = json.loads(request.body)
  56. name = data['name']
  57. except JSONDecodeError:
  58. name = None
  59. error('json decode error')
  60. except KeyError:
  61. name = None
  62. error('key error')
  63. r = Request.objects.create(name='Crear contenedor Odoo')
  64. r.user = user
  65. if not name:
  66. r.issue = 'name is required'
  67. r.status = 5
  68. r.save()
  69. error('name is required')
  70. return self.create_response(request, {
  71. 'error_message': 'name is required'
  72. })
  73. info('%s: request is ok' % name)
  74. # 1. Check and get name
  75. name = normalize_name(name)
  76. name_exists = check_name(name)
  77. if name_exists:
  78. r.issue = '%s: name is already exists' % name
  79. r.status = 5
  80. r.save()
  81. error('%s: name is already exists' % name)
  82. return self.create_response(request, {
  83. 'error_message': '%s: name is already exists' % name
  84. })
  85. info('%s: name is ok' % name)
  86. # 2. Get port
  87. port = randomize_port()
  88. info('%s: port is ok' % port)
  89. # 3. Folder structure create
  90. folders_created = create_folders(name)
  91. if not folders_created:
  92. r.issue = '%s: folders structure cannot be created' % name
  93. r.status = 5
  94. r.save()
  95. error('%s: folders structure cannot be created' % name)
  96. return self.create_response(request, {
  97. 'error_message': '%s: folders structure cannot be created' % name
  98. })
  99. info('%s: folders is ok' % name)
  100. # 4. Configuration create
  101. conf_created = create_configuration(name)
  102. if not conf_created:
  103. r.issue = '%s: configuration cannot be created' % name
  104. r.status = 5
  105. r.save()
  106. error('%s: configuration cannot be created' % name)
  107. return self.create_response(request, {
  108. 'error_message': '%s: configuration cannot be created' % name
  109. })
  110. info('%s: configuration is ok' % name)
  111. # 5. Database create
  112. db_created = create_database(name)
  113. if not db_created:
  114. r.issue = '%s: database cannot be created' % name
  115. r.status = 5
  116. r.save()
  117. error('%s: database cannot be created' % name)
  118. return self.create_response(request, {
  119. 'error_message': '%s: database cannot be created' % name
  120. })
  121. info('%s: database is ok' % name)
  122. # 6. Copy a database backup
  123. seed_copied = copy_database_seed()
  124. if not seed_copied:
  125. r.issue = '%s: database seed cannot be copied' % name
  126. r.status = 5
  127. r.save()
  128. error('%s: database seed cannot be copied' % name)
  129. return self.create_response(request, {
  130. 'error_message': '%s: database seed cannot be copied' % name
  131. })
  132. info('%s: database seed is ok' % name)
  133. # 7. Restore database schema
  134. db_restored = restore_database(name)
  135. if not db_restored:
  136. r.issue = '%s: database cannot be restored' % name
  137. r.status = 5
  138. r.save()
  139. error('%s: database cannot be restored' % name)
  140. return self.create_response(request, {
  141. 'error_message': '%s: database cannot be restored' % name
  142. })
  143. info('%s: database restore is ok' % name)
  144. # 8. Remove unused bakup file
  145. seed_removed = remove_database_seed()
  146. if not seed_removed:
  147. r.issue = '%s: seed cannot be removed' % name
  148. r.status = 5
  149. r.save()
  150. error('%s: seed cannot be removed' % name)
  151. return self.create_response(request, {
  152. 'error_message': '%s: seed cannot be removed' % name
  153. })
  154. info('%s: database seed remove is ok' % name)
  155. # 9. Odoo create
  156. odoo_created = create_odoo_container(name, [port])
  157. if not odoo_created:
  158. r.issue = '%s: odoo container cannot be created' % name
  159. r.status = 5
  160. r.save()
  161. error('%s: odoo container cannot be created' % name)
  162. return self.create_response(request, {
  163. 'error_message': '%s: odoo container cannot be created' % name
  164. })
  165. info('%s: container creation is ok' % name)
  166. # 10. Apply permissions
  167. permissions_applied = apply_permissions(name)
  168. if not permissions_applied:
  169. r.issue = '%s: odoo container cannot be started' % name
  170. r.status = 5
  171. r.save()
  172. error('%s: odoo container cannot be started' % name)
  173. return self.create_response(request, {
  174. 'error_message': '%s: odoo container cannot be started' % name
  175. })
  176. info('%s: container started is ok' % name)
  177. r.issue = '%s: odoo container created successfully' % name
  178. r.status = 4
  179. r.save()
  180. # 11. Get internal IP
  181. internal_ip = get_odoo_internal_ip(name)
  182. # 12. Send email
  183. email_sended = send_email(
  184. '''
  185. El usuario %s ha creado exitosamente un nuevo sistema Odoo\n\n
  186. ------------------- Datos -------------------\n
  187. -\tNombre del Sistema:\t%s\n
  188. -\tIP Externo:\t%s\n
  189. -\tPuerto Externo:\t%s\n
  190. -\tIP Interno:\t%s\n
  191. ---------------------------------------------\n\n
  192. Obs.: Estos datos pueden ser usados para generar el subdominio del sistema
  193. ''' % (user.username, name, settings.EXTERNAL_IP, port, internal_ip),
  194. user.username,
  195. to_admins=True
  196. )
  197. if not email_sended:
  198. warning('%s email not sended' % user.username)
  199. else:
  200. info('%s email sended' % user.username)
  201. # 13. Send response
  202. info('%s: odoo creation is ok' % name)
  203. return self.create_response(request, {
  204. 'action': {
  205. 'type': 'redirect',
  206. 'ip': settings.EXTERNAL_IP,
  207. 'port': port
  208. }
  209. })
  210. '''
  211. '''
  212. def install_odoo_module(self, request, **kwargs):
  213. info('odoo module installation is requested')
  214. self.method_check(request, allowed='post')
  215. self.is_authenticated(request)
  216. authorization_header = request.META.get(settings.JWT_ACCEPT_HEADER)
  217. prefix_length = len(settings.JWT_PREFIX_HEADER)
  218. user = get_user(authorization_header[prefix_length + 1:])
  219. info('%s is authenticated' % user.username)
  220. err = {'error_message': None}
  221. data = None
  222. try:
  223. data = json.loads(request.body)
  224. except JSONDecodeError:
  225. error('json decode error')
  226. if not data:
  227. err['error_message'] = 'cannot parse request body'
  228. if data and (not 'system' in data or not 'modules' in data):
  229. err['error_message'] = 'module names and system name is required'
  230. system = data.get('system', '')
  231. modules = data.get('modules', [])
  232. result = install_modules(system, modules)
  233. if 'error' in result:
  234. err['error_message'] = result['error']
  235. if len(err) != 0:
  236. return self.create_response(request, err)
  237. module_names = ''
  238. for module_name in data.get('modules', []):
  239. module_names = '-\t' + module_name + '\n'
  240. send_email('El usuario %s ha instalado los siguientes módulos en el sistema %d:\n%s', (user.username, system, module_names), user.username, only_admins=True)
  241. return self.create_response(request, {
  242. 'success_message': '%s successfully installed' % data.get('module')
  243. })