move over fabric from XOS repo
diff --git a/xos/admin.py b/xos/admin.py
new file mode 100644
index 0000000..e372a7d
--- /dev/null
+++ b/xos/admin.py
@@ -0,0 +1,62 @@
+from django.contrib import admin
+
+from services.fabric.models import *
+from django import forms
+from django.utils.safestring import mark_safe
+from django.contrib.auth.admin import UserAdmin
+from django.contrib.admin.widgets import FilteredSelectMultiple
+from django.contrib.auth.forms import ReadOnlyPasswordHashField
+from django.contrib.auth.signals import user_logged_in
+from django.utils import timezone
+from django.contrib.contenttypes import generic
+from suit.widgets import LinkedSelect
+from core.models import AddressPool
+from core.admin import ServiceAppAdmin,SliceInline,ServiceAttrAsTabInline, ReadOnlyAwareAdmin, XOSTabularInline, ServicePrivilegeInline, TenantRootTenantInline, TenantRootPrivilegeInline
+from core.middleware import get_request
+
+from functools import update_wrapper
+from django.contrib.admin.views.main import ChangeList
+from django.core.urlresolvers import reverse
+from django.contrib.admin.utils import quote
+
+class FabricServiceForm(forms.ModelForm):
+    def __init__(self,*args,**kwargs):
+        super (FabricServiceForm,self ).__init__(*args,**kwargs)
+
+    def save(self, commit=True):
+        return super(FabricServiceForm, self).save(commit=commit)
+
+    class Meta:
+        model = FabricService
+
+class FabricServiceAdmin(ReadOnlyAwareAdmin):
+    model = FabricService
+    verbose_name = "Fabric Service"
+    verbose_name_plural = "Fabric Services"
+    list_display = ("backend_status_icon", "name", "enabled")
+    list_display_links = ('backend_status_icon', 'name', )
+    fieldsets = [(None, {'fields': ['backend_status_text', 'name','enabled','versionNumber', 'description', "view_url", "icon_url", "autoconfig", ],
+                         'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text', )
+    inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline]
+    form = FabricServiceForm
+
+    extracontext_registered_admins = True
+
+    user_readonly_fields = ["name", "enabled", "versionNumber", "description"]
+
+    suit_form_tabs =(('general', 'Fabric Service Details'),
+        ('administration', 'Administration'),
+        #('tools', 'Tools'),
+        ('slices','Slices'),
+        ('serviceattrs','Additional Attributes'),
+        ('serviceprivileges','Privileges'),
+    )
+
+    suit_form_includes = (('fabricadmin.html', 'top', 'administration'),
+                           )
+
+    def queryset(self, request):
+        return FabricService.get_service_objects_by_user(request.user)
+
+admin.site.register(FabricService, FabricServiceAdmin)
diff --git a/xos/fabric-onboard.yaml b/xos/fabric-onboard.yaml
new file mode 100644
index 0000000..12b535b
--- /dev/null
+++ b/xos/fabric-onboard.yaml
@@ -0,0 +1,24 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the fabric
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    servicecontroller#fabric:
+      type: tosca.nodes.ServiceController
+      properties:
+          base_url: file:///opt/xos_services/fabric/xos/
+          # The following will concatenate with base_url automatically, if
+          # base_url is non-null.
+          models: models.py
+          admin: admin.py
+          admin_template: templates/fabricadmin.html
+          synchronizer: synchronizer/manifest
+          synchronizer_run: fabric-synchronizer.py
+          tosca_resource: tosca/resources/fabricservice.py
+          #private_key: file:///opt/xos/key_import/vsg_rsa
+          #public_key: file:///opt/xos/key_import/vsg_rsa.pub
+
diff --git a/xos/models.py b/xos/models.py
new file mode 100644
index 0000000..bd37416
--- /dev/null
+++ b/xos/models.py
@@ -0,0 +1,16 @@
+from django.db import models
+from core.models import Service
+import traceback
+from xos.exceptions import *
+from xos.config import Config
+
+FABRIC_KIND = "fabric"
+
+class FabricService(Service):
+    KIND = FABRIC_KIND
+
+    class Meta:
+        app_label = "fabric"
+        verbose_name = "Fabric Service"
+
+    autoconfig = models.BooleanField(default=True, help_text="Autoconfigure the fabric")
diff --git a/xos/synchronizer/fabric-synchronizer.py b/xos/synchronizer/fabric-synchronizer.py
new file mode 100755
index 0000000..84bec4f
--- /dev/null
+++ b/xos/synchronizer/fabric-synchronizer.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+
+# This imports and runs ../../xos-observer.py
+
+import importlib
+import os
+import sys
+observer_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),"../../synchronizers/base")
+sys.path.append(observer_path)
+mod = importlib.import_module("xos-synchronizer")
+mod.main()
diff --git a/xos/synchronizer/fabric_synchronizer_config b/xos/synchronizer/fabric_synchronizer_config
new file mode 100644
index 0000000..2ed56fe
--- /dev/null
+++ b/xos/synchronizer/fabric_synchronizer_config
@@ -0,0 +1,23 @@
+# Required by XOS
+[db]
+name=xos
+user=postgres
+password=password
+host=localhost
+port=5432
+
+# Required by XOS
+[api]
+nova_enabled=True
+
+# Sets options for the synchronizer
+[observer]
+name=fabric
+dependency_graph=/opt/xos/synchronizers/fabric/model-deps
+steps_dir=/opt/xos/synchronizers/fabric/steps
+sys_dir=/opt/xos/synchronizers/fabric/sys
+logfile=console
+pretend=False
+backoff_disabled=True
+save_ansible_output=True
+proxy_ssh=False
diff --git a/xos/synchronizer/manifest b/xos/synchronizer/manifest
new file mode 100644
index 0000000..62a0722
--- /dev/null
+++ b/xos/synchronizer/manifest
@@ -0,0 +1,9 @@
+manifest
+fabric_synchronizer_config
+steps/sync_host.yaml
+steps/sync_vroutertenant.py
+start.sh
+stop.sh
+model-deps
+run.sh
+fabric-synchronizer.py
diff --git a/xos/synchronizer/model-deps b/xos/synchronizer/model-deps
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/xos/synchronizer/model-deps
@@ -0,0 +1 @@
+{}
diff --git a/xos/synchronizer/run.sh b/xos/synchronizer/run.sh
new file mode 100755
index 0000000..4e0c214
--- /dev/null
+++ b/xos/synchronizer/run.sh
@@ -0,0 +1,2 @@
+export XOS_DIR=/opt/xos
+python fabric-synchronizer.py  -C $XOS_DIR/synchronizers/fabric/fabric_synchronizer_config
diff --git a/xos/synchronizer/start.sh b/xos/synchronizer/start.sh
new file mode 100755
index 0000000..8d02bf3
--- /dev/null
+++ b/xos/synchronizer/start.sh
@@ -0,0 +1,2 @@
+export XOS_DIR=/opt/xos
+nohup python fabric-synchronizer.py  -C $XOS_DIR/synchronizers/fabric/fabric_synchronizer_config > /dev/null 2>&1 &
diff --git a/xos/synchronizer/steps/sync_host.yaml b/xos/synchronizer/steps/sync_host.yaml
new file mode 100644
index 0000000..58bccba
--- /dev/null
+++ b/xos/synchronizer/steps/sync_host.yaml
@@ -0,0 +1,20 @@
+---
+- hosts: 127.0.0.1
+  connection: local
+  vars:
+    rest_hostname: {{ rest_hostname }}
+    rest_port: {{ rest_port }}
+    rest_endpoint: {{ rest_endpoint }}
+    rest_json: '{{ rest_json }}'
+
+  tasks:
+  - debug: var=rest_json
+
+  - name: Call Fabric REST API
+    uri:
+      url: http://{{ '{{' }} rest_hostname {{ '}}' }}:{{ '{{' }} rest_port {{ '}}' }}/{{ '{{' }} rest_endpoint {{ '}}' }} #http://localhost:8181/onos/v1/network/configuration/
+      body: "{{ '{{' }} rest_json {{ '}}' }}"
+      body_format: raw
+      method: POST
+      user: karaf
+      password: karaf
diff --git a/xos/synchronizer/steps/sync_vroutertenant.py b/xos/synchronizer/steps/sync_vroutertenant.py
new file mode 100644
index 0000000..fd77ca2
--- /dev/null
+++ b/xos/synchronizer/steps/sync_vroutertenant.py
@@ -0,0 +1,103 @@
+import os
+import base64
+from collections import defaultdict
+from django.db.models import F, Q
+from xos.config import Config
+from synchronizers.base.openstacksyncstep import OpenStackSyncStep
+from synchronizers.base.syncstep import *
+from core.models import Controller
+from core.models import Image, ControllerImages
+from xos.logger import observer_logger as logger
+from synchronizers.base.ansible import *
+from services.vrouter.models import VRouterTenant
+from services.onos.models import ONOSService
+from services.fabric.models import FabricService
+import json
+
+class SyncVRouterTenant(SyncStep):
+    provides=[VRouterTenant]
+    observes = VRouterTenant
+    requested_interval=30
+    playbook='sync_host.yaml'
+
+    def get_fabric_onos_service(self):
+        fos = None
+        fs = FabricService.get_service_objects().all()[0]
+        if fs.subscribed_tenants.exists():
+            app = fs.subscribed_tenants.all()[0]
+            if app.provider_service:
+                ps = app.provider_service
+                fos = ONOSService.get_service_objects().filter(id=ps.id)[0]
+        return fos
+
+    def get_node_tag(self, node, tagname):
+        tags = Tag.select_by_content_object(node).filter(name=tagname)
+        return tags[0].value
+
+    def fetch_pending(self, deleted):
+        fs = FabricService.get_service_objects().all()[0]
+        if not fs.autoconfig:
+            return None
+
+        if (not deleted):
+            objs = VRouterTenant.get_tenant_objects().filter(Q(lazy_blocked=False))
+        else:
+            objs = VRouterTenant.get_deleted_tenant_objects()
+
+        return objs
+
+    def map_sync_inputs(self, vroutertenant):
+
+        fos = self.get_fabric_onos_service()
+
+        name = None
+        instance = None
+        # VRouterTenant setup is kind of hacky right now, we'll
+        # need to revisit.  The idea is:
+        # * Look up the instance corresponding to the address
+        # * Look up the node running the instance
+        # * Get the "location" tag, push to the fabric
+        #
+        # Do we have a vCPE subscriber_tenant?
+        if (vroutertenant.subscriber_tenant):
+            sub = vroutertenant.subscriber_tenant
+            if (sub.kind == 'vCPE'):
+                instance_id = sub.get_attribute("instance_id")
+                if instance_id:
+                    instance = Instance.objects.filter(id=instance_id)[0]
+                    name = str(sub)
+        else:
+            # Maybe the VRouterTenant is for an instance
+            instance_id = vroutertenant.get_attribute("tenant_for_instance_id")
+            if instance_id: 
+                instance = Instance.objects.filter(id=instance_id)[0]
+                name = str(instance)
+
+        node = instance.node
+        location = self.get_node_tag(node, "location")
+
+        # Is it a POST or DELETE?
+
+        # Create JSON
+        data = {
+            "%s/-1"%vroutertenant.public_mac : {
+                "basic" : {
+                    "ips" : [ vroutertenant.public_ip ],
+                    "location" : location
+                }
+            }
+        }
+
+        rest_json = json.dumps(data, indent=4)
+
+        fields = {
+            'rest_hostname': fos.rest_hostname,
+            'rest_port': fos.rest_port,
+            'rest_json': rest_json,
+            'rest_endpoint': "onos/v1/network/configuration/hosts",
+            'ansible_tag': '%s'%name, # name of ansible playbook
+        }
+        return fields
+
+    def map_sync_outputs(self, controller_image, res):
+        pass
diff --git a/xos/synchronizer/stop.sh b/xos/synchronizer/stop.sh
new file mode 100755
index 0000000..d35b057
--- /dev/null
+++ b/xos/synchronizer/stop.sh
@@ -0,0 +1 @@
+pkill -9 -f fabric-synchronizer.py
diff --git a/xos/templates/fabricadmin.html b/xos/templates/fabricadmin.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/xos/templates/fabricadmin.html
diff --git a/xos/tosca/resources/fabricservice.py b/xos/tosca/resources/fabricservice.py
new file mode 100644
index 0000000..0c9cfb4
--- /dev/null
+++ b/xos/tosca/resources/fabricservice.py
@@ -0,0 +1,16 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from services.fabric.models import FabricService
+
+from service import XOSService
+
+class FabricService(XOSService):
+    provides = "tosca.nodes.FabricService"
+    xos_model = FabricService
+    copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key", "versionNumber"]
+