Explorar o código

[IMP] settings manager

robert %!s(int64=6) %!d(string=hai) anos
pai
achega
c3e3f84aed

+ 1 - 0
__init__.py

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

BIN=BIN
__init__.pyc


+ 3 - 1
__openerp__.py

@@ -6,10 +6,12 @@
     'version': '0.1',
     'depends': [
         'base',
+        'bus',
         'web'
     ],
     'data': [
-        'templates.xml',
+        'odoo_management.xml',
+        'odoo_management_data.xml',
         'workflow.xml'
     ],
     'qweb': [

+ 2 - 0
controllers/__init__.py

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

+ 47 - 0
controllers/main.py

@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+from openerp import http
+from openerp.addons.bus import bus
+from openerp.http import request as r
+from ..utils import docker_api as docker
+
+
+class ConfigController(http.Controller):
+
+    @http.route('/odoo_management/get_config', auth='user', type='json')
+    def get_config(self, **kw):
+        settings = r.env['odoo.management.config'].get_default_settings([])
+
+        settings.update({
+            'images': docker.get_all_containers(),
+            'containers': docker.get_all_containers(),
+            'networks': docker.get_all_networks()
+        })
+
+        return settings
+
+    @http.route('/odoo_management/save_config', auth='user', type='json')
+    def save_config(self, **kw):
+        r.env['odoo.management.config'].set_default_settings(kw)
+
+    @http.route('/odoo_management/images', auth='user', methods=['GET'], type='json')
+    def get_images(self, **kw):
+        images = docker.get_all_images()
+
+        return images
+
+    @http.route('/odoo_management/containers', auth='user', methods=['GET'], type='json')
+    def get_containers(self, **kw):
+        containers = docker.get_all_containers()
+
+        return containers
+
+
+class InstancesController(bus.Controller):
+
+    def _poll(self, dbname, channels, last, options):
+        if r.session.uid:
+            registry, cr, uid, context = r.registry, r.cr, r.session.uid, r.context
+            new_channel = (r.db, 'odoo.instance', r.uid)
+            channels.append(new_channel)
+
+        return super(InstancesController, self)._poll(dbname, channels, last, options)

+ 1 - 1
models/__init__.py

@@ -1,4 +1,4 @@
 # -*- coding: utf-8 -*-
 import payment_plan
-import system_instance
+import odoo_instance
 import odoo_management_config

BIN=BIN
models/__init__.pyc


+ 108 - 0
models/odoo_instance.py

@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+from openerp import models, fields, api
+from openerp.exceptions import Warning
+import unicodedata
+import stringcase
+
+
+class OdooInstance(models.Model):
+    _name = 'odoo.instance'
+
+    CONTAINER_STATUS = [
+        ('draft', 'Por activar'),
+        ('activated', 'Activado'),
+        ('disapproved', 'No aprobado'),
+        ('suspended', 'Suspendido'),
+        ('destroyed', 'Eliminado')
+    ]
+
+    name = fields.Char(string='Nombre', size=50)
+    normalized_name = fields.Char(string='Nombre normalizado', compute='_normalize_name', size=50)
+    logo = fields.Binary(string='Logo')
+    internal_ip = fields.Char(string='IP interno', size=15)
+    internal_port = fields.Integer(string='Puerto interno')
+    external_ip = fields.Char(string='IP externo', size=15)
+    external_port = fields.Integer(string='Puerto externo')
+    expose_ip = fields.Boolean(string='Exponer IP', default=True)
+    state = fields.Selection(string='Estado', selection=CONTAINER_STATUS, default='draft')
+    demo = fields.Boolean(string='Es un demo?', default=False)
+    domain = fields.Char(string='Dominio', size=100)
+    running = fields.Boolean(string='Está online?', default=False)
+    payment_plan_id = fields.Many2one(string='Plan de pago', comodel_name='payment.plan', required=True)
+
+    @api.one
+    @api.onchange('name')
+    def _onchange_name(self):
+        if self.name:
+            self.name = self.name.title()
+
+    @api.one
+    @api.depends('name')
+    def _normalize_name(self):
+        name = None
+
+        try:
+            name = unicodedata.normalize('NFKD', self.name)
+            name = name.encode('ASCII', 'ignore')
+        except TypeError:
+            pass
+
+        if not name:
+            return
+
+        name = stringcase.trimcase(name)
+        name = stringcase.lowercase(name)
+
+        self.normalized_name = stringcase.snakecase(name)
+
+    @api.one
+    def action_activate(self):
+        if self.state not in ('draft', 'suspended'):
+            raise Warning('No se puede activar un sistema ya activo')
+
+        self.state = 'activated'
+
+    @api.one
+    def action_disapprove(self):
+        if self.state != 'draft':
+            raise Warning('No se puede desaprobar un sistema ya activo')
+
+        self.state = 'disapproved'
+
+    @api.one
+    def action_suspend(self):
+        if self.state != 'activated':
+            raise Warning('No se puede suspender un sistema no activo')
+
+        self.state = 'suspended'
+        self.running = False
+
+    @api.one
+    def copy(self):
+        raise Warning('Atención', 'No se puede duplicar una instancia. Por favor, cree uno nuevo')
+
+    @api.one
+    def action_destroy(self):
+        if self.state == 'destroyed':
+            raise Warning('No se puede eliminar un sistema ya eliminado')
+
+        self.state = 'destroyed'
+        self.running = False
+
+    @api.one
+    def action_start(self):
+        if self.running:
+            raise Warning('Atención', 'No se puede arrancar una instancia que ya está arrancada')
+
+        self.running = True
+
+    @api.one
+    def action_restart(self):
+        if not self.running:
+            raise Warning('Atención', 'No se puede parar y arrancar una instancia que ya está parada')
+
+        self.running = True
+
+    @api.model
+    def check_status(self):
+        print('croned')

+ 46 - 21
models/odoo_management_config.py

@@ -1,38 +1,63 @@
 # -*- coding: utf-8 -*-
 from openerp import api, models, fields
-from openerp.tools.safe_eval import safe_eval
 
 
 class OdooManagementConfig(models.TransientModel):
     _inherit = 'res.config.settings'
     _name = 'odoo.management.config'
 
-    docker_sock = fields.Char(string='Socket', size=100, default='/var/run/docker.sock')
-    docker_exclusion = fields.Char(string='Lista de exclusión', size=160)
-    odoo_image = fields.Char(string='Imagen docker', size=50)
+    field_types = (
+        ('docker_socket_path', 'char'),
+        ('docker_exclusion_list', 'list'),
+        ('odoo_docker_image', 'char'),
+        ('odoo_network', 'char'),
+        ('odoo_ports_range', 'list'),
+        ('odoo_root_path', 'char'),
+        ('odoo_db_link', 'char'),
+        ('modules_git_path', 'char'),
+    )
+
+    docker_socket_path = fields.Char(string='Socket', size=100, default='/var/run/docker.sock')
+    docker_exclusion_list = fields.Char(string='Lista de exclusión', size=160)
+    odoo_docker_image = fields.Char(string='Imagen docker', size=50)
     odoo_network = fields.Char(string='Red virtual', size=50, default='eiru')
     odoo_ports_range = fields.Char(string='Rango de puertos', size=50)
     odoo_root_path = fields.Char(string='Ruta raíz', size=50, default='/opt/odoo')
-    odoo_db = fields.Char(string='Base de datos', size=50, default='db')
-    git_path = fields.Char(string='Ruta del repositorio', size=100, default='/opt/gogs/git/gogs-repositories')
+    odoo_db_link = fields.Char(string='Base de datos', size=50, default='db')
+    modules_git_path = fields.Char(string='Ruta del repositorio', size=100, default='/opt/gogs/git/gogs-repositories')
 
     @api.multi
-    def set_default_settings(self):
-        pass
+    def set_default_settings(self, values):
+        ir_values_obj = self.env['ir.values']
+        types = dict(self.field_types)
+
+        for v in values:
+            value = None
+
+            if types[v] == 'char':
+                value = values[v]
+
+            if types[v] == 'list':
+                value = ','.join(map(lambda x: x.strip(), values[v]))
+
+            value = value or ''
+            ir_values_obj.set_default('odoo.instance', v, value)
 
     @api.model
     def get_default_settings(self, fields):
-        return {
-            'docker_sock': '/var/run/docker.sock',
-            'docker_exclusion': (('test_001', 'Test 001'), ('test_002', 'Test 002')),
-            'odoo_image': 'odoo:1.0',
-            'odoo_network': 'eiru',
-            'odoo_ports_range': safe_eval('[10000, 20000]'),
-            'odoo_root_path': '/opt/odoo',
-            'odoo_db': 'db',
-            'git_path': '/opt/gogs/git/gogs-repositories'
-        }
+        ir_values = self.env['ir.values'].get_defaults_dict('odoo.instance')
+        types = dict(self.field_types)
+        defaults = {}
 
-    @api.model
-    def on_change_docker_exclusion(self):
-        pass
+        for v in ir_values:
+            value = None
+
+            if types[v] == 'char':
+                value = ir_values[v]
+
+            if types[v] == 'list':
+                value = filter(lambda x: x != '', ir_values[v].split(','))
+
+            defaults[v] = value or ''
+
+        return defaults

+ 0 - 223
models/system_instance.py

@@ -1,223 +0,0 @@
-# -*- 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
-
-# print(config['docker_sock'])
-
-
-class SystemInstance(models.Model):
-    _name = 'system.instance'
-
-    CONTAINER_STATUS = [
-        ('draft', 'Por activar'),
-        ('activated', 'Activado'),
-        ('disapproved', 'No aprobado'),
-        ('suspended', 'Suspendido'),
-        ('destroyed', 'Eliminado')
-    ]
-
-    name = fields.Char(string='Nombre', size=50)
-    normalized_name = fields.Char(string='Nombre normalizado', compute='_normalize_name', size=50)
-    logo = fields.Binary(string='Logo')
-    internal_ip = fields.Char(string='IP interno', size=15)
-    internal_port = fields.Integer(string='Puerto interno')
-    external_ip = fields.Char(string='IP externo', size=15)
-    external_port = fields.Integer(string='Puerto externo')
-    expose_ip = fields.Boolean(string='Exponer IP', default=True)
-    state = fields.Selection(string='Estado', selection=CONTAINER_STATUS, default='draft')
-    demo = fields.Boolean(string='Es un demo?', default=False)
-    domain = fields.Char(string='Dominio', size=100)
-    running = fields.Boolean(string='Está online?', default=False)
-    payment_plan_id = fields.Many2one(string='Plan de pago', comodel_name='payment.plan', required=True)
-
-    @api.one
-    @api.onchange('name')
-    def _onchange_name(self):
-        if self.name:
-            self.name = self.name.title()
-
-    @api.one
-    @api.depends('name')
-    def _normalize_name(self):
-        name = None
-
-        try:
-            name = unicodedata.normalize('NFKD', self.name)
-            name = name.encode('ASCII', 'ignore')
-        except TypeError:
-            pass
-
-        if not name:
-            return
-
-        name = stringcase.trimcase(name)
-        name = stringcase.lowercase(name)
-
-        self.normalized_name = stringcase.snakecase(name)
-
-    @api.one
-    def action_activate(self):
-        if self.state not in ('draft', 'suspended'):
-            raise Warning('No se puede activar un sistema ya activo')
-
-        self.state = 'activated'
-
-    @api.one
-    def action_disapprove(self):
-        if self.state != 'draft':
-            raise Warning('No se puede desaprobar un sistema ya activo')
-
-        self.state = 'disapproved'
-
-    @api.one
-    def action_suspend(self):
-        if self.state != 'activated':
-            raise Warning('No se puede suspender un sistema no activo')
-
-        self.state = 'suspended'
-        self.running = False
-
-    @api.one
-    def copy(self):
-        raise Warning('Atención', 'No se puede duplicar una instancia. Por favor, cree uno nuevo')
-
-    @api.one
-    def action_destroy(self):
-        if self.state == 'destroyed':
-            raise Warning('No se puede eliminar un sistema ya eliminado')
-
-        self.state = 'destroyed'
-        self.running = False
-
-    @api.one
-    def action_start(self):
-        if self.running:
-            raise Warning('Atención', 'No se puede arrancar una instancia que ya está arrancada')
-
-        self.running = True
-
-    @api.one
-    def action_restart(self):
-        if not self.running:
-            raise Warning('Atención', 'No se puede parar y arrancar una instancia que ya está parada')
-
-        self.running = True
-
-    # 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)

+ 11 - 61
templates.xml → odoo_management.xml

@@ -9,10 +9,10 @@
             </xpath>
         </template>
 
-        <!-- system.instance tree view -->
-        <record id="system_instance_tree_view" model="ir.ui.view">
-            <field name="name">system.instance.tree</field>
-            <field name="model">system.instance</field>
+        <!-- odoo.instance tree view -->
+        <record id="odoo_instance_tree_view" model="ir.ui.view">
+            <field name="name">odoo.instance.tree</field>
+            <field name="model">odoo.instance</field>
             <field name="arch" type="xml">
                 <tree colors="green:running == True and state == 'activated';red:running == False and state == 'activated';blue:state == 'draft';yellow:state == 'disapproved';orange:state == 'suspended';gray:state == 'destroyed'" delete="false" copy="false">
                     <field name="name" />
@@ -36,10 +36,10 @@
             </field>
         </record>
 
-        <!-- system.instance form view -->
-        <record id="system_instance_form_view" model="ir.ui.view">
-            <field name="name">system.instance.form</field>
-            <field name="model">system.instance</field>
+        <!-- odoo.instance form view -->
+        <record id="odoo_instance_form_view" model="ir.ui.view">
+            <field name="name">odoo.instance.form</field>
+            <field name="model">odoo.instance</field>
             <field name="arch" type="xml">
                 <form string="Sistema Odoo" delete="false" duplicate="false" copy="false">
                     <header>
@@ -163,51 +163,11 @@
             </field>
         </record>
 
-        <!--  odoo.management.config form -->
-        <record id="odoo_management_config_form_view" model="ir.ui.view">
-            <field name="name">Preferencias</field>
-            <field name="model">odoo.management.config</field>
-            <field name="arch" type="xml">
-                <form string="Preferencias">
-                    <header>
-                        <button string="Guardar" type="object" name="execute" class="oe_highlight" />
-                        or
-                        <button string="Cancelar" type="object" name="cancel" class="oe_link" />
-                    </header>
-                    <div name="general">
-                        <group>
-                            <group string="Docker">
-                                <field name="docker_sock" />
-                                <field name="docker_exclusion" widget="many2many_tags" context="{'model': None}" />
-                            </group>
-                            <group />
-                        </group>
-                        <group>
-                            <group string="Odoo">
-                                <field name="odoo_image" />
-                                <field name="odoo_network" />
-                                <field name="odoo_ports_range" />
-                                <field name="odoo_root_path" />
-                                <field name="odoo_db" />
-                            </group>
-                            <group />
-                        </group>
-                        <group>
-                            <group string="Git">
-                                <field name="git_path" />
-                            </group>
-                            <group />
-                        </group>
-                    </div>
-                </form>
-            </field>
-        </record>
-
-        <!-- system.instance action -->
+        <!-- odoo.instance action -->
         <record id="odoo_container_action" model="ir.actions.act_window">
             <field name="name">Sistemas Odoo</field>
             <field name="type">ir.actions.act_window</field>
-            <field name="res_model">system.instance</field>
+            <field name="res_model">odoo.instance</field>
             <field name="view_mode">tree,form</field>
             <field name="view_type">form</field>
             <field name="help" type="html">
@@ -232,16 +192,7 @@
         </record>
 
         <!-- odoo.management.config action -->
-        <record id="odoo_management_config_action" model="ir.actions.act_window">
-            <field name="name">Configuración</field>
-            <field name="type">ir.actions.act_window</field>
-            <field name="res_model">odoo.management.config</field>
-            <field name="view_mode">form</field>
-            <field name="target">inline</field>
-        </record>
-
-        <!-- odoo.management.config action -->
-        <record id="odoo_management_config_action2" model="ir.actions.client">
+        <record id="odoo_management_config_action" model="ir.actions.client">
             <field name="name">Configuración</field>
             <field name="tag">odoo_management.configuration</field>
         </record>
@@ -257,6 +208,5 @@
         <menuitem id="configuration_menu_categ" name="Configuración" parent="sysadmin_menu_root" />
         <menuitem id="payment_plan_menu_act" name="Planes de pago" parent="configuration_menu_categ" action="payment_plan_action" />
         <menuitem id="configuration_menu_act" name="Configuración" parent="configuration_menu_categ" action="odoo_management_config_action" />
-        <menuitem id="configuration_menu_act2" name="Configuración 2" parent="configuration_menu_categ" action="odoo_management_config_action2" />
     </data>
 </openerp>

+ 80 - 0
odoo_management_data.xml

@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data noupdate="1">
+        <record id="docker_socket_path" model="ir.values">
+            <field name="name">docker_socket_path</field>
+            <field name="key">default</field>
+            <field name="key2"></field>
+            <field name="value_unpickle" eval="'/var/run/docker.sock'" />
+            <field name="model">odoo.instance</field>
+        </record>
+
+        <record id="docker_exclusion_list" model="ir.values">
+            <field name="name">docker_exclusion_list</field>
+            <field name="key">default</field>
+            <field name="key2"></field>
+            <field name="value_unpickle" eval="''" />
+            <field name="model">odoo.instance</field>
+        </record>
+
+        <record id="odoo_docker_image" model="ir.values">
+            <field name="name">odoo_docker_image</field>
+            <field name="key">default</field>
+            <field name="key2"></field>
+            <field name="value_unpickle" eval="''" />
+            <field name="model">odoo.instance</field>
+        </record>
+
+        <record id="odoo_db_link" model="ir.values">
+            <field name="name">odoo_db_link</field>
+            <field name="key">default</field>
+            <field name="key2"></field>
+            <field name="value_unpickle" eval="''" />
+            <field name="model">odoo.instance</field>
+        </record>
+
+        <record id="odoo_network" model="ir.values">
+            <field name="name">odoo_network</field>
+            <field name="key">default</field>
+            <field name="key2"></field>
+            <field name="value_unpickle" eval="''" />
+            <field name="model">odoo.instance</field>
+        </record>
+
+        <record id="odoo_ports_range" model="ir.values">
+            <field name="name">odoo_ports_range</field>
+            <field name="key">default</field>
+            <field name="key2"></field>
+            <field name="value_unpickle" eval="''" />
+            <field name="model">odoo.instance</field>
+        </record>
+
+        <record id="odoo_root_path" model="ir.values">
+            <field name="name">odoo_root_path</field>
+            <field name="key">default</field>
+            <field name="key2"></field>
+            <field name="value_unpickle" eval="'/opt/odoo'" />
+            <field name="model">odoo.instance</field>
+        </record>
+
+        <record id="modules_git_path" model="ir.values">
+            <field name="name">modules_git_path</field>
+            <field name="key">default</field>
+            <field name="key2"></field>
+            <field name="value_unpickle" eval="''" />
+            <field name="model">odoo.instance</field>
+        </record>
+
+        <record id="system_status_checker" model="ir.cron">
+            <field name="name">System Instance Checker</field>
+            <field name="active" eval="True" />
+            <field name="user_id" ref="base.user_root" />
+            <field name="interval_number">1</field>
+            <field name="interval_type">minutes</field>
+            <field name="numbercall">-1</field>
+            <field name="doall" eval="False" />
+            <field name="model" eval="'odoo.instance'" />
+            <field name="function" eval="'check_status'" />
+        </record>
+    </data>
+</openerp>

+ 110 - 12
static/src/js/main.js

@@ -2,22 +2,120 @@ openerp.odoo_management = function(instance, local) {
 
     local.ConfigPage = instance.Widget.extend({
         template: 'ConfigTemplate',
+        data: {
+            docker_socket_path: '',
+            docker_exclusion_list: [],
+            odoo_docker_image: '',
+            odoo_network: '',
+            odoo_ports_range: [],
+            odoo_root_path: '',
+            odoo_db_link: '',
+            modules_git_path: ''
+        },
+        events: {
+            'click .oe_button': 'send_config'
+        },
         start: function() {
-           this.initializeInputs(); 
-        },
-        initializeInputs: function() {
-            this.$('#exclusions-input').textext({
-                plugins : 'tags arrow autocomplete',
-                tagsItems : [ 'eiru', 'db'],
-                core: {
-                    onSetInputData: function(e, data) {
-                        if (data === '') {
-                            this._plugins.autocomplete._suggestions = null;
+            this.$exclusions = this.$('#exclusions-input');
+            this.$odooImage = this.$('#image-input');
+            this.$odooNetwork = this.$('#network-input');
+            this.$odooDb = this.$('#db-input');
+
+            this.prepare_inputs();
+            this.get_config();
+        },
+        configure_tags_input: function($input, plugins, tags, cb) {
+            $input.textext({
+                plugins: plugins,
+                tagsItems: tags,
+                ext: {
+                    autocomplete: {
+                        selectFromDropdown: function() {
+                            var suggestion = this.selectedSuggestionElement().data('text-suggestion');
+                            
+                            if (suggestion) {
+                                this.val(this.itemManager().itemToString(suggestion));
+                                this.core().getFormData();
+                                
+                                cb(suggestion);
+                            }
+    
+                            this.trigger('hideDropdown');
                         }
-                        this.input().val(data);
-                    },
+                    }
                 }
             });
+        },
+        prepare_inputs: function() {
+            var _this = this;
+            
+            this.configure_tags_input(this.$exclusions, 'tags arrow autocomplete', [], function(suggestion) {
+                _this.data.docker_exclusion_list.push(suggestion);
+            });
+
+            this.configure_tags_input(this.$odooImage, 'autocomplete arrow', [], function(suggestion) {
+                _this.data.odoo_docker_image = suggestion;
+            });
+
+            this.configure_tags_input(this.$odooNetwork, 'autocomplete arrow', [], function(suggestion) {
+                _this.data.odoo_network = suggestion;
+            });
+
+            this.configure_tags_input(this.$odooDb, 'autocomplete arrow', [], function(suggestion) {
+                _this.data.odoo_db_link = suggestion;
+            });
+        },
+        prepare_suggestions: function(collection, filter) {
+            return function(e, data) {
+                var suggestions = _.map(collection, function(item) {
+                    return item.name;
+                });
+
+                var textext = $(e.target).textext()[0];
+                var query = (data ? data.query : '') || '';
+
+                $(this).trigger('setSuggestions', {
+                    result: !!filter ? textext.itemManager().filter(suggestions, query) : suggestions
+                });
+            }
+        },
+        initialize_inputs: function() {
+            this.$exclusions.bind('getSuggestions', this.prepare_suggestions(this.config.containers, true));
+            this.$odooImage.bind('getSuggestions', this.prepare_suggestions(this.config.images));
+            this.$odooNetwork.bind('getSuggestions', this.prepare_suggestions(this.config.networks));
+            this.$odooDb.bind('getSuggestions', this.prepare_suggestions(this.config.images));
+        },
+        set_initial_data: function() {
+            this.$exclusions.textext()[0].tags().addTags(this.config.docker_exclusion_list);
+            this.$(this.$odooImage).val(this.config.odoo_docker_image);
+            this.$(this.$odooNetwork).val(this.config.odoo_network);
+            this.$(this.$odooDb).val(this.config.odoo_db_link);
+
+            this.$('#socket-input').val(this.config.docker_socket_path);
+            this.$('#ports-range-input').val(this.config.odoo_ports_range);
+            this.$('#odoo-path-input').val(this.config.odoo_root_path);
+            this.$('#git-path-input').val(this.config.modules_git_path);
+        },
+        get_config: function() {
+            var _this = this;
+
+            this.rpc('/odoo_management/get_config').done(function(config) {
+                _this.config = config;
+                _this.initialize_inputs();
+                _this.set_initial_data();
+            });  
+        },
+        send_config: function() {
+            _.extend(this.data, {
+                docker_socket_path: this.$('#socket-input').val(),
+                odoo_ports_range: this.$('#ports-range-input').val(),
+                odoo_root_path: this.$('#odoo-path-input').val(),
+                modules_git_path: this.$('#git-path-input').val()
+            });
+
+            this.rpc('/odoo_management/save_config', this.data).done(function(data) {
+                console.log(data);
+            }); 
         }
     });
 

+ 17 - 17
static/src/xml/main.xml

@@ -40,7 +40,7 @@
                                     </td>
                                     <td class="oe_form_group_cell oe_form_group_cell_label" colspan="1" width="99%">
                                         <span class="oe_form_field oe_form_field_char">
-                                            <input id="socket-input" maxlength="100" type="text" placeholder="/var/run/docker.sock" />
+                                            <input id="socket-input" name="docker_sock" maxlength="100" type="text" placeholder="/var/run/docker.sock" />
                                         </span>
                                     </td>
                                 </tr>
@@ -50,7 +50,7 @@
                                     </td>
                                     <td class="oe_form_group_cell" colspan="1" width="99%">
                                         <span class="oe_form_field oe_tags">
-                                            <textarea id="exclusions-input" rows="1"></textarea>
+                                            <textarea id="exclusions-input" name="docker_exclusion" rows="1"></textarea>
                                         </span>
                                     </td>
                                 </tr>
@@ -74,51 +74,51 @@
                             <tbody>
                                 <tr class="oe_form_group_row">
                                     <td class="oe_form_group_cell oe_form_group_cell_label" colspan="1" width="1%">
-                                        <label for="oe-field-input-4" class=" oe_form_label oe_align_right">Imagen docker</label>
+                                        <label for="image-input" class=" oe_form_label oe_align_right">Imagen docker</label>
                                     </td>
                                     <td class="oe_form_group_cell" colspan="1" width="99%">
-                                        <span class="oe_form_field oe_form_field_char">
-                                            <input id="oe-field-input-4" maxlength="50" type="text" />
+                                        <span class="oe_form_field oe_tags">
+                                            <textarea id="image-input" name="odoo_image" rows="1"></textarea>
                                         </span>
                                     </td>
                                 </tr>
                                 <tr class="oe_form_group_row">
                                     <td class="oe_form_group_cell oe_form_group_cell_label" colspan="1" width="1%">
-                                        <label for="oe-field-input-5" class=" oe_form_label oe_align_right">Red virtual</label>
+                                        <label for="network-input" class=" oe_form_label oe_align_right">Red virtual</label>
                                     </td>
                                     <td class="oe_form_group_cell" colspan="1" width="99%">
-                                        <span class="oe_form_field oe_form_field_char">
-                                            <input id="oe-field-input-5" maxlength="50" type="text" />
+                                        <span class="oe_form_field oe_tags">
+                                            <textarea id="network-input" name="odoo_network" rows="1"></textarea>
                                         </span>
                                     </td>
                                 </tr>
                                 <tr class="oe_form_group_row">
                                     <td class="oe_form_group_cell oe_form_group_cell_label" colspan="1" width="1%">
-                                        <label for="oe-field-input-6" class=" oe_form_label oe_align_right">Rango de puertos</label>
+                                        <label for="ports-range-input" class=" oe_form_label oe_align_right">Rango de puertos</label>
                                     </td>
                                     <td class="oe_form_group_cell" colspan="1" width="99%">
                                         <span class="oe_form_field oe_form_field_char">
-                                            <input id="oe-field-input-6" maxlength="50" type="text" />
+                                            <input id="ports-range-input" name="odoo_ports_range" maxlength="50" type="text" />
                                         </span>
                                     </td>
                                 </tr>
                                 <tr class="oe_form_group_row">
                                     <td class="oe_form_group_cell oe_form_group_cell_label" colspan="1" width="1%">
-                                        <label for="oe-field-input-7" class=" oe_form_label oe_align_right">Ruta raíz</label>
+                                        <label for="odoo-path-input" class=" oe_form_label oe_align_right">Ruta raíz</label>
                                     </td>
                                     <td class="oe_form_group_cell" colspan="1" width="99%">
                                         <span class="oe_form_field oe_form_field_char">
-                                            <input id="oe-field-input-7" maxlength="50" type="text" />
+                                            <input id="odoo-path-input" name="odoo_root_path" maxlength="50" type="text" />
                                         </span>
                                     </td>
                                 </tr>
                                 <tr class="oe_form_group_row">
                                     <td class="oe_form_group_cell oe_form_group_cell_label" colspan="1" width="1%">
-                                        <label for="oe-field-input-8" class=" oe_form_label oe_align_right">Base de datos</label>
+                                        <label for="db-input" class=" oe_form_label oe_align_right">Base de datos</label>
                                     </td>
                                     <td class="oe_form_group_cell" colspan="1" width="99%">
-                                        <span class="oe_form_field oe_form_field_char">
-                                            <input id="oe-field-input-8" maxlength="50" type="text" />
+                                        <span class="oe_form_field oe_tags">
+                                            <textarea id="db-input" name="odoo_db" rows="1"></textarea>
                                         </span>
                                     </td>
                                 </tr>
@@ -142,11 +142,11 @@
                             <tbody>
                                 <tr class="oe_form_group_row">
                                     <td class="oe_form_group_cell oe_form_group_cell_label" colspan="1" width="1%">
-                                        <label for="oe-field-input-9" class=" oe_form_label oe_align_right">Ruta del repositorio</label>
+                                        <label for="git-path-input" class=" oe_form_label oe_align_right">Ruta del repositorio</label>
                                     </td>
                                     <td class="oe_form_group_cell" colspan="1" width="99%">
                                         <span class="oe_form_field oe_form_field_char">
-                                            <input id="oe-field-input-9" maxlength="100" type="text" />
+                                            <input id="git-path-input" name="git_path" maxlength="100" type="text" />
                                         </span>
                                     </td>
                                 </tr>

+ 2 - 1
utils/__init__.py

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

+ 24 - 1
utils/docker_api.py

@@ -11,6 +11,15 @@ except DockerException:
     raise Warning('Socket not found')
 
 
+def get_client():
+    return client
+
+
+def run_watchdog(func):
+    for e in client.events():
+        func(e)
+
+
 def get_all_images():
     images = []
 
@@ -36,7 +45,7 @@ def get_all_containers():
             'id': container.id,
             'short_id': container.short_id,
             'name': container.name,
-            'image': container.image,
+            'image': container.image.tags,
             'labels': container.labels,
             'status': container.status,
             'attrs': container.attrs
@@ -62,6 +71,20 @@ def get_all_external_ports():
     return ports
 
 
+def get_all_networks():
+    networks = []
+
+    for n in client.networks.list():
+        networks.append({
+            'id': n.id,
+            'short_id': n.short_id,
+            'name': n.name,
+            'attrs': n.attrs
+        })
+
+    return networks
+
+
 def get_network(network_name_or_id):
     try:
         network = client.networks.get(network_name_or_id)