sync nodes
diff --git a/planetstack/observer/steps/__init__.py b/planetstack/observer/steps/__init__.py
index 7954426..50405a8 100644
--- a/planetstack/observer/steps/__init__.py
+++ b/planetstack/observer/steps/__init__.py
@@ -9,4 +9,5 @@
 from .sync_slivers import SyncSlivers
 from .sync_users import SyncUsers
 from .sync_roles import SyncRoles
+from .sync_nodes import SyncNodes
 from .garbage_collector import GarbageCollector
diff --git a/planetstack/observer/steps/garbage_collector.py b/planetstack/observer/steps/garbage_collector.py
index 5d434a0..a45db8c 100644
--- a/planetstack/observer/steps/garbage_collector.py
+++ b/planetstack/observer/steps/garbage_collector.py
@@ -16,7 +16,7 @@
 
     def call(self, **args):
         try:
-            #self.sync_roles()
+            #self.gc_roles()
             self.gc_tenants()
             self.gc_users()
             self.gc_user_tenant_roles()
@@ -208,3 +208,23 @@
 
     def gc_external_routes(self):
         pass
+
+    def gc_nodes(self):
+         # collect local nodes
+        nodes = Node.objects.all()
+        nodes_dict = {}
+        for node in nodes:
+            nodes_dict[node.name] = node
+
+        # collect nova nodes:
+        compute_nodes = self.client.nova.hypervisors.list()
+        compute_nodes_dict = {}
+        for compute_node in compute_nodes:
+            compute_nodes_dict[compute_node.hypervisor_hostname] = compute_node
+
+        # remove old nodes
+        old_node_names = set(nodes_dict.keys()).difference(compute_nodes_dict.keys())
+        Node.objects.filter(name__in=old_node_names).delete()
+
+    def gc_images(self):
+        pass
diff --git a/planetstack/observer/steps/sync_nodes.py b/planetstack/observer/steps/sync_nodes.py
new file mode 100644
index 0000000..a1f0803
--- /dev/null
+++ b/planetstack/observer/steps/sync_nodes.py
@@ -0,0 +1,42 @@
+import os
+import base64
+import random
+from datetime import datetime 
+from django.db.models import F, Q
+from planetstack.config import Config
+from observer.openstacksyncstep import OpenStackSyncStep
+from core.models.node import Node
+from core.models.deployment import Deployment
+from core.models.site import Site
+
+class SyncNodes(OpenStackSyncStep):
+    provides=[Node]
+    requested_interval=0
+
+    def fetch_pending(self):
+        config = Config()
+        deployment = Deployment.objects.filter(name=config.plc_deployment)[0]
+        login_bases = ['princeton', 'stanford', 'gt', 'uw', 'mpisws']
+        sites = Site.objects.filter(login_base__in=login_bases)
+        
+        # collect local nodes
+        nodes = Node.objects.all()
+        node_hostnames  = [node.name for node in nodes]
+
+        # collect nova nodes
+        # generate list of new nodes
+        new_nodes = []
+        compute_nodes = self.driver.shell.nova.hypervisors.list()
+        for compute_node in compute_nodes:
+            if compute_node.hypervisor_hostname not in node_hostnames:
+                # pick a random site to add the node to for now
+                site_index = random.randint(0, len(sites))
+                node = Node(name=compute_node.hypervisor_hostname, 
+                            site=sites[site_index], deployment=deployment)
+                new_nodes.append(node) 
+        
+        return new_nodes
+
+    def sync_record(self, node):
+        node.save()
+