Browse Source

[ADD] initial commit

robert 6 years ago
commit
4eb2531b49

+ 2 - 0
__init__.py

@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+import models

BIN
__init__.pyc


+ 8 - 0
__openerp__.py

@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+{
+    'name': "Odoo Management",
+    'author': "Robert Gauto",
+    'category': 'Tools',
+    'version': '0.1',
+    'depends': ['base']
+}

+ 3 - 0
models/__init__.py

@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+import payment_plan
+import odoo_container

BIN
models/__init__.pyc


+ 159 - 0
models/odoo_container.py

@@ -0,0 +1,159 @@
+# -*- coding: utf-8 -*-
+from openerp import models, fields, api
+from openerp.tools import config
+from openerp.exceptions import Warning
+from random import randint
+from jinja2 import Environment, PackageLoader
+from subprocess import check_output
+from ..utils import docker_api
+import os
+import unicodedata
+import stringcase
+import time
+
+
+class OdooContainer(models.Model):
+    _name = 'odoo.management.odoo.container'
+
+    CONTAINER_STATUS = [
+        ('to_activate', 'Por activar'),
+        ('activated', 'Activado'),
+        ('disapproved', 'No aprobado'),
+        ('suspended', 'Suspendido'),
+        ('destroyed', 'Eliminado')
+    ]
+
+    normalized_name = fields.Char(string='Normalized Name', compute='_normalize_name', size=50)
+    logo = fields.Binary(string='Logo')
+    internal_ip = fields.Char(string='Internal IP', size=15)
+    internal_port = fields.Integer(string='Internal Port')
+    external_ip = fields.Char(string='External IP', size=15)
+    external_port = fields.Integer(string='External Port')
+    expose_service = fields.Boolean(string='Expose Service', default=True)
+    status = fields.Selection(string='Estado', selection=CONTAINER_STATUS, default='draft')
+    demo = fields.Boolean(string='Is Demo?', default=False)
+    active = fields.Boolean(string='Is Active', default=False)
+    payment_plan_id = fields.Many2one(string='Payment Plan', comodel_name='odoo.management.payment.plan', required=True)
+
+    @api.one
+    # @api.depends('name')
+    def _normalize_name(self):
+        try:
+            name = unicodedata.normalize('NFKD', self.name)
+            name = name.encode('ASCII', 'ignore')
+        except TypeError:
+            pass
+
+        name = stringcase.trimcase(name)
+        name = stringcase.lowercase(name)
+        self.normalized_name = stringcase.snakecase(name)
+
+    def check_existence(self):
+        root_path = config['odoo_root_path'] or None
+
+        if not root_path:
+            raise Warning('No se puede encontrar la configuración')
+
+        system_path = os.path.join(root_path, self.normalized_name)
+
+        if system_path:
+            raise Warning('Ya existe un sistema con este nombre')
+
+        return True
+
+    def check_docker_port(self, port):
+        if port == 0:
+            return False
+
+        if port in docker_api.get_all_external_ports():
+            return False
+
+        return True
+
+    def take_randomized_port(self):
+        port_range = config['odoo_ports_range']
+        port_range = map(lambda x: int(x.strip()), port_range.split(','))
+
+        port = 0
+
+        while not self.check_docker_port(port):
+            port = randint(port_range[0], port_range[1])
+            time.sleep(0.3)
+
+        self.external_port = port
+
+    def create_odoo_folders(self):
+        root_path = config('odoo_root_path')
+        defaults_path = config('odoo_defaults_path')
+
+        for p in defaults_path:
+            full_path = os.path.join(root_path, self.normalized_name, p.strip())
+            os.makedirs(full_path)
+
+            time.sleep(0.3)
+
+        return True
+
+    def create_odoo_config(self):
+        config_path = os.path.join(config('odoo_root_path'), self.normalized_name, 'config')
+
+        if not os.path.exists(config_path):
+            return False
+
+        env = Environment(loader=PackageLoader('resources'))
+
+        template = env.get_template('openerp-server.j2')
+        rendered = template.stream({
+            'admin_password': config('odoo_default_password'),
+            'db_host': config('odoo_db_host'),
+            'db_name': self.normalized_name,
+            'db_user': config('db_user'),
+            'db_password': config('db_password')
+        })
+
+        rendered.dump(os.path.join(config_path, 'openerp-server.conf'))
+
+        return True
+
+    def create_odoo_db(self):
+        cmd = 'createdb -U %s %s' % (config('db_user'), self.normalized_name)
+        result = docker_api.run_command(config('odoo_db_container'), cmd)
+
+        return result
+
+    def copy_odoo_db_seed(self):
+        backup_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'resources', 'odoo.tar')
+        return docker_api.copy_in(config('odoo_db_container'), '/tmp', backup_path)
+
+    def restore_odoo_db(self):
+        cmd = 'psql -U %s -d %s -f %s' % (config('db_user'), self.normalized_name, '/tmp/odoo.sql')
+        return docker_api.run_command(config('odoo_db_container'), cmd)
+
+    def remove_odoo_db_seed(self):
+        cmd = 'rm -f %s' % '/tmp/odoo.sql'
+        return docker_api.run_command(config('odoo_db_container'), cmd)
+
+    def create_odoo_container(self):
+        result = docker_api.run_container(
+            image=config('odoo_image'),
+            name=self.normalized_name,
+            ports={'8069/tcp': self.external_port},
+            volumes=None,
+            network=config('odoo_network'),
+            memory_limit='150M',
+            memory_swap_limit='150M'
+        )
+
+        if not result:
+            raise Warning('No se pudo crear el contenedor')
+
+        return True
+
+    def apply_odoo_folders_permission(self):
+        full_path = os.path.join(config('odoo_root_path'), self.normalized_name)
+        check_output(['chmod', '-Rf', '777'], full_path)
+
+        return True
+
+    def take_internal_ip(self):
+        self.internal_ip = docker_api.get_internal_ip(self.normalized_name)

BIN
models/odoo_container.pyc


+ 9 - 0
models/payment_plan.py

@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+from openerp import models, fields
+
+
+class PaymentPlan(models.Model):
+    _name = 'odoo.management.payment.plan'
+
+    amount = fields.Float(string='Amount')
+    limit_storage = fields.Float(string='Limit Storage')

BIN
models/payment_plan.pyc


+ 5 - 0
templates.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+    <data>
+    </data>
+</openerp>

+ 2 - 0
utils/__init__.py

@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+import docker_api

+ 205 - 0
utils/docker_api.py

@@ -0,0 +1,205 @@
+# -*- coding: utf-8 -*-
+from openerp.tools import config
+from openerp.exceptions import Warning
+from docker import DockerClient
+from docker.errors import DockerException, NotFound, APIError, ContainerError, ImageNotFound
+import time
+
+try:
+    client = DockerClient(base_url='unix:/%s' % config['docker_sock'])
+except DockerException:
+    raise Warning('Socket not found')
+
+
+def get_all_images():
+    images = []
+
+    for image in client.images.list():
+        images.append({
+            'id': image.id,
+            'short_id': image.short_id,
+            'tags': image.tags
+        })
+
+    return images
+
+
+def get_all_containers():
+    exclusion_list = map(lambda x: x.strip(), config['docker_exclusion'] or [])
+    containers = []
+
+    for container in client.containers.list(all=True):
+        if container.name in exclusion_list:
+            continue
+
+        containers.append({
+            'id': container.id,
+            'short_id': container.short_id,
+            'name': container.name,
+            'image': container.image,
+            'labels': container.labels,
+            'status': container.status,
+            'attrs': container.attrs
+        })
+
+    return containers
+
+
+def get_all_external_ports():
+    port_dict = map(lambda x: x.get('attrs').get('NetworkSettings').get('Ports'), get_all_containers())
+    ports = []
+
+    for m in port_dict:
+        if not m:
+            continue
+
+        for _, v in m.iteritems():
+            if not v:
+                continue
+
+            ports.extend(map(lambda x: x['HostPort'], v))
+
+    return ports
+
+
+def get_network(network_name_or_id):
+    try:
+        network = client.networks.get(network_name_or_id)
+
+        return {
+            'id': network.id,
+            'short_id': network.short_id,
+            'name': network.name,
+            'attrs': network.attrs
+        }
+    except (NotFound, APIError):
+        return None
+
+
+def get_internal_ip(container_name_or_id):
+    network = get_network(config['docker_network'] or 'bridge')
+
+    if not network:
+        return None
+
+    try:
+        container = client.containers.get(container_name_or_id)
+        internal_ip = container.attrs.get('NetworkSettings').get('Networks').get(network.get('name')).get('IPAddress')
+
+        return str(internal_ip)
+    except (NotFound, APIError):
+        return None
+
+
+def run_container(image, name, ports=[], volumes=None, network=None, memory_limit=None, memory_swap_limit=None):
+    try:
+        client.containers.run(
+            image,
+            None,
+            name=name,
+            detach=True,
+            mem_limit=memory_limit,
+            memswap_limit=memory_swap_limit,
+            network=network,
+            ports=ports,
+            volumes=volumes
+        )
+
+        return True
+    except (ContainerError, ImageNotFound, APIError):
+        return False
+
+
+def start_container(container_name_or_id):
+    try:
+        container = client.containers.get(container_name_or_id)
+        container.start()
+
+        time.sleep(0.3)
+
+        container.reload()
+
+        return {
+            'id': container.id,
+            'short_id': container.short_id,
+            'name': container.name,
+            'image': container.image,
+            'labels': container.labels,
+            'status': container.status
+        }
+    except (NotFound, APIError):
+        return False
+
+
+def restart_container(container_name_or_id):
+    try:
+        container = client.containers.get(container_name_or_id)
+        container.restart()
+
+        time.sleep(0.3)
+
+        container.reload()
+
+        return {
+            'id': container.id,
+            'short_id': container.short_id,
+            'name': container.name,
+            'image': container.image,
+            'labels': container.labels,
+            'status': container.status
+        }
+    except (NotFound, APIError):
+        return False
+
+
+def stop_container(container_name_or_id):
+    try:
+        container = client.containers.get(container_name_or_id)
+        container.stop()
+
+        time.sleep(0.3)
+
+        container.reload()
+
+        return {
+            'id': container.id,
+            'short_id': container.short_id,
+            'name': container.name,
+            'image': container.image,
+            'labels': container.labels,
+            'status': container.status
+        }
+    except (NotFound, APIError):
+        return False
+
+
+def run_command(container_name_or_id, command):
+    try:
+        container = client.containers.get(container_name_or_id)
+        (exit_code, _) = container.exec_run(command)
+
+        return  (False, True)[exit_code == 0]
+    except (NotFound, APIError):
+        return False
+
+
+def copy_in(container_name_or_id, path, tarfile):
+    try:
+        filestream = open(tarfile, 'r')
+
+        container = client.containers.get(container_name_or_id)
+        result = container.put_archive(path, filestream)
+
+        filestream.close()
+
+        return result
+    except (NotFound, APIError, IOError):
+        return False
+
+
+def get_status(container_name_or_id):
+    try:
+        container = client.containers.get(container_name_or_id)
+        return (False, True)[container.status == 'running']
+    except (NotFound, APIError):
+        return False

+ 1 - 0
utils/odoo_api.py

@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-

+ 41 - 0
views/odoo_container.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+    <data>
+        <!--Tree-->
+        <record id="odoo_management.odoo_container_tree" model="ir.ui.view">
+            <field name="name">odoo.management.odoo.container.tree</field>
+            <field name="model">odoo.container</field>
+            <field name="arch" type="xml">
+                <tree>
+                    <field name="name" />
+                    <field name="normalized_name" />
+                    <field name="external_port" />
+                    <field name="status" />
+                </tree>
+            </field>
+        </record>
+
+        <!--Form-->
+        <record id="odoo_management.odoo_container_form" model="ir.ui.view">
+            <field name="name">odoo.management.odoo.container.form</field>
+            <field name="model">odoo.container</field>
+            <field name="arch" type="xml">
+                <form string="Odoo Container">
+                    <sheet>
+                        <div class="oe_title oe_left">
+                            <h1>
+                                <field name="name" class="oe_inline"></field>
+                            </h1>
+                        </div>
+                        <group>
+                            <group>
+                                <field name="normalized_name" />
+                                <field name="internal_ip" />
+                            </group>
+                        </group>
+                    </sheet>
+                </form>
+            </field>
+        </record>
+    </data>
+</openerp>

+ 5 - 0
views/payment_plan.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+    <data>
+    </data>
+</openerp>