# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.conf.urls import url from django.conf import settings from tastypie.resources import Resource from tastypie.utils import trailing_slash from core.models.request import Request from api.utils.odoo_api import ( normalize_name, check_name, randomize_port, create_folders, create_configuration, create_database, copy_database_seed, restore_database, remove_database_seed, create_odoo_container, apply_permissions, get_odoo_internal_ip, install_modules ) from api.utils.git_api import get_odoo_modules_repos_names from api.utils.docker_api import get_all_containers from api.utils.jwt_token import get_user from api.utils.jwt_authentication import JWTAuthentication from api.utils.logger import ( info, error, warning ) from api.utils.email import send_email from simplejson import JSONDecodeError import simplejson as json class OdooResource(Resource): class Meta: authentication = JWTAuthentication() ''' ''' def prepend_urls(self): return [ url(r'^(?P%s)/create%s$' % (self._meta.resource_name, trailing_slash), self.wrap_view('odoo_create'), name='api_odoo_create'), url(r'^(?P%s)/install_modules%s$' % (self._meta.resource_name, trailing_slash), self.wrap_view('install_odoo_modules'), name='api_install_odoo_modules'), ] ''' ''' def odoo_create(self, request, **kwargs): info('odoo creation is requested') self.method_check(request, allowed='post') self.is_authenticated(request) authorization_header = request.META.get(settings.JWT_ACCEPT_HEADER) prefix_length = len(settings.JWT_PREFIX_HEADER) user = get_user(authorization_header[prefix_length + 1:]) info('%s is authenticated' % user.username) name = None try: data = json.loads(request.body) name = data['name'] except JSONDecodeError: name = None error('json decode error') except KeyError: name = None error('key error') r = Request.objects.create(name='Crear contenedor Odoo') r.user = user if not name: r.issue = 'name is required' r.status = 5 r.save() error('name is required') return self.create_response(request, { 'error_message': 'name is required' }) info('%s: request is ok' % name) # 1. Check and get name name = normalize_name(name) name_exists = check_name(name) if name_exists: r.issue = '%s: name is already exists' % name r.status = 5 r.save() error('%s: name is already exists' % name) return self.create_response(request, { 'error_message': '%s: name is already exists' % name }) info('%s: name is ok' % name) # 2. Get port port = randomize_port() info('%s: port is ok' % port) # 3. Folder structure create folders_created = create_folders(name) if not folders_created: r.issue = '%s: folders structure cannot be created' % name r.status = 5 r.save() error('%s: folders structure cannot be created' % name) return self.create_response(request, { 'error_message': '%s: folders structure cannot be created' % name }) info('%s: folders is ok' % name) # 4. Configuration create conf_created = create_configuration(name) if not conf_created: r.issue = '%s: configuration cannot be created' % name r.status = 5 r.save() error('%s: configuration cannot be created' % name) return self.create_response(request, { 'error_message': '%s: configuration cannot be created' % name }) info('%s: configuration is ok' % name) # 5. Database create db_created = create_database(name) if not db_created: r.issue = '%s: database cannot be created' % name r.status = 5 r.save() error('%s: database cannot be created' % name) return self.create_response(request, { 'error_message': '%s: database cannot be created' % name }) info('%s: database is ok' % name) # 6. Copy a database backup seed_copied = copy_database_seed() if not seed_copied: r.issue = '%s: database seed cannot be copied' % name r.status = 5 r.save() error('%s: database seed cannot be copied' % name) return self.create_response(request, { 'error_message': '%s: database seed cannot be copied' % name }) info('%s: database seed is ok' % name) # 7. Restore database schema db_restored = restore_database(name) if not db_restored: r.issue = '%s: database cannot be restored' % name r.status = 5 r.save() error('%s: database cannot be restored' % name) return self.create_response(request, { 'error_message': '%s: database cannot be restored' % name }) info('%s: database restore is ok' % name) # 8. Remove unused bakup file seed_removed = remove_database_seed() if not seed_removed: r.issue = '%s: seed cannot be removed' % name r.status = 5 r.save() error('%s: seed cannot be removed' % name) return self.create_response(request, { 'error_message': '%s: seed cannot be removed' % name }) info('%s: database seed remove is ok' % name) # 9. Odoo create odoo_created = create_odoo_container(name, [port]) if not odoo_created: r.issue = '%s: odoo container cannot be created' % name r.status = 5 r.save() error('%s: odoo container cannot be created' % name) return self.create_response(request, { 'error_message': '%s: odoo container cannot be created' % name }) info('%s: container creation is ok' % name) # 10. Apply permissions permissions_applied = apply_permissions(name) if not permissions_applied: r.issue = '%s: odoo container cannot be started' % name r.status = 5 r.save() error('%s: odoo container cannot be started' % name) return self.create_response(request, { 'error_message': '%s: odoo container cannot be started' % name }) info('%s: container started is ok' % name) r.issue = '%s: odoo container created successfully' % name r.status = 4 r.save() # 11. Get internal IP internal_ip = get_odoo_internal_ip(name) # 12. Send email email_sended = send_email( ''' El usuario %s ha creado exitosamente un nuevo sistema Odoo\n\n ------------------- Datos -------------------\n -\tNombre del Sistema:\t%s\n -\tIP Externo:\t%s\n -\tPuerto Externo:\t%s\n -\tIP Interno:\t%s\n ---------------------------------------------\n\n Obs.: Estos datos pueden ser usados para generar el subdominio del sistema ''' % (user.username, name, settings.EXTERNAL_IP, port, internal_ip), user.username, to_admins=True ) if not email_sended: warning('%s email not sended' % user.username) else: info('%s email sended' % user.username) # 13. Send response info('%s: odoo creation is ok' % name) return self.create_response(request, { 'action': { 'type': 'redirect', 'ip': settings.EXTERNAL_IP, 'port': port } }) ''' ''' def install_odoo_modules(self, request, **kwargs): info('odoo module installation is requested') self.method_check(request, allowed=['get', 'post']) self.is_authenticated(request) authorization_header = request.META.get(settings.JWT_ACCEPT_HEADER) prefix_length = len(settings.JWT_PREFIX_HEADER) user = get_user(authorization_header[prefix_length + 1:]) info('%s is authenticated' % user.username) if request.META.get('REQUEST_METHOD') == 'GET': return self.create_response(request, { 'containers': get_all_containers(), 'repositories': get_odoo_modules_repos_names() }) err = {'error_message': None} data = None try: data = json.loads(request.body) except JSONDecodeError: error('json decode error') r = Request.objects.create(name='Copiar/actualizar módulos de Odoo') r.user = user if not data: err['error_message'] = 'cannot parse request body' if data and (not 'system' in data or not 'modules' in data): err['error_message'] = 'module names and system name is required' system = data.get('system', '') modules = data.get('modules', []) result = install_modules(system, modules) if 'error' in result: err['error_message'] = result['error'] if err['error_message']: return self.create_response(request, err) module_names = '' for module_name in data.get('modules', []): module_names = '-\t' + module_name + '\n' r.issue = '%s: modules successfully installed' % system r.status = 4 r.save() 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) if not email_sended: warning('%s email not sended' % user.username) else: info('%s email sended' % user.username) return self.create_response(request, { 'success_message': 'modules successfully installed' })