diff --git a/.gitattributes b/.gitattributes
index 7f2e3c6ceedbecfea7dec07e74461dd98857c169..23413022bb48edeb4527613aada83afc50740858 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -4488,8 +4488,14 @@ MAC/Navigator2/scripts/readStationConfigs.ctl -text
 MAC/Navigator2/scripts/readStationConnections.ctl -text
 MAC/Navigator2/scripts/setSumAlerts.ctl -text
 MAC/Navigator2/scripts/transferMPs.ctl -text
+MAC/Services/src/ObservationControl2.py -text
+MAC/Services/src/config.py -text
+MAC/Services/src/observationcontrol2 -text
+MAC/Services/src/observationcontrol2.ini -text
 MAC/Services/src/pipelinecontrol -text
 MAC/Services/src/pipelinecontrol.ini -text
+MAC/Services/test/tObservationControl2.py -text
+MAC/Services/test/tObservationControl2.sh -text
 MAC/Services/test/tPipelineControl.sh eol=lf
 MAC/Test/APL/PVSSproject/colorDB/Lofar[!!-~]colors -text svneol=native#application/octet-stream
 MAC/Test/APL/PVSSproject/colorDB/colorDB_de -text svneol=native#application/octet-stream
diff --git a/MAC/Services/src/CMakeLists.txt b/MAC/Services/src/CMakeLists.txt
index 692b7b5ce4ab157ee88c3d60c29c3c350723c0ab..665e7d6dbc5f1f87ab3718f73b795d833828bf9f 100644
--- a/MAC/Services/src/CMakeLists.txt
+++ b/MAC/Services/src/CMakeLists.txt
@@ -2,14 +2,18 @@
 
 lofar_add_bin_scripts(
   pipelinecontrol
+  observationcontrol2
 )
 
 python_install(
   PipelineControl.py
+  ObservationControl2.py
+  config.py
   DESTINATION lofar/mac
 )
 
 # supervisord config files
 install(FILES
   pipelinecontrol.ini
+  observationcontrol2.ini
   DESTINATION etc/supervisord.d)
diff --git a/MAC/Services/src/ObservationControl2.py b/MAC/Services/src/ObservationControl2.py
new file mode 100644
index 0000000000000000000000000000000000000000..82d4be7867eb849ff6de1c37da60dd38da95044e
--- /dev/null
+++ b/MAC/Services/src/ObservationControl2.py
@@ -0,0 +1,117 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2016
+# ASTRON (Netherlands Institute for Radio Astronomy)
+# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+#
+# This file is part of the LOFAR software suite.
+# The LOFAR software suite is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# The LOFAR software suite is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.
+import os
+import logging
+from fabric import tasks
+from optparse import OptionParser
+
+from fabric.api import env, run
+from lofar.messaging import Service
+from lofar.messaging import setQpidLogLevel
+from lofar.common.util import waitForInterrupt
+from lofar.messaging.Service import MessageHandlerInterface
+from lofar.mac.config import DEFAULT_OBSERVATION_CONTROL_BUS_NAME, DEFAULT_OBSERVATION_CONTROL_SERVICE_NAME
+
+logger = logging.getLogger(__name__)
+
+
+class ObservationControlHandler(MessageHandlerInterface):
+    def __init__(self, **kwargs):
+        super(ObservationControlHandler, self).__init__(**kwargs)
+
+        self.service2MethodMap = {
+            'AbortObservation': self.abort_observation
+        }
+
+        env.hosts = ["localhost"]
+
+        if os.environ.has_key("LOFARENV"):
+            lofar_environment = os.environ['LOFARENV']
+
+            if lofar_environment == "PRODUCTION":
+                env.hosts = ["mcu001.control.lofar"]
+            elif lofar_environment == "TEST":
+                env.hosts = ["mcu099.control.lofar"]
+
+    def abort_observation_task(self, sas_id):
+        logger.info("trying to abort ObservationControl for SAS ID: %s", sas_id)
+
+        killed = False
+
+        pid_line = run('pidof ObservationControl')
+        pids = pid_line.split(' ')
+
+        for pid in pids:
+            pid_sas_id = run("ps -p %s --no-heading -o command | awk -F[{}] '{ print $2; }'" % pid)
+            if pid_sas_id == sas_id:
+                logger.info("Killing ObservationControl with PID: %s for SAS ID: %s", pid, sas_id)
+                run('kill -SIGINT %s' % pid)
+                killed = True
+
+        return killed
+
+    def abort_observation(self, sas_id):
+        result = tasks.execute(self.abort_observation_task, sas_id)
+        aborted = True in result.values()
+        return {'aborted': aborted}
+
+    def handle_message(self, msg):
+        pass
+
+
+def create_service(bus_name=DEFAULT_OBSERVATION_CONTROL_BUS_NAME, service_name=DEFAULT_OBSERVATION_CONTROL_SERVICE_NAME,
+                   broker=None, verbose=False):
+    return Service(service_name,
+                   ObservationControlHandler,
+                   busname=bus_name,
+                   broker=broker,
+                   use_service_methods=True,
+                   numthreads=4,
+                   handler_args={},
+                   verbose=verbose)
+
+
+def main():
+    # make sure we run in UTC timezone
+    import os
+    os.environ['TZ'] = 'UTC'
+
+    # Check the invocation arguments
+    parser = OptionParser("%prog [options]",
+                          description='runs the observationcontrol service')
+    parser.add_option('-q', '--broker', dest='broker', type='string', default=None, help='Address of the qpid broker, default: localhost')
+    parser.add_option("-b", "--busname", dest="busname", type="string", default=DEFAULT_OBSERVATION_CONTROL_BUS_NAME, help="Name of the bus exchange on the qpid broker, default: %s" % DEFAULT_OBSERVATION_CONTROL_BUS_NAME)
+    parser.add_option("-s", "--servicename", dest="servicename", type="string", default=DEFAULT_OBSERVATION_CONTROL_SERVICE_NAME, help="Name for this service, default: %s" % DEFAULT_OBSERVATION_CONTROL_SERVICE_NAME)
+    parser.add_option('-V', '--verbose', dest='verbose', action='store_true', help='verbose logging')
+    (options, args) = parser.parse_args()
+
+    setQpidLogLevel(logging.INFO)
+    logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
+                        level=logging.DEBUG if options.verbose else logging.INFO)
+
+    with create_service(bus_name=options.busname,
+                        service_name=options.servicename,
+                        broker=options.broker,
+                        verbose=options.verbose):
+        waitForInterrupt()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/MAC/Services/src/config.py b/MAC/Services/src/config.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a72a7e412a9de1436828f4026e5cb36c3947865
--- /dev/null
+++ b/MAC/Services/src/config.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2016
+# ASTRON (Netherlands Institute for Radio Astronomy)
+# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+#
+# This file is part of the LOFAR software suite.
+# The LOFAR software suite is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# The LOFAR software suite is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.
+
+from lofar.messaging import adaptNameToEnvironment
+
+DEFAULT_OBSERVATION_CONTROL_BUS_NAME = adaptNameToEnvironment('lofar.mac.command')
+DEFAULT_OBSERVATION_CONTROL_SERVICE_NAME = 'ObservationControl2'
diff --git a/MAC/Services/src/observationcontrol2 b/MAC/Services/src/observationcontrol2
new file mode 100644
index 0000000000000000000000000000000000000000..7c08d7da4f548b53e289169f35a6a875f89c0ff7
--- /dev/null
+++ b/MAC/Services/src/observationcontrol2
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2016
+# ASTRON (Netherlands Institute for Radio Astronomy)
+# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+#
+# This file is part of the LOFAR software suite.
+# The LOFAR software suite is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# The LOFAR software suite is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.
+
+'''
+runs the ObservationControl service
+'''
+from lofar.mac import ObservationControl2
+
+if __name__ == '__main__':
+    ObservationControl2.main()
diff --git a/MAC/Services/src/observationcontrol2.ini b/MAC/Services/src/observationcontrol2.ini
new file mode 100644
index 0000000000000000000000000000000000000000..ba538bf84860db403624c00d2fc4891b9b6f3df5
--- /dev/null
+++ b/MAC/Services/src/observationcontrol2.ini
@@ -0,0 +1,8 @@
+[program:observationcontrol2]
+command=/bin/bash -c 'source $LOFARROOT/lofarinit.sh;exec observationcontrol2'
+user=lofarsys
+stopsignal=INT ; KeyboardInterrupt
+stopasgroup=true ; bash does not propagate signals
+stdout_logfile=%(program_name)s.log
+redirect_stderr=true
+stderr_logfile=NONE
diff --git a/MAC/Services/test/tObservationControl2.py b/MAC/Services/test/tObservationControl2.py
new file mode 100644
index 0000000000000000000000000000000000000000..85e8892b3e18fc1cbd26bca508ee90af7f1c5276
--- /dev/null
+++ b/MAC/Services/test/tObservationControl2.py
@@ -0,0 +1,122 @@
+import unittest
+import mock
+import os
+
+from lofar.mac.ObservationControl2 import ObservationControlHandler
+
+
+class TestObservationControlHandler(unittest.TestCase):
+    pid1 = "1000"
+    pid2 = "2000"
+
+    sas_id = "100"
+
+    test_host = "mcu099.control.lofar"
+    production_host = "mcu001.control.lofar"
+    local_host = "localhost"
+
+    def _run_side_effect(self, cmd):
+        if cmd.startswith("ps -p %s" % self.pid1):
+            return self.sas_id
+        elif cmd.startswith("ps -p %s" % self.pid2):
+            return self.sas_id + "10"
+        elif cmd.startswith("pidof"):
+            return "%s %s" % (self.pid1, self.pid2)
+        elif cmd.startswith("kill"):
+            return ""
+
+    def setUp(self):
+        fabric_run_pathcher = mock.patch('lofar.mac.ObservationControl2.run')
+        self.addCleanup(fabric_run_pathcher.stop)
+        self.fabric_run_mock = fabric_run_pathcher.start()
+
+        self.fabric_run_mock.side_effect = self._run_side_effect
+
+        fabric_tasks_pathcher = mock.patch('lofar.mac.ObservationControl2.tasks')
+        self.addCleanup(fabric_tasks_pathcher.stop)
+        self.fabric_tasks_mock = fabric_tasks_pathcher.start()
+
+        fabric_env_pathcher = mock.patch('lofar.mac.ObservationControl2.env')
+        self.addCleanup(fabric_env_pathcher.stop)
+        self.fabric_env_mock = fabric_env_pathcher.start()
+
+        logger_patcher = mock.patch('lofar.mac.ObservationControl2.logger')
+        self.addCleanup(logger_patcher.stop)
+        self.logger_mock = logger_patcher.start()
+
+        self.observation_control_handler = ObservationControlHandler()
+
+    def test_abort_observation_task_should_run_pidof_ObservationControl(self):
+        self.observation_control_handler.abort_observation_task(self.sas_id)
+
+        self.fabric_run_mock.assert_any_call('pidof ObservationControl')
+
+    def test_abort_observation_tasks_should_run_ps_to_find_sas_id_on_command(self):
+        self.observation_control_handler.abort_observation_task(self.sas_id)
+
+        self.fabric_run_mock.assert_any_call(
+            "ps -p %s --no-heading -o command | awk -F[{}] '{ print $2; }'" % self.pid1)
+        self.fabric_run_mock.assert_any_call(
+            "ps -p %s --no-heading -o command | awk -F[{}] '{ print $2; }'" % self.pid2)
+
+    def test_abort_observation_task_should_run_kill_when_sas_id_matches(self):
+        self.observation_control_handler.abort_observation_task(self.sas_id)
+
+        self.fabric_run_mock.assert_any_call('kill -SIGINT %s' % self.pid1)
+
+    @mock.patch.dict(os.environ, {'LOFARENV': 'TEST'})
+    def test_observation_control_should_select_test_host_if_lofar_environment_is_test(self):
+        ObservationControlHandler()
+
+        self.assertEqual(self.fabric_env_mock.hosts, [self.test_host])
+
+    @mock.patch.dict(os.environ, {'LOFARENV': 'PRODUCTION'})
+    def test_observation_control_should_select_production_host_if_lofar_environment_is_production(self):
+        ObservationControlHandler()
+
+        self.assertEqual(self.fabric_env_mock.hosts, [self.production_host])
+
+    def test_observation_control_should_select_local_host_if_no_lofar_environment_is_set(self):
+        ObservationControlHandler()
+
+        self.assertEqual(self.fabric_env_mock.hosts, [self.local_host])
+
+    def test_abort_observation_should_execute_abort_observation_task_on_localhost(self):
+        self.observation_control_handler.abort_observation(self.sas_id)
+
+        self.fabric_tasks_mock.execute.assert_any_call(self.observation_control_handler.abort_observation_task,
+                                                       self.sas_id)
+
+    def test_abort_observation_task_should_return_false_on_unknown_sas_id(self):
+        self.assertFalse(self.observation_control_handler.abort_observation_task("unknown"))
+
+    def test_abort_observation_task_should_return_true_on_known_sas_id(self):
+        self.assertTrue(self.observation_control_handler.abort_observation_task(self.sas_id))
+
+    def test_abort_observation_task_should_log_call(self):
+        self.observation_control_handler.abort_observation_task(self.sas_id)
+
+        self.logger_mock.info.assert_any_call("trying to abort ObservationControl for SAS ID: %s", self.sas_id)
+
+    def test_abort_observation_taks_should_log_the_kill(self):
+        self.observation_control_handler.abort_observation_task(self.sas_id)
+
+        self.logger_mock.info.assert_any_call(
+            "Killing ObservationControl with PID: %s for SAS ID: %s", self.pid1, self.sas_id)
+
+    def test_abort_observation_should_return_aborted_true_if_execute_returns_true(self):
+        self.fabric_tasks_mock.execute.return_value = {'localhost': True}
+
+        result = self.observation_control_handler.abort_observation(self.sas_id)
+
+        self.assertTrue(result['aborted'])
+
+    def test_abort_observation_should_return_aborted_false_if_execute_returns_false(self):
+        self.fabric_tasks_mock.execute.return_value = {'localhost': False}
+
+        result = self.observation_control_handler.abort_observation(self.sas_id)
+
+        self.assertFalse(result['aborted'])
+
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file
diff --git a/MAC/Services/test/tObservationControl2.sh b/MAC/Services/test/tObservationControl2.sh
new file mode 100644
index 0000000000000000000000000000000000000000..6634f8db752024d72592c6d3c690b367522ee263
--- /dev/null
+++ b/MAC/Services/test/tObservationControl2.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+./runctest.sh tObservationControl2
\ No newline at end of file