Commit 467b6b86 authored by Boris Kocherov's avatar Boris Kocherov

use connection string as configure interlink between libreoffice and uno client

parent a073ec45
......@@ -29,7 +29,7 @@
from zope.interface import implements
from cloudooo.interfaces.application import IApplication
from cloudooo.util import logger
from psutil import pid_exists, Process, AccessDenied, TimeoutExpired, NoSuchProcess
from psutil import pid_exists, Process, TimeoutExpired, NoSuchProcess
class Application(object):
......@@ -100,17 +100,7 @@ class Application(object):
pid = self.pid()
if pid is None or not pid_exists(pid):
return False
process = Process(pid)
try:
for connection in process.connections():
if connection.status == 'LISTEN' and \
connection.laddr[1] == self.port:
return True
except AccessDenied:
return False
return False
return True
def getAddress(self):
"""Return port and hostname of OOo Instance."""
......
......@@ -25,10 +25,8 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import uuid
import pkg_resources
import psutil
from psutil import AccessDenied
from os.path import exists, join
from subprocess import Popen, PIPE
from threading import Lock
......@@ -37,12 +35,12 @@ from application import Application
from cloudooo.interfaces.lockable import ILockable
from cloudooo.util import logger
from cloudooo.handler.ooo.util import waitStartDaemon, \
removeDirectory, \
socketStatus
removeDirectory
try:
import json
except ImportError:
import simplejson as json
from time import sleep
class OpenOffice(Application):
......@@ -62,17 +60,16 @@ class OpenOffice(Application):
self.last_test_error = None
self._cleanRequest()
def _testOpenOffice(self, host, port):
def _testOpenOffice(self):
"""Test if OpenOffice was started correctly"""
logger.debug("Test OpenOffice %s - Pid %s" % (self.getAddress()[-1],
logger.debug("Test OpenOffice %s - Pid %s" % (self.getConnection(),
self.pid()))
python = join(self.office_binary_path, "python")
args = [exists(python) and python or "python",
pkg_resources.resource_filename("cloudooo",
join('handler', 'ooo',
"helper", "openoffice_tester.py")),
"--hostname=%s" % host,
"--port=%s" % port,
"--connection=%s" % self.getConnection(),
"--uno_path=%s" % self.uno_path,
"--office_binary_path=%s" % self.office_binary_path]
stdout, stderr = Popen(args, stdout=PIPE,
......@@ -85,7 +82,7 @@ class OpenOffice(Application):
stdout = json.loads(stdout)
self.last_test_error = stderr
if stdout == True:
logger.debug("Instance %s works" % port)
logger.debug("Instance %s works" % self.getConnection())
return stdout
def _cleanRequest(self):
......@@ -108,6 +105,17 @@ class OpenOffice(Application):
self.uno_path = uno_path
self.default_language = default_language
self.environment_dict = environment_dict
self.connection = "socket,host=%s,port=%d" % (self.hostname, self.port)
self.connection = "pipe,name=cloudooo_libreoffice_%s" % str(uuid.uuid1())
def status(self):
if Application.status(self) and \
self._testOpenOffice():
# repeat for check if uno client do not terminate
# libreoffice
if Application.status(self):
return True
return False
def _startProcess(self, command, env):
"""Start OpenOffice.org process"""
......@@ -116,29 +124,15 @@ class OpenOffice(Application):
self.process = Popen(command,
close_fds=True,
env=env)
if not waitStartDaemon(self, self.timeout):
continue
if self._testOpenOffice(self.hostname, self.port):
return
def _releaseOpenOfficePort(self):
for process in psutil.process_iter():
try:
if process.exe() == join(self.office_binary_path, self._bin_soffice):
for connection in process.connections():
if connection.status == "LISTEN" and \
connection.laddr[1] == self.port:
self.stopProcess(process.pid)
break
except AccessDenied, e:
pass
except TypeError, e:
# exception to prevent one psutil issue with zombie processes
logger.error(e)
except NotImplementedError, e:
logger.error("lsof isn't installed on this machine: %s", str(e))
sleep(1)
if waitStartDaemon(self, self.timeout - 1):
if self.last_test_error:
logger.debug(self.last_test_error)
break
def getConnection(self):
return self.connection
def start(self, init=True):
"""Start Instance."""
self.path_user_installation = join(self.path_run_dir, \
......@@ -154,7 +148,7 @@ class OpenOffice(Application):
'--nodefault',
'--norestore',
'--nofirststartwizard',
'--accept=socket,host=%s,port=%d;urp;' % (self.hostname, self.port),
'--accept=%s;urp;' % self.getConnection(),
'-env:UserInstallation=file://%s' % self.path_user_installation,
'--language=%s' % self.default_language,
]
......@@ -172,8 +166,6 @@ class OpenOffice(Application):
"""Stop the instance by pid. By the default
the signal is 15."""
Application.stop(self)
if socketStatus(self.hostname, self.port):
self._releaseOpenOfficePort()
self._cleanRequest()
def isLocked(self):
......
......@@ -83,13 +83,11 @@ class Handler(object):
def _getCommand(self, *args, **kw):
"""Transforms all parameters passed in a command"""
hostname, port = openoffice.getAddress()
kw['hostname'] = hostname
kw['port'] = port
python = path.join(self.office_binary_path, "python")
command_list = [path.exists(python) and python or "python",
pkg_resources.resource_filename(__name__,
path.join("helper", "unoconverter.py")),
"--connection=%s" % openoffice.getConnection(),
"--uno_path=%s" % self.uno_path,
"--office_binary_path=%s" % self.office_binary_path,
'--document_url=%s' % self.document.getUrl()]
......@@ -146,7 +144,6 @@ class Handler(object):
logger.debug("stop convert first")
if not stdout and stderr:
first_error = stderr
logger.error(stderr)
self.document.restoreOriginal()
openoffice.restart()
kw['document_url'] = self.document.getUrl()
......@@ -316,6 +313,5 @@ def bootstrapHandler(configuration_dict):
# Load all filters
openoffice.acquire()
mimemapper.loadFilterList(application_hostname,
openoffice_port, **kw)
mimemapper.loadFilterList(openoffice.getConnection(), **kw)
openoffice.release()
......@@ -2,7 +2,7 @@ import signal
import sys
import os
def getServiceManager(host, port, uno_path, office_binary_path):
def getServiceManager(connection, uno_path, office_binary_path):
"""Get the ServiceManager from the running OpenOffice.org.
"""
# Add in sys.path the path of pyuno
......@@ -21,7 +21,7 @@ def getServiceManager(host, port, uno_path, office_binary_path):
uno_context)
# Connect to the running OpenOffice.org and get its
# context.
uno_connection = resolver.resolve("uno:socket,host=%s,port=%s,tcpNoDelay=1;urp;StarOffice.ComponentContext" % (host, port))
uno_connection = resolver.resolve("uno:%s;urp;StarOffice.ComponentContext" % connection)
# Get the ServiceManager object
return uno_connection.ServiceManager
......
......@@ -9,10 +9,10 @@ except ImportError:
import simplejson as json
def test_openoffice(hostname, port, uno_path, office_binary_path):
def test_openoffice(connection, uno_path, office_binary_path):
import pyuno
try:
helper_util.getServiceManager(hostname, port, uno_path, office_binary_path)
helper_util.getServiceManager(connection, uno_path, office_binary_path)
return True
except pyuno.getClass("com.sun.star.connection.NoConnectException"):
return False
......@@ -21,18 +21,16 @@ def test_openoffice(hostname, port, uno_path, office_binary_path):
def main():
try:
opt_list, arg_list = getopt(sys.argv[1:], "",
["port=", "hostname=", "uno_path=",
["connection=", "uno_path=",
"office_binary_path="])
except GetoptError as e:
sys.stderr.write("%s \nUse --port and --hostname" % e)
sys.stderr.write("%s \nUse --connection" % e)
sys.exit(2)
port = hostname = uno_path = office_binary_path = None
connection = uno_path = office_binary_path = None
for opt, arg in opt_list:
if opt == "--port":
port = arg
elif opt == "--hostname":
hostname = arg
if opt == "--connection":
connection = arg
elif opt == "--uno_path":
uno_path = arg
if uno_path not in sys.path:
......@@ -40,7 +38,7 @@ def main():
elif opt == "--office_binary_path":
office_binary_path = arg
output = json.dumps(test_openoffice(hostname, port,
output = json.dumps(test_openoffice(connection,
uno_path, office_binary_path))
sys.stdout.write(output)
......
......@@ -298,7 +298,7 @@ def main():
opt_list, arg_list = getopt(sys.argv[1:], "h", ["help", "test",
"convert", "getmetadata", "setmetadata",
"uno_path=", "office_binary_path=",
"hostname=", "port=", "source_format=",
"connection=", "source_format=",
"document_url=", "destination_format=",
"mimemapper=", "metadata=", "refresh=",
"unomimemapper_bin="])
......@@ -313,15 +313,13 @@ def main():
import json
except ImportError:
import simplejson as json
hostname = port = document_url = office_binary_path = uno_path =\
connection = document_url = office_binary_path = uno_path =\
destination_format = source_format = refresh = metadata = mimemapper = None
for opt, arg in iter(opt_list):
if opt in ('-h', '--help'):
help()
elif opt == '--hostname':
hostname = arg
elif opt == '--port':
port = arg
elif opt == '--connection':
connection = arg
elif opt == '--document_url':
document_url = arg
elif opt == '--office_binary_path':
......@@ -340,7 +338,7 @@ def main():
elif opt == '--mimemapper':
mimemapper = json.loads(arg)
service_manager = helper_util.getServiceManager(hostname, port,
service_manager = helper_util.getServiceManager(connection,
uno_path, office_binary_path)
if '--getmetadata' in param_list and '--convert' in param_list:
with UnoConverter(service_manager, document_url, source_format, refresh) as unoconverter:
......
......@@ -66,9 +66,9 @@ Options:
class UnoMimemapper(object):
""" """
def __init__(self, hostname, port, uno_path=None, office_binary_path=None):
def __init__(self, connection, uno_path=None, office_binary_path=None):
""" Receives hostname and port from openoffice and create a service manager"""
self.service_manager = helper_util.getServiceManager(hostname, port,
self.service_manager = helper_util.getServiceManager(connection,
uno_path,
office_binary_path)
......@@ -111,7 +111,7 @@ def main():
try:
opt_list, arg_list = getopt(sys.argv[1:], "h", ["help",
"uno_path=", "office_binary_path=",
"hostname=", "port="])
"connection="])
except GetoptError as msg:
msg = msg.msg + "\nUse --help or -h\n"
sys.stderr.write(msg)
......@@ -120,7 +120,7 @@ def main():
if not opt_list:
help()
port = hostname = uno_path = office_binary_path = None
connection = uno_path = office_binary_path = None
for opt, arg in opt_list:
if opt in ("-h", "--help"):
help()
......@@ -128,12 +128,10 @@ def main():
uno_path = arg
elif opt == "--office_binary_path":
office_binary_path = arg
elif opt == '--hostname':
hostname = arg
elif opt == "--port":
port = arg
elif opt == '--connection':
connection = arg
mimemapper = UnoMimemapper(hostname, port, uno_path, office_binary_path)
mimemapper = UnoMimemapper(connection, uno_path, office_binary_path)
filter_dict = mimemapper.getFilterDict()
type_dict = mimemapper.getTypeDict()
......
......@@ -88,7 +88,7 @@ class MimeMapper(object):
"""Verify if filters were loaded"""
return self._loaded
def loadFilterList(self, hostname, port, **kw):
def loadFilterList(self, connection, **kw):
"""Load all filters of openoffice.
Keyword arguments:
hostname -- host of OpenOffice
......@@ -122,8 +122,7 @@ class MimeMapper(object):
path.join("helper", "unomimemapper.py")),
"--uno_path=%s" % uno_path,
"--office_binary_path=%s" % office_binary_path,
"--hostname=%s" % hostname,
"--port=%s" % port]
"--connection=%s" % connection]
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True)
stdout, stderr = process.communicate()
......
......@@ -150,9 +150,7 @@ class TestMimeMapper(HandlerTestCase):
"""Mimemapper is created and load uno path."""
self.mimemapper = MimeMapper()
openoffice.acquire()
hostname, port = openoffice.getAddress()
self.mimemapper.loadFilterList(hostname,
port,
self.mimemapper.loadFilterList(openoffice.getConnection(),
python_path=self.python_path)
openoffice.release()
......
......@@ -32,7 +32,6 @@ from cloudooo.handler.ooo.application.openoffice import openoffice
from cloudooo.handler.ooo.monitor.memory import MonitorMemory
from psutil import Process
from types import IntType
from cloudooo.tests.handlerTestCase import make_suite
OPENOFFICE = True
......
......@@ -47,7 +47,7 @@ class TestUnoConverter(HandlerTestCase):
def afterSetUp(self):
""" """
openoffice.acquire()
self.hostname, self.port = openoffice.getAddress()
self.connection = openoffice.getConnection()
data = open("data/test.odt", 'r').read()
self.document = FileSystemDocument(self.tmp_url, data, 'odt')
......@@ -69,8 +69,7 @@ class TestUnoConverter(HandlerTestCase):
"--convert",
"--uno_path=%s" % self.uno_path,
"--office_binary_path=%s" % self.office_binary_path,
"--hostname=%s" % self.hostname,
"--port=%s" % self.port,
"--connection=%s" % self.connection,
"--document_url=%s" % self.document.getUrl(),
"--destination_format=%s" % "doc",
"--source_format=%s" % "odt",
......
......@@ -54,36 +54,13 @@ class TestUnoMimeMapper(HandlerTestCase):
def testCreateLocalAttributes(self):
"""Test if filters returns correctly the filters and types in dict"""
hostname, host = openoffice.getAddress()
python = path.join(self.office_binary_path, "python")
command = [path.exists(python) and python or "python",
pkg_resources.resource_filename(self.package_namespace,
"/helper/unomimemapper.py"),
"--uno_path=%s" % self.uno_path,
"--office_binary_path=%s" % self.office_binary_path,
"--hostname=%s" % self.hostname,
"--port=%s" % self.openoffice_port]
process = Popen(command, stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
self.assertEquals(process.returncode, -15)
self.assertEquals(stderr, '')
filter_dict, type_dict = json.loads(stdout)
self.assertTrue('filter_dict' in locals())
self.assertTrue('type_dict' in locals())
self.assertNotEquals(filter_dict.get('writer8'), None)
self.assertEquals(type_dict.get('writer8').get('Name'), 'writer8')
self.assertNotEquals(filter_dict.get('writer8'), None)
self.assertEquals(type_dict.get('writer8').get('PreferredFilter'), 'writer8')
self.assertEquals(stderr, '')
def testCallUnoMimemapperOnlyHostNameAndPort(self):
""" Test call unomimemapper without uno_path and office_binary_path"""
hostname, host = openoffice.getAddress()
command = [path.join(self.office_binary_path, "python"),
pkg_resources.resource_filename(self.package_namespace,
"/helper/unomimemapper.py"),
"--hostname=%s" % self.hostname,
"--port=%s" % self.openoffice_port]
"--connection=%s" % openoffice.getConnection()]
process = Popen(command, stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
self.assertEquals(process.returncode, -3)
......@@ -99,8 +76,7 @@ class TestUnoMimeMapper(HandlerTestCase):
def testWithoutOpenOffice(self):
"""Test when the openoffice is stopped"""
error_msg = "couldn\'t connect to socket (Success)\n"
hostname, host = openoffice.getAddress()
error_msg = "helper_util.com.sun.star.connection.NoConnectException: Connector : couldn't connect to "
openoffice.stop()
python = path.join(self.office_binary_path, "python")
command = [path.exists(python) and python or "python",
......@@ -108,13 +84,12 @@ class TestUnoMimeMapper(HandlerTestCase):
"/helper/unomimemapper.py"),
"--uno_path=%s" % self.uno_path,
"--office_binary_path=%s" % self.office_binary_path,
"--hostname=%s" % self.hostname,
"--port=%s" % self.openoffice_port]
"--connection=%s" % openoffice.getConnection()]
process = Popen(command, stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
self.assertEquals(process.returncode, -3)
self.assertEquals(stdout, '')
self.assertTrue(stderr.endswith(error_msg), stderr)
self.assertTrue(error_msg in stderr, stderr)
openoffice.start()
......@@ -26,8 +26,6 @@
#
##############################################################################
from socket import socket, error
from errno import EADDRINUSE
from time import sleep
from os import remove
from shutil import rmtree
......@@ -41,19 +39,6 @@ def removeDirectory(path):
except OSError, msg:
logger.error(msg)
def socketStatus(hostname, port):
"""Verify if the address is busy."""
try:
socket().bind((hostname, port),)
# False if the is free
return False
except error, (num, err):
if num == EADDRINUSE:
# True if the isn't free
return True
def waitStartDaemon(daemon, attempts):
"""Wait a certain time to start the daemon."""
for num in range(attempts):
......
......@@ -58,7 +58,7 @@ def startFakeEnvironment(start_openoffice=True, conf_path=None):
uno_path = config.get("app:main", "uno_path")
working_path = config.get("app:main", "working_path")
hostname = config.get("server:main", "host")
openoffice_port = int(config.get("app:main", "openoffice_port"))
openoffice_port = int(config.get("app:main", "openoffice_port")) + 1
office_binary_path = config.get("app:main", "office_binary_path")
environment_dict = {}
for item in config.options("app:main"):
......@@ -93,11 +93,10 @@ def startFakeEnvironment(start_openoffice=True, conf_path=None):
environment_dict)
openoffice.start()
openoffice.acquire()
hostname, port = openoffice.getAddress()
kw = dict(uno_path=config.get("app:main", "uno_path"),
office_binary_path=config.get("app:main", "office_binary_path"))
if not mimemapper.isLoaded():
mimemapper.loadFilterList(hostname, port, **kw)
mimemapper.loadFilterList(openoffice.getConnection(), **kw)
openoffice.release()
return openoffice
......@@ -110,8 +109,9 @@ def stopFakeEnvironment(stop_openoffice=True):
if 1:
from cloudooo.handler.ooo.application.openoffice import OpenOffice
from cloudooo.handler.ooo.util import waitStartDaemon, waitStopDaemon
from cloudooo.handler.ooo.util import waitStartDaemon
from subprocess import Popen, PIPE
from time import sleep
# patch OpenOffice._startProcess not to put bogus output to stderr,
# that prevents detecting the end of unit test.
......@@ -119,14 +119,16 @@ if 1:
"""Start OpenOffice.org process"""
for i in range(5):
self.stop()
waitStopDaemon(self, self.timeout)
self.process = Popen(command, stderr=PIPE,
close_fds=True,
env=env)
if not waitStartDaemon(self, self.timeout):
sleep(1)
if self.process.poll() is not None:
# process already terminated so
# rerun
continue
if self._testOpenOffice(self.hostname, self.port):
return
if waitStartDaemon(self, self.timeout - 1):
break
OpenOffice._startProcess = _startProcess
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment