|
@@ -1,7 +1,14 @@
|
|
|
# -*- coding: utf-8 -*-
|
|
|
from openerp import models, fields, api
|
|
|
-from openerp.exceptions import Warning
|
|
|
-from ..utils import odoo_api
|
|
|
+from openerp.exceptions import Warning, ValidationError
|
|
|
+from jinja2 import Environment as JinjaEnv, PackageLoader as JinjaLoader
|
|
|
+from ..utils.docker_api import get_all_external_ports
|
|
|
+from ..utils.command import execute
|
|
|
+from random import randint
|
|
|
+import unicodedata
|
|
|
+import stringcase
|
|
|
+import time
|
|
|
+import os
|
|
|
|
|
|
|
|
|
class OdooInstance(models.Model):
|
|
@@ -15,6 +22,94 @@ class OdooInstance(models.Model):
|
|
|
('destroyed', 'Eliminado')
|
|
|
]
|
|
|
|
|
|
+ DEFAULT_DIRS = [
|
|
|
+ 'config',
|
|
|
+ 'custom-addons',
|
|
|
+ 'files'
|
|
|
+ ]
|
|
|
+
|
|
|
+ # 'config: /etc/odoo, custom-addons: /mnt/extra-addons, files: /var/lib/odoo'
|
|
|
+
|
|
|
+ def _snakeike_name(self, name):
|
|
|
+ try:
|
|
|
+ name = unicodedata.normalize('NFKD', name)
|
|
|
+ name = name.encode('ASCII', 'ignore')
|
|
|
+ except TypeError:
|
|
|
+ pass
|
|
|
+
|
|
|
+ name = stringcase.trimcase(name)
|
|
|
+ name = stringcase.lowercase(name)
|
|
|
+ name = stringcase.snakecase(name)
|
|
|
+
|
|
|
+ return name
|
|
|
+
|
|
|
+ def _check_port_availability(self, port):
|
|
|
+ return port not in get_all_external_ports()
|
|
|
+
|
|
|
+ def _check_name_availability(self, name):
|
|
|
+ if len(name) == 0:
|
|
|
+ return False
|
|
|
+
|
|
|
+ root_path = self.env['ir.values'].get_default(self._name, 'odoo_root_path')
|
|
|
+
|
|
|
+ if len(root_path) == 0:
|
|
|
+ raise Warning('La ruta por defecto para los sistemas no está definido')
|
|
|
+
|
|
|
+ full_path = os.path.join(root_path, name)
|
|
|
+
|
|
|
+ return os.path.exists(full_path)
|
|
|
+
|
|
|
+ def _randomize_port(self):
|
|
|
+ ports = self.env['ir.values'].get_default(self._name, 'odoo_ports_range')
|
|
|
+ ports = filter(lambda x: x != '', ports.split(','))
|
|
|
+
|
|
|
+ if len(ports) == 0:
|
|
|
+ raise Warning('El rango de puertos para los sistemas no está definido')
|
|
|
+
|
|
|
+ port = 0
|
|
|
+
|
|
|
+ while not self._check_port_availability(port):
|
|
|
+ port = randint(ports[0], ports[1])
|
|
|
+ time.sleep(1)
|
|
|
+
|
|
|
+ return port
|
|
|
+
|
|
|
+ def _make_default_dirs(self, name):
|
|
|
+ root_path = self.env['ir.values'].get_default(self._name, 'odoo_root_path')
|
|
|
+
|
|
|
+ for d in self.DEFAULT_DIRS:
|
|
|
+ full_path = os.path.join(root_path, name, d.strip())
|
|
|
+ os.makedirs(full_path)
|
|
|
+ time.sleep(1)
|
|
|
+
|
|
|
+ def _make_config_file(self, name):
|
|
|
+ root_path = self.env['ir.values'].get_default(self._name, 'odoo_root_path')
|
|
|
+ config_path = os.path.join(root_path, name, 'config')
|
|
|
+
|
|
|
+ if not os.path.exists(config_path):
|
|
|
+ raise Warning('No se creó el directorio para el archivo de configuración')
|
|
|
+
|
|
|
+ env = JinjaEnv(loader=JinjaLoader('assets', 'templates'))
|
|
|
+ tmpl = env.get_template('openerp-server.j2')
|
|
|
+
|
|
|
+ tmpl_rendered = tmpl.stream({
|
|
|
+ 'admin_password': 'admin',
|
|
|
+ 'db_host': '',
|
|
|
+ 'db_port': '',
|
|
|
+ 'db_name': '',
|
|
|
+ 'db_user': '',
|
|
|
+ 'db_password': ''
|
|
|
+ })
|
|
|
+
|
|
|
+ tmpl_rendered.dump(os.path.join(config_path, 'openerp-config.conf'))
|
|
|
+
|
|
|
+ def _create_database(self, name):
|
|
|
+ odoo_db = self.env['ir.values'].get_default(self._name, 'odoo_db_link')
|
|
|
+ cmd = 'createdb -U %s %s' % ('odoo', name)
|
|
|
+
|
|
|
+ return execute(cmd)
|
|
|
+
|
|
|
+
|
|
|
name = fields.Char(string='Nombre', size=50)
|
|
|
normalized_name = fields.Char(string='Nombre normalizado', compute='_normalize_name', size=50)
|
|
|
logo = fields.Binary(string='Logo')
|
|
@@ -29,6 +124,16 @@ class OdooInstance(models.Model):
|
|
|
running = fields.Boolean(string='Está online?', default=False)
|
|
|
payment_plan_id = fields.Many2one(string='Plan de pago', comodel_name='payment.plan', required=True)
|
|
|
|
|
|
+ @api.model
|
|
|
+ def create(self, values):
|
|
|
+ snaked_name = self._snakeike_name(values.get('name'))
|
|
|
+ name_is_available = self._check_name_availability(snaked_name)
|
|
|
+
|
|
|
+ if not name_is_available:
|
|
|
+ raise ValidationError('El nombre ya está siendo usado por otro sistema')
|
|
|
+
|
|
|
+ return super(self, OdooInstance).create(values)
|
|
|
+
|
|
|
@api.one
|
|
|
@api.onchange('name')
|
|
|
def _onchange_name(self):
|
|
@@ -38,79 +143,81 @@ class OdooInstance(models.Model):
|
|
|
@api.one
|
|
|
@api.depends('name')
|
|
|
def _normalize_name(self):
|
|
|
- self.normalized_name = odoo_api.snakeize_name(self.name)
|
|
|
+ self.normalized_name = self._snakeike_name(self.name)
|
|
|
|
|
|
@api.one
|
|
|
def action_activate(self):
|
|
|
if self.state not in ('draft', 'suspended'):
|
|
|
raise Warning('No se puede activar un sistema ya activo')
|
|
|
|
|
|
- # 1. Check name
|
|
|
- name_is_available = odoo_api.check_name_availability(self.normalized_name)
|
|
|
-
|
|
|
- if not name_is_available:
|
|
|
- raise Warning('El nombre ya está siendo usado por otro sistema')
|
|
|
-
|
|
|
- # 2. Get a port
|
|
|
- port_to_use = odoo_api.randomize_port()
|
|
|
-
|
|
|
- # 3. Create dirs
|
|
|
- make_ok = odoo_api.make_default_dirs(self.normalized_name)
|
|
|
-
|
|
|
- if not make_ok:
|
|
|
- raise Warning('No se pudo crear la estructura de directorios')
|
|
|
-
|
|
|
- # 4. Create configuration file
|
|
|
- config_ok = odoo_api.make_config_file(self.normalized_name)
|
|
|
-
|
|
|
- if not config_ok:
|
|
|
- raise Warning('No se pudo crear el archivo de configuración')
|
|
|
-
|
|
|
- # 5. Create database
|
|
|
- db_ok = odoo_api.create_database(self.normalized_name)
|
|
|
-
|
|
|
- if not db_ok:
|
|
|
- raise Warning('No se pudo crear la base de datos')
|
|
|
-
|
|
|
- # 6. Copy database seed
|
|
|
- seed_copied = odoo_api.copy_database_seed()
|
|
|
-
|
|
|
- if not seed_copied:
|
|
|
- raise Warning('No se pudo copiar la estructura inicial de la base de datos')
|
|
|
-
|
|
|
- # 7. Restore database schema
|
|
|
- restored = odoo_api.restore_database(self.normalized_name)
|
|
|
-
|
|
|
- if not restored:
|
|
|
- raise Warning('No se pudo reestablecer la copia de base de datos')
|
|
|
-
|
|
|
- # 8. Remove database seed
|
|
|
- seed_removed = odoo_api.remove_database_seed()
|
|
|
-
|
|
|
- if not seed_removed:
|
|
|
- raise Warning('No se pudo remover la copia de base de datos')
|
|
|
-
|
|
|
- # 9. Create odoo container
|
|
|
- odoo_created = odoo_api.create_container(self.normalized_name, [port_to_use])
|
|
|
-
|
|
|
- if not odoo_created:
|
|
|
- raise Warning('No se pudo crear el contenedor')
|
|
|
-
|
|
|
- # 10. Apply permissions
|
|
|
- permissions_applied = odoo_api.apply_permissions(self.normalized_name)
|
|
|
-
|
|
|
- if not permissions_applied:
|
|
|
- raise Warning('No se pudo aplicar los permisos correspondientes')
|
|
|
-
|
|
|
- # 11. Get internal ip
|
|
|
- internal_ip = odoo_api.get_internal_ip(self.normalized_name)
|
|
|
-
|
|
|
- # 12. Send email
|
|
|
- # TODO
|
|
|
-
|
|
|
- print(internal_ip)
|
|
|
-
|
|
|
- self.state = 'activated'
|
|
|
+ self._check_name_availability(self.normalized_name)
|
|
|
+
|
|
|
+ # # 1. Check name
|
|
|
+ # name_is_available = odoo_api.check_name_availability(self.normalized_name)
|
|
|
+ #
|
|
|
+ # if not name_is_available:
|
|
|
+ # raise Warning('El nombre ya está siendo usado por otro sistema')
|
|
|
+ #
|
|
|
+ # # 2. Get a port
|
|
|
+ # port_to_use = odoo_api.randomize_port()
|
|
|
+ #
|
|
|
+ # # 3. Create dirs
|
|
|
+ # make_ok = odoo_api.make_default_dirs(self.normalized_name)
|
|
|
+ #
|
|
|
+ # if not make_ok:
|
|
|
+ # raise Warning('No se pudo crear la estructura de directorios')
|
|
|
+ #
|
|
|
+ # # 4. Create configuration file
|
|
|
+ # config_ok = odoo_api.make_config_file(self.normalized_name)
|
|
|
+ #
|
|
|
+ # if not config_ok:
|
|
|
+ # raise Warning('No se pudo crear el archivo de configuración')
|
|
|
+ #
|
|
|
+ # # 5. Create database
|
|
|
+ # db_ok = odoo_api.create_database(self.normalized_name)
|
|
|
+ #
|
|
|
+ # if not db_ok:
|
|
|
+ # raise Warning('No se pudo crear la base de datos')
|
|
|
+ #
|
|
|
+ # # 6. Copy database seed
|
|
|
+ # seed_copied = odoo_api.copy_database_seed()
|
|
|
+ #
|
|
|
+ # if not seed_copied:
|
|
|
+ # raise Warning('No se pudo copiar la estructura inicial de la base de datos')
|
|
|
+ #
|
|
|
+ # # 7. Restore database schema
|
|
|
+ # restored = odoo_api.restore_database(self.normalized_name)
|
|
|
+ #
|
|
|
+ # if not restored:
|
|
|
+ # raise Warning('No se pudo reestablecer la copia de base de datos')
|
|
|
+ #
|
|
|
+ # # 8. Remove database seed
|
|
|
+ # seed_removed = odoo_api.remove_database_seed()
|
|
|
+ #
|
|
|
+ # if not seed_removed:
|
|
|
+ # raise Warning('No se pudo remover la copia de base de datos')
|
|
|
+ #
|
|
|
+ # # 9. Create odoo container
|
|
|
+ # odoo_created = odoo_api.create_container(self.normalized_name, [port_to_use])
|
|
|
+ #
|
|
|
+ # if not odoo_created:
|
|
|
+ # raise Warning('No se pudo crear el contenedor')
|
|
|
+ #
|
|
|
+ # # 10. Apply permissions
|
|
|
+ # permissions_applied = odoo_api.apply_permissions(self.normalized_name)
|
|
|
+ #
|
|
|
+ # if not permissions_applied:
|
|
|
+ # raise Warning('No se pudo aplicar los permisos correspondientes')
|
|
|
+ #
|
|
|
+ # # 11. Get internal ip
|
|
|
+ # internal_ip = odoo_api.get_internal_ip(self.normalized_name)
|
|
|
+ #
|
|
|
+ # # 12. Send email
|
|
|
+ # # TODO
|
|
|
+ #
|
|
|
+ # print(internal_ip)
|
|
|
+ #
|
|
|
+ # self.state = 'activated'
|
|
|
|
|
|
@api.one
|
|
|
def action_disapprove(self):
|