Commit 172d7606 authored by jssuzanne's avatar jssuzanne
Browse files

Add script

--HG--
branch : 8.0
parent 7423da45b651
......@@ -40,9 +40,8 @@
'security/ir.model.access.csv',
'view/menu.xml',
'view/connection.xml',
'view/exchange.xml',
'view/queue.xml',
'wizard/anybus_installer.xml',
'view/consumer.xml',
'view/message.xml',
],
'demo_xml': [
],
......
......@@ -21,6 +21,14 @@ class anybusConnection(models.Model):
default='disconnected', readonly=True,
)
_sql_constraints = [
(
'name_unique',
'UNIQUE (name)',
'The name of the connection must be unique !'
),
]
broker_connection = None
def action_purge(self, queue):
......
......@@ -8,3 +8,8 @@ class AnybusConsumer(models.Model):
name = fields.Char(required=True)
queue = fields.Char(required=True)
model = fields.Many2one('res.model', required=True)
consumer_method = fields.Char(required=True)
def process(self):
pass
......@@ -2,21 +2,32 @@
from openerp import models, fields
class AbstractAnybusMessage(models.Model):
class AnybusMessage(models.Model):
_name = "anybus.message"
_description = "Abstract anybus message"
_inherit = [
'ir.needaction_mixin',
]
_order = 'sequence, id'
consumer = fields.Many2one('anybus.consumer', required=True)
consumer = fields.Many2one('anybus.consumer', readonly=True)
exchange = fields.Char(readonly=True)
binding_key = fields.Char(readonly=True)
sequence = fields.Integer(required=True, default=100)
message = fields.Binary('Message', required=True),
message = fields.Binary(required=True)
contenttype = fields.Char(required=True)
error = fields.Text(required=True)
name = fields.Char(compute="get_name")
def _needaction_domain_get(self):
return []
def _needaction_domain_get(self, *a, **kw):
return [('id', '!=', 0)]
def get_name(self):
for this in self:
if this.consumer:
this.name = this.consumer.name
else:
this.name = "%s => %s" % (this.exchange, this.binding_key)
def process(self):
pass
......
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"acc_anybus_connection","Connection","model_anybus_connection","",1,1,1,1
"acc_anybus_entity_queue","Queue","model_anybus_entity_queue","",1,1,1,1
from . import test_simple_connection
from . import test_anybus_model
fast_suite = [
test_anybus_model,
test_simple_connection,
]
# -*- coding: utf-8 -*-
from openerp.tests.common import TransactionCase, SingleTransactionCase
import os
from subprocess import call, Popen, PIPE
class AnybusModelCase(TransactionCase):
def _test_model(self, model_name, read=True):
cr, uid = self.cr, self.uid
model = self.registry(model_name)
if read:
model_ids = model.search(cr, uid, [])
model.read(cr, uid, model_ids, [])
view_model = self.registry('ir.ui.view')
view_ids = view_model.search(cr, uid, [('model', '=', model_name)])
for view in view_model.browse(cr, uid, view_ids):
model.fields_view_get(
cr, uid, view_id=view.id, view_type=view.type)
class AnybusCase(object):
@classmethod
def _setUpClass(self):
env = os.environ
self.uri = env.get(
'RMQ_BASE_URI', 'amqp://guest:guest@localhost:5672/')
self.binary = env.get('RMQ_BINARY', '/opt/local/sbin/rabbitmqctl')
self.sudo = env.get('AMQP_CTL_SUDO', True)
self.dbname = self.cr.dbname
if self._rabbitmq_vhost_exist('/' + self.cr.dbname):
self._rabbitmq_delete_vhost()
self._rabbitmq_add_vhost()
self.conn_model = self.registry('anybus.connection')
self.conn_demo_id = self.ref('anybus.anybus_connection_demo')
self.conn_model.write(
self.cr, self.uid, [self.conn_demo_id],
{'uri': self.uri + '/%(dbname)s'})
self.ex_model = self.registry('anybus.entity.exchange')
self.ex_demo_id = self.ref('anybus.anybus_entity_exchange_demo')
self.q_model = self.registry('anybus.entity.queue')
self.q_demo_id = self.ref('anybus.anybus_entity_queue_demo')
self.bind_model = self.registry('anybus.binding')
self.bind_demo_id = self.ref('anybus.anybus_binding_demo')
@classmethod
def _tearDownClass(self):
self._rabbitmq_delete_vhost()
@classmethod
def _rabbitmq_add_vhost(self):
base_ctl = []
if self.sudo:
base_ctl.append('sudo')
ctl = [
self.binary,
'add_vhost',
'/' + self.dbname,
]
call(base_ctl + ctl)
ctl = [
self.binary,
'set_permissions',
'-p',
'/' + self.dbname,
'guest',
'.*',
'.*',
'.*',
]
call(base_ctl + ctl)
@classmethod
def _rabbitmq_vhost_exist(self, vhost):
base_ctl = []
if self.sudo:
base_ctl.append('sudo')
ctl = [
self.binary,
'list_vhosts',
]
stdout = Popen(base_ctl + ctl, stdout=PIPE)
vhosts = stdout.communicate()[0].split('\n')
for v in vhosts:
if v == vhost:
return True
return False
@classmethod
def _rabbitmq_delete_vhost(self):
base_ctl = []
if self.sudo:
base_ctl.append('sudo')
ctl = [
self.binary,
'delete_vhost',
'/' + self.dbname,
]
call(base_ctl + ctl)
def declare_connection(self, conn_id):
self.conn_model.action_declare(self.cr, self.uid, [conn_id])
def declare_demo_connection(self):
self.declare_connection(self.conn_demo_id)
def declare_all_connection(self, conn_ids):
self.conn_model.action_declare_all(self.cr, self.uid, conn_ids)
def redraft_connection(self, conn_id):
self.conn_model.action_redraft(self.cr, self.uid, [conn_id])
def redraft_demo_connection(self):
self.redraft_connection(self.conn_demo_id)
def redraft_all_connection(self, conn_ids):
self.conn_model.action_redraft(self.cr, self.uid, conn_ids)
def purge_all_connections_queues(self, conn_ids):
self.conn_model.action_purge_all(self.cr, self.uid, conn_ids)
def drain_events(self, conn_id):
self.conn_model.action_connect(self.cr, self.uid, [conn_id])
def drain_events_demo(self):
self.drain_events(self.conn_demo_id)
def declare_entity(self, model, entity_id):
model.action_declare(self.cr, self.uid, [entity_id])
def declare_demo_exchange(self):
self.declare_entity(self.ex_model, self.ex_demo_id)
def declare_demo_queue(self):
self.declare_entity(self.q_model, self.q_demo_id)
def purge_queue(self, queue_id):
self.q_model.action_purge(self.cr, self.uid, [queue_id])
def purge_demo_queue(self):
self.purge_demo_queue(self.q_demo_id)
def redraft_entity(self, model, entity_id):
model.action_redraft(self.cr, self.uid, [entity_id])
def redraft_demo_queue(self):
self.redraft_entity(self.q_model, self.q_demo_id)
def redraft_demo_exchange(self):
self.redraft_entity(self.ex_model, self.q_demo_id)
def get_queue_reception_qty(self, queue):
base_ctl = []
if self.sudo:
base_ctl.append('sudo')
ctl = [
self.binary,
'list_queues',
'-p',
'/' + self.dbname,
]
res = Popen(base_ctl + ctl, stdout=PIPE)
stdout = res.communicate()[0].split('\n')
for l in stdout:
if l.find(queue) != -1:
q, qty = l.split('\t')
return int(qty)
self.fail('No queue %r found' % queue)
def _test_action_publish(self, action_model, action_id):
model = self.registry('res.partner')
model_ids = model.search(self.cr, self.uid, [])
queue_name = self.q_model.name_get(
self.cr, self.uid, [self.q_demo_id])[0][1]
action_model.make_action(
self.cr, self.uid, [action_id], model._name, model_ids)
qty = self.get_queue_reception_qty(queue_name)
if not qty:
self.fail("No message received")
class AnybusTransactionCase(TransactionCase, AnybusCase):
conn_ids = []
def setUp(self):
super(AnybusTransactionCase, self).setUp()
self._setUpClass()
self.conn_ids.append(self.conn_demo_id)
self.declare_all_connection(self.conn_ids)
def tearDown(self):
self.redraft_all_connection(self.conn_ids)
self.purge_all_connections_queues(self.conn_ids)
self._tearDownClass()
super(AnybusTransactionCase, self).tearDown()
class AnybusSingleTransactionCase(SingleTransactionCase, AnybusCase):
@classmethod
def setUpClass(self):
super(AnybusSingleTransactionCase, self).setUpClass()
self._setUpClass()
@classmethod
def tearDownClass(self):
self._tearDownClass()
super(AnybusSingleTransactionCase, self).tearDownClass()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# -*- coding: utf-8 -*-
from test_anybus import AnybusModelCase
class TestAnybusModel(AnybusModelCase):
def test_anybus_connection(self):
self._test_model('anybus.connection', read=True)
def test_anybus_entity_exchange(self):
self._test_model('anybus.entity.exchange', read=True)
def test_anybus_entity_queue(self):
self._test_model('anybus.entity.queue', read=True)
def test_anybus_binding(self):
self._test_model('anybus.binding', read=True)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# -*- coding: utf-8 -*-
from test_anybus import AnybusSingleTransactionCase
from subprocess import Popen, PIPE
class TestSimpleConnection(AnybusSingleTransactionCase):
def check_entity_exist_in_rabbitmq(self, entity_ctl, names,
mustfound=True):
base_ctl = []
if self.sudo:
base_ctl.append('sudo')
ctl = [
self.binary,
entity_ctl,
'-p',
'/' + self.dbname,
]
res = Popen(base_ctl + ctl, stdout=PIPE)
stdout = res.communicate()[0]
for name in names:
if mustfound and stdout.find(name) == -1:
self.fail(
'No entity %r found in %r command' % (name, entity_ctl))
elif not mustfound and stdout.find(name) != -1:
self.fail(
'Entity %r found in %r command, this entity would have '
'been delete' % (name, entity_ctl))
def test_0_declare_connection(self):
"""
test if the connaction can be done with rabbitmq one the vhost
"""
self.declare_demo_connection()
def test_1_declare_exchange(self):
"""
Declare the exchange demo in the vhost
"""
self.declare_demo_exchange()
exchange_id = self.ref('anybus.anybus_entity_exchange_demo')
name = self.registry('anybus.entity.exchange').name_get(
self.cr, self.uid, [exchange_id])[0][1]
self.check_entity_exist_in_rabbitmq('list_exchanges', [name])
def test_2_declare_queue(self):
"""
Declare the queue demo in the vhost
"""
self.declare_demo_queue()
queue_id = self.ref('anybus.anybus_entity_queue_demo')
queue_name = self.registry('anybus.entity.queue').name_get(
self.cr, self.uid, [queue_id])[0][1]
exchange_id = self.ref('anybus.anybus_entity_exchange_demo')
exchange_name = self.registry('anybus.entity.exchange').name_get(
self.cr, self.uid, [exchange_id])[0][1]
self.check_entity_exist_in_rabbitmq('list_queues', [queue_name])
self.check_entity_exist_in_rabbitmq(
'list_bindings', [queue_name, exchange_name])
def test_3_publish_a_message(self):
"""
Just publish a message
"""
queue_name = self.q_model.name_get(
self.cr, self.uid, [self.q_demo_id])[0][1]
rk = self.bind_model._get_routing_key(
self.cr, self.uid, self.bind_demo_id)
self.ex_model.publish(self.cr, self.uid, self.ex_demo_id, "", rk)
qty = self.get_queue_reception_qty(queue_name)
if not qty:
self.fail("No message received")
def test_4_receive_the_message(self):
"""
Get the message
"""
queue_name = self.q_model.name_get(
self.cr, self.uid, [self.q_demo_id])[0][1]
self.q_model.get(self.cr, self.uid, self.q_demo_id)
qty = self.get_queue_reception_qty(queue_name)
if qty:
self.fail("No message consume")
def test_5_redraft_connection(self):
"""
Redraft the connection
Remove the exchange demo in the vhost
Remove the queue demo in the vhost
"""
self.redraft_demo_connection()
queue_id = self.ref('anybus.anybus_entity_queue_demo')
queue_name = self.registry('anybus.entity.queue').name_get(
self.cr, self.uid, [queue_id])[0][1]
exchange_id = self.ref('anybus.anybus_entity_exchange_demo')
exchange_name = self.registry('anybus.entity.exchange').name_get(
self.cr, self.uid, [exchange_id])[0][1]
self.check_entity_exist_in_rabbitmq(
'list_bindings', [queue_name, exchange_name], mustfound=False)
self.check_entity_exist_in_rabbitmq(
'list_queues', [queue_name], mustfound=False)
self.check_entity_exist_in_rabbitmq(
'list_exchanges', [exchange_name], mustfound=False)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
......@@ -6,63 +6,17 @@
<field name="model">anybus.connection</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<tree string="Connections" colors="grey:state=='draft';blue:state == 'declared';green:state == 'connected'">
<tree
string="Connections"
colors="red:state == 'disconnected';green:state == 'connected'"
editable="bottom"
>
<field name="name"/>
<field name="url"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="view_anybus_connection_form" model="ir.ui.view">
<field name="name">anybus.connection.form</field>
<field name="model">anybus.connection</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<form string="Connections" version="7.0">
<header>
<button string="Declare" states="draft" type="object" name="action_declare" class="oe_highlight"/>
<button string="Redraft" states="declared" type="object" name="action_redraft"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<group colspan="4">
<field name="name"/>
</group>
<notebook colspan="4">
<page string="Configuration">
<separator string="URI" colspan="4"/>
<label colspan="4" string="transport://userid:password@hostname:port/virtual_host"/>
<label colspan="4" string="The query part of the URL can also be used to set options, e.g.:"/>
<label colspan="4" string=" amqp://localhost/myvhost?ssl=1"/>
<field name="uri" colspan="4" nolabel="1" attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<label colspan="4" string="You can use %%(dbname)s in your uri, this field is evaluated"/>
<separator string="Keyword arguments" colspan="4"/>
<label colspan="4" string="The BrokerConnection class supports additional keyword arguments, these are:"/>
<label colspan="4" string="hostname: Default host name if not provided in the URL."/>
<label colspan="4" string="userid: Default user name if not provided in the URL."/>
<label colspan="4" string="password: Default password if not provided in the URL."/>
<label colspan="4" string="virtual_host: Default virtual host if not provided in the URL."/>
<label colspan="4" string="port: Default port if not provided in the URL."/>
<label colspan="4" string="transport: Default transport if not provided in the URL. Can be a string specifying the path to the class. (e.g. kombu.transport.pyamqplib.Transport), or one of the aliases: amqplib, pika, redis, memory, and so on."/>
<label colspan="4" string="ssl: Use SSL to connect to the server. Default is False. Only supported by the amqp transport."/>
<label colspan="4" string="insist: Insist on connecting to a server. In a configuration with multiple load-sharing servers, the insist option tells the server that the client is insisting on a connection to the specified server. Default is False. Only supported by the amqp and pika transports, and not by AMQP 0-9-1."/>
<label colspan="4" string="connect_timeout: Timeout in seconds for connecting to the server. May not be supported by the specified transport."/>
<label colspan="4" string="transport_options: A dict of additional connection arguments to pass to alternate kombu channel implementations. Consult the transport documentation for available options."/>
</page>
<page string="Actions" invisible="1">
</page>
<page string="Entities">
<separator string="Exchanges" colspan="4"/>
<field name="exchange_ids" nolabel="1" colspan="4"/>
<separator string="Queues" colspan="4"/>
<field name="queue_ids" nolabel="1" colspan="4"/>
<button string="Declare all entities" icon="gtk-ok" states="declared,connected" type="object" name="action_declare_all"/>
<button string="Purge all queues" icon="gtk-ok" states="declared,connected" type="object" name="action_purge_all"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="view_anybus_connection_search" model="ir.ui.view">
<field name="name">anybus.connection.search</field>
<field name="model">anybus.connection</field>
......@@ -70,6 +24,7 @@
<field name="arch" type="xml">
<search string="Connections">
<field name="name"/>
<field name="url"/>
<field name="state"/>
</search>
</field>
......@@ -79,17 +34,11 @@
<field name="type">ir.actions.act_window</field>
<field name="res_model">anybus.connection</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_mode">tree</field>
<field name="search_view_id" ref="view_anybus_connection_search"/>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record model="ir.actions.act_window.view" id="act_open_anybus_connection_view_form">
<field name="act_window_id" ref="act_open_anybus_connection_view"/>
<field name="sequence" eval="20"/>
<field name="view_mode">form</field>
<field name="view_id" ref="view_anybus_connection_form"/>
</record>
<record model="ir.actions.act_window.view" id="act_open_anybus_connection_view_tree">
<field name="act_window_id" ref="act_open_anybus_connection_view"/>
<field name="sequence" eval="10"/>
......@@ -98,7 +47,7 @@
</record>
<menuitem id="menu_anybus_connection"
parent="menu_anybus_general"
sequence="40"
sequence="10"
action="act_open_anybus_connection_view"/>
</data>
</openerp>
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record id="view_anybus_consumer_tree" model="ir.ui.view">
<field name="name">anybus.consumer.tree</field>
<field name="model">anybus.consumer</field>
<field name="type">tree</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<tree string="Consumers" editable="bottom">
<field name="name"/>
<field name="queue"/>
<field name="consumer_method"/>
</tree>
</field>
</record>
<record id="view_anybus_consumer_search" model="ir.ui.view">
<field name="name">anybus.consumer.search</field>
<field name="model">anybus.consumer</field>
<field name="type">search</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<search string="Consumers">
<field name="name"/>
<field name="queue"/>
<field name="consumer_method"/>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="act_open_anybus_consumer_view">
<field name="name">Consumers</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">anybus.consumer</field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="search_view_id" ref="view_anybus_consumer_search"/>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record model="ir.actions.act_window.view" id="act_open_anybus_consumer_view_tree">
<field name="act_window_id" ref="act_open_anybus_consumer_view"/>
<field name="sequence" eval="10"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="view_anybus_consumer_tree"/>
</record>
<menuitem id="menu_anybus_consumer"
sequence="20"
parent="menu_anybus_general"
action="act_open_anybus_consumer_view"/>
</data>
</openerp>
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record id="view_anybus_entity_exchange_tree" model="ir.ui.view">
<field name="name">anybus.entity.exchange.tree</field>
<field name="model">anybus.entity.exchange</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<tree string="Exchanges" fonts="bold:state=='declared'" colors="grey:type=='direct';green:type=='topic';blue:type=='fanout';red:type=='headers'">
<field name="connection_id"/>
<field name="name"/>
<field name="type"/>