Installing the Moin2rst plugin
I was trying to install this plugin into my MoinMoin 1.9 wiki → https://github.com/dwf/moin2rst
The installation instruction are incorrect
wiki/data/plugin/action/RenderAsRestructuredtext.py wiki/data/plugin/formatter/text_x-rst.py
Errors and changes to make this work with MoinMoin 1.9
Traceback (most recent call last): File "/usr/local/lib/python2.7/site-packages/MoinMoin/support/werkzeug/wsgi.py", line 766, in __call__ return self.app(environ, start_response) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 264, in __call__ response = run(context) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 89, in run response = dispatch(request, context, action_name) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 137, in dispatch response = handle_action(context, pagename, action_name) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 203, in handle_action handler(context.page.page_name, context) File "/usr/local/lib/python2.7/site-packages/MoinMoin/action/__init__.py", line 277, in do_format do_show(pagename, request, count_hit=0, cacheable=0, mimetype=u'text/plain') File "/usr/local/lib/python2.7/site-packages/MoinMoin/action/__init__.py", line 267, in do_show content_only=content_only, File "/usr/local/lib/python2.7/site-packages/MoinMoin/Page.py", line 1165, in send_page Formatter = wikiutil.searchAndImportPlugin(request.cfg, "formatter", self.output_mimetype) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wikiutil.py", line 1194, in searchAndImportPlugin raise PluginMissingError("Plugin not found! (%r %r %r)" % (type, name, what)) MoinMoin.wikiutil.PluginMissingError: Plugin not found! ('formatter' 'text/x-rst' 'Formatter')
A change in wikiutil.py#Mime means the formatter plug in is not being found. The file we are looking for won't be what is supplied with the GIT repo.
modname = mimetype.replace("/", "_").replace("-", "_").replace(".", "_")
Rename the file from text_x-rst.py TO text_x_rst.py
-rw-r--r-- 1 root www 34417 Jan 21 17:11 text_x_rst.py
Next problem
Traceback (most recent call last): File "/usr/local/lib/python2.7/site-packages/MoinMoin/support/werkzeug/wsgi.py", line 766, in __call__ return self.app(environ, start_response) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 264, in __call__ response = run(context) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 89, in run response = dispatch(request, context, action_name) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 137, in dispatch response = handle_action(context, pagename, action_name) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 203, in handle_action handler(context.page.page_name, context) File "/usr/local/lib/python2.7/site-packages/MoinMoin/action/__init__.py", line 277, in do_format do_show(pagename, request, count_hit=0, cacheable=0, mimetype=u'text/plain') File "/usr/local/lib/python2.7/site-packages/MoinMoin/action/__init__.py", line 267, in do_show content_only=content_only, File "/usr/local/lib/python2.7/site-packages/MoinMoin/Page.py", line 1332, in send_page start_line=pi['lines']) File "/usr/local/lib/python2.7/site-packages/MoinMoin/Page.py", line 1422, in send_page_content self.format(parser) File "/usr/local/lib/python2.7/site-packages/MoinMoin/Page.py", line 1443, in format parser.format(self.formatter) File "/usr/local/lib/python2.7/site-packages/MoinMoin/parser/text_moin_wiki.py", line 1553, in format formatted_line = self.scan(line, inhibit_p=inhibit_p) File "/usr/local/lib/python2.7/site-packages/MoinMoin/parser/text_moin_wiki.py", line 1363, in scan result.append(self.replace(match, inhibit_p)) File "/usr/local/lib/python2.7/site-packages/MoinMoin/parser/text_moin_wiki.py", line 1407, in replace result.append(replace_func(hit, match.groupdict())) File "/usr/local/lib/python2.7/site-packages/MoinMoin/parser/text_moin_wiki.py", line 1330, in _macro_repl return self.formatter.macro(self.macro, macro_name, macro_args, markup=groups.get('macro')) TypeError: macro() got an unexpected keyword argument 'markup'
text_x_rst.py: Change the definition of this call:
def macro(self, macroObj, name, argString): to: def macro(self, macroObj, name, argString, **kwargs):
Next problem
Traceback (most recent call last): File "/usr/local/lib/python2.7/site-packages/MoinMoin/support/werkzeug/wsgi.py", line 766, in __call__ return self.app(environ, start_response) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 264, in __call__ response = run(context) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 89, in run response = dispatch(request, context, action_name) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 137, in dispatch response = handle_action(context, pagename, action_name) File "/usr/local/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 203, in handle_action handler(context.page.page_name, context) File "/usr/local/lib/python2.7/site-packages/MoinMoin/action/__init__.py", line 277, in do_format do_show(pagename, request, count_hit=0, cacheable=0, mimetype=u'text/plain') File "/usr/local/lib/python2.7/site-packages/MoinMoin/action/__init__.py", line 267, in do_show content_only=content_only, File "/usr/local/lib/python2.7/site-packages/MoinMoin/Page.py", line 1332, in send_page start_line=pi['lines']) File "/usr/local/lib/python2.7/site-packages/MoinMoin/Page.py", line 1422, in send_page_content self.format(parser) File "/usr/local/lib/python2.7/site-packages/MoinMoin/Page.py", line 1443, in format parser.format(self.formatter) File "/usr/local/lib/python2.7/site-packages/MoinMoin/parser/text_moin_wiki.py", line 1553, in format formatted_line = self.scan(line, inhibit_p=inhibit_p) File "/usr/local/lib/python2.7/site-packages/MoinMoin/parser/text_moin_wiki.py", line 1363, in scan result.append(self.replace(match, inhibit_p)) File "/usr/local/lib/python2.7/site-packages/MoinMoin/parser/text_moin_wiki.py", line 1407, in replace result.append(replace_func(hit, match.groupdict())) File "/usr/local/lib/python2.7/site-packages/MoinMoin/parser/text_moin_wiki.py", line 876, in _link_repl self._link_description(desc, target, page_name_and_anchor) + File "/usr/local/www/wiki/data/plugin/formatter/text_x_rst.py", line 488, in pagelink url = self.request.normalizePagename(pagename) File "/usr/local/lib/python2.7/site-packages/MoinMoin/web/contexts.py", line 224, in __getattr__ return super(HTTPContext, self).__getattribute__(name) AttributeError: 'AllContext' object has no attribute 'normalizePagename'
Change these two calls in the text_x_rst.py file
def pagelink... url = self.request.normalizePagename(pagename) urlPath = url.split("/") thisPath = self.request.normalizePagename(self.page.page_name).split("/") TO url = wikiutil.normalize_pagename(pagename, self.request.cfg) urlPath = url.split("/") thisPath = wikiutil.normalize_pagename(self.page.page_name, self.request.cfg).split("/")
After all this and getting it working I decided it was just easier to use docbook !
FreeNAS 11.2-U5 and 10Gbe
This is just a note as I see a lot of posts out there saying use Chelsio cards for FreeNAS as they are well supported. Well I tried this and yes the card was recognized but the DAC cable was not.
Aug 9 18:45:00 ale cxgbc0: <Chelsio T310, 1 port> mem 0xfb881000-0xfb881fff,0xfb000000-0xfb7fffff,0xfb880000-0xfb880fff irq 42 at device 0.0 on pci10 Aug 9 18:45:00 ale kernel: PHY 0 i2c read of dev.addr a0.0 timed out Aug 9 18:45:00 ale kernel: PHY 0 i2c read of dev.addr a0.0 timed out Aug 9 18:45:00 ale cxgbc0: using MSI-X interrupts (9 vectors) Aug 9 18:45:00 ale kernel: found old FW minor version(7.10), driver compiled for version 7.11 Aug 9 18:45:00 ale kernel: found old FW minor version(7.10), driver compiled for version 7.11 Aug 9 18:45:00 ale cxgbc0: firmware needs to be updated to version 7.11.0 Aug 9 18:45:00 ale cxgb0: <Port 0 10GBASE-R> on cxgbc0 Aug 9 18:45:00 ale cxgb0: Using defaults for TSO: 65518/35/2048 Aug 9 18:45:00 ale cxgb0: Ethernet address: 00:07:43:05:fe:ae Aug 9 18:45:00 ale cxgbc0: Firmware Version 7.10.0
Firmware update - I don't think this was necessary as the driver auto updates we just need a reboot
cxgbtool cxgb0 loadfw t3fw-7.11.0.bin Reboot
Next time around the firmware has been updated
Aug 9 18:55:44 ale cxgbc0: using MSI-X interrupts (9 vectors) Aug 9 18:55:44 ale cxgb0: <Port 0 10GBASE-R> on cxgbc0 Aug 9 18:55:44 ale cxgb0: Using defaults for TSO: 65518/35/2048 Aug 9 18:55:44 ale cxgb0: Ethernet address: 00:07:43:05:fe:ae Aug 9 18:55:44 ale cxgbc0: Firmware Version 7.11.0
The drive is plumbed into the kernel but the link won't come up to ACTIVE.
I was using SPF+ CISCO Passive Twinax cable part 74752-9519 connected to Mikrotik CRS305 switch but the link would not activate. I switched to a different 10Gbe card and presto.
MNPA19-XTR | Mellanox EN ConnectX-2 1-Port 10GbE Network Adapter
Aug 22 19:52:55 ale mlx4_core0: <mlx4_core> mem 0xfaa00000-0xfaafffff,0xf5000000-0xf57fffff irq 42 at device 0.0 on pci10 Aug 22 19:52:55 ale kernel: mlx4_core: Mellanox ConnectX core driver v3.4.1 (October 2017) Aug 22 19:52:55 ale kernel: mlx4_core: Initializing mlx4_core Aug 22 19:52:55 ale mlx4_core0: Unable to determine PCI device chain minimum BW Aug 22 19:52:55 ale kernel: mlx4_en mlx4_core0: Activating port:1 Aug 22 19:52:55 ale mlxen0: Ethernet address: 00:02:c9:51:35:34 Aug 22 19:52:55 ale kernel: mlx4_en: mlx4_core0: Port 1: Using 12 TX rings Aug 22 19:52:55 ale kernel: mlx4_en: mlx4_core0: Port 1: Using 12 TX rings Aug 22 19:52:55 ale kernel: mlxen0: link state changed to DOWN Aug 22 19:52:55 ale kernel: mlxen0: link state changed to DOWN Aug 22 19:52:55 ale kernel: mlx4_en: mlx4_core0: Port 1: Using 8 RX rings Aug 22 19:52:55 ale kernel: mlx4_en: mlx4_core0: Port 1: Using 8 RX rings Aug 22 19:52:55 ale kernel: mlx4_en: mlxen0: Using 12 TX rings Aug 22 19:52:55 ale kernel: mlx4_en: mlxen0: Using 12 TX rings Aug 22 19:52:55 ale kernel: mlx4_en: mlxen0: Using 8 RX rings Aug 22 19:52:55 ale kernel: mlx4_en: mlxen0: Using 8 RX rings Aug 22 19:52:55 ale kernel: mlx4_en: mlxen0: Initializing port Aug 22 19:52:55 ale kernel: mlx4_en: mlxen0: Initializing port
ifconfig output for the device. Its alive and happy.
mlxen0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=ad00b9<RXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN _HWFILTER,VLAN_HWTSO,LINKSTATE,RXCSUM_IPV6> ether 00:02:c9:51:35:34 hwaddr 00:02:c9:51:35:34 inet 192.168.1.22 netmask 0xffffff00 broadcast 192.168.1.255 nd6 options=9<PERFORMNUD,IFDISABLED> media: Ethernet autoselect (10Gbase-SR <full-duplex,rxpause,txpause>) status: active root@ale[~]#
Transparent I2P tunneling
These notes are to setup an I2P FreeNAS jail to transparently tunnel .i2p traffic using a Ubiquiti EdgeRouter ER-X
Huge kudos to these notes that got me moving in the right direction:
This is the logical flow of what we are going to setup. Pictures really help the understanding.
EdgeRouter ER-X setup
As I have an EdgeRouter ER-X the instructions will cover what you need to configure on this device in terms of the router setup
Setup DNSMASQ on server to catch .i2p DNS requests return the IP 10.191.0.1 as the domain lookup
/etc/dnsmasq.conf address=/i2p/10.191.0.1
Test it out. Any domain ending in .i2p will return the IP 10.191.0.1
# dig @127.0.0.1 hello.i2p ; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 hello.i2p ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8423 ;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;hello.i2p. IN A ;; ANSWER SECTION: hello.i2p. 0 IN A 10.191.0.1 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Tue Dec 19 02:13:21 UTC 2017 ;; MSG SIZE rcvd: 43
We need to configure a NAT rule to redirect our 10.191.0.1:80 traffic to the server running the privoxy/i2p software.
ubnt@ubnt# show service nat nat { rule 1 { description i2p destination { address 10.191.0.1 port 80 } inbound-interface switch0 inside-address { address 192.168.1.14 port 8118 } log disable protocol tcp source { group { address-group !I2P_EXCLUDE } } type destination } rule 5001 { description "masquerade for WAN" outbound-interface eth0 type masquerade } rule 5002 { description "hairpin for i2p" destination { address 192.168.1.0/24 port 8118 } log disable outbound-interface switch0 protocol tcp source { address 192.168.1.0/24 } type masquerade } } ubnt@ubnt# show firewall group address-group I2P_EXCLUDE { address 192.168.1.14 description "exclude these IP address from being routed via i2p proxy" }
We will end up with a NAT configuration like this:
With the following firewall rule.
FreeNAS I2P jail
I run i2p and privoxy inside a FreeNAS jail so these instructions reflect this.
Follow the instructions to setup the I2P jail
Privoxy configuration
Now the I2P jail is setup we need install the privoxy for transparent routing. The jail does not install privoxy.
Install privoxy into the jail and forward .i2p domain name requests to the router.
# pkg install privoxy
Allow it to autostart edit /etc/rc.conf
privoxy_enable="YES"
We need to pre-create this
# mkdir /var/run/privoxy # chown privoxy:privoxy /var/run/privoxy
Start Privoxy manually to create the necessary config files run:
# /usr/local/etc/rc.d/privoxy forcestart
This will create the file /usr/local/etc/privoxy/config
That is hokey. You have to run it to create the config file so you can edit it ?
Edit the configuration file
listen-address 192.168.1.14:8118 accept-intercepted-requests 1 forward .i2p 127.0.0.1:4444
Restart after making those changes
/usr/local/etc/rc.d/privoxy restart
Setting up Opengrok in a FreeNAS 11.2 iocage jail
Create storage dataset's for GROK
Create a jail for GROK
Setup jail mount points for src and data. You need to stop the jail to add mount points and then restart afterwards.
- /mnt/u03/opengrok/src → /var/opengrok/src
- /mnt/u03/opengrok/data → /var/opengrok/data
Find the JAIL and open a shell
root@ale[~]# jls JID IP Address Hostname Path 1 plex /mnt/u02/iocage/jails/plex/root 2 bind /mnt/u02/iocage/jails/bind/root 5 beer /mnt/u02/iocage/jails/beer/root 6 grok /mnt/u02/iocage/jails/grok/root root@ale[~]# jexec 6 /bin/sh
Install opengrok and git. To generate the history caches from GIT based repositories we need the git command line tool.
# pkg install -y opengrok git # pkg info opengrok opengrok-1.0 Name : opengrok Version : 1.0 Installed on : Tue May 14 09:04:03 2019 EDT Origin : devel/opengrok Architecture : FreeBSD:11:* Prefix : /usr/local Categories : devel java Licenses : APACHE20, CDDL Maintainer : ports@FreeBSD.org WWW : http://opengrok.github.io/OpenGrok/ Comment : Fast and powerful code search and cross-reference engine Options : DOCS : on RESIN3 : off TOMCAT6 : off TOMCAT7 : off TOMCAT8 : on TOMCAT85 : off Annotations : repo_type : binary repository : FreeBSD Flat size : 20.5MiB Description : OpenGrok is a fast source code search and cross reference engine. It helps you search, cross-reference and navigate your source tree. It can understand various program file formats and version control histories like Mercurial, Git, SCCS, RCS, CVS, Subversion, Teamware, ClearCase, Perforce and Bazaar. In other words it lets you grok (profoundly understand) the open source, hence the name OpenGrok. It is written in Java. WWW: http://opengrok.github.io/OpenGrok/
This installs tomcat8 we need to autostart this.
# ls /usr/local/etc/rc.d tomcat8
Enable for auto start /etc/rc.conf
echo tomcat8_enable="YES" >>/etc/rc.conf
and start it
service tomcat8 start
This should fire up with an error. That's OK as we have not indexed anything the error will disappear after indexing.
Make a directory
mkdir /var/opengrok/etc
Create a helper script and run it.
cat <<EOF >~/opengrok-index opengrok -c /usr/local/bin/exctags -s /var/opengrok/src -d /var/opengrok/data -H -P -S -G -W /var/opengrok/etc/configuration.xml service tomcat8 restart EOF chmod a+x ~/opengrok-index ~/opengrok-index
The -U parameter only takes host:port and it assumes the WEBAPP is called /source which means the indexer can't tell the running opengrok to reload. So restart tomcat as part of the index run. A minor wart.
Making opengrok the default webapp and use port 80
Moving tomcat from port 8080 to port 80 Edit /usr/local/apache-tomcat-8.0/conf/server.xml file and replace 8080 with 80
<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
Make opengrok the default web application by adding a <Context> tag inside <Host>
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context path="" docBase="/usr/local/apache-tomcat-8.0/webapps/opengrok"> <WatchedResource>WEB-INF/web.xml</WatchedResource> </Context>
Setting up MoinMoin in a FreeNAS 11.2 iocage jail
Create a jail and attach the storage into the JAIL at this location: /usr/local/www/wiki/data
Login to the jail and install moin this version will do nicely.
# pkg search moin moinmoin-1.9.10 Easy to use, full-featured and extensible wiki software package
Install MoinMoin and run the recommend steps installing from a package.
# pkg install -y moinmoin
Setup for WSGI
export MOINSCRIPT="moin.wsgi" export MOINDIR="/usr/local/share/moin" export MOINDEST="/usr/local/www/wiki" export CGIUSER="www" export CGIGROUP="www" mkdir -p ${MOINDEST}/data mkdir -p ${MOINDEST}/underlay cp -R ${MOINDIR}/data ${MOINDEST} cp -R ${MOINDIR}/underlay ${MOINDEST} chmod -R u+rw,go-ws ${MOINDEST}/data install -m 0555 ${MOINDIR}/config/wikiconfig.py ${MOINDEST} test -z "${MOINSCRIPT}" || \ install -m 0555 ${MOINDIR}/server/${MOINSCRIPT} ${MOINDEST} chown -R ${CGIUSER}:${CGIGROUP} ${MOINDEST}
NGINX setup
Based very closely around * https://wiki.freebsd.org/Ports/www/moinmoin
Install nginx and uwsgi server
pkg install -y nginx uwsgi
Replace /usr/local/etc/nginx/nginx.conf with
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name wiki.local; location / { uwsgi_pass unix:/var/run/moin.sock; include uwsgi_params; } location ~ ^/moin_static[0-9]+/(.*) { alias /usr/local/lib/python2.7/site-packages/MoinMoin/web/static/htdocs/$1; } } }
NOTE: Its important to access the server by a DNS name in the nginx.conf file that resolves to the jail IP. Not doing this will result in the NGINX server not being able to correctly lookup the static content.
Append to /etc/rc.conf
uwsgi_enable="YES" uwsgi_configfile="/usr/local/www/wiki/uwsgi.ini" uwsgi_uid="www" uwsgi_gid="www" nginx_enable="YES"
Create /usr/local/www/wiki/uwsgi.ini
[uwsgi] socket = /var/run/moin.sock chmod-socket = 660 chdir = /usr/local/www/wiki wsgi-file = moin.wsgi master workers = 3 max-requests = 200 harakiri = 30 die-on-term
Wiki config
Allow anybody to edit anything and for them to create their own account.
Add the acl_rights_default entries and uncomment page_front_page and actions_superuser.
/usr/local/www/wiki/wikiconfig.py
class Config(multiconfig.DefaultConfig): # Critical setup --------------------------------------------------- # Directory containing THIS wikiconfig: wikiconfig_dir = os.path.abspath(os.path.dirname(__file__)) acl_rights_default = u"All:read,write,delete,revert,admin" page_front_page = u'FrontPage' actions_superuser = multiconfig.DefaultConfig.actions_superuser[:] actions_superuser.remove('newaccount')
Start it up
service uwsgi start service ngnix start
Xapian
Speeding up searching by enabling xapian
pkg install xapian-core py27-xapian
/usr/local/www/wiki/wikiconfig.py
xapian_search = True xapian_stemming = True
Restart
service uwsgi restart
You can check to see if its enabled by navigating to SystemInfo
Installing the umlsequence diagram plugin
Grab the plugin: https://moinmo.in/ParserMarket/UmlSequence and install the file umlsequence.py into /usr/local/www/wiki/data/plugin/parser/
File with all modification presented below: umlsequence.zip
Install additional packages into the jail:
- plotutils → supplies pic2plot
- ImageMagick7-nox11 → supplied convert
pkg update -f pkg install plotutils pkg install ImageMagick7-nox11
We need to edit the umlsequence.py source code to adjust where the required utilities are installed.
pic2plot path change
# Launch pic2plot => postscript os.system ('/usr/local/bin/pic2plot -T ps "%s" > "%s" 2>"%s"' % (pic, ps, err))
The convert program would not run with just the path to the program. The path /usr/local/bin has to be in the PATH env var.
# Run the postprocessing/conversion chain cmd = 'PATH=$PATH:/usr/local/bin convert -density %dx%d "%s" "%s"' % (opt_percent, opt_percent, ps, pngpath) os.system(cmd)
Enabling the alternative format specification
The src code was modified to include the alt= switch so that original and alternative could be supported in the wiki.
*************** *** 804,813 **** --- 804,815 ---- opt_dbg = False opt_help = None opt_percent = 100 + opt_alt = False for (key, val) in self.attrs.items (): val = val [1:-1] if key == 'debug': opt_dbg = int (val) elif key == 'help': opt_help = val + elif key == 'alt': opt_alt = True elif key == 'percent': opt_percent = int (val) else: self.request.write (formatter.rawHTML (""" *************** *** 845,851 **** lines = raw.split ('\n') # alternate syntax support ! lines = self._convert_from_alternate_1 (lines) # debug ? post-print if opt_dbg==2: --- 847,854 ---- lines = raw.split ('\n') # alternate syntax support ! if opt_alt: ! lines = self._convert_from_alternate_1 (lines) # debug ? post-print if opt_dbg==2:
Using the alternate format to draw diagrams
{{{#!umlsequence alt=1 S : s:Switch P : p:Pump S -> P run() S -> P stop() }}}
The original syntax
{{{#!umlsequence # Object definition object(S,"s:Switch"); object(P,"p:Pump"); # Message exchange message(S,P,"run()"); message(S,P,"stop()"); # Object lifeline completion complete(S); complete(P); }}}