Devesh's changes to request router models and observer
diff --git a/planetstack/rr_observer/configurationPush.py b/planetstack/rr_observer/configurationPush.py
new file mode 100644
index 0000000..857de8b
--- /dev/null
+++ b/planetstack/rr_observer/configurationPush.py
@@ -0,0 +1,30 @@
+import ansible.playbook
+import ansible.constants as C
+import ansible.utils.template
+from ansible import errors
+from ansible import callbacks
+from ansible import utils
+from subprocess import call
+
+class ConfigurationPush:
+	def __init__(self):
+		pass
+
+	def config_push(self, service_name, user, playbook_name,hostfile):
+		'''stats = callbacks.AggregateStats()
+		playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
+		runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
+		pb = ansible.playbook.PlayBook(playbook="playbook/site.yml",
+					callbacks=playbook_cb,
+            				runner_callbacks=runner_cb,
+            				stats=stats
+					)
+		result = pb.run()
+		print result
+		'''
+
+		call("ansible-playbook --private-key=planetw "+playbook_name+" -i "+hostfile+" -u "+user+"  --extra-vars \"name="+service_name+"\"", shell=True)
+	
+
+if __name__ == "__main__":
+        main()
diff --git a/planetstack/rr_observer/deleters/servicemap_deleter.py b/planetstack/rr_observer/deleters/servicemap_deleter.py
new file mode 100644
index 0000000..b5d4509
--- /dev/null
+++ b/planetstack/rr_observer/deleters/servicemap_deleter.py
@@ -0,0 +1,41 @@
+import os
+import sys
+import traceback
+from requestrouter.models import ServiceMap
+from observer.deleter import Deleter
+from util.logger import Logger, logging
+
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+from rrlib import RequestRouterLibrary
+from configurationPush import ConfigurationPush
+import rrlib_config
+
+logger = Logger(level=logging.INFO)
+
+class ServiceMapDeleter(Deleter, RequestRouterLibrary, ConfigurationPush):
+        model='ServiceMap'
+
+        def __init__(self, **args):
+            Deleter.__init__(self, **args)
+            RequestRouterLibrary.__init__(self)
+            ConfigurationPush.__init__(self)
+
+
+        def call(self, pk, model_dict):
+          try:
+              servicemap = ServiceMap.objects.get(pk=pk)
+              service_uid = self.get_servicemap_uid(servicemap)
+              self.config_push(service_uid, rrlib_config.REDIR_USER, "/opt/planetstack/rr_observer/playbook/site_redir_delete.yml", "/etc/ansible/requestrouter/dnsredir/hosts")
+              self.config_push(service_uid, rrlib_config.DEMUX_USER, "/opt/planetstack/rr_observer/playbook/site_demux_delete.yml", "/etc/ansible/requestrouter/dnsdemux/hosts")
+              print "XXX delete ServiceMap %s", servicemap.name
+              return True
+          except Exception, e:
+              traceback.print_exc()
+              logger.exception("Failed to erase map '%s'" % map_name)
+              return False
+
+if __name__ == "__main__":
+  smap = ServiceMapDeleter()
+  smap.call( 6, {'name': 'Service23'} )
diff --git a/planetstack/rr_observer/model-deps b/planetstack/rr_observer/model-deps
new file mode 100644
index 0000000..36ef620
--- /dev/null
+++ b/planetstack/rr_observer/model-deps
@@ -0,0 +1,12 @@
+{
+    "ServiceMap": [
+        "Slice"
+    ], 
+    "Slice": [
+        "Site", 
+        "Service"
+    ], 
+    "User": [
+        "Site"
+    ]
+}
diff --git a/planetstack/rr_observer/playbook/roles/delete_demux/handlers/main.yml b/planetstack/rr_observer/playbook/roles/delete_demux/handlers/main.yml
new file mode 100644
index 0000000..a888468
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/delete_demux/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: restart dnsdemux
+  service: name=dnsdemux state=restarted
diff --git a/planetstack/rr_observer/playbook/roles/delete_demux/tasks/main.yml b/planetstack/rr_observer/playbook/roles/delete_demux/tasks/main.yml
new file mode 100644
index 0000000..417401a
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/delete_demux/tasks/main.yml
@@ -0,0 +1,5 @@
+---
+# This playbook contains plays to delete configuration files from dnsdemux slice
+- name: delete dnsdemux config files
+  file: path={{dst_dnsdemux_conf}}/{{name}}.conf state=absent
+  notify: restart dnsdemux
diff --git a/planetstack/rr_observer/playbook/roles/delete_demux/vars/main.yml b/planetstack/rr_observer/playbook/roles/delete_demux/vars/main.yml
new file mode 100644
index 0000000..b457050
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/delete_demux/vars/main.yml
@@ -0,0 +1,6 @@
+---
+# Variables listed here are applicable to all host groups
+
+src_dnsdemux: ../../../../temp_config/dnsdemux
+dst_dnsdemux_conf: /etc/dnsdemux/default/
+
diff --git a/planetstack/rr_observer/playbook/roles/delete_redir/handlers/main.yml b/planetstack/rr_observer/playbook/roles/delete_redir/handlers/main.yml
new file mode 100644
index 0000000..8aa497e
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/delete_redir/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: restart dnsredir
+  service: name=dnsredir state=restarted
diff --git a/planetstack/rr_observer/playbook/roles/delete_redir/tasks/main.yml b/planetstack/rr_observer/playbook/roles/delete_redir/tasks/main.yml
new file mode 100644
index 0000000..58833bb
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/delete_redir/tasks/main.yml
@@ -0,0 +1,13 @@
+---
+# This playbook contains plays to delete configuration files from dnsredir slice
+- name: delete  maps.d directory ( and deletes all intermeadiate directories )
+  #copy: src={{src_dnsredir}}/{{name}}.d dest={{dst_dnsredir_confdir}}
+  file: path={{dst_dnsredir_confdir}}/{{name}}.d/maps.d state=absent
+ 
+- name: delete config directory
+  file: path={{dst_dnsredir_confdir}}/{{name}}.d/ state=absent
+ 
+- name: copy dnsredir config file
+  file: path={{dst_dnsredir_conf}}/{{name}}.conf state=absent
+  notify: restart dnsredir
+
diff --git a/planetstack/rr_observer/playbook/roles/delete_redir/vars/main.yml b/planetstack/rr_observer/playbook/roles/delete_redir/vars/main.yml
new file mode 100644
index 0000000..dc79d35
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/delete_redir/vars/main.yml
@@ -0,0 +1,6 @@
+---
+# Variables listed here are applicable to all host groups
+
+src_dnsredir: ../../../../temp_config/dnsredir
+dst_dnsredir_conf: /etc/dnsredir/conf.d/
+dst_dnsredir_confdir: /etc/dnsredir
diff --git a/planetstack/rr_observer/playbook/roles/demux/handlers/main.yml b/planetstack/rr_observer/playbook/roles/demux/handlers/main.yml
new file mode 100644
index 0000000..a888468
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/demux/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: restart dnsdemux
+  service: name=dnsdemux state=restarted
diff --git a/planetstack/rr_observer/playbook/roles/demux/tasks/main.yml b/planetstack/rr_observer/playbook/roles/demux/tasks/main.yml
new file mode 100644
index 0000000..0339aed
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/demux/tasks/main.yml
@@ -0,0 +1,9 @@
+---
+# This playbook contains plays to copy configurations to destination
+- name: copy dnsdemux config files
+  copy: src={{src_dnsdemux}}/{{name}}.conf dest={{dst_dnsdemux_conf}}/{{name}}.conf
+  notify: restart dnsdemux
+
+#- name: Start the dnsdemux service
+  #service: name=dnsdemux state=started enabled=true
+
diff --git a/planetstack/rr_observer/playbook/roles/demux/vars/main.yml b/planetstack/rr_observer/playbook/roles/demux/vars/main.yml
new file mode 100644
index 0000000..b457050
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/demux/vars/main.yml
@@ -0,0 +1,6 @@
+---
+# Variables listed here are applicable to all host groups
+
+src_dnsdemux: ../../../../temp_config/dnsdemux
+dst_dnsdemux_conf: /etc/dnsdemux/default/
+
diff --git a/planetstack/rr_observer/playbook/roles/redir/handlers/main.yml b/planetstack/rr_observer/playbook/roles/redir/handlers/main.yml
new file mode 100644
index 0000000..8aa497e
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/redir/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: restart dnsredir
+  service: name=dnsredir state=restarted
diff --git a/planetstack/rr_observer/playbook/roles/redir/tasks/main.yml b/planetstack/rr_observer/playbook/roles/redir/tasks/main.yml
new file mode 100644
index 0000000..e390ed9
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/redir/tasks/main.yml
@@ -0,0 +1,19 @@
+---
+# This playbook contains plays to copy configurations to destination
+- name: create  maps.d directory ( and creates all intermeadiate directories )
+  #copy: src={{src_dnsredir}}/{{name}}.d dest={{dst_dnsredir_confdir}}
+  file: src={{src_dnsredir}}/{{name}}.d/maps.d dest={{dst_dnsredir_confdir}}/{{name}}.d/maps.d state=directory
+ 
+- name: copy map.conf
+  copy: src={{src_dnsredir}}/{{name}}.d/maps.d/map.conf dest={{dst_dnsredir_confdir}}/{{name}}.d/maps.d/map.conf
+ 
+- name: copy codeen_nodes.conf
+  copy: src={{src_dnsredir}}/{{name}}.d/codeen_nodes.conf dest={{dst_dnsredir_confdir}}/{{name}}.d/codeen_nodes.conf
+  
+- name: copy node-to-ip.txt
+  copy: src={{src_dnsredir}}/{{name}}.d/node-to-ip.txt dest={{dst_dnsredir_confdir}}/{{name}}.d/node-to-ip.txt
+
+- name: copy dnsredir config file
+  copy: src={{src_dnsredir}}/{{name}}.conf dest={{dst_dnsredir_conf}}/{{name}}.conf
+  notify: restart dnsredir
+
diff --git a/planetstack/rr_observer/playbook/roles/redir/vars/main.yml b/planetstack/rr_observer/playbook/roles/redir/vars/main.yml
new file mode 100644
index 0000000..dc79d35
--- /dev/null
+++ b/planetstack/rr_observer/playbook/roles/redir/vars/main.yml
@@ -0,0 +1,6 @@
+---
+# Variables listed here are applicable to all host groups
+
+src_dnsredir: ../../../../temp_config/dnsredir
+dst_dnsredir_conf: /etc/dnsredir/conf.d/
+dst_dnsredir_confdir: /etc/dnsredir
diff --git a/planetstack/rr_observer/playbook/site_demux.yml b/planetstack/rr_observer/playbook/site_demux.yml
new file mode 100644
index 0000000..b5261dc
--- /dev/null
+++ b/planetstack/rr_observer/playbook/site_demux.yml
@@ -0,0 +1,9 @@
+---
+# This playbook copies the dnsdemux configuration files from temp directory.
+
+- name: copies the configuration files from temp directory
+  hosts: all
+  #remote_user: {{r_user}}
+
+  roles:
+    - demux
diff --git a/planetstack/rr_observer/playbook/site_demux_delete.yml b/planetstack/rr_observer/playbook/site_demux_delete.yml
new file mode 100644
index 0000000..49a7c87
--- /dev/null
+++ b/planetstack/rr_observer/playbook/site_demux_delete.yml
@@ -0,0 +1,9 @@
+---
+# This playbook deletes the dnsdemux configuration files from request router instances
+
+- name: deletes the configuration files from request router instances
+  hosts: all
+  #remote_user: {{r_user}}
+
+  roles:
+    - delete_demux
diff --git a/planetstack/rr_observer/playbook/site_redir.yml b/planetstack/rr_observer/playbook/site_redir.yml
new file mode 100644
index 0000000..50a7284
--- /dev/null
+++ b/planetstack/rr_observer/playbook/site_redir.yml
@@ -0,0 +1,9 @@
+---
+# This playbook copies the dnsredir configuration files from temp directory.
+
+- name: copies the configuration files from temp directory
+  hosts: all
+  #remote_user: {{r_user}}
+
+  roles:
+    - redir
diff --git a/planetstack/rr_observer/playbook/site_redir_delete.yml b/planetstack/rr_observer/playbook/site_redir_delete.yml
new file mode 100644
index 0000000..9a8611d
--- /dev/null
+++ b/planetstack/rr_observer/playbook/site_redir_delete.yml
@@ -0,0 +1,9 @@
+---
+# This playbook deletes the dnsredir configuration files from request router instances
+
+- name: deletes the configuration files from request router instances
+  hosts: all
+  #remote_user: {{r_user}}
+
+  roles:
+    - delete_redir
diff --git a/planetstack/rr_observer/rr_observer_config b/planetstack/rr_observer/rr_observer_config
new file mode 100644
index 0000000..1fb52d0
--- /dev/null
+++ b/planetstack/rr_observer/rr_observer_config
@@ -0,0 +1,36 @@
+
+[plc]
+name=plc
+#deployment=VICCI
+deployment=VINI
+
+[db]
+name=planetstack
+user=plstackuser
+#password=2uMDYtJK
+password=1HL07C0E
+host=localhost
+port=5432
+
+[api]
+host=128.112.171.237
+port=8000
+ssl_key=None
+ssl_cert=None
+ca_ssl_cert=None
+ratelimit_enabled=0
+omf_enabled=0
+mail_support_address=support@localhost
+nova_enabled=True
+
+[observer]
+dependency_graph=/opt/planetstack/rr_observer/model-deps
+steps_dir=/opt/planetstack/rr_observer/steps
+deleters_dir=/opt/planetstack/rr_observer/deleters
+log_file=console
+#/var/log/hpc.log
+driver=None
+
+#[feefie]
+#client_id='vicci_dev_central'
+#user_id='pl'
diff --git a/planetstack/rr_observer/rrlib.py b/planetstack/rr_observer/rrlib.py
new file mode 100644
index 0000000..10a5171
--- /dev/null
+++ b/planetstack/rr_observer/rrlib.py
@@ -0,0 +1,203 @@
+import os
+import base64
+import string
+import sys
+import socket
+from sets import Set
+if __name__ == '__main__':
+    sys.path.append("/opt/planetstack")
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
+
+from planetstack.config import Config
+from core.models import Service
+from requestrouter.models import RequestRouterService, ServiceMap
+from util.logger import Logger, logging
+import rrlib_config
+
+logger = Logger(level=logging.INFO)
+
+'''
+Conventions:
+1) All dnsredir backend will listen at port 9000+ servicemap.pk ( where pk is the primary key generated in django model)
+'''
+
+class RequestRouterLibrary:
+
+    def __init__(self):
+        pass
+    
+    def gen_slice_info(self, service=None):   
+        """generates sliver information from slice of request router
+        """
+
+        if (service is None ):
+            service = RequestRouterService.objects.get()
+
+        mapping = {}
+        #static mapping for demo purpose 
+        #mapping["node47.princeton.vicci.org"] = "128.112.171.112"
+        mapping["node48.princeton.vicci.org"] = "128.112.171.114"
+    
+        '''for slice in service.service.all():
+            name = slice.name
+            for sliver in slice.slivers.all():
+                mapping[sliver.name] = str(sliver.ip)
+        '''
+        return mapping
+
+    def gen_servicemap_slice_info(self, servicemap):
+        """generates sliver information from slice of servicemap
+        """
+
+        wzone = Set(['arizona', 'stanford', 'on.lab', 'housten']) # zone=1 in cooden.conf
+        ezone = Set(['princeton', 'atlanta', 'new york', 'georgia tech']) # zone=2 in coodeen.conf
+
+        mapping_zone = {}
+        mapping_ip = {}
+        slice = servicemap.slice
+        name = slice.name
+        for sliver in slice.slivers.all():
+            mapping_ip[sliver.node.name] = socket.gethostbyname(sliver.node.name)
+            #print "sliver name "+sliver.name+str(sliver.ip)+"\n"
+            site = sliver.node.site.name
+            if(site.lower() in wzone):
+                mapping_zone[sliver.node.name] = str(1)
+            else:
+                mapping_zone[sliver.node.name] = str(2)
+
+        return mapping_ip, mapping_zone
+
+
+
+    def gen_slice_file(self, service):
+        """ generates host file for the slice information
+            to be used by ansible to push configuration files
+        """
+
+        mapping = self.gen_slice_info(service)
+
+        fn = "/etc/ansible/requestrouter/dnsredir/hosts"
+        f = open(fn, "w")
+        for (k,v) in mapping.items():
+            f.write("%s\n" % k)
+
+        fn = "/etc/ansible/requestrouter/dnsdemux/hosts"
+        f = open(fn, "w")
+        for (k,v) in mapping.items():
+            f.write("%s\n" % k)
+
+
+    def get_servicemap_uid(self, servicemap):
+        seq = ("service_", str(servicemap.pk));
+        return "".join(seq)
+
+    def get_service_port(self, servicemap):
+                return str(9000+servicemap.pk)
+
+    def gen_dnsredir_serviceconf(self, servicemap):
+        objname = self.get_servicemap_uid(servicemap)
+    
+        rr_mapping = self.gen_slice_info(None)
+    
+        #generate dnsredir.conf file parameters to be used in static file.
+        mapping = {}
+        mapping["port_listen"] = self.get_service_port(servicemap)
+        mapping["configdir"] = rrlib_config.DNSREDIR_CONFIGDIR_PREFIX+objname+".d/"
+        mapping["logdir"] = rrlib_config.DNSREDIR_LOGDIR_PREFIX+objname+".d"
+        mapping["pidfile"] = rrlib_config.DNSREDIR_PIDFILE_PREFIX+objname+".pid"
+        mapping["domain_name"] = servicemap.prefix      
+        mapping["heartbeat_port"] = rrlib_config.HEARTBEAT_PORT
+
+        #generate dnsredir.conf file 
+
+        fn = "./temp_config/dnsredir/"+objname+".conf"
+        f = open(fn, "w")
+        for (k,v) in rr_mapping.items():
+                        f.write(mapping["domain_name"]+". NS "+k+". "+v+" 3600 \n" % mapping)
+
+
+        f.write("""
+Default_TTL 30
+
+Port %(port_listen)s
+
+ConfigDir %(configdir)s
+
+MapsDir maps.d
+
+HTTPPort %(heartbeat_port)d
+
+PidFile %(pidfile)s
+
+HttpRequestPort 8081
+
+""" % mapping)
+
+        #generate configdirectory
+        
+        os.mkdir("./temp_config/dnsredir/"+objname+".d")
+        
+        #geenrate codeen_nodes.conf
+        mapping_ip, mapping_zone = self.gen_servicemap_slice_info(servicemap)
+
+        codeen_name = "./temp_config/dnsredir/"+objname+".d/codeen_nodes.conf"
+        f = open(codeen_name, "w")
+        for (k,v) in mapping_zone.items():
+            f.write(k+" zone="+v+" \n")
+
+        iptxt = "./temp_config/dnsredir/"+objname+".d/node-to-ip.txt"
+        f = open(iptxt, "w")
+        for (k,v) in mapping_ip.items():
+            f.write(k+" "+v+" \n")
+
+        #generate maps directory
+        os.mkdir("./temp_config/dnsredir/"+objname+".d/maps.d")
+
+        # redirection map
+        map = "./temp_config/dnsredir/"+objname+".d/maps.d/map.conf"
+        f = open(map, "w")
+		#hardcoded probable public IP masks from arizona and princeton region respectively
+        f.write("prefix "+servicemap.prefix+" \n")
+        f.write("map 150.135.211.252/32 zone 1 || zone 2 \n")
+        f.write("map 128.112.171.112/24 zone 2 || zone 1 \n")
+        f.write("map 0.0.0.0/0 zone 1 || zone 2 \n")
+
+
+    def gen_dnsdemux_serviceconf(self, servicemap):
+        '''
+        generates frontend service*.conf file for each of the service
+        It assumes that there is a dnsdemux frontend running on the RR istallation and will
+        just add a conf file for each service in /etc/dnsdemux/default
+        '''
+        objname = self.get_servicemap_uid(servicemap)
+        #generate dnsdemux.conf file parameters to be used in static file.
+       
+        port_listen = self.get_service_port(servicemap)
+        domain_name = servicemap.prefix  
+        #generate service specific .conf file
+
+        rr_mapping = self.gen_slice_info(None)
+
+        fn = "./temp_config/dnsdemux/"+objname+".conf"
+        f = open(fn, "w")
+
+        for (k,v) in rr_mapping.items():
+            f.write("Forward "+v+" "+port_listen+" 8081 "+domain_name+".\n")
+
+    
+    def teardown_temp_configfiles(self, objname):
+        if os.path.exists("./temp_config/dnsdemux/"+objname+".conf"):
+            os.remove("./temp_config/dnsdemux/"+objname+".conf")
+        if os.path.exists("./temp_config/dnsredir/"+objname+".d/maps.d/map.conf"):
+            os.remove("./temp_config/dnsredir/"+objname+".d/maps.d/map.conf")
+        if os.path.exists("./temp_config/dnsredir/"+objname+".d/maps.d"):
+            os.rmdir("./temp_config/dnsredir/"+objname+".d/maps.d")
+        if os.path.exists("./temp_config/dnsredir/"+objname+".d/node-to-ip.txt"):
+            os.remove("./temp_config/dnsredir/"+objname+".d/node-to-ip.txt")
+        if os.path.exists("./temp_config/dnsredir/"+objname+".d/codeen_nodes.conf"):
+            os.remove("./temp_config/dnsredir/"+objname+".d/codeen_nodes.conf")
+        if os.path.exists("./temp_config/dnsredir/"+objname+".d"):
+            os.rmdir("./temp_config/dnsredir/"+objname+".d")
+        if os.path.exists("./temp_config/dnsredir/"+objname+".conf"):
+            os.remove("./temp_config/dnsredir/"+objname+".conf")
+
diff --git a/planetstack/rr_observer/rrlib_config.py b/planetstack/rr_observer/rrlib_config.py
new file mode 100644
index 0000000..6d785e7
--- /dev/null
+++ b/planetstack/rr_observer/rrlib_config.py
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+
+DNSREDIR_CONFIGDIR_PREFIX = "/etc/dnsredir/"
+DNSREDIR_LOGDIR_PREFIX = "/var/log/dnsredir/"
+DNSREDIR_PIDFILE_PREFIX = "/var/run/dnsredir."
+REDIR_USER = "princeton_coredirect"
+#REDIR_USER = "arizona_tools1"
+#DEMUX_USER = "arizona_tools1"
+DEMUX_USER = "princeton_codnsdemux"
+HEARTBEAT_PORT = 9000
+#not required as of now, as there will be only one frontend dnsdemux for all the services
+#DNSDEMUX_CONFIGDIR_PREFIX = "/etc/dnsdemux/"
+#DNSDEMUX_LOGDIR_PREFIX = "/var/log/dnsdemux/"
+#DNSDEMUX_PIDFILE_PREFIX = "/var/run/dnsdemux."
+
+TBD = "TBD"
diff --git a/planetstack/rr_observer/steps/sync_requestrouterservices.py b/planetstack/rr_observer/steps/sync_requestrouterservices.py
new file mode 100644
index 0000000..546b45d
--- /dev/null
+++ b/planetstack/rr_observer/steps/sync_requestrouterservices.py
@@ -0,0 +1,46 @@
+import os
+import sys
+import base64
+import traceback
+from django.db.models import F, Q
+from planetstack.config import Config
+from observer.syncstep import SyncStep
+from core.models import Service
+from requestrouter.models import RequestRouterService
+from util.logger import Logger, logging
+
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+from rrlib import RequestRouterLibrary
+
+logger = Logger(level=logging.INFO)
+
+class SyncRequestRouterService(SyncStep, RequestRouterLibrary):
+    provides=[RequestRouterService]
+    requested_interval=0
+
+    def __init__(self, **args):
+        SyncStep.__init__(self, **args)
+        RequestRouterLibrary.__init__(self)
+
+    def fetch_pending(self):
+	try:
+        	ret = RequestRouterService.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+        	return ret
+	except Exception, e:
+        	traceback.print_exc()
+            	return None	
+
+    def sync_record(self, rr_service):
+	try:
+        	print "syncing service!"
+        	logger.info("sync'ing rr_service %s" % str(rr_service))
+        	self.gen_slice_file(rr_service)
+        	rr_service.save()
+		return True
+	except Exception, e:
+                traceback.print_exc()
+                return False
+
+
diff --git a/planetstack/rr_observer/steps/sync_servicemap.py b/planetstack/rr_observer/steps/sync_servicemap.py
new file mode 100644
index 0000000..76d2fdd
--- /dev/null
+++ b/planetstack/rr_observer/steps/sync_servicemap.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+
+import os
+import sys
+import base64
+import traceback
+from django.db.models import F, Q
+from planetstack.config import Config
+from observer.syncstep import SyncStep
+from core.models import Service
+from requestrouter.models import ServiceMap
+from util.logger import Logger, logging
+
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+from rrlib import RequestRouterLibrary
+from configurationPush import ConfigurationPush
+import rrlib_config
+
+logger = Logger(level=logging.INFO)
+
+class SyncServiceMap(SyncStep, RequestRouterLibrary, ConfigurationPush):
+    provides=[ServiceMap]
+    requested_interval=0
+
+    def __init__(self, **args):
+        SyncStep.__init__(self, **args)
+	RequestRouterLibrary.__init__(self)
+	ConfigurationPush.__init__(self)
+
+    def fetch_pending(self):
+	try:
+        	ret = ServiceMap.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+        	return ret
+	except Exception, e:
+        	traceback.print_exc()
+            	return None
+
+    def sync_record(self, servicemap):
+	try:
+		print "sync! %s " % self.get_servicemap_uid(servicemap)
+		self.gen_dnsredir_serviceconf(servicemap)
+		self.gen_dnsdemux_serviceconf(servicemap)
+        	# push generated files from temp_config
+		service_uid = self.get_servicemap_uid(servicemap)
+		self.config_push(service_uid, rrlib_config.REDIR_USER, "/opt/planetstack/rr_observer/playbook/site_redir.yml", "/etc/ansible/requestrouter/dnsredir/hosts")
+		self.config_push(service_uid, rrlib_config.DEMUX_USER, "/opt/planetstack/rr_observer/playbook/site_demux.yml", "/etc/ansible/requestrouter/dnsdemux/hosts")
+		self.teardown_temp_configfiles(service_uid)
+	except Exception, e:
+                traceback.print_exc()
+                return False
+
+if __name__ == "__main__":
+    sv = SyncServiceMap()
+
+    recs = sv.fetch_pending()
+
+    for rec in recs:
+        sv.sync_record( rec )