odoo_resource.py 10 KB

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