Merge branch 'master' into feature/fabric-synchronizer
diff --git a/.gitignore b/.gitignore
index bf493e8..617f1f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,4 @@
 .DS_Store
 xos/configurations/setup/
 migrations/
+xos/configurations/frontend/onboarding-docker-compose/
diff --git a/containers/onboarding_synchronizer/Dockerfile b/containers/onboarding_synchronizer/Dockerfile
index 967e234..b86cbb1 100644
--- a/containers/onboarding_synchronizer/Dockerfile
+++ b/containers/onboarding_synchronizer/Dockerfile
@@ -10,12 +10,20 @@
 # This container must be started in privileged mode. 
 
 RUN apt-get install -y curl
-# iptables 
-ENV DOCKER_BUCKET=get.docker.com
-ENV DOCKER_VERSION=1.8.3
-ENV DOCKER_SHA256=f024bc65c45a3778cf07213d26016075e8172de8f6e4b5702bedde06c241650f
-RUN curl -fSL "https://${DOCKER_BUCKET}/builds/Linux/x86_64/docker-$DOCKER_VERSION" -o /usr/local/bin/docker && echo "${DOCKER_SHA256} /usr/local/bin/docker" | sha256sum -c - && chmod +x /usr/local/bin/docker
 
+# XXX version 1.10.3
+ENV DOCKER_BUCKET get.docker.com
+ENV DOCKER_VERSION 1.10.3

+ENV DOCKER_SHA256 d0df512afa109006a450f41873634951e19ddabf8c7bd419caeb5a526032d86d

+RUN curl -fSL "https://${DOCKER_BUCKET}/builds/Linux/x86_64/docker-$DOCKER_VERSION" -o /usr/local/bin/docker && echo "${DOCKER_SHA256}  /usr/local/bin/docker" | sha256sum -c - && chmod +x /usr/local/bin/docker

+
+# XXX vserioin 1.8.3
+#ENV DOCKER_BUCKET=get.docker.com
+#ENV DOCKER_VERSION=1.8.3
+#ENV DOCKER_SHA256=f024bc65c45a3778cf07213d26016075e8172de8f6e4b5702bedde06c241650f
+#RUN curl -fSL "https://${DOCKER_BUCKET}/builds/Linux/x86_64/docker-$DOCKER_VERSION" -o /usr/local/bin/docker && echo "${DOCKER_SHA256} /usr/local/bin/docker" | sha256sum -c - && chmod +x /usr/local/bin/docker
+
+# XXX version 1.8.3
 # XXX uncomment the following 6 lines to run docker-in-docker
 #     comment them out if using the docker socket in a volume instead
 #ENV DIND_COMMIT=3b5fac462d21ca164b3778647420016315289034
diff --git a/containers/xos/Dockerfile.base b/containers/xos/Dockerfile.base
index e430dc8..e653b5a 100644
--- a/containers/xos/Dockerfile.base
+++ b/containers/xos/Dockerfile.base
@@ -126,17 +126,17 @@
 COPY ansible-hosts /etc/ansible/hosts
 
 # For Synchronizer
-ENV PHANTOMJS_DL_URL http://phantomjs.googlecode.com/files/phantomjs-1.7.0-linux-x86_64.tar.bz2
-ENV PHANTOMJS_SHA256 a7658f5f2d9464f86891afdb979eb60b754d5f404801db624368ac11e16724d4
+# ENV PHANTOMJS_DL_URL http://phantomjs.googlecode.com/files/phantomjs-1.7.0-linux-x86_64.tar.bz2
+# ENV PHANTOMJS_SHA256 a7658f5f2d9464f86891afdb979eb60b754d5f404801db624368ac11e16724d4
 
-RUN curl -fLsS $PHANTOMJS_DL_URL -o phantomjs.tar.bz2 && \
-  echo "$PHANTOMJS_SHA256  phantomjs.tar.bz2" | sha256sum -c - && \
-  tar -C /usr/local/share -xjf phantomjs.tar.bz2 && \
-  ln -s /usr/local/share/phantomjs-* /usr/local/share/phantomjs && \
-  ln -s /usr/local/share/phantomjs/bin/phantomjs /bin/phantomjs && \
-  rm phantomjs.tar.bz2
+# RUN curl -fLsS $PHANTOMJS_DL_URL -o phantomjs.tar.bz2 && \
+#  echo "$PHANTOMJS_SHA256  phantomjs.tar.bz2" | sha256sum -c - && \
+#  tar -C /usr/local/share -xjf phantomjs.tar.bz2 && \
+#  ln -s /usr/local/share/phantomjs-* /usr/local/share/phantomjs && \
+#  ln -s /usr/local/share/phantomjs/bin/phantomjs /bin/phantomjs && \
+#  rm phantomjs.tar.bz2
 
-RUN git clone git://git.planet-lab.org/fofum.git /tmp/fofum && \
-    cd /tmp/fofum; python setup.py install && \
-    rm -rf /tmp/fofum
+#RUN git clone git://git.planet-lab.org/fofum.git /tmp/fofum && \
+#    cd /tmp/fofum; python setup.py install && \
+#    rm -rf /tmp/fofum
 
diff --git a/views/ngXosLib/.eslintrc b/views/ngXosLib/.eslintrc
index 1cd7d33..6a8ce79 100644
--- a/views/ngXosLib/.eslintrc
+++ b/views/ngXosLib/.eslintrc
@@ -12,7 +12,7 @@
         "es6": true
     },
     "plugins": [
-        //"angular"
+        "angular"
     ],
     "rules": {
         "quotes": [2, "single"],
@@ -28,12 +28,15 @@
         "no-trailing-spaces": [1, { skipBlankLines: true }],
         "no-unused-vars": [1, {"vars": "all", "args": "after-used"}],
         "new-cap": 0,
+        "no-multiple-empty-lines": 2,
 
-        //"angular/ng_module_name": [2, '/^xos\.*[a-z]*$/'],
-        //"angular/ng_controller_name": [2, '/^[a-z].*Ctrl$/'],
+        "angular/ng_module_name": [2, '/^xos\.*[a-z]*$/'],
+//        "angular/ng_controller_name": [2, '/^[a-z].*Ctrl$/'],
         //"angular/ng_service_name": [2, '/^[A-Z].*Service$/'],
-        //"angular/ng_directive_name": [2, '/^[a-z]+[[A-Z].*]*$/'],
-        //"angular/ng_di": [0, "function or array"]
+        "angular/ng_directive_name": [2, '/^[xos[[A-Z].*]*$/'],
+        "angular/ng_di": [0, "function or array"],
+        "angular/ng_angularelement": 0,
+        "angular/ng_on_watch": 1
     },
     "globals" :{
         "angular": true
diff --git a/views/ngXosLib/bower.json b/views/ngXosLib/bower.json
index d2c7744..351756c 100644
--- a/views/ngXosLib/bower.json
+++ b/views/ngXosLib/bower.json
@@ -26,7 +26,8 @@
   },
   "devDependencies": {
     "angular-mocks": "1.4.7",
-    "jasmine-jquery": "~2.1.1"
+    "jasmine-jquery": "~2.1.1",
+    "jquery": "~3.0.0"
   },
   "resolutions": {
     "angular": "1.4.7"
diff --git a/views/ngXosLib/gulp/ngXosHelpers.js b/views/ngXosLib/gulp/ngXosHelpers.js
index 638e665..a19d85e 100644
--- a/views/ngXosLib/gulp/ngXosHelpers.js
+++ b/views/ngXosLib/gulp/ngXosHelpers.js
@@ -68,9 +68,9 @@
 
     var ngOptions = {
       scripts: [].concat([
-        'https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular-mocks.js',
         `./${options.ngXosVendor}ngXosVendor.js`,
         `./${options.ngXosVendor}ngXosHelpers.js`,
+          'https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular-mocks.js',
       ]),
       styles: [
         `./${options.ngXosStyles}xosNgLib.css`,
@@ -107,7 +107,7 @@
         baseDir: './docs',
         routes: {
           '/xos/core/xoslib/static/js/vendor': options.ngXosVendor,
-          '/xos/core/static': options.ngXosStyles
+          '/xos/core/static': options.ngXosStyles,
         }
       }
     });
diff --git a/views/ngXosLib/karma.conf.ci.js b/views/ngXosLib/karma.conf.ci.js
index da10570..3bd017c 100644
--- a/views/ngXosLib/karma.conf.ci.js
+++ b/views/ngXosLib/karma.conf.ci.js
@@ -19,7 +19,6 @@
 viewFiles = viewFiles
               .filter(f => f.indexOf('xosAdminSite') === -1)
               .filter(f => f.indexOf('xosCord') === -1)
-              .filter(f => f.indexOf('xosTenant') === -1)
               .filter(f => f.indexOf('xosHpc') === -1);
 
 viewFiles = viewFiles.filter(f => f.indexOf('js') >= 0).filter(f => f.match(/^xos[A-Z][a-z]+/)).map(f => `${viewDir}${f}`);
@@ -43,15 +42,12 @@
   // loading ngMock
   'template.module.js',
   `./bower_components/angular-mocks/angular-mocks.js`,
-
-  // loading templates
-  `../../xos/core/xoslib/dashboards/xosDiagnostic.html`,
-
 ]
 .concat(vendorFiles)
 .concat(viewFiles)
 .concat([
   // loading tests
+  `xosHelpers/spec/test_helpers.js`,
   `../ngXosViews/*/spec/*.test.js`,
   `../ngXosViews/*/spec/**/*.mock.js`,
   'xosHelpers/spec/**/*.test.js'
diff --git a/views/ngXosLib/karma.conf.js b/views/ngXosLib/karma.conf.js
index 9d880a0..4032b49 100644
--- a/views/ngXosLib/karma.conf.js
+++ b/views/ngXosLib/karma.conf.js
@@ -21,6 +21,7 @@
   'node_modules/babel-polyfill/dist/polyfill.js',
   'xosHelpers/src/**/*.module.js',
   'xosHelpers/src/**/*.js',
+  `xosHelpers/spec/test_helpers.js`,
   `xosHelpers/spec/**/${testFiles}.test.js`
 ]);
 
@@ -94,7 +95,7 @@
     // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
     browsers: [
       'PhantomJS',
-      // 'Chrome'
+       //'Chrome'
     ],
 
 
diff --git a/views/ngXosLib/xosHelpers/spec/.eslintrc b/views/ngXosLib/xosHelpers/spec/.eslintrc
new file mode 100644
index 0000000..de1e44b
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/spec/.eslintrc
@@ -0,0 +1,7 @@
+{
+  "rules": {
+    "angular/ng_angularelement": 0,
+    "angular/ng_no_digest": 0,
+    "angular/ng_json_functions": 0
+  }
+}
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/spec/log.test.js b/views/ngXosLib/xosHelpers/spec/log.test.js
index f286a8e..21085c6 100644
--- a/views/ngXosLib/xosHelpers/spec/log.test.js
+++ b/views/ngXosLib/xosHelpers/spec/log.test.js
@@ -3,6 +3,7 @@
  *
  * Created by teone on 4/18/16.
  */
+/* eslint-disable angular/ng_window_service*/
 
 // TODO write tests for log
 // NODE Actually the code is working, the tests are not.
@@ -12,9 +13,9 @@
 
   xdescribe('The xos.helper module', function(){
 
-    let log;
+    let log, window;
 
-    var mockLog;
+    let mockLog;
 
     beforeEach(function() {
       mockLog = jasmine.createSpyObj('logMock', ['info']);
@@ -28,8 +29,9 @@
       });
     });
 
-    beforeEach(inject(($log) => {
+    beforeEach(inject(($log, $window) => {
       log = $log;
+      window = $window;
       // log.reset();
     }));
 
diff --git a/views/ngXosLib/xosHelpers/spec/services/helpers/comparator.test.js b/views/ngXosLib/xosHelpers/spec/services/helpers/comparator.test.js
new file mode 100644
index 0000000..66e26d3
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/spec/services/helpers/comparator.test.js
@@ -0,0 +1,60 @@
+(function () {
+  'use strict';
+
+  describe('The xos.helper module', function(){
+    describe('The Comparator service', () => {
+
+      let service;
+
+      // load the application module
+      beforeEach(module('xos.helpers'));
+
+      // inject the cartService
+      beforeEach(inject(function (_Comparator_) {
+        // The injector unwraps the underscores (_) from around the parameter names when matching
+        service = _Comparator_;
+      }));
+
+      describe('given a string', () => {
+        it('should return true if expected is substring of actual', () => {
+          const res = service('test', 'te');
+          expect(res).toBeTruthy();
+        });
+
+        it('should return false if expected is not substring of actual', () => {
+          const res = service('test', 'ab');
+          expect(res).toBeFalsy();
+        });
+      });
+
+      describe('given a boolean', () => {
+        it('should return true if values match', () => {
+          expect(service(false, false)).toBeTruthy();
+          expect(service(true, true)).toBeTruthy();
+          expect(service(0, false)).toBeTruthy();
+          expect(service(1, true)).toBeTruthy();
+        });
+
+        it('should return false if values doesn\'t match', () => {
+          expect(service(false, true)).toBeFalsy();
+          expect(service(true, false)).toBeFalsy();
+          expect(service(1, false)).toBeFalsy();
+          expect(service(0, true)).toBeFalsy();
+        });
+      });
+
+      describe('given a number', () => {
+        // NOTE if numbers should we compare with === ??
+        it('should return true if expected is substring of actual', () => {
+          expect(service(12, 1)).toBeTruthy();
+        });
+
+        it('should return false if expected is not substring of actual', () => {
+          expect(service(12, 3)).toBeFalsy();
+        });
+      });
+
+    });
+  });
+
+})();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/spec/test_helpers.js b/views/ngXosLib/xosHelpers/spec/test_helpers.js
new file mode 100644
index 0000000..b78bf3d
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/spec/test_helpers.js
@@ -0,0 +1,17 @@
+/**
+ * Collection of helpers for xos tests
+ */
+
+const clickElement = function (el){
+  var ev = document.createEvent("MouseEvent");
+  ev.initMouseEvent(
+    "click",
+    true /* bubble */, true /* cancelable */,
+    window, null,
+    0, 0, 0, 0, /* coordinates */
+    false, false, false, false, /* modifier keys */
+    0 /*left*/, null
+  );
+  el.dispatchEvent(ev);
+};
+console.log('---------------------- Test Helpers Loaded!! -----------------------');
diff --git a/views/ngXosLib/xosHelpers/spec/ui/custom-validator.test.js b/views/ngXosLib/xosHelpers/spec/ui/custom-validator.test.js
new file mode 100644
index 0000000..76f41a9
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/spec/ui/custom-validator.test.js
@@ -0,0 +1,107 @@
+/**
+ * © OpenCORD
+ *
+ * Created by teone on 5/25/16.
+ */
+
+(function () {
+  'use strict';
+
+  describe('The xos.helper module', function () {
+    describe('The xosCustomValidator directive', () => {
+      let element, scope, isolatedScope, rootScope, compile, form, input;
+      const compileElement = (el) => {
+        element = el;
+
+        if(!scope){
+          scope = rootScope.$new();
+        }
+        if(angular.isUndefined(element)){
+          element = angular.element(`
+            <form name="form">
+              <input name="testInput" type="text" ng-model="value" xos-custom-validator custom-validator="validator"/>
+            </form>
+          `);
+        }
+        compile(element)(scope);
+        scope.$digest();
+        input = $(element).find('input');
+        isolatedScope = angular.element(input).isolateScope();
+        form = scope.form;
+      };
+
+      beforeEach(module('xos.helpers'));
+
+      beforeEach(inject(function ($compile, $rootScope) {
+        compile = $compile;
+        rootScope = $rootScope;
+      }));
+
+      beforeEach(() => {
+        scope = rootScope.$new();
+        scope.validator = 'validator';
+        scope.value = '';
+        compileElement();
+      });
+
+      it('should bind the validator', () => {
+        expect(isolatedScope.fn).toEqual('validator');
+      });
+
+      describe('given a validator function', () => {
+
+        beforeEach(() => {
+          scope = rootScope.$new();
+          scope.value = '';
+          scope.validator = (model) => angular.equals(model, 'test');
+          spyOn(scope, 'validator').and.callThrough();
+          compileElement();
+        });
+
+        it('should call the validator function on value change', () => {
+          form.testInput.$setViewValue('something');
+          scope.$digest();
+          expect(scope.validator).toHaveBeenCalledWith('something');
+          expect(scope.value).toEqual('something');
+        });
+
+        it('should set the field invalid', () => {
+          form.testInput.$setViewValue('something');
+          scope.$digest();
+          expect(scope.validator).toHaveBeenCalledWith('something');
+          expect(input).toHaveClass('ng-invalid');
+          expect(input).toHaveClass('ng-invalid-custom-validation');
+        });
+
+        it('should set the field valid', () => {
+          form.testInput.$setViewValue('test');
+          scope.$digest();
+          expect(scope.validator).toHaveBeenCalledWith('test');
+          expect(input).not.toHaveClass('ng-invalid');
+          expect(input).not.toHaveClass('ng-invalid-custom-validation');
+        });
+
+        describe('if the validation function return an array', () => {
+
+          beforeEach(() => {
+            scope = rootScope.$new();
+            scope.value = '';
+            scope.validator = (model) => {
+              return ['randomTest', angular.equals(model, 'test')];
+            };
+            spyOn(scope, 'validator').and.callThrough();
+            compileElement();
+          });
+
+          it('should set the field invalid', () => {
+            form.testInput.$setViewValue('something');
+            scope.$digest();
+            expect(scope.validator).toHaveBeenCalledWith('something');
+            expect(input).toHaveClass('ng-invalid');
+            expect(input).toHaveClass('ng-invalid-random-test');
+          });
+        });
+      });
+    });
+  });
+})();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/spec/ui/field.test.js b/views/ngXosLib/xosHelpers/spec/ui/field.test.js
index 62a41a7..8a02d4d 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/field.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/field.test.js
@@ -7,24 +7,23 @@
 (function () {
   'use strict';
 
-  let element, scope, isolatedScope, rootScope, compile;
-  const compileElement = (el) => {
-    element = el;
-
-    if(!scope){
-      scope = rootScope.$new();
-    }
-    if(!angular.isDefined(element)){
-      element = angular.element('<xos-field name="name" field="field" ng-model="ngModel"></xos-field>');
-    }
-    compile(element)(scope);
-    scope.$digest();
-    isolatedScope = element.isolateScope().vm;
-  }
-
   describe('The xos.helper module', function(){
 
     describe('The xosField component', () => {
+      let element, scope, isolatedScope, rootScope, compile;
+      const compileElement = (el) => {
+        element = el;
+
+        if(!scope){
+          scope = rootScope.$new();
+        }
+        if(angular.isUndefined(element)){
+          element = angular.element('<xos-field name="name" field="field" ng-model="ngModel"></xos-field>');
+        }
+        compile(element)(scope);
+        scope.$digest();
+        isolatedScope = element.isolateScope().vm;
+      };
 
       beforeEach(module('xos.helpers'));
 
@@ -93,7 +92,9 @@
           scope.field = {
             label: 'Label',
             type: 'text',
-            validators: {}
+            validators: {
+              custom: 'fake'
+            }
           };
           scope.ngModel = 'label';
           compileElement();
@@ -102,11 +103,14 @@
         it('should print a text field', () => {
           expect($(element).find('[name="label"]')).toHaveAttr('type', 'text');
         });
+
+        it('should attach the custom validator directive', () => {
+          let input = $(element).find('[name="label"]');
+          expect(input).toHaveAttr('xos-custom-validator');
+          expect(input).toHaveAttr('custom-validator', 'vm.field.validators.custom || null');
+        });
       });
 
-
-
-
       describe('when a option is selected in dropdown', () => {
         beforeEach(() => {
           scope = rootScope.$new();
@@ -126,17 +130,18 @@
               }
             ]
           };
-          scope.ngModel = 'label';
+          scope.ngModel = 0;
           compileElement();
         });
 
         it('No of select elements', () => {
-          expect($(element).find('select').children('option').length).toEqual(3);
+          expect($(element).find('select').children('option').length).toEqual(2);
         });
 
-        it('should show a selected value', () => {
-          var elem =  angular.element($(element).find('select').children('option')[1]);
+        it('should show the selected value', () => {
+          var elem =  angular.element($(element).find('select').children('option')[0]);
           expect(elem.text()).toEqual('---Site---');
+          expect(elem).toHaveAttr('selected');
         });
       });
 
@@ -174,17 +179,17 @@
         let setFalse, setTrue;
 
         beforeEach(() => {
-          setFalse= $(element).find('.boolean-field > button:first-child');
-          setTrue = $(element).find('.boolean-field > button:last-child');
+          setFalse= $(element).find('.boolean-field > a:first-child');
+          setTrue = $(element).find('.boolean-field > a:last-child');
         });
 
         it('should print two buttons', () => {
-          expect($(element).find('.boolean-field > button').length).toEqual(2)
+          expect($(element).find('.boolean-field > a').length).toEqual(2)
         });
 
         it('should change value to false', () => {
           expect(isolatedScope.ngModel).toEqual(true);
-          setFalse.click()
+          clickElement(setFalse[0]);
           expect(isolatedScope.ngModel).toEqual(false);
         });
 
@@ -192,7 +197,7 @@
           isolatedScope.ngModel = false;
           scope.$apply();
           expect(isolatedScope.ngModel).toEqual(false);
-          setTrue.click()
+          clickElement(setTrue[0]);
           expect(isolatedScope.ngModel).toEqual(true);
         });
       });
@@ -220,7 +225,7 @@
 
         it('should print the right input type for each property', () => {
           expect($(element).find('input').length).toBe(2);
-          expect($(element).find('.boolean-field > button').length).toEqual(2);
+          expect($(element).find('.boolean-field > a').length).toEqual(2);
         });
 
         it('should format labels', () => {
@@ -267,6 +272,59 @@
           });
         });
       });
+
+      describe('when validation options are passed', () => {
+        let input;
+        describe('given a a text field', () => {
+          beforeEach(() => {
+            scope.field = {
+              label: 'Label',
+              type: 'text',
+              validators: {
+                minlength: 10,
+                maxlength: 15,
+                required: true
+              }
+            };
+
+            scope.$digest();
+            input = $(element).find('input');
+          });
+
+          it('should validate required', () => {
+            scope.ngModel= null;
+            scope.$digest();
+            expect(input).toHaveClass('ng-invalid-required');
+
+            scope.ngModel= 'not too short';
+            scope.$digest();
+            expect(input).not.toHaveClass('ng-invalid-required');
+            expect(input).not.toHaveClass('ng-invalid');
+          });
+
+          it('should validate minlength', () => {
+            scope.ngModel= 'short';
+            scope.$digest();
+            expect(input).toHaveClass('ng-invalid-minlength');
+
+            scope.ngModel= 'not too short';
+            scope.$digest();
+            expect(input).not.toHaveClass('ng-invalid-minlength');
+            expect(input).not.toHaveClass('ng-invalid');
+          });
+
+          it('should validate maxlength', () => {
+            scope.ngModel= 'this is definitely too long!!';
+            scope.$digest();
+            expect(input).toHaveClass('ng-invalid-maxlength');
+
+            scope.ngModel= 'not too short';
+            scope.$digest();
+            expect(input).not.toHaveClass('ng-invalid-maxlength');
+            expect(input).not.toHaveClass('ng-invalid');
+          });
+        });
+      });
     });
   });
 })();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/spec/ui/form.test.js b/views/ngXosLib/xosHelpers/spec/ui/form.test.js
index eac10f5..87f671a 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/form.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/form.test.js
@@ -109,13 +109,16 @@
         });
 
         it('should render 1 boolean field', () => {
-          expect($(element).find('.boolean-field > button').length).toEqual(2)
+          expect($(element).find('.boolean-field > a').length).toEqual(2)
         });
 
         it('when clicking on action should invoke callback', () => {
           var link = $(element).find('[role="button"]');
+          //console.log(link);
           link.click();
-          expect(cb).toHaveBeenCalledWith(scope.model);
+          // TODO : Check correct parameters
+          expect(cb).toHaveBeenCalled();
+
         });
 
         it('should set a custom label', () => {
@@ -130,7 +133,7 @@
           expect($(element).find('[name="email"]')).toHaveAttr('type', 'email');
         });
 
-        describe('the boolean field', () => {
+        xdescribe('the boolean field test', () => {
 
           let setFalse, setTrue;
 
@@ -141,7 +144,7 @@
 
           it('should change value to false', () => {
             expect(isolatedScope.ngModel.enabled).toEqual(true);
-            setFalse.click()
+            setFalse.click();
             expect(isolatedScope.ngModel.enabled).toEqual(false);
           });
 
@@ -154,59 +157,6 @@
           });
         });
 
-        // NOTE not sure why this tests are failing
-        xdescribe('the custom validation options', () => {
-          beforeEach(() => {
-            scope.config.fields.first_name.validators = {
-              minlength: 10,
-              maxlength: 15,
-              required: true
-            };
-
-            scope.config.fields.age = {
-              validators: {
-                min: 10,
-                max: 20
-              }
-            };
-
-            scope.$digest();
-          });
-
-          it('should validate required', () => {
-            scope.model.first_name = null;
-            scope.$digest();
-
-            expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
-            expect(isolatedScope.testForm.first_name.$error.required).toBeTruthy();
-          });
-
-          it('should validate minlength', () => {
-            scope.model.first_name = 'short';
-            scope.$digest();
-
-            expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
-            expect(isolatedScope.testForm.first_name.$error.minlength).toBeTruthy();
-          });
-
-          it('should validate maxlength', () => {
-            scope.model.first_name = 'this is way too long!';
-            scope.$digest();
-
-            expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
-            expect(isolatedScope.testForm.first_name.$error.maxlength).toBeTruthy();
-          });
-
-          it('should validate min', () => {
-            // not validating min and max for now
-            scope.model.age = 8;
-            scope.$digest();
-
-            expect(isolatedScope.testForm.age.$valid).toBeFalsy();
-            expect(isolatedScope.testForm.age.$error.min).toBeTruthy();
-          });
-        });
-
         describe('when a deep model is passed', () => {
 
           beforeEach(inject(($rootScope) => {
@@ -254,6 +204,66 @@
           });
         });
       });
+      describe('when correctly configured for feedback', () => {
+
+        let fb = jasmine.createSpy('feedback').and.callFake(function(statusFlag) {
+          if(statusFlag){
+            scope.config.feedback.show = true;
+            scope.config.feedback.message = 'Form Submitted';
+            scope.config.feedback.type = 'success';
+          }
+          else {
+            scope.config.feedback.show = true;
+            scope.config.feedback.message = 'Error';
+            scope.config.feedback.type = 'danger';
+
+          }
+        });
+
+        beforeEach(()=> {
+          scope = rootScope.$new();
+          scope.config =
+          {
+
+            feedback: {
+              show: false,
+              message: 'Form submitted successfully !!!',
+              type: 'success'
+            },
+            actions: [
+              {
+                label: 'Save',
+                icon: 'ok', // refers to bootstraps glyphicon
+                cb: () => {},
+                class: 'success'
+              }
+            ]
+          };
+          scope.model={};
+          compileElement();
+        });
+
+        it('should not show feedback when loaded', () => {
+          expect($(element).find('xos-alert > div')).toHaveClass('alert alert-success ng-hide');
+        });
+
+        it('should show a success feedback', () => {
+          fb(true);
+          scope.$digest();
+          expect(isolatedScope.config.feedback.type).toEqual('success');
+          expect(fb).toHaveBeenCalledWith(true);
+          expect($(element).find('xos-alert > div')).toHaveClass('alert alert-success');
+        });
+
+        it('should show an error feedback', function() {
+          fb(false);
+          scope.$digest();
+          expect(isolatedScope.config.feedback.type).toEqual('danger');
+          expect(fb).toHaveBeenCalledWith(false);
+          expect($(element).find('xos-alert > div')).toHaveClass('alert alert-danger');
+        });
+      });
+
     });
   });
 })();
diff --git a/views/ngXosLib/xosHelpers/spec/ui/smart-pie.test.js b/views/ngXosLib/xosHelpers/spec/ui/smart-pie.test.js
index 4c90421..2b3476a 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/smart-pie.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/smart-pie.test.js
@@ -23,8 +23,7 @@
 
   describe('The xos.helper module', function(){
     describe('The xos-smart-pie component', () => {
-
-
+      
       beforeEach(module('xos.helpers'));
 
       beforeEach(function(){
diff --git a/views/ngXosLib/xosHelpers/spec/ui/smart-table.test.js b/views/ngXosLib/xosHelpers/spec/ui/smart-table.test.js
index 09445ca..d579ce6 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/smart-table.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/smart-table.test.js
@@ -26,7 +26,7 @@
             last_name: 'Snow',
             hidden_field: 'hidden'
           }
-        ]
+        ];
 
         jasmine.addMatchers({
           toBeInstanceOf: function() {
diff --git a/views/ngXosLib/xosHelpers/spec/ui/table.test.js b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
index 1535c6e..321a476 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/table.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
@@ -48,7 +48,7 @@
         expect(errorFunctionWrapper).toThrow(new Error('[xosTable] Please provide a columns list in the configuration'));
       });
 
-      describe('when basicly configured', function() {
+      describe('when basically configured', function() {
 
         beforeEach(inject(function ($compile, $rootScope) {
 
@@ -124,15 +124,22 @@
                     label: 'Label 1',
                     prop: 'label-1',
                     type: 'boolean'
+                  },
+                  {
+                    label: 'Label 2',
+                    prop: 'label-2',
+                    type: 'boolean'
                   }
                 ]
               };
               scope.data = [
                 {
-                  'label-1': true
+                  'label-1': true,
+                  'label-2': 1
                 },
                 {
-                  'label-1': false
+                  'label-1': false,
+                  'label-2': 0
                 }
               ];
               compileElement();
@@ -156,6 +163,30 @@
                 expect(td1).toContainElement('select');
                 expect(td1).not.toContainElement('input');
               });
+
+              it('should correctly filter results', () => {
+                isolatedScope.query = {
+                  'label-1': false
+                };
+                scope.$digest();
+                expect(isolatedScope.query['label-1']).toBeFalsy();
+                var tr = $(element).find('tbody:last-child > tr');
+                var icon = $(tr[0]).find('td i');
+                expect(tr.length).toEqual(1);
+                expect(icon).toHaveClass('glyphicon-remove');
+              });
+
+              it('should correctly filter results if the field is in the form of 0|1', () => {
+                isolatedScope.query = {
+                  'label-2': false
+                };
+                scope.$digest();
+                expect(isolatedScope.query['label-1']).toBeFalsy();
+                var tr = $(element).find('tbody:last-child > tr');
+                var icon = $(tr[0]).find('td i');
+                expect(tr.length).toEqual(1);
+                expect(icon).toHaveClass('glyphicon-remove');
+              });
             });
           });
 
@@ -190,6 +221,7 @@
                 {categories: ['Film', 'Music']}
               ];
               scope.config = {
+                filter: 'field',
                 columns: [
                   {
                     label: 'Categories',
@@ -201,9 +233,14 @@
               compileElement();
             });
             it('should render a comma separated list', () => {
-              let td1 = $(element).find('tbody tr:first-child')[0];
+              let td1 = $(element).find('tbody:last-child tr:first-child')[0];
               expect($(td1).text().trim()).toEqual('Film, Music');
             });
+
+            it('should not render the filter field', () => {
+              let filter = $(element).find('tbody tr td')[0];
+              expect($(filter)).not.toContainElement('input');
+            });
           });
 
           describe('and is object', () => {
@@ -217,6 +254,7 @@
                 }
               ];
               scope.config = {
+                filter: 'field',
                 columns: [
                   {
                     label: 'Categories',
@@ -228,7 +266,7 @@
               compileElement();
             });
             it('should render a list of key-values', () => {
-              let td = $(element).find('tbody tr:first-child')[0];
+              let td = $(element).find('tbody:last-child tr:first-child')[0];
               let ageLabel = $(td).find('dl dt')[0];
               let ageValue = $(td).find('dl dd')[0];
               let heightLabel = $(td).find('dl dt')[1];
@@ -238,6 +276,11 @@
               expect($(heightLabel).text().trim()).toEqual('height');
               expect($(heightValue).text().trim()).toEqual('50');
             });
+
+            it('should not render the filter field', () => {
+              let filter = $(element).find('tbody tr td')[0];
+              expect($(filter)).not.toContainElement('input');
+            });
           });
 
           describe('and is custom', () => {
diff --git a/views/ngXosLib/xosHelpers/spec/ui/validation.test.js b/views/ngXosLib/xosHelpers/spec/ui/validation.test.js
index f8350ed..1029f2d 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/validation.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/validation.test.js
@@ -15,7 +15,7 @@
     if(!scope){
       scope = rootScope.$new();
     }
-    if(!angular.isDefined(element)){
+    if(angular.isUndefined(element)){
       element = angular.element('<xos-validation field="field" form="form"></xos-validation>');
     }
     compile(element)(scope);
diff --git a/views/ngXosLib/xosHelpers/src/services/helpers/ui/comparator.service.js b/views/ngXosLib/xosHelpers/src/services/helpers/ui/comparator.service.js
new file mode 100644
index 0000000..77e6210
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/services/helpers/ui/comparator.service.js
@@ -0,0 +1,96 @@
+(function() {
+  'use strict';
+
+  /**
+   * @ngdoc service
+   * @name xos.uiComponents.Comparator
+   * @description
+   * This factory define a function that replace the native angular.filter comparator.
+   *
+   * It is done to allow the comparation between (0|1) values with booleans.
+   * >Note that this factory return a single function, not an object.
+   *
+   * The tipical usage of this factory is inside an `ng-repeat`
+   * @example
+   * <example module="comparator">
+   *   <file name="index.html">
+   *     <div ng-controller="sample as vm">
+   *       <div class="row">
+   *         <div class="col-xs-6">
+   *           <label>Filter by name:</label>
+   *           <input class="form-control" type="text" ng-model="vm.query.name"/>
+   *         </div>
+   *         <div class="col-xs-6">
+   *           <label>Filter by status:</label>
+   *           <select
+   *            ng-model="vm.query.status"
+   *            ng-options="i for i in [true, false]">
+   *           </select>
+   *         </div>
+   *       </div>
+   *       <div ng-repeat="item in vm.data | filter:vm.query:vm.comparator">
+   *         <div class="row">
+   *           <div class="col-xs-6">{{item.name}}</div>
+   *           <div class="col-xs-6">{{item.status}}</div>
+   *         </div>
+   *       </div>
+   *     </div>
+   *   </file>
+   *   <file name="script.js">
+   *     angular.module('comparator', ['xos.uiComponents'])
+   *     .controller('sample', function(Comparator){
+   *       this.comparator = Comparator;
+   *       this.data = [
+   *         {name: 'Jhon', status: 1},
+   *         {name: 'Jack', status: 0},
+   *         {name: 'Mike', status: 1},
+   *         {name: 'Scott', status: 0}
+   *       ];
+   *     });
+   *   </file>
+   * </example>
+   **/
+
+  angular
+    .module('xos.uiComponents')
+    .factory('Comparator', comparator);
+
+  function comparator() {
+
+    return function(actual, expected){
+
+      if (angular.isUndefined(actual)) {
+        // No substring matching against `undefined`
+        return false;
+      }
+      if ((actual === null) || (expected === null)) {
+        // No substring matching against `null`; only match against `null`
+        return actual === expected;
+      }
+      if (angular.isObject(expected) || (angular.isObject(actual))){
+        return angular.equals(expected, actual);
+      }
+
+      if(_.isBoolean(actual) || _.isBoolean(expected)){
+        if(actual === 0 || actual === 1){
+          actual = !!actual;
+        }
+        return angular.equals(expected, actual);
+      }
+
+      if(!angular.isString(actual) || !angular.isString(expected)){
+        if(angular.isDefined(actual.toString) && angular.isDefined(expected.toString)){
+          actual = actual.toString();
+          expected = expected.toString();
+        }
+        else {
+          return actual === expected;
+        }
+      }
+
+      actual = actual.toLowerCase() + '';
+      expected = expected.toLowerCase() + '';
+      return actual.indexOf(expected) !== -1;
+    };
+  }
+})();
diff --git a/views/ngXosLib/xosHelpers/src/services/helpers/ui/form.helpers.js b/views/ngXosLib/xosHelpers/src/services/helpers/ui/form.helpers.js
index bc6a503..0a9d3ec 100644
--- a/views/ngXosLib/xosHelpers/src/services/helpers/ui/form.helpers.js
+++ b/views/ngXosLib/xosHelpers/src/services/helpers/ui/form.helpers.js
@@ -60,7 +60,7 @@
       }
 
       // if null return string
-      if(typeof value === 'string' || value === null){
+      if(angular.isString(value) || value === null){
         return 'text';
       }
 
diff --git a/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js b/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js
index 27edf7f..7bf8ae1 100644
--- a/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js
+++ b/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js
@@ -23,7 +23,7 @@
 
   .service('XosUserPrefs', function($cookies){
 
-    let userPrefs = $cookies.get('xosUserPrefs') ? JSON.parse($cookies.get('xosUserPrefs')) : {};
+    let userPrefs = $cookies.get('xosUserPrefs') ? angular.fromJson($cookies.get('xosUserPrefs')) : {};
 
     /**
     * @ngdoc method
@@ -34,7 +34,7 @@
     * @returns {object} The user preferences
     **/
     this.getAll = () => {
-      userPrefs = $cookies.get('xosUserPrefs') ? JSON.parse($cookies.get('xosUserPrefs')) : {};
+      userPrefs = $cookies.get('xosUserPrefs') ? angular.fromJson($cookies.get('xosUserPrefs')) : {};
       return userPrefs;
     };
 
@@ -47,7 +47,7 @@
     * @param {object} prefs The user preferences
     **/
     this.setAll = (prefs) => {
-      $cookies.put('xosUserPrefs', JSON.stringify(prefs));
+      $cookies.put('xosUserPrefs', angular.toJson(prefs));
     };
 
     /**
diff --git a/views/ngXosLib/xosHelpers/src/services/log.decorator.js b/views/ngXosLib/xosHelpers/src/services/log.decorator.js
index b8c5297..e6bd621 100644
--- a/views/ngXosLib/xosHelpers/src/services/log.decorator.js
+++ b/views/ngXosLib/xosHelpers/src/services/log.decorator.js
@@ -1,5 +1,7 @@
 // TODO write tests for log
 
+/* eslint-disable  angular/ng_window_service*/
+
 angular.module('xos.helpers')
 .config([ '$provide', function( $provide )
 {
@@ -11,7 +13,7 @@
 
     const isLogEnabled = () => {
       return window.location.href.indexOf('debug=true') >= 0;
-    }
+    };
     // Save the original $log.debug()
     let logFn = $delegate.log;
     let infoFn = $delegate.info;
@@ -34,7 +36,7 @@
         args[0] = `[${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}] ${args[0]}`;
 
         // HACK awfull fix for angular mock implementation whithin jasmine test failing issue
-        if (typeof $delegate.reset === 'function' && !($delegate.debug.logs instanceof Array)) {
+        if (angular.isFunction($delegate.reset) && !($delegate.debug.logs instanceof Array)) {
           // if we are within the mock and did not reset yet, we call it to avoid issue
           // console.log('mock log impl fix to avoid logs array not existing...');
           $delegate.reset();
diff --git a/views/ngXosLib/xosHelpers/src/services/notification.service.js b/views/ngXosLib/xosHelpers/src/services/notification.service.js
index e190451..9a1598e 100644
--- a/views/ngXosLib/xosHelpers/src/services/notification.service.js
+++ b/views/ngXosLib/xosHelpers/src/services/notification.service.js
@@ -1,3 +1,4 @@
+/* eslint-disable  angular/ng_window_service*/
 (function() {
   'use strict';
 
diff --git a/views/ngXosLib/xosHelpers/src/services/rest/Images.js b/views/ngXosLib/xosHelpers/src/services/rest/Images.js
new file mode 100644
index 0000000..4fe9cb3
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/services/rest/Images.js
@@ -0,0 +1,15 @@
+(function() {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Images
+  * @description Angular resource to fetch /api/core/images/
+  **/
+  .service('Images', function($resource){
+    return $resource('/api/core/images/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  })
+})();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/src/styles/loader.scss b/views/ngXosLib/xosHelpers/src/styles/loader.scss
new file mode 100644
index 0000000..66297df
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/styles/loader.scss
@@ -0,0 +1,51 @@
+.loader {
+  font-size: 10px;
+  margin: 0 auto;
+  text-indent: -9999em;
+  width: 11em;
+  height: 11em;
+  border-radius: 50%;
+  background: #ffffff;
+  background: -moz-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+  background: -webkit-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+  background: -o-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+  background: -ms-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+  background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+  position: relative;
+  animation: loaderSpinner 1.4s infinite linear;
+  transform: translateZ(0);
+}
+.loader:before {
+  width: 50%;
+  height: 50%;
+  background: $brand-primary;
+  border-radius: 100% 0 0 0;
+  position: absolute;
+  top: 0;
+  left: 0;
+  content: '';
+}
+.loader:after {
+  background: #fff;
+  width: 75%;
+  height: 75%;
+  border-radius: 50%;
+  content: '';
+  margin: auto;
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+}
+
+@keyframes loaderSpinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/src/styles/main.scss b/views/ngXosLib/xosHelpers/src/styles/main.scss
index cc02e6f..5768ad0 100644
--- a/views/ngXosLib/xosHelpers/src/styles/main.scss
+++ b/views/ngXosLib/xosHelpers/src/styles/main.scss
@@ -1,10 +1,12 @@
 @import './animations.scss';
 @import '../../../../../views/style/sass/bootstrap/bootstrap/_variables.scss';
+@import './loader.scss';
 
 @import '../ui_components/dumbComponents/table/table.scss';
 @import '../ui_components/dumbComponents/alert/alert.scss';
 @import '../ui_components/dumbComponents/validation/validation.scss';
 @import '../ui_components/dumbComponents/field/field.scss';
+@import '../ui_components/dumbComponents/form/form.scss';
 
 @import '../ui_components/smartComponents/smartTable/smartTable.scss';
 
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/alert/alert.scss b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/alert/alert.scss
index f1330fe..f031ba6 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/alert/alert.scss
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/alert/alert.scss
@@ -1,6 +1,8 @@
 @import '../../../styles/animations.scss';
 
 xos-alert {
+  margin-top: $form-group-margin-bottom;
+  display: block;
 
   /* when hiding */
   .ng-hide-add         { animation:0.5s fadeOutDown ease-in-out; }
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.component.js b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.component.js
index 686dd38..2719bb3 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.component.js
@@ -153,6 +153,7 @@
       template: `
         <label ng-if="vm.field.type !== 'object'">{{vm.field.label}}</label>
             <input
+              xos-custom-validator custom-validator="vm.field.validators.custom || null"
               ng-if="vm.field.type !== 'boolean' && vm.field.type !== 'object' && vm.field.type !== 'select'"
               type="{{vm.field.type}}"
               name="{{vm.name}}"
@@ -163,23 +164,23 @@
               ng-required="vm.field.validators.required || false" />
               <select class="form-control" ng-if ="vm.field.type === 'select'"
                 name = "{{vm.name}}"
-                ng-options="item.id as item.label for item in vm.field.options track by item.id"
+                ng-options="item.id as item.label for item in vm.field.options"
                 ng-model="vm.ngModel"
                 ng-required="vm.field.validators.required || false">
                 </select>
             <span class="boolean-field" ng-if="vm.field.type === 'boolean'">
-              <button
+              <a href="#"
                 class="btn btn-success"
                 ng-show="vm.ngModel"
                 ng-click="vm.ngModel = false">
                 <i class="glyphicon glyphicon-ok"></i>
-              </button>
-              <button
+              </a>
+              <a href="#"
                 class="btn btn-danger"
                 ng-show="!vm.ngModel"
                 ng-click="vm.ngModel = true">
                 <i class="glyphicon glyphicon-remove"></i>
-              </button>
+              </a>
             </span>
             <div
               class="panel panel-default object-field"
@@ -228,12 +229,51 @@
         if(!$attrs.ngModel){
           throw new Error('[xosField] Please provide an ng-model');
         }
-
         this.getType = XosFormHelpers._getFieldFormat;
         this.formatLabel = LabelFormatter.format;
 
         this.isEmptyObject = o => o ? Object.keys(o).length === 0 : true;
       }
     }
+  })
+
+/**
+ * @ngdoc directive
+ * @name xos.uiComponents.directive:xosCustomValidator
+ * @restrict A
+ * @description The xosCustomValidator directive.
+ * This component apply a custom validation function
+ * @param {function} customValidator The function that execute the validation.
+ *
+ * You should do your validation here and return true | false,
+ * or alternatively you can return an array [errorName, true|false]
+ */
+  .directive('xosCustomValidator', function(){
+    return {
+      restrict: 'A',
+      scope: {
+        fn: '=customValidator'
+      },
+      require: 'ngModel',
+      link: function(scope, element, attr, ctrl){
+        if(!angular.isFunction(scope.fn)){
+          return;
+        }
+
+        function customValidatorWrapper(ngModelValue) {
+          const valid = scope.fn(ngModelValue);
+          if(angular.isArray(valid)){
+            // ES6 spread rocks over fn.apply()
+            ctrl.$setValidity(...valid);
+          }
+          else{
+            ctrl.$setValidity('customValidation', valid);
+          }
+          return ngModelValue;
+        }
+
+        ctrl.$parsers.push(customValidatorWrapper);
+      }
+    };
   });
 })();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.component.js b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.component.js
index 2a9f00c..89ef192 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.component.js
@@ -32,16 +32,25 @@
             class: 'success'
           }
     *   ],
+    *   feedback: {
+          show: false,
+          message: 'Form submitted successfully !!!',
+          type: 'success'  //refers to bootstrap class
+        },
     *   fields: {
     *     field_name: {
     *       label: 'Field Label',
-    *       type: 'string' // options are: [date, boolean, number, email, string],
+    *       type: 'string' // options are: [date, boolean, number, email, string, select],
     *       validators: {
-    *         minlength: number,
+    *               minlength: number,
               maxlength: number,
               required: boolean,
               min: number,
-              max: number
+              max: number,
+              custom: (value) => {
+                // do your validation here and return true | false
+                // alternatively you can return an array [errorName, true|false]
+              }
     *       }
     *     }
     *   }
@@ -97,23 +106,32 @@
 
   <example module="sampleForm1">
     <file name="script.js">
-      angular.module('sampleForm1', ['xos.uiComponents'])
+      angular.module('sampleForm1', ['xos.uiComponents','ngResource', 'ngMockE2E'])
       .factory('_', function($window){
         return $window._;
       })
-      .controller('SampleCtrl1', function(){
+      .controller('SampleCtrl1', function(SampleResource){
+
+
         this.model = {
         };
 
         this.config = {
           exclude: ['password', 'last_login'],
           formName: 'sampleForm1',
+          feedback: {
+            show: false,
+            message: 'Form submitted successfully !!!',
+            type: 'success'
+          },
           actions: [
             {
               label: 'Save',
               icon: 'ok', // refers to bootstraps glyphicon
               cb: (user) => { // receive the model
                 console.log(user);
+                this.config.feedback.show = true;
+                this.config.feedback.type='success';
               },
               class: 'success'
             }
@@ -140,9 +158,42 @@
                 min: 21
               }
             },
-          }
+
+            site: {
+            label: 'Site',
+            type: 'select',
+            validators: { required: true},
+            hint: 'The Site this Slice belongs to',
+            options: []
+            },
+         }
         };
+        SampleResource.query().$promise
+          .then((users) => {
+          //this.users_site = users;
+        //console.log(users);
+          this.optionVal = users;
+          this.config.fields['site'].options = this.optionVal;
+        //= this.optionVal;
+
+      })
+      .catch((e) => {
+        throw new Error(e);
       });
+
+      });
+    </file>
+   <file name="backend.js">
+     angular.module('sampleForm1')
+     .run(function($httpBackend, _){
+        let datas = [{id: 1, label: 'site1'},{id: 4, label: 'site4'},{id: 3, label: 'site3'}];
+        let paramsUrl = new RegExp(/\/test\/(.+)/);
+        $httpBackend.whenGET('/test').respond(200, datas)
+      })
+      .service('SampleResource', function($resource){
+        return $resource('/test/:id', {id: '@id'});
+      });
+
     </file>
     <file name="index.html">
       <div ng-controller="SampleCtrl1 as vm">
@@ -161,22 +212,25 @@
         ngModel: '='
       },
       template: `
-        <ng-form name="vm.{{vm.config.formName || 'form'}}">
+        <form name="vm.{{vm.config.formName || 'form'}}" novalidate>
           <div class="form-group" ng-repeat="(name, field) in vm.formField">
             <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>
-            <xos-validation field="vm[vm.config.formName || 'form'][name]" form="vm[vm.config.formName || 'form']"></xos-validation>
+            <xos-validation field="vm[vm.config.formName || 'form'][name]" form = "vm[vm.config.formName || 'form']"></xos-validation>
+            <div class="alert alert-info" ng-show="(field.hint).length >0" role="alert">{{field.hint}}</div>
           </div>
           <div class="form-group" ng-if="vm.config.actions">
+          <xos-alert config="vm.config.feedback" show="vm.config.feedback.show">{{vm.config.feedback.message}}</xos-alert>
+
             <button role="button" href=""
               ng-repeat="action in vm.config.actions"
-              ng-click="action.cb(vm.ngModel)"
+              ng-click="action.cb(vm.ngModel, vm[vm.config.formName || 'form'])"
               class="btn btn-{{action.class}}"
               title="{{action.label}}">
               <i class="glyphicon glyphicon-{{action.icon}}"></i>
               {{action.label}}
             </button>
           </div>
-        </ng-form>
+        </form>
       `,
       bindToController: true,
       controllerAs: 'vm',
@@ -190,22 +244,36 @@
           throw new Error('[xosForm] Please provide an action list in the configuration');
         }
 
+        if(!this.config.feedback){
+          this.config.feedback =  {
+            show: false,
+            message: 'Form submitted successfully !!!',
+            type: 'success'
+          }
+        }
+
         this.excludedField = ['id', 'validators', 'created', 'updated', 'deleted', 'backend_status'];
         if(this.config && this.config.exclude){
           this.excludedField = this.excludedField.concat(this.config.exclude);
         }
 
-
         this.formField = [];
-        $scope.$watch(() => this.ngModel, (model) => {
 
+        $scope.$watch(() => this.config, ()=> {
+          if(!this.ngModel){
+            return;
+          }
+          let diff = _.difference(Object.keys(this.ngModel), this.excludedField);
+          let modelField = XosFormHelpers.parseModelField(diff);
+          this.formField = XosFormHelpers.buildFormStructure(modelField, this.config.fields, this.ngModel);
+        }, true);
+
+        $scope.$watch(() => this.ngModel, (model) => {
           // empty from old stuff
           this.formField = {};
-
           if(!model){
             return;
           }
-
           let diff = _.difference(Object.keys(model), this.excludedField);
           let modelField = XosFormHelpers.parseModelField(diff);
           this.formField = XosFormHelpers.buildFormStructure(modelField, this.config.fields, model);
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.scss b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.scss
new file mode 100644
index 0000000..b61f8e2
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.scss
@@ -0,0 +1,8 @@
+@import '../../../styles/animations.scss';
+@import '../../../../../../style/sass/bootstrap/bootstrap/_variables.scss';
+
+xos-form {
+  button {
+    margin-bottom: $form-group-margin-bottom;
+  }
+}
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.component.js b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.component.js
index 04671ba..94e2ab3 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.component.js
@@ -338,7 +338,7 @@
           config: '='
         },
         template: `
-          <div ng-show="vm.data.length > 0">
+          <div ng-show="vm.data.length > 0 && vm.loader == false">
             <div class="row" ng-if="vm.config.filter == 'fulltext'">
               <div class="col-xs-12">
                 <input
@@ -369,7 +369,7 @@
                 <tr>
                   <td ng-repeat="col in vm.columns">
                     <input
-                      ng-if="col.type !== 'boolean'"
+                      ng-if="col.type !== 'boolean' && col.type !== 'array' && col.type !== 'object'"
                       class="form-control"
                       placeholder="Type to search by {{col.label}}"
                       type="text"
@@ -387,8 +387,8 @@
                 </tr>
               </tbody>
               <tbody>
-                <tr ng-repeat="item in vm.data | filter:vm.query | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">
-                  <td ng-repeat="col in vm.columns" link-wrapper>
+                <tr ng-repeat="item in vm.data | filter:vm.query:vm.comparator | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">
+                  <td ng-repeat="col in vm.columns" xos-link-wrapper>
                     <span ng-if="!col.type">{{item[col.prop]}}</span>
                     <span ng-if="col.type === 'boolean'">
                       <i class="glyphicon"
@@ -437,15 +437,28 @@
               change="vm.goToPage">
               </xos-pagination>
           </div>
-          <div ng-show="vm.data.length == 0 || !vm.data">
+          <div ng-show="(vm.data.length == 0 || !vm.data) && vm.loader == false">
              <xos-alert config="{type: 'info'}">
               No data to show.
             </xos-alert>
           </div>
+          <div ng-show="vm.loader == true">
+            <div class="loader"></div>
+          </div>
         `,
         bindToController: true,
         controllerAs: 'vm',
-        controller: function(_){
+        controller: function(_, $scope, Comparator){
+
+          this.comparator = Comparator;
+
+          this.loader = true;
+
+          $scope.$watch(() => this.data, data => {
+            if(angular.isDefined(data)){
+              this.loader = false;
+            }
+          });
 
           if(!this.config){
             throw new Error('[xosTable] Please provide a configuration via the "config" attribute');
@@ -521,7 +534,7 @@
       }
     })
     // TODO test
-    .directive('linkWrapper', function() {
+    .directive('xosLinkWrapper', function() {
       return {
         restrict: 'A',
         transclude: true,
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.component.js b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.component.js
index 27b1ef6..622952f 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.component.js
@@ -218,6 +218,7 @@
           .then((res) => {
 
             if(!res[0]){
+              this.data = res;
               return;
             }
 
@@ -241,7 +242,7 @@
                 prop: p
               };
 
-              if(typeof item[p] !== 'string' && typeof item[p] !== 'undefined'){
+              if(angular.isString(item[p]) && typeof item[p] !== 'undefined'){
                 fieldConfig.type = typeof item[p];
               }
 
diff --git a/views/ngXosLib/xosHelpers/src/xosHelpers.module.js b/views/ngXosLib/xosHelpers/src/xosHelpers.module.js
index fe246a6..3d534b9 100644
--- a/views/ngXosLib/xosHelpers/src/xosHelpers.module.js
+++ b/views/ngXosLib/xosHelpers/src/xosHelpers.module.js
@@ -1,6 +1,8 @@
 (function() {
   'use strict';
-  
+
+  /* eslint-disable angular/ng_module_name */
+
   angular.module('bugSnag', []).factory('$exceptionHandler', function () {
     return function (exception, cause) {
       if( window.Bugsnag ){
@@ -12,6 +14,8 @@
     };
   });
 
+  /* eslint-enable angular/ng_module_name */
+
   /**
   * @ngdoc overview
   * @name xos.helpers
diff --git a/views/ngXosViews/tenant/.bowerrc b/views/ngXosViews/tenant/.bowerrc
new file mode 100644
index 0000000..e491038
--- /dev/null
+++ b/views/ngXosViews/tenant/.bowerrc
@@ -0,0 +1,3 @@
+{
+  "directory": "src/vendor/"
+}
\ No newline at end of file
diff --git a/views/ngXosViews/tenant/.eslintrc b/views/ngXosViews/tenant/.eslintrc
new file mode 100644
index 0000000..f9a952f
--- /dev/null
+++ b/views/ngXosViews/tenant/.eslintrc
@@ -0,0 +1,42 @@
+{
+    "ecmaFeatures": {
+        "blockBindings": true,
+        "forOf": true,
+        "destructuring": true,
+        "arrowFunctions": true,
+        "templateStrings": true
+    },
+    "env": { 
+        "browser": true,
+        "node": true,
+        "es6": true
+    },
+    "plugins": [
+        //"angular"
+    ],
+    "rules": {
+        "quotes": [2, "single"],
+        "camelcase": [0, {"properties": "always"}],
+        "no-underscore-dangle": 1,
+        "eqeqeq": [2, "smart"],
+        "no-alert": 1,
+        "key-spacing": [1, { "beforeColon": false, "afterColon": true }],
+        "indent": [2, 2],
+        "no-irregular-whitespace": 1,
+        "eol-last": 0,
+        "max-nested-callbacks": [2, 4],
+        "comma-spacing": [1, {"before": false, "after": true}],
+        "no-trailing-spaces": [1, { skipBlankLines: true }],
+        "no-unused-vars": [1, {"vars": "all", "args": "after-used"}],
+        "new-cap": 0,
+
+        //"angular/ng_module_name": [2, '/^xos\.*[a-z]*$/'],
+        //"angular/ng_controller_name": [2, '/^[a-z].*Ctrl$/'],
+        //"angular/ng_service_name": [2, '/^[A-Z].*Service$/'],
+        //"angular/ng_directive_name": [2, '/^[a-z]+[[A-Z].*]*$/'],
+        //"angular/ng_di": [0, "function or array"]
+    },
+    "globals" :{
+        "angular": true
+    } 
+}
\ No newline at end of file
diff --git a/views/ngXosViews/tenant/.gitignore b/views/ngXosViews/tenant/.gitignore
new file mode 100644
index 0000000..567aee4
--- /dev/null
+++ b/views/ngXosViews/tenant/.gitignore
@@ -0,0 +1,6 @@
+dist/
+src/vendor
+.tmp
+node_modules
+npm-debug.log
+dist/
\ No newline at end of file
diff --git a/views/ngXosViews/tenant/bower.json b/views/ngXosViews/tenant/bower.json
new file mode 100644
index 0000000..c37483b
--- /dev/null
+++ b/views/ngXosViews/tenant/bower.json
@@ -0,0 +1,32 @@
+{
+  "name": "xos-tenant",
+  "version": "0.0.0",
+  "authors": [
+    " <>"
+  ],
+  "description": "The tenant view",
+  "license": "MIT",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "static/js/vendor/",
+    "test",
+    "tests"
+  ],
+  "dependencies": {},
+  "devDependencies": {
+    "jquery": "2.1.4",
+    "angular-mocks": "1.4.7",
+    "angular": "1.4.7",
+    "angular-ui-router": "0.2.15",
+    "angular-cookies": "1.4.7",
+    "angular-animate": "1.4.7",
+    "angular-resource": "1.4.7",
+    "lodash": "~4.11.1",
+    "bootstrap-css": "3.3.6",
+    "angular-chart.js": "~0.10.2",
+    "d3": "~3.5.17",
+    "angular-recursion": "^1.0.5"
+  }
+}
diff --git a/views/ngXosViews/tenant/env/default.js b/views/ngXosViews/tenant/env/default.js
new file mode 100644
index 0000000..e8b1522
--- /dev/null
+++ b/views/ngXosViews/tenant/env/default.js
@@ -0,0 +1,13 @@
+// This is a default configuration for your development environment.
+// You can duplicate this configuration for any of your Backend Environments.
+// Different configurations are loaded setting a NODE_ENV variable that contain the config file name.
+// `NODE_ENV=local npm start`
+//
+// If xoscsrftoken or xossessionid are not specified the browser value are used
+// (works only for local environment as both application are served on the same domain)
+
+module.exports = {
+  host: 'http://xos.dev:9999',
+  xoscsrftoken: 'FIdWwEI8XNESlpH3Wr6Hu5ORJs2EkIYl',
+  xossessionid: 'six66atpd31hh0b131zh9bc05t6f77d4'
+};
diff --git a/views/ngXosViews/tenant/gulp/build.js b/views/ngXosViews/tenant/gulp/build.js
new file mode 100644
index 0000000..8a7b279
--- /dev/null
+++ b/views/ngXosViews/tenant/gulp/build.js
@@ -0,0 +1,164 @@
+'use strict';
+
+// BUILD
+//
+// The only purpose of this gulpfile is to build a XOS view and copy the correct files into
+// .html => dashboards
+// .js (minified and concat) => static/js
+//
+// The template are parsed and added to js with angular $templateCache
+
+var gulp = require('gulp');
+var ngAnnotate = require('gulp-ng-annotate');
+var uglify = require('gulp-uglify');
+var templateCache = require('gulp-angular-templatecache');
+var runSequence = require('run-sequence');
+var concat = require('gulp-concat-util');
+var del = require('del');
+var wiredep = require('wiredep');
+var angularFilesort = require('gulp-angular-filesort');
+var _ = require('lodash');
+var eslint = require('gulp-eslint');
+var inject = require('gulp-inject');
+var rename = require('gulp-rename');
+var replace = require('gulp-replace');
+var postcss = require('gulp-postcss');
+var autoprefixer = require('autoprefixer');
+var mqpacker = require('css-mqpacker');
+var csswring = require('csswring');
+
+const TEMPLATE_FOOTER = `
+angular.module('xos.tenant')
+.run(['$location', function(a){
+  a.path('/');
+}])
+`
+
+module.exports = function(options){
+  
+  // delete previous builded file
+  gulp.task('clean', function(){
+    return del(
+      [
+        options.dashboards + 'xosTenant.html',
+        options.static + 'css/xosTenant.css'
+      ],
+      {force: true}
+    );
+  });
+
+  // minify css
+  gulp.task('css', function () {
+    var processors = [
+      autoprefixer({browsers: ['last 1 version']}),
+      mqpacker,
+      csswring
+    ];
+
+    gulp.src([
+      `${options.css}**/*.css`,
+      `!${options.css}dev.css`
+    ])
+    .pipe(postcss(processors))
+    .pipe(gulp.dest(options.tmp + '/css/'));
+  });
+
+  // copy css in correct folder
+  gulp.task('copyCss', ['wait'], function(){
+    return gulp.src([`${options.tmp}/css/*.css`])
+    .pipe(concat('xosTenant.css'))
+    .pipe(gulp.dest(options.static + 'css/'))
+  });
+
+  // compile and minify scripts
+  gulp.task('scripts', function() {
+    return gulp.src([
+      options.tmp + '**/*.js'
+    ])
+    .pipe(ngAnnotate())
+    .pipe(angularFilesort())
+    .pipe(concat('xosTenant.js'))
+    .pipe(concat.header('//Autogenerated, do not edit!!!\n'))
+    .pipe(concat.footer(TEMPLATE_FOOTER))
+    .pipe(uglify())
+    .pipe(gulp.dest(options.static + 'js/'));
+  });
+
+  // set templates in cache
+  gulp.task('templates', function(){
+    return gulp.src('./src/templates/*.html')
+      .pipe(templateCache({
+        module: 'xos.tenant',
+        root: 'templates/'
+      }))
+      .pipe(gulp.dest(options.tmp));
+  });
+
+  // copy html index to Django Folder
+  gulp.task('copyHtml', function(){
+    return gulp.src(options.src + 'index.html')
+      // remove dev dependencies from html
+      .pipe(replace(/<!-- bower:css -->(\n^<link.*)*\n<!-- endbower -->/gmi, ''))
+      .pipe(replace(/<!-- bower:js -->(\n^<script.*)*\n<!-- endbower -->/gmi, ''))
+      // injecting minified files
+      .pipe(
+        inject(
+          gulp.src([
+            options.static + 'js/vendor/xosTenantVendor.js',
+            options.static + 'js/xosTenant.js',
+            options.static + 'css/xosTenant.css'
+          ]),
+          {ignorePath: '/../../../xos/core/xoslib'}
+        )
+      )
+      .pipe(rename('xosTenant.html'))
+      .pipe(gulp.dest(options.dashboards));
+  });
+
+  // minify vendor js files
+  gulp.task('wiredep', function(){
+    var bowerDeps = wiredep().js;
+    if(!bowerDeps){
+      return;
+    }
+
+    // remove angular (it's already loaded)
+    _.remove(bowerDeps, function(dep){
+      return dep.indexOf('angular/angular.js') !== -1;
+    });
+
+    return gulp.src(bowerDeps)
+      .pipe(concat('xosTenantVendor.js'))
+      .pipe(uglify())
+      .pipe(gulp.dest(options.static + 'js/vendor/'));
+  });
+
+  gulp.task('lint', function () {
+    return gulp.src(['src/js/**/*.js'])
+      .pipe(eslint())
+      .pipe(eslint.format())
+      .pipe(eslint.failAfterError());
+  });
+
+  gulp.task('wait', function (cb) {
+    // setTimeout could be any async task
+    setTimeout(function () {
+      cb();
+    }, 1000);
+  });
+
+  gulp.task('build', function() {
+    runSequence(
+      'clean',
+      'sass',
+      'templates',
+      'babel',
+      'scripts',
+      'wiredep',
+      'css',
+      'copyCss',
+      'copyHtml',
+      'cleanTmp'
+    );
+  });
+};
\ No newline at end of file
diff --git a/views/ngXosViews/tenant/gulp/server.js b/views/ngXosViews/tenant/gulp/server.js
new file mode 100644
index 0000000..c1f7608
--- /dev/null
+++ b/views/ngXosViews/tenant/gulp/server.js
@@ -0,0 +1,168 @@
+'use strict';
+
+var gulp = require('gulp');
+var browserSync = require('browser-sync').create();
+var inject = require('gulp-inject');
+var runSequence = require('run-sequence');
+var angularFilesort = require('gulp-angular-filesort');
+var babel = require('gulp-babel');
+var wiredep = require('wiredep').stream;
+var httpProxy = require('http-proxy');
+var del = require('del');
+var sass = require('gulp-sass');
+
+const environment = process.env.NODE_ENV;
+
+if (environment){
+  var conf = require(`../env/${environment}.js`);
+}
+else{
+  var conf = require('../env/default.js')
+}
+
+var proxy = httpProxy.createProxyServer({
+  target: conf.host || 'http://0.0.0.0:9999'
+});
+
+
+proxy.on('error', function(error, req, res) {
+  res.writeHead(500, {
+    'Content-Type': 'text/plain'
+  });
+
+  console.error('[Proxy]', error);
+});
+
+module.exports = function(options){
+
+  gulp.task('browser', function() {
+    browserSync.init({
+      startPath: '#/',
+      snippetOptions: {
+        rule: {
+          match: /<!-- browserSync -->/i
+        }
+      },
+      server: {
+        baseDir: options.src,
+        routes: {
+          '/xos/core/xoslib/static/js/vendor': options.helpers,
+          '/xos/core/static': options.static + '../../static/'
+        },
+        middleware: function(req, res, next){
+          if(
+            // to be removed, deprecated API
+            // req.url.indexOf('/xos/') !== -1 ||
+             req.url.indexOf('/xoslib/tenant') !== -1 ||
+            // req.url.indexOf('/hpcapi/') !== -1 ||
+            req.url.indexOf('/api/') !== -1
+          ){
+            if(conf.xoscsrftoken && conf.xossessionid){
+              req.headers.cookie = `xoscsrftoken=${conf.xoscsrftoken}; xossessionid=${conf.xossessionid}`;
+              req.headers['x-csrftoken'] = conf.xoscsrftoken;
+            }
+            proxy.web(req, res);
+          }
+          else{
+            next();
+          }
+        }
+      }
+    });
+
+    gulp.watch(options.src + 'js/**/*.js', ['js-watch']);
+    gulp.watch(options.src + 'vendor/**/*.js', ['bower'], function(){
+      browserSync.reload();
+    });
+    gulp.watch(options.src + '**/*.html', function(){
+      browserSync.reload();
+    });
+    gulp.watch(options.css + '**/*.css', function(){
+      browserSync.reload();
+    });
+    gulp.watch(`${options.sass}/**/*.scss`, ['sass'], function(){
+      browserSync.reload();
+    });
+
+    gulp.watch([
+      options.helpers + 'ngXosHelpers.js',
+      options.static + '../../static/xosNgLib.css'
+    ], function(){
+      browserSync.reload();
+    });
+  });
+
+  // compile sass
+  gulp.task('sass', function () {
+    return gulp.src(`${options.sass}/**/*.scss`)
+      .pipe(sass().on('error', sass.logError))
+      .pipe(gulp.dest(options.css));
+  });
+
+  // transpile js with sourceMaps
+  gulp.task('babel', function(){
+    return gulp.src(options.scripts + '**/*.js')
+      .pipe(babel({sourceMaps: true}))
+      .pipe(gulp.dest(options.tmp));
+  });
+
+  // inject scripts
+  gulp.task('injectScript', ['cleanTmp', 'babel'], function(){
+    return gulp.src(options.src + 'index.html')
+      .pipe(
+        inject(
+          gulp.src([
+            options.tmp + '**/*.js',
+            options.helpers + 'ngXosHelpers.js'
+          ])
+          .pipe(angularFilesort()),
+          {
+            ignorePath: [options.src, '/../../ngXosLib']
+          }
+        )
+      )
+      .pipe(gulp.dest(options.src));
+  });
+
+  // inject CSS
+  gulp.task('injectCss', function(){
+    return gulp.src(options.src + 'index.html')
+      .pipe(
+        inject(
+          gulp.src([
+            options.src + 'css/*.css',
+            options.static + '../../static/xosNgLib.css'
+          ]),
+          {
+            ignorePath: [options.src]
+          }
+          )
+        )
+      .pipe(gulp.dest(options.src));
+  });
+
+  // inject bower dependencies with wiredep
+  gulp.task('bower', function () {
+    return gulp.src(options.src + 'index.html')
+    .pipe(wiredep({devDependencies: true}))
+    .pipe(gulp.dest(options.src));
+  });
+
+  gulp.task('js-watch', ['injectScript'], function(){
+    browserSync.reload();
+  });
+
+  gulp.task('cleanTmp', function(){
+    return del([options.tmp + '**/*']);
+  });
+
+  gulp.task('serve', function() {
+    runSequence(
+      'sass',
+      'bower',
+      'injectScript',
+      'injectCss',
+      ['browser']
+    );
+  });
+};
diff --git a/views/ngXosViews/tenant/gulpfile.js b/views/ngXosViews/tenant/gulpfile.js
new file mode 100644
index 0000000..08df554
--- /dev/null
+++ b/views/ngXosViews/tenant/gulpfile.js
@@ -0,0 +1,26 @@
+'use strict';
+
+var gulp = require('gulp');
+var wrench = require('wrench');
+
+var options = {
+  src: 'src/',
+  css: 'src/css/',
+  sass: 'src/sass/',
+  scripts: 'src/js/',
+  tmp: 'src/.tmp',
+  dist: 'dist/',
+  api: '../../ngXosLib/api/',
+  helpers: '../../../xos/core/xoslib/static/js/vendor/',
+  static: '../../../xos/core/xoslib/static/', // this is the django static folder
+  dashboards: '../../../xos/core/xoslib/dashboards/' // this is the django html folder
+};
+
+wrench.readdirSyncRecursive('./gulp')
+.map(function(file) {
+  require('./gulp/' + file)(options);
+});
+
+gulp.task('default', function () {
+  gulp.start('build');
+});
diff --git a/views/ngXosViews/tenant/karma.conf.js b/views/ngXosViews/tenant/karma.conf.js
new file mode 100644
index 0000000..4123be9
--- /dev/null
+++ b/views/ngXosViews/tenant/karma.conf.js
@@ -0,0 +1,88 @@
+// Karma configuration
+// Generated on Tue Oct 06 2015 09:27:10 GMT+0000 (UTC)
+
+/* eslint indent: [2,2], quotes: [2, "single"]*/
+
+/*eslint-disable*/
+var wiredep = require('wiredep');
+var path = require('path');
+
+var bowerComponents = wiredep( {devDependencies: true} )[ 'js' ].map(function( file ){
+  return path.relative(process.cwd(), file);
+});
+
+module.exports = function(config) {
+/*eslint-enable*/
+  config.set({
+
+    // base path that will be used to resolve all patterns (eg. files, exclude)
+    basePath: '',
+
+
+    // frameworks to use
+    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+    frameworks: ['jasmine'],
+
+
+    // list of files / patterns to load in the browser
+    files: bowerComponents.concat([
+      '../../../xos/core/xoslib/static/js/vendor/ngXosVendor.js',
+      '../../../xos/core/xoslib/static/js/vendor/ngXosHelpers.js',
+      'src/js/**/*.js',
+      'spec/**/*.mock.js',
+      'spec/**/*.test.js',
+      'src/**/*.html'
+    ]),
+
+
+    // list of files to exclude
+    exclude: [
+    ],
+
+
+    // preprocess matching files before serving them to the browser
+    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+    preprocessors: {
+      'src/js/**/*.js': ['babel'],
+      'spec/**/*.test.js': ['babel'],
+      'src/**/*.html': ['ng-html2js']
+    },
+
+    ngHtml2JsPreprocessor: {
+      stripPrefix: 'src/', //strip the src path from template url (http://stackoverflow.com/questions/22869668/karma-unexpected-request-when-testing-angular-directive-even-with-ng-html2js)
+      moduleName: 'templates' // define the template module name
+    },
+
+    // test results reporter to use
+    // possible values: 'dots', 'progress'
+    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+    reporters: ['mocha'],
+
+
+    // web server port
+    port: 9876,
+
+
+    // enable / disable colors in the output (reporters and logs)
+    colors: true,
+
+
+    // level of logging
+    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+    logLevel: config.LOG_INFO,
+
+
+    // enable / disable watching file and executing tests whenever any file changes
+    autoWatch: true,
+
+
+    // start these browsers
+    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+    browsers: ['PhantomJS'],
+
+
+    // Continuous Integration mode
+    // if true, Karma captures browsers, runs the tests and exits
+    singleRun: false
+  });
+};
diff --git a/views/ngXosViews/tenant/package.json b/views/ngXosViews/tenant/package.json
new file mode 100644
index 0000000..ed04285
--- /dev/null
+++ b/views/ngXosViews/tenant/package.json
@@ -0,0 +1,63 @@
+{
+  "name": "xos-tenant",
+  "version": "1.0.0",
+  "description": "Angular Application for XOS, created with generator-xos",
+  "scripts": {
+    "prestart": "npm install && bower install",
+    "start": "gulp serve",
+    "prebuild": "npm install && bower install",
+    "build": "gulp",
+    "test": "karma start",
+    "test:ci": "karma start --single-run",
+    "lint": "eslint src/js/"
+  },
+  "keywords": [
+    "XOS",
+    "Angular",
+    "XOSlib"
+  ],
+  "author": "",
+  "license": "MIT",
+  "dependencies": {},
+  "devDependencies": {
+    "autoprefixer": "^6.3.3",
+    "browser-sync": "^2.9.11",
+    "css-mqpacker": "^4.0.0",
+    "csswring": "^4.2.1",
+    "del": "^2.0.2",
+    "easy-mocker": "^1.2.0",
+    "eslint": "^1.8.0",
+    "eslint-plugin-angular": "linkmesrl/eslint-plugin-angular",
+    "gulp": "^3.9.0",
+    "gulp-angular-filesort": "^1.1.1",
+    "gulp-angular-templatecache": "^1.8.0",
+    "gulp-babel": "^5.3.0",
+    "gulp-concat": "^2.6.0",
+    "gulp-concat-util": "^0.5.5",
+    "gulp-eslint": "^1.0.0",
+    "gulp-inject": "^3.0.0",
+    "gulp-minify-html": "^1.0.4",
+    "gulp-ng-annotate": "^1.1.0",
+    "gulp-postcss": "^6.0.1",
+    "gulp-rename": "^1.2.2",
+    "gulp-replace": "^0.5.4",
+    "gulp-sass": "^2.2.0",
+    "gulp-uglify": "^1.4.2",
+    "http-proxy": "^1.12.0",
+    "ink-docstrap": "^0.5.2",
+    "jasmine-core": "~2.3.4",
+    "karma": "^0.13.14",
+    "karma-babel-preprocessor": "~5.2.2",
+    "karma-coverage": "^0.5.3",
+    "karma-jasmine": "~0.3.6",
+    "karma-mocha-reporter": "~1.1.1",
+    "karma-ng-html2js-preprocessor": "^0.2.0",
+    "karma-phantomjs-launcher": "~0.2.1",
+    "lodash": "^3.10.1",
+    "phantomjs": "^1.9.19",
+    "proxy-middleware": "^0.15.0",
+    "run-sequence": "^1.1.4",
+    "wiredep": "^3.0.0-beta",
+    "wrench": "^1.5.8"
+  }
+}
diff --git a/views/ngXosViews/tenant/spec/sample.test.js b/views/ngXosViews/tenant/spec/sample.test.js
new file mode 100644
index 0000000..bd0fd92
--- /dev/null
+++ b/views/ngXosViews/tenant/spec/sample.test.js
@@ -0,0 +1,54 @@
+'use strict';
+
+describe('Tenant View', () => {
+  
+  var scope, element, isolatedScope, httpBackend;
+
+  beforeEach(module('xos.tenant'));
+  beforeEach(module('templates'));
+
+  beforeEach(inject(function($httpBackend, $compile, $rootScope){
+    
+    httpBackend = $httpBackend;
+    // Setting up mock request
+    scope = $rootScope.$new();
+    element = angular.element('<users-list></users-list>');
+    $compile(element)(scope);
+    scope.$digest();
+    isolatedScope = element.isolateScope().vm;
+  }));
+describe('site list table',() =>{
+  it('site list ', () => {
+    var sites = [
+      {
+        'name':'Mysite',
+        'id':'1'
+
+      }];
+    var slices = [{
+      'site':'1',
+      'instance_total':1,
+      'instance_total_ready':1
+    },
+      {
+      'site':'1',
+      'instance_total':2,
+      'instance_total_ready':3
+    },
+      {
+      'site':'2',
+      'instance_total':'1',
+      'instance_total_ready':'2'
+    }];
+    var result = isolatedScope.returnData(sites,slices);
+    expect(result).toEqual([{
+      'name':'Mysite',
+      'id':'1',
+      'instance_total':3,
+      'instance_total_ready':4
+    }
+])
+//httpBackend.flush();
+  });
+});
+});
\ No newline at end of file
diff --git a/views/ngXosViews/tenant/src/css/main.css b/views/ngXosViews/tenant/src/css/main.css
new file mode 100644
index 0000000..a22d515
--- /dev/null
+++ b/views/ngXosViews/tenant/src/css/main.css
@@ -0,0 +1,2 @@
+#xosTenant a {
+  margin-bottom: 15px; }
diff --git a/views/ngXosViews/tenant/src/index.html b/views/ngXosViews/tenant/src/index.html
new file mode 100644
index 0000000..e1a83d4
--- /dev/null
+++ b/views/ngXosViews/tenant/src/index.html
@@ -0,0 +1,36 @@
+<!-- browserSync -->
+<!-- bower:css -->
+<link rel="stylesheet" href="vendor/bootstrap-css/css/bootstrap.min.css" />
+<link rel="stylesheet" href="vendor/angular-chart.js/dist/angular-chart.css" />
+<!-- endbower -->
+<!-- endcss -->
+<!-- inject:css -->
+<link rel="stylesheet" href="/css/main.css">
+<link rel="stylesheet" href="/../../../xos/core/static/xosNgLib.css">
+<!-- endinject -->
+
+
+<div ng-app="xos.tenant" id="xosTenant" class="container-fluid">
+   <div ui-view></div>
+</div>
+
+<!-- bower:js -->
+<script src="vendor/jquery/dist/jquery.js"></script>
+<script src="vendor/angular/angular.js"></script>
+<script src="vendor/angular-mocks/angular-mocks.js"></script>
+<script src="vendor/angular-ui-router/release/angular-ui-router.js"></script>
+<script src="vendor/angular-cookies/angular-cookies.js"></script>
+<script src="vendor/angular-animate/angular-animate.js"></script>
+<script src="vendor/angular-resource/angular-resource.js"></script>
+<script src="vendor/lodash/lodash.js"></script>
+<script src="vendor/bootstrap-css/js/bootstrap.min.js"></script>
+<script src="vendor/Chart.js/Chart.js"></script>
+<script src="vendor/angular-chart.js/dist/angular-chart.js"></script>
+<script src="vendor/d3/d3.js"></script>
+<script src="vendor/angular-recursion/angular-recursion.js"></script>
+<!-- endbower -->
+<!-- endjs -->
+<!-- inject:js -->
+<script src="/../../../xos/core/xoslib/static/js/vendor/ngXosHelpers.js"></script>
+<script src="/.tmp/main.js"></script>
+<!-- endinject -->
\ No newline at end of file
diff --git a/views/ngXosViews/tenant/src/js/main.js b/views/ngXosViews/tenant/src/js/main.js
new file mode 100644
index 0000000..65fc90d
--- /dev/null
+++ b/views/ngXosViews/tenant/src/js/main.js
@@ -0,0 +1,418 @@
+'use strict';
+
+angular.module('xos.tenant', [
+  'ngResource',
+  'ngCookies',
+  'ui.router',
+  'xos.helpers'
+])
+.config(($stateProvider) => {
+  $stateProvider
+  .state('user-list', {
+    url: '/',
+    template: '<users-list></users-list>'
+  })
+    .state('site', {
+      url: '/site/:id',
+      template: '<site-detail></site-detail>'
+
+    })
+    .state('createslice', {
+      url: '/site/:site/slice/:id?',
+      template: '<create-slice></create-slice>'
+
+    });
+})
+.config(function($httpProvider){
+  $httpProvider.interceptors.push('NoHyperlinks');
+})
+.directive('usersList', function(){
+  return {
+    //sites : {},
+    restrict: 'E',
+    scope: {},
+    bindToController: true,
+    controllerAs: 'vm',
+    templateUrl: 'templates/users-list.tpl.html',
+    controller: function(Sites, SlicesPlus){
+
+
+
+      this.tableConfig = {
+        columns: [
+          {
+            label: 'Site1',
+            prop: 'name',
+            link: item => `/#/site/${item.id}`
+          },
+          {
+            label: 'Allocated',
+            prop: 'instance_total'
+          },
+          {
+            label: 'Ready',
+            prop: 'instance_total_ready'
+          }
+        ]
+      };
+
+      // retrieving user list
+      Sites.query().$promise
+      .then((users) => {
+        this.sites = users;
+        return  SlicesPlus.query().$promise
+      })
+      .then((users) => {
+        this.slices = users;
+        this.site_list = this.returnData(this.sites, this.slices);
+      })
+      .catch((e) => {
+        throw new Error(e);
+      });
+
+
+      this.returnData = (sites, slices) => {
+        var i, j=0;
+        var site_list=[];
+
+        for(i = 0; i<sites.length; i++){
+          var instance_t = 0;
+          var instance_t_r = 0;
+          for(j=0;j<slices.length;j++){
+            if (sites[i].id != null && slices[j].site !=null && sites[i].id === slices[j].site){
+              instance_t = instance_t + slices[j].instance_total;
+              instance_t_r = instance_t_r + slices[j].instance_total_ready;
+            }
+          }
+          var data_sites = {
+            'id': sites[i].id,
+            'name': sites[i].name,
+            'instance_total': instance_t,
+            'instance_total_ready': instance_t_r
+          };
+          site_list.push(data_sites);
+        }
+        return site_list;
+      }
+    }
+  };
+})
+.directive('siteDetail', function(){
+  return {
+    restrict: 'E',
+    scope: {},
+    bindToController: true,
+    controllerAs: 'sl',
+    templateUrl: 'templates/slicelist.html',
+    controller: function(SlicesPlus, $stateParams){
+      this.siteId  = $stateParams.id;
+      this.tableConfig = {
+        columns: [
+          {
+            label: 'Slice List',
+            prop: 'name',
+            link: item => `/#/site/${item.site}/slice/${item.id}`
+          },
+          {
+            label: 'Allocated',
+            prop: 'instance_total'
+          },
+          {
+            label: 'Ready',
+            prop: 'instance_total_ready'
+          }
+        ]
+      };
+
+      // retrieving user list
+      SlicesPlus.query({
+        site: $stateParams.id
+      }).$promise
+      .then((users) => {
+        this.sliceList = users;
+      })
+      .catch((e) => {
+        throw new Error(e);
+      });
+    }
+  };
+})
+.directive('createSlice', function(){
+  return {
+    //sites : {},
+    restrict: 'E',
+    scope: {},
+    bindToController: true,
+    controllerAs: 'cs',
+    templateUrl: 'templates/createslice.html',
+    controller: function(Slices, SlicesPlus, Sites, Images, $stateParams, $http, $state, $q){
+      this.config = {
+        exclude: ['site', 'password', 'last_login', 'mount_data_sets', 'default_flavor', 'creator', 'exposed_ports', 'networks', 'omf_friendly', 'omf_friendly', 'no_sync', 'no_policy', 'lazy_blocked', 'write_protect', 'deleted', 'backend_status', 'backend_register', 'policed', 'enacted', 'updated', 'created', 'validators', 'humanReadableName'],
+        formName: 'SliceDetails',
+        feedback: {
+          show: false,
+          message: 'Form submitted successfully !!!',
+          type: 'success'
+        },
+        actions: [
+          {
+            label: 'Save',
+            icon: 'ok', // refers to bootstraps glyphicon
+            cb: (model, form) => { // receive the model
+              saveform(model, form).then(()=> {
+                $state.go('site', {id: this.model.site});
+              });
+            },
+            class: 'success'
+          },  {
+            label: 'Save and continue editing',
+            icon: 'ok', // refers to bootstraps glyphicon
+            cb: (model, form) => { // receive the model
+              saveform(model,form);
+            },
+            class: 'primary'
+          },
+          {
+            label: 'Save and add another',
+            icon: 'ok', // refers to bootstraps glyphicon
+            cb: (model, form) => {
+              saveform(model,form).then(()=> {
+                $state.go('createslice',{site : this.model.site,id : ''});
+              });
+            },
+            class: 'primary'
+          }
+        ],
+        fields:
+        {
+          site: {
+            label: 'Site',
+            type: 'select',
+            validators: { required: true},
+            hint: 'The Site this Slice belongs to',
+            options: []
+
+          },
+          name: {
+            label: 'Name',
+            type: 'string',
+            hint: 'The Name of the Slice',
+            validators: {
+              required: true
+            }
+          },
+          serviceClass: {
+            label: 'ServiceClass',
+            type: 'select',
+            validators: {required: true},
+            hint: 'The Site this Slice belongs to',
+            options: [
+              {
+                id: 1,
+                label: 'Best effort'
+              }
+            ]
+          },
+          enabled: {
+            label: 'Enabled',
+            type: 'boolean',
+            hint: 'Status for this Slice'
+          },
+          description: {
+            label: 'Description',
+            type: 'string',
+            hint: 'High level description of the slice and expected activities',
+            validators: {
+              required: false,
+              minlength: 10
+            }
+          },
+          service: {
+            label: 'Service',
+            type: 'select',
+            validators: { required: false},
+            options: [
+              {
+                id: 0,
+                label: '--------'
+              }
+            ]
+          },
+          slice_url: {
+            label: 'Slice url',
+            type: 'string',
+            validators: {
+              required: false,
+              minlength: 10
+            }
+          },
+          max_instances: {
+            label: 'Max Instances',
+            type: 'number',
+            validators: {
+              required: false,
+              min: 0
+            }
+          },
+          default_isolation: {
+            label: 'Default Isolation',
+            type: 'select',
+            validators: { required: false},
+            options: [
+              {
+                id: 'vm',
+                label: 'Virtual Machine'
+              },
+              {
+                id: 'container',
+                label: 'Container'
+              },
+              {
+                id: 'container_vm',
+                label: 'Container in VM'
+              }
+            ]
+          },
+          default_image: {
+            label: 'Default image',
+            type: 'select',
+            validators: { required: false},
+            options: []
+          },
+          network: {
+            label: 'Network',
+            type: 'select',
+            validators: { required: false},
+            options: [
+              {
+                id: 'default',
+                label: 'Default'
+              },
+              {
+                id: 'host',
+                label: 'Host'
+              },
+              {
+                id: 'bridged',
+                label: 'Bridged'
+              },
+              {
+                id: 'noauto',
+                label: 'No Automatic Networks'
+              }
+            ]
+          }
+
+        }
+      };
+      var data;
+      Images.query().$promise
+          .then((users) => {
+            this.users = users;
+            data = this.users;
+            this.optionValImg = this.setData(data, {field1: 'id', field2: 'name'});
+            this.config.fields['default_image'].options = this.optionValImg;
+          })
+          .catch((e) => {
+            throw new Error(e);
+          });
+
+      // Use this method for select by seting object in fields variable of format { field1 : "val1", field2 : "val2"}
+      this.setData = (data, fields) => {
+        var i;
+        var retObj=[];
+        for(i = 0; i<data.length; i++){
+          var optVal = {id: data[i][fields.field1], label: data[i][fields.field2]};
+          retObj.push(optVal);
+
+        }
+        return retObj;
+      };
+
+      // retrieving user list
+
+      if ($stateParams.id)
+      {
+        delete this.config.fields['site'];
+        this.config.exclude.push('site');
+
+        Slices.get({id: $stateParams.id}).$promise
+          .then((users) => {
+            this.users = users;
+            data = users;
+
+            this.model = data;
+          })
+          .catch((e) => {
+            throw new Error(e);
+          });
+      }
+      else
+      {
+
+
+        this.model = {};
+        $http.get('/xoslib/tenantview/').
+        success((data) => {
+          this.userList = data;
+          this.model['creator'] = this.userList.current_user_id;
+
+        });
+
+
+
+
+
+
+        Sites.query().$promise
+      .then((users) => {
+        this.users_site = users;
+        this.optionVal = this.setData(this.users_site, {field1: 'id', field2: 'name'});
+        this.config.fields['site'].options = this.optionVal;
+        //= this.optionVal;
+
+      })
+      .catch((e) => {
+        throw new Error(e);
+      });
+
+      }
+
+      var  saveform = (model,form) =>
+      { // receive the model
+        var deferred = $q.defer();
+        delete model.networks;
+        if (form.$valid )
+        {
+          if(model.id){
+            var pr = Slices.update(model).$promise;
+          }
+          else{
+            var pr = Slices.save(model).$promise;
+          }
+          pr.then((users) => {
+            this.model = users;
+            //data = users;
+            //this.model = this.users;
+            this.config.feedback.show = true;
+            deferred.resolve(this.model);
+          })
+          .catch((e) => {
+            this.config.feedback.show = true;
+            this.config.feedback.type='danger';
+            if(e.data && e.data.detail )
+            {
+              this.config.feedback.message = e.data.detail;
+            }
+            else {
+              this.config.feedback.message=e.statusText;
+            }
+            deferred.reject(e);
+          });
+        }
+
+        return  deferred.promise;
+      }
+    }
+  };
+});
\ No newline at end of file
diff --git a/views/ngXosViews/tenant/src/sass/main.scss b/views/ngXosViews/tenant/src/sass/main.scss
new file mode 100644
index 0000000..268f1b4
--- /dev/null
+++ b/views/ngXosViews/tenant/src/sass/main.scss
@@ -0,0 +1,9 @@
+@import '../../../../style/sass/lib/_variables.scss';
+@import '../../../../../views/style/sass/bootstrap/bootstrap/_variables.scss';
+
+
+#xosTenant {
+  a{
+    margin-bottom: $form-group-margin-bottom;
+  }
+}
\ No newline at end of file
diff --git a/views/ngXosViews/tenant/src/templates/createslice.html b/views/ngXosViews/tenant/src/templates/createslice.html
new file mode 100644
index 0000000..b04ee28
--- /dev/null
+++ b/views/ngXosViews/tenant/src/templates/createslice.html
@@ -0,0 +1,11 @@
+<!--<xos-table config="cs.tableConfig" data="cs.sites"></xos-table>-->
+<h2>Slice Details</h2>
+<hr></hr>
+<xos-form ng-model="cs.model" config="cs.config" ></xos-form>
+
+<!--<pre>-->
+<!--&lt;!&ndash;{{cs.users | json}}&ndash;&gt;-->
+
+<!--{{cs.users.name | json}}-->
+
+<!--</pre>-->
\ No newline at end of file
diff --git a/views/ngXosViews/tenant/src/templates/slicelist.html b/views/ngXosViews/tenant/src/templates/slicelist.html
new file mode 100644
index 0000000..fb42315
--- /dev/null
+++ b/views/ngXosViews/tenant/src/templates/slicelist.html
@@ -0,0 +1,6 @@
+<!--<span ng-bind="siteNameSe"></span>-->
+<!--<xos-field></xos-field>-->
+<a class="addlink btn btn-info" ui-sref="createslice({site: sl.siteId})"><i class="glyphicon glyphicon-plus-sign"></i> Create Slice</a>
+<xos-table config="sl.tableConfig" data="sl.sliceList"></xos-table>
+<!--<div ui-view="sliceDetails"></div>-->
+<!--<pre>{{sl.users[0].site}}</pre>-->
diff --git a/views/ngXosViews/tenant/src/templates/users-list.tpl.html b/views/ngXosViews/tenant/src/templates/users-list.tpl.html
new file mode 100644
index 0000000..1242734
--- /dev/null
+++ b/views/ngXosViews/tenant/src/templates/users-list.tpl.html
@@ -0,0 +1 @@
+<xos-table config="vm.tableConfig" data="vm.site_list"></xos-table>
\ No newline at end of file
diff --git a/xos/api/service/vbng/debug.py b/xos/api/service/vbng/debug.py
deleted file mode 100644
index 8ecec0f..0000000
--- a/xos/api/service/vbng/debug.py
+++ /dev/null
@@ -1,61 +0,0 @@
-from rest_framework.decorators import api_view
-from rest_framework.response import Response
-from rest_framework.reverse import reverse
-from rest_framework import serializers
-from rest_framework import generics
-from rest_framework import viewsets
-from rest_framework.decorators import detail_route, list_route
-from rest_framework.views import APIView
-from core.models import *
-from django.forms import widgets
-from django.conf.urls import patterns, url
-from services.cord.models import VOLTTenant, VBNGTenant, CordSubscriberRoot
-from core.xoslib.objects.cordsubscriber import CordSubscriber
-from api.xosapi_helpers import PlusModelSerializer, XOSViewSet
-from django.shortcuts import get_object_or_404
-from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
-from xos.exceptions import *
-import json
-import subprocess
-
-if hasattr(serializers, "ReadOnlyField"):
-    # rest_framework 3.x
-    ReadOnlyField = serializers.ReadOnlyField
-else:
-    # rest_framework 2.x
-    ReadOnlyField = serializers.Field
-
-class CordDebugIdSerializer(PlusModelSerializer):
-    # Swagger is failing because CordDebugViewSet has neither a model nor
-    # a serializer_class. Stuck this in here as a placeholder for now.
-    id = ReadOnlyField()
-    class Meta:
-        model = CordSubscriber
-
-class CordDebugViewSet(XOSViewSet):
-    base_name = "debug"
-    method_name = "debug"
-    method_kind = "viewset"
-    serializer_class = CordDebugIdSerializer
-
-    @classmethod
-    def get_urlpatterns(self, api_path="^"):
-        patterns = []
-        patterns.append( url(api_path + "debug/vbng_dump/$", self.as_view({"get": "get_vbng_dump"}), name="vbng_dump"))
-        return patterns
-
-    # contact vBNG service and dump current list of mappings
-    def get_vbng_dump(self, request, pk=None):
-        result=subprocess.check_output(["curl", "http://10.0.3.136:8181/onos/virtualbng/privateip/map"])
-        if request.GET.get("theformat",None)=="text":
-            from django.http import HttpResponse
-            result = json.loads(result)["map"]
-
-            lines = []
-            for row in result:
-                for k in row.keys():
-                     lines.append( "%s %s" % (k, row[k]) )
-
-            return HttpResponse("\n".join(lines), content_type="text/plain")
-        else:
-            return Response( {"vbng_dump": json.loads(result)["map"] } )
diff --git a/xos/configurations/common/disable-onboarding.yaml b/xos/configurations/common/disable-onboarding.yaml
new file mode 100644
index 0000000..acb75c8
--- /dev/null
+++ b/xos/configurations/common/disable-onboarding.yaml
@@ -0,0 +1,16 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    xos:
+      type: tosca.nodes.XOS
+      properties:
+        no-create: true
+        no-delete: true
+        enable_build: false
+
diff --git a/xos/configurations/common/enable-onboarding.yaml b/xos/configurations/common/enable-onboarding.yaml
new file mode 100644
index 0000000..98e433c
--- /dev/null
+++ b/xos/configurations/common/enable-onboarding.yaml
@@ -0,0 +1,16 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    xos:
+      type: tosca.nodes.XOS
+      properties:
+        no-create: true
+        no-delete: true
+        enable_build: true
+
diff --git a/xos/configurations/cord-pod/Makefile b/xos/configurations/cord-pod/Makefile
index 1b9e967..1d5f68c 100644
--- a/xos/configurations/cord-pod/Makefile
+++ b/xos/configurations/cord-pod/Makefile
@@ -20,6 +20,30 @@
 	echo "[ONBOARDING]"
 	# on-board any services here
 	bash ../common/wait_for_onboarding_ready.sh 81 xos
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/configurations/common/disable-onboarding.yaml
+	sudo cp id_rsa key_import/vsg_rsa
+	sudo cp id_rsa.pub key_import/vsg_rsa.pub
+	sudo cp id_rsa key_import/volt_rsa
+	sudo cp id_rsa.pub key_import/volt_rsa.pub
+	sudo cp id_rsa key_import/onos_rsa
+	sudo cp id_rsa key_import/onos_rsa.pub
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/vrouter/vrouter-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/volt/volt-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/vsg/vsg-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/vtn/vtn-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/onos/onos-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/fabric/fabric-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/vtr/vtr-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/configurations/cord-pod/synchronizers.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/configurations/common/enable-onboarding.yaml
+	bash ../common/wait_for_onboarding_ready.sh 81 services/vrouter
+	bash ../common/wait_for_onboarding_ready.sh 81 services/volt
+	bash ../common/wait_for_onboarding_ready.sh 81 services/vsg
+	bash ../common/wait_for_onboarding_ready.sh 81 services/vtn
+	bash ../common/wait_for_onboarding_ready.sh 81 services/onos
+	bash ../common/wait_for_onboarding_ready.sh 81 services/fabric
+	bash ../common/wait_for_onboarding_ready.sh 81 services/vtr
+	bash ../common/wait_for_onboarding_ready.sh 81 xos
 	bash ../common/wait_for_xos_port.sh 80
 
 podconfig: nodes.yaml images.yaml
@@ -41,11 +65,35 @@
 	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-vtn-vsg.yaml
 	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-volt-devices.yaml
 
-exampleservice:
-	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/pod-exampleservice.yaml
+clean-nodes:
+	rm -f nodes.yaml
 
-cord-ceilometer: ceilometer_custom_images cord
-	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/ceilometer.yaml
+update-nodes: nodes.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
+
+new-nodes: clean-nodes update-nodes vtn
+
+exampleservice: onboard-exampleservice
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/pod-exampleservice.yaml
+
+onboard-exampleservice:
+	sudo cp id_rsa key_import/exampleservice_rsa
+	sudo cp id_rsa.pub key_import/exampleservice_rsa.pub
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/exampleservice/exampleservice-onboard.yaml
+	bash ../common/wait_for_onboarding_ready.sh 81 services/exampleservice
+	bash ../common/wait_for_onboarding_ready.sh 81 xos
+	bash ../common/wait_for_xos_port.sh 80
+
+cord-ceilometer: ceilometer_custom_images cord onboard-ceilometer
+	sudo docker-compose  -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/ceilometer.yaml
+
+onboard-ceilometer:
+	sudo cp id_rsa key_import/monitoring_channel_rsa
+	sudo cp id_rsa.pub key_import/monitoring_channel_rsa.pub
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/ceilometer/ceilometer-onboard.yaml
+	bash ../common/wait_for_onboarding_ready.sh 81 services/ceilometer
+	bash ../common/wait_for_onboarding_ready.sh 81 xos
+	bash ../common/wait_for_xos_port.sh 80
 
 nodes.yaml:
 	export SETUPDIR=.; bash ../common/make-nodes-yaml.sh
diff --git a/xos/configurations/cord-pod/cord-vtn-vsg.yaml b/xos/configurations/cord-pod/cord-vtn-vsg.yaml
index 44d4fbb..6996527 100644
--- a/xos/configurations/cord-pod/cord-vtn-vsg.yaml
+++ b/xos/configurations/cord-pod/cord-vtn-vsg.yaml
@@ -25,6 +25,10 @@
           view_url: /admin/cord/voltservice/$id$/
           kind: vOLT
           replaces: service_volt
+          public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
+          private_key_fn: /opt/xos/services/volt/keys/volt_rsa
+      artifacts:
+          pubkey: /opt/xos/services/volt/keys/volt_rsa.pub
 
     addresses_vsg:
       type: tosca.nodes.AddressPool
@@ -50,11 +54,11 @@
           view_url: /admin/cord/vsgservice/$id$/
           backend_network_label: hpc_client
           public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
-          private_key_fn: /opt/xos/synchronizers/vcpe/vcpe_private_key
+          private_key_fn: /opt/xos/services/vsg/keys/vsg_rsa
 #          node_label: label_vsg
           replaces: service_vsg
       artifacts:
-          pubkey: /opt/xos/synchronizers/vcpe/vcpe_public_key
+          pubkey: /opt/xos/services/vsg/keys/vsg_rsa.pub
 
     service#vrouter:
       type: tosca.nodes.VRouterService
diff --git a/xos/configurations/cord-pod/docker-compose-bootstrap.yml b/xos/configurations/cord-pod/docker-compose-bootstrap.yml
index 9f17c42..8bf073f 100644
--- a/xos/configurations/cord-pod/docker-compose-bootstrap.yml
+++ b/xos/configurations/cord-pod/docker-compose-bootstrap.yml
@@ -40,52 +40,52 @@
             max-size: "100k"
             max-file: "5"
 
-xos_synchronizer_onos:
-    image: xosproject/xos-synchronizer-openstack
-    command: bash -c "python /opt/xos/synchronizers/onos/onos-synchronizer.py -C /opt/xos/synchronizers/onos/onos_synchronizer_config"
-    labels:
-        org.xosproject.kind: synchronizer
-        org.xosproject.target: onos
-    links:
-        - xos_db
-    volumes:
-        - .:/root/setup:ro
-        - ./id_rsa:/opt/xos/synchronizers/onos/onos_key:ro  # private key
-    log_driver: "json-file"
-    log_opt:
-            max-size: "100k"
-            max-file: "5"
+#xos_synchronizer_onos:
+#    image: xosproject/xos-synchronizer-openstack
+#    command: bash -c "python /opt/xos/synchronizers/onos/onos-synchronizer.py -C /opt/xos/synchronizers/onos/onos_synchronizer_config"
+#    labels:
+#        org.xosproject.kind: synchronizer
+#        org.xosproject.target: onos
+#    links:
+#        - xos_db
+#    volumes:
+#        - .:/root/setup:ro
+#        - ./id_rsa:/opt/xos/synchronizers/onos/onos_key:ro  # private key
+#    log_driver: "json-file"
+#    log_opt:
+#            max-size: "100k"
+#            max-file: "5"
 
-xos_synchronizer_vcpe:
-    image: xosproject/xos-synchronizer-openstack
-    command: bash -c "sleep 120; cp /root/setup/node_key /opt/xos/synchronizers/vcpe/; chmod 0600 /opt/xos/synchronizers/vcpe/node_key; python /opt/xos/synchronizers/vcpe/vcpe-synchronizer.py -C /root/setup/files/vcpe_synchronizer_config"
-    labels:
-        org.xosproject.kind: synchronizer
-        org.xosproject.target: vcpe
-    links:
-        - xos_db
-    volumes:
-        - .:/root/setup:ro
-        - ./id_rsa:/opt/xos/synchronizers/vcpe/vcpe_private_key:ro  # private key
-    log_driver: "json-file"
-    log_opt:
-            max-size: "100k"
-            max-file: "5"
+#xos_synchronizer_vcpe:
+#    image: xosproject/xos-synchronizer-openstack
+#    command: bash -c "sleep 120; cp /root/setup/node_key /opt/xos/synchronizers/vcpe/; chmod 0600 /opt/xos/synchronizers/vcpe/node_key; python /opt/xos/synchronizers/vcpe/vcpe-synchronizer.py -C /root/setup/files/vcpe_synchronizer_config"
+#    labels:
+#        org.xosproject.kind: synchronizer
+#        org.xosproject.target: vcpe
+#    links:
+#        - xos_db
+#    volumes:
+#        - .:/root/setup:ro
+#        - ./id_rsa:/opt/xos/synchronizers/vcpe/vcpe_private_key:ro  # private key
+#    log_driver: "json-file"
+#    log_opt:
+#            max-size: "100k"
+#            max-file: "5"
 
-xos_synchronizer_vtn:
-    image: xosproject/xos-synchronizer-openstack
-    command: bash -c "sleep 120; python /opt/xos/synchronizers/vtn/vtn-synchronizer.py -C /opt/xos/synchronizers/vtn/vtn_synchronizer_config"
-    labels:
-        org.xosproject.kind: synchronizer
-        org.xosproject.target: vtn
-    links:
-        - xos_db
-    volumes:
-        - .:/root/setup:ro
-    log_driver: "json-file"
-    log_opt:
-            max-size: "100k"
-            max-file: "5"
+#xos_synchronizer_vtn:
+#    image: xosproject/xos-synchronizer-openstack
+#    command: bash -c "sleep 120; python /opt/xos/synchronizers/vtn/vtn-synchronizer.py -C /opt/xos/synchronizers/vtn/vtn_synchronizer_config"
+#    labels:
+#        org.xosproject.kind: synchronizer
+#        org.xosproject.target: vtn
+#    links:
+#        - xos_db
+#    volumes:
+#        - .:/root/setup:ro
+#    log_driver: "json-file"
+#    log_opt:
+#            max-size: "100k"
+#            max-file: "5"
 
 xos_synchronizer_monitoring_channel:
     image: xosproject/xos-synchronizer-openstack
@@ -103,21 +103,36 @@
             max-size: "100k"
             max-file: "5"
 
-xos_synchronizer_vtr:
-    image: xosproject/xos-synchronizer-openstack
-    command: bash -c "sleep 120; cp /root/setup/node_key /opt/xos/synchronizers/vtr/; chmod 0600 /opt/xos/synchronizers/vtr/node_key; python /opt/xos/synchronizers/vtr/vtr-synchronizer.py -C /root/setup/files/vtr_synchronizer_config"
-    labels:
-        org.xosproject.kind: synchronizer
-        org.xosproject.target: vtr
-    links:
-        - xos_db
-    volumes:
-        - .:/root/setup:ro
-        - ./id_rsa:/opt/xos/synchronizers/vtr/vcpe_private_key:ro  # private key
-    log_driver: "json-file"
-    log_opt:
-            max-size: "100k"
-            max-file: "5"
+#xos_synchronizer_vtr:
+#    image: xosproject/xos-synchronizer-openstack
+#    command: bash -c "sleep 120; cp /root/setup/node_key /opt/xos/synchronizers/vtr/; chmod 0600 /opt/xos/synchronizers/vtr/node_key; python /opt/xos/synchronizers/vtr/vtr-synchronizer.py -C /root/setup/files/vtr_synchronizer_config"
+#    labels:
+#        org.xosproject.kind: synchronizer
+#        org.xosproject.target: vtr
+#    links:
+#        - xos_db
+#    volumes:
+#        - .:/root/setup:ro
+#        - ./id_rsa:/opt/xos/synchronizers/vtr/vcpe_private_key:ro  # private key
+#    log_driver: "json-file"
+#    log_opt:
+#            max-size: "100k"
+#            max-file: "5"
+
+#xos_synchronizer_fabric:
+#    image: xosproject/xos-synchronizer-openstack
+#    command: bash -c "sleep 120; python /opt/xos/synchronizers/fabric/fabric-synchronizer.py -C /opt/xos/synchronizers/fabric/fabric_synchronizer_config"
+#    labels:
+#        org.xosproject.kind: synchronizer
+#        org.xosproject.target: fabric
+#    links:
+#        - xos_db
+#    volumes:
+#        - .:/root/setup:ro
+#    log_driver: "json-file"
+#    log_opt:
+#            max-size: "100k"
+#            max-file: "5"
 
 xos_synchronizer_fabric:
     image: xosproject/xos-synchronizer-openstack
diff --git a/xos/configurations/cord-pod/files/vcpe_synchronizer_config b/xos/configurations/cord-pod/files/vcpe_synchronizer_config
index 46ee0c3..9da6ede 100644
--- a/xos/configurations/cord-pod/files/vcpe_synchronizer_config
+++ b/xos/configurations/cord-pod/files/vcpe_synchronizer_config
@@ -23,10 +23,10 @@
 
 [observer]
 name=vcpe
-dependency_graph=/opt/xos/synchronizers/vcpe/model-deps
-steps_dir=/opt/xos/synchronizers/vcpe/steps
-sys_dir=/opt/xos/synchronizers/vcpe/sys
-deleters_dir=/opt/xos/synchronizers/vcpe/deleters
+dependency_graph=/opt/xos/synchronizers/vsg/model-deps
+steps_dir=/opt/xos/synchronizers/vsg/steps
+sys_dir=/opt/xos/synchronizers/vsg/sys
+deleters_dir=/opt/xos/synchronizers/vsg/deleters
 log_file=console
 #/var/log/hpc.log
 driver=None
diff --git a/xos/configurations/cord-pod/files/vtr_synchronizer_config b/xos/configurations/cord-pod/files/vtr_synchronizer_config
index 2c9140a..223ab00 100644
--- a/xos/configurations/cord-pod/files/vtr_synchronizer_config
+++ b/xos/configurations/cord-pod/files/vtr_synchronizer_config
@@ -36,7 +36,7 @@
 # set proxy_ssh to false on cloudlab
 full_setup=True
 proxy_ssh=True
-proxy_ssh_key=/opt/xos/synchronizers/vtr/node_key
+proxy_ssh_key=/root/setup/node_key
 proxy_ssh_user=root
 
 [networking]
diff --git a/xos/configurations/cord-pod/synchronizers.yaml b/xos/configurations/cord-pod/synchronizers.yaml
new file mode 100644
index 0000000..02035e3
--- /dev/null
+++ b/xos/configurations/cord-pod/synchronizers.yaml
@@ -0,0 +1,19 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: This recipe provides additional configuration for the onboarded services.
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    servicecontroller#vsg:
+      type: tosca.nodes.ServiceController
+      properties:
+        no-create: true
+        synchronizer_config: /root/setup/files/vcpe_synchronizer_config
+    servicecontroller#vtr:
+      type: tosca.nodes.ServiceController
+      properties:
+        no-create: true
+        synchronizer_config: /root/setup/files/vtr_synchronizer_config
diff --git a/xos/configurations/cord-pod/xos.yaml b/xos/configurations/cord-pod/xos.yaml
index 06b5eb5..95cbf18 100644
--- a/xos/configurations/cord-pod/xos.yaml
+++ b/xos/configurations/cord-pod/xos.yaml
@@ -54,25 +54,25 @@
              node: xos
              relationship: tosca.relationships.UsedByXOS
 
-    /opt/xos/synchronizers/onos/onos_key.pub:
-      type: tosca.nodes.XOSVolume
-      properties:
-          host_path: { path_join: [ SELF, CONFIG_DIR, id_rsa.pub, ENV_VAR ] }
-          read_only: true
-      requirements:
-          - xos:
-             node: xos
-             relationship: tosca.relationships.UsedByXOS
+#    /opt/xos/synchronizers/onos/onos_key.pub:
+#      type: tosca.nodes.XOSVolume
+#      properties:
+#          host_path: { path_join: [ SELF, CONFIG_DIR, id_rsa.pub, ENV_VAR ] }
+#          read_only: true
+#      requirements:
+#          - xos:
+#             node: xos
+#             relationship: tosca.relationships.UsedByXOS
 
-    /opt/xos/synchronizers/vcpe/vcpe_public_key:
-      type: tosca.nodes.XOSVolume
-      properties:
-          host_path: { path_join: [ SELF, CONFIG_DIR, id_rsa.pub, ENV_VAR ] }                                                      
-          read_only: true
-      requirements:
-          - xos:
-             node: xos
-             relationship: tosca.relationships.UsedByXOS
+#    /opt/xos/synchronizers/vcpe/vcpe_public_key:
+#      type: tosca.nodes.XOSVolume
+#      properties:
+#          host_path: { path_join: [ SELF, CONFIG_DIR, id_rsa.pub, ENV_VAR ] }
+#          read_only: true
+#      requirements:
+#          - xos:
+#             node: xos
+#             relationship: tosca.relationships.UsedByXOS
 
     /opt/xos/synchronizers/monitoring_channel/monitoring_channel_public_key:
       type: tosca.nodes.XOSVolume
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index 46f39bf..8845196 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -3,23 +3,33 @@
 DOCKER_COMPOSE_YML=./onboarding-docker-compose/docker-compose.yml
 BOOTSTRAP_YML=./docker-compose-bootstrap.yml
 DOCKER_PROJECT=frontend
+XOS_BOOTSTRAP_PORT=9998
+XOS_UI_PORT=9999
 
-frontend: prereqs bootstrap
-	bash ../common/wait_for_xos_port.sh 9999
-	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
-	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
-	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
+frontend: prereqs bootstrap onboarding frontendconfig
 
 prereqs:
 	sudo make -f ../common/Makefile.prereqs
 
 bootstrap:
+	echo "[BOOTSTRAP]"
 	sudo rm -f onboarding-docker-compose/docker-compose.yml
-	sudo rm -f docker-compose.yml
 	sudo docker-compose -p $(DOCKER_PROJECT) -f docker-compose-bootstrap.yml up -d
-	bash ../common/wait_for_xos_port.sh 9998
+	bash ../common/wait_for_xos_port.sh $(XOS_BOOTSTRAP_PORT)
 	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run -e CONFIG_DIR=$(CONFIG_DIR) xos_bootstrap_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/frontend/xos.yaml
 
+onboarding:
+	echo "[ONBOARDING]"
+	# on-board any services here
+	bash ../common/wait_for_onboarding_ready.sh $(XOS_BOOTSTRAP_PORT) xos
+	bash ../common/wait_for_xos_port.sh $(XOS_UI_PORT)
+
+frontendconfig:
+	echo "[FRONTENDCONFIG]"
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
+
 containers:
 	cd ../../../containers/xos; make devel
 	cd ../../../containers/synchronizer; make
@@ -50,15 +60,29 @@
 	sudo docker exec frontend_xos_1 rm -f /opt/xos/xos_configuration/xos_mcord_config
 	sudo docker exec frontend_xos_1 rm -f /opt/xos/xos_configuration/xos_cord_config
 
-mock-cord-pod:
-	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
-	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/mgmt-net.yaml
-	#sudo docker-compose run xos bash -c "echo somekey > /opt/xos/synchronizers/vcpe/vcpe_public_key; python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/cord-vtn-vsg.yaml"
-	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/cord-volt-devices.yaml
+mock-cord-pod: onboard-cord-pod
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/mgmt-net.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/cord-vtn-vsg.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/cord-volt-devices.yaml
 	sudo docker exec frontend_xos_1 cp /opt/xos/configurations/cord-pod/xos_cord_config /opt/xos/xos_configuration/
 	sudo docker exec frontend_xos_1 touch /opt/xos/xos/settings.py
 
-
+onboard-cord-pod:
+	#sudo cp id_rsa key_import/vsg_rsa
+	#sudo cp id_rsa.pub key_import/vsg_rsa.pub
+	#sudo cp id_rsa key_import/volt_rsa
+	#sudo cp id_rsa.pub key_import/volt_rsa.pub
+	sudo bash -c "echo somekey > key_import/vsg_rsa"
+	sudo bash -c "echo somekey > key_import/vsg_rsa.pub"
+	sudo bash -c "echo somekey > key_import/volt_rsa"
+	sudo bash -c "echo somekey > key_import/volt_rsa.pub"
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/volt/volt-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/vsg/vsg-onboard.yaml
+	bash ../common/wait_for_onboarding_ready.sh 9998 services/volt
+	bash ../common/wait_for_onboarding_ready.sh 9998 services/vsg
+	bash ../common/wait_for_onboarding_ready.sh $(XOS_BOOTSTRAP_PORT) xos
+	bash ../common/wait_for_xos_port.sh $(XOS_UI_PORT)
 
 mock-mcord:
 	# check this
diff --git a/xos/configurations/frontend/docker-compose-bootstrap.yml b/xos/configurations/frontend/docker-compose-bootstrap.yml
index 3975893..00a43f3 100644
--- a/xos/configurations/frontend/docker-compose-bootstrap.yml
+++ b/xos/configurations/frontend/docker-compose-bootstrap.yml
@@ -17,7 +17,7 @@
 xos_synchronizer_onboarding:
     image: xosproject/xos-synchronizer-onboarding
     command: bash -c "cd /opt/xos/synchronizers/onboarding; ./run.sh"
-    #command: sleep 86400
+#    command: sleep 86400
     labels:
         org.xosproject.kind: synchronizer
         org.xosproject.target: onboarding
diff --git a/xos/configurations/frontend/xos.yaml b/xos/configurations/frontend/xos.yaml
index 8b286cd..3153e95 100644
--- a/xos/configurations/frontend/xos.yaml
+++ b/xos/configurations/frontend/xos.yaml
@@ -13,6 +13,7 @@
         ui_port: 9999
         bootstrap_ui_port: 9998
         docker_project_name: frontend
+        frontend_only: true
 
     /opt/xos/xos_configuration/xos_common_config:
       type: tosca.nodes.XOSVolume
diff --git a/xos/configurations/test-standalone/Makefile b/xos/configurations/test-standalone/Makefile
index 9eafa61..9807e5d 100644
--- a/xos/configurations/test-standalone/Makefile
+++ b/xos/configurations/test-standalone/Makefile
@@ -1,4 +1,10 @@
 MYIP:=$(shell hostname -i)
+CONFIG_DIR:=$(shell pwd)
+DOCKER_COMPOSE_YML=./onboarding-docker-compose/docker-compose.yml
+BOOTSTRAP_YML=./docker-compose-bootstrap.yml
+DOCKER_PROJECT=teststandalone
+XOS_BOOTSTRAP_PORT=9998
+XOS_UI_PORT=9999
 
 define TRUNCATE_FN
 	CREATE OR REPLACE FUNCTION truncate_tables(username IN VARCHAR) RETURNS void AS $$$$
@@ -16,13 +22,40 @@
 export TRUNCATE_FN
 
 prepare: xos
-	sudo docker exec -i teststandalone_xos_1 bash -c "cd /opt/xos/tests/api; npm install --production"
-	sudo docker exec teststandalone_xos_1 pip install dredd_hooks
+	sudo docker exec -i teststandalone_xos_ui_1 bash -c "cd /opt/xos/tests/api; npm install --production"
+	sudo docker exec teststandalone_xos_ui_1 pip install dredd_hooks
 
-xos:
+xos: prereqs bootstrap onboarding
+
+prereqs:
 	sudo make -f ../common/Makefile.prereqs
-	sudo docker-compose up -d
-	bash ../common/wait_for_xos.sh
+
+bootstrap:
+	echo "[BOOTSTRAP]"
+	sudo rm -f onboarding-docker-compose/docker-compose.yml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f docker-compose-bootstrap.yml up -d
+	bash ../common/wait_for_xos_port.sh 9998
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run -e CONFIG_DIR=$(CONFIG_DIR) xos_bootstrap_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/test-standalone/xos.yaml
+
+onboarding:
+	echo "[ONBOARDING]"
+	bash ../common/wait_for_onboarding_ready.sh 9998 xos
+	sudo bash -c "echo somekey > key_import/vsg_rsa"
+	sudo bash -c "echo somekey > key_import/vsg_rsa.pub"
+	sudo bash -c "echo somekey > key_import/volt_rsa"
+	sudo bash -c "echo somekey > key_import/volt_rsa.pub"
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/configurations/common/disable-onboarding.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/vrouter/vrouter-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/volt/volt-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/vsg/vsg-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/onboard/vtr/vtr-onboard.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run xos_bootstrap_ui python /opt/xos/tosca/run.py None /opt/xos/configurations/common/enable-onboarding.yaml
+	bash ../common/wait_for_onboarding_ready.sh 9998 services/vrouter
+	bash ../common/wait_for_onboarding_ready.sh 9998 services/volt
+	bash ../common/wait_for_onboarding_ready.sh 9998 services/vsg
+	bash ../common/wait_for_onboarding_ready.sh 9998 services/vtr
+	bash ../common/wait_for_onboarding_ready.sh 9998 xos
+	bash ../common/wait_for_xos_port.sh 9999
 
 restore-initial-db-status:
 	sudo docker exec teststandalone_xos_db_1 psql -U postgres -d xos -c "$$TRUNCATE_FN" >/dev/null 2>&1
@@ -31,43 +64,47 @@
 	sudo docker exec teststandalone_xos_db_1 psql -U postgres -d xos -c "SELECT setval('core_deployment_id_seq', 1)" >/dev/null 2>&1
 	sudo docker exec teststandalone_xos_db_1 psql -U postgres -d xos -c "SELECT setval('core_flavor_id_seq', 1)" >/dev/null 2>&1
 	sudo docker exec teststandalone_xos_db_1 psql -U postgres -d xos -c "SELECT setval('core_service_id_seq', 1)" >/dev/null 2>&1
-	sudo docker-compose run xos python /opt/xos/manage.py --noobserver --nomodelpolicy loaddata /opt/xos/core/fixtures/core_initial_data.json
-	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
-	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
-	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/manage.py --noobserver --nomodelpolicy loaddata /opt/xos/core/fixtures/core_initial_data.json
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
 
 
 test: restore-initial-db-status
 	# RUN TESTS
-	sudo docker cp ../../../apiary.apib teststandalone_xos_1:/opt/xos/tests/api/apiary.apib
-	sudo docker exec -i teststandalone_xos_1 bash -c "cd /opt/xos/tests/api; npm test"
+	sudo docker cp ../../../apiary.apib teststandalone_xos_ui_1:/opt/xos/tests/api/apiary.apib
+	sudo docker exec -i teststandalone_xos_ui_1 bash -c "cd /opt/xos/tests/api; npm test"
 
 test-tosca: restore-initial-db-status
-	sudo docker-compose run xos bash -c "cd /opt/xos/tosca/tests; python ./alltests.py"
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui bash -c "cd /opt/xos/tosca/tests; python ./alltests.py"
 
 base-container: 
 	cd ../../../containers/xos; make base
 
 devel-container: base-container
 	cd ../../../containers/xos; make devel
+	cd ../../../containers/synchronizer; make
+	cd ../../../containers/onboarding_synchronizer; make
 
 containers: devel-container
 	cd ../../../containers/xos; make test
 
 stop:
-	sudo docker-compose stop
+	test ! -s $(DOCKER_COMPOSE_YML) || sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) stop
+	sudo docker-compose -f $(BOOTSTRAP_YML) stop
 
 showlogs:
 	sudo docker-compose logs
 
 rm: stop
-	sudo docker-compose rm -f
+	test ! -s $(DOCKER_COMPOSE_YML) || sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) rm
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) rm
 
 docker-clean:
 	sudo docker rm -f $(shell sudo docker ps -aq)
 
 enter-xos:
-	sudo docker exec -ti teststandalone_xos_1 bash
+	sudo docker exec -ti teststandalone_xos_ui_1 bash
 
 enter-xos-db:
 	sudo docker exec -ti teststandalone_xos_db_1 bash
diff --git a/xos/configurations/test-standalone/docker-compose-bootstrap.yml b/xos/configurations/test-standalone/docker-compose-bootstrap.yml
new file mode 100644
index 0000000..00a43f3
--- /dev/null
+++ b/xos/configurations/test-standalone/docker-compose-bootstrap.yml
@@ -0,0 +1,34 @@
+xos_db:
+    image: xosproject/xos-postgres
+    expose:
+        - "5432"
+
+xos_bootstrap_ui:
+    image: xosproject/xos
+    command: python /opt/xos/manage.py runserver 0.0.0.0:9998 --insecure --makemigrations
+    ports:
+        - "9998:9998"
+    links:
+        - xos_db
+    volumes:
+      - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config
+      - ../vtn/files/xos_vtn_config:/opt/xos/xos_configuration/xos_vtn_config:ro
+
+xos_synchronizer_onboarding:
+    image: xosproject/xos-synchronizer-onboarding
+    command: bash -c "cd /opt/xos/synchronizers/onboarding; ./run.sh"
+#    command: sleep 86400
+    labels:
+        org.xosproject.kind: synchronizer
+        org.xosproject.target: onboarding
+    links:
+        - xos_db
+    volumes:
+#        - .:/root/setup:ro
+        - /var/run/docker.sock:/var/run/docker.sock
+        - ./key_import:/opt/xos/key_import:ro
+        - ./onboarding-docker-compose:/opt/xos/synchronizers/onboarding/docker-compose
+    log_driver: "json-file"
+    log_opt:
+            max-size: "100k"
+            max-file: "5"
diff --git a/xos/configurations/test-standalone/docker-compose.yml b/xos/configurations/test-standalone/docker-compose.yml
deleted file mode 100644
index a0b87ed..0000000
--- a/xos/configurations/test-standalone/docker-compose.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-xos_db:
-    image: xosproject/xos-postgres
-    expose:
-        - "5432"
-
-# FUTURE
-#xos_swarm_synchronizer:
-#    image: xosproject/xos-swarm-synchronizer
-#    labels:
-#        org.xosproject.kind: synchronizer
-#        org.xosproject.target: swarm
-
-xos:
-    image: xosproject/xos-test
-    command: python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations
-    #command: sleep 86400    # For interactive session
-    ports:
-        - "9999:8000"
-    links:
-        - xos_db
-    volumes:
-      - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config
-      - ../../core/xoslib:/opt/xos/core/xoslib
-      - ../../core/static:/opt/xos/core/static
-      - ../../templates/admin:/opt/xos/templates/admin
-      - ../../configurations:/opt/xos/configurations
-      - ../../tests:/opt/xos/tests
-      - ../../api:/opt/xos/api
diff --git a/xos/configurations/test-standalone/xos.yaml b/xos/configurations/test-standalone/xos.yaml
new file mode 100644
index 0000000..62331d0
--- /dev/null
+++ b/xos/configurations/test-standalone/xos.yaml
@@ -0,0 +1,27 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    xos:
+      type: tosca.nodes.XOS
+      properties:
+        ui_port: 9999
+        bootstrap_ui_port: 9998
+        docker_project_name: teststandalone
+        frontend_only: true
+        source_ui_image: xosproject/xos-test
+
+    /opt/xos/xos_configuration/xos_common_config:
+      type: tosca.nodes.XOSVolume
+      properties:
+          host_path: { path_join: [ SELF, CONFIG_DIR, ../common/xos_common_config, ENV_VAR ] }
+          read_only: false
+      requirements:
+          - xos:
+             node: xos
+             relationship: tosca.relationships.UsedByXOS
diff --git a/xos/core/admin.py b/xos/core/admin.py
index c5e36be..4c46d81 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -1060,7 +1060,7 @@
 class ServiceControllerAdmin(XOSBaseAdmin):
     list_display = ("backend_status_icon", "name",)
     list_display_links = ('backend_status_icon', 'name',)
-    fieldList = ["backend_status_text", "name", "xos", "base_url"]
+    fieldList = ["backend_status_text", "name", "xos", "base_url", "synchronizer_run", "synchronizer_config"]
     fieldsets = [
         (None, {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
     inlines = [ServiceControllerResourceInline]
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index c871c7e..83b827c 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -70,6 +70,9 @@
     name = StrippedCharField(max_length=30, help_text="Service Name")
     base_url = StrippedCharField(max_length=1024, help_text="Base URL, allows use of relative URLs for resources", null=True, blank=True)
 
+    synchronizer_run = StrippedCharField(max_length=1024, help_text="synchronizer run command", null=True, blank=True)
+    synchronizer_config = StrippedCharField(max_length=1024, help_text="synchronizer config file", null=True, blank=True)
+
     def __unicode__(self): return u'%s' % (self.name)
 
     def save(self, *args, **kwargs):
@@ -83,6 +86,7 @@
 class ServiceControllerResource(PlCoreBase):
     KIND_CHOICES = (('models', 'Models'),
                     ('admin', 'Admin'),
+                    ('admin_template', 'Admin Template'),
                     ('django_library', 'Django Library'),
                     ('synchronizer', 'Synchronizer'),
                     ('rest_service', 'REST API (service)'),
@@ -102,6 +106,7 @@
                                 help_text="The Service Controller this resource is associated with")
 
     name = StrippedCharField(max_length=30, help_text="Object Name")
+    subdirectory = StrippedCharField(max_length=1024, help_text="optional subdirectory", null=True, blank=True)
     kind = StrippedCharField(choices=KIND_CHOICES, max_length=30)
     format = StrippedCharField(choices=FORMAT_CHOICES, max_length=30)
     url = StrippedCharField(max_length=1024, help_text="URL of resource", null=True, blank=True)
diff --git a/xos/core/models/xosmodel.py b/xos/core/models/xosmodel.py
index 4942241..ea53bd1 100644
--- a/xos/core/models/xosmodel.py
+++ b/xos/core/models/xosmodel.py
@@ -14,6 +14,8 @@
     db_container_name = StrippedCharField(max_length=200, help_text="name of XOS db container", default="xos_db")
     docker_project_name = StrippedCharField(max_length=200, help_text="docker project name")
     enable_build = models.BooleanField(help_text="True if Onboarding Synchronizer should build XOS as necessary", default=True)
+    frontend_only = models.BooleanField(help_text="If True, XOS will not start synchronizer containers", default=False)
+    source_ui_image = StrippedCharField(max_length=200, default="xosproject/xos")
 
     def __unicode__(self):  return u'%s' % (self.name)
 
diff --git a/xos/core/static/xosNgLib.css b/xos/core/static/xosNgLib.css
index 35cb6fa..91a1574 100644
--- a/xos/core/static/xosNgLib.css
+++ b/xos/core/static/xosNgLib.css
@@ -27,6 +27,54 @@
     opacity: 0;
     transform: translate3d(0, 100%, 0); } }
 
+.loader {
+  font-size: 10px;
+  margin: 0 auto;
+  text-indent: -9999em;
+  width: 11em;
+  height: 11em;
+  border-radius: 50%;
+  background: #ffffff;
+  background: -moz-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+  background: -webkit-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+  background: -o-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+  background: -ms-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+  background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+  position: relative;
+  animation: loaderSpinner 1.4s infinite linear;
+  transform: translateZ(0); }
+
+.loader:before {
+  width: 50%;
+  height: 50%;
+  background: #337ab7;
+  border-radius: 100% 0 0 0;
+  position: absolute;
+  top: 0;
+  left: 0;
+  content: ''; }
+
+.loader:after {
+  background: #fff;
+  width: 75%;
+  height: 75%;
+  border-radius: 50%;
+  content: '';
+  margin: auto;
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0; }
+
+@keyframes loaderSpinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg); }
+  100% {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg); } }
+
 @keyframes slideInRight {
   from {
     transform: translate3d(100%, 0, 0);
@@ -113,6 +161,8 @@
     transform: translate3d(0, 100%, 0); } }
 
 xos-alert {
+  margin-top: 15px;
+  display: block;
   /* when hiding */
   /* when showing */ }
   xos-alert .ng-hide-add {
@@ -156,6 +206,38 @@
 xos-field {
   display: block; }
 
+@keyframes slideInRight {
+  from {
+    transform: translate3d(100%, 0, 0);
+    visibility: visible; }
+  to {
+    transform: translate3d(0, 0, 0); } }
+
+@keyframes slideOutRight {
+  from {
+    transform: translate3d(0, 0, 0); }
+  to {
+    visibility: hidden;
+    transform: translate3d(100%, 0, 0); } }
+
+@keyframes fadeInUp {
+  from {
+    opacity: 0;
+    transform: translate3d(0, 100%, 0); }
+  to {
+    opacity: 1;
+    transform: none; } }
+
+@keyframes fadeOutDown {
+  from {
+    opacity: 1; }
+  to {
+    opacity: 0;
+    transform: translate3d(0, 100%, 0); } }
+
+xos-form button {
+  margin-bottom: 15px; }
+
 [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
   display: none !important; }
 
@@ -163,4 +245,4 @@
   /* TODO move in xos.scss*/
   margin-top: 15px; }
 
-/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieG9zTmdMaWIuY3NzIiwic291cmNlcyI6WyJtYWluLnNjc3MiLCJhbmltYXRpb25zLnNjc3MiLCIuLi8uLi8uLi8uLi9zdHlsZS9zYXNzL2Jvb3RzdHJhcC9ib290c3RyYXAvX3ZhcmlhYmxlcy5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy90YWJsZS90YWJsZS5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9hbGVydC9hbGVydC5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy92YWxpZGF0aW9uL3ZhbGlkYXRpb24uc2NzcyIsIi4uL3VpX2NvbXBvbmVudHMvZHVtYkNvbXBvbmVudHMvZmllbGQvZmllbGQuc2NzcyIsIi4uL3VpX2NvbXBvbmVudHMvc21hcnRDb21wb25lbnRzL3NtYXJ0VGFibGUvc21hcnRUYWJsZS5zY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIkBpbXBvcnQgJy4vYW5pbWF0aW9ucy5zY3NzJztcbkBpbXBvcnQgJy4uLy4uLy4uLy4uLy4uL3ZpZXdzL3N0eWxlL3Nhc3MvYm9vdHN0cmFwL2Jvb3RzdHJhcC9fdmFyaWFibGVzLnNjc3MnO1xuXG5AaW1wb3J0ICcuLi91aV9jb21wb25lbnRzL2R1bWJDb21wb25lbnRzL3RhYmxlL3RhYmxlLnNjc3MnO1xuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9hbGVydC9hbGVydC5zY3NzJztcbkBpbXBvcnQgJy4uL3VpX2NvbXBvbmVudHMvZHVtYkNvbXBvbmVudHMvdmFsaWRhdGlvbi92YWxpZGF0aW9uLnNjc3MnO1xuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9maWVsZC9maWVsZC5zY3NzJztcblxuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9zbWFydENvbXBvbmVudHMvc21hcnRUYWJsZS9zbWFydFRhYmxlLnNjc3MnO1xuXG5bbmdcXDpjbG9ha10sIFtuZy1jbG9ha10sIFtkYXRhLW5nLWNsb2FrXSwgW3gtbmctY2xvYWtdLCAubmctY2xvYWssIC54LW5nLWNsb2FrIHtcbiAgZGlzcGxheTogbm9uZSAhaW1wb3J0YW50O1xufVxuXG4ucm93ICsgLnJvdyB7XG4gIC8qIFRPRE8gbW92ZSBpbiB4b3Muc2NzcyovIFxuICBtYXJnaW4tdG9wOiAkZm9ybS1ncm91cC1tYXJnaW4tYm90dG9tO1xufSIsIkBrZXlmcmFtZXMgc2xpZGVJblJpZ2h0IHtcbiAgZnJvbSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgxMDAlLCAwLCAwKTtcbiAgICB2aXNpYmlsaXR5OiB2aXNpYmxlO1xuICB9XG5cbiAgdG8ge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgMCwgMCk7XG4gIH1cbn1cblxuQGtleWZyYW1lcyBzbGlkZU91dFJpZ2h0IHtcbiAgZnJvbSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuXG4gIHRvIHtcbiAgICB2aXNpYmlsaXR5OiBoaWRkZW47XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgxMDAlLCAwLCAwKTtcbiAgfVxufVxuXG5Aa2V5ZnJhbWVzIGZhZGVJblVwIHtcbiAgZnJvbSB7XG4gICAgb3BhY2l0eTogMDtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDEwMCUsIDApO1xuICB9XG5cbiAgdG8ge1xuICAgIG9wYWNpdHk6IDE7XG4gICAgdHJhbnNmb3JtOiBub25lO1xuICB9XG59XG5cbkBrZXlmcmFtZXMgZmFkZU91dERvd24ge1xuICBmcm9tIHtcbiAgICBvcGFjaXR5OiAxO1xuICB9XG5cbiAgdG8ge1xuICAgIG9wYWNpdHk6IDA7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAxMDAlLCAwKTtcbiAgfVxufSIsIiRib290c3RyYXAtc2Fzcy1hc3NldC1oZWxwZXI6IGZhbHNlICFkZWZhdWx0O1xuLy9cbi8vIFZhcmlhYmxlc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXG4vLz09IENvbG9yc1xuLy9cbi8vIyMgR3JheSBhbmQgYnJhbmQgY29sb3JzIGZvciB1c2UgYWNyb3NzIEJvb3RzdHJhcC5cblxuJGdyYXktYmFzZTogICAgICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG4kZ3JheS1kYXJrZXI6ICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1iYXNlLCAxMy41JSkgIWRlZmF1bHQ7IC8vICMyMjJcbiRncmF5LWRhcms6ICAgICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDIwJSkgIWRlZmF1bHQ7ICAgLy8gIzMzM1xuJGdyYXk6ICAgICAgICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktYmFzZSwgMzMuNSUpICFkZWZhdWx0OyAvLyAjNTU1XG4kZ3JheS1saWdodDogICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1iYXNlLCA0Ni43JSkgIWRlZmF1bHQ7IC8vICM3NzdcbiRncmF5LWxpZ2h0ZXI6ICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDkzLjUlKSAhZGVmYXVsdDsgLy8gI2VlZVxuXG4kYnJhbmQtcHJpbWFyeTogICAgICAgICBkYXJrZW4oIzQyOGJjYSwgNi41JSkgIWRlZmF1bHQ7IC8vICMzMzdhYjdcbiRicmFuZC1zdWNjZXNzOiAgICAgICAgICM1Y2I4NWMgIWRlZmF1bHQ7XG4kYnJhbmQtaW5mbzogICAgICAgICAgICAjNWJjMGRlICFkZWZhdWx0O1xuJGJyYW5kLXdhcm5pbmc6ICAgICAgICAgI2YwYWQ0ZSAhZGVmYXVsdDtcbiRicmFuZC1kYW5nZXI6ICAgICAgICAgICNkOTUzNGYgIWRlZmF1bHQ7XG5cblxuLy89PSBTY2FmZm9sZGluZ1xuLy9cbi8vIyMgU2V0dGluZ3MgZm9yIHNvbWUgb2YgdGhlIG1vc3QgZ2xvYmFsIHN0eWxlcy5cblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIGZvciBgPGJvZHk+YC5cbiRib2R5LWJnOiAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIEdsb2JhbCB0ZXh0IGNvbG9yIG9uIGA8Ym9keT5gLlxuJHRleHQtY29sb3I6ICAgICAgICAgICAgJGdyYXktZGFyayAhZGVmYXVsdDtcblxuLy8qKiBHbG9iYWwgdGV4dHVhbCBsaW5rIGNvbG9yLlxuJGxpbmstY29sb3I6ICAgICAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG4vLyoqIExpbmsgaG92ZXIgY29sb3Igc2V0IHZpYSBgZGFya2VuKClgIGZ1bmN0aW9uLlxuJGxpbmstaG92ZXItY29sb3I6ICAgICAgZGFya2VuKCRsaW5rLWNvbG9yLCAxNSUpICFkZWZhdWx0O1xuLy8qKiBMaW5rIGhvdmVyIGRlY29yYXRpb24uXG4kbGluay1ob3Zlci1kZWNvcmF0aW9uOiB1bmRlcmxpbmUgIWRlZmF1bHQ7XG5cblxuLy89PSBUeXBvZ3JhcGh5XG4vL1xuLy8jIyBGb250LCBsaW5lLWhlaWdodCwgYW5kIGNvbG9yIGZvciBib2R5IHRleHQsIGhlYWRpbmdzLCBhbmQgbW9yZS5cblxuJGZvbnQtZmFtaWx5LXNhbnMtc2VyaWY6ICBcIkhlbHZldGljYSBOZXVlXCIsIEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWYgIWRlZmF1bHQ7XG4kZm9udC1mYW1pbHktc2VyaWY6ICAgICAgIEdlb3JnaWEsIFwiVGltZXMgTmV3IFJvbWFuXCIsIFRpbWVzLCBzZXJpZiAhZGVmYXVsdDtcbi8vKiogRGVmYXVsdCBtb25vc3BhY2UgZm9udHMgZm9yIGA8Y29kZT5gLCBgPGtiZD5gLCBhbmQgYDxwcmU+YC5cbiRmb250LWZhbWlseS1tb25vc3BhY2U6ICAgTWVubG8sIE1vbmFjbywgQ29uc29sYXMsIFwiQ291cmllciBOZXdcIiwgbW9ub3NwYWNlICFkZWZhdWx0O1xuJGZvbnQtZmFtaWx5LWJhc2U6ICAgICAgICAkZm9udC1mYW1pbHktc2Fucy1zZXJpZiAhZGVmYXVsdDtcblxuJGZvbnQtc2l6ZS1iYXNlOiAgICAgICAgICAxNHB4ICFkZWZhdWx0O1xuJGZvbnQtc2l6ZS1sYXJnZTogICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAxLjI1KSkgIWRlZmF1bHQ7IC8vIH4xOHB4XG4kZm9udC1zaXplLXNtYWxsOiAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDAuODUpKSAhZGVmYXVsdDsgLy8gfjEycHhcblxuJGZvbnQtc2l6ZS1oMTogICAgICAgICAgICBmbG9vcigoJGZvbnQtc2l6ZS1iYXNlICogMi42KSkgIWRlZmF1bHQ7IC8vIH4zNnB4XG4kZm9udC1zaXplLWgyOiAgICAgICAgICAgIGZsb29yKCgkZm9udC1zaXplLWJhc2UgKiAyLjE1KSkgIWRlZmF1bHQ7IC8vIH4zMHB4XG4kZm9udC1zaXplLWgzOiAgICAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDEuNykpICFkZWZhdWx0OyAvLyB+MjRweFxuJGZvbnQtc2l6ZS1oNDogICAgICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAxLjI1KSkgIWRlZmF1bHQ7IC8vIH4xOHB4XG4kZm9udC1zaXplLWg1OiAgICAgICAgICAgICRmb250LXNpemUtYmFzZSAhZGVmYXVsdDtcbiRmb250LXNpemUtaDY6ICAgICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMC44NSkpICFkZWZhdWx0OyAvLyB+MTJweFxuXG4vLyoqIFVuaXQtbGVzcyBgbGluZS1oZWlnaHRgIGZvciB1c2UgaW4gY29tcG9uZW50cyBsaWtlIGJ1dHRvbnMuXG4kbGluZS1oZWlnaHQtYmFzZTogICAgICAgIDEuNDI4NTcxNDI5ICFkZWZhdWx0OyAvLyAyMC8xNFxuLy8qKiBDb21wdXRlZCBcImxpbmUtaGVpZ2h0XCIgKGBmb250LXNpemVgICogYGxpbmUtaGVpZ2h0YCkgZm9yIHVzZSB3aXRoIGBtYXJnaW5gLCBgcGFkZGluZ2AsIGV0Yy5cbiRsaW5lLWhlaWdodC1jb21wdXRlZDogICAgZmxvb3IoKCRmb250LXNpemUtYmFzZSAqICRsaW5lLWhlaWdodC1iYXNlKSkgIWRlZmF1bHQ7IC8vIH4yMHB4XG5cbi8vKiogQnkgZGVmYXVsdCwgdGhpcyBpbmhlcml0cyBmcm9tIHRoZSBgPGJvZHk+YC5cbiRoZWFkaW5ncy1mb250LWZhbWlseTogICAgaW5oZXJpdCAhZGVmYXVsdDtcbiRoZWFkaW5ncy1mb250LXdlaWdodDogICAgNTAwICFkZWZhdWx0O1xuJGhlYWRpbmdzLWxpbmUtaGVpZ2h0OiAgICAxLjEgIWRlZmF1bHQ7XG4kaGVhZGluZ3MtY29sb3I6ICAgICAgICAgIGluaGVyaXQgIWRlZmF1bHQ7XG5cblxuLy89PSBJY29ub2dyYXBoeVxuLy9cbi8vIyMgU3BlY2lmeSBjdXN0b20gbG9jYXRpb24gYW5kIGZpbGVuYW1lIG9mIHRoZSBpbmNsdWRlZCBHbHlwaGljb25zIGljb24gZm9udC4gVXNlZnVsIGZvciB0aG9zZSBpbmNsdWRpbmcgQm9vdHN0cmFwIHZpYSBCb3dlci5cblxuLy8qKiBMb2FkIGZvbnRzIGZyb20gdGhpcyBkaXJlY3RvcnkuXG5cbi8vIFtjb252ZXJ0ZXJdIElmICRib290c3RyYXAtc2Fzcy1hc3NldC1oZWxwZXIgaWYgdXNlZCwgcHJvdmlkZSBwYXRoIHJlbGF0aXZlIHRvIHRoZSBhc3NldHMgbG9hZCBwYXRoLlxuLy8gW2NvbnZlcnRlcl0gVGhpcyBpcyBiZWNhdXNlIHNvbWUgYXNzZXQgaGVscGVycywgc3VjaCBhcyBTcHJvY2tldHMsIGRvIG5vdCB3b3JrIHdpdGggZmlsZS1yZWxhdGl2ZSBwYXRocy5cbiRpY29uLWZvbnQtcGF0aDogaWYoJGJvb3RzdHJhcC1zYXNzLWFzc2V0LWhlbHBlciwgXCJib290c3RyYXAvXCIsIFwiLi4vZm9udHMvYm9vdHN0cmFwL1wiKSAhZGVmYXVsdDtcblxuLy8qKiBGaWxlIG5hbWUgZm9yIGFsbCBmb250IGZpbGVzLlxuJGljb24tZm9udC1uYW1lOiAgICAgICAgICBcImdseXBoaWNvbnMtaGFsZmxpbmdzLXJlZ3VsYXJcIiAhZGVmYXVsdDtcbi8vKiogRWxlbWVudCBJRCB3aXRoaW4gU1ZHIGljb24gZmlsZS5cbiRpY29uLWZvbnQtc3ZnLWlkOiAgICAgICAgXCJnbHlwaGljb25zX2hhbGZsaW5nc3JlZ3VsYXJcIiAhZGVmYXVsdDtcblxuXG4vLz09IENvbXBvbmVudHNcbi8vXG4vLyMjIERlZmluZSBjb21tb24gcGFkZGluZyBhbmQgYm9yZGVyIHJhZGl1cyBzaXplcyBhbmQgbW9yZS4gVmFsdWVzIGJhc2VkIG9uIDE0cHggdGV4dCBhbmQgMS40MjggbGluZS1oZWlnaHQgKH4yMHB4IHRvIHN0YXJ0KS5cblxuJHBhZGRpbmctYmFzZS12ZXJ0aWNhbDogICAgIDZweCAhZGVmYXVsdDtcbiRwYWRkaW5nLWJhc2UtaG9yaXpvbnRhbDogICAxMnB4ICFkZWZhdWx0O1xuXG4kcGFkZGluZy1sYXJnZS12ZXJ0aWNhbDogICAgMTBweCAhZGVmYXVsdDtcbiRwYWRkaW5nLWxhcmdlLWhvcml6b250YWw6ICAxNnB4ICFkZWZhdWx0O1xuXG4kcGFkZGluZy1zbWFsbC12ZXJ0aWNhbDogICAgNXB4ICFkZWZhdWx0O1xuJHBhZGRpbmctc21hbGwtaG9yaXpvbnRhbDogIDEwcHggIWRlZmF1bHQ7XG5cbiRwYWRkaW5nLXhzLXZlcnRpY2FsOiAgICAgICAxcHggIWRlZmF1bHQ7XG4kcGFkZGluZy14cy1ob3Jpem9udGFsOiAgICAgNXB4ICFkZWZhdWx0O1xuXG4kbGluZS1oZWlnaHQtbGFyZ2U6ICAgICAgICAgMS4zMzMzMzMzICFkZWZhdWx0OyAvLyBleHRyYSBkZWNpbWFscyBmb3IgV2luIDguMSBDaHJvbWVcbiRsaW5lLWhlaWdodC1zbWFsbDogICAgICAgICAxLjUgIWRlZmF1bHQ7XG5cbiRib3JkZXItcmFkaXVzLWJhc2U6ICAgICAgICA0cHggIWRlZmF1bHQ7XG4kYm9yZGVyLXJhZGl1cy1sYXJnZTogICAgICAgNnB4ICFkZWZhdWx0O1xuJGJvcmRlci1yYWRpdXMtc21hbGw6ICAgICAgIDNweCAhZGVmYXVsdDtcblxuLy8qKiBHbG9iYWwgY29sb3IgZm9yIGFjdGl2ZSBpdGVtcyAoZS5nLiwgbmF2cyBvciBkcm9wZG93bnMpLlxuJGNvbXBvbmVudC1hY3RpdmUtY29sb3I6ICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIEdsb2JhbCBiYWNrZ3JvdW5kIGNvbG9yIGZvciBhY3RpdmUgaXRlbXMgKGUuZy4sIG5hdnMgb3IgZHJvcGRvd25zKS5cbiRjb21wb25lbnQtYWN0aXZlLWJnOiAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcblxuLy8qKiBXaWR0aCBvZiB0aGUgYGJvcmRlcmAgZm9yIGdlbmVyYXRpbmcgY2FyZXRzIHRoYXQgaW5kaWNhdG9yIGRyb3Bkb3ducy5cbiRjYXJldC13aWR0aC1iYXNlOiAgICAgICAgICA0cHggIWRlZmF1bHQ7XG4vLyoqIENhcmV0cyBpbmNyZWFzZSBzbGlnaHRseSBpbiBzaXplIGZvciBsYXJnZXIgY29tcG9uZW50cy5cbiRjYXJldC13aWR0aC1sYXJnZTogICAgICAgICA1cHggIWRlZmF1bHQ7XG5cblxuLy89PSBUYWJsZXNcbi8vXG4vLyMjIEN1c3RvbWl6ZXMgdGhlIGAudGFibGVgIGNvbXBvbmVudCB3aXRoIGJhc2ljIHZhbHVlcywgZWFjaCB1c2VkIGFjcm9zcyBhbGwgdGFibGUgdmFyaWF0aW9ucy5cblxuLy8qKiBQYWRkaW5nIGZvciBgPHRoPmBzIGFuZCBgPHRkPmBzLlxuJHRhYmxlLWNlbGwtcGFkZGluZzogICAgICAgICAgICA4cHggIWRlZmF1bHQ7XG4vLyoqIFBhZGRpbmcgZm9yIGNlbGxzIGluIGAudGFibGUtY29uZGVuc2VkYC5cbiR0YWJsZS1jb25kZW5zZWQtY2VsbC1wYWRkaW5nOiAgNXB4ICFkZWZhdWx0O1xuXG4vLyoqIERlZmF1bHQgYmFja2dyb3VuZCBjb2xvciB1c2VkIGZvciBhbGwgdGFibGVzLlxuJHRhYmxlLWJnOiAgICAgICAgICAgICAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcbi8vKiogQmFja2dyb3VuZCBjb2xvciB1c2VkIGZvciBgLnRhYmxlLXN0cmlwZWRgLlxuJHRhYmxlLWJnLWFjY2VudDogICAgICAgICAgICAgICAjZjlmOWY5ICFkZWZhdWx0O1xuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIHVzZWQgZm9yIGAudGFibGUtaG92ZXJgLlxuJHRhYmxlLWJnLWhvdmVyOiAgICAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuJHRhYmxlLWJnLWFjdGl2ZTogICAgICAgICAgICAgICAkdGFibGUtYmctaG92ZXIgIWRlZmF1bHQ7XG5cbi8vKiogQm9yZGVyIGNvbG9yIGZvciB0YWJsZSBhbmQgY2VsbCBib3JkZXJzLlxuJHRhYmxlLWJvcmRlci1jb2xvcjogICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG5cbi8vPT0gQnV0dG9uc1xuLy9cbi8vIyMgRm9yIGVhY2ggb2YgQm9vdHN0cmFwJ3MgYnV0dG9ucywgZGVmaW5lIHRleHQsIGJhY2tncm91bmQgYW5kIGJvcmRlciBjb2xvci5cblxuJGJ0bi1mb250LXdlaWdodDogICAgICAgICAgICAgICAgbm9ybWFsICFkZWZhdWx0O1xuXG4kYnRuLWRlZmF1bHQtY29sb3I6ICAgICAgICAgICAgICAjMzMzICFkZWZhdWx0O1xuJGJ0bi1kZWZhdWx0LWJnOiAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4tZGVmYXVsdC1ib3JkZXI6ICAgICAgICAgICAgICNjY2MgIWRlZmF1bHQ7XG5cbiRidG4tcHJpbWFyeS1jb2xvcjogICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYnRuLXByaW1hcnktYmc6ICAgICAgICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbiRidG4tcHJpbWFyeS1ib3JkZXI6ICAgICAgICAgICAgIGRhcmtlbigkYnRuLXByaW1hcnktYmcsIDUlKSAhZGVmYXVsdDtcblxuJGJ0bi1zdWNjZXNzLWNvbG9yOiAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4tc3VjY2Vzcy1iZzogICAgICAgICAgICAgICAgICRicmFuZC1zdWNjZXNzICFkZWZhdWx0O1xuJGJ0bi1zdWNjZXNzLWJvcmRlcjogICAgICAgICAgICAgZGFya2VuKCRidG4tc3VjY2Vzcy1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLWluZm8tY29sb3I6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1pbmZvLWJnOiAgICAgICAgICAgICAgICAgICAgJGJyYW5kLWluZm8gIWRlZmF1bHQ7XG4kYnRuLWluZm8tYm9yZGVyOiAgICAgICAgICAgICAgICBkYXJrZW4oJGJ0bi1pbmZvLWJnLCA1JSkgIWRlZmF1bHQ7XG5cbiRidG4td2FybmluZy1jb2xvcjogICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYnRuLXdhcm5pbmctYmc6ICAgICAgICAgICAgICAgICAkYnJhbmQtd2FybmluZyAhZGVmYXVsdDtcbiRidG4td2FybmluZy1ib3JkZXI6ICAgICAgICAgICAgIGRhcmtlbigkYnRuLXdhcm5pbmctYmcsIDUlKSAhZGVmYXVsdDtcblxuJGJ0bi1kYW5nZXItY29sb3I6ICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4tZGFuZ2VyLWJnOiAgICAgICAgICAgICAgICAgICRicmFuZC1kYW5nZXIgIWRlZmF1bHQ7XG4kYnRuLWRhbmdlci1ib3JkZXI6ICAgICAgICAgICAgICBkYXJrZW4oJGJ0bi1kYW5nZXItYmcsIDUlKSAhZGVmYXVsdDtcblxuJGJ0bi1saW5rLWRpc2FibGVkLWNvbG9yOiAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG5cbi8vIEFsbG93cyBmb3IgY3VzdG9taXppbmcgYnV0dG9uIHJhZGl1cyBpbmRlcGVuZGVudGx5IGZyb20gZ2xvYmFsIGJvcmRlciByYWRpdXNcbiRidG4tYm9yZGVyLXJhZGl1cy1iYXNlOiAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4kYnRuLWJvcmRlci1yYWRpdXMtbGFyZ2U6ICAgICAgICAkYm9yZGVyLXJhZGl1cy1sYXJnZSAhZGVmYXVsdDtcbiRidG4tYm9yZGVyLXJhZGl1cy1zbWFsbDogICAgICAgICRib3JkZXItcmFkaXVzLXNtYWxsICFkZWZhdWx0O1xuXG5cbi8vPT0gRm9ybXNcbi8vXG4vLyMjXG5cbi8vKiogYDxpbnB1dD5gIGJhY2tncm91bmQgY29sb3JcbiRpbnB1dC1iZzogICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIGA8aW5wdXQgZGlzYWJsZWQ+YCBiYWNrZ3JvdW5kIGNvbG9yXG4kaW5wdXQtYmctZGlzYWJsZWQ6ICAgICAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuXG4vLyoqIFRleHQgY29sb3IgZm9yIGA8aW5wdXQ+YHNcbiRpbnB1dC1jb2xvcjogICAgICAgICAgICAgICAgICAgICRncmF5ICFkZWZhdWx0O1xuLy8qKiBgPGlucHV0PmAgYm9yZGVyIGNvbG9yXG4kaW5wdXQtYm9yZGVyOiAgICAgICAgICAgICAgICAgICAjY2NjICFkZWZhdWx0O1xuXG4vLyBUT0RPOiBSZW5hbWUgYCRpbnB1dC1ib3JkZXItcmFkaXVzYCB0byBgJGlucHV0LWJvcmRlci1yYWRpdXMtYmFzZWAgaW4gdjRcbi8vKiogRGVmYXVsdCBgLmZvcm0tY29udHJvbGAgYm9yZGVyIHJhZGl1c1xuLy8gVGhpcyBoYXMgbm8gZWZmZWN0IG9uIGA8c2VsZWN0PmBzIGluIHNvbWUgYnJvd3NlcnMsIGR1ZSB0byB0aGUgbGltaXRlZCBzdHlsYWJpbGl0eSBvZiBgPHNlbGVjdD5gcyBpbiBDU1MuXG4kaW5wdXQtYm9yZGVyLXJhZGl1czogICAgICAgICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuLy8qKiBMYXJnZSBgLmZvcm0tY29udHJvbGAgYm9yZGVyIHJhZGl1c1xuJGlucHV0LWJvcmRlci1yYWRpdXMtbGFyZ2U6ICAgICAgJGJvcmRlci1yYWRpdXMtbGFyZ2UgIWRlZmF1bHQ7XG4vLyoqIFNtYWxsIGAuZm9ybS1jb250cm9sYCBib3JkZXIgcmFkaXVzXG4kaW5wdXQtYm9yZGVyLXJhZGl1cy1zbWFsbDogICAgICAkYm9yZGVyLXJhZGl1cy1zbWFsbCAhZGVmYXVsdDtcblxuLy8qKiBCb3JkZXIgY29sb3IgZm9yIGlucHV0cyBvbiBmb2N1c1xuJGlucHV0LWJvcmRlci1mb2N1czogICAgICAgICAgICAgIzY2YWZlOSAhZGVmYXVsdDtcblxuLy8qKiBQbGFjZWhvbGRlciB0ZXh0IGNvbG9yXG4kaW5wdXQtY29sb3ItcGxhY2Vob2xkZXI6ICAgICAgICAjOTk5ICFkZWZhdWx0O1xuXG4vLyoqIERlZmF1bHQgYC5mb3JtLWNvbnRyb2xgIGhlaWdodFxuJGlucHV0LWhlaWdodC1iYXNlOiAgICAgICAgICAgICAgKCRsaW5lLWhlaWdodC1jb21wdXRlZCArICgkcGFkZGluZy1iYXNlLXZlcnRpY2FsICogMikgKyAyKSAhZGVmYXVsdDtcbi8vKiogTGFyZ2UgYC5mb3JtLWNvbnRyb2xgIGhlaWdodFxuJGlucHV0LWhlaWdodC1sYXJnZTogICAgICAgICAgICAgKGNlaWwoJGZvbnQtc2l6ZS1sYXJnZSAqICRsaW5lLWhlaWdodC1sYXJnZSkgKyAoJHBhZGRpbmctbGFyZ2UtdmVydGljYWwgKiAyKSArIDIpICFkZWZhdWx0O1xuLy8qKiBTbWFsbCBgLmZvcm0tY29udHJvbGAgaGVpZ2h0XG4kaW5wdXQtaGVpZ2h0LXNtYWxsOiAgICAgICAgICAgICAoZmxvb3IoJGZvbnQtc2l6ZS1zbWFsbCAqICRsaW5lLWhlaWdodC1zbWFsbCkgKyAoJHBhZGRpbmctc21hbGwtdmVydGljYWwgKiAyKSArIDIpICFkZWZhdWx0O1xuXG4vLyoqIGAuZm9ybS1ncm91cGAgbWFyZ2luXG4kZm9ybS1ncm91cC1tYXJnaW4tYm90dG9tOiAgICAgICAxNXB4ICFkZWZhdWx0O1xuXG4kbGVnZW5kLWNvbG9yOiAgICAgICAgICAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuJGxlZ2VuZC1ib3JkZXItY29sb3I6ICAgICAgICAgICAgI2U1ZTVlNSAhZGVmYXVsdDtcblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIGZvciB0ZXh0dWFsIGlucHV0IGFkZG9uc1xuJGlucHV0LWdyb3VwLWFkZG9uLWJnOiAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbi8vKiogQm9yZGVyIGNvbG9yIGZvciB0ZXh0dWFsIGlucHV0IGFkZG9uc1xuJGlucHV0LWdyb3VwLWFkZG9uLWJvcmRlci1jb2xvcjogJGlucHV0LWJvcmRlciAhZGVmYXVsdDtcblxuLy8qKiBEaXNhYmxlZCBjdXJzb3IgZm9yIGZvcm0gY29udHJvbHMgYW5kIGJ1dHRvbnMuXG4kY3Vyc29yLWRpc2FibGVkOiAgICAgICAgICAgICAgICBub3QtYWxsb3dlZCAhZGVmYXVsdDtcblxuXG4vLz09IERyb3Bkb3duc1xuLy9cbi8vIyMgRHJvcGRvd24gbWVudSBjb250YWluZXIgYW5kIGNvbnRlbnRzLlxuXG4vLyoqIEJhY2tncm91bmQgZm9yIHRoZSBkcm9wZG93biBtZW51LlxuJGRyb3Bkb3duLWJnOiAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogRHJvcGRvd24gbWVudSBgYm9yZGVyLWNvbG9yYC5cbiRkcm9wZG93bi1ib3JkZXI6ICAgICAgICAgICAgICAgIHJnYmEoMCwwLDAsLjE1KSAhZGVmYXVsdDtcbi8vKiogRHJvcGRvd24gbWVudSBgYm9yZGVyLWNvbG9yYCAqKmZvciBJRTgqKi5cbiRkcm9wZG93bi1mYWxsYmFjay1ib3JkZXI6ICAgICAgICNjY2MgIWRlZmF1bHQ7XG4vLyoqIERpdmlkZXIgY29sb3IgZm9yIGJldHdlZW4gZHJvcGRvd24gaXRlbXMuXG4kZHJvcGRvd24tZGl2aWRlci1iZzogICAgICAgICAgICAjZTVlNWU1ICFkZWZhdWx0O1xuXG4vLyoqIERyb3Bkb3duIGxpbmsgdGV4dCBjb2xvci5cbiRkcm9wZG93bi1saW5rLWNvbG9yOiAgICAgICAgICAgICRncmF5LWRhcmsgIWRlZmF1bHQ7XG4vLyoqIEhvdmVyIGNvbG9yIGZvciBkcm9wZG93biBsaW5rcy5cbiRkcm9wZG93bi1saW5rLWhvdmVyLWNvbG9yOiAgICAgIGRhcmtlbigkZ3JheS1kYXJrLCA1JSkgIWRlZmF1bHQ7XG4vLyoqIEhvdmVyIGJhY2tncm91bmQgZm9yIGRyb3Bkb3duIGxpbmtzLlxuJGRyb3Bkb3duLWxpbmstaG92ZXItYmc6ICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcblxuLy8qKiBBY3RpdmUgZHJvcGRvd24gbWVudSBpdGVtIHRleHQgY29sb3IuXG4kZHJvcGRvd24tbGluay1hY3RpdmUtY29sb3I6ICAgICAkY29tcG9uZW50LWFjdGl2ZS1jb2xvciAhZGVmYXVsdDtcbi8vKiogQWN0aXZlIGRyb3Bkb3duIG1lbnUgaXRlbSBiYWNrZ3JvdW5kIGNvbG9yLlxuJGRyb3Bkb3duLWxpbmstYWN0aXZlLWJnOiAgICAgICAgJGNvbXBvbmVudC1hY3RpdmUtYmcgIWRlZmF1bHQ7XG5cbi8vKiogRGlzYWJsZWQgZHJvcGRvd24gbWVudSBpdGVtIGJhY2tncm91bmQgY29sb3IuXG4kZHJvcGRvd24tbGluay1kaXNhYmxlZC1jb2xvcjogICAkZ3JheS1saWdodCAhZGVmYXVsdDtcblxuLy8qKiBUZXh0IGNvbG9yIGZvciBoZWFkZXJzIHdpdGhpbiBkcm9wZG93biBtZW51cy5cbiRkcm9wZG93bi1oZWFkZXItY29sb3I6ICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLyoqIERlcHJlY2F0ZWQgYCRkcm9wZG93bi1jYXJldC1jb2xvcmAgYXMgb2YgdjMuMS4wXG4kZHJvcGRvd24tY2FyZXQtY29sb3I6ICAgICAgICAgICAjMDAwICFkZWZhdWx0O1xuXG5cbi8vLS0gWi1pbmRleCBtYXN0ZXIgbGlzdFxuLy9cbi8vIFdhcm5pbmc6IEF2b2lkIGN1c3RvbWl6aW5nIHRoZXNlIHZhbHVlcy4gVGhleSdyZSB1c2VkIGZvciBhIGJpcmQncyBleWUgdmlld1xuLy8gb2YgY29tcG9uZW50cyBkZXBlbmRlbnQgb24gdGhlIHotYXhpcyBhbmQgYXJlIGRlc2lnbmVkIHRvIGFsbCB3b3JrIHRvZ2V0aGVyLlxuLy9cbi8vIE5vdGU6IFRoZXNlIHZhcmlhYmxlcyBhcmUgbm90IGdlbmVyYXRlZCBpbnRvIHRoZSBDdXN0b21pemVyLlxuXG4kemluZGV4LW5hdmJhcjogICAgICAgICAgICAxMDAwICFkZWZhdWx0O1xuJHppbmRleC1kcm9wZG93bjogICAgICAgICAgMTAwMCAhZGVmYXVsdDtcbiR6aW5kZXgtcG9wb3ZlcjogICAgICAgICAgIDEwNjAgIWRlZmF1bHQ7XG4kemluZGV4LXRvb2x0aXA6ICAgICAgICAgICAxMDcwICFkZWZhdWx0O1xuJHppbmRleC1uYXZiYXItZml4ZWQ6ICAgICAgMTAzMCAhZGVmYXVsdDtcbiR6aW5kZXgtbW9kYWwtYmFja2dyb3VuZDogIDEwNDAgIWRlZmF1bHQ7XG4kemluZGV4LW1vZGFsOiAgICAgICAgICAgICAxMDUwICFkZWZhdWx0O1xuXG5cbi8vPT0gTWVkaWEgcXVlcmllcyBicmVha3BvaW50c1xuLy9cbi8vIyMgRGVmaW5lIHRoZSBicmVha3BvaW50cyBhdCB3aGljaCB5b3VyIGxheW91dCB3aWxsIGNoYW5nZSwgYWRhcHRpbmcgdG8gZGlmZmVyZW50IHNjcmVlbiBzaXplcy5cblxuLy8gRXh0cmEgc21hbGwgc2NyZWVuIC8gcGhvbmVcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi14c2AgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXhzOiAgICAgICAgICAgICAgICAgIDQ4MHB4ICFkZWZhdWx0O1xuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLXhzLW1pbmAgYXMgb2YgdjMuMi4wXG4kc2NyZWVuLXhzLW1pbjogICAgICAgICAgICAgICRzY3JlZW4teHMgIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tcGhvbmVgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi1waG9uZTogICAgICAgICAgICAgICAkc2NyZWVuLXhzLW1pbiAhZGVmYXVsdDtcblxuLy8gU21hbGwgc2NyZWVuIC8gdGFibGV0XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tc21gIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi1zbTogICAgICAgICAgICAgICAgICA3NjhweCAhZGVmYXVsdDtcbiRzY3JlZW4tc20tbWluOiAgICAgICAgICAgICAgJHNjcmVlbi1zbSAhZGVmYXVsdDtcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi10YWJsZXRgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi10YWJsZXQ6ICAgICAgICAgICAgICAkc2NyZWVuLXNtLW1pbiAhZGVmYXVsdDtcblxuLy8gTWVkaXVtIHNjcmVlbiAvIGRlc2t0b3Bcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1tZGAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLW1kOiAgICAgICAgICAgICAgICAgIDk5MnB4ICFkZWZhdWx0O1xuJHNjcmVlbi1tZC1taW46ICAgICAgICAgICAgICAkc2NyZWVuLW1kICFkZWZhdWx0O1xuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLWRlc2t0b3BgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi1kZXNrdG9wOiAgICAgICAgICAgICAkc2NyZWVuLW1kLW1pbiAhZGVmYXVsdDtcblxuLy8gTGFyZ2Ugc2NyZWVuIC8gd2lkZSBkZXNrdG9wXG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tbGdgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi1sZzogICAgICAgICAgICAgICAgICAxMjAwcHggIWRlZmF1bHQ7XG4kc2NyZWVuLWxnLW1pbjogICAgICAgICAgICAgICRzY3JlZW4tbGcgIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tbGctZGVza3RvcGAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLWxnLWRlc2t0b3A6ICAgICAgICAgICRzY3JlZW4tbGctbWluICFkZWZhdWx0O1xuXG4vLyBTbyBtZWRpYSBxdWVyaWVzIGRvbid0IG92ZXJsYXAgd2hlbiByZXF1aXJlZCwgcHJvdmlkZSBhIG1heGltdW1cbiRzY3JlZW4teHMtbWF4OiAgICAgICAgICAgICAgKCRzY3JlZW4tc20tbWluIC0gMSkgIWRlZmF1bHQ7XG4kc2NyZWVuLXNtLW1heDogICAgICAgICAgICAgICgkc2NyZWVuLW1kLW1pbiAtIDEpICFkZWZhdWx0O1xuJHNjcmVlbi1tZC1tYXg6ICAgICAgICAgICAgICAoJHNjcmVlbi1sZy1taW4gLSAxKSAhZGVmYXVsdDtcblxuXG4vLz09IEdyaWQgc3lzdGVtXG4vL1xuLy8jIyBEZWZpbmUgeW91ciBjdXN0b20gcmVzcG9uc2l2ZSBncmlkLlxuXG4vLyoqIE51bWJlciBvZiBjb2x1bW5zIGluIHRoZSBncmlkLlxuJGdyaWQtY29sdW1uczogICAgICAgICAgICAgIDEyICFkZWZhdWx0O1xuLy8qKiBQYWRkaW5nIGJldHdlZW4gY29sdW1ucy4gR2V0cyBkaXZpZGVkIGluIGhhbGYgZm9yIHRoZSBsZWZ0IGFuZCByaWdodC5cbiRncmlkLWd1dHRlci13aWR0aDogICAgICAgICAzMHB4ICFkZWZhdWx0O1xuLy8gTmF2YmFyIGNvbGxhcHNlXG4vLyoqIFBvaW50IGF0IHdoaWNoIHRoZSBuYXZiYXIgYmVjb21lcyB1bmNvbGxhcHNlZC5cbiRncmlkLWZsb2F0LWJyZWFrcG9pbnQ6ICAgICAkc2NyZWVuLXNtLW1pbiAhZGVmYXVsdDtcbi8vKiogUG9pbnQgYXQgd2hpY2ggdGhlIG5hdmJhciBiZWdpbnMgY29sbGFwc2luZy5cbiRncmlkLWZsb2F0LWJyZWFrcG9pbnQtbWF4OiAoJGdyaWQtZmxvYXQtYnJlYWtwb2ludCAtIDEpICFkZWZhdWx0O1xuXG5cbi8vPT0gQ29udGFpbmVyIHNpemVzXG4vL1xuLy8jIyBEZWZpbmUgdGhlIG1heGltdW0gd2lkdGggb2YgYC5jb250YWluZXJgIGZvciBkaWZmZXJlbnQgc2NyZWVuIHNpemVzLlxuXG4vLyBTbWFsbCBzY3JlZW4gLyB0YWJsZXRcbiRjb250YWluZXItdGFibGV0OiAgICAgICAgICAgICAoNzIwcHggKyAkZ3JpZC1ndXR0ZXItd2lkdGgpICFkZWZhdWx0O1xuLy8qKiBGb3IgYCRzY3JlZW4tc20tbWluYCBhbmQgdXAuXG4kY29udGFpbmVyLXNtOiAgICAgICAgICAgICAgICAgJGNvbnRhaW5lci10YWJsZXQgIWRlZmF1bHQ7XG5cbi8vIE1lZGl1bSBzY3JlZW4gLyBkZXNrdG9wXG4kY29udGFpbmVyLWRlc2t0b3A6ICAgICAgICAgICAgKDk0MHB4ICsgJGdyaWQtZ3V0dGVyLXdpZHRoKSAhZGVmYXVsdDtcbi8vKiogRm9yIGAkc2NyZWVuLW1kLW1pbmAgYW5kIHVwLlxuJGNvbnRhaW5lci1tZDogICAgICAgICAgICAgICAgICRjb250YWluZXItZGVza3RvcCAhZGVmYXVsdDtcblxuLy8gTGFyZ2Ugc2NyZWVuIC8gd2lkZSBkZXNrdG9wXG4kY29udGFpbmVyLWxhcmdlLWRlc2t0b3A6ICAgICAgKDExNDBweCArICRncmlkLWd1dHRlci13aWR0aCkgIWRlZmF1bHQ7XG4vLyoqIEZvciBgJHNjcmVlbi1sZy1taW5gIGFuZCB1cC5cbiRjb250YWluZXItbGc6ICAgICAgICAgICAgICAgICAkY29udGFpbmVyLWxhcmdlLWRlc2t0b3AgIWRlZmF1bHQ7XG5cblxuLy89PSBOYXZiYXJcbi8vXG4vLyMjXG5cbi8vIEJhc2ljcyBvZiBhIG5hdmJhclxuJG5hdmJhci1oZWlnaHQ6ICAgICAgICAgICAgICAgICAgICA1MHB4ICFkZWZhdWx0O1xuJG5hdmJhci1tYXJnaW4tYm90dG9tOiAgICAgICAgICAgICAkbGluZS1oZWlnaHQtY29tcHV0ZWQgIWRlZmF1bHQ7XG4kbmF2YmFyLWJvcmRlci1yYWRpdXM6ICAgICAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4kbmF2YmFyLXBhZGRpbmctaG9yaXpvbnRhbDogICAgICAgIGZsb29yKCgkZ3JpZC1ndXR0ZXItd2lkdGggLyAyKSkgIWRlZmF1bHQ7XG4kbmF2YmFyLXBhZGRpbmctdmVydGljYWw6ICAgICAgICAgICgoJG5hdmJhci1oZWlnaHQgLSAkbGluZS1oZWlnaHQtY29tcHV0ZWQpIC8gMikgIWRlZmF1bHQ7XG4kbmF2YmFyLWNvbGxhcHNlLW1heC1oZWlnaHQ6ICAgICAgIDM0MHB4ICFkZWZhdWx0O1xuXG4kbmF2YmFyLWRlZmF1bHQtY29sb3I6ICAgICAgICAgICAgICM3NzcgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtYmc6ICAgICAgICAgICAgICAgICNmOGY4ZjggIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtYm9yZGVyOiAgICAgICAgICAgIGRhcmtlbigkbmF2YmFyLWRlZmF1bHQtYmcsIDYuNSUpICFkZWZhdWx0O1xuXG4vLyBOYXZiYXIgbGlua3NcbiRuYXZiYXItZGVmYXVsdC1saW5rLWNvbG9yOiAgICAgICAgICAgICAgICAjNzc3ICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgICMzMzMgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1hY3RpdmUtY29sb3I6ICAgICAgICAgIzU1NSAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWFjdGl2ZS1iZzogICAgICAgICAgICBkYXJrZW4oJG5hdmJhci1kZWZhdWx0LWJnLCA2LjUlKSAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWRpc2FibGVkLWNvbG9yOiAgICAgICAjY2NjICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstZGlzYWJsZWQtYmc6ICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuXG4vLyBOYXZiYXIgYnJhbmQgbGFiZWxcbiRuYXZiYXItZGVmYXVsdC1icmFuZC1jb2xvcjogICAgICAgICAgICAgICAkbmF2YmFyLWRlZmF1bHQtbGluay1jb2xvciAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1icmFuZC1ob3Zlci1jb2xvcjogICAgICAgICBkYXJrZW4oJG5hdmJhci1kZWZhdWx0LWJyYW5kLWNvbG9yLCAxMCUpICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWJyYW5kLWhvdmVyLWJnOiAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuXG4vLyBOYXZiYXIgdG9nZ2xlXG4kbmF2YmFyLWRlZmF1bHQtdG9nZ2xlLWhvdmVyLWJnOiAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC10b2dnbGUtaWNvbi1iYXItYmc6ICAgICAgICAjODg4ICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LXRvZ2dsZS1ib3JkZXItY29sb3I6ICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cblxuLy89PT0gSW52ZXJ0ZWQgbmF2YmFyXG4vLyBSZXNldCBpbnZlcnRlZCBuYXZiYXIgYmFzaWNzXG4kbmF2YmFyLWludmVyc2UtY29sb3I6ICAgICAgICAgICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktbGlnaHQsIDE1JSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICMyMjIgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtYm9yZGVyOiAgICAgICAgICAgICAgICAgICAgIGRhcmtlbigkbmF2YmFyLWludmVyc2UtYmcsIDEwJSkgIWRlZmF1bHQ7XG5cbi8vIEludmVydGVkIG5hdmJhciBsaW5rc1xuJG5hdmJhci1pbnZlcnNlLWxpbmstY29sb3I6ICAgICAgICAgICAgICAgICBsaWdodGVuKCRncmF5LWxpZ2h0LCAxNSUpICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWxpbmstaG92ZXItYmc6ICAgICAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWFjdGl2ZS1jb2xvcjogICAgICAgICAgJG5hdmJhci1pbnZlcnNlLWxpbmstaG92ZXItY29sb3IgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1hY3RpdmUtYmc6ICAgICAgICAgICAgIGRhcmtlbigkbmF2YmFyLWludmVyc2UtYmcsIDEwJSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1kaXNhYmxlZC1jb2xvcjogICAgICAgICM0NDQgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1kaXNhYmxlZC1iZzogICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuXG4vLyBJbnZlcnRlZCBuYXZiYXIgYnJhbmQgbGFiZWxcbiRuYXZiYXItaW52ZXJzZS1icmFuZC1jb2xvcjogICAgICAgICAgICAgICAgJG5hdmJhci1pbnZlcnNlLWxpbmstY29sb3IgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtYnJhbmQtaG92ZXItY29sb3I6ICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtYnJhbmQtaG92ZXItYmc6ICAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuXG4vLyBJbnZlcnRlZCBuYXZiYXIgdG9nZ2xlXG4kbmF2YmFyLWludmVyc2UtdG9nZ2xlLWhvdmVyLWJnOiAgICAgICAgICAgICMzMzMgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtdG9nZ2xlLWljb24tYmFyLWJnOiAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtdG9nZ2xlLWJvcmRlci1jb2xvcjogICAgICAgICMzMzMgIWRlZmF1bHQ7XG5cblxuLy89PSBOYXZzXG4vL1xuLy8jI1xuXG4vLz09PSBTaGFyZWQgbmF2IHN0eWxlc1xuJG5hdi1saW5rLXBhZGRpbmc6ICAgICAgICAgICAgICAgICAgICAgICAgICAxMHB4IDE1cHggIWRlZmF1bHQ7XG4kbmF2LWxpbmstaG92ZXItYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG5cbiRuYXYtZGlzYWJsZWQtbGluay1jb2xvcjogICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4kbmF2LWRpc2FibGVkLWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLz09IFRhYnNcbiRuYXYtdGFicy1ib3JkZXItY29sb3I6ICAgICAgICAgICAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcblxuJG5hdi10YWJzLWxpbmstaG92ZXItYm9yZGVyLWNvbG9yOiAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuXG4kbmF2LXRhYnMtYWN0aXZlLWxpbmstaG92ZXItYmc6ICAgICAgICAgICAgICRib2R5LWJnICFkZWZhdWx0O1xuJG5hdi10YWJzLWFjdGl2ZS1saW5rLWhvdmVyLWNvbG9yOiAgICAgICAgICAkZ3JheSAhZGVmYXVsdDtcbiRuYXYtdGFicy1hY3RpdmUtbGluay1ob3Zlci1ib3JkZXItY29sb3I6ICAgI2RkZCAhZGVmYXVsdDtcblxuJG5hdi10YWJzLWp1c3RpZmllZC1saW5rLWJvcmRlci1jb2xvcjogICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuJG5hdi10YWJzLWp1c3RpZmllZC1hY3RpdmUtbGluay1ib3JkZXItY29sb3I6ICAgICAkYm9keS1iZyAhZGVmYXVsdDtcblxuLy89PSBQaWxsc1xuJG5hdi1waWxscy1ib3JkZXItcmFkaXVzOiAgICAgICAgICAgICAgICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuJG5hdi1waWxscy1hY3RpdmUtbGluay1ob3Zlci1iZzogICAgICAgICAgICAkY29tcG9uZW50LWFjdGl2ZS1iZyAhZGVmYXVsdDtcbiRuYXYtcGlsbHMtYWN0aXZlLWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgJGNvbXBvbmVudC1hY3RpdmUtY29sb3IgIWRlZmF1bHQ7XG5cblxuLy89PSBQYWdpbmF0aW9uXG4vL1xuLy8jI1xuXG4kcGFnaW5hdGlvbi1jb2xvcjogICAgICAgICAgICAgICAgICAgICAkbGluay1jb2xvciAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWJnOiAgICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG4kcGFnaW5hdGlvbi1ob3Zlci1jb2xvcjogICAgICAgICAgICAgICAkbGluay1ob3Zlci1jb2xvciAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWhvdmVyLWJnOiAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1ob3Zlci1ib3JkZXI6ICAgICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG4kcGFnaW5hdGlvbi1hY3RpdmUtY29sb3I6ICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJHBhZ2luYXRpb24tYWN0aXZlLWJnOiAgICAgICAgICAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1hY3RpdmUtYm9yZGVyOiAgICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcblxuJHBhZ2luYXRpb24tZGlzYWJsZWQtY29sb3I6ICAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1kaXNhYmxlZC1iZzogICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJHBhZ2luYXRpb24tZGlzYWJsZWQtYm9yZGVyOiAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcblxuXG4vLz09IFBhZ2VyXG4vL1xuLy8jI1xuXG4kcGFnZXItYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGFnaW5hdGlvbi1iZyAhZGVmYXVsdDtcbiRwYWdlci1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWJvcmRlciAhZGVmYXVsdDtcbiRwYWdlci1ib3JkZXItcmFkaXVzOiAgICAgICAgICAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG5cbiRwYWdlci1ob3Zlci1iZzogICAgICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWhvdmVyLWJnICFkZWZhdWx0O1xuXG4kcGFnZXItYWN0aXZlLWJnOiAgICAgICAgICAgICAgICAgICAgICAkcGFnaW5hdGlvbi1hY3RpdmUtYmcgIWRlZmF1bHQ7XG4kcGFnZXItYWN0aXZlLWNvbG9yOiAgICAgICAgICAgICAgICAgICAkcGFnaW5hdGlvbi1hY3RpdmUtY29sb3IgIWRlZmF1bHQ7XG5cbiRwYWdlci1kaXNhYmxlZC1jb2xvcjogICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWRpc2FibGVkLWNvbG9yICFkZWZhdWx0O1xuXG5cbi8vPT0gSnVtYm90cm9uXG4vL1xuLy8jI1xuXG4kanVtYm90cm9uLXBhZGRpbmc6ICAgICAgICAgICAgICAzMHB4ICFkZWZhdWx0O1xuJGp1bWJvdHJvbi1jb2xvcjogICAgICAgICAgICAgICAgaW5oZXJpdCAhZGVmYXVsdDtcbiRqdW1ib3Ryb24tYmc6ICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4kanVtYm90cm9uLWhlYWRpbmctY29sb3I6ICAgICAgICBpbmhlcml0ICFkZWZhdWx0O1xuJGp1bWJvdHJvbi1mb250LXNpemU6ICAgICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMS41KSkgIWRlZmF1bHQ7XG4kanVtYm90cm9uLWhlYWRpbmctZm9udC1zaXplOiAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiA0LjUpKSAhZGVmYXVsdDtcblxuXG4vLz09IEZvcm0gc3RhdGVzIGFuZCBhbGVydHNcbi8vXG4vLyMjIERlZmluZSBjb2xvcnMgZm9yIGZvcm0gZmVlZGJhY2sgc3RhdGVzIGFuZCwgYnkgZGVmYXVsdCwgYWxlcnRzLlxuXG4kc3RhdGUtc3VjY2Vzcy10ZXh0OiAgICAgICAgICAgICAjM2M3NjNkICFkZWZhdWx0O1xuJHN0YXRlLXN1Y2Nlc3MtYmc6ICAgICAgICAgICAgICAgI2RmZjBkOCAhZGVmYXVsdDtcbiRzdGF0ZS1zdWNjZXNzLWJvcmRlcjogICAgICAgICAgIGRhcmtlbihhZGp1c3QtaHVlKCRzdGF0ZS1zdWNjZXNzLWJnLCAtMTApLCA1JSkgIWRlZmF1bHQ7XG5cbiRzdGF0ZS1pbmZvLXRleHQ6ICAgICAgICAgICAgICAgICMzMTcwOGYgIWRlZmF1bHQ7XG4kc3RhdGUtaW5mby1iZzogICAgICAgICAgICAgICAgICAjZDllZGY3ICFkZWZhdWx0O1xuJHN0YXRlLWluZm8tYm9yZGVyOiAgICAgICAgICAgICAgZGFya2VuKGFkanVzdC1odWUoJHN0YXRlLWluZm8tYmcsIC0xMCksIDclKSAhZGVmYXVsdDtcblxuJHN0YXRlLXdhcm5pbmctdGV4dDogICAgICAgICAgICAgIzhhNmQzYiAhZGVmYXVsdDtcbiRzdGF0ZS13YXJuaW5nLWJnOiAgICAgICAgICAgICAgICNmY2Y4ZTMgIWRlZmF1bHQ7XG4kc3RhdGUtd2FybmluZy1ib3JkZXI6ICAgICAgICAgICBkYXJrZW4oYWRqdXN0LWh1ZSgkc3RhdGUtd2FybmluZy1iZywgLTEwKSwgNSUpICFkZWZhdWx0O1xuXG4kc3RhdGUtZGFuZ2VyLXRleHQ6ICAgICAgICAgICAgICAjYTk0NDQyICFkZWZhdWx0O1xuJHN0YXRlLWRhbmdlci1iZzogICAgICAgICAgICAgICAgI2YyZGVkZSAhZGVmYXVsdDtcbiRzdGF0ZS1kYW5nZXItYm9yZGVyOiAgICAgICAgICAgIGRhcmtlbihhZGp1c3QtaHVlKCRzdGF0ZS1kYW5nZXItYmcsIC0xMCksIDUlKSAhZGVmYXVsdDtcblxuXG4vLz09IFRvb2x0aXBzXG4vL1xuLy8jI1xuXG4vLyoqIFRvb2x0aXAgbWF4IHdpZHRoXG4kdG9vbHRpcC1tYXgtd2lkdGg6ICAgICAgICAgICAyMDBweCAhZGVmYXVsdDtcbi8vKiogVG9vbHRpcCB0ZXh0IGNvbG9yXG4kdG9vbHRpcC1jb2xvcjogICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBUb29sdGlwIGJhY2tncm91bmQgY29sb3JcbiR0b29sdGlwLWJnOiAgICAgICAgICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG4kdG9vbHRpcC1vcGFjaXR5OiAgICAgICAgICAgICAuOSAhZGVmYXVsdDtcblxuLy8qKiBUb29sdGlwIGFycm93IHdpZHRoXG4kdG9vbHRpcC1hcnJvdy13aWR0aDogICAgICAgICA1cHggIWRlZmF1bHQ7XG4vLyoqIFRvb2x0aXAgYXJyb3cgY29sb3JcbiR0b29sdGlwLWFycm93LWNvbG9yOiAgICAgICAgICR0b29sdGlwLWJnICFkZWZhdWx0O1xuXG5cbi8vPT0gUG9wb3ZlcnNcbi8vXG4vLyMjXG5cbi8vKiogUG9wb3ZlciBib2R5IGJhY2tncm91bmQgY29sb3JcbiRwb3BvdmVyLWJnOiAgICAgICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogUG9wb3ZlciBtYXhpbXVtIHdpZHRoXG4kcG9wb3Zlci1tYXgtd2lkdGg6ICAgICAgICAgICAgICAgICAgIDI3NnB4ICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIGJvcmRlciBjb2xvclxuJHBvcG92ZXItYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICAgICByZ2JhKDAsMCwwLC4yKSAhZGVmYXVsdDtcbi8vKiogUG9wb3ZlciBmYWxsYmFjayBib3JkZXIgY29sb3JcbiRwb3BvdmVyLWZhbGxiYWNrLWJvcmRlci1jb2xvcjogICAgICAgI2NjYyAhZGVmYXVsdDtcblxuLy8qKiBQb3BvdmVyIHRpdGxlIGJhY2tncm91bmQgY29sb3JcbiRwb3BvdmVyLXRpdGxlLWJnOiAgICAgICAgICAgICAgICAgICAgZGFya2VuKCRwb3BvdmVyLWJnLCAzJSkgIWRlZmF1bHQ7XG5cbi8vKiogUG9wb3ZlciBhcnJvdyB3aWR0aFxuJHBvcG92ZXItYXJyb3ctd2lkdGg6ICAgICAgICAgICAgICAgICAxMHB4ICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIGFycm93IGNvbG9yXG4kcG9wb3Zlci1hcnJvdy1jb2xvcjogICAgICAgICAgICAgICAgICRwb3BvdmVyLWJnICFkZWZhdWx0O1xuXG4vLyoqIFBvcG92ZXIgb3V0ZXIgYXJyb3cgd2lkdGhcbiRwb3BvdmVyLWFycm93LW91dGVyLXdpZHRoOiAgICAgICAgICAgKCRwb3BvdmVyLWFycm93LXdpZHRoICsgMSkgIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgb3V0ZXIgYXJyb3cgY29sb3JcbiRwb3BvdmVyLWFycm93LW91dGVyLWNvbG9yOiAgICAgICAgICAgZmFkZV9pbigkcG9wb3Zlci1ib3JkZXItY29sb3IsIDAuMDUpICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIG91dGVyIGFycm93IGZhbGxiYWNrIGNvbG9yXG4kcG9wb3Zlci1hcnJvdy1vdXRlci1mYWxsYmFjay1jb2xvcjogIGRhcmtlbigkcG9wb3Zlci1mYWxsYmFjay1ib3JkZXItY29sb3IsIDIwJSkgIWRlZmF1bHQ7XG5cblxuLy89PSBMYWJlbHNcbi8vXG4vLyMjXG5cbi8vKiogRGVmYXVsdCBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtZGVmYXVsdC1iZzogICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogUHJpbWFyeSBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtcHJpbWFyeS1iZzogICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbi8vKiogU3VjY2VzcyBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtc3VjY2Vzcy1iZzogICAgICAgICAgICAkYnJhbmQtc3VjY2VzcyAhZGVmYXVsdDtcbi8vKiogSW5mbyBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtaW5mby1iZzogICAgICAgICAgICAgICAkYnJhbmQtaW5mbyAhZGVmYXVsdDtcbi8vKiogV2FybmluZyBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtd2FybmluZy1iZzogICAgICAgICAgICAkYnJhbmQtd2FybmluZyAhZGVmYXVsdDtcbi8vKiogRGFuZ2VyIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1kYW5nZXItYmc6ICAgICAgICAgICAgICRicmFuZC1kYW5nZXIgIWRlZmF1bHQ7XG5cbi8vKiogRGVmYXVsdCBsYWJlbCB0ZXh0IGNvbG9yXG4kbGFiZWwtY29sb3I6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBEZWZhdWx0IHRleHQgY29sb3Igb2YgYSBsaW5rZWQgbGFiZWxcbiRsYWJlbC1saW5rLWhvdmVyLWNvbG9yOiAgICAgICNmZmYgIWRlZmF1bHQ7XG5cblxuLy89PSBNb2RhbHNcbi8vXG4vLyMjXG5cbi8vKiogUGFkZGluZyBhcHBsaWVkIHRvIHRoZSBtb2RhbCBib2R5XG4kbW9kYWwtaW5uZXItcGFkZGluZzogICAgICAgICAxNXB4ICFkZWZhdWx0O1xuXG4vLyoqIFBhZGRpbmcgYXBwbGllZCB0byB0aGUgbW9kYWwgdGl0bGVcbiRtb2RhbC10aXRsZS1wYWRkaW5nOiAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIHRpdGxlIGxpbmUtaGVpZ2h0XG4kbW9kYWwtdGl0bGUtbGluZS1oZWlnaHQ6ICAgICAkbGluZS1oZWlnaHQtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIG1vZGFsIGNvbnRlbnQgYXJlYVxuJG1vZGFsLWNvbnRlbnQtYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBjb250ZW50IGJvcmRlciBjb2xvclxuJG1vZGFsLWNvbnRlbnQtYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICAgICAgICByZ2JhKDAsMCwwLC4yKSAhZGVmYXVsdDtcbi8vKiogTW9kYWwgY29udGVudCBib3JkZXIgY29sb3IgKipmb3IgSUU4KipcbiRtb2RhbC1jb250ZW50LWZhbGxiYWNrLWJvcmRlci1jb2xvcjogICAgICAgICAgIzk5OSAhZGVmYXVsdDtcblxuLy8qKiBNb2RhbCBiYWNrZHJvcCBiYWNrZ3JvdW5kIGNvbG9yXG4kbW9kYWwtYmFja2Ryb3AtYmc6ICAgICAgICAgICAjMDAwICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBiYWNrZHJvcCBvcGFjaXR5XG4kbW9kYWwtYmFja2Ryb3Atb3BhY2l0eTogICAgICAuNSAhZGVmYXVsdDtcbi8vKiogTW9kYWwgaGVhZGVyIGJvcmRlciBjb2xvclxuJG1vZGFsLWhlYWRlci1ib3JkZXItY29sb3I6ICAgI2U1ZTVlNSAhZGVmYXVsdDtcbi8vKiogTW9kYWwgZm9vdGVyIGJvcmRlciBjb2xvclxuJG1vZGFsLWZvb3Rlci1ib3JkZXItY29sb3I6ICAgJG1vZGFsLWhlYWRlci1ib3JkZXItY29sb3IgIWRlZmF1bHQ7XG5cbiRtb2RhbC1sZzogICAgICAgICAgICAgICAgICAgIDkwMHB4ICFkZWZhdWx0O1xuJG1vZGFsLW1kOiAgICAgICAgICAgICAgICAgICAgNjAwcHggIWRlZmF1bHQ7XG4kbW9kYWwtc206ICAgICAgICAgICAgICAgICAgICAzMDBweCAhZGVmYXVsdDtcblxuXG4vLz09IEFsZXJ0c1xuLy9cbi8vIyMgRGVmaW5lIGFsZXJ0IGNvbG9ycywgYm9yZGVyIHJhZGl1cywgYW5kIHBhZGRpbmcuXG5cbiRhbGVydC1wYWRkaW5nOiAgICAgICAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG4kYWxlcnQtYm9yZGVyLXJhZGl1czogICAgICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuJGFsZXJ0LWxpbmstZm9udC13ZWlnaHQ6ICAgICAgYm9sZCAhZGVmYXVsdDtcblxuJGFsZXJ0LXN1Y2Nlc3MtYmc6ICAgICAgICAgICAgJHN0YXRlLXN1Y2Nlc3MtYmcgIWRlZmF1bHQ7XG4kYWxlcnQtc3VjY2Vzcy10ZXh0OiAgICAgICAgICAkc3RhdGUtc3VjY2Vzcy10ZXh0ICFkZWZhdWx0O1xuJGFsZXJ0LXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgJHN0YXRlLXN1Y2Nlc3MtYm9yZGVyICFkZWZhdWx0O1xuXG4kYWxlcnQtaW5mby1iZzogICAgICAgICAgICAgICAkc3RhdGUtaW5mby1iZyAhZGVmYXVsdDtcbiRhbGVydC1pbmZvLXRleHQ6ICAgICAgICAgICAgICRzdGF0ZS1pbmZvLXRleHQgIWRlZmF1bHQ7XG4kYWxlcnQtaW5mby1ib3JkZXI6ICAgICAgICAgICAkc3RhdGUtaW5mby1ib3JkZXIgIWRlZmF1bHQ7XG5cbiRhbGVydC13YXJuaW5nLWJnOiAgICAgICAgICAgICRzdGF0ZS13YXJuaW5nLWJnICFkZWZhdWx0O1xuJGFsZXJ0LXdhcm5pbmctdGV4dDogICAgICAgICAgJHN0YXRlLXdhcm5pbmctdGV4dCAhZGVmYXVsdDtcbiRhbGVydC13YXJuaW5nLWJvcmRlcjogICAgICAgICRzdGF0ZS13YXJuaW5nLWJvcmRlciAhZGVmYXVsdDtcblxuJGFsZXJ0LWRhbmdlci1iZzogICAgICAgICAgICAgJHN0YXRlLWRhbmdlci1iZyAhZGVmYXVsdDtcbiRhbGVydC1kYW5nZXItdGV4dDogICAgICAgICAgICRzdGF0ZS1kYW5nZXItdGV4dCAhZGVmYXVsdDtcbiRhbGVydC1kYW5nZXItYm9yZGVyOiAgICAgICAgICRzdGF0ZS1kYW5nZXItYm9yZGVyICFkZWZhdWx0O1xuXG5cbi8vPT0gUHJvZ3Jlc3MgYmFyc1xuLy9cbi8vIyNcblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIHRoZSB3aG9sZSBwcm9ncmVzcyBjb21wb25lbnRcbiRwcm9ncmVzcy1iZzogICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4vLyoqIFByb2dyZXNzIGJhciB0ZXh0IGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLWNvbG9yOiAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBWYXJpYWJsZSBmb3Igc2V0dGluZyByb3VuZGVkIGNvcm5lcnMgb24gcHJvZ3Jlc3MgYmFyLlxuJHByb2dyZXNzLWJvcmRlci1yYWRpdXM6ICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBEZWZhdWx0IHByb2dyZXNzIGJhciBjb2xvclxuJHByb2dyZXNzLWJhci1iZzogICAgICAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG4vLyoqIFN1Y2Nlc3MgcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLXN1Y2Nlc3MtYmc6ICAgICAkYnJhbmQtc3VjY2VzcyAhZGVmYXVsdDtcbi8vKiogV2FybmluZyBwcm9ncmVzcyBiYXIgY29sb3JcbiRwcm9ncmVzcy1iYXItd2FybmluZy1iZzogICAgICRicmFuZC13YXJuaW5nICFkZWZhdWx0O1xuLy8qKiBEYW5nZXIgcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLWRhbmdlci1iZzogICAgICAkYnJhbmQtZGFuZ2VyICFkZWZhdWx0O1xuLy8qKiBJbmZvIHByb2dyZXNzIGJhciBjb2xvclxuJHByb2dyZXNzLWJhci1pbmZvLWJnOiAgICAgICAgJGJyYW5kLWluZm8gIWRlZmF1bHQ7XG5cblxuLy89PSBMaXN0IGdyb3VwXG4vL1xuLy8jI1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3Igb24gYC5saXN0LWdyb3VwLWl0ZW1gXG4kbGlzdC1ncm91cC1iZzogICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIGAubGlzdC1ncm91cC1pdGVtYCBib3JkZXIgY29sb3JcbiRsaXN0LWdyb3VwLWJvcmRlcjogICAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcbi8vKiogTGlzdCBncm91cCBib3JkZXIgcmFkaXVzXG4kbGlzdC1ncm91cC1ib3JkZXItcmFkaXVzOiAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG5cbi8vKiogQmFja2dyb3VuZCBjb2xvciBvZiBzaW5nbGUgbGlzdCBpdGVtcyBvbiBob3ZlclxuJGxpc3QtZ3JvdXAtaG92ZXItYmc6ICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuLy8qKiBUZXh0IGNvbG9yIG9mIGFjdGl2ZSBsaXN0IGl0ZW1zXG4kbGlzdC1ncm91cC1hY3RpdmUtY29sb3I6ICAgICAgICRjb21wb25lbnQtYWN0aXZlLWNvbG9yICFkZWZhdWx0O1xuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIGFjdGl2ZSBsaXN0IGl0ZW1zXG4kbGlzdC1ncm91cC1hY3RpdmUtYmc6ICAgICAgICAgICRjb21wb25lbnQtYWN0aXZlLWJnICFkZWZhdWx0O1xuLy8qKiBCb3JkZXIgY29sb3Igb2YgYWN0aXZlIGxpc3QgZWxlbWVudHNcbiRsaXN0LWdyb3VwLWFjdGl2ZS1ib3JkZXI6ICAgICAgJGxpc3QtZ3JvdXAtYWN0aXZlLWJnICFkZWZhdWx0O1xuLy8qKiBUZXh0IGNvbG9yIGZvciBjb250ZW50IHdpdGhpbiBhY3RpdmUgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtYWN0aXZlLXRleHQtY29sb3I6ICBsaWdodGVuKCRsaXN0LWdyb3VwLWFjdGl2ZS1iZywgNDAlKSAhZGVmYXVsdDtcblxuLy8qKiBUZXh0IGNvbG9yIG9mIGRpc2FibGVkIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWRpc2FibGVkLWNvbG9yOiAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIGRpc2FibGVkIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWRpc2FibGVkLWJnOiAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4vLyoqIFRleHQgY29sb3IgZm9yIGNvbnRlbnQgd2l0aGluIGRpc2FibGVkIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWRpc2FibGVkLXRleHQtY29sb3I6ICRsaXN0LWdyb3VwLWRpc2FibGVkLWNvbG9yICFkZWZhdWx0O1xuXG4kbGlzdC1ncm91cC1saW5rLWNvbG9yOiAgICAgICAgICM1NTUgIWRlZmF1bHQ7XG4kbGlzdC1ncm91cC1saW5rLWhvdmVyLWNvbG9yOiAgICRsaXN0LWdyb3VwLWxpbmstY29sb3IgIWRlZmF1bHQ7XG4kbGlzdC1ncm91cC1saW5rLWhlYWRpbmctY29sb3I6ICMzMzMgIWRlZmF1bHQ7XG5cblxuLy89PSBQYW5lbHNcbi8vXG4vLyMjXG5cbiRwYW5lbC1iZzogICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFuZWwtYm9keS1wYWRkaW5nOiAgICAgICAgICAxNXB4ICFkZWZhdWx0O1xuJHBhbmVsLWhlYWRpbmctcGFkZGluZzogICAgICAgMTBweCAxNXB4ICFkZWZhdWx0O1xuJHBhbmVsLWZvb3Rlci1wYWRkaW5nOiAgICAgICAgJHBhbmVsLWhlYWRpbmctcGFkZGluZyAhZGVmYXVsdDtcbiRwYW5lbC1ib3JkZXItcmFkaXVzOiAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG5cbi8vKiogQm9yZGVyIGNvbG9yIGZvciBlbGVtZW50cyB3aXRoaW4gcGFuZWxzXG4kcGFuZWwtaW5uZXItYm9yZGVyOiAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuJHBhbmVsLWZvb3Rlci1iZzogICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcblxuJHBhbmVsLWRlZmF1bHQtdGV4dDogICAgICAgICAgJGdyYXktZGFyayAhZGVmYXVsdDtcbiRwYW5lbC1kZWZhdWx0LWJvcmRlcjogICAgICAgICNkZGQgIWRlZmF1bHQ7XG4kcGFuZWwtZGVmYXVsdC1oZWFkaW5nLWJnOiAgICAjZjVmNWY1ICFkZWZhdWx0O1xuXG4kcGFuZWwtcHJpbWFyeS10ZXh0OiAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJHBhbmVsLXByaW1hcnktYm9yZGVyOiAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG4kcGFuZWwtcHJpbWFyeS1oZWFkaW5nLWJnOiAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcblxuJHBhbmVsLXN1Y2Nlc3MtdGV4dDogICAgICAgICAgJHN0YXRlLXN1Y2Nlc3MtdGV4dCAhZGVmYXVsdDtcbiRwYW5lbC1zdWNjZXNzLWJvcmRlcjogICAgICAgICRzdGF0ZS1zdWNjZXNzLWJvcmRlciAhZGVmYXVsdDtcbiRwYW5lbC1zdWNjZXNzLWhlYWRpbmctYmc6ICAgICRzdGF0ZS1zdWNjZXNzLWJnICFkZWZhdWx0O1xuXG4kcGFuZWwtaW5mby10ZXh0OiAgICAgICAgICAgICAkc3RhdGUtaW5mby10ZXh0ICFkZWZhdWx0O1xuJHBhbmVsLWluZm8tYm9yZGVyOiAgICAgICAgICAgJHN0YXRlLWluZm8tYm9yZGVyICFkZWZhdWx0O1xuJHBhbmVsLWluZm8taGVhZGluZy1iZzogICAgICAgJHN0YXRlLWluZm8tYmcgIWRlZmF1bHQ7XG5cbiRwYW5lbC13YXJuaW5nLXRleHQ6ICAgICAgICAgICRzdGF0ZS13YXJuaW5nLXRleHQgIWRlZmF1bHQ7XG4kcGFuZWwtd2FybmluZy1ib3JkZXI6ICAgICAgICAkc3RhdGUtd2FybmluZy1ib3JkZXIgIWRlZmF1bHQ7XG4kcGFuZWwtd2FybmluZy1oZWFkaW5nLWJnOiAgICAkc3RhdGUtd2FybmluZy1iZyAhZGVmYXVsdDtcblxuJHBhbmVsLWRhbmdlci10ZXh0OiAgICAgICAgICAgJHN0YXRlLWRhbmdlci10ZXh0ICFkZWZhdWx0O1xuJHBhbmVsLWRhbmdlci1ib3JkZXI6ICAgICAgICAgJHN0YXRlLWRhbmdlci1ib3JkZXIgIWRlZmF1bHQ7XG4kcGFuZWwtZGFuZ2VyLWhlYWRpbmctYmc6ICAgICAkc3RhdGUtZGFuZ2VyLWJnICFkZWZhdWx0O1xuXG5cbi8vPT0gVGh1bWJuYWlsc1xuLy9cbi8vIyNcblxuLy8qKiBQYWRkaW5nIGFyb3VuZCB0aGUgdGh1bWJuYWlsIGltYWdlXG4kdGh1bWJuYWlsLXBhZGRpbmc6ICAgICAgICAgICA0cHggIWRlZmF1bHQ7XG4vLyoqIFRodW1ibmFpbCBiYWNrZ3JvdW5kIGNvbG9yXG4kdGh1bWJuYWlsLWJnOiAgICAgICAgICAgICAgICAkYm9keS1iZyAhZGVmYXVsdDtcbi8vKiogVGh1bWJuYWlsIGJvcmRlciBjb2xvclxuJHRodW1ibmFpbC1ib3JkZXI6ICAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcbi8vKiogVGh1bWJuYWlsIGJvcmRlciByYWRpdXNcbiR0aHVtYm5haWwtYm9yZGVyLXJhZGl1czogICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG5cbi8vKiogQ3VzdG9tIHRleHQgY29sb3IgZm9yIHRodW1ibmFpbCBjYXB0aW9uc1xuJHRodW1ibmFpbC1jYXB0aW9uLWNvbG9yOiAgICAgJHRleHQtY29sb3IgIWRlZmF1bHQ7XG4vLyoqIFBhZGRpbmcgYXJvdW5kIHRoZSB0aHVtYm5haWwgY2FwdGlvblxuJHRodW1ibmFpbC1jYXB0aW9uLXBhZGRpbmc6ICAgOXB4ICFkZWZhdWx0O1xuXG5cbi8vPT0gV2VsbHNcbi8vXG4vLyMjXG5cbiR3ZWxsLWJnOiAgICAgICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4kd2VsbC1ib3JkZXI6ICAgICAgICAgICAgICAgICBkYXJrZW4oJHdlbGwtYmcsIDclKSAhZGVmYXVsdDtcblxuXG4vLz09IEJhZGdlc1xuLy9cbi8vIyNcblxuJGJhZGdlLWNvbG9yOiAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogTGlua2VkIGJhZGdlIHRleHQgY29sb3Igb24gaG92ZXJcbiRiYWRnZS1saW5rLWhvdmVyLWNvbG9yOiAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYmFkZ2UtYmc6ICAgICAgICAgICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcblxuLy8qKiBCYWRnZSB0ZXh0IGNvbG9yIGluIGFjdGl2ZSBuYXYgbGlua1xuJGJhZGdlLWFjdGl2ZS1jb2xvcjogICAgICAgICAgJGxpbmstY29sb3IgIWRlZmF1bHQ7XG4vLyoqIEJhZGdlIGJhY2tncm91bmQgY29sb3IgaW4gYWN0aXZlIG5hdiBsaW5rXG4kYmFkZ2UtYWN0aXZlLWJnOiAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuXG4kYmFkZ2UtZm9udC13ZWlnaHQ6ICAgICAgICAgICBib2xkICFkZWZhdWx0O1xuJGJhZGdlLWxpbmUtaGVpZ2h0OiAgICAgICAgICAgMSAhZGVmYXVsdDtcbiRiYWRnZS1ib3JkZXItcmFkaXVzOiAgICAgICAgIDEwcHggIWRlZmF1bHQ7XG5cblxuLy89PSBCcmVhZGNydW1ic1xuLy9cbi8vIyNcblxuJGJyZWFkY3J1bWItcGFkZGluZy12ZXJ0aWNhbDogICA4cHggIWRlZmF1bHQ7XG4kYnJlYWRjcnVtYi1wYWRkaW5nLWhvcml6b250YWw6IDE1cHggIWRlZmF1bHQ7XG4vLyoqIEJyZWFkY3J1bWIgYmFja2dyb3VuZCBjb2xvclxuJGJyZWFkY3J1bWItYmc6ICAgICAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuLy8qKiBCcmVhZGNydW1iIHRleHQgY29sb3JcbiRicmVhZGNydW1iLWNvbG9yOiAgICAgICAgICAgICAgI2NjYyAhZGVmYXVsdDtcbi8vKiogVGV4dCBjb2xvciBvZiBjdXJyZW50IHBhZ2UgaW4gdGhlIGJyZWFkY3J1bWJcbiRicmVhZGNydW1iLWFjdGl2ZS1jb2xvcjogICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIFRleHR1YWwgc2VwYXJhdG9yIGZvciBiZXR3ZWVuIGJyZWFkY3J1bWIgZWxlbWVudHNcbiRicmVhZGNydW1iLXNlcGFyYXRvcjogICAgICAgICAgXCIvXCIgIWRlZmF1bHQ7XG5cblxuLy89PSBDYXJvdXNlbFxuLy9cbi8vIyNcblxuJGNhcm91c2VsLXRleHQtc2hhZG93OiAgICAgICAgICAgICAgICAgICAgICAgIDAgMXB4IDJweCByZ2JhKDAsMCwwLC42KSAhZGVmYXVsdDtcblxuJGNhcm91c2VsLWNvbnRyb2wtY29sb3I6ICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtY29udHJvbC13aWR0aDogICAgICAgICAgICAgICAgICAgICAgMTUlICFkZWZhdWx0O1xuJGNhcm91c2VsLWNvbnRyb2wtb3BhY2l0eTogICAgICAgICAgICAgICAgICAgIC41ICFkZWZhdWx0O1xuJGNhcm91c2VsLWNvbnRyb2wtZm9udC1zaXplOiAgICAgICAgICAgICAgICAgIDIwcHggIWRlZmF1bHQ7XG5cbiRjYXJvdXNlbC1pbmRpY2F0b3ItYWN0aXZlLWJnOiAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGNhcm91c2VsLWluZGljYXRvci1ib3JkZXItY29sb3I6ICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG5cbiRjYXJvdXNlbC1jYXB0aW9uLWNvbG9yOiAgICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuXG5cbi8vPT0gQ2xvc2Vcbi8vXG4vLyMjXG5cbiRjbG9zZS1mb250LXdlaWdodDogICAgICAgICAgIGJvbGQgIWRlZmF1bHQ7XG4kY2xvc2UtY29sb3I6ICAgICAgICAgICAgICAgICAjMDAwICFkZWZhdWx0O1xuJGNsb3NlLXRleHQtc2hhZG93OiAgICAgICAgICAgMCAxcHggMCAjZmZmICFkZWZhdWx0O1xuXG5cbi8vPT0gQ29kZVxuLy9cbi8vIyNcblxuJGNvZGUtY29sb3I6ICAgICAgICAgICAgICAgICAgI2M3MjU0ZSAhZGVmYXVsdDtcbiRjb2RlLWJnOiAgICAgICAgICAgICAgICAgICAgICNmOWYyZjQgIWRlZmF1bHQ7XG5cbiRrYmQtY29sb3I6ICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4ka2JkLWJnOiAgICAgICAgICAgICAgICAgICAgICAjMzMzICFkZWZhdWx0O1xuXG4kcHJlLWJnOiAgICAgICAgICAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuJHByZS1jb2xvcjogICAgICAgICAgICAgICAgICAgJGdyYXktZGFyayAhZGVmYXVsdDtcbiRwcmUtYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICNjY2MgIWRlZmF1bHQ7XG4kcHJlLXNjcm9sbGFibGUtbWF4LWhlaWdodDogICAzNDBweCAhZGVmYXVsdDtcblxuXG4vLz09IFR5cGVcbi8vXG4vLyMjXG5cbi8vKiogSG9yaXpvbnRhbCBvZmZzZXQgZm9yIGZvcm1zIGFuZCBsaXN0cy5cbiRjb21wb25lbnQtb2Zmc2V0LWhvcml6b250YWw6IDE4MHB4ICFkZWZhdWx0O1xuLy8qKiBUZXh0IG11dGVkIGNvbG9yXG4kdGV4dC1tdXRlZDogICAgICAgICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogQWJicmV2aWF0aW9ucyBhbmQgYWNyb255bXMgYm9yZGVyIGNvbG9yXG4kYWJici1ib3JkZXItY29sb3I6ICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogSGVhZGluZ3Mgc21hbGwgY29sb3JcbiRoZWFkaW5ncy1zbWFsbC1jb2xvcjogICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBCbG9ja3F1b3RlIHNtYWxsIGNvbG9yXG4kYmxvY2txdW90ZS1zbWFsbC1jb2xvcjogICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogQmxvY2txdW90ZSBmb250IHNpemVcbiRibG9ja3F1b3RlLWZvbnQtc2l6ZTogICAgICAgICgkZm9udC1zaXplLWJhc2UgKiAxLjI1KSAhZGVmYXVsdDtcbi8vKiogQmxvY2txdW90ZSBib3JkZXIgY29sb3JcbiRibG9ja3F1b3RlLWJvcmRlci1jb2xvcjogICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4vLyoqIFBhZ2UgaGVhZGVyIGJvcmRlciBjb2xvclxuJHBhZ2UtaGVhZGVyLWJvcmRlci1jb2xvcjogICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbi8vKiogV2lkdGggb2YgaG9yaXpvbnRhbCBkZXNjcmlwdGlvbiBsaXN0IHRpdGxlc1xuJGRsLWhvcml6b250YWwtb2Zmc2V0OiAgICAgICAgJGNvbXBvbmVudC1vZmZzZXQtaG9yaXpvbnRhbCAhZGVmYXVsdDtcbi8vKiogUG9pbnQgYXQgd2hpY2ggLmRsLWhvcml6b250YWwgYmVjb21lcyBob3Jpem9udGFsXG4kZGwtaG9yaXpvbnRhbC1icmVha3BvaW50OiAgICAkZ3JpZC1mbG9hdC1icmVha3BvaW50ICFkZWZhdWx0O1xuLy8qKiBIb3Jpem9udGFsIGxpbmUgY29sb3IuXG4kaHItYm9yZGVyOiAgICAgICAgICAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuIiwiQGltcG9ydCAnLi4vLi4vLi4vc3R5bGVzL2FuaW1hdGlvbnMuc2Nzcyc7XG5cbnhvcy10YWJsZSB7XG5cbiAgZGlzcGxheTogYmxvY2s7XG5cbiAgdHIubmctbW92ZSxcbiAgdHIubmctZW50ZXIsXG4gIHRyLm5nLWxlYXZlIHtcbiAgICB0cmFuc2l0aW9uOmFsbCBsaW5lYXIgMC41cztcbiAgfVxuXG4gIHRyLm5nLWxlYXZlLm5nLWxlYXZlLWFjdGl2ZSxcbiAgdHIubmctbW92ZSxcbiAgdHIubmctZW50ZXIge1xuICAgIG9wYWNpdHk6MDtcbiAgICBhbmltYXRpb246IDAuNXMgc2xpZGVPdXRSaWdodCBlYXNlLWluLW91dDtcbiAgfVxuXG4gIHRyLm5nLWxlYXZlLFxuICB0ci5uZy1tb3ZlLm5nLW1vdmUtYWN0aXZlLFxuICB0ci5uZy1lbnRlci5uZy1lbnRlci1hY3RpdmUge1xuICAgIG9wYWNpdHk6MTtcbiAgICBhbmltYXRpb246IDAuNXMgc2xpZGVJblJpZ2h0IGVhc2UtaW4tb3V0O1xuICB9XG5cbiAgdGQgZGwge1xuICAgIG1hcmdpbi1ib3R0b206IDA7XG5cbiAgICBkdCB7XG4gICAgICB3aWR0aDogYXV0byAhaW1wb3J0YW50O1xuICAgICAgbWFyZ2luLXJpZ2h0OiAxMHB4O1xuICAgIH1cbiAgICBcbiAgICBkdDphZnRlciB7XG4gICAgICAvKmRpc3BsYXk6IGJsb2NrOyovXG4gICAgICBjb250ZW50OiAnOic7XG4gICAgfVxuXG4gICAgZGQge1xuICAgICAgbWFyZ2luLWxlZnQ6IDAgIWltcG9ydGFudDtcbiAgICB9XG4gIH1cbn0iLCJAaW1wb3J0ICcuLi8uLi8uLi9zdHlsZXMvYW5pbWF0aW9ucy5zY3NzJztcblxueG9zLWFsZXJ0IHtcblxuICAvKiB3aGVuIGhpZGluZyAqL1xuICAubmctaGlkZS1hZGQgICAgICAgICB7IGFuaW1hdGlvbjowLjVzIGZhZGVPdXREb3duIGVhc2UtaW4tb3V0OyB9XG5cbiAgLyogd2hlbiBzaG93aW5nICovXG4gIC5uZy1oaWRlLXJlbW92ZSAgICAgIHsgYW5pbWF0aW9uOjAuNXMgZmFkZUluVXAgZWFzZS1pbi1vdXQ7IH1cbn0iLCJAaW1wb3J0ICcuLi8uLi8uLi9zdHlsZXMvYW5pbWF0aW9ucy5zY3NzJztcbkBpbXBvcnQgJy4uLy4uLy4uLy4uLy4uLy4uL3N0eWxlL3Nhc3MvYm9vdHN0cmFwL2Jvb3RzdHJhcC9fdmFyaWFibGVzLnNjc3MnO1xuXG5pbnB1dCArIHhvcy12YWxpZGF0aW9uIHtcbiAgbWFyZ2luLXRvcDogJGZvcm0tZ3JvdXAtbWFyZ2luLWJvdHRvbTtcbiAgZGlzcGxheTogYmxvY2s7XG59IiwieG9zLWZpZWxkIHtcbiAgZGlzcGxheTogYmxvY2s7XG59IiwieG9zLXNtYXJ0LXRhYmxle1xuICBcbn0iXSwibWFwcGluZ3MiOiJBQ0FBLFVBQVUsQ0FBQyxBQUFBLFlBQVk7RUFDckIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLHVCQUFXO0lBQ3RCLFVBQVUsRUFBRSxPQUFRO0VBR3RCLEFBQUEsRUFBRTtJQUNBLFNBQVMsRUFBRSxvQkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsYUFBYTtFQUN0QixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsb0JBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsVUFBVSxFQUFFLE1BQU87SUFDbkIsU0FBUyxFQUFFLHVCQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxRQUFRO0VBQ2pCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLElBQUs7O0FBSXBCLFVBQVUsQ0FBQyxBQUFBLFdBQVc7RUFDcEIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7RUFHYixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVzs7QUF6QzFCLFVBQVUsQ0FBQyxBQUFBLFlBQVk7RUFDckIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLHVCQUFXO0lBQ3RCLFVBQVUsRUFBRSxPQUFRO0VBR3RCLEFBQUEsRUFBRTtJQUNBLFNBQVMsRUFBRSxvQkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsYUFBYTtFQUN0QixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsb0JBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsVUFBVSxFQUFFLE1BQU87SUFDbkIsU0FBUyxFQUFFLHVCQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxRQUFRO0VBQ2pCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLElBQUs7O0FBSXBCLFVBQVUsQ0FBQyxBQUFBLFdBQVc7RUFDcEIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7RUFHYixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVzs7QUV2QzFCLEFBQUEsU0FBUyxDQUFDO0VBRVIsT0FBTyxFQUFFLEtBQU0sR0F1Q2hCO0VBekNELEFBSUksU0FKSyxDQUlQLEVBQUUsQUFBQSxRQUFRO0VBSlosQUFLSSxTQUxLLENBS1AsRUFBRSxBQUFBLFNBQVM7RUFMYixBQU1JLFNBTkssQ0FNUCxFQUFFLEFBQUEsU0FBUyxDQUFDO0lBQ1YsVUFBVSxFQUFDLGVBQWdCLEdBQzVCO0VBUkgsQUFVYSxTQVZKLENBVVAsRUFBRSxBQUFBLFNBQVMsQUFBQSxnQkFBZ0I7RUFWN0IsQUFXSSxTQVhLLENBV1AsRUFBRSxBQUFBLFFBQVE7RUFYWixBQVlJLFNBWkssQ0FZUCxFQUFFLEFBQUEsU0FBUyxDQUFDO0lBQ1YsT0FBTyxFQUFDLENBQUU7SUFDVixTQUFTLEVBQUUsOEJBQStCLEdBQzNDO0VBZkgsQUFpQkksU0FqQkssQ0FpQlAsRUFBRSxBQUFBLFNBQVM7RUFqQmIsQUFrQlksU0FsQkgsQ0FrQlAsRUFBRSxBQUFBLFFBQVEsQUFBQSxlQUFlO0VBbEIzQixBQW1CYSxTQW5CSixDQW1CUCxFQUFFLEFBQUEsU0FBUyxBQUFBLGdCQUFnQixDQUFDO0lBQzFCLE9BQU8sRUFBQyxDQUFFO0lBQ1YsU0FBUyxFQUFFLDZCQUE4QixHQUMxQztFQXRCSCxBQXdCSyxTQXhCSSxDQXdCUCxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ0osYUFBYSxFQUFFLENBQUUsR0FlbEI7SUF4Q0gsQUEyQkksU0EzQkssQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FHSCxFQUFFLENBQUM7TUFDRCxLQUFLLEVBQUUsZUFBZ0I7TUFDdkIsWUFBWSxFQUFFLElBQUssR0FDcEI7SUE5QkwsQUFnQ00sU0FoQ0csQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FRSCxFQUFFLEFBQUEsTUFBTSxDQUFDO01BQ1AsbUJBQW1CO01BQ25CLE9BQU8sRUFBRSxHQUFJLEdBQ2Q7SUFuQ0wsQUFxQ0ksU0FyQ0ssQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FhSCxFQUFFLENBQUM7TUFDRCxXQUFXLEVBQUUsWUFBYSxHQUMzQjs7QUZ6Q0wsVUFBVSxDQUFDLEFBQUEsWUFBWTtFQUNyQixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsdUJBQVc7SUFDdEIsVUFBVSxFQUFFLE9BQVE7RUFHdEIsQUFBQSxFQUFFO0lBQ0EsU0FBUyxFQUFFLG9CQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxhQUFhO0VBQ3RCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSxvQkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxVQUFVLEVBQUUsTUFBTztJQUNuQixTQUFTLEVBQUUsdUJBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLFFBQVE7RUFDakIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsSUFBSzs7QUFJcEIsVUFBVSxDQUFDLEFBQUEsV0FBVztFQUNwQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtFQUdiLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXOztBR3ZDMUIsQUFBQSxTQUFTLENBQUM7RUFFUixpQkFBaUI7RUFHakIsa0JBQWtCLEVBRW5CO0VBUEQsQUFHRSxTQUhPLENBR1AsWUFBWSxDQUFTO0lBQUUsU0FBUyxFQUFDLDRCQUE2QixHQUFJO0VBSHBFLEFBTUUsU0FOTyxDQU1QLGVBQWUsQ0FBTTtJQUFFLFNBQVMsRUFBQyx5QkFBMEIsR0FBSTs7QUhSakUsVUFBVSxDQUFDLEFBQUEsWUFBWTtFQUNyQixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsdUJBQVc7SUFDdEIsVUFBVSxFQUFFLE9BQVE7RUFHdEIsQUFBQSxFQUFFO0lBQ0EsU0FBUyxFQUFFLG9CQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxhQUFhO0VBQ3RCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSxvQkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxVQUFVLEVBQUUsTUFBTztJQUNuQixTQUFTLEVBQUUsdUJBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLFFBQVE7RUFDakIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsSUFBSzs7QUFJcEIsVUFBVSxDQUFDLEFBQUEsV0FBVztFQUNwQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtFQUdiLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXOztBSXRDMUIsQUFBUSxLQUFILEdBQUcsY0FBYyxDQUFDO0VBQ3JCLFVBQVUsRUh3TnFCLElBQUk7RUd2Tm5DLE9BQU8sRUFBRSxLQUFNLEdBQ2hCOztBQ05ELEFBQUEsU0FBUyxDQUFDO0VBQ1IsT0FBTyxFQUFFLEtBQU0sR0FDaEI7O0NOUUQsQUFBQSxBQUFVLFNBQVQsQUFBQSxJQUFZLEFBQUEsQUFBUyxRQUFSLEFBQUEsSUFBVyxBQUFBLEFBQWMsYUFBYixBQUFBLElBQWdCLEFBQUEsQUFBVyxVQUFWLEFBQUEsR0FBYSxBQUFBLFNBQVMsRUFBRSxBQUFBLFdBQVcsQ0FBQztFQUM3RSxPQUFPLEVBQUUsZUFBZ0IsR0FDMUI7O0FBRUQsQUFBTyxJQUFILEdBQUcsSUFBSSxDQUFDO0VBQ1YsMEJBQTBCO0VBQzFCLFVBQVUsRUU0TXFCLElBQUksR0YzTXBDIiwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== */
+/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieG9zTmdMaWIuY3NzIiwic291cmNlcyI6WyJtYWluLnNjc3MiLCJhbmltYXRpb25zLnNjc3MiLCIuLi8uLi8uLi8uLi9zdHlsZS9zYXNzL2Jvb3RzdHJhcC9ib290c3RyYXAvX3ZhcmlhYmxlcy5zY3NzIiwibG9hZGVyLnNjc3MiLCIuLi91aV9jb21wb25lbnRzL2R1bWJDb21wb25lbnRzL3RhYmxlL3RhYmxlLnNjc3MiLCIuLi91aV9jb21wb25lbnRzL2R1bWJDb21wb25lbnRzL2FsZXJ0L2FsZXJ0LnNjc3MiLCIuLi91aV9jb21wb25lbnRzL2R1bWJDb21wb25lbnRzL3ZhbGlkYXRpb24vdmFsaWRhdGlvbi5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9maWVsZC9maWVsZC5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9mb3JtL2Zvcm0uc2NzcyIsIi4uL3VpX2NvbXBvbmVudHMvc21hcnRDb21wb25lbnRzL3NtYXJ0VGFibGUvc21hcnRUYWJsZS5zY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIkBpbXBvcnQgJy4vYW5pbWF0aW9ucy5zY3NzJztcbkBpbXBvcnQgJy4uLy4uLy4uLy4uLy4uL3ZpZXdzL3N0eWxlL3Nhc3MvYm9vdHN0cmFwL2Jvb3RzdHJhcC9fdmFyaWFibGVzLnNjc3MnO1xuQGltcG9ydCAnLi9sb2FkZXIuc2Nzcyc7XG5cbkBpbXBvcnQgJy4uL3VpX2NvbXBvbmVudHMvZHVtYkNvbXBvbmVudHMvdGFibGUvdGFibGUuc2Nzcyc7XG5AaW1wb3J0ICcuLi91aV9jb21wb25lbnRzL2R1bWJDb21wb25lbnRzL2FsZXJ0L2FsZXJ0LnNjc3MnO1xuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy92YWxpZGF0aW9uL3ZhbGlkYXRpb24uc2Nzcyc7XG5AaW1wb3J0ICcuLi91aV9jb21wb25lbnRzL2R1bWJDb21wb25lbnRzL2ZpZWxkL2ZpZWxkLnNjc3MnO1xuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9mb3JtL2Zvcm0uc2Nzcyc7XG5cbkBpbXBvcnQgJy4uL3VpX2NvbXBvbmVudHMvc21hcnRDb21wb25lbnRzL3NtYXJ0VGFibGUvc21hcnRUYWJsZS5zY3NzJztcblxuW25nXFw6Y2xvYWtdLCBbbmctY2xvYWtdLCBbZGF0YS1uZy1jbG9ha10sIFt4LW5nLWNsb2FrXSwgLm5nLWNsb2FrLCAueC1uZy1jbG9hayB7XG4gIGRpc3BsYXk6IG5vbmUgIWltcG9ydGFudDtcbn1cblxuLnJvdyArIC5yb3cge1xuICAvKiBUT0RPIG1vdmUgaW4geG9zLnNjc3MqLyBcbiAgbWFyZ2luLXRvcDogJGZvcm0tZ3JvdXAtbWFyZ2luLWJvdHRvbTtcbn0iLCJAa2V5ZnJhbWVzIHNsaWRlSW5SaWdodCB7XG4gIGZyb20ge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMTAwJSwgMCwgMCk7XG4gICAgdmlzaWJpbGl0eTogdmlzaWJsZTtcbiAgfVxuXG4gIHRvIHtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuICB9XG59XG5cbkBrZXlmcmFtZXMgc2xpZGVPdXRSaWdodCB7XG4gIGZyb20ge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgMCwgMCk7XG4gIH1cblxuICB0byB7XG4gICAgdmlzaWJpbGl0eTogaGlkZGVuO1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMTAwJSwgMCwgMCk7XG4gIH1cbn1cblxuQGtleWZyYW1lcyBmYWRlSW5VcCB7XG4gIGZyb20ge1xuICAgIG9wYWNpdHk6IDA7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAxMDAlLCAwKTtcbiAgfVxuXG4gIHRvIHtcbiAgICBvcGFjaXR5OiAxO1xuICAgIHRyYW5zZm9ybTogbm9uZTtcbiAgfVxufVxuXG5Aa2V5ZnJhbWVzIGZhZGVPdXREb3duIHtcbiAgZnJvbSB7XG4gICAgb3BhY2l0eTogMTtcbiAgfVxuXG4gIHRvIHtcbiAgICBvcGFjaXR5OiAwO1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgMTAwJSwgMCk7XG4gIH1cbn0iLCIkYm9vdHN0cmFwLXNhc3MtYXNzZXQtaGVscGVyOiBmYWxzZSAhZGVmYXVsdDtcbi8vXG4vLyBWYXJpYWJsZXNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblxuLy89PSBDb2xvcnNcbi8vXG4vLyMjIEdyYXkgYW5kIGJyYW5kIGNvbG9ycyBmb3IgdXNlIGFjcm9zcyBCb290c3RyYXAuXG5cbiRncmF5LWJhc2U6ICAgICAgICAgICAgICAjMDAwICFkZWZhdWx0O1xuJGdyYXktZGFya2VyOiAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktYmFzZSwgMTMuNSUpICFkZWZhdWx0OyAvLyAjMjIyXG4kZ3JheS1kYXJrOiAgICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1iYXNlLCAyMCUpICFkZWZhdWx0OyAgIC8vICMzMzNcbiRncmF5OiAgICAgICAgICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDMzLjUlKSAhZGVmYXVsdDsgLy8gIzU1NVxuJGdyYXktbGlnaHQ6ICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktYmFzZSwgNDYuNyUpICFkZWZhdWx0OyAvLyAjNzc3XG4kZ3JheS1saWdodGVyOiAgICAgICAgICAgbGlnaHRlbigkZ3JheS1iYXNlLCA5My41JSkgIWRlZmF1bHQ7IC8vICNlZWVcblxuJGJyYW5kLXByaW1hcnk6ICAgICAgICAgZGFya2VuKCM0MjhiY2EsIDYuNSUpICFkZWZhdWx0OyAvLyAjMzM3YWI3XG4kYnJhbmQtc3VjY2VzczogICAgICAgICAjNWNiODVjICFkZWZhdWx0O1xuJGJyYW5kLWluZm86ICAgICAgICAgICAgIzViYzBkZSAhZGVmYXVsdDtcbiRicmFuZC13YXJuaW5nOiAgICAgICAgICNmMGFkNGUgIWRlZmF1bHQ7XG4kYnJhbmQtZGFuZ2VyOiAgICAgICAgICAjZDk1MzRmICFkZWZhdWx0O1xuXG5cbi8vPT0gU2NhZmZvbGRpbmdcbi8vXG4vLyMjIFNldHRpbmdzIGZvciBzb21lIG9mIHRoZSBtb3N0IGdsb2JhbCBzdHlsZXMuXG5cbi8vKiogQmFja2dyb3VuZCBjb2xvciBmb3IgYDxib2R5PmAuXG4kYm9keS1iZzogICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBHbG9iYWwgdGV4dCBjb2xvciBvbiBgPGJvZHk+YC5cbiR0ZXh0LWNvbG9yOiAgICAgICAgICAgICRncmF5LWRhcmsgIWRlZmF1bHQ7XG5cbi8vKiogR2xvYmFsIHRleHR1YWwgbGluayBjb2xvci5cbiRsaW5rLWNvbG9yOiAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuLy8qKiBMaW5rIGhvdmVyIGNvbG9yIHNldCB2aWEgYGRhcmtlbigpYCBmdW5jdGlvbi5cbiRsaW5rLWhvdmVyLWNvbG9yOiAgICAgIGRhcmtlbigkbGluay1jb2xvciwgMTUlKSAhZGVmYXVsdDtcbi8vKiogTGluayBob3ZlciBkZWNvcmF0aW9uLlxuJGxpbmstaG92ZXItZGVjb3JhdGlvbjogdW5kZXJsaW5lICFkZWZhdWx0O1xuXG5cbi8vPT0gVHlwb2dyYXBoeVxuLy9cbi8vIyMgRm9udCwgbGluZS1oZWlnaHQsIGFuZCBjb2xvciBmb3IgYm9keSB0ZXh0LCBoZWFkaW5ncywgYW5kIG1vcmUuXG5cbiRmb250LWZhbWlseS1zYW5zLXNlcmlmOiAgXCJIZWx2ZXRpY2EgTmV1ZVwiLCBIZWx2ZXRpY2EsIEFyaWFsLCBzYW5zLXNlcmlmICFkZWZhdWx0O1xuJGZvbnQtZmFtaWx5LXNlcmlmOiAgICAgICBHZW9yZ2lhLCBcIlRpbWVzIE5ldyBSb21hblwiLCBUaW1lcywgc2VyaWYgIWRlZmF1bHQ7XG4vLyoqIERlZmF1bHQgbW9ub3NwYWNlIGZvbnRzIGZvciBgPGNvZGU+YCwgYDxrYmQ+YCwgYW5kIGA8cHJlPmAuXG4kZm9udC1mYW1pbHktbW9ub3NwYWNlOiAgIE1lbmxvLCBNb25hY28sIENvbnNvbGFzLCBcIkNvdXJpZXIgTmV3XCIsIG1vbm9zcGFjZSAhZGVmYXVsdDtcbiRmb250LWZhbWlseS1iYXNlOiAgICAgICAgJGZvbnQtZmFtaWx5LXNhbnMtc2VyaWYgIWRlZmF1bHQ7XG5cbiRmb250LXNpemUtYmFzZTogICAgICAgICAgMTRweCAhZGVmYXVsdDtcbiRmb250LXNpemUtbGFyZ2U6ICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMS4yNSkpICFkZWZhdWx0OyAvLyB+MThweFxuJGZvbnQtc2l6ZS1zbWFsbDogICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAwLjg1KSkgIWRlZmF1bHQ7IC8vIH4xMnB4XG5cbiRmb250LXNpemUtaDE6ICAgICAgICAgICAgZmxvb3IoKCRmb250LXNpemUtYmFzZSAqIDIuNikpICFkZWZhdWx0OyAvLyB+MzZweFxuJGZvbnQtc2l6ZS1oMjogICAgICAgICAgICBmbG9vcigoJGZvbnQtc2l6ZS1iYXNlICogMi4xNSkpICFkZWZhdWx0OyAvLyB+MzBweFxuJGZvbnQtc2l6ZS1oMzogICAgICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAxLjcpKSAhZGVmYXVsdDsgLy8gfjI0cHhcbiRmb250LXNpemUtaDQ6ICAgICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMS4yNSkpICFkZWZhdWx0OyAvLyB+MThweFxuJGZvbnQtc2l6ZS1oNTogICAgICAgICAgICAkZm9udC1zaXplLWJhc2UgIWRlZmF1bHQ7XG4kZm9udC1zaXplLWg2OiAgICAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDAuODUpKSAhZGVmYXVsdDsgLy8gfjEycHhcblxuLy8qKiBVbml0LWxlc3MgYGxpbmUtaGVpZ2h0YCBmb3IgdXNlIGluIGNvbXBvbmVudHMgbGlrZSBidXR0b25zLlxuJGxpbmUtaGVpZ2h0LWJhc2U6ICAgICAgICAxLjQyODU3MTQyOSAhZGVmYXVsdDsgLy8gMjAvMTRcbi8vKiogQ29tcHV0ZWQgXCJsaW5lLWhlaWdodFwiIChgZm9udC1zaXplYCAqIGBsaW5lLWhlaWdodGApIGZvciB1c2Ugd2l0aCBgbWFyZ2luYCwgYHBhZGRpbmdgLCBldGMuXG4kbGluZS1oZWlnaHQtY29tcHV0ZWQ6ICAgIGZsb29yKCgkZm9udC1zaXplLWJhc2UgKiAkbGluZS1oZWlnaHQtYmFzZSkpICFkZWZhdWx0OyAvLyB+MjBweFxuXG4vLyoqIEJ5IGRlZmF1bHQsIHRoaXMgaW5oZXJpdHMgZnJvbSB0aGUgYDxib2R5PmAuXG4kaGVhZGluZ3MtZm9udC1mYW1pbHk6ICAgIGluaGVyaXQgIWRlZmF1bHQ7XG4kaGVhZGluZ3MtZm9udC13ZWlnaHQ6ICAgIDUwMCAhZGVmYXVsdDtcbiRoZWFkaW5ncy1saW5lLWhlaWdodDogICAgMS4xICFkZWZhdWx0O1xuJGhlYWRpbmdzLWNvbG9yOiAgICAgICAgICBpbmhlcml0ICFkZWZhdWx0O1xuXG5cbi8vPT0gSWNvbm9ncmFwaHlcbi8vXG4vLyMjIFNwZWNpZnkgY3VzdG9tIGxvY2F0aW9uIGFuZCBmaWxlbmFtZSBvZiB0aGUgaW5jbHVkZWQgR2x5cGhpY29ucyBpY29uIGZvbnQuIFVzZWZ1bCBmb3IgdGhvc2UgaW5jbHVkaW5nIEJvb3RzdHJhcCB2aWEgQm93ZXIuXG5cbi8vKiogTG9hZCBmb250cyBmcm9tIHRoaXMgZGlyZWN0b3J5LlxuXG4vLyBbY29udmVydGVyXSBJZiAkYm9vdHN0cmFwLXNhc3MtYXNzZXQtaGVscGVyIGlmIHVzZWQsIHByb3ZpZGUgcGF0aCByZWxhdGl2ZSB0byB0aGUgYXNzZXRzIGxvYWQgcGF0aC5cbi8vIFtjb252ZXJ0ZXJdIFRoaXMgaXMgYmVjYXVzZSBzb21lIGFzc2V0IGhlbHBlcnMsIHN1Y2ggYXMgU3Byb2NrZXRzLCBkbyBub3Qgd29yayB3aXRoIGZpbGUtcmVsYXRpdmUgcGF0aHMuXG4kaWNvbi1mb250LXBhdGg6IGlmKCRib290c3RyYXAtc2Fzcy1hc3NldC1oZWxwZXIsIFwiYm9vdHN0cmFwL1wiLCBcIi4uL2ZvbnRzL2Jvb3RzdHJhcC9cIikgIWRlZmF1bHQ7XG5cbi8vKiogRmlsZSBuYW1lIGZvciBhbGwgZm9udCBmaWxlcy5cbiRpY29uLWZvbnQtbmFtZTogICAgICAgICAgXCJnbHlwaGljb25zLWhhbGZsaW5ncy1yZWd1bGFyXCIgIWRlZmF1bHQ7XG4vLyoqIEVsZW1lbnQgSUQgd2l0aGluIFNWRyBpY29uIGZpbGUuXG4kaWNvbi1mb250LXN2Zy1pZDogICAgICAgIFwiZ2x5cGhpY29uc19oYWxmbGluZ3NyZWd1bGFyXCIgIWRlZmF1bHQ7XG5cblxuLy89PSBDb21wb25lbnRzXG4vL1xuLy8jIyBEZWZpbmUgY29tbW9uIHBhZGRpbmcgYW5kIGJvcmRlciByYWRpdXMgc2l6ZXMgYW5kIG1vcmUuIFZhbHVlcyBiYXNlZCBvbiAxNHB4IHRleHQgYW5kIDEuNDI4IGxpbmUtaGVpZ2h0ICh+MjBweCB0byBzdGFydCkuXG5cbiRwYWRkaW5nLWJhc2UtdmVydGljYWw6ICAgICA2cHggIWRlZmF1bHQ7XG4kcGFkZGluZy1iYXNlLWhvcml6b250YWw6ICAgMTJweCAhZGVmYXVsdDtcblxuJHBhZGRpbmctbGFyZ2UtdmVydGljYWw6ICAgIDEwcHggIWRlZmF1bHQ7XG4kcGFkZGluZy1sYXJnZS1ob3Jpem9udGFsOiAgMTZweCAhZGVmYXVsdDtcblxuJHBhZGRpbmctc21hbGwtdmVydGljYWw6ICAgIDVweCAhZGVmYXVsdDtcbiRwYWRkaW5nLXNtYWxsLWhvcml6b250YWw6ICAxMHB4ICFkZWZhdWx0O1xuXG4kcGFkZGluZy14cy12ZXJ0aWNhbDogICAgICAgMXB4ICFkZWZhdWx0O1xuJHBhZGRpbmcteHMtaG9yaXpvbnRhbDogICAgIDVweCAhZGVmYXVsdDtcblxuJGxpbmUtaGVpZ2h0LWxhcmdlOiAgICAgICAgIDEuMzMzMzMzMyAhZGVmYXVsdDsgLy8gZXh0cmEgZGVjaW1hbHMgZm9yIFdpbiA4LjEgQ2hyb21lXG4kbGluZS1oZWlnaHQtc21hbGw6ICAgICAgICAgMS41ICFkZWZhdWx0O1xuXG4kYm9yZGVyLXJhZGl1cy1iYXNlOiAgICAgICAgNHB4ICFkZWZhdWx0O1xuJGJvcmRlci1yYWRpdXMtbGFyZ2U6ICAgICAgIDZweCAhZGVmYXVsdDtcbiRib3JkZXItcmFkaXVzLXNtYWxsOiAgICAgICAzcHggIWRlZmF1bHQ7XG5cbi8vKiogR2xvYmFsIGNvbG9yIGZvciBhY3RpdmUgaXRlbXMgKGUuZy4sIG5hdnMgb3IgZHJvcGRvd25zKS5cbiRjb21wb25lbnQtYWN0aXZlLWNvbG9yOiAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBHbG9iYWwgYmFja2dyb3VuZCBjb2xvciBmb3IgYWN0aXZlIGl0ZW1zIChlLmcuLCBuYXZzIG9yIGRyb3Bkb3ducykuXG4kY29tcG9uZW50LWFjdGl2ZS1iZzogICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG5cbi8vKiogV2lkdGggb2YgdGhlIGBib3JkZXJgIGZvciBnZW5lcmF0aW5nIGNhcmV0cyB0aGF0IGluZGljYXRvciBkcm9wZG93bnMuXG4kY2FyZXQtd2lkdGgtYmFzZTogICAgICAgICAgNHB4ICFkZWZhdWx0O1xuLy8qKiBDYXJldHMgaW5jcmVhc2Ugc2xpZ2h0bHkgaW4gc2l6ZSBmb3IgbGFyZ2VyIGNvbXBvbmVudHMuXG4kY2FyZXQtd2lkdGgtbGFyZ2U6ICAgICAgICAgNXB4ICFkZWZhdWx0O1xuXG5cbi8vPT0gVGFibGVzXG4vL1xuLy8jIyBDdXN0b21pemVzIHRoZSBgLnRhYmxlYCBjb21wb25lbnQgd2l0aCBiYXNpYyB2YWx1ZXMsIGVhY2ggdXNlZCBhY3Jvc3MgYWxsIHRhYmxlIHZhcmlhdGlvbnMuXG5cbi8vKiogUGFkZGluZyBmb3IgYDx0aD5gcyBhbmQgYDx0ZD5gcy5cbiR0YWJsZS1jZWxsLXBhZGRpbmc6ICAgICAgICAgICAgOHB4ICFkZWZhdWx0O1xuLy8qKiBQYWRkaW5nIGZvciBjZWxscyBpbiBgLnRhYmxlLWNvbmRlbnNlZGAuXG4kdGFibGUtY29uZGVuc2VkLWNlbGwtcGFkZGluZzogIDVweCAhZGVmYXVsdDtcblxuLy8qKiBEZWZhdWx0IGJhY2tncm91bmQgY29sb3IgdXNlZCBmb3IgYWxsIHRhYmxlcy5cbiR0YWJsZS1iZzogICAgICAgICAgICAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG4vLyoqIEJhY2tncm91bmQgY29sb3IgdXNlZCBmb3IgYC50YWJsZS1zdHJpcGVkYC5cbiR0YWJsZS1iZy1hY2NlbnQ6ICAgICAgICAgICAgICAgI2Y5ZjlmOSAhZGVmYXVsdDtcbi8vKiogQmFja2dyb3VuZCBjb2xvciB1c2VkIGZvciBgLnRhYmxlLWhvdmVyYC5cbiR0YWJsZS1iZy1ob3ZlcjogICAgICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcbiR0YWJsZS1iZy1hY3RpdmU6ICAgICAgICAgICAgICAgJHRhYmxlLWJnLWhvdmVyICFkZWZhdWx0O1xuXG4vLyoqIEJvcmRlciBjb2xvciBmb3IgdGFibGUgYW5kIGNlbGwgYm9yZGVycy5cbiR0YWJsZS1ib3JkZXItY29sb3I6ICAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcblxuXG4vLz09IEJ1dHRvbnNcbi8vXG4vLyMjIEZvciBlYWNoIG9mIEJvb3RzdHJhcCdzIGJ1dHRvbnMsIGRlZmluZSB0ZXh0LCBiYWNrZ3JvdW5kIGFuZCBib3JkZXIgY29sb3IuXG5cbiRidG4tZm9udC13ZWlnaHQ6ICAgICAgICAgICAgICAgIG5vcm1hbCAhZGVmYXVsdDtcblxuJGJ0bi1kZWZhdWx0LWNvbG9yOiAgICAgICAgICAgICAgIzMzMyAhZGVmYXVsdDtcbiRidG4tZGVmYXVsdC1iZzogICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYnRuLWRlZmF1bHQtYm9yZGVyOiAgICAgICAgICAgICAjY2NjICFkZWZhdWx0O1xuXG4kYnRuLXByaW1hcnktY29sb3I6ICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1wcmltYXJ5LWJnOiAgICAgICAgICAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG4kYnRuLXByaW1hcnktYm9yZGVyOiAgICAgICAgICAgICBkYXJrZW4oJGJ0bi1wcmltYXJ5LWJnLCA1JSkgIWRlZmF1bHQ7XG5cbiRidG4tc3VjY2Vzcy1jb2xvcjogICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYnRuLXN1Y2Nlc3MtYmc6ICAgICAgICAgICAgICAgICAkYnJhbmQtc3VjY2VzcyAhZGVmYXVsdDtcbiRidG4tc3VjY2Vzcy1ib3JkZXI6ICAgICAgICAgICAgIGRhcmtlbigkYnRuLXN1Y2Nlc3MtYmcsIDUlKSAhZGVmYXVsdDtcblxuJGJ0bi1pbmZvLWNvbG9yOiAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4taW5mby1iZzogICAgICAgICAgICAgICAgICAgICRicmFuZC1pbmZvICFkZWZhdWx0O1xuJGJ0bi1pbmZvLWJvcmRlcjogICAgICAgICAgICAgICAgZGFya2VuKCRidG4taW5mby1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLXdhcm5pbmctY29sb3I6ICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi13YXJuaW5nLWJnOiAgICAgICAgICAgICAgICAgJGJyYW5kLXdhcm5pbmcgIWRlZmF1bHQ7XG4kYnRuLXdhcm5pbmctYm9yZGVyOiAgICAgICAgICAgICBkYXJrZW4oJGJ0bi13YXJuaW5nLWJnLCA1JSkgIWRlZmF1bHQ7XG5cbiRidG4tZGFuZ2VyLWNvbG9yOiAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYnRuLWRhbmdlci1iZzogICAgICAgICAgICAgICAgICAkYnJhbmQtZGFuZ2VyICFkZWZhdWx0O1xuJGJ0bi1kYW5nZXItYm9yZGVyOiAgICAgICAgICAgICAgZGFya2VuKCRidG4tZGFuZ2VyLWJnLCA1JSkgIWRlZmF1bHQ7XG5cbiRidG4tbGluay1kaXNhYmxlZC1jb2xvcjogICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLyBBbGxvd3MgZm9yIGN1c3RvbWl6aW5nIGJ1dHRvbiByYWRpdXMgaW5kZXBlbmRlbnRseSBmcm9tIGdsb2JhbCBib3JkZXIgcmFkaXVzXG4kYnRuLWJvcmRlci1yYWRpdXMtYmFzZTogICAgICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuJGJ0bi1ib3JkZXItcmFkaXVzLWxhcmdlOiAgICAgICAgJGJvcmRlci1yYWRpdXMtbGFyZ2UgIWRlZmF1bHQ7XG4kYnRuLWJvcmRlci1yYWRpdXMtc21hbGw6ICAgICAgICAkYm9yZGVyLXJhZGl1cy1zbWFsbCAhZGVmYXVsdDtcblxuXG4vLz09IEZvcm1zXG4vL1xuLy8jI1xuXG4vLyoqIGA8aW5wdXQ+YCBiYWNrZ3JvdW5kIGNvbG9yXG4kaW5wdXQtYmc6ICAgICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBgPGlucHV0IGRpc2FibGVkPmAgYmFja2dyb3VuZCBjb2xvclxuJGlucHV0LWJnLWRpc2FibGVkOiAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcblxuLy8qKiBUZXh0IGNvbG9yIGZvciBgPGlucHV0PmBzXG4kaW5wdXQtY29sb3I6ICAgICAgICAgICAgICAgICAgICAkZ3JheSAhZGVmYXVsdDtcbi8vKiogYDxpbnB1dD5gIGJvcmRlciBjb2xvclxuJGlucHV0LWJvcmRlcjogICAgICAgICAgICAgICAgICAgI2NjYyAhZGVmYXVsdDtcblxuLy8gVE9ETzogUmVuYW1lIGAkaW5wdXQtYm9yZGVyLXJhZGl1c2AgdG8gYCRpbnB1dC1ib3JkZXItcmFkaXVzLWJhc2VgIGluIHY0XG4vLyoqIERlZmF1bHQgYC5mb3JtLWNvbnRyb2xgIGJvcmRlciByYWRpdXNcbi8vIFRoaXMgaGFzIG5vIGVmZmVjdCBvbiBgPHNlbGVjdD5gcyBpbiBzb21lIGJyb3dzZXJzLCBkdWUgdG8gdGhlIGxpbWl0ZWQgc3R5bGFiaWxpdHkgb2YgYDxzZWxlY3Q+YHMgaW4gQ1NTLlxuJGlucHV0LWJvcmRlci1yYWRpdXM6ICAgICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcbi8vKiogTGFyZ2UgYC5mb3JtLWNvbnRyb2xgIGJvcmRlciByYWRpdXNcbiRpbnB1dC1ib3JkZXItcmFkaXVzLWxhcmdlOiAgICAgICRib3JkZXItcmFkaXVzLWxhcmdlICFkZWZhdWx0O1xuLy8qKiBTbWFsbCBgLmZvcm0tY29udHJvbGAgYm9yZGVyIHJhZGl1c1xuJGlucHV0LWJvcmRlci1yYWRpdXMtc21hbGw6ICAgICAgJGJvcmRlci1yYWRpdXMtc21hbGwgIWRlZmF1bHQ7XG5cbi8vKiogQm9yZGVyIGNvbG9yIGZvciBpbnB1dHMgb24gZm9jdXNcbiRpbnB1dC1ib3JkZXItZm9jdXM6ICAgICAgICAgICAgICM2NmFmZTkgIWRlZmF1bHQ7XG5cbi8vKiogUGxhY2Vob2xkZXIgdGV4dCBjb2xvclxuJGlucHV0LWNvbG9yLXBsYWNlaG9sZGVyOiAgICAgICAgIzk5OSAhZGVmYXVsdDtcblxuLy8qKiBEZWZhdWx0IGAuZm9ybS1jb250cm9sYCBoZWlnaHRcbiRpbnB1dC1oZWlnaHQtYmFzZTogICAgICAgICAgICAgICgkbGluZS1oZWlnaHQtY29tcHV0ZWQgKyAoJHBhZGRpbmctYmFzZS12ZXJ0aWNhbCAqIDIpICsgMikgIWRlZmF1bHQ7XG4vLyoqIExhcmdlIGAuZm9ybS1jb250cm9sYCBoZWlnaHRcbiRpbnB1dC1oZWlnaHQtbGFyZ2U6ICAgICAgICAgICAgIChjZWlsKCRmb250LXNpemUtbGFyZ2UgKiAkbGluZS1oZWlnaHQtbGFyZ2UpICsgKCRwYWRkaW5nLWxhcmdlLXZlcnRpY2FsICogMikgKyAyKSAhZGVmYXVsdDtcbi8vKiogU21hbGwgYC5mb3JtLWNvbnRyb2xgIGhlaWdodFxuJGlucHV0LWhlaWdodC1zbWFsbDogICAgICAgICAgICAgKGZsb29yKCRmb250LXNpemUtc21hbGwgKiAkbGluZS1oZWlnaHQtc21hbGwpICsgKCRwYWRkaW5nLXNtYWxsLXZlcnRpY2FsICogMikgKyAyKSAhZGVmYXVsdDtcblxuLy8qKiBgLmZvcm0tZ3JvdXBgIG1hcmdpblxuJGZvcm0tZ3JvdXAtbWFyZ2luLWJvdHRvbTogICAgICAgMTVweCAhZGVmYXVsdDtcblxuJGxlZ2VuZC1jb2xvcjogICAgICAgICAgICAgICAgICAgJGdyYXktZGFyayAhZGVmYXVsdDtcbiRsZWdlbmQtYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICNlNWU1ZTUgIWRlZmF1bHQ7XG5cbi8vKiogQmFja2dyb3VuZCBjb2xvciBmb3IgdGV4dHVhbCBpbnB1dCBhZGRvbnNcbiRpbnB1dC1ncm91cC1hZGRvbi1iZzogICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4vLyoqIEJvcmRlciBjb2xvciBmb3IgdGV4dHVhbCBpbnB1dCBhZGRvbnNcbiRpbnB1dC1ncm91cC1hZGRvbi1ib3JkZXItY29sb3I6ICRpbnB1dC1ib3JkZXIgIWRlZmF1bHQ7XG5cbi8vKiogRGlzYWJsZWQgY3Vyc29yIGZvciBmb3JtIGNvbnRyb2xzIGFuZCBidXR0b25zLlxuJGN1cnNvci1kaXNhYmxlZDogICAgICAgICAgICAgICAgbm90LWFsbG93ZWQgIWRlZmF1bHQ7XG5cblxuLy89PSBEcm9wZG93bnNcbi8vXG4vLyMjIERyb3Bkb3duIG1lbnUgY29udGFpbmVyIGFuZCBjb250ZW50cy5cblxuLy8qKiBCYWNrZ3JvdW5kIGZvciB0aGUgZHJvcGRvd24gbWVudS5cbiRkcm9wZG93bi1iZzogICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIERyb3Bkb3duIG1lbnUgYGJvcmRlci1jb2xvcmAuXG4kZHJvcGRvd24tYm9yZGVyOiAgICAgICAgICAgICAgICByZ2JhKDAsMCwwLC4xNSkgIWRlZmF1bHQ7XG4vLyoqIERyb3Bkb3duIG1lbnUgYGJvcmRlci1jb2xvcmAgKipmb3IgSUU4KiouXG4kZHJvcGRvd24tZmFsbGJhY2stYm9yZGVyOiAgICAgICAjY2NjICFkZWZhdWx0O1xuLy8qKiBEaXZpZGVyIGNvbG9yIGZvciBiZXR3ZWVuIGRyb3Bkb3duIGl0ZW1zLlxuJGRyb3Bkb3duLWRpdmlkZXItYmc6ICAgICAgICAgICAgI2U1ZTVlNSAhZGVmYXVsdDtcblxuLy8qKiBEcm9wZG93biBsaW5rIHRleHQgY29sb3IuXG4kZHJvcGRvd24tbGluay1jb2xvcjogICAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuLy8qKiBIb3ZlciBjb2xvciBmb3IgZHJvcGRvd24gbGlua3MuXG4kZHJvcGRvd24tbGluay1ob3Zlci1jb2xvcjogICAgICBkYXJrZW4oJGdyYXktZGFyaywgNSUpICFkZWZhdWx0O1xuLy8qKiBIb3ZlciBiYWNrZ3JvdW5kIGZvciBkcm9wZG93biBsaW5rcy5cbiRkcm9wZG93bi1saW5rLWhvdmVyLWJnOiAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG5cbi8vKiogQWN0aXZlIGRyb3Bkb3duIG1lbnUgaXRlbSB0ZXh0IGNvbG9yLlxuJGRyb3Bkb3duLWxpbmstYWN0aXZlLWNvbG9yOiAgICAgJGNvbXBvbmVudC1hY3RpdmUtY29sb3IgIWRlZmF1bHQ7XG4vLyoqIEFjdGl2ZSBkcm9wZG93biBtZW51IGl0ZW0gYmFja2dyb3VuZCBjb2xvci5cbiRkcm9wZG93bi1saW5rLWFjdGl2ZS1iZzogICAgICAgICRjb21wb25lbnQtYWN0aXZlLWJnICFkZWZhdWx0O1xuXG4vLyoqIERpc2FibGVkIGRyb3Bkb3duIG1lbnUgaXRlbSBiYWNrZ3JvdW5kIGNvbG9yLlxuJGRyb3Bkb3duLWxpbmstZGlzYWJsZWQtY29sb3I6ICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG5cbi8vKiogVGV4dCBjb2xvciBmb3IgaGVhZGVycyB3aXRoaW4gZHJvcGRvd24gbWVudXMuXG4kZHJvcGRvd24taGVhZGVyLWNvbG9yOiAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcblxuLy8qKiBEZXByZWNhdGVkIGAkZHJvcGRvd24tY2FyZXQtY29sb3JgIGFzIG9mIHYzLjEuMFxuJGRyb3Bkb3duLWNhcmV0LWNvbG9yOiAgICAgICAgICAgIzAwMCAhZGVmYXVsdDtcblxuXG4vLy0tIFotaW5kZXggbWFzdGVyIGxpc3Rcbi8vXG4vLyBXYXJuaW5nOiBBdm9pZCBjdXN0b21pemluZyB0aGVzZSB2YWx1ZXMuIFRoZXkncmUgdXNlZCBmb3IgYSBiaXJkJ3MgZXllIHZpZXdcbi8vIG9mIGNvbXBvbmVudHMgZGVwZW5kZW50IG9uIHRoZSB6LWF4aXMgYW5kIGFyZSBkZXNpZ25lZCB0byBhbGwgd29yayB0b2dldGhlci5cbi8vXG4vLyBOb3RlOiBUaGVzZSB2YXJpYWJsZXMgYXJlIG5vdCBnZW5lcmF0ZWQgaW50byB0aGUgQ3VzdG9taXplci5cblxuJHppbmRleC1uYXZiYXI6ICAgICAgICAgICAgMTAwMCAhZGVmYXVsdDtcbiR6aW5kZXgtZHJvcGRvd246ICAgICAgICAgIDEwMDAgIWRlZmF1bHQ7XG4kemluZGV4LXBvcG92ZXI6ICAgICAgICAgICAxMDYwICFkZWZhdWx0O1xuJHppbmRleC10b29sdGlwOiAgICAgICAgICAgMTA3MCAhZGVmYXVsdDtcbiR6aW5kZXgtbmF2YmFyLWZpeGVkOiAgICAgIDEwMzAgIWRlZmF1bHQ7XG4kemluZGV4LW1vZGFsLWJhY2tncm91bmQ6ICAxMDQwICFkZWZhdWx0O1xuJHppbmRleC1tb2RhbDogICAgICAgICAgICAgMTA1MCAhZGVmYXVsdDtcblxuXG4vLz09IE1lZGlhIHF1ZXJpZXMgYnJlYWtwb2ludHNcbi8vXG4vLyMjIERlZmluZSB0aGUgYnJlYWtwb2ludHMgYXQgd2hpY2ggeW91ciBsYXlvdXQgd2lsbCBjaGFuZ2UsIGFkYXB0aW5nIHRvIGRpZmZlcmVudCBzY3JlZW4gc2l6ZXMuXG5cbi8vIEV4dHJhIHNtYWxsIHNjcmVlbiAvIHBob25lXG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4teHNgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi14czogICAgICAgICAgICAgICAgICA0ODBweCAhZGVmYXVsdDtcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi14cy1taW5gIGFzIG9mIHYzLjIuMFxuJHNjcmVlbi14cy1taW46ICAgICAgICAgICAgICAkc2NyZWVuLXhzICFkZWZhdWx0O1xuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLXBob25lYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tcGhvbmU6ICAgICAgICAgICAgICAgJHNjcmVlbi14cy1taW4gIWRlZmF1bHQ7XG5cbi8vIFNtYWxsIHNjcmVlbiAvIHRhYmxldFxuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLXNtYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tc206ICAgICAgICAgICAgICAgICAgNzY4cHggIWRlZmF1bHQ7XG4kc2NyZWVuLXNtLW1pbjogICAgICAgICAgICAgICRzY3JlZW4tc20gIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tdGFibGV0YCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tdGFibGV0OiAgICAgICAgICAgICAgJHNjcmVlbi1zbS1taW4gIWRlZmF1bHQ7XG5cbi8vIE1lZGl1bSBzY3JlZW4gLyBkZXNrdG9wXG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tbWRgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi1tZDogICAgICAgICAgICAgICAgICA5OTJweCAhZGVmYXVsdDtcbiRzY3JlZW4tbWQtbWluOiAgICAgICAgICAgICAgJHNjcmVlbi1tZCAhZGVmYXVsdDtcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1kZXNrdG9wYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tZGVza3RvcDogICAgICAgICAgICAgJHNjcmVlbi1tZC1taW4gIWRlZmF1bHQ7XG5cbi8vIExhcmdlIHNjcmVlbiAvIHdpZGUgZGVza3RvcFxuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLWxnYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tbGc6ICAgICAgICAgICAgICAgICAgMTIwMHB4ICFkZWZhdWx0O1xuJHNjcmVlbi1sZy1taW46ICAgICAgICAgICAgICAkc2NyZWVuLWxnICFkZWZhdWx0O1xuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLWxnLWRlc2t0b3BgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi1sZy1kZXNrdG9wOiAgICAgICAgICAkc2NyZWVuLWxnLW1pbiAhZGVmYXVsdDtcblxuLy8gU28gbWVkaWEgcXVlcmllcyBkb24ndCBvdmVybGFwIHdoZW4gcmVxdWlyZWQsIHByb3ZpZGUgYSBtYXhpbXVtXG4kc2NyZWVuLXhzLW1heDogICAgICAgICAgICAgICgkc2NyZWVuLXNtLW1pbiAtIDEpICFkZWZhdWx0O1xuJHNjcmVlbi1zbS1tYXg6ICAgICAgICAgICAgICAoJHNjcmVlbi1tZC1taW4gLSAxKSAhZGVmYXVsdDtcbiRzY3JlZW4tbWQtbWF4OiAgICAgICAgICAgICAgKCRzY3JlZW4tbGctbWluIC0gMSkgIWRlZmF1bHQ7XG5cblxuLy89PSBHcmlkIHN5c3RlbVxuLy9cbi8vIyMgRGVmaW5lIHlvdXIgY3VzdG9tIHJlc3BvbnNpdmUgZ3JpZC5cblxuLy8qKiBOdW1iZXIgb2YgY29sdW1ucyBpbiB0aGUgZ3JpZC5cbiRncmlkLWNvbHVtbnM6ICAgICAgICAgICAgICAxMiAhZGVmYXVsdDtcbi8vKiogUGFkZGluZyBiZXR3ZWVuIGNvbHVtbnMuIEdldHMgZGl2aWRlZCBpbiBoYWxmIGZvciB0aGUgbGVmdCBhbmQgcmlnaHQuXG4kZ3JpZC1ndXR0ZXItd2lkdGg6ICAgICAgICAgMzBweCAhZGVmYXVsdDtcbi8vIE5hdmJhciBjb2xsYXBzZVxuLy8qKiBQb2ludCBhdCB3aGljaCB0aGUgbmF2YmFyIGJlY29tZXMgdW5jb2xsYXBzZWQuXG4kZ3JpZC1mbG9hdC1icmVha3BvaW50OiAgICAgJHNjcmVlbi1zbS1taW4gIWRlZmF1bHQ7XG4vLyoqIFBvaW50IGF0IHdoaWNoIHRoZSBuYXZiYXIgYmVnaW5zIGNvbGxhcHNpbmcuXG4kZ3JpZC1mbG9hdC1icmVha3BvaW50LW1heDogKCRncmlkLWZsb2F0LWJyZWFrcG9pbnQgLSAxKSAhZGVmYXVsdDtcblxuXG4vLz09IENvbnRhaW5lciBzaXplc1xuLy9cbi8vIyMgRGVmaW5lIHRoZSBtYXhpbXVtIHdpZHRoIG9mIGAuY29udGFpbmVyYCBmb3IgZGlmZmVyZW50IHNjcmVlbiBzaXplcy5cblxuLy8gU21hbGwgc2NyZWVuIC8gdGFibGV0XG4kY29udGFpbmVyLXRhYmxldDogICAgICAgICAgICAgKDcyMHB4ICsgJGdyaWQtZ3V0dGVyLXdpZHRoKSAhZGVmYXVsdDtcbi8vKiogRm9yIGAkc2NyZWVuLXNtLW1pbmAgYW5kIHVwLlxuJGNvbnRhaW5lci1zbTogICAgICAgICAgICAgICAgICRjb250YWluZXItdGFibGV0ICFkZWZhdWx0O1xuXG4vLyBNZWRpdW0gc2NyZWVuIC8gZGVza3RvcFxuJGNvbnRhaW5lci1kZXNrdG9wOiAgICAgICAgICAgICg5NDBweCArICRncmlkLWd1dHRlci13aWR0aCkgIWRlZmF1bHQ7XG4vLyoqIEZvciBgJHNjcmVlbi1tZC1taW5gIGFuZCB1cC5cbiRjb250YWluZXItbWQ6ICAgICAgICAgICAgICAgICAkY29udGFpbmVyLWRlc2t0b3AgIWRlZmF1bHQ7XG5cbi8vIExhcmdlIHNjcmVlbiAvIHdpZGUgZGVza3RvcFxuJGNvbnRhaW5lci1sYXJnZS1kZXNrdG9wOiAgICAgICgxMTQwcHggKyAkZ3JpZC1ndXR0ZXItd2lkdGgpICFkZWZhdWx0O1xuLy8qKiBGb3IgYCRzY3JlZW4tbGctbWluYCBhbmQgdXAuXG4kY29udGFpbmVyLWxnOiAgICAgICAgICAgICAgICAgJGNvbnRhaW5lci1sYXJnZS1kZXNrdG9wICFkZWZhdWx0O1xuXG5cbi8vPT0gTmF2YmFyXG4vL1xuLy8jI1xuXG4vLyBCYXNpY3Mgb2YgYSBuYXZiYXJcbiRuYXZiYXItaGVpZ2h0OiAgICAgICAgICAgICAgICAgICAgNTBweCAhZGVmYXVsdDtcbiRuYXZiYXItbWFyZ2luLWJvdHRvbTogICAgICAgICAgICAgJGxpbmUtaGVpZ2h0LWNvbXB1dGVkICFkZWZhdWx0O1xuJG5hdmJhci1ib3JkZXItcmFkaXVzOiAgICAgICAgICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuJG5hdmJhci1wYWRkaW5nLWhvcml6b250YWw6ICAgICAgICBmbG9vcigoJGdyaWQtZ3V0dGVyLXdpZHRoIC8gMikpICFkZWZhdWx0O1xuJG5hdmJhci1wYWRkaW5nLXZlcnRpY2FsOiAgICAgICAgICAoKCRuYXZiYXItaGVpZ2h0IC0gJGxpbmUtaGVpZ2h0LWNvbXB1dGVkKSAvIDIpICFkZWZhdWx0O1xuJG5hdmJhci1jb2xsYXBzZS1tYXgtaGVpZ2h0OiAgICAgICAzNDBweCAhZGVmYXVsdDtcblxuJG5hdmJhci1kZWZhdWx0LWNvbG9yOiAgICAgICAgICAgICAjNzc3ICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWJnOiAgICAgICAgICAgICAgICAjZjhmOGY4ICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWJvcmRlcjogICAgICAgICAgICBkYXJrZW4oJG5hdmJhci1kZWZhdWx0LWJnLCA2LjUlKSAhZGVmYXVsdDtcblxuLy8gTmF2YmFyIGxpbmtzXG4kbmF2YmFyLWRlZmF1bHQtbGluay1jb2xvcjogICAgICAgICAgICAgICAgIzc3NyAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWhvdmVyLWNvbG9yOiAgICAgICAgICAjMzMzICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstaG92ZXItYmc6ICAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstYWN0aXZlLWNvbG9yOiAgICAgICAgICM1NTUgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1hY3RpdmUtYmc6ICAgICAgICAgICAgZGFya2VuKCRuYXZiYXItZGVmYXVsdC1iZywgNi41JSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1kaXNhYmxlZC1jb2xvcjogICAgICAgI2NjYyAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWRpc2FibGVkLWJnOiAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcblxuLy8gTmF2YmFyIGJyYW5kIGxhYmVsXG4kbmF2YmFyLWRlZmF1bHQtYnJhbmQtY29sb3I6ICAgICAgICAgICAgICAgJG5hdmJhci1kZWZhdWx0LWxpbmstY29sb3IgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtYnJhbmQtaG92ZXItY29sb3I6ICAgICAgICAgZGFya2VuKCRuYXZiYXItZGVmYXVsdC1icmFuZC1jb2xvciwgMTAlKSAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1icmFuZC1ob3Zlci1iZzogICAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcblxuLy8gTmF2YmFyIHRvZ2dsZVxuJG5hdmJhci1kZWZhdWx0LXRvZ2dsZS1ob3Zlci1iZzogICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtdG9nZ2xlLWljb24tYmFyLWJnOiAgICAgICAgIzg4OCAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC10b2dnbGUtYm9yZGVyLWNvbG9yOiAgICAgICAjZGRkICFkZWZhdWx0O1xuXG5cbi8vPT09IEludmVydGVkIG5hdmJhclxuLy8gUmVzZXQgaW52ZXJ0ZWQgbmF2YmFyIGJhc2ljc1xuJG5hdmJhci1pbnZlcnNlLWNvbG9yOiAgICAgICAgICAgICAgICAgICAgICBsaWdodGVuKCRncmF5LWxpZ2h0LCAxNSUpICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWJnOiAgICAgICAgICAgICAgICAgICAgICAgICAjMjIyICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWJvcmRlcjogICAgICAgICAgICAgICAgICAgICBkYXJrZW4oJG5hdmJhci1pbnZlcnNlLWJnLCAxMCUpICFkZWZhdWx0O1xuXG4vLyBJbnZlcnRlZCBuYXZiYXIgbGlua3NcbiRuYXZiYXItaW52ZXJzZS1saW5rLWNvbG9yOiAgICAgICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1saWdodCwgMTUlKSAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWhvdmVyLWNvbG9yOiAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWhvdmVyLWJnOiAgICAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1hY3RpdmUtY29sb3I6ICAgICAgICAgICRuYXZiYXItaW52ZXJzZS1saW5rLWhvdmVyLWNvbG9yICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWxpbmstYWN0aXZlLWJnOiAgICAgICAgICAgICBkYXJrZW4oJG5hdmJhci1pbnZlcnNlLWJnLCAxMCUpICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWxpbmstZGlzYWJsZWQtY29sb3I6ICAgICAgICAjNDQ0ICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWxpbmstZGlzYWJsZWQtYmc6ICAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcblxuLy8gSW52ZXJ0ZWQgbmF2YmFyIGJyYW5kIGxhYmVsXG4kbmF2YmFyLWludmVyc2UtYnJhbmQtY29sb3I6ICAgICAgICAgICAgICAgICRuYXZiYXItaW52ZXJzZS1saW5rLWNvbG9yICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWJyYW5kLWhvdmVyLWNvbG9yOiAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWJyYW5kLWhvdmVyLWJnOiAgICAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcblxuLy8gSW52ZXJ0ZWQgbmF2YmFyIHRvZ2dsZVxuJG5hdmJhci1pbnZlcnNlLXRvZ2dsZS1ob3Zlci1iZzogICAgICAgICAgICAjMzMzICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLXRvZ2dsZS1pY29uLWJhci1iZzogICAgICAgICAjZmZmICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLXRvZ2dsZS1ib3JkZXItY29sb3I6ICAgICAgICAjMzMzICFkZWZhdWx0O1xuXG5cbi8vPT0gTmF2c1xuLy9cbi8vIyNcblxuLy89PT0gU2hhcmVkIG5hdiBzdHlsZXNcbiRuYXYtbGluay1wYWRkaW5nOiAgICAgICAgICAgICAgICAgICAgICAgICAgMTBweCAxNXB4ICFkZWZhdWx0O1xuJG5hdi1saW5rLWhvdmVyLWJnOiAgICAgICAgICAgICAgICAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuXG4kbmF2LWRpc2FibGVkLWxpbmstY29sb3I6ICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuJG5hdi1kaXNhYmxlZC1saW5rLWhvdmVyLWNvbG9yOiAgICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcblxuLy89PSBUYWJzXG4kbmF2LXRhYnMtYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cbiRuYXYtdGFicy1saW5rLWhvdmVyLWJvcmRlci1jb2xvcjogICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcblxuJG5hdi10YWJzLWFjdGl2ZS1saW5rLWhvdmVyLWJnOiAgICAgICAgICAgICAkYm9keS1iZyAhZGVmYXVsdDtcbiRuYXYtdGFicy1hY3RpdmUtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAgJGdyYXkgIWRlZmF1bHQ7XG4kbmF2LXRhYnMtYWN0aXZlLWxpbmstaG92ZXItYm9yZGVyLWNvbG9yOiAgICNkZGQgIWRlZmF1bHQ7XG5cbiRuYXYtdGFicy1qdXN0aWZpZWQtbGluay1ib3JkZXItY29sb3I6ICAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcbiRuYXYtdGFicy1qdXN0aWZpZWQtYWN0aXZlLWxpbmstYm9yZGVyLWNvbG9yOiAgICAgJGJvZHktYmcgIWRlZmF1bHQ7XG5cbi8vPT0gUGlsbHNcbiRuYXYtcGlsbHMtYm9yZGVyLXJhZGl1czogICAgICAgICAgICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcbiRuYXYtcGlsbHMtYWN0aXZlLWxpbmstaG92ZXItYmc6ICAgICAgICAgICAgJGNvbXBvbmVudC1hY3RpdmUtYmcgIWRlZmF1bHQ7XG4kbmF2LXBpbGxzLWFjdGl2ZS1saW5rLWhvdmVyLWNvbG9yOiAgICAgICAgICRjb21wb25lbnQtYWN0aXZlLWNvbG9yICFkZWZhdWx0O1xuXG5cbi8vPT0gUGFnaW5hdGlvblxuLy9cbi8vIyNcblxuJHBhZ2luYXRpb24tY29sb3I6ICAgICAgICAgICAgICAgICAgICAgJGxpbmstY29sb3IgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1iZzogICAgICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJHBhZ2luYXRpb24tYm9yZGVyOiAgICAgICAgICAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcblxuJHBhZ2luYXRpb24taG92ZXItY29sb3I6ICAgICAgICAgICAgICAgJGxpbmstaG92ZXItY29sb3IgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1ob3Zlci1iZzogICAgICAgICAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuJHBhZ2luYXRpb24taG92ZXItYm9yZGVyOiAgICAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcblxuJHBhZ2luYXRpb24tYWN0aXZlLWNvbG9yOiAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWFjdGl2ZS1iZzogICAgICAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuJHBhZ2luYXRpb24tYWN0aXZlLWJvcmRlcjogICAgICAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG5cbiRwYWdpbmF0aW9uLWRpc2FibGVkLWNvbG9yOiAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuJHBhZ2luYXRpb24tZGlzYWJsZWQtYmc6ICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWRpc2FibGVkLWJvcmRlcjogICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cblxuLy89PSBQYWdlclxuLy9cbi8vIyNcblxuJHBhZ2VyLWJnOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24tYmcgIWRlZmF1bHQ7XG4kcGFnZXItYm9yZGVyOiAgICAgICAgICAgICAgICAgICAgICAgICAkcGFnaW5hdGlvbi1ib3JkZXIgIWRlZmF1bHQ7XG4kcGFnZXItYm9yZGVyLXJhZGl1czogICAgICAgICAgICAgICAgICAxNXB4ICFkZWZhdWx0O1xuXG4kcGFnZXItaG92ZXItYmc6ICAgICAgICAgICAgICAgICAgICAgICAkcGFnaW5hdGlvbi1ob3Zlci1iZyAhZGVmYXVsdDtcblxuJHBhZ2VyLWFjdGl2ZS1iZzogICAgICAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24tYWN0aXZlLWJnICFkZWZhdWx0O1xuJHBhZ2VyLWFjdGl2ZS1jb2xvcjogICAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24tYWN0aXZlLWNvbG9yICFkZWZhdWx0O1xuXG4kcGFnZXItZGlzYWJsZWQtY29sb3I6ICAgICAgICAgICAgICAgICAkcGFnaW5hdGlvbi1kaXNhYmxlZC1jb2xvciAhZGVmYXVsdDtcblxuXG4vLz09IEp1bWJvdHJvblxuLy9cbi8vIyNcblxuJGp1bWJvdHJvbi1wYWRkaW5nOiAgICAgICAgICAgICAgMzBweCAhZGVmYXVsdDtcbiRqdW1ib3Ryb24tY29sb3I6ICAgICAgICAgICAgICAgIGluaGVyaXQgIWRlZmF1bHQ7XG4kanVtYm90cm9uLWJnOiAgICAgICAgICAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuJGp1bWJvdHJvbi1oZWFkaW5nLWNvbG9yOiAgICAgICAgaW5oZXJpdCAhZGVmYXVsdDtcbiRqdW1ib3Ryb24tZm9udC1zaXplOiAgICAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDEuNSkpICFkZWZhdWx0O1xuJGp1bWJvdHJvbi1oZWFkaW5nLWZvbnQtc2l6ZTogICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogNC41KSkgIWRlZmF1bHQ7XG5cblxuLy89PSBGb3JtIHN0YXRlcyBhbmQgYWxlcnRzXG4vL1xuLy8jIyBEZWZpbmUgY29sb3JzIGZvciBmb3JtIGZlZWRiYWNrIHN0YXRlcyBhbmQsIGJ5IGRlZmF1bHQsIGFsZXJ0cy5cblxuJHN0YXRlLXN1Y2Nlc3MtdGV4dDogICAgICAgICAgICAgIzNjNzYzZCAhZGVmYXVsdDtcbiRzdGF0ZS1zdWNjZXNzLWJnOiAgICAgICAgICAgICAgICNkZmYwZDggIWRlZmF1bHQ7XG4kc3RhdGUtc3VjY2Vzcy1ib3JkZXI6ICAgICAgICAgICBkYXJrZW4oYWRqdXN0LWh1ZSgkc3RhdGUtc3VjY2Vzcy1iZywgLTEwKSwgNSUpICFkZWZhdWx0O1xuXG4kc3RhdGUtaW5mby10ZXh0OiAgICAgICAgICAgICAgICAjMzE3MDhmICFkZWZhdWx0O1xuJHN0YXRlLWluZm8tYmc6ICAgICAgICAgICAgICAgICAgI2Q5ZWRmNyAhZGVmYXVsdDtcbiRzdGF0ZS1pbmZvLWJvcmRlcjogICAgICAgICAgICAgIGRhcmtlbihhZGp1c3QtaHVlKCRzdGF0ZS1pbmZvLWJnLCAtMTApLCA3JSkgIWRlZmF1bHQ7XG5cbiRzdGF0ZS13YXJuaW5nLXRleHQ6ICAgICAgICAgICAgICM4YTZkM2IgIWRlZmF1bHQ7XG4kc3RhdGUtd2FybmluZy1iZzogICAgICAgICAgICAgICAjZmNmOGUzICFkZWZhdWx0O1xuJHN0YXRlLXdhcm5pbmctYm9yZGVyOiAgICAgICAgICAgZGFya2VuKGFkanVzdC1odWUoJHN0YXRlLXdhcm5pbmctYmcsIC0xMCksIDUlKSAhZGVmYXVsdDtcblxuJHN0YXRlLWRhbmdlci10ZXh0OiAgICAgICAgICAgICAgI2E5NDQ0MiAhZGVmYXVsdDtcbiRzdGF0ZS1kYW5nZXItYmc6ICAgICAgICAgICAgICAgICNmMmRlZGUgIWRlZmF1bHQ7XG4kc3RhdGUtZGFuZ2VyLWJvcmRlcjogICAgICAgICAgICBkYXJrZW4oYWRqdXN0LWh1ZSgkc3RhdGUtZGFuZ2VyLWJnLCAtMTApLCA1JSkgIWRlZmF1bHQ7XG5cblxuLy89PSBUb29sdGlwc1xuLy9cbi8vIyNcblxuLy8qKiBUb29sdGlwIG1heCB3aWR0aFxuJHRvb2x0aXAtbWF4LXdpZHRoOiAgICAgICAgICAgMjAwcHggIWRlZmF1bHQ7XG4vLyoqIFRvb2x0aXAgdGV4dCBjb2xvclxuJHRvb2x0aXAtY29sb3I6ICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogVG9vbHRpcCBiYWNrZ3JvdW5kIGNvbG9yXG4kdG9vbHRpcC1iZzogICAgICAgICAgICAgICAgICAjMDAwICFkZWZhdWx0O1xuJHRvb2x0aXAtb3BhY2l0eTogICAgICAgICAgICAgLjkgIWRlZmF1bHQ7XG5cbi8vKiogVG9vbHRpcCBhcnJvdyB3aWR0aFxuJHRvb2x0aXAtYXJyb3ctd2lkdGg6ICAgICAgICAgNXB4ICFkZWZhdWx0O1xuLy8qKiBUb29sdGlwIGFycm93IGNvbG9yXG4kdG9vbHRpcC1hcnJvdy1jb2xvcjogICAgICAgICAkdG9vbHRpcC1iZyAhZGVmYXVsdDtcblxuXG4vLz09IFBvcG92ZXJzXG4vL1xuLy8jI1xuXG4vLyoqIFBvcG92ZXIgYm9keSBiYWNrZ3JvdW5kIGNvbG9yXG4kcG9wb3Zlci1iZzogICAgICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgbWF4aW11bSB3aWR0aFxuJHBvcG92ZXItbWF4LXdpZHRoOiAgICAgICAgICAgICAgICAgICAyNzZweCAhZGVmYXVsdDtcbi8vKiogUG9wb3ZlciBib3JkZXIgY29sb3JcbiRwb3BvdmVyLWJvcmRlci1jb2xvcjogICAgICAgICAgICAgICAgcmdiYSgwLDAsMCwuMikgIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgZmFsbGJhY2sgYm9yZGVyIGNvbG9yXG4kcG9wb3Zlci1mYWxsYmFjay1ib3JkZXItY29sb3I6ICAgICAgICNjY2MgIWRlZmF1bHQ7XG5cbi8vKiogUG9wb3ZlciB0aXRsZSBiYWNrZ3JvdW5kIGNvbG9yXG4kcG9wb3Zlci10aXRsZS1iZzogICAgICAgICAgICAgICAgICAgIGRhcmtlbigkcG9wb3Zlci1iZywgMyUpICFkZWZhdWx0O1xuXG4vLyoqIFBvcG92ZXIgYXJyb3cgd2lkdGhcbiRwb3BvdmVyLWFycm93LXdpZHRoOiAgICAgICAgICAgICAgICAgMTBweCAhZGVmYXVsdDtcbi8vKiogUG9wb3ZlciBhcnJvdyBjb2xvclxuJHBvcG92ZXItYXJyb3ctY29sb3I6ICAgICAgICAgICAgICAgICAkcG9wb3Zlci1iZyAhZGVmYXVsdDtcblxuLy8qKiBQb3BvdmVyIG91dGVyIGFycm93IHdpZHRoXG4kcG9wb3Zlci1hcnJvdy1vdXRlci13aWR0aDogICAgICAgICAgICgkcG9wb3Zlci1hcnJvdy13aWR0aCArIDEpICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIG91dGVyIGFycm93IGNvbG9yXG4kcG9wb3Zlci1hcnJvdy1vdXRlci1jb2xvcjogICAgICAgICAgIGZhZGVfaW4oJHBvcG92ZXItYm9yZGVyLWNvbG9yLCAwLjA1KSAhZGVmYXVsdDtcbi8vKiogUG9wb3ZlciBvdXRlciBhcnJvdyBmYWxsYmFjayBjb2xvclxuJHBvcG92ZXItYXJyb3ctb3V0ZXItZmFsbGJhY2stY29sb3I6ICBkYXJrZW4oJHBvcG92ZXItZmFsbGJhY2stYm9yZGVyLWNvbG9yLCAyMCUpICFkZWZhdWx0O1xuXG5cbi8vPT0gTGFiZWxzXG4vL1xuLy8jI1xuXG4vLyoqIERlZmF1bHQgbGFiZWwgYmFja2dyb3VuZCBjb2xvclxuJGxhYmVsLWRlZmF1bHQtYmc6ICAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIFByaW1hcnkgbGFiZWwgYmFja2dyb3VuZCBjb2xvclxuJGxhYmVsLXByaW1hcnktYmc6ICAgICAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG4vLyoqIFN1Y2Nlc3MgbGFiZWwgYmFja2dyb3VuZCBjb2xvclxuJGxhYmVsLXN1Y2Nlc3MtYmc6ICAgICAgICAgICAgJGJyYW5kLXN1Y2Nlc3MgIWRlZmF1bHQ7XG4vLyoqIEluZm8gbGFiZWwgYmFja2dyb3VuZCBjb2xvclxuJGxhYmVsLWluZm8tYmc6ICAgICAgICAgICAgICAgJGJyYW5kLWluZm8gIWRlZmF1bHQ7XG4vLyoqIFdhcm5pbmcgbGFiZWwgYmFja2dyb3VuZCBjb2xvclxuJGxhYmVsLXdhcm5pbmctYmc6ICAgICAgICAgICAgJGJyYW5kLXdhcm5pbmcgIWRlZmF1bHQ7XG4vLyoqIERhbmdlciBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtZGFuZ2VyLWJnOiAgICAgICAgICAgICAkYnJhbmQtZGFuZ2VyICFkZWZhdWx0O1xuXG4vLyoqIERlZmF1bHQgbGFiZWwgdGV4dCBjb2xvclxuJGxhYmVsLWNvbG9yOiAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogRGVmYXVsdCB0ZXh0IGNvbG9yIG9mIGEgbGlua2VkIGxhYmVsXG4kbGFiZWwtbGluay1ob3Zlci1jb2xvcjogICAgICAjZmZmICFkZWZhdWx0O1xuXG5cbi8vPT0gTW9kYWxzXG4vL1xuLy8jI1xuXG4vLyoqIFBhZGRpbmcgYXBwbGllZCB0byB0aGUgbW9kYWwgYm9keVxuJG1vZGFsLWlubmVyLXBhZGRpbmc6ICAgICAgICAgMTVweCAhZGVmYXVsdDtcblxuLy8qKiBQYWRkaW5nIGFwcGxpZWQgdG8gdGhlIG1vZGFsIHRpdGxlXG4kbW9kYWwtdGl0bGUtcGFkZGluZzogICAgICAgICAxNXB4ICFkZWZhdWx0O1xuLy8qKiBNb2RhbCB0aXRsZSBsaW5lLWhlaWdodFxuJG1vZGFsLXRpdGxlLWxpbmUtaGVpZ2h0OiAgICAgJGxpbmUtaGVpZ2h0LWJhc2UgIWRlZmF1bHQ7XG5cbi8vKiogQmFja2dyb3VuZCBjb2xvciBvZiBtb2RhbCBjb250ZW50IGFyZWFcbiRtb2RhbC1jb250ZW50LWJnOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogTW9kYWwgY29udGVudCBib3JkZXIgY29sb3JcbiRtb2RhbC1jb250ZW50LWJvcmRlci1jb2xvcjogICAgICAgICAgICAgICAgICAgcmdiYSgwLDAsMCwuMikgIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIGNvbnRlbnQgYm9yZGVyIGNvbG9yICoqZm9yIElFOCoqXG4kbW9kYWwtY29udGVudC1mYWxsYmFjay1ib3JkZXItY29sb3I6ICAgICAgICAgICM5OTkgIWRlZmF1bHQ7XG5cbi8vKiogTW9kYWwgYmFja2Ryb3AgYmFja2dyb3VuZCBjb2xvclxuJG1vZGFsLWJhY2tkcm9wLWJnOiAgICAgICAgICAgIzAwMCAhZGVmYXVsdDtcbi8vKiogTW9kYWwgYmFja2Ryb3Agb3BhY2l0eVxuJG1vZGFsLWJhY2tkcm9wLW9wYWNpdHk6ICAgICAgLjUgIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIGhlYWRlciBib3JkZXIgY29sb3JcbiRtb2RhbC1oZWFkZXItYm9yZGVyLWNvbG9yOiAgICNlNWU1ZTUgIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIGZvb3RlciBib3JkZXIgY29sb3JcbiRtb2RhbC1mb290ZXItYm9yZGVyLWNvbG9yOiAgICRtb2RhbC1oZWFkZXItYm9yZGVyLWNvbG9yICFkZWZhdWx0O1xuXG4kbW9kYWwtbGc6ICAgICAgICAgICAgICAgICAgICA5MDBweCAhZGVmYXVsdDtcbiRtb2RhbC1tZDogICAgICAgICAgICAgICAgICAgIDYwMHB4ICFkZWZhdWx0O1xuJG1vZGFsLXNtOiAgICAgICAgICAgICAgICAgICAgMzAwcHggIWRlZmF1bHQ7XG5cblxuLy89PSBBbGVydHNcbi8vXG4vLyMjIERlZmluZSBhbGVydCBjb2xvcnMsIGJvcmRlciByYWRpdXMsIGFuZCBwYWRkaW5nLlxuXG4kYWxlcnQtcGFkZGluZzogICAgICAgICAgICAgICAxNXB4ICFkZWZhdWx0O1xuJGFsZXJ0LWJvcmRlci1yYWRpdXM6ICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcbiRhbGVydC1saW5rLWZvbnQtd2VpZ2h0OiAgICAgIGJvbGQgIWRlZmF1bHQ7XG5cbiRhbGVydC1zdWNjZXNzLWJnOiAgICAgICAgICAgICRzdGF0ZS1zdWNjZXNzLWJnICFkZWZhdWx0O1xuJGFsZXJ0LXN1Y2Nlc3MtdGV4dDogICAgICAgICAgJHN0YXRlLXN1Y2Nlc3MtdGV4dCAhZGVmYXVsdDtcbiRhbGVydC1zdWNjZXNzLWJvcmRlcjogICAgICAgICRzdGF0ZS1zdWNjZXNzLWJvcmRlciAhZGVmYXVsdDtcblxuJGFsZXJ0LWluZm8tYmc6ICAgICAgICAgICAgICAgJHN0YXRlLWluZm8tYmcgIWRlZmF1bHQ7XG4kYWxlcnQtaW5mby10ZXh0OiAgICAgICAgICAgICAkc3RhdGUtaW5mby10ZXh0ICFkZWZhdWx0O1xuJGFsZXJ0LWluZm8tYm9yZGVyOiAgICAgICAgICAgJHN0YXRlLWluZm8tYm9yZGVyICFkZWZhdWx0O1xuXG4kYWxlcnQtd2FybmluZy1iZzogICAgICAgICAgICAkc3RhdGUtd2FybmluZy1iZyAhZGVmYXVsdDtcbiRhbGVydC13YXJuaW5nLXRleHQ6ICAgICAgICAgICRzdGF0ZS13YXJuaW5nLXRleHQgIWRlZmF1bHQ7XG4kYWxlcnQtd2FybmluZy1ib3JkZXI6ICAgICAgICAkc3RhdGUtd2FybmluZy1ib3JkZXIgIWRlZmF1bHQ7XG5cbiRhbGVydC1kYW5nZXItYmc6ICAgICAgICAgICAgICRzdGF0ZS1kYW5nZXItYmcgIWRlZmF1bHQ7XG4kYWxlcnQtZGFuZ2VyLXRleHQ6ICAgICAgICAgICAkc3RhdGUtZGFuZ2VyLXRleHQgIWRlZmF1bHQ7XG4kYWxlcnQtZGFuZ2VyLWJvcmRlcjogICAgICAgICAkc3RhdGUtZGFuZ2VyLWJvcmRlciAhZGVmYXVsdDtcblxuXG4vLz09IFByb2dyZXNzIGJhcnNcbi8vXG4vLyMjXG5cbi8vKiogQmFja2dyb3VuZCBjb2xvciBvZiB0aGUgd2hvbGUgcHJvZ3Jlc3MgY29tcG9uZW50XG4kcHJvZ3Jlc3MtYmc6ICAgICAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuLy8qKiBQcm9ncmVzcyBiYXIgdGV4dCBjb2xvclxuJHByb2dyZXNzLWJhci1jb2xvcjogICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogVmFyaWFibGUgZm9yIHNldHRpbmcgcm91bmRlZCBjb3JuZXJzIG9uIHByb2dyZXNzIGJhci5cbiRwcm9ncmVzcy1ib3JkZXItcmFkaXVzOiAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG5cbi8vKiogRGVmYXVsdCBwcm9ncmVzcyBiYXIgY29sb3JcbiRwcm9ncmVzcy1iYXItYmc6ICAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuLy8qKiBTdWNjZXNzIHByb2dyZXNzIGJhciBjb2xvclxuJHByb2dyZXNzLWJhci1zdWNjZXNzLWJnOiAgICAgJGJyYW5kLXN1Y2Nlc3MgIWRlZmF1bHQ7XG4vLyoqIFdhcm5pbmcgcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLXdhcm5pbmctYmc6ICAgICAkYnJhbmQtd2FybmluZyAhZGVmYXVsdDtcbi8vKiogRGFuZ2VyIHByb2dyZXNzIGJhciBjb2xvclxuJHByb2dyZXNzLWJhci1kYW5nZXItYmc6ICAgICAgJGJyYW5kLWRhbmdlciAhZGVmYXVsdDtcbi8vKiogSW5mbyBwcm9ncmVzcyBiYXIgY29sb3JcbiRwcm9ncmVzcy1iYXItaW5mby1iZzogICAgICAgICRicmFuZC1pbmZvICFkZWZhdWx0O1xuXG5cbi8vPT0gTGlzdCBncm91cFxuLy9cbi8vIyNcblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9uIGAubGlzdC1ncm91cC1pdGVtYFxuJGxpc3QtZ3JvdXAtYmc6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBgLmxpc3QtZ3JvdXAtaXRlbWAgYm9yZGVyIGNvbG9yXG4kbGlzdC1ncm91cC1ib3JkZXI6ICAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG4vLyoqIExpc3QgZ3JvdXAgYm9yZGVyIHJhZGl1c1xuJGxpc3QtZ3JvdXAtYm9yZGVyLXJhZGl1czogICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2Ygc2luZ2xlIGxpc3QgaXRlbXMgb24gaG92ZXJcbiRsaXN0LWdyb3VwLWhvdmVyLWJnOiAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcbi8vKiogVGV4dCBjb2xvciBvZiBhY3RpdmUgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtYWN0aXZlLWNvbG9yOiAgICAgICAkY29tcG9uZW50LWFjdGl2ZS1jb2xvciAhZGVmYXVsdDtcbi8vKiogQmFja2dyb3VuZCBjb2xvciBvZiBhY3RpdmUgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtYWN0aXZlLWJnOiAgICAgICAgICAkY29tcG9uZW50LWFjdGl2ZS1iZyAhZGVmYXVsdDtcbi8vKiogQm9yZGVyIGNvbG9yIG9mIGFjdGl2ZSBsaXN0IGVsZW1lbnRzXG4kbGlzdC1ncm91cC1hY3RpdmUtYm9yZGVyOiAgICAgICRsaXN0LWdyb3VwLWFjdGl2ZS1iZyAhZGVmYXVsdDtcbi8vKiogVGV4dCBjb2xvciBmb3IgY29udGVudCB3aXRoaW4gYWN0aXZlIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWFjdGl2ZS10ZXh0LWNvbG9yOiAgbGlnaHRlbigkbGlzdC1ncm91cC1hY3RpdmUtYmcsIDQwJSkgIWRlZmF1bHQ7XG5cbi8vKiogVGV4dCBjb2xvciBvZiBkaXNhYmxlZCBsaXN0IGl0ZW1zXG4kbGlzdC1ncm91cC1kaXNhYmxlZC1jb2xvcjogICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogQmFja2dyb3VuZCBjb2xvciBvZiBkaXNhYmxlZCBsaXN0IGl0ZW1zXG4kbGlzdC1ncm91cC1kaXNhYmxlZC1iZzogICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuLy8qKiBUZXh0IGNvbG9yIGZvciBjb250ZW50IHdpdGhpbiBkaXNhYmxlZCBsaXN0IGl0ZW1zXG4kbGlzdC1ncm91cC1kaXNhYmxlZC10ZXh0LWNvbG9yOiAkbGlzdC1ncm91cC1kaXNhYmxlZC1jb2xvciAhZGVmYXVsdDtcblxuJGxpc3QtZ3JvdXAtbGluay1jb2xvcjogICAgICAgICAjNTU1ICFkZWZhdWx0O1xuJGxpc3QtZ3JvdXAtbGluay1ob3Zlci1jb2xvcjogICAkbGlzdC1ncm91cC1saW5rLWNvbG9yICFkZWZhdWx0O1xuJGxpc3QtZ3JvdXAtbGluay1oZWFkaW5nLWNvbG9yOiAjMzMzICFkZWZhdWx0O1xuXG5cbi8vPT0gUGFuZWxzXG4vL1xuLy8jI1xuXG4kcGFuZWwtYmc6ICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJHBhbmVsLWJvZHktcGFkZGluZzogICAgICAgICAgMTVweCAhZGVmYXVsdDtcbiRwYW5lbC1oZWFkaW5nLXBhZGRpbmc6ICAgICAgIDEwcHggMTVweCAhZGVmYXVsdDtcbiRwYW5lbC1mb290ZXItcGFkZGluZzogICAgICAgICRwYW5lbC1oZWFkaW5nLXBhZGRpbmcgIWRlZmF1bHQ7XG4kcGFuZWwtYm9yZGVyLXJhZGl1czogICAgICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuXG4vLyoqIEJvcmRlciBjb2xvciBmb3IgZWxlbWVudHMgd2l0aGluIHBhbmVsc1xuJHBhbmVsLWlubmVyLWJvcmRlcjogICAgICAgICAgI2RkZCAhZGVmYXVsdDtcbiRwYW5lbC1mb290ZXItYmc6ICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG5cbiRwYW5lbC1kZWZhdWx0LXRleHQ6ICAgICAgICAgICRncmF5LWRhcmsgIWRlZmF1bHQ7XG4kcGFuZWwtZGVmYXVsdC1ib3JkZXI6ICAgICAgICAjZGRkICFkZWZhdWx0O1xuJHBhbmVsLWRlZmF1bHQtaGVhZGluZy1iZzogICAgI2Y1ZjVmNSAhZGVmYXVsdDtcblxuJHBhbmVsLXByaW1hcnktdGV4dDogICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRwYW5lbC1wcmltYXJ5LWJvcmRlcjogICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuJHBhbmVsLXByaW1hcnktaGVhZGluZy1iZzogICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG5cbiRwYW5lbC1zdWNjZXNzLXRleHQ6ICAgICAgICAgICRzdGF0ZS1zdWNjZXNzLXRleHQgIWRlZmF1bHQ7XG4kcGFuZWwtc3VjY2Vzcy1ib3JkZXI6ICAgICAgICAkc3RhdGUtc3VjY2Vzcy1ib3JkZXIgIWRlZmF1bHQ7XG4kcGFuZWwtc3VjY2Vzcy1oZWFkaW5nLWJnOiAgICAkc3RhdGUtc3VjY2Vzcy1iZyAhZGVmYXVsdDtcblxuJHBhbmVsLWluZm8tdGV4dDogICAgICAgICAgICAgJHN0YXRlLWluZm8tdGV4dCAhZGVmYXVsdDtcbiRwYW5lbC1pbmZvLWJvcmRlcjogICAgICAgICAgICRzdGF0ZS1pbmZvLWJvcmRlciAhZGVmYXVsdDtcbiRwYW5lbC1pbmZvLWhlYWRpbmctYmc6ICAgICAgICRzdGF0ZS1pbmZvLWJnICFkZWZhdWx0O1xuXG4kcGFuZWwtd2FybmluZy10ZXh0OiAgICAgICAgICAkc3RhdGUtd2FybmluZy10ZXh0ICFkZWZhdWx0O1xuJHBhbmVsLXdhcm5pbmctYm9yZGVyOiAgICAgICAgJHN0YXRlLXdhcm5pbmctYm9yZGVyICFkZWZhdWx0O1xuJHBhbmVsLXdhcm5pbmctaGVhZGluZy1iZzogICAgJHN0YXRlLXdhcm5pbmctYmcgIWRlZmF1bHQ7XG5cbiRwYW5lbC1kYW5nZXItdGV4dDogICAgICAgICAgICRzdGF0ZS1kYW5nZXItdGV4dCAhZGVmYXVsdDtcbiRwYW5lbC1kYW5nZXItYm9yZGVyOiAgICAgICAgICRzdGF0ZS1kYW5nZXItYm9yZGVyICFkZWZhdWx0O1xuJHBhbmVsLWRhbmdlci1oZWFkaW5nLWJnOiAgICAgJHN0YXRlLWRhbmdlci1iZyAhZGVmYXVsdDtcblxuXG4vLz09IFRodW1ibmFpbHNcbi8vXG4vLyMjXG5cbi8vKiogUGFkZGluZyBhcm91bmQgdGhlIHRodW1ibmFpbCBpbWFnZVxuJHRodW1ibmFpbC1wYWRkaW5nOiAgICAgICAgICAgNHB4ICFkZWZhdWx0O1xuLy8qKiBUaHVtYm5haWwgYmFja2dyb3VuZCBjb2xvclxuJHRodW1ibmFpbC1iZzogICAgICAgICAgICAgICAgJGJvZHktYmcgIWRlZmF1bHQ7XG4vLyoqIFRodW1ibmFpbCBib3JkZXIgY29sb3JcbiR0aHVtYm5haWwtYm9yZGVyOiAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG4vLyoqIFRodW1ibmFpbCBib3JkZXIgcmFkaXVzXG4kdGh1bWJuYWlsLWJvcmRlci1yYWRpdXM6ICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuXG4vLyoqIEN1c3RvbSB0ZXh0IGNvbG9yIGZvciB0aHVtYm5haWwgY2FwdGlvbnNcbiR0aHVtYm5haWwtY2FwdGlvbi1jb2xvcjogICAgICR0ZXh0LWNvbG9yICFkZWZhdWx0O1xuLy8qKiBQYWRkaW5nIGFyb3VuZCB0aGUgdGh1bWJuYWlsIGNhcHRpb25cbiR0aHVtYm5haWwtY2FwdGlvbi1wYWRkaW5nOiAgIDlweCAhZGVmYXVsdDtcblxuXG4vLz09IFdlbGxzXG4vL1xuLy8jI1xuXG4kd2VsbC1iZzogICAgICAgICAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuJHdlbGwtYm9yZGVyOiAgICAgICAgICAgICAgICAgZGFya2VuKCR3ZWxsLWJnLCA3JSkgIWRlZmF1bHQ7XG5cblxuLy89PSBCYWRnZXNcbi8vXG4vLyMjXG5cbiRiYWRnZS1jb2xvcjogICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIExpbmtlZCBiYWRnZSB0ZXh0IGNvbG9yIG9uIGhvdmVyXG4kYmFkZ2UtbGluay1ob3Zlci1jb2xvcjogICAgICAjZmZmICFkZWZhdWx0O1xuJGJhZGdlLWJnOiAgICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG5cbi8vKiogQmFkZ2UgdGV4dCBjb2xvciBpbiBhY3RpdmUgbmF2IGxpbmtcbiRiYWRnZS1hY3RpdmUtY29sb3I6ICAgICAgICAgICRsaW5rLWNvbG9yICFkZWZhdWx0O1xuLy8qKiBCYWRnZSBiYWNrZ3JvdW5kIGNvbG9yIGluIGFjdGl2ZSBuYXYgbGlua1xuJGJhZGdlLWFjdGl2ZS1iZzogICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcblxuJGJhZGdlLWZvbnQtd2VpZ2h0OiAgICAgICAgICAgYm9sZCAhZGVmYXVsdDtcbiRiYWRnZS1saW5lLWhlaWdodDogICAgICAgICAgIDEgIWRlZmF1bHQ7XG4kYmFkZ2UtYm9yZGVyLXJhZGl1czogICAgICAgICAxMHB4ICFkZWZhdWx0O1xuXG5cbi8vPT0gQnJlYWRjcnVtYnNcbi8vXG4vLyMjXG5cbiRicmVhZGNydW1iLXBhZGRpbmctdmVydGljYWw6ICAgOHB4ICFkZWZhdWx0O1xuJGJyZWFkY3J1bWItcGFkZGluZy1ob3Jpem9udGFsOiAxNXB4ICFkZWZhdWx0O1xuLy8qKiBCcmVhZGNydW1iIGJhY2tncm91bmQgY29sb3JcbiRicmVhZGNydW1iLWJnOiAgICAgICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcbi8vKiogQnJlYWRjcnVtYiB0ZXh0IGNvbG9yXG4kYnJlYWRjcnVtYi1jb2xvcjogICAgICAgICAgICAgICNjY2MgIWRlZmF1bHQ7XG4vLyoqIFRleHQgY29sb3Igb2YgY3VycmVudCBwYWdlIGluIHRoZSBicmVhZGNydW1iXG4kYnJlYWRjcnVtYi1hY3RpdmUtY29sb3I6ICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBUZXh0dWFsIHNlcGFyYXRvciBmb3IgYmV0d2VlbiBicmVhZGNydW1iIGVsZW1lbnRzXG4kYnJlYWRjcnVtYi1zZXBhcmF0b3I6ICAgICAgICAgIFwiL1wiICFkZWZhdWx0O1xuXG5cbi8vPT0gQ2Fyb3VzZWxcbi8vXG4vLyMjXG5cbiRjYXJvdXNlbC10ZXh0LXNoYWRvdzogICAgICAgICAgICAgICAgICAgICAgICAwIDFweCAycHggcmdiYSgwLDAsMCwuNikgIWRlZmF1bHQ7XG5cbiRjYXJvdXNlbC1jb250cm9sLWNvbG9yOiAgICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGNhcm91c2VsLWNvbnRyb2wtd2lkdGg6ICAgICAgICAgICAgICAgICAgICAgIDE1JSAhZGVmYXVsdDtcbiRjYXJvdXNlbC1jb250cm9sLW9wYWNpdHk6ICAgICAgICAgICAgICAgICAgICAuNSAhZGVmYXVsdDtcbiRjYXJvdXNlbC1jb250cm9sLWZvbnQtc2l6ZTogICAgICAgICAgICAgICAgICAyMHB4ICFkZWZhdWx0O1xuXG4kY2Fyb3VzZWwtaW5kaWNhdG9yLWFjdGl2ZS1iZzogICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRjYXJvdXNlbC1pbmRpY2F0b3ItYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuXG4kY2Fyb3VzZWwtY2FwdGlvbi1jb2xvcjogICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcblxuXG4vLz09IENsb3NlXG4vL1xuLy8jI1xuXG4kY2xvc2UtZm9udC13ZWlnaHQ6ICAgICAgICAgICBib2xkICFkZWZhdWx0O1xuJGNsb3NlLWNvbG9yOiAgICAgICAgICAgICAgICAgIzAwMCAhZGVmYXVsdDtcbiRjbG9zZS10ZXh0LXNoYWRvdzogICAgICAgICAgIDAgMXB4IDAgI2ZmZiAhZGVmYXVsdDtcblxuXG4vLz09IENvZGVcbi8vXG4vLyMjXG5cbiRjb2RlLWNvbG9yOiAgICAgICAgICAgICAgICAgICNjNzI1NGUgIWRlZmF1bHQ7XG4kY29kZS1iZzogICAgICAgICAgICAgICAgICAgICAjZjlmMmY0ICFkZWZhdWx0O1xuXG4ka2JkLWNvbG9yOiAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGtiZC1iZzogICAgICAgICAgICAgICAgICAgICAgIzMzMyAhZGVmYXVsdDtcblxuJHByZS1iZzogICAgICAgICAgICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcbiRwcmUtY29sb3I6ICAgICAgICAgICAgICAgICAgICRncmF5LWRhcmsgIWRlZmF1bHQ7XG4kcHJlLWJvcmRlci1jb2xvcjogICAgICAgICAgICAjY2NjICFkZWZhdWx0O1xuJHByZS1zY3JvbGxhYmxlLW1heC1oZWlnaHQ6ICAgMzQwcHggIWRlZmF1bHQ7XG5cblxuLy89PSBUeXBlXG4vL1xuLy8jI1xuXG4vLyoqIEhvcml6b250YWwgb2Zmc2V0IGZvciBmb3JtcyBhbmQgbGlzdHMuXG4kY29tcG9uZW50LW9mZnNldC1ob3Jpem9udGFsOiAxODBweCAhZGVmYXVsdDtcbi8vKiogVGV4dCBtdXRlZCBjb2xvclxuJHRleHQtbXV0ZWQ6ICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIEFiYnJldmlhdGlvbnMgYW5kIGFjcm9ueW1zIGJvcmRlciBjb2xvclxuJGFiYnItYm9yZGVyLWNvbG9yOiAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIEhlYWRpbmdzIHNtYWxsIGNvbG9yXG4kaGVhZGluZ3Mtc21hbGwtY29sb3I6ICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogQmxvY2txdW90ZSBzbWFsbCBjb2xvclxuJGJsb2NrcXVvdGUtc21hbGwtY29sb3I6ICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIEJsb2NrcXVvdGUgZm9udCBzaXplXG4kYmxvY2txdW90ZS1mb250LXNpemU6ICAgICAgICAoJGZvbnQtc2l6ZS1iYXNlICogMS4yNSkgIWRlZmF1bHQ7XG4vLyoqIEJsb2NrcXVvdGUgYm9yZGVyIGNvbG9yXG4kYmxvY2txdW90ZS1ib3JkZXItY29sb3I6ICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuLy8qKiBQYWdlIGhlYWRlciBib3JkZXIgY29sb3JcbiRwYWdlLWhlYWRlci1ib3JkZXItY29sb3I6ICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4vLyoqIFdpZHRoIG9mIGhvcml6b250YWwgZGVzY3JpcHRpb24gbGlzdCB0aXRsZXNcbiRkbC1ob3Jpem9udGFsLW9mZnNldDogICAgICAgICRjb21wb25lbnQtb2Zmc2V0LWhvcml6b250YWwgIWRlZmF1bHQ7XG4vLyoqIFBvaW50IGF0IHdoaWNoIC5kbC1ob3Jpem9udGFsIGJlY29tZXMgaG9yaXpvbnRhbFxuJGRsLWhvcml6b250YWwtYnJlYWtwb2ludDogICAgJGdyaWQtZmxvYXQtYnJlYWtwb2ludCAhZGVmYXVsdDtcbi8vKiogSG9yaXpvbnRhbCBsaW5lIGNvbG9yLlxuJGhyLWJvcmRlcjogICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbiIsIi5sb2FkZXIge1xuICBmb250LXNpemU6IDEwcHg7XG4gIG1hcmdpbjogMCBhdXRvO1xuICB0ZXh0LWluZGVudDogLTk5OTllbTtcbiAgd2lkdGg6IDExZW07XG4gIGhlaWdodDogMTFlbTtcbiAgYm9yZGVyLXJhZGl1czogNTAlO1xuICBiYWNrZ3JvdW5kOiAjZmZmZmZmO1xuICBiYWNrZ3JvdW5kOiAtbW96LWxpbmVhci1ncmFkaWVudChsZWZ0LCAjZmZmZmZmIDEwJSwgcmdiYSgyNTUsIDI1NSwgMjU1LCAwKSA0MiUpO1xuICBiYWNrZ3JvdW5kOiAtd2Via2l0LWxpbmVhci1ncmFkaWVudChsZWZ0LCAjZmZmZmZmIDEwJSwgcmdiYSgyNTUsIDI1NSwgMjU1LCAwKSA0MiUpO1xuICBiYWNrZ3JvdW5kOiAtby1saW5lYXItZ3JhZGllbnQobGVmdCwgI2ZmZmZmZiAxMCUsIHJnYmEoMjU1LCAyNTUsIDI1NSwgMCkgNDIlKTtcbiAgYmFja2dyb3VuZDogLW1zLWxpbmVhci1ncmFkaWVudChsZWZ0LCAjZmZmZmZmIDEwJSwgcmdiYSgyNTUsIDI1NSwgMjU1LCAwKSA0MiUpO1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gcmlnaHQsICNmZmZmZmYgMTAlLCByZ2JhKDI1NSwgMjU1LCAyNTUsIDApIDQyJSk7XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgYW5pbWF0aW9uOiBsb2FkZXJTcGlubmVyIDEuNHMgaW5maW5pdGUgbGluZWFyO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVooMCk7XG59XG4ubG9hZGVyOmJlZm9yZSB7XG4gIHdpZHRoOiA1MCU7XG4gIGhlaWdodDogNTAlO1xuICBiYWNrZ3JvdW5kOiAkYnJhbmQtcHJpbWFyeTtcbiAgYm9yZGVyLXJhZGl1czogMTAwJSAwIDAgMDtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB0b3A6IDA7XG4gIGxlZnQ6IDA7XG4gIGNvbnRlbnQ6ICcnO1xufVxuLmxvYWRlcjphZnRlciB7XG4gIGJhY2tncm91bmQ6ICNmZmY7XG4gIHdpZHRoOiA3NSU7XG4gIGhlaWdodDogNzUlO1xuICBib3JkZXItcmFkaXVzOiA1MCU7XG4gIGNvbnRlbnQ6ICcnO1xuICBtYXJnaW46IGF1dG87XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgdG9wOiAwO1xuICBsZWZ0OiAwO1xuICBib3R0b206IDA7XG4gIHJpZ2h0OiAwO1xufVxuXG5Aa2V5ZnJhbWVzIGxvYWRlclNwaW5uZXIge1xuICAwJSB7XG4gICAgLXdlYmtpdC10cmFuc2Zvcm06IHJvdGF0ZSgwZGVnKTtcbiAgICB0cmFuc2Zvcm06IHJvdGF0ZSgwZGVnKTtcbiAgfVxuICAxMDAlIHtcbiAgICAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG4gICAgdHJhbnNmb3JtOiByb3RhdGUoMzYwZGVnKTtcbiAgfVxufSIsIkBpbXBvcnQgJy4uLy4uLy4uL3N0eWxlcy9hbmltYXRpb25zLnNjc3MnO1xuXG54b3MtdGFibGUge1xuXG4gIGRpc3BsYXk6IGJsb2NrO1xuXG4gIHRyLm5nLW1vdmUsXG4gIHRyLm5nLWVudGVyLFxuICB0ci5uZy1sZWF2ZSB7XG4gICAgdHJhbnNpdGlvbjphbGwgbGluZWFyIDAuNXM7XG4gIH1cblxuICB0ci5uZy1sZWF2ZS5uZy1sZWF2ZS1hY3RpdmUsXG4gIHRyLm5nLW1vdmUsXG4gIHRyLm5nLWVudGVyIHtcbiAgICBvcGFjaXR5OjA7XG4gICAgYW5pbWF0aW9uOiAwLjVzIHNsaWRlT3V0UmlnaHQgZWFzZS1pbi1vdXQ7XG4gIH1cblxuICB0ci5uZy1sZWF2ZSxcbiAgdHIubmctbW92ZS5uZy1tb3ZlLWFjdGl2ZSxcbiAgdHIubmctZW50ZXIubmctZW50ZXItYWN0aXZlIHtcbiAgICBvcGFjaXR5OjE7XG4gICAgYW5pbWF0aW9uOiAwLjVzIHNsaWRlSW5SaWdodCBlYXNlLWluLW91dDtcbiAgfVxuXG4gIHRkIGRsIHtcbiAgICBtYXJnaW4tYm90dG9tOiAwO1xuXG4gICAgZHQge1xuICAgICAgd2lkdGg6IGF1dG8gIWltcG9ydGFudDtcbiAgICAgIG1hcmdpbi1yaWdodDogMTBweDtcbiAgICB9XG4gICAgXG4gICAgZHQ6YWZ0ZXIge1xuICAgICAgLypkaXNwbGF5OiBibG9jazsqL1xuICAgICAgY29udGVudDogJzonO1xuICAgIH1cblxuICAgIGRkIHtcbiAgICAgIG1hcmdpbi1sZWZ0OiAwICFpbXBvcnRhbnQ7XG4gICAgfVxuICB9XG59IiwiQGltcG9ydCAnLi4vLi4vLi4vc3R5bGVzL2FuaW1hdGlvbnMuc2Nzcyc7XG5cbnhvcy1hbGVydCB7XG4gIG1hcmdpbi10b3A6ICRmb3JtLWdyb3VwLW1hcmdpbi1ib3R0b207XG4gIGRpc3BsYXk6IGJsb2NrO1xuXG4gIC8qIHdoZW4gaGlkaW5nICovXG4gIC5uZy1oaWRlLWFkZCAgICAgICAgIHsgYW5pbWF0aW9uOjAuNXMgZmFkZU91dERvd24gZWFzZS1pbi1vdXQ7IH1cblxuICAvKiB3aGVuIHNob3dpbmcgKi9cbiAgLm5nLWhpZGUtcmVtb3ZlICAgICAgeyBhbmltYXRpb246MC41cyBmYWRlSW5VcCBlYXNlLWluLW91dDsgfVxufSIsIkBpbXBvcnQgJy4uLy4uLy4uL3N0eWxlcy9hbmltYXRpb25zLnNjc3MnO1xuQGltcG9ydCAnLi4vLi4vLi4vLi4vLi4vLi4vc3R5bGUvc2Fzcy9ib290c3RyYXAvYm9vdHN0cmFwL192YXJpYWJsZXMuc2Nzcyc7XG5cbmlucHV0ICsgeG9zLXZhbGlkYXRpb24ge1xuICBtYXJnaW4tdG9wOiAkZm9ybS1ncm91cC1tYXJnaW4tYm90dG9tO1xuICBkaXNwbGF5OiBibG9jaztcbn0iLCJ4b3MtZmllbGQge1xuICBkaXNwbGF5OiBibG9jaztcbn0iLCJAaW1wb3J0ICcuLi8uLi8uLi9zdHlsZXMvYW5pbWF0aW9ucy5zY3NzJztcbkBpbXBvcnQgJy4uLy4uLy4uLy4uLy4uLy4uL3N0eWxlL3Nhc3MvYm9vdHN0cmFwL2Jvb3RzdHJhcC9fdmFyaWFibGVzLnNjc3MnO1xuXG54b3MtZm9ybSB7XG4gIGJ1dHRvbiB7XG4gICAgbWFyZ2luLWJvdHRvbTogJGZvcm0tZ3JvdXAtbWFyZ2luLWJvdHRvbTtcbiAgfVxufSIsInhvcy1zbWFydC10YWJsZXtcbiAgXG59Il0sIm1hcHBpbmdzIjoiQUNBQSxVQUFVLENBQUMsQUFBQSxZQUFZO0VBQ3JCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSx1QkFBVztJQUN0QixVQUFVLEVBQUUsT0FBUTtFQUd0QixBQUFBLEVBQUU7SUFDQSxTQUFTLEVBQUUsb0JBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLGFBQWE7RUFDdEIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLG9CQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLFVBQVUsRUFBRSxNQUFPO0lBQ25CLFNBQVMsRUFBRSx1QkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsUUFBUTtFQUNqQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSxJQUFLOztBQUlwQixVQUFVLENBQUMsQUFBQSxXQUFXO0VBQ3BCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0VBR2IsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7O0FFekMxQixBQUFBLE9BQU8sQ0FBQztFQUNOLFNBQVMsRUFBRSxJQUFLO0VBQ2hCLE1BQU0sRUFBRSxNQUFPO0VBQ2YsV0FBVyxFQUFFLE9BQVE7RUFDckIsS0FBSyxFQUFFLElBQUs7RUFDWixNQUFNLEVBQUUsSUFBSztFQUNiLGFBQWEsRUFBRSxHQUFJO0VBQ25CLFVBQVUsRUFBRSxPQUFRO0VBQ3BCLFVBQVUsRUFBRSxtRUFBb0I7RUFDaEMsVUFBVSxFQUFFLHNFQUF1QjtFQUNuQyxVQUFVLEVBQUUsaUVBQWtCO0VBQzlCLFVBQVUsRUFBRSxrRUFBbUI7RUFDL0IsVUFBVSxFQUFFLGtFQUFlO0VBQzNCLFFBQVEsRUFBRSxRQUFTO0VBQ25CLFNBQVMsRUFBRSxrQ0FBbUM7RUFDOUMsU0FBUyxFQUFFLGFBQVUsR0FDdEI7O0FBQ0QsQUFBTyxPQUFBLEFBQUEsT0FBTyxDQUFDO0VBQ2IsS0FBSyxFQUFFLEdBQUk7RUFDWCxNQUFNLEVBQUUsR0FBSTtFQUNaLFVBQVUsRURIWSxPQUFNO0VDSTVCLGFBQWEsRUFBRSxVQUFXO0VBQzFCLFFBQVEsRUFBRSxRQUFTO0VBQ25CLEdBQUcsRUFBRSxDQUFFO0VBQ1AsSUFBSSxFQUFFLENBQUU7RUFDUixPQUFPLEVBQUUsRUFBRyxHQUNiOztBQUNELEFBQU8sT0FBQSxBQUFBLE1BQU0sQ0FBQztFQUNaLFVBQVUsRUFBRSxJQUFLO0VBQ2pCLEtBQUssRUFBRSxHQUFJO0VBQ1gsTUFBTSxFQUFFLEdBQUk7RUFDWixhQUFhLEVBQUUsR0FBSTtFQUNuQixPQUFPLEVBQUUsRUFBRztFQUNaLE1BQU0sRUFBRSxJQUFLO0VBQ2IsUUFBUSxFQUFFLFFBQVM7RUFDbkIsR0FBRyxFQUFFLENBQUU7RUFDUCxJQUFJLEVBQUUsQ0FBRTtFQUNSLE1BQU0sRUFBRSxDQUFFO0VBQ1YsS0FBSyxFQUFFLENBQUUsR0FDVjs7QUFFRCxVQUFVLENBQUMsQUFBQSxhQUFhO0VBQ3RCLEFBQUEsRUFBRTtJQUNBLGlCQUFpQixFQUFFLFlBQU07SUFDekIsU0FBUyxFQUFFLFlBQU07RUFFbkIsQUFBQSxJQUFJO0lBQ0YsaUJBQWlCLEVBQUUsY0FBTTtJQUN6QixTQUFTLEVBQUUsY0FBTTs7QUZoRHJCLFVBQVUsQ0FBQyxBQUFBLFlBQVk7RUFDckIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLHVCQUFXO0lBQ3RCLFVBQVUsRUFBRSxPQUFRO0VBR3RCLEFBQUEsRUFBRTtJQUNBLFNBQVMsRUFBRSxvQkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsYUFBYTtFQUN0QixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsb0JBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsVUFBVSxFQUFFLE1BQU87SUFDbkIsU0FBUyxFQUFFLHVCQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxRQUFRO0VBQ2pCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLElBQUs7O0FBSXBCLFVBQVUsQ0FBQyxBQUFBLFdBQVc7RUFDcEIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7RUFHYixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVzs7QUd2QzFCLEFBQUEsU0FBUyxDQUFDO0VBRVIsT0FBTyxFQUFFLEtBQU0sR0F1Q2hCO0VBekNELEFBSUksU0FKSyxDQUlQLEVBQUUsQUFBQSxRQUFRO0VBSlosQUFLSSxTQUxLLENBS1AsRUFBRSxBQUFBLFNBQVM7RUFMYixBQU1JLFNBTkssQ0FNUCxFQUFFLEFBQUEsU0FBUyxDQUFDO0lBQ1YsVUFBVSxFQUFDLGVBQWdCLEdBQzVCO0VBUkgsQUFVYSxTQVZKLENBVVAsRUFBRSxBQUFBLFNBQVMsQUFBQSxnQkFBZ0I7RUFWN0IsQUFXSSxTQVhLLENBV1AsRUFBRSxBQUFBLFFBQVE7RUFYWixBQVlJLFNBWkssQ0FZUCxFQUFFLEFBQUEsU0FBUyxDQUFDO0lBQ1YsT0FBTyxFQUFDLENBQUU7SUFDVixTQUFTLEVBQUUsOEJBQStCLEdBQzNDO0VBZkgsQUFpQkksU0FqQkssQ0FpQlAsRUFBRSxBQUFBLFNBQVM7RUFqQmIsQUFrQlksU0FsQkgsQ0FrQlAsRUFBRSxBQUFBLFFBQVEsQUFBQSxlQUFlO0VBbEIzQixBQW1CYSxTQW5CSixDQW1CUCxFQUFFLEFBQUEsU0FBUyxBQUFBLGdCQUFnQixDQUFDO0lBQzFCLE9BQU8sRUFBQyxDQUFFO0lBQ1YsU0FBUyxFQUFFLDZCQUE4QixHQUMxQztFQXRCSCxBQXdCSyxTQXhCSSxDQXdCUCxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ0osYUFBYSxFQUFFLENBQUUsR0FlbEI7SUF4Q0gsQUEyQkksU0EzQkssQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FHSCxFQUFFLENBQUM7TUFDRCxLQUFLLEVBQUUsZUFBZ0I7TUFDdkIsWUFBWSxFQUFFLElBQUssR0FDcEI7SUE5QkwsQUFnQ00sU0FoQ0csQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FRSCxFQUFFLEFBQUEsTUFBTSxDQUFDO01BQ1AsbUJBQW1CO01BQ25CLE9BQU8sRUFBRSxHQUFJLEdBQ2Q7SUFuQ0wsQUFxQ0ksU0FyQ0ssQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FhSCxFQUFFLENBQUM7TUFDRCxXQUFXLEVBQUUsWUFBYSxHQUMzQjs7QUh6Q0wsVUFBVSxDQUFDLEFBQUEsWUFBWTtFQUNyQixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsdUJBQVc7SUFDdEIsVUFBVSxFQUFFLE9BQVE7RUFHdEIsQUFBQSxFQUFFO0lBQ0EsU0FBUyxFQUFFLG9CQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxhQUFhO0VBQ3RCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSxvQkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxVQUFVLEVBQUUsTUFBTztJQUNuQixTQUFTLEVBQUUsdUJBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLFFBQVE7RUFDakIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsSUFBSzs7QUFJcEIsVUFBVSxDQUFDLEFBQUEsV0FBVztFQUNwQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtFQUdiLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXOztBSXZDMUIsQUFBQSxTQUFTLENBQUM7RUFDUixVQUFVLEVIeU5xQixJQUFJO0VHeE5uQyxPQUFPLEVBQUUsS0FBTTtFQUVmLGlCQUFpQjtFQUdqQixrQkFBa0IsRUFFbkI7RUFURCxBQUtFLFNBTE8sQ0FLUCxZQUFZLENBQVM7SUFBRSxTQUFTLEVBQUMsNEJBQTZCLEdBQUk7RUFMcEUsQUFRRSxTQVJPLENBUVAsZUFBZSxDQUFNO0lBQUUsU0FBUyxFQUFDLHlCQUEwQixHQUFJOztBSlZqRSxVQUFVLENBQUMsQUFBQSxZQUFZO0VBQ3JCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSx1QkFBVztJQUN0QixVQUFVLEVBQUUsT0FBUTtFQUd0QixBQUFBLEVBQUU7SUFDQSxTQUFTLEVBQUUsb0JBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLGFBQWE7RUFDdEIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLG9CQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLFVBQVUsRUFBRSxNQUFPO0lBQ25CLFNBQVMsRUFBRSx1QkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsUUFBUTtFQUNqQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSxJQUFLOztBQUlwQixVQUFVLENBQUMsQUFBQSxXQUFXO0VBQ3BCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0VBR2IsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7O0FLdEMxQixBQUFRLEtBQUgsR0FBRyxjQUFjLENBQUM7RUFDckIsVUFBVSxFSndOcUIsSUFBSTtFSXZObkMsT0FBTyxFQUFFLEtBQU0sR0FDaEI7O0FDTkQsQUFBQSxTQUFTLENBQUM7RUFDUixPQUFPLEVBQUUsS0FBTSxHQUNoQjs7QU5GRCxVQUFVLENBQUMsQUFBQSxZQUFZO0VBQ3JCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSx1QkFBVztJQUN0QixVQUFVLEVBQUUsT0FBUTtFQUd0QixBQUFBLEVBQUU7SUFDQSxTQUFTLEVBQUUsb0JBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLGFBQWE7RUFDdEIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLG9CQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLFVBQVUsRUFBRSxNQUFPO0lBQ25CLFNBQVMsRUFBRSx1QkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsUUFBUTtFQUNqQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSxJQUFLOztBQUlwQixVQUFVLENBQUMsQUFBQSxXQUFXO0VBQ3BCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0VBR2IsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7O0FPdEMxQixBQUNFLFFBRE0sQ0FDTixNQUFNLENBQUM7RUFDTCxhQUFhLEVOdU5nQixJQUFJLEdNdE5sQzs7Q1JNSCxBQUFBLEFBQVUsU0FBVCxBQUFBLElBQVksQUFBQSxBQUFTLFFBQVIsQUFBQSxJQUFXLEFBQUEsQUFBYyxhQUFiLEFBQUEsSUFBZ0IsQUFBQSxBQUFXLFVBQVYsQUFBQSxHQUFhLEFBQUEsU0FBUyxFQUFFLEFBQUEsV0FBVyxDQUFDO0VBQzdFLE9BQU8sRUFBRSxlQUFnQixHQUMxQjs7QUFFRCxBQUFPLElBQUgsR0FBRyxJQUFJLENBQUM7RUFDViwwQkFBMEI7RUFDMUIsVUFBVSxFRTBNcUIsSUFBSSxHRnpNcEMiLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 */
diff --git a/xos/core/xoslib/dashboards/xosTenant.html b/xos/core/xoslib/dashboards/xosTenant.html
index 8881bb8..814f3de 100644
--- a/xos/core/xoslib/dashboards/xosTenant.html
+++ b/xos/core/xoslib/dashboards/xosTenant.html
@@ -1,122 +1,17 @@
-<script src="{{ STATIC_URL }}/js/vendor/underscore-min.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.syphon.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.wreqr.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.babysitter.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.marionette.js"></script>
+<!-- browserSync -->
 
-<link rel="stylesheet" type="text/css" href="{% static 'css/xosTenantDashboard.css' %}" media="all" >
-<link rel="stylesheet" type="text/css" href="{% static 'css/xosAdminSite.css' %}" media="all" >
+<!-- endcss -->
+<!-- inject:css -->
+<link rel="stylesheet" href="/static/css/xosTenant.css">
+<!-- endinject -->
 
-<script src="{{ STATIC_URL }}/js/xoslib/xos-util.js"></script>
-<script src="{{ STATIC_URL }}/js/xoslib/xos-defaults.js"></script>
-<script src="{{ STATIC_URL }}/js/xoslib/xos-validators.js"></script>
-<script src="{{ STATIC_URL }}/js/xoslib/xos-backbone.js"></script>
-<script src="{{ STATIC_URL }}/js/xoslib/xosHelper.js"></script>
-<script src="{{ STATIC_URL }}/js/picker.js"></script>
-<script src="{{ STATIC_URL }}/js/xosTenant.js"></script>
 
-<script type="text/template" id="xos-tenant-buttons-template">
-  <div class="box save-box">
-    <button class="btn btn-high btn-success btn-tenant-create">Create New Slice</button>
-    <button class="btn btn-high btn-danger btn-tenant-delete">Delete Slice</button>
-    <button class="btn btn-high btn-primary btn-tenant-add-user">Edit Users</button>
-    <button class="btn btn-high btn-primary btn-tenant-download-ssh">SSH Commands</button>
-    <button class="btn btn-high btn-success btn-tenant-save">Save</button>
-  </div>
-</script>
-
-<script type="text/template" id="xos-tenant-buttons-noslice-template">
-  <div class="box save-box">
-    <button class="btn btn-high btn-tenant-create">Create New Slice</button>
-  </div>
-</script>
-
-<script type="text/template" id="xos-log-template">
-  <tr id="<%= logMessageId %>" class="xos-log xos-<%= statusclass %>">
-     <td><%= what %><br>
-         <%= status %> <%= statusText %>
-     </td>
-  </tr>
-</script>
-
-<script type="text/template" id="tenant-sanity-check">
-    Tenant view sanity check failed:
-       <ul>
-       <% for (index in errors) { %>
-           <li><%= errors[index] %></li>
-       <% } %>
-       </ul>
-       Steps to correct issues in the tenant view:
-       <ol>
-       <li>Make sure that the tenant view is linked to at least one deployment. You
-           may find the list of dashboard views at <a href="/admin/core/dashboardview/">here</a>.
-           Deployments currently attached to the tenant view are: <%= blessed_deployment_names.join(",") %>
-           </li>
-       <li>Make sure that at least one Image and one Flavor is attached to a tenant view deployment.</li>
-       <li>Make sure at least one Site is attached to a tenant view deployment.</li>
-       <li>Make sure at least one of the Sites has one or more nodes attached to it.</li>
-       </ol>
-</script>
-
-<script type="text/template" id="tenant-edit-users">
-    <%= xosPickerTemplate({pickedItems: model.usersBuffer,
-                          unpickedItems: array_subtract(xos.tenant().current_user_site_users, model.usersBuffer),
-                          id: "users",
-                          fieldName: "users",
-                          detailView: detailView,
-                          lookupFunc: function(x) { return array_pair_lookup(x,
-                                                     $.merge($.merge([], xos.tenant().current_user_site_user_names), model.user_namesOrig),
-                                                     $.merge($.merge([], xos.tenant().current_user_site_users), model.usersOrig)); },
-                          } ) %>
-</script>
-
-<div id="xos-confirm-dialog" title="Confirmation Required">
-  Are you sure about this?
+<div ng-app="xos.tenant" id="xosTenant" class="container-fluid">
+   <div ui-view></div>
 </div>
 
-<div id="tenant-addslice-dialog" title="Create New Slice">
-<div id="tenant-addslice-interior"></div>
-</div>
 
-<div id="tenant-edit-users-dialog" title="Edit Users">
-<div id="tenant-edit-users-interior"></div>
-</div>
-
-<div id="tenant-ssh-commands-dialog" title="SSH Commands">
-<div id="tenant-ssh-commands-interior"></div>
-</div>
-
-<div id="xos-error-dialog" title="Error Message">
-</div>
-
-<div id="xos-tenant-view-panel"> <!-- contentPanel"> -->
-<div id="contentTitle">
-</div>
-<div id="contentButtonPanel">
-
-<div id="rightButtonPanel"></div>
-
-<div class="box" id="logPanel">
-<table id="logTable">
-<tbody>
-</tbody>
-</table> <!-- end logTable -->
-</div> <!-- end logPanel -->
-</div> <!-- end contentButtonPanel -->
-
-<div id="contentInner">
-
-<div id="tenantSliceSelector">
-</div>
-<div id="tenantSummary">
-</div>
-<div id="tenantSiteList">
-</div>
-<div id="tenantButtons">
-</div>
-
-</div> <!-- end contentInner -->
-</div> <!-- end contentPanel -->
-
-{% include 'xosAdmin.html' %}
+<!-- endjs -->
+<!-- inject:js -->
+<script src="/static/js/xosTenant.js"></script>
+<!-- endinject -->
diff --git a/xos/core/xoslib/methods/ceilometerview.py b/xos/core/xoslib/methods/ceilometerview._unused
similarity index 100%
rename from xos/core/xoslib/methods/ceilometerview.py
rename to xos/core/xoslib/methods/ceilometerview._unused
diff --git a/xos/core/xoslib/methods/cordsubscriber.py b/xos/core/xoslib/methods/cordsubscriber._unused
similarity index 87%
rename from xos/core/xoslib/methods/cordsubscriber.py
rename to xos/core/xoslib/methods/cordsubscriber._unused
index b69b09d..8fc88e0 100644
--- a/xos/core/xoslib/methods/cordsubscriber.py
+++ b/xos/core/xoslib/methods/cordsubscriber._unused
@@ -9,7 +9,7 @@
 from core.models import *
 from django.forms import widgets
 from django.conf.urls import patterns, url
-from services.cord.models import VOLTTenant, VBNGTenant, CordSubscriberRoot
+from services.volt.models import VOLTTenant, CordSubscriberRoot
 from core.xoslib.objects.cordsubscriber import CordSubscriber
 from plus import PlusSerializerMixin, XOSViewSet
 from django.shortcuts import get_object_or_404
@@ -208,7 +208,7 @@
         patterns.append( url("^rs/subidlookup/(?P<ssid>[0-9\-]+)/$", self.as_view({"get": "ssiddetail"}), name="ssiddetail") )
         patterns.append( url("^rs/subidlookup/$", self.as_view({"get": "ssidlist"}), name="ssidlist") )
 
-        patterns.append( url("^rs/vbng_mapping/$", self.as_view({"get": "get_vbng_mapping"}), name="vbng_mapping") )
+        #patterns.append( url("^rs/vbng_mapping/$", self.as_view({"get": "get_vbng_mapping"}), name="vbng_mapping") )
 
         return patterns
 
@@ -367,47 +367,14 @@
 
         return Response( ssidmap[0] )
 
-    def get_vbng_mapping(self, request):
-        object_list = VBNGTenant.get_tenant_objects().all()
+    #def get_vbng_mapping(self, request):
+    #    object_list = VBNGTenant.get_tenant_objects().all()
+    #
+    #    mappings = []
+    #    for vbng in object_list:
+    #        if vbng.mapped_ip and vbng.routeable_subnet:
+    #            mappings.append( {"private_ip": vbng.mapped_ip, "routeable_subnet": vbng.routeable_subnet, "mac": vbng.mapped_mac, "hostname": vbng.mapped_hostname} )
+    #
+    #    return Response( {"vbng_mapping": mappings} )
 
-        mappings = []
-        for vbng in object_list:
-            if vbng.mapped_ip and vbng.routeable_subnet:
-                mappings.append( {"private_ip": vbng.mapped_ip, "routeable_subnet": vbng.routeable_subnet, "mac": vbng.mapped_mac, "hostname": vbng.mapped_hostname} )
 
-        return Response( {"vbng_mapping": mappings} )
-
-class CordDebugIdSerializer(serializers.ModelSerializer, PlusSerializerMixin):
-    # Swagger is failing because CordDebugViewSet has neither a model nor
-    # a serializer_class. Stuck this in here as a placeholder for now.
-    id = ReadOnlyField()
-    class Meta:
-        model = CordSubscriber
-
-class CordDebugViewSet(XOSViewSet):
-    base_name = "cord_debug"
-    method_name = "rs/cord_debug"
-    method_kind = "viewset"
-    serializer_class = CordDebugIdSerializer
-
-    @classmethod
-    def get_urlpatterns(self):
-        patterns = []
-        patterns.append( url("^rs/cord_debug/vbng_dump/$", self.as_view({"get": "get_vbng_dump"}), name="vbng_dump"))
-        return patterns
-
-    # contact vBNG service and dump current list of mappings
-    def get_vbng_dump(self, request, pk=None):
-        result=subprocess.check_output(["curl", "http://10.0.3.136:8181/onos/virtualbng/privateip/map"])
-        if request.GET.get("theformat",None)=="text":
-            from django.http import HttpResponse
-            result = json.loads(result)["map"]
-
-            lines = []
-            for row in result:
-                for k in row.keys():
-                     lines.append( "%s %s" % (k, row[k]) )
-
-            return HttpResponse("\n".join(lines), content_type="text/plain")
-        else:
-            return Response( {"vbng_dump": json.loads(result)["map"] } )
diff --git a/xos/core/xoslib/methods/monitoringchannel.py b/xos/core/xoslib/methods/monitoringchannel._unused
similarity index 100%
rename from xos/core/xoslib/methods/monitoringchannel.py
rename to xos/core/xoslib/methods/monitoringchannel._unused
diff --git a/xos/core/xoslib/methods/truckroll.py b/xos/core/xoslib/methods/truckroll.py
deleted file mode 100644
index 917a676..0000000
--- a/xos/core/xoslib/methods/truckroll.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from rest_framework.decorators import api_view
-from rest_framework.response import Response
-from rest_framework.reverse import reverse
-from rest_framework import serializers
-from rest_framework import generics
-from rest_framework import status
-from core.models import *
-from django.forms import widgets
-from services.cord.models import CordSubscriberRoot
-from services.vtr.models import VTRTenant, VTRService
-from plus import PlusSerializerMixin
-from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
-
-if hasattr(serializers, "ReadOnlyField"):
-    # rest_framework 3.x
-    ReadOnlyField = serializers.ReadOnlyField
-else:
-    # rest_framework 2.x
-    ReadOnlyField = serializers.Field
-
-def get_default_vtr_service():
-    vtr_services = VTRService.get_service_objects().all()
-    if vtr_services:
-        return vtr_services[0].id
-    return None
-
-class VTRTenantIdSerializer(serializers.ModelSerializer, PlusSerializerMixin):
-        id = ReadOnlyField()
-        target_id = serializers.IntegerField()
-        test = serializers.CharField()
-        scope = serializers.CharField()
-        argument = serializers.CharField(required=False)
-        provider_service = serializers.PrimaryKeyRelatedField(queryset=VTRService.get_service_objects().all(), default=get_default_vtr_service)
-        result = serializers.CharField(required=False)
-        result_code = serializers.CharField(required=False)
-        backend_status = ReadOnlyField()
-
-        humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
-        is_synced = serializers.SerializerMethodField("isSynced")
-
-        class Meta:
-            model = VTRTenant
-            fields = ('humanReadableName', 'id', 'provider_service', 'target_id', 'scope', 'test', 'argument', 'result', 'result_code', 'is_synced', 'backend_status' )
-
-        def getHumanReadableName(self, obj):
-            return obj.__unicode__()
-
-        def isSynced(self, obj):
-            return (obj.enacted is not None) and (obj.enacted >= obj.updated)
-
-class VTRTenantList(XOSListCreateAPIView):
-    serializer_class = VTRTenantIdSerializer
-
-    method_kind = "list"
-    method_name = "truckroll"
-
-    def get_queryset(self):
-        queryset = VTRTenant.get_tenant_objects().select_related().all()
-
-        test = self.request.QUERY_PARAMS.get('test', None)
-        if test is not None:
-            ids = [x.id for x in queryset if x.get_attribute("test", None)==test]
-            queryset = queryset.filter(id__in=ids)
-
-        return queryset
-
-    def post(self, request, format=None):
-        data = request.DATA
-
-        existing_obj = None
-#        for obj in VTRTenant.get_tenant_objects().all():
-#            if (obj.tesst == data.get("test", None)) and (obj.target == data.get("target", None))):
-#               existing_obj = obj
-
-        if existing_obj:
-            serializer = VTRTenantIdSerializer(existing_obj)
-            headers = self.get_success_headers(serializer.data)
-            return Response( serializer.data, status=status.HTTP_200_OK )
-
-        return super(VTRTenantList, self).post(request, format)
-
-class VTRTenantDetail(XOSRetrieveUpdateDestroyAPIView):
-    serializer_class = VTRTenantIdSerializer
-    queryset = VTRTenant.get_tenant_objects().select_related().all()
-
-    method_kind = "detail"
-    method_name = "truckroll"
-
-
-
-
-
diff --git a/xos/core/xoslib/methods/volttenant.py b/xos/core/xoslib/methods/volttenant._unused
similarity index 97%
rename from xos/core/xoslib/methods/volttenant.py
rename to xos/core/xoslib/methods/volttenant._unused
index 25559a0..03a2a97 100644
--- a/xos/core/xoslib/methods/volttenant.py
+++ b/xos/core/xoslib/methods/volttenant._unused
@@ -6,7 +6,7 @@
 from rest_framework import status
 from core.models import *
 from django.forms import widgets
-from services.cord.models import VOLTTenant, VOLTService, CordSubscriberRoot
+from services.volt.models import VOLTTenant, VOLTService, CordSubscriberRoot
 from plus import PlusSerializerMixin
 from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
 
diff --git a/xos/core/xoslib/methods/vtn.py b/xos/core/xoslib/methods/vtn._unused
similarity index 100%
rename from xos/core/xoslib/methods/vtn.py
rename to xos/core/xoslib/methods/vtn._unused
diff --git a/xos/core/xoslib/objects/cordsubscriber.py b/xos/core/xoslib/objects/cordsubscriber.py
index 681b769..d97bd5a 100644
--- a/xos/core/xoslib/objects/cordsubscriber.py
+++ b/xos/core/xoslib/objects/cordsubscriber.py
@@ -1,23 +1,9 @@
 from core.models import Slice, SlicePrivilege, SliceRole, Instance, Site, Node, User
-from services.cord.models import VOLTTenant, CordSubscriberRoot
+from services.volt.models import VOLTTenant, CordSubscriberRoot
 from plus import PlusObjectMixin
 from operator import itemgetter, attrgetter
 from rest_framework.exceptions import APIException
 
-"""
-import os
-import sys
-sys.path.append("/opt/xos")
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
-import django
-from core.models import *
-from services.hpc.models import *
-from services.cord.models import *
-django.setup()
-from core.xoslib.objects.cordsubscriber import CordSubscriber
-c=CordSubscriber.get_tenant_objects().select_related().all()[0]
-"""
-
 class CordSubscriber(CordSubscriberRoot):
     class Meta:
         proxy = True
diff --git a/xos/core/xoslib/static/css/xosTenant.css b/xos/core/xoslib/static/css/xosTenant.css
new file mode 100644
index 0000000..1675325
--- /dev/null
+++ b/xos/core/xoslib/static/css/xosTenant.css
@@ -0,0 +1 @@
+#xosTenant a{margin-bottom:15px}
\ No newline at end of file
diff --git a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
index 90049b8..f511337 100644
--- a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
+++ b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
@@ -1 +1,2 @@
-"use strict";!function(){angular.module("xos.uiComponents",["chart.js","RecursionHelper"])}();var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};!function(){angular.module("xos.uiComponents").directive("xosSmartTable",function(){return{restrict:"E",scope:{config:"="},template:'\n        <div class="row" ng-show="vm.data.length > 0">\n          <div class="col-xs-12 text-right">\n            <a href="" class="btn btn-success" ng-click="vm.createItem()">\n              Add\n            </a>\n          </div>\n        </div>\n        <div class="row">\n          <div class="col-xs-12 table-responsive">\n            <xos-table config="vm.tableConfig" data="vm.data"></xos-table>\n          </div>\n        </div>\n        <div class="panel panel-default" ng-show="vm.detailedItem">\n          <div class="panel-heading">\n            <div class="row">\n              <div class="col-xs-11">\n                <h3 class="panel-title" ng-show="vm.detailedItem.id">Update {{vm.config.resource}} {{vm.detailedItem.id}}</h3>\n                <h3 class="panel-title" ng-show="!vm.detailedItem.id">Create {{vm.config.resource}} item</h3>\n              </div>\n              <div class="col-xs-1">\n                <a href="" ng-click="vm.cleanForm()">\n                  <i class="glyphicon glyphicon-remove pull-right"></i>\n                </a>\n              </div>\n            </div>\n          </div>\n          <div class="panel-body">\n            <xos-form config="vm.formConfig" ng-model="vm.detailedItem"></xos-form>\n          </div>\n        </div>\n        <xos-alert config="{type: \'success\', closeBtn: true}" show="vm.responseMsg">{{vm.responseMsg}}</xos-alert>\n        <xos-alert config="{type: \'danger\', closeBtn: true}" show="vm.responseErr">{{vm.responseErr}}</xos-alert>\n      ',bindToController:!0,controllerAs:"vm",controller:["$injector","LabelFormatter","_","XosFormHelpers",function(e,n,o,t){var i=this;this.responseMsg=!1,this.responseErr=!1,this.tableConfig={columns:[],actions:[{label:"delete",icon:"remove",cb:function(e){i.Resource["delete"]({id:e.id}).$promise.then(function(){o.remove(i.data,function(n){return n.id===e.id}),i.responseMsg=i.config.resource+" with id "+e.id+" successfully deleted"})["catch"](function(n){i.responseErr=n.data.detail||"Error while deleting "+i.config.resource+" with id "+e.id})},color:"red"},{label:"details",icon:"search",cb:function(e){i.detailedItem=e}}],classes:"table table-striped table-bordered table-responsive",filter:"field",order:!0,pagination:{pageSize:10}},this.formConfig={exclude:this.config.hiddenFields,fields:{},formName:this.config.resource+"Form",actions:[{label:"Save",icon:"ok",cb:function(e){var n=void 0,o=!0;e.id?(n=e.$update(),o=!1):n=e.$save(),n.then(function(n){o&&i.data.push(angular.copy(n)),delete i.detailedItem,i.responseMsg=i.config.resource+" with id "+e.id+" successfully saved"})["catch"](function(n){i.responseErr=n.data.detail||"Error while saving "+i.config.resource+" with id "+e.id})},"class":"success"}]},this.cleanForm=function(){delete i.detailedItem},this.createItem=function(){i.detailedItem=new i.Resource},this.Resource=e.get(this.config.resource);var r=function(){i.Resource.query().$promise.then(function(e){if(e[0]){var r=e[0],s=Object.keys(r);o.remove(s,function(e){return"id"===e||"validators"===e}),angular.isArray(i.config.hiddenFields)&&(s=o.difference(s,i.config.hiddenFields));var a=s.map(function(e){return n.format(e)});s.forEach(function(e,n){var o={label:a[n],prop:e};"string"!=typeof r[e]&&"undefined"!=typeof r[e]&&(o.type=_typeof(r[e])),i.tableConfig.columns.push(o)}),s.forEach(function(e,o){i.formConfig.fields[e]={label:n.format(a[o]).replace(":",""),type:t._getFieldFormat(r[e])}}),i.data=e}})};r()}]}})}(),function(){angular.module("xos.uiComponents").directive("xosValidation",function(){return{restrict:"E",scope:{field:"=",form:"="},template:'\n        <div ng-cloak>\n          <xos-alert config="vm.config" show="vm.field.$error.required !== undefined && vm.field.$error.required !== false  && (vm.field.$touched || vm.form.$submitted)">\n            Field required\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.email !== undefined && vm.field.$error.email !== false && (vm.field.$touched || vm.form.$submitted)">\n            This is not a valid email\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.minlength !== undefined && vm.field.$error.minlength !== false && (vm.field.$touched || vm.form.$submitted)">\n            Too short\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.maxlength !== undefined && vm.field.$error.maxlength !== false && (vm.field.$touched || vm.form.$submitted)">\n            Too long\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.custom !== undefined && vm.field.$error.custom !== false && (vm.field.$touched || vm.form.$submitted)">\n            Field invalid\n          </xos-alert>\n        </div>\n      ',transclude:!0,bindToController:!0,controllerAs:"vm",controller:function(){this.config={type:"danger"}}}})}(),function(){angular.module("xos.uiComponents").directive("xosSmartPie",function(){return{restrict:"E",scope:{config:"="},template:'\n        <canvas\n          class="chart chart-pie {{vm.config.classes}}"\n          chart-data="vm.data" chart-labels="vm.labels"\n          chart-legend="{{vm.config.legend}}">\n        </canvas>\n      ',bindToController:!0,controllerAs:"vm",controller:["$injector","$interval","$scope","$timeout","_",function(e,n,o,t,i){var r=this;if(!this.config.resource&&!this.config.data)throw new Error("[xosSmartPie] Please provide a resource or an array of data in the configuration");var s=function(e){return i.groupBy(e,r.config.groupBy)},a=function(e){return i.reduce(Object.keys(e),function(n,o){return n.concat(e[o].length)},[])},l=function(e){return angular.isFunction(r.config.labelFormatter)?r.config.labelFormatter(Object.keys(e)):Object.keys(e)},c=function(e){var n=s(e);r.data=a(n),r.labels=l(n)};this.config.resource?!function(){r.Resource=e.get(r.config.resource);var o=function(){r.Resource.query().$promise.then(function(e){e[0]&&c(e)})};o(),r.config.poll&&n(function(){o()},1e3*r.config.poll)}():o.$watch(function(){return r.config.data},function(e){e&&c(r.config.data)},!0),o.$on("create",function(e,n){console.log("create: "+n.id)}),o.$on("destroy",function(e,n){console.log("destroy: "+n.id)})}]}})}(),function(){angular.module("xos.uiComponents").directive("xosTable",function(){return{restrict:"E",scope:{data:"=",config:"="},template:'\n          <div ng-show="vm.data.length > 0">\n            <div class="row" ng-if="vm.config.filter == \'fulltext\'">\n              <div class="col-xs-12">\n                <input\n                  class="form-control"\n                  placeholder="Type to search.."\n                  type="text"\n                  ng-model="vm.query"/>\n              </div>\n            </div>\n            <table ng-class="vm.classes" ng-hide="vm.data.length == 0">\n              <thead>\n                <tr>\n                  <th ng-repeat="col in vm.columns">\n                    {{col.label}}\n                    <span ng-if="vm.config.order">\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">\n                        <i class="glyphicon glyphicon-chevron-up"></i>\n                      </a>\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">\n                        <i class="glyphicon glyphicon-chevron-down"></i>\n                      </a>\n                    </span>\n                  </th>\n                  <th ng-if="vm.config.actions">Actions:</th>\n                </tr>\n              </thead>\n              <tbody ng-if="vm.config.filter == \'field\'">\n                <tr>\n                  <td ng-repeat="col in vm.columns">\n                    <input\n                      ng-if="col.type !== \'boolean\'"\n                      class="form-control"\n                      placeholder="Type to search by {{col.label}}"\n                      type="text"\n                      ng-model="vm.query[col.prop]"/>\n                    <select\n                      ng-if="col.type === \'boolean\'"\n                      class="form-control"\n                      ng-model="vm.query[col.prop]">\n                      <option value="">-</option>\n                      <option value="true">True</option>\n                      <option value="false">False</option>\n                    </select>\n                  </td>\n                  <td ng-if="vm.config.actions"></td>\n                </tr>\n              </tbody>\n              <tbody>\n                <tr ng-repeat="item in vm.data | filter:vm.query | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">\n                  <td ng-repeat="col in vm.columns" link-wrapper>\n                    <span ng-if="!col.type">{{item[col.prop]}}</span>\n                    <span ng-if="col.type === \'boolean\'">\n                      <i class="glyphicon"\n                        ng-class="{\'glyphicon-ok\': item[col.prop], \'glyphicon-remove\': !item[col.prop]}">\n                      </i>\n                    </span>\n                    <span ng-if="col.type === \'date\'">\n                      {{item[col.prop] | date:\'H:mm MMM d, yyyy\'}}\n                    </span>\n                    <span ng-if="col.type === \'array\'">\n                      {{item[col.prop] | arrayToList}}\n                    </span>\n                    <span ng-if="col.type === \'object\'">\n                      <dl class="dl-horizontal">\n                        <span ng-repeat="(k,v) in item[col.prop]">\n                          <dt>{{k}}</dt>\n                          <dd>{{v}}</dd>\n                        </span>\n                      </dl>\n                    </span>\n                    <span ng-if="col.type === \'custom\'">\n                      {{col.formatter(item)}}\n                    </span>\n                    <span ng-if="col.type === \'icon\'">\n                      <i class="glyphicon glyphicon-{{col.formatter(item)}}">\n                      </i>\n                    </span>\n                  </td>\n                  <td ng-if="vm.config.actions">\n                    <a href=""\n                      ng-repeat="action in vm.config.actions"\n                      ng-click="action.cb(item)"\n                      title="{{action.label}}">\n                      <i\n                        class="glyphicon glyphicon-{{action.icon}}"\n                        style="color: {{action.color}};"></i>\n                    </a>\n                  </td>\n                </tr>\n              </tbody>\n            </table>\n            <xos-pagination\n              ng-if="vm.config.pagination"\n              page-size="vm.config.pagination.pageSize"\n              total-elements="vm.data.length"\n              change="vm.goToPage">\n              </xos-pagination>\n          </div>\n          <div ng-show="vm.data.length == 0 || !vm.data">\n             <xos-alert config="{type: \'info\'}">\n              No data to show.\n            </xos-alert>\n          </div>\n        ',bindToController:!0,controllerAs:"vm",controller:["_",function(e){var n=this;if(!this.config)throw new Error('[xosTable] Please provide a configuration via the "config" attribute');if(!this.config.columns)throw new Error("[xosTable] Please provide a columns list in the configuration");this.config.order&&angular.isObject(this.config.order)&&(this.reverse=this.config.order.reverse||!1,this.orderBy=this.config.order.field||"id");var o=e.filter(this.config.columns,{type:"custom"});angular.isArray(o)&&o.length>0&&e.forEach(o,function(e){if(!e.formatter||!angular.isFunction(e.formatter))throw new Error("[xosTable] You have provided a custom field type, a formatter function should provided too.")});var t=e.filter(this.config.columns,{type:"icon"});angular.isArray(t)&&t.length>0&&e.forEach(t,function(e){if(!e.formatter||!angular.isFunction(e.formatter))throw new Error("[xosTable] You have provided an icon field type, a formatter function should provided too.")});var i=e.filter(this.config.columns,function(e){return angular.isDefined(e.link)});angular.isArray(i)&&i.length>0&&e.forEach(i,function(e){if(!angular.isFunction(e.link))throw new Error("[xosTable] The link property should be a function.")}),this.columns=this.config.columns,this.classes=this.config.classes||"table table-striped table-bordered",this.config.actions,this.config.pagination&&(this.currentPage=0,this.goToPage=function(e){n.currentPage=e})}]}}).filter("arrayToList",function(){return function(e){return angular.isArray(e)?e.join(", "):e}}).directive("linkWrapper",function(){return{restrict:"A",transclude:!0,template:'\n          <a ng-if="col.link" href="{{col.link(item)}}">\n            <div ng-transclude></div>\n          </a>\n          <div ng-transclude ng-if="!col.link"></div>\n        '}})}(),function(){angular.module("xos.uiComponents").directive("xosPagination",function(){return{restrict:"E",scope:{pageSize:"=",totalElements:"=",change:"="},template:'\n        <div class="row" ng-if="vm.pageList.length > 1">\n          <div class="col-xs-12 text-center">\n            <ul class="pagination">\n              <li\n                ng-click="vm.goToPage(vm.currentPage - 1)"\n                ng-class="{disabled: vm.currentPage == 0}">\n                <a href="" aria-label="Previous">\n                    <span aria-hidden="true">&laquo;</span>\n                </a>\n              </li>\n              <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">\n                <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>\n              </li>\n              <li\n                ng-click="vm.goToPage(vm.currentPage + 1)"\n                ng-class="{disabled: vm.currentPage == vm.pages - 1}">\n                <a href="" aria-label="Next">\n                    <span aria-hidden="true">&raquo;</span>\n                </a>\n              </li>\n            </ul>\n          </div>\n        </div>\n      ',bindToController:!0,controllerAs:"vm",controller:["$scope",function(e){var n=this;this.currentPage=0,this.goToPage=function(e){0>e||e===n.pages||(n.currentPage=e,n.change(e))},this.createPages=function(e){for(var n=[],o=0;e>o;o++)n.push(o);return n},e.$watch(function(){return n.totalElements},function(){n.totalElements&&(n.pages=Math.ceil(n.totalElements/n.pageSize),n.pageList=n.createPages(n.pages))})}]}}).filter("pagination",function(){return function(e,n){return e&&angular.isArray(e)?(n=parseInt(n,10),e.slice(n)):e}})}(),function(){angular.module("xos.uiComponents").directive("xosForm",function(){return{restrict:"E",scope:{config:"=",ngModel:"="},template:'\n        <ng-form name="vm.{{vm.config.formName || \'form\'}}">\n          <div class="form-group" ng-repeat="(name, field) in vm.formField">\n            <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>\n            <xos-validation field="vm[vm.config.formName || \'form\'][name]" form="vm[vm.config.formName || \'form\']"></xos-validation>\n          </div>\n          <div class="form-group" ng-if="vm.config.actions">\n            <button role="button" href=""\n              ng-repeat="action in vm.config.actions"\n              ng-click="action.cb(vm.ngModel)"\n              class="btn btn-{{action.class}}"\n              title="{{action.label}}">\n              <i class="glyphicon glyphicon-{{action.icon}}"></i>\n              {{action.label}}\n            </button>\n          </div>\n        </ng-form>\n      ',bindToController:!0,controllerAs:"vm",controller:["$scope","$log","_","XosFormHelpers",function(e,n,o,t){var i=this;if(!this.config)throw new Error('[xosForm] Please provide a configuration via the "config" attribute');if(!this.config.actions)throw new Error("[xosForm] Please provide an action list in the configuration");this.excludedField=["id","validators","created","updated","deleted","backend_status"],this.config&&this.config.exclude&&(this.excludedField=this.excludedField.concat(this.config.exclude)),this.formField=[],e.$watch(function(){return i.ngModel},function(e){if(i.formField={},e){var n=o.difference(Object.keys(e),i.excludedField),r=t.parseModelField(n);i.formField=t.buildFormStructure(r,i.config.fields,e)}})}]}})}(),function(){angular.module("xos.uiComponents").directive("xosField",["RecursionHelper",function(e){return{restrict:"E",scope:{name:"=",field:"=",ngModel:"="},template:'\n        <label ng-if="vm.field.type !== \'object\'">{{vm.field.label}}</label>\n            <input\n              ng-if="vm.field.type !== \'boolean\' && vm.field.type !== \'object\' && vm.field.type !== \'select\'"\n              type="{{vm.field.type}}"\n              name="{{vm.name}}"\n              class="form-control"\n              ng-model="vm.ngModel"\n              ng-minlength="vm.field.validators.minlength || 0"\n              ng-maxlength="vm.field.validators.maxlength || 2000"\n              ng-required="vm.field.validators.required || false" />\n              <select class="form-control" ng-if ="vm.field.type === \'select\'"\n                name = "{{vm.name}}"\n                ng-options="item.id as item.label for item in vm.field.options track by item.id"\n                ng-model="vm.ngModel"\n                ng-required="vm.field.validators.required || false">\n                </select>\n            <span class="boolean-field" ng-if="vm.field.type === \'boolean\'">\n              <button\n                class="btn btn-success"\n                ng-show="vm.ngModel"\n                ng-click="vm.ngModel = false">\n                <i class="glyphicon glyphicon-ok"></i>\n              </button>\n              <button\n                class="btn btn-danger"\n                ng-show="!vm.ngModel"\n                ng-click="vm.ngModel = true">\n                <i class="glyphicon glyphicon-remove"></i>\n              </button>\n            </span>\n            <div\n              class="panel panel-default object-field"\n              ng-if="vm.field.type == \'object\' && (!vm.isEmptyObject(vm.ngModel) || !vm.isEmptyObject(vm.field.properties))"\n              >\n              <div class="panel-heading">{{vm.field.label}}</div>\n              <div class="panel-body">\n                <div ng-if="!vm.field.properties" ng-repeat="(k, v) in vm.ngModel">\n                  <xos-field\n                    name="k"\n                    field="{label: vm.formatLabel(k), type: vm.getType(v)}"\n                    ng-model="v">\n                  </xos-field>\n                </div>\n                <div ng-if="vm.field.properties" ng-repeat="(k, v) in vm.field.properties">\n                  <xos-field\n                    name="k"\n                    field="{\n                      label: v.label || vm.formatLabel(k),\n                      type: v.type,\n                      validators: v.validators\n                    }"\n                    ng-model="vm.ngModel[k]">\n                  </xos-field>\n                </div>\n              </div>\n            </div>\n      ',bindToController:!0,controllerAs:"vm",compile:function(n){return e.compile(n)},controller:["$attrs","XosFormHelpers","LabelFormatter",function(e,n,o){if(!this.name)throw new Error("[xosField] Please provide a field name");if(!this.field)throw new Error("[xosField] Please provide a field definition");if(!this.field.type)throw new Error("[xosField] Please provide a type in the field definition");if(!e.ngModel)throw new Error("[xosField] Please provide an ng-model");this.getType=n._getFieldFormat,this.formatLabel=o.format,this.isEmptyObject=function(e){return e?0===Object.keys(e).length:!0}}]}}])}(),function(){angular.module("xos.uiComponents").directive("xosAlert",function(){return{restrict:"E",scope:{config:"=",show:"=?"},template:'\n        <div ng-cloak class="alert alert-{{vm.config.type}}" ng-hide="!vm.show">\n          <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">\n            <span aria-hidden="true">&times;</span>\n          </button>\n          <p ng-transclude></p>\n        </div>\n      ',transclude:!0,bindToController:!0,controllerAs:"vm",controller:["$timeout",function(e){var n=this;if(!this.config)throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');this.show=this.show!==!1,this.dismiss=function(){n.show=!1},this.config.autoHide&&!function(){var o=e(function(){n.dismiss(),e.cancel(o)},n.config.autoHide)}()}]}})}(),function(){function e(){var e=function(e){return e.split("_").join(" ").trim()},n=function(e){return e.split(/(?=[A-Z])/).map(function(e){return e.toLowerCase()}).join(" ")},o=function(e){return e.slice(0,1).toUpperCase()+e.slice(1)},t=function(t){return t=e(t),t=n(t),t=o(t).replace(/\s\s+/g," ")+":",t.replace("::",":")};return{_formatByUnderscore:e,_formatByUppercase:n,_capitalize:o,format:t}}angular.module("xos.uiComponents").factory("LabelFormatter",e)}();var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};!function(){angular.module("xos.uiComponents").service("XosFormHelpers",["_","LabelFormatter",function(e,n){var o=this;this._isEmail=function(e){var n=/(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;return n.test(e)},this._getFieldFormat=function(n){return angular.isArray(n)?"array":e.isDate(n)||!Number.isNaN(Date.parse(n))&&new Date(n).getTime()>6311808e5?"date":"boolean"==typeof n?"boolean":o._isEmail(n)?"email":"string"==typeof n||null===n?"text":"undefined"==typeof n?"undefined":_typeof(n)},this.buildFormStructure=function(t,i,r){return t=angular.extend(t,i),i=i||{},e.reduce(Object.keys(t),function(e,t){return e[t]={label:i[t]&&i[t].label?i[t].label+":":n.format(t),type:i[t]&&i[t].type?i[t].type:o._getFieldFormat(r[t]),validators:i[t]&&i[t].validators?i[t].validators:{},hint:i[t]&&i[t].hint?i[t].hint:""},i[t]&&i[t].options&&(e[t].options=i[t].options),i[t]&&i[t].properties&&(e[t].properties=i[t].properties),"date"===e[t].type&&(r[t]=new Date(r[t])),"number"===e[t].type&&(r[t]=parseInt(r[t],10)),e},{})},this.parseModelField=function(n){return e.reduce(n,function(e,n){return e[n]={},e},{})}}])}(),function(){function e(e,n,o){e.interceptors.push("SetCSRFToken"),n.startSymbol("{$"),n.endSymbol("$}"),o.defaults.stripTrailingSlashes=!1}e.$inject=["$httpProvider","$interpolateProvider","$resourceProvider"],angular.module("bugSnag",[]).factory("$exceptionHandler",function(){return function(e,n){window.Bugsnag?Bugsnag.notifyException(e,{diagnostics:{cause:n}}):console.error(e,n,e.stack)}}),angular.module("xos.helpers",["ngCookies","ngResource","ngAnimate","bugSnag","xos.uiComponents"]).config(e).factory("_",["$window",function(e){return e._}])}(),function(){angular.module("xos.helpers").service("vSG-Collection",["$resource",function(e){return e("/api/service/vsg/")}])}(),function(){angular.module("xos.helpers").service("vOLT-Collection",["$resource",function(e){return e("/api/tenant/cord/volt/:volt_id/",{volt_id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Login",["$resource",function(e){return e("/api/utility/login/")}]).service("Logout",["$resource",function(e){return e("/api/utility/logout/")}])}(),function(){angular.module("xos.helpers").service("Users",["$resource",function(e){return e("/api/core/users/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Truckroll",["$resource",function(e){return e("/api/tenant/truckroll/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Tenants",["$resource",function(e){return e("/api/core/tenants/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Subscribers",["$resource",function(e){return e("/api/tenant/cord/subscriber/:id/",{id:"@id"},{update:{method:"PUT"},"View-a-Subscriber-Features-Detail":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/"},"Read-Subscriber-uplink_speed":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uplink_speed/"},"Update-Subscriber-uplink_speed":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uplink_speed/"},"Read-Subscriber-downlink_speed":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/downlink_speed/"},"Update-Subscriber-downlink_speed":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/downlink_speed/"},"Read-Subscriber-cdn":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/cdn/"},"Update-Subscriber-cdn":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/cdn/"},"Read-Subscriber-uverse":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uverse/"},"Update-Subscriber-uverse":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uverse/"},"Read-Subscriber-status":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/status/"},"Update-Subscriber-status":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/status/"}})}])}(),function(){angular.module("xos.helpers").service("SlicesPlus",["$http","$q",function(e,n){this.query=function(o){var t=n.defer();return e.get("/api/utility/slicesplus/",{params:o}).then(function(e){t.resolve(e.data)})["catch"](function(e){t.reject(e.data)}),{$promise:t.promise}},this.get=function(o,t){var i=n.defer();return e.get("/api/utility/slicesplus/"+o,{params:t}).then(function(e){i.resolve(e.data)})["catch"](function(e){i.reject(e.data)}),{$promise:i.promise}}}])}(),function(){angular.module("xos.helpers").service("Slices",["$resource",function(e){return e("/api/core/slices/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Sites",["$resource",function(e){return e("/api/core/sites/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Services",["$resource",function(e){return e("/api/core/services/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("ONOS-Services-Collection",["$resource",function(e){return e("/api/service/onos/")}])}(),function(){angular.module("xos.helpers").service("ONOS-App-Collection",["$resource",function(e){return e("/api/tenant/onos/app/")}])}(),function(){angular.module("xos.helpers").service("Nodes",["$resource",function(e){return e("/api/core/nodes/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Networks",["$resource",function(e){return e("/api/core/networks/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Instances",["$resource",function(e){return e("/api/core/instances/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Flavors",["$resource",function(e){return e("/api/core/flavors/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Example-Services-Collection",["$resource",function(e){return e("/api/service/exampleservice/")}])}(),function(){angular.module("xos.helpers").service("Deployments",["$resource",function(e){return e("/api/core/deployments/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("XosUserPrefs",["$cookies",function(e){var n=this,o=e.get("xosUserPrefs")?JSON.parse(e.get("xosUserPrefs")):{};this.getAll=function(){return o=e.get("xosUserPrefs")?JSON.parse(e.get("xosUserPrefs")):{}},this.setAll=function(n){e.put("xosUserPrefs",JSON.stringify(n))},this.getSynchronizerNotificationStatus=function(){var e=arguments.length<=0||void 0===arguments[0]?!1:arguments[0];return e?n.getAll().synchronizers.notification[e]:n.getAll().synchronizers.notification},this.setSynchronizerNotificationStatus=function(){var e=arguments.length<=0||void 0===arguments[0]?!1:arguments[0],o=arguments[1];if(!e)throw new Error("[XosUserPrefs] When updating a synchronizer is mandatory to provide a name.");var t=n.getAll();t.synchronizers||(t.synchronizers={notification:{}}),t.synchronizers.notification[e]=o,n.setAll(t)}}])}(),function(){angular.module("xos.helpers").service("GraphService",["$q","Tenants","Services",function(e,n,o){var t=this;this.loadCoarseData=function(){var t=void 0,i=e.defer();return o.query().$promise.then(function(e){return t=e,n.query({kind:"coarse"}).$promise}).then(function(e){i.resolve({tenants:e,services:t})}),i.promise},this.getCoarseGraph=function(){return t.loadCoarseData().then(function(e){console.log(e)}),"ciao"}}])}(),function(){angular.module("xos.helpers").factory("Notification",function(){return window.Notification}).service("xosNotification",["$q","$log","Notification",function(e,n,o){var t=this;this.checkPermission=function(){var n=e.defer();return o.requestPermission().then(function(e){"granted"===e?n.resolve(e):n.reject(e)}),n.promise},this.sendNotification=function(e,t){var i=new o(e,t);i.onerror=function(e){n.error(e)}},this.notify=function(e,i){"Notification"in window?"granted"!==o.permission?t.checkPermission().then(function(){return t.sendNotification(e,i)}):"granted"===o.permission&&t.sendNotification(e,i):n.info("This browser does not support desktop notification")}}])}(),function(){function e(){return{request:function(e){return-1===e.url.indexOf(".html")&&(e.url+="?no_hyperlinks=1"),e}}}angular.module("xos.helpers").factory("NoHyperlinks",e)}(),angular.module("xos.helpers").config(["$provide",function(e){e.decorator("$log",["$delegate",function(e){var n=function(){return window.location.href.indexOf("debug=true")>=0},o=e.log,t=e.info,i=e.warn,r=e.error,s=e.debug,a=function(o){return function(){if(n()){var t=[].slice.call(arguments),i=new Date;t[0]="["+i.getHours()+":"+i.getMinutes()+":"+i.getSeconds()+"] "+t[0],"function"!=typeof e.reset||e.debug.logs instanceof Array||e.reset(),o.apply(null,t)}}};return e.info=a(t),e.log=a(o),e.warn=a(i),e.error=a(r),e.debug=a(s),e}])}]),function(){function e(){var e=function(e){return e.split("_").join(" ").trim()},n=function(e){return e.split(/(?=[A-Z])/).map(function(e){return e.toLowerCase()}).join(" ")},o=function(e){return e.slice(0,1).toUpperCase()+e.slice(1)},t=function(t){return t=e(t),t=n(t),t=o(t).replace(/\s\s+/g," ")+":",t.replace("::",":")};return{_formatByUnderscore:e,_formatByUppercase:n,_capitalize:o,format:t}}angular.module("xos.uiComponents").factory("LabelFormatter",e)}(),function(){function e(e){return{request:function(n){return"GET"!==n.method&&(n.headers["X-CSRFToken"]=e.get("xoscsrftoken")),n}}}e.$inject=["$cookies"],angular.module("xos.helpers").factory("SetCSRFToken",e)}();
\ No newline at end of file
+"use strict";function _toConsumableArray(e){if(Array.isArray(e)){for(var n=0,o=Array(e.length);n<e.length;n++)o[n]=e[n];return o}return Array.from(e)}!function(){angular.module("xos.uiComponents",["chart.js","RecursionHelper"])}();var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};!function(){angular.module("xos.uiComponents").directive("xosSmartTable",function(){return{restrict:"E",scope:{config:"="},template:'\n        <div class="row" ng-show="vm.data.length > 0">\n          <div class="col-xs-12 text-right">\n            <a href="" class="btn btn-success" ng-click="vm.createItem()">\n              Add\n            </a>\n          </div>\n        </div>\n        <div class="row">\n          <div class="col-xs-12 table-responsive">\n            <xos-table config="vm.tableConfig" data="vm.data"></xos-table>\n          </div>\n        </div>\n        <div class="panel panel-default" ng-show="vm.detailedItem">\n          <div class="panel-heading">\n            <div class="row">\n              <div class="col-xs-11">\n                <h3 class="panel-title" ng-show="vm.detailedItem.id">Update {{vm.config.resource}} {{vm.detailedItem.id}}</h3>\n                <h3 class="panel-title" ng-show="!vm.detailedItem.id">Create {{vm.config.resource}} item</h3>\n              </div>\n              <div class="col-xs-1">\n                <a href="" ng-click="vm.cleanForm()">\n                  <i class="glyphicon glyphicon-remove pull-right"></i>\n                </a>\n              </div>\n            </div>\n          </div>\n          <div class="panel-body">\n            <xos-form config="vm.formConfig" ng-model="vm.detailedItem"></xos-form>\n          </div>\n        </div>\n        <xos-alert config="{type: \'success\', closeBtn: true}" show="vm.responseMsg">{{vm.responseMsg}}</xos-alert>\n        <xos-alert config="{type: \'danger\', closeBtn: true}" show="vm.responseErr">{{vm.responseErr}}</xos-alert>\n      ',bindToController:!0,controllerAs:"vm",controller:["$injector","LabelFormatter","_","XosFormHelpers",function(e,n,o,i){var t=this;this.responseMsg=!1,this.responseErr=!1,this.tableConfig={columns:[],actions:[{label:"delete",icon:"remove",cb:function(e){t.Resource["delete"]({id:e.id}).$promise.then(function(){o.remove(t.data,function(n){return n.id===e.id}),t.responseMsg=t.config.resource+" with id "+e.id+" successfully deleted"})["catch"](function(n){t.responseErr=n.data.detail||"Error while deleting "+t.config.resource+" with id "+e.id})},color:"red"},{label:"details",icon:"search",cb:function(e){t.detailedItem=e}}],classes:"table table-striped table-bordered table-responsive",filter:"field",order:!0,pagination:{pageSize:10}},this.formConfig={exclude:this.config.hiddenFields,fields:{},formName:this.config.resource+"Form",actions:[{label:"Save",icon:"ok",cb:function(e){var n=void 0,o=!0;e.id?(n=e.$update(),o=!1):n=e.$save(),n.then(function(n){o&&t.data.push(angular.copy(n)),delete t.detailedItem,t.responseMsg=t.config.resource+" with id "+e.id+" successfully saved"})["catch"](function(n){t.responseErr=n.data.detail||"Error while saving "+t.config.resource+" with id "+e.id})},"class":"success"}]},this.cleanForm=function(){delete t.detailedItem},this.createItem=function(){t.detailedItem=new t.Resource},this.Resource=e.get(this.config.resource);var r=function(){t.Resource.query().$promise.then(function(e){if(!e[0])return void(t.data=e);var r=e[0],a=Object.keys(r);o.remove(a,function(e){return"id"===e||"validators"===e}),angular.isArray(t.config.hiddenFields)&&(a=o.difference(a,t.config.hiddenFields));var s=a.map(function(e){return n.format(e)});a.forEach(function(e,n){var o={label:s[n],prop:e};angular.isString(r[e])&&"undefined"!=typeof r[e]&&(o.type=_typeof(r[e])),t.tableConfig.columns.push(o)}),a.forEach(function(e,o){t.formConfig.fields[e]={label:n.format(s[o]).replace(":",""),type:i._getFieldFormat(r[e])}}),t.data=e})};r()}]}})}(),function(){angular.module("xos.uiComponents").directive("xosSmartPie",function(){return{restrict:"E",scope:{config:"="},template:'\n        <canvas\n          class="chart chart-pie {{vm.config.classes}}"\n          chart-data="vm.data" chart-labels="vm.labels"\n          chart-legend="{{vm.config.legend}}">\n        </canvas>\n      ',bindToController:!0,controllerAs:"vm",controller:["$injector","$interval","$scope","$timeout","_",function(e,n,o,i,t){var r=this;if(!this.config.resource&&!this.config.data)throw new Error("[xosSmartPie] Please provide a resource or an array of data in the configuration");var a=function(e){return t.groupBy(e,r.config.groupBy)},s=function(e){return t.reduce(Object.keys(e),function(n,o){return n.concat(e[o].length)},[])},l=function(e){return angular.isFunction(r.config.labelFormatter)?r.config.labelFormatter(Object.keys(e)):Object.keys(e)},c=function(e){var n=a(e);r.data=s(n),r.labels=l(n)};this.config.resource?!function(){r.Resource=e.get(r.config.resource);var o=function(){r.Resource.query().$promise.then(function(e){e[0]&&c(e)})};o(),r.config.poll&&n(function(){o()},1e3*r.config.poll)}():o.$watch(function(){return r.config.data},function(e){e&&c(r.config.data)},!0),o.$on("create",function(e,n){console.log("create: "+n.id)}),o.$on("destroy",function(e,n){console.log("destroy: "+n.id)})}]}})}(),function(){function e(){var e=function(e){return e.split("_").join(" ").trim()},n=function(e){return e.split(/(?=[A-Z])/).map(function(e){return e.toLowerCase()}).join(" ")},o=function(e){return e.slice(0,1).toUpperCase()+e.slice(1)},i=function(i){return i=e(i),i=n(i),i=o(i).replace(/\s\s+/g," ")+":",i.replace("::",":")};return{_formatByUnderscore:e,_formatByUppercase:n,_capitalize:o,format:i}}angular.module("xos.uiComponents").factory("LabelFormatter",e)}();var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};!function(){angular.module("xos.uiComponents").service("XosFormHelpers",["_","LabelFormatter",function(e,n){var o=this;this._isEmail=function(e){var n=/(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;return n.test(e)},this._getFieldFormat=function(n){return angular.isArray(n)?"array":e.isDate(n)||!Number.isNaN(Date.parse(n))&&new Date(n).getTime()>6311808e5?"date":"boolean"==typeof n?"boolean":o._isEmail(n)?"email":angular.isString(n)||null===n?"text":"undefined"==typeof n?"undefined":_typeof(n)},this.buildFormStructure=function(i,t,r){return i=angular.extend(i,t),t=t||{},e.reduce(Object.keys(i),function(e,i){return e[i]={label:t[i]&&t[i].label?t[i].label+":":n.format(i),type:t[i]&&t[i].type?t[i].type:o._getFieldFormat(r[i]),validators:t[i]&&t[i].validators?t[i].validators:{},hint:t[i]&&t[i].hint?t[i].hint:""},t[i]&&t[i].options&&(e[i].options=t[i].options),t[i]&&t[i].properties&&(e[i].properties=t[i].properties),"date"===e[i].type&&(r[i]=new Date(r[i])),"number"===e[i].type&&(r[i]=parseInt(r[i],10)),e},{})},this.parseModelField=function(n){return e.reduce(n,function(e,n){return e[n]={},e},{})}}])}(),function(){function e(){return function(e,n){if(angular.isUndefined(e))return!1;if(null===e||null===n)return e===n;if(angular.isObject(n)||angular.isObject(e))return angular.equals(n,e);if(_.isBoolean(e)||_.isBoolean(n))return 0!==e&&1!==e||(e=!!e),angular.equals(n,e);if(!angular.isString(e)||!angular.isString(n)){if(!angular.isDefined(e.toString)||!angular.isDefined(n.toString))return e===n;e=e.toString(),n=n.toString()}return e=e.toLowerCase()+"",n=n.toLowerCase()+"",-1!==e.indexOf(n)}}angular.module("xos.uiComponents").factory("Comparator",e)}(),function(){angular.module("xos.uiComponents").directive("xosField",["RecursionHelper",function(e){return{restrict:"E",scope:{name:"=",field:"=",ngModel:"="},template:'\n        <label ng-if="vm.field.type !== \'object\'">{{vm.field.label}}</label>\n            <input\n              xos-custom-validator custom-validator="vm.field.validators.custom || null"\n              ng-if="vm.field.type !== \'boolean\' && vm.field.type !== \'object\' && vm.field.type !== \'select\'"\n              type="{{vm.field.type}}"\n              name="{{vm.name}}"\n              class="form-control"\n              ng-model="vm.ngModel"\n              ng-minlength="vm.field.validators.minlength || 0"\n              ng-maxlength="vm.field.validators.maxlength || 2000"\n              ng-required="vm.field.validators.required || false" />\n              <select class="form-control" ng-if ="vm.field.type === \'select\'"\n                name = "{{vm.name}}"\n                ng-options="item.id as item.label for item in vm.field.options"\n                ng-model="vm.ngModel"\n                ng-required="vm.field.validators.required || false">\n                </select>\n            <span class="boolean-field" ng-if="vm.field.type === \'boolean\'">\n              <a href="#"\n                class="btn btn-success"\n                ng-show="vm.ngModel"\n                ng-click="vm.ngModel = false">\n                <i class="glyphicon glyphicon-ok"></i>\n              </a>\n              <a href="#"\n                class="btn btn-danger"\n                ng-show="!vm.ngModel"\n                ng-click="vm.ngModel = true">\n                <i class="glyphicon glyphicon-remove"></i>\n              </a>\n            </span>\n            <div\n              class="panel panel-default object-field"\n              ng-if="vm.field.type == \'object\' && (!vm.isEmptyObject(vm.ngModel) || !vm.isEmptyObject(vm.field.properties))"\n              >\n              <div class="panel-heading">{{vm.field.label}}</div>\n              <div class="panel-body">\n                <div ng-if="!vm.field.properties" ng-repeat="(k, v) in vm.ngModel">\n                  <xos-field\n                    name="k"\n                    field="{label: vm.formatLabel(k), type: vm.getType(v)}"\n                    ng-model="v">\n                  </xos-field>\n                </div>\n                <div ng-if="vm.field.properties" ng-repeat="(k, v) in vm.field.properties">\n                  <xos-field\n                    name="k"\n                    field="{\n                      label: v.label || vm.formatLabel(k),\n                      type: v.type,\n                      validators: v.validators\n                    }"\n                    ng-model="vm.ngModel[k]">\n                  </xos-field>\n                </div>\n              </div>\n            </div>\n      ',bindToController:!0,controllerAs:"vm",compile:function(n){return e.compile(n)},controller:["$attrs","XosFormHelpers","LabelFormatter",function(e,n,o){if(!this.name)throw new Error("[xosField] Please provide a field name");if(!this.field)throw new Error("[xosField] Please provide a field definition");if(!this.field.type)throw new Error("[xosField] Please provide a type in the field definition");if(!e.ngModel)throw new Error("[xosField] Please provide an ng-model");this.getType=n._getFieldFormat,this.formatLabel=o.format,this.isEmptyObject=function(e){return e?0===Object.keys(e).length:!0}}]}}]).directive("xosCustomValidator",function(){return{restrict:"A",scope:{fn:"=customValidator"},require:"ngModel",link:function(e,n,o,i){function t(n){var o=e.fn(n);return angular.isArray(o)?i.$setValidity.apply(i,_toConsumableArray(o)):i.$setValidity("customValidation",o),n}angular.isFunction(e.fn)&&i.$parsers.push(t)}}})}(),function(){angular.module("xos.uiComponents").directive("xosValidation",function(){return{restrict:"E",scope:{field:"=",form:"="},template:'\n        <div ng-cloak>\n          <xos-alert config="vm.config" show="vm.field.$error.required !== undefined && vm.field.$error.required !== false  && (vm.field.$touched || vm.form.$submitted)">\n            Field required\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.email !== undefined && vm.field.$error.email !== false && (vm.field.$touched || vm.form.$submitted)">\n            This is not a valid email\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.minlength !== undefined && vm.field.$error.minlength !== false && (vm.field.$touched || vm.form.$submitted)">\n            Too short\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.maxlength !== undefined && vm.field.$error.maxlength !== false && (vm.field.$touched || vm.form.$submitted)">\n            Too long\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.custom !== undefined && vm.field.$error.custom !== false && (vm.field.$touched || vm.form.$submitted)">\n            Field invalid\n          </xos-alert>\n        </div>\n      ',transclude:!0,bindToController:!0,controllerAs:"vm",controller:function(){this.config={type:"danger"}}}})}(),function(){angular.module("xos.uiComponents").directive("xosTable",function(){return{restrict:"E",scope:{data:"=",config:"="},template:'\n          <div ng-show="vm.data.length > 0 && vm.loader == false">\n            <div class="row" ng-if="vm.config.filter == \'fulltext\'">\n              <div class="col-xs-12">\n                <input\n                  class="form-control"\n                  placeholder="Type to search.."\n                  type="text"\n                  ng-model="vm.query"/>\n              </div>\n            </div>\n            <table ng-class="vm.classes" ng-hide="vm.data.length == 0">\n              <thead>\n                <tr>\n                  <th ng-repeat="col in vm.columns">\n                    {{col.label}}\n                    <span ng-if="vm.config.order">\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">\n                        <i class="glyphicon glyphicon-chevron-up"></i>\n                      </a>\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">\n                        <i class="glyphicon glyphicon-chevron-down"></i>\n                      </a>\n                    </span>\n                  </th>\n                  <th ng-if="vm.config.actions">Actions:</th>\n                </tr>\n              </thead>\n              <tbody ng-if="vm.config.filter == \'field\'">\n                <tr>\n                  <td ng-repeat="col in vm.columns">\n                    <input\n                      ng-if="col.type !== \'boolean\' && col.type !== \'array\' && col.type !== \'object\'"\n                      class="form-control"\n                      placeholder="Type to search by {{col.label}}"\n                      type="text"\n                      ng-model="vm.query[col.prop]"/>\n                    <select\n                      ng-if="col.type === \'boolean\'"\n                      class="form-control"\n                      ng-model="vm.query[col.prop]">\n                      <option value="">-</option>\n                      <option value="true">True</option>\n                      <option value="false">False</option>\n                    </select>\n                  </td>\n                  <td ng-if="vm.config.actions"></td>\n                </tr>\n              </tbody>\n              <tbody>\n                <tr ng-repeat="item in vm.data | filter:vm.query:vm.comparator | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">\n                  <td ng-repeat="col in vm.columns" xos-link-wrapper>\n                    <span ng-if="!col.type">{{item[col.prop]}}</span>\n                    <span ng-if="col.type === \'boolean\'">\n                      <i class="glyphicon"\n                        ng-class="{\'glyphicon-ok\': item[col.prop], \'glyphicon-remove\': !item[col.prop]}">\n                      </i>\n                    </span>\n                    <span ng-if="col.type === \'date\'">\n                      {{item[col.prop] | date:\'H:mm MMM d, yyyy\'}}\n                    </span>\n                    <span ng-if="col.type === \'array\'">\n                      {{item[col.prop] | arrayToList}}\n                    </span>\n                    <span ng-if="col.type === \'object\'">\n                      <dl class="dl-horizontal">\n                        <span ng-repeat="(k,v) in item[col.prop]">\n                          <dt>{{k}}</dt>\n                          <dd>{{v}}</dd>\n                        </span>\n                      </dl>\n                    </span>\n                    <span ng-if="col.type === \'custom\'">\n                      {{col.formatter(item)}}\n                    </span>\n                    <span ng-if="col.type === \'icon\'">\n                      <i class="glyphicon glyphicon-{{col.formatter(item)}}">\n                      </i>\n                    </span>\n                  </td>\n                  <td ng-if="vm.config.actions">\n                    <a href=""\n                      ng-repeat="action in vm.config.actions"\n                      ng-click="action.cb(item)"\n                      title="{{action.label}}">\n                      <i\n                        class="glyphicon glyphicon-{{action.icon}}"\n                        style="color: {{action.color}};"></i>\n                    </a>\n                  </td>\n                </tr>\n              </tbody>\n            </table>\n            <xos-pagination\n              ng-if="vm.config.pagination"\n              page-size="vm.config.pagination.pageSize"\n              total-elements="vm.data.length"\n              change="vm.goToPage">\n              </xos-pagination>\n          </div>\n          <div ng-show="(vm.data.length == 0 || !vm.data) && vm.loader == false">\n             <xos-alert config="{type: \'info\'}">\n              No data to show.\n            </xos-alert>\n          </div>\n          <div ng-show="vm.loader == true">\n            <div class="loader"></div>\n          </div>\n        ',bindToController:!0,controllerAs:"vm",controller:["_","$scope","Comparator",function(e,n,o){var i=this;if(this.comparator=o,this.loader=!0,n.$watch(function(){return i.data},function(e){angular.isDefined(e)&&(i.loader=!1)}),!this.config)throw new Error('[xosTable] Please provide a configuration via the "config" attribute');if(!this.config.columns)throw new Error("[xosTable] Please provide a columns list in the configuration");this.config.order&&angular.isObject(this.config.order)&&(this.reverse=this.config.order.reverse||!1,this.orderBy=this.config.order.field||"id");var t=e.filter(this.config.columns,{type:"custom"});angular.isArray(t)&&t.length>0&&e.forEach(t,function(e){if(!e.formatter||!angular.isFunction(e.formatter))throw new Error("[xosTable] You have provided a custom field type, a formatter function should provided too.")});var r=e.filter(this.config.columns,{type:"icon"});angular.isArray(r)&&r.length>0&&e.forEach(r,function(e){if(!e.formatter||!angular.isFunction(e.formatter))throw new Error("[xosTable] You have provided an icon field type, a formatter function should provided too.")});var a=e.filter(this.config.columns,function(e){return angular.isDefined(e.link)});angular.isArray(a)&&a.length>0&&e.forEach(a,function(e){if(!angular.isFunction(e.link))throw new Error("[xosTable] The link property should be a function.")}),this.columns=this.config.columns,this.classes=this.config.classes||"table table-striped table-bordered",this.config.actions,this.config.pagination&&(this.currentPage=0,this.goToPage=function(e){i.currentPage=e})}]}}).filter("arrayToList",function(){return function(e){return angular.isArray(e)?e.join(", "):e}}).directive("xosLinkWrapper",function(){return{restrict:"A",transclude:!0,template:'\n          <a ng-if="col.link" href="{{col.link(item)}}">\n            <div ng-transclude></div>\n          </a>\n          <div ng-transclude ng-if="!col.link"></div>\n        '}})}(),function(){angular.module("xos.uiComponents").directive("xosForm",function(){return{restrict:"E",scope:{config:"=",ngModel:"="},template:'\n        <form name="vm.{{vm.config.formName || \'form\'}}" novalidate>\n          <div class="form-group" ng-repeat="(name, field) in vm.formField">\n            <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>\n            <xos-validation field="vm[vm.config.formName || \'form\'][name]" form = "vm[vm.config.formName || \'form\']"></xos-validation>\n            <div class="alert alert-info" ng-show="(field.hint).length >0" role="alert">{{field.hint}}</div>\n          </div>\n          <div class="form-group" ng-if="vm.config.actions">\n          <xos-alert config="vm.config.feedback" show="vm.config.feedback.show">{{vm.config.feedback.message}}</xos-alert>\n\n            <button role="button" href=""\n              ng-repeat="action in vm.config.actions"\n              ng-click="action.cb(vm.ngModel, vm[vm.config.formName || \'form\'])"\n              class="btn btn-{{action.class}}"\n              title="{{action.label}}">\n              <i class="glyphicon glyphicon-{{action.icon}}"></i>\n              {{action.label}}\n            </button>\n          </div>\n        </form>\n      ',bindToController:!0,controllerAs:"vm",controller:["$scope","$log","_","XosFormHelpers",function(e,n,o,i){var t=this;if(!this.config)throw new Error('[xosForm] Please provide a configuration via the "config" attribute');if(!this.config.actions)throw new Error("[xosForm] Please provide an action list in the configuration");this.config.feedback||(this.config.feedback={show:!1,message:"Form submitted successfully !!!",type:"success"}),this.excludedField=["id","validators","created","updated","deleted","backend_status"],this.config&&this.config.exclude&&(this.excludedField=this.excludedField.concat(this.config.exclude)),this.formField=[],e.$watch(function(){return t.config},function(){if(t.ngModel){var e=o.difference(Object.keys(t.ngModel),t.excludedField),n=i.parseModelField(e);t.formField=i.buildFormStructure(n,t.config.fields,t.ngModel)}},!0),e.$watch(function(){return t.ngModel},function(e){if(t.formField={},e){var n=o.difference(Object.keys(e),t.excludedField),r=i.parseModelField(n);t.formField=i.buildFormStructure(r,t.config.fields,e)}})}]}})}(),function(){angular.module("xos.uiComponents").directive("xosPagination",function(){return{restrict:"E",scope:{pageSize:"=",totalElements:"=",change:"="},template:'\n        <div class="row" ng-if="vm.pageList.length > 1">\n          <div class="col-xs-12 text-center">\n            <ul class="pagination">\n              <li\n                ng-click="vm.goToPage(vm.currentPage - 1)"\n                ng-class="{disabled: vm.currentPage == 0}">\n                <a href="" aria-label="Previous">\n                    <span aria-hidden="true">&laquo;</span>\n                </a>\n              </li>\n              <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">\n                <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>\n              </li>\n              <li\n                ng-click="vm.goToPage(vm.currentPage + 1)"\n                ng-class="{disabled: vm.currentPage == vm.pages - 1}">\n                <a href="" aria-label="Next">\n                    <span aria-hidden="true">&raquo;</span>\n                </a>\n              </li>\n            </ul>\n          </div>\n        </div>\n      ',bindToController:!0,controllerAs:"vm",controller:["$scope",function(e){var n=this;this.currentPage=0,this.goToPage=function(e){0>e||e===n.pages||(n.currentPage=e,n.change(e))},this.createPages=function(e){for(var n=[],o=0;e>o;o++)n.push(o);return n},e.$watch(function(){return n.totalElements},function(){n.totalElements&&(n.pages=Math.ceil(n.totalElements/n.pageSize),n.pageList=n.createPages(n.pages))})}]}}).filter("pagination",function(){return function(e,n){return e&&angular.isArray(e)?(n=parseInt(n,10),e.slice(n)):e}})}(),function(){angular.module("xos.uiComponents").directive("xosAlert",function(){return{restrict:"E",scope:{config:"=",show:"=?"},template:'\n        <div ng-cloak class="alert alert-{{vm.config.type}}" ng-hide="!vm.show">\n          <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">\n            <span aria-hidden="true">&times;</span>\n          </button>\n          <p ng-transclude></p>\n        </div>\n      ',transclude:!0,bindToController:!0,controllerAs:"vm",controller:["$timeout",function(e){var n=this;if(!this.config)throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');this.show=this.show!==!1,this.dismiss=function(){n.show=!1},this.config.autoHide&&!function(){var o=e(function(){n.dismiss(),e.cancel(o)},n.config.autoHide)}()}]}})}(),function(){function e(e,n,o){e.interceptors.push("SetCSRFToken"),n.startSymbol("{$"),n.endSymbol("$}"),o.defaults.stripTrailingSlashes=!1}e.$inject=["$httpProvider","$interpolateProvider","$resourceProvider"],angular.module("bugSnag",[]).factory("$exceptionHandler",function(){return function(e,n){window.Bugsnag?Bugsnag.notifyException(e,{diagnostics:{cause:n}}):console.error(e,n,e.stack)}}),angular.module("xos.helpers",["ngCookies","ngResource","ngAnimate","bugSnag","xos.uiComponents"]).config(e).factory("_",["$window",function(e){return e._}])}(),function(){angular.module("xos.helpers").service("vSG-Collection",["$resource",function(e){return e("/api/service/vsg/")}])}(),function(){angular.module("xos.helpers").service("vOLT-Collection",["$resource",function(e){return e("/api/tenant/cord/volt/:volt_id/",{volt_id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Login",["$resource",function(e){return e("/api/utility/login/")}]).service("Logout",["$resource",function(e){return e("/api/utility/logout/")}])}(),function(){angular.module("xos.helpers").service("Users",["$resource",function(e){return e("/api/core/users/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Truckroll",["$resource",function(e){return e("/api/tenant/truckroll/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Tenants",["$resource",function(e){return e("/api/core/tenants/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Subscribers",["$resource",function(e){return e("/api/tenant/cord/subscriber/:id/",{id:"@id"},{update:{method:"PUT"},"View-a-Subscriber-Features-Detail":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/"},"Read-Subscriber-uplink_speed":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uplink_speed/"},"Update-Subscriber-uplink_speed":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uplink_speed/"},"Read-Subscriber-downlink_speed":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/downlink_speed/"},"Update-Subscriber-downlink_speed":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/downlink_speed/"},"Read-Subscriber-cdn":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/cdn/"},"Update-Subscriber-cdn":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/cdn/"},"Read-Subscriber-uverse":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uverse/"},"Update-Subscriber-uverse":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uverse/"},"Read-Subscriber-status":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/status/"},"Update-Subscriber-status":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/status/"}})}])}(),function(){angular.module("xos.helpers").service("SlicesPlus",["$http","$q",function(e,n){this.query=function(o){var i=n.defer();return e.get("/api/utility/slicesplus/",{params:o}).then(function(e){i.resolve(e.data)})["catch"](function(e){i.reject(e.data)}),{$promise:i.promise}},this.get=function(o,i){var t=n.defer();return e.get("/api/utility/slicesplus/"+o,{params:i}).then(function(e){t.resolve(e.data)})["catch"](function(e){t.reject(e.data)}),{$promise:t.promise}}}])}(),function(){angular.module("xos.helpers").service("Slices",["$resource",function(e){return e("/api/core/slices/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Sites",["$resource",function(e){return e("/api/core/sites/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Services",["$resource",function(e){return e("/api/core/services/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("ONOS-Services-Collection",["$resource",function(e){return e("/api/service/onos/")}])}(),function(){angular.module("xos.helpers").service("ONOS-App-Collection",["$resource",function(e){return e("/api/tenant/onos/app/")}])}(),function(){angular.module("xos.helpers").service("Nodes",["$resource",function(e){return e("/api/core/nodes/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Networks",["$resource",function(e){return e("/api/core/networks/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Instances",["$resource",function(e){return e("/api/core/instances/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Images",["$resource",function(e){return e("/api/core/images/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Flavors",["$resource",function(e){return e("/api/core/flavors/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Example-Services-Collection",["$resource",function(e){return e("/api/service/exampleservice/")}])}(),function(){angular.module("xos.helpers").service("Deployments",["$resource",function(e){return e("/api/core/deployments/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("XosUserPrefs",["$cookies",function(e){var n=this,o=e.get("xosUserPrefs")?angular.fromJson(e.get("xosUserPrefs")):{};this.getAll=function(){return o=e.get("xosUserPrefs")?angular.fromJson(e.get("xosUserPrefs")):{}},this.setAll=function(n){e.put("xosUserPrefs",angular.toJson(n))},this.getSynchronizerNotificationStatus=function(){var e=arguments.length<=0||void 0===arguments[0]?!1:arguments[0];return e?n.getAll().synchronizers.notification[e]:n.getAll().synchronizers.notification},this.setSynchronizerNotificationStatus=function(){var e=arguments.length<=0||void 0===arguments[0]?!1:arguments[0],o=arguments[1];if(!e)throw new Error("[XosUserPrefs] When updating a synchronizer is mandatory to provide a name.");var i=n.getAll();i.synchronizers||(i.synchronizers={notification:{}}),i.synchronizers.notification[e]=o,n.setAll(i)}}])}(),function(){angular.module("xos.helpers").service("GraphService",["$q","Tenants","Services",function(e,n,o){var i=this;this.loadCoarseData=function(){var i=void 0,t=e.defer();return o.query().$promise.then(function(e){return i=e,n.query({kind:"coarse"}).$promise}).then(function(e){t.resolve({tenants:e,services:i})}),t.promise},this.getCoarseGraph=function(){return i.loadCoarseData().then(function(e){console.log(e)}),"ciao"}}])}(),function(){angular.module("xos.helpers").factory("Notification",function(){return window.Notification}).service("xosNotification",["$q","$log","Notification",function(e,n,o){var i=this;this.checkPermission=function(){var n=e.defer();return o.requestPermission().then(function(e){"granted"===e?n.resolve(e):n.reject(e)}),n.promise},this.sendNotification=function(e,i){var t=new o(e,i);t.onerror=function(e){n.error(e)}},this.notify=function(e,t){"Notification"in window?"granted"!==o.permission?i.checkPermission().then(function(){
+return i.sendNotification(e,t)}):"granted"===o.permission&&i.sendNotification(e,t):n.info("This browser does not support desktop notification")}}])}(),function(){function e(){return{request:function(e){return-1===e.url.indexOf(".html")&&(e.url+="?no_hyperlinks=1"),e}}}angular.module("xos.helpers").factory("NoHyperlinks",e)}(),angular.module("xos.helpers").config(["$provide",function(e){e.decorator("$log",["$delegate",function(e){var n=function(){return window.location.href.indexOf("debug=true")>=0},o=e.log,i=e.info,t=e.warn,r=e.error,a=e.debug,s=function(o){return function(){if(n()){var i=[].slice.call(arguments),t=new Date;i[0]="["+t.getHours()+":"+t.getMinutes()+":"+t.getSeconds()+"] "+i[0],!angular.isFunction(e.reset)||e.debug.logs instanceof Array||e.reset(),o.apply(null,i)}}};return e.info=s(i),e.log=s(o),e.warn=s(t),e.error=s(r),e.debug=s(a),e}])}]),function(){function e(){var e=function(e){return e.split("_").join(" ").trim()},n=function(e){return e.split(/(?=[A-Z])/).map(function(e){return e.toLowerCase()}).join(" ")},o=function(e){return e.slice(0,1).toUpperCase()+e.slice(1)},i=function(i){return i=e(i),i=n(i),i=o(i).replace(/\s\s+/g," ")+":",i.replace("::",":")};return{_formatByUnderscore:e,_formatByUppercase:n,_capitalize:o,format:i}}angular.module("xos.uiComponents").factory("LabelFormatter",e)}(),function(){function e(e){return{request:function(n){return"GET"!==n.method&&(n.headers["X-CSRFToken"]=e.get("xoscsrftoken")),n}}}e.$inject=["$cookies"],angular.module("xos.helpers").factory("SetCSRFToken",e)}();
\ No newline at end of file
diff --git a/xos/core/xoslib/static/js/xosTenant.js b/xos/core/xoslib/static/js/xosTenant.js
index 0bd3604..be4338c 100644
--- a/xos/core/xoslib/static/js/xosTenant.js
+++ b/xos/core/xoslib/static/js/xosTenant.js
@@ -1,524 +1 @@
-

-/* globals XOSModel, XOSCollection */

-/* eslint-disable no-undef, guard-for-in, new-cap, space-before-blocks, no-unused-vars, no-alert, eqeqeq */

-

-XOSTenantSite = XOSModel.extend({

-  listFields: ['name', 'allocated'],

-  modelName: 'tenantSite',

-  collectionName: 'tenantSites'

-});

-

-XOSTenantSiteCollection = XOSCollection.extend({

-  listFields: ['name', 'allocated', 'ready'],

-  modelName: 'tenantSite',

-  collectionName: 'tenantSites',

-

-  getFromSlice: function(slice) {

-    var tenantSites = [];

-    var id = 0;

-    var that = this;

-

-    for (siteName in slice.attributes.site_allocation) {

-      allocated = slice.attributes.site_allocation[siteName];

-      ready = slice.attributes.site_ready[siteName] || 0;

-      tenantSites.push(new XOSTenantSite({name: siteName, allocated: allocated, ready: ready, id: id}));

-      id = id + 1;

-    }

-

-    for (index in xos.tenantview.models[0].attributes.blessed_site_names) {

-      siteName = xos.tenantview.models[0].attributes.blessed_site_names[index];

-      if (! (siteName in slice.attributes.site_allocation)) {

-        tenantSites.push(new XOSTenantSite({name: siteName, allocated: 0, ready: 0, id: id}));

-        id = id + 1;

-      }

-    }

-    this.set(tenantSites);

-

-    this.listenTo(slice, 'change', function() {

-      that.getReadyFromSlice(slice);

-    });

-  },

-

-  getReadyFromSlice: function(slice) {

-    for (siteName in slice.attributes.site_ready) {

-      ready = slice.attributes.site_ready[siteName];

-      for (index in this.models) {

-        tenantSite = this.models[index];

-        if (tenantSite.attributes.name == siteName) {

-          tenantSite.set('ready', ready);

-        }

-      }

-    }

-  },

-

-  putToSlice: function(slice) {

-    slice.attributes.site_allocation = {};

-    for (index in this.models) {

-      var model = this.models[index];

-

-      slice.attributes.site_allocation[ model.attributes.name ] = model.attributes.allocated;

-    }

-  },

-});

-

-XOSEditUsersView = Marionette.ItemView.extend({

-  template: '#tenant-edit-users',

-  viewInitializers: [],

-

-  onShow: function() {

-    _.each(this.viewInitializers, function(initializer) {

-      initializer();

-    });

-  },

-

-  templateHelpers: function() {

-    return {detailView: this, model: this.model};

-  }

-

-});

-

-XOSTenantSummaryView = XOSDetailView.extend({

-  events: {'change': 'onChange'},

-

-  onChange: function(e) {

-    XOSTenantApp.setDirty(true);

-  },

-

-  saveSuccess: function() {

-    XOSTenantApp.setDirty(false);

-  },

-

-});

-

-

-XOSTenantButtonView = Marionette.ItemView.extend({

-  template: '#xos-tenant-buttons-template',

-

-  events: {'click button.btn-tenant-create': 'createClicked',

-           'click button.btn-tenant-delete': 'deleteClicked',

-           'click button.btn-tenant-add-user': 'addUserClicked',

-           'click button.btn-tenant-save': 'saveClicked',

-           'click button.btn-tenant-download-ssh': 'downloadClicked',

-           },

-

-  createClicked: function() {

-    XOSTenantApp.addSlice();

-  },

-

-  deleteClicked: function() {

-    XOSTenantApp.deleteSlice(this.options.linkedView.model);

-  },

-

-  addUserClicked: function() {

-    XOSTenantApp.editUsers(this.options.linkedView.model);

-  },

-

-  downloadClicked: function() {

-    XOSTenantApp.downloadSSH(this.options.linkedView.model);

-  },

-

-  saveClicked: function(e) {

-    var model = this.options.linkedView.model;

-

-    model.tenantSiteCollection.putToSlice(model);

-    model.attributes.users = model.usersBuffer;

-

-    e.preventDefault();

-    this.options.linkedView.save();

-    //this.options.linkedView.submitContinueClicked.call(this.options.linkedView, e);

-    //XOSTenantApp.setDirty(false);

-  }

-});

-

-XOSTenantApp = new XOSApplication({

-  logTableId: '#logTable',

-  statusMsgId: '#statusMsg',

-  hideTabsByDefault: true,

-  dirty: false,

-  varName: 'XOSTenantApp',

-});

-

-XOSTenantApp.addRegions({

-  tenantSliceSelector: '#tenantSliceSelector',

-  tenantSummary: '#tenantSummary',

-  tenantSiteList: '#tenantSiteList',

-  tenantButtons: '#tenantButtons',

-  tenantAddSliceInterior: '#tenant-addslice-interior',

-  tenantEditUsersInterior: '#tenant-edit-users-interior',

-  tenantSSHCommandsInterior: '#tenant-ssh-commands-interior',

-});

-

-XOSTenantApp.setDirty = function(dirty) {

-  XOSTenantApp.dirty = dirty;

-  if (dirty) {

-    $('button.btn-tenant-save').addClass('btn-success');

-  }

-  else {

-    $('button.btn-tenant-save').removeClass('btn-success');

-  }

-};

-

-XOSTenantApp.buildViews = function() {

-  XOSTenantApp.tenantSites = new XOSTenantSiteCollection();

-

-  tenantSummaryClass = XOSTenantSummaryView.extend({

-    template: '#xos-detail-template',

-    app: XOSTenantApp,

-    detailFields: ['serviceClass', 'default_image', 'default_flavor', 'network_ports'],

-    fieldDisplayNames: {

-      serviceClass: 'Service Level',

-      default_flavor: 'Flavor',

-      default_image: 'Image',

-      mount_data_sets: 'Data Sets'

-    },

-    helpText: {

-      'serviceClass': 'Existing instances will be re-instantiated if changed',

-      'default_image': 'Existing instances will be re-instantiated if changed',

-      'default_flavor': 'Existing instances will be re-instantiated if changed'

-    },

-    onShow: function() {

-      // the slice selector is in a different table, so make every label cell the maximal width

-      make_same_width('#xos-tenant-view-panel', '.xos-label-cell');

-    },

-  });

-

-  XOSTenantApp.tenantSummaryView = tenantSummaryClass;

-

-  tenantAddClass = XOSDetailView.extend({

-    template: '#xos-detail-template',

-    app: XOSTenantApp,

-    detailFields: ['name', 'description']

-  });

-

-  XOSTenantApp.tenantAddView = tenantAddClass;

-

-  tenantSiteItemClass = XOSItemView.extend({

-    template: '#xos-listitem-template',

-    app: XOSTenantApp

-  });

-

-  XOSTenantApp.tenantSiteItemView = tenantSiteItemClass;

-

-  tenantSiteListClass = XOSDataTableView.extend({

-    template: '#xos-list-template',

-    app: XOSTenantApp,

-    childView: tenantSiteItemClass,

-    collection: XOSTenantApp.tenantSites,

-    title: 'sites',

-    inputType: {allocated: 'spinner'},

-    noDeleteColumn: true,

-    disablePaginate: true,

-    disableFilter: true,

-    fieldDisplayNames: {name: 'Site'},

-  });

-

-  XOSTenantApp.tenantSiteListView = tenantSiteListClass;

-

-  XOSTenantApp.tenantSliceSelectorView = SliceSelectorView.extend({

-    sliceChanged: function(id) {

-      XOSTenantApp.navToSlice(id);

-    },

-    filter: function(slice) {

-      return slice.attributes.current_user_can_see;

-    },

-  });

-

-  xos.sites.fetch();

-  xos.slicesPlus.fetch();

-  xos.tenantview.fetch();

-};

-

-make_choices = function(list_of_names, list_of_values) {

-  var result = [];

-  var displayName;

-

-  if (!list_of_values) {

-    for (var index in list_of_names) {

-      displayName = list_of_names[index];

-      result.push([displayName, displayName]);

-    }

-  }

-  else {

-    for (var index in list_of_names) {

-      displayName = list_of_names[index];

-      id = list_of_values[index];

-      result.push([displayName, id]);

-    }

-  }

-  return result;

-};

-

-XOSTenantApp.navToSlice = function(id) {

-  XOSTenantApp.viewSlice(xos.slicesPlus.get(id));

-};

-

-XOSTenantApp.adjustCollectionField = function(collectionName, id, fieldName, amount) {

-  model = XOSTenantApp[collectionName].get(id);

-  model.set(fieldName, Math.max(model.get(fieldName) + amount, 0));

-  XOSTenantApp.setDirty(true);

-};

-

-XOSTenantApp.addSlice = function() {

-  var app = this;

-

-  if (!xos.tenant().current_user_can_create_slice) {

-    window.alert('You do not have sufficient rights to create a slice on your site');

-    return;

-  }

-

-  model = new xos.slicesPlus.model({

-    site: xos.tenant().current_user_site_id,

-    name: xos.tenant().current_user_login_base + '_',

-    creator: xos.tenant().current_user_id

-  });

-

-  var detailView = new XOSTenantApp.tenantAddView({

-    model: model,

-    collection: xos.slicesPlus,

-    noSubmitButton: true,

-  });

-

-  detailView.dialog = $('#tenant-addslice-dialog');

-  app.tenantAddSliceInterior.show(detailView);

-

-  $('#tenant-addslice-dialog').dialog({

-    autoOpen: false,

-    modal: true,

-    width: 640,

-    buttons: {

-      'Create Slice': function() {

-        var addDialog = this;

-

-        detailView.synchronous = true;

-        detailView.afterSave = function() {

-          $(addDialog).dialog('close');

-          XOSTenantApp.navToSlice(detailView.model.id);

-        };

-        detailView.save();

-      },

-      'Cancel': function() {

-        $(this).dialog('close');

-      }

-    }

-  });

-  $('#tenant-addslice-dialog').dialog('open');

-};

-

-XOSTenantApp.editUsers = function(model) {

-  var app = this;

-  var detailView = new XOSEditUsersView({model: model, collection: xos.slicesPlus});

-

-  detailView.dialog = $('#tenant-edit-users-dialog');

-  app.tenantEditUsersInterior.show(detailView);

-

-  $('#tenant-edit-users-dialog').dialog({

-    autoOpen: false,

-    modal: true,

-    width: 640,

-    buttons: {

-      'Ok': function() {

-        var editDialog = this;

-        var user_ids = all_options($('#tenant-edit-users-dialog').find('.select-picker-to'));

-

-        user_ids = user_ids.map(function(x) {

-          return parseInt(x,10);

-        });

-

-        if (!array_same_elements(user_ids, model.usersBuffer)) {

-          XOSTenantApp.setDirty(true);

-        }

-        model.usersBuffer = user_ids;

-        $(editDialog).dialog('close');

-      },

-      'Cancel': function() {

-        $(this).dialog('close');

-      }

-    }

-  });

-  $('#tenant-edit-users-dialog').dialog('open');

-};

-

-XOSTenantApp.downloadSSH = function(model) {

-  var sshCommands = '';

-

-  for (index in model.attributes.sliceInfo.sshCommands) {

-    sshCommand = model.attributes.sliceInfo.sshCommands[index];

-    sshCommands = sshCommands + sshCommand + '\n';

-  }

-

-  if (sshCommands.length == 0) {

-    alert('this slice has no instantiated instances yet');

-    return;

-  }

-

-  var htmlView = new HTMLView({

-    html: '<pre style="overflow: auto; word-wrap: normal; white-space: pre; word-wrap: normal;">' +

-      sshCommands + '</pre>'

-  });

-

-  XOSTenantApp.tenantSSHCommandsInterior.show(htmlView);

-

-  $('#tenant-ssh-commands-dialog').dialog({

-    autoOpen: false,

-    modal: true,

-    width: 640,

-    buttons: {

-      'Download': function() {

-        var dlLink = document.createElement('a');

-

-        dlLink.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(sshCommands));

-        dlLink.setAttribute('download', 'sshcommands.txt');

-        dlLink.click();

-

-        //window.open('data:text/text,' + encodeURIComponent(sshCommands));

-      },

-      'Close': function() {

-        $(this).dialog('close');

-      },

-    }

-  });

-  $('#tenant-ssh-commands-dialog').dialog('open');

-};

-

-XOSTenantApp.deleteSlice = function(model) {

-  var app = this;

-

-  app.deleteDialog(model, function() {

-    app.viewSlice(undefined);

-  });

-};

-

-XOSTenantApp.viewSlice = function(model) {

-  if (XOSTenantApp.dirty) {

-    if (!confirm('The current instance has unsaved data -- view new instance anyway ?')) {

-      $('#tenantSliceSelector select').val(XOSTenantApp.currentSlice.id);

-      return;

-    }

-  }

-

-  XOSTenantApp.setDirty(false);

-

-  if (!model && xos.slicesPlus.models.length > 0) {

-    model = xos.slicesPlus.models[0];

-  }

-

-  if (model) {

-    sliceSelector = new XOSTenantApp.tenantSliceSelectorView({

-      collection: xos.slicesPlus,

-      selectedID: model ? model.id : null,

-    });

-

-    XOSTenantApp.sliceSelector = sliceSelector;

-    XOSTenantApp.tenantSliceSelector.show(sliceSelector);

-

-    tenantSummary = new XOSTenantApp.tenantSummaryView({

-      model: model,

-      choices: {

-        mount_data_sets: make_choices(xos.tenant().public_volume_names, null),

-        serviceClass: make_choices(xos.tenant().blessed_service_class_names, xos.tenant().blessed_service_classes),

-        default_image: make_choices(xos.tenant().blessed_image_names, xos.tenant().blessed_images),

-        default_flavor: make_choices(xos.tenant().blessed_flavor_names, xos.tenant().blessed_flavors)

-      },

-    });

-

-    XOSTenantApp.tenantSummary.show(tenantSummary);

-

-    tenantSites = new XOSTenantSiteCollection();

-    tenantSites.getFromSlice(model);

-    model.usersBuffer = model.attributes.users; /* save a copy of 'users' that we can edit. This prevents another view (developer) from overwriting our copy with a fetch from the server */

-    model.usersOrig = model.attributes.users;   /* save an immutable copy that we'll use for username lookups */

-    model.user_namesOrig = model.attributes.user_names;

-    model.tenantSiteCollection = tenantSites;

-    XOSTenantApp.tenantSites = tenantSites;

-

-    tenantSiteList = new XOSTenantApp.tenantSiteListView({collection: tenantSites});

-    XOSTenantApp.tenantSiteList.show(tenantSiteList);

-    // on xos.slicePlus.sort, need to update xostenantapp.tenantSites

-

-    XOSTenantApp.tenantButtons.show(

-      new XOSTenantButtonView({

-        app: XOSTenantApp,

-        linkedView: tenantSummary

-      })

-    );

-

-    XOSTenantApp.currentSlice = model;

-  }

-  else {

-    XOSTenantApp.tenantSliceSelector.show(new HTMLView({html: ''}));

-    XOSTenantApp.tenantSummary.show(new HTMLView({html: 'You have no slices'}));

-    XOSTenantApp.tenantSiteList.show(new HTMLView({html: ''}));

-    XOSTenantApp.tenantButtons.show(

-      new XOSTenantButtonView({

-        template: '#xos-tenant-buttons-noslice-template',

-        app: XOSTenantApp,

-        linkedView: tenantSummary

-      })

-    );

-  }

-};

-

-XOSTenantApp.sanityCheck = function() {

-  errors = [];

-  if (xos.tenant().blessed_deployments && xos.tenant().blessed_deployments.length == 0) {

-    errors.push('no blessed deployments');

-  }

-  if (xos.tenant().blessed_service_classes.length == 0) {

-    errors.push('no blessed service classes');

-  }

-  if (xos.tenant().blessed_flavors.length == 0) {

-    errors.push('no blessed flavors');

-  }

-  if (xos.tenant().blessed_images.length == 0) {

-    errors.push('no blessed images');

-  }

-  if (xos.tenant().blessed_sites.length == 0) {

-    errors.push('no blessed sites');

-  }

-  if (xos.tenant().current_user_site_id == null) {

-    errors.push('current user does not have a site');

-  }

-

-  if (errors.length > 0) {

-    t = templateFromId('#tenant-sanity-check');

-    $('#tenantSummary').html(t({

-      errors: errors,

-      blessed_deployment_names:

-      xos.tenant().blessed_deployment_names

-    }));

-    return false;

-  }

-

-  return true;

-};

-

-XOSTenantApp.collectionLoadChange = function() {

-  stats = xos.getCollectionStatus();

-

-  if (!XOSTenantApp.navigationStarted) {

-    if (stats['isLoaded'] + stats['failedLoad'] >= stats['startedLoad']) {

-      if (XOSTenantApp.sanityCheck()) {

-        XOSTenantApp.viewSlice(undefined);

-      }

-    }

-    else {

-      $('#tenantSummary').html('<h3>Loading...</h3><div id="xos-startup-progress"></div>');

-      $('#xos-startup-progress').progressbar({value: stats['completedLoad'], max: stats['startedLoad']});

-    }

-  }

-};

-

-XOSTenantApp.on('start', function() {

-  XOSTenantApp.buildViews();

-

-  // fire it once to initially show the progress bar

-  XOSTenantApp.collectionLoadChange();

-

-  // fire it each time the collection load status is updated

-  Backbone.on('xoslib:collectionLoadChange', XOSTenantApp.collectionLoadChange);

-});

-

-$(document).ready(function() {

-  XOSTenantApp.start();

-});

-/* eslint-enable */

+"use strict";angular.module("xos.tenant",["ngResource","ngCookies","ui.router","xos.helpers"]).config(["$stateProvider",function(e){e.state("user-list",{url:"/",template:"<users-list></users-list>"}).state("site",{url:"/site/:id",template:"<site-detail></site-detail>"}).state("createslice",{url:"/site/:site/slice/:id?",template:"<create-slice></create-slice>"})}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).directive("usersList",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/users-list.tpl.html",controller:["Sites","SlicesPlus",function(e,t){var i=this;this.tableConfig={columns:[{label:"Site1",prop:"name",link:function(e){return"/#/site/"+e.id}},{label:"Allocated",prop:"instance_total"},{label:"Ready",prop:"instance_total_ready"}]},e.query().$promise.then(function(e){return i.sites=e,t.query().$promise}).then(function(e){i.slices=e,i.site_list=i.returnData(i.sites,i.slices)})["catch"](function(e){throw new Error(e)}),this.returnData=function(e,t){var i,s=0,l=[];for(i=0;i<e.length;i++){var n=0,a=0;for(s=0;s<t.length;s++)null!=e[i].id&&null!=t[s].site&&e[i].id===t[s].site&&(n+=t[s].instance_total,a+=t[s].instance_total_ready);var r={id:e[i].id,name:e[i].name,instance_total:n,instance_total_ready:a};l.push(r)}return l}}]}}).directive("siteDetail",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"sl",templateUrl:"templates/slicelist.html",controller:["SlicesPlus","$stateParams",function(e,t){var i=this;this.siteId=t.id,this.tableConfig={columns:[{label:"Slice List",prop:"name",link:function(e){return"/#/site/"+e.site+"/slice/"+e.id}},{label:"Allocated",prop:"instance_total"},{label:"Ready",prop:"instance_total_ready"}]},e.query({site:t.id}).$promise.then(function(e){i.sliceList=e})["catch"](function(e){throw new Error(e)})}]}}).directive("createSlice",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"cs",templateUrl:"templates/createslice.html",controller:["Slices","SlicesPlus","Sites","Images","$stateParams","$http","$state","$q",function(e,t,i,s,l,n,a,r){var o=this;this.config={exclude:["site","password","last_login","mount_data_sets","default_flavor","creator","exposed_ports","networks","omf_friendly","omf_friendly","no_sync","no_policy","lazy_blocked","write_protect","deleted","backend_status","backend_register","policed","enacted","updated","created","validators","humanReadableName"],formName:"SliceDetails",feedback:{show:!1,message:"Form submitted successfully !!!",type:"success"},actions:[{label:"Save",icon:"ok",cb:function(e,t){d(e,t).then(function(){a.go("site",{id:o.model.site})})},"class":"success"},{label:"Save and continue editing",icon:"ok",cb:function(e,t){d(e,t)},"class":"primary"},{label:"Save and add another",icon:"ok",cb:function(e,t){d(e,t).then(function(){a.go("createslice",{site:o.model.site,id:""})})},"class":"primary"}],fields:{site:{label:"Site",type:"select",validators:{required:!0},hint:"The Site this Slice belongs to",options:[]},name:{label:"Name",type:"string",hint:"The Name of the Slice",validators:{required:!0}},serviceClass:{label:"ServiceClass",type:"select",validators:{required:!0},hint:"The Site this Slice belongs to",options:[{id:1,label:"Best effort"}]},enabled:{label:"Enabled",type:"boolean",hint:"Status for this Slice"},description:{label:"Description",type:"string",hint:"High level description of the slice and expected activities",validators:{required:!1,minlength:10}},service:{label:"Service",type:"select",validators:{required:!1},options:[{id:0,label:"--------"}]},slice_url:{label:"Slice url",type:"string",validators:{required:!1,minlength:10}},max_instances:{label:"Max Instances",type:"number",validators:{required:!1,min:0}},default_isolation:{label:"Default Isolation",type:"select",validators:{required:!1},options:[{id:"vm",label:"Virtual Machine"},{id:"container",label:"Container"},{id:"container_vm",label:"Container in VM"}]},default_image:{label:"Default image",type:"select",validators:{required:!1},options:[]},network:{label:"Network",type:"select",validators:{required:!1},options:[{id:"default",label:"Default"},{id:"host",label:"Host"},{id:"bridged",label:"Bridged"},{id:"noauto",label:"No Automatic Networks"}]}}};var c;s.query().$promise.then(function(e){o.users=e,c=o.users,o.optionValImg=o.setData(c,{field1:"id",field2:"name"}),o.config.fields.default_image.options=o.optionValImg})["catch"](function(e){throw new Error(e)}),this.setData=function(e,t){var i,s=[];for(i=0;i<e.length;i++){var l={id:e[i][t.field1],label:e[i][t.field2]};s.push(l)}return s},l.id?(delete this.config.fields.site,this.config.exclude.push("site"),e.get({id:l.id}).$promise.then(function(e){o.users=e,c=e,o.model=c})["catch"](function(e){throw new Error(e)})):(this.model={},n.get("/xoslib/tenantview/").success(function(e){o.userList=e,o.model.creator=o.userList.current_user_id}),i.query().$promise.then(function(e){o.users_site=e,o.optionVal=o.setData(o.users_site,{field1:"id",field2:"name"}),o.config.fields.site.options=o.optionVal})["catch"](function(e){throw new Error(e)}));var d=function(t,i){var s=r.defer();if(delete t.networks,i.$valid){if(t.id)var l=e.update(t).$promise;else var l=e.save(t).$promise;l.then(function(e){o.model=e,o.config.feedback.show=!0,s.resolve(o.model)})["catch"](function(e){o.config.feedback.show=!0,o.config.feedback.type="danger",e.data&&e.data.detail?o.config.feedback.message=e.data.detail:o.config.feedback.message=e.statusText,s.reject(e)})}return s.promise}}]}}),angular.module("xos.tenant").run(["$templateCache",function(e){e.put("templates/createslice.html",'<!--<xos-table config="cs.tableConfig" data="cs.sites"></xos-table>-->\r\n<h2>Slice Details</h2>\r\n<hr></hr>\r\n<xos-form ng-model="cs.model" config="cs.config" ></xos-form>\r\n\r\n<!--<pre>-->\r\n<!--&lt;!&ndash;{{cs.users | json}}&ndash;&gt;-->\r\n\r\n<!--{{cs.users.name | json}}-->\r\n\r\n<!--</pre>-->'),e.put("templates/slicelist.html",'<!--<span ng-bind="siteNameSe"></span>-->\r\n<!--<xos-field></xos-field>-->\r\n<a class="addlink btn btn-info" ui-sref="createslice({site: sl.siteId})"><i class="glyphicon glyphicon-plus-sign"></i> Create Slice</a>\r\n<xos-table config="sl.tableConfig" data="sl.sliceList"></xos-table>\r\n<!--<div ui-view="sliceDetails"></div>-->\r\n<!--<pre>{{sl.users[0].site}}</pre>-->\r\n'),e.put("templates/users-list.tpl.html",'<xos-table config="vm.tableConfig" data="vm.site_list"></xos-table>')}]),angular.module("xos.tenant").run(["$location",function(e){e.path("/")}]);
diff --git a/xos/services/ceilometer/admin.py b/xos/onboard/ceilometer/admin.py
similarity index 100%
rename from xos/services/ceilometer/admin.py
rename to xos/onboard/ceilometer/admin.py
diff --git a/xos/api/tenant/ceilometer/monitoringchannel.py b/xos/onboard/ceilometer/api/tenant/ceilometer/monitoringchannel.py
similarity index 100%
rename from xos/api/tenant/ceilometer/monitoringchannel.py
rename to xos/onboard/ceilometer/api/tenant/ceilometer/monitoringchannel.py
diff --git a/xos/onboard/ceilometer/ceilometer-onboard.yaml b/xos/onboard/ceilometer/ceilometer-onboard.yaml
new file mode 100644
index 0000000..82c955f
--- /dev/null
+++ b/xos/onboard/ceilometer/ceilometer-onboard.yaml
@@ -0,0 +1,25 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    servicecontroller#ceilometer:
+      type: tosca.nodes.ServiceController
+      properties:
+          base_url: file:///opt/xos/onboard/ceilometer/
+          # The following will concatenate with base_url automatically, if
+          # base_url is non-null.
+          models: models.py
+          admin: admin.py
+          admin_template: templates/ceilometeradmin.html, templates/sflowadmin.html
+          synchronizer: synchronizer/manifest
+          synchronizer_run: monitoring_channel_synchronizer.py
+          tosca_resource: tosca/resources/ceilometerservice.py, tosca/resources/ceilometertenant.py, tosca/resources/sflowservice.py
+          rest_tenant: subdirectory:ceilometer api/tenant/ceilometer/monitoringchannel.py
+          private_key: file:///opt/xos/key_import/monitoring_channel_rsa
+          public_key: file:///opt/xos/key_import/monitoring_channel_rsa.pub
+
diff --git a/xos/services/ceilometer/models.py b/xos/onboard/ceilometer/models.py
similarity index 100%
rename from xos/services/ceilometer/models.py
rename to xos/onboard/ceilometer/models.py
diff --git a/xos/synchronizers/monitoring_channel/files/docker.list b/xos/onboard/ceilometer/synchronizer/files/docker.list
similarity index 100%
rename from xos/synchronizers/monitoring_channel/files/docker.list
rename to xos/onboard/ceilometer/synchronizer/files/docker.list
diff --git a/xos/synchronizers/monitoring_channel/files/vm-resolv.conf b/xos/onboard/ceilometer/synchronizer/files/vm-resolv.conf
similarity index 100%
rename from xos/synchronizers/monitoring_channel/files/vm-resolv.conf
rename to xos/onboard/ceilometer/synchronizer/files/vm-resolv.conf
diff --git a/xos/onboard/ceilometer/synchronizer/manifest b/xos/onboard/ceilometer/synchronizer/manifest
new file mode 100644
index 0000000..c679225
--- /dev/null
+++ b/xos/onboard/ceilometer/synchronizer/manifest
@@ -0,0 +1,26 @@
+templates/Dockerfile.monitoring_channel
+templates/ceilometer_proxy_config.j2
+templates/Dockerfile.sflowpubsub
+templates/sflow_pub_sub/sample_sflow_pub_sub.conf_sample
+templates/sflow_pub_sub/README
+templates/sflow_pub_sub/sflow_sub_records.py
+templates/sflow_pub_sub/start_sflow_pub_sub
+templates/sflow_pub_sub/sflow_pub_sub_main.py
+templates/sflow_pub_sub/sflow_pub_sub_config.j2
+templates/start-monitoring-channel.sh.j2
+templates/monitoring-channel.conf.j2
+templates/ceilometer_proxy_server.py
+templates/start_ceilometer_proxy
+manifest
+monitoring_channel_synchronizer_config
+steps/sync_sflowtenant.yaml
+steps/sync_sflowtenant.py
+steps/sync_monitoringchannel.yaml
+steps/sync_monitoringchannel.py
+steps/sync_sflowservice.yaml
+steps/sync_sflowservice.py
+files/vm-resolv.conf
+files/docker.list
+model-deps
+supervisor/monitoring_channel_observer.conf
+monitoring_channel_synchronizer.py
diff --git a/xos/synchronizers/vtr/model-deps b/xos/onboard/ceilometer/synchronizer/model-deps
similarity index 100%
rename from xos/synchronizers/vtr/model-deps
rename to xos/onboard/ceilometer/synchronizer/model-deps
diff --git a/xos/synchronizers/monitoring_channel/monitoring_channel_synchronizer.py b/xos/onboard/ceilometer/synchronizer/monitoring_channel_synchronizer.py
similarity index 100%
rename from xos/synchronizers/monitoring_channel/monitoring_channel_synchronizer.py
rename to xos/onboard/ceilometer/synchronizer/monitoring_channel_synchronizer.py
diff --git a/xos/synchronizers/monitoring_channel/monitoring_channel_synchronizer_config b/xos/onboard/ceilometer/synchronizer/monitoring_channel_synchronizer_config
similarity index 100%
rename from xos/synchronizers/monitoring_channel/monitoring_channel_synchronizer_config
rename to xos/onboard/ceilometer/synchronizer/monitoring_channel_synchronizer_config
diff --git a/xos/synchronizers/monitoring_channel/steps/sync_monitoringchannel.py b/xos/onboard/ceilometer/synchronizer/steps/sync_monitoringchannel.py
similarity index 100%
rename from xos/synchronizers/monitoring_channel/steps/sync_monitoringchannel.py
rename to xos/onboard/ceilometer/synchronizer/steps/sync_monitoringchannel.py
diff --git a/xos/synchronizers/monitoring_channel/steps/sync_monitoringchannel.yaml b/xos/onboard/ceilometer/synchronizer/steps/sync_monitoringchannel.yaml
similarity index 100%
rename from xos/synchronizers/monitoring_channel/steps/sync_monitoringchannel.yaml
rename to xos/onboard/ceilometer/synchronizer/steps/sync_monitoringchannel.yaml
diff --git a/xos/synchronizers/monitoring_channel/steps/sync_sflowservice.py b/xos/onboard/ceilometer/synchronizer/steps/sync_sflowservice.py
similarity index 100%
rename from xos/synchronizers/monitoring_channel/steps/sync_sflowservice.py
rename to xos/onboard/ceilometer/synchronizer/steps/sync_sflowservice.py
diff --git a/xos/synchronizers/monitoring_channel/steps/sync_sflowservice.yaml b/xos/onboard/ceilometer/synchronizer/steps/sync_sflowservice.yaml
similarity index 100%
rename from xos/synchronizers/monitoring_channel/steps/sync_sflowservice.yaml
rename to xos/onboard/ceilometer/synchronizer/steps/sync_sflowservice.yaml
diff --git a/xos/synchronizers/monitoring_channel/steps/sync_sflowtenant.py b/xos/onboard/ceilometer/synchronizer/steps/sync_sflowtenant.py
similarity index 100%
rename from xos/synchronizers/monitoring_channel/steps/sync_sflowtenant.py
rename to xos/onboard/ceilometer/synchronizer/steps/sync_sflowtenant.py
diff --git a/xos/synchronizers/monitoring_channel/steps/sync_sflowtenant.yaml b/xos/onboard/ceilometer/synchronizer/steps/sync_sflowtenant.yaml
similarity index 100%
rename from xos/synchronizers/monitoring_channel/steps/sync_sflowtenant.yaml
rename to xos/onboard/ceilometer/synchronizer/steps/sync_sflowtenant.yaml
diff --git a/xos/synchronizers/monitoring_channel/supervisor/monitoring_channel_observer.conf b/xos/onboard/ceilometer/synchronizer/supervisor/monitoring_channel_observer.conf
similarity index 100%
rename from xos/synchronizers/monitoring_channel/supervisor/monitoring_channel_observer.conf
rename to xos/onboard/ceilometer/synchronizer/supervisor/monitoring_channel_observer.conf
diff --git a/xos/synchronizers/monitoring_channel/templates/Dockerfile.monitoring_channel b/xos/onboard/ceilometer/synchronizer/templates/Dockerfile.monitoring_channel
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/Dockerfile.monitoring_channel
rename to xos/onboard/ceilometer/synchronizer/templates/Dockerfile.monitoring_channel
diff --git a/xos/synchronizers/monitoring_channel/templates/Dockerfile.sflowpubsub b/xos/onboard/ceilometer/synchronizer/templates/Dockerfile.sflowpubsub
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/Dockerfile.sflowpubsub
rename to xos/onboard/ceilometer/synchronizer/templates/Dockerfile.sflowpubsub
diff --git a/xos/synchronizers/monitoring_channel/templates/ceilometer_proxy_config.j2 b/xos/onboard/ceilometer/synchronizer/templates/ceilometer_proxy_config.j2
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/ceilometer_proxy_config.j2
rename to xos/onboard/ceilometer/synchronizer/templates/ceilometer_proxy_config.j2
diff --git a/xos/synchronizers/monitoring_channel/templates/ceilometer_proxy_server.py b/xos/onboard/ceilometer/synchronizer/templates/ceilometer_proxy_server.py
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/ceilometer_proxy_server.py
rename to xos/onboard/ceilometer/synchronizer/templates/ceilometer_proxy_server.py
diff --git a/xos/synchronizers/monitoring_channel/templates/monitoring-channel.conf.j2 b/xos/onboard/ceilometer/synchronizer/templates/monitoring-channel.conf.j2
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/monitoring-channel.conf.j2
rename to xos/onboard/ceilometer/synchronizer/templates/monitoring-channel.conf.j2
diff --git a/xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/README b/xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/README
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/README
rename to xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/README
diff --git a/xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/sample_sflow_pub_sub.conf_sample b/xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/sample_sflow_pub_sub.conf_sample
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/sample_sflow_pub_sub.conf_sample
rename to xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/sample_sflow_pub_sub.conf_sample
diff --git a/xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/sflow_pub_sub_config.j2 b/xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/sflow_pub_sub_config.j2
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/sflow_pub_sub_config.j2
rename to xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/sflow_pub_sub_config.j2
diff --git a/xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/sflow_pub_sub_main.py b/xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/sflow_pub_sub_main.py
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/sflow_pub_sub_main.py
rename to xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/sflow_pub_sub_main.py
diff --git a/xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/sflow_sub_records.py b/xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/sflow_sub_records.py
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/sflow_sub_records.py
rename to xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/sflow_sub_records.py
diff --git a/xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/start_sflow_pub_sub b/xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/start_sflow_pub_sub
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/start_sflow_pub_sub
rename to xos/onboard/ceilometer/synchronizer/templates/sflow_pub_sub/start_sflow_pub_sub
diff --git a/xos/synchronizers/monitoring_channel/templates/start-monitoring-channel.sh.j2 b/xos/onboard/ceilometer/synchronizer/templates/start-monitoring-channel.sh.j2
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/start-monitoring-channel.sh.j2
rename to xos/onboard/ceilometer/synchronizer/templates/start-monitoring-channel.sh.j2
diff --git a/xos/synchronizers/monitoring_channel/templates/start_ceilometer_proxy b/xos/onboard/ceilometer/synchronizer/templates/start_ceilometer_proxy
similarity index 100%
rename from xos/synchronizers/monitoring_channel/templates/start_ceilometer_proxy
rename to xos/onboard/ceilometer/synchronizer/templates/start_ceilometer_proxy
diff --git a/xos/services/ceilometer/templates/ceilometeradmin.html b/xos/onboard/ceilometer/templates/ceilometeradmin.html
similarity index 100%
rename from xos/services/ceilometer/templates/ceilometeradmin.html
rename to xos/onboard/ceilometer/templates/ceilometeradmin.html
diff --git a/xos/services/ceilometer/templates/sflowadmin.html b/xos/onboard/ceilometer/templates/sflowadmin.html
similarity index 100%
rename from xos/services/ceilometer/templates/sflowadmin.html
rename to xos/onboard/ceilometer/templates/sflowadmin.html
diff --git a/xos/tosca/resources/ceilometerservice.py b/xos/onboard/ceilometer/tosca/resources/ceilometerservice.py
similarity index 100%
rename from xos/tosca/resources/ceilometerservice.py
rename to xos/onboard/ceilometer/tosca/resources/ceilometerservice.py
diff --git a/xos/tosca/resources/ceilometertenant.py b/xos/onboard/ceilometer/tosca/resources/ceilometertenant.py
similarity index 100%
rename from xos/tosca/resources/ceilometertenant.py
rename to xos/onboard/ceilometer/tosca/resources/ceilometertenant.py
diff --git a/xos/tosca/resources/sflowservice.py b/xos/onboard/ceilometer/tosca/resources/sflowservice.py
similarity index 100%
rename from xos/tosca/resources/sflowservice.py
rename to xos/onboard/ceilometer/tosca/resources/sflowservice.py
diff --git a/xos/onboard/exampleservice/api/tenant/exampletenant.py b/xos/onboard/exampleservice/api/tenant/exampletenant.py
index c50680f..f4778cc 100644
--- a/xos/onboard/exampleservice/api/tenant/exampletenant.py
+++ b/xos/onboard/exampleservice/api/tenant/exampletenant.py
@@ -6,7 +6,6 @@
 from rest_framework import status
 from core.models import *
 from django.forms import widgets
-from services.cord.models import CordSubscriberRoot
 from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
 from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
 
diff --git a/xos/onboard/exampleservice/exampleservice-onboard.yaml b/xos/onboard/exampleservice/exampleservice-onboard.yaml
index 91dbb2e..9999a38 100644
--- a/xos/onboard/exampleservice/exampleservice-onboard.yaml
+++ b/xos/onboard/exampleservice/exampleservice-onboard.yaml
@@ -17,6 +17,7 @@
           admin: admin.py
           synchronizer: synchronizer/manifest
           tosca_custom_types: exampleservice.yaml
+          tosca_resource: tosca/resources/exampleservice.py, tosca/resources/exampletenant.py
           rest_service: api/service/exampleservice.py
           rest_tenant: api/tenant/exampletenant.py
           private_key: file:///opt/xos/key_import/exampleservice_rsa
diff --git a/xos/tosca/resources/exampleservice._unused b/xos/onboard/exampleservice/tosca/resources/exampleservice.py
similarity index 100%
rename from xos/tosca/resources/exampleservice._unused
rename to xos/onboard/exampleservice/tosca/resources/exampleservice.py
diff --git a/xos/tosca/resources/exampletenant._unused b/xos/onboard/exampleservice/tosca/resources/exampletenant.py
similarity index 100%
rename from xos/tosca/resources/exampletenant._unused
rename to xos/onboard/exampleservice/tosca/resources/exampletenant.py
diff --git a/xos/services/fabric/admin.py b/xos/onboard/fabric/admin.py
similarity index 100%
rename from xos/services/fabric/admin.py
rename to xos/onboard/fabric/admin.py
diff --git a/xos/onboard/fabric/fabric-onboard.yaml b/xos/onboard/fabric/fabric-onboard.yaml
new file mode 100644
index 0000000..e0f0fa7
--- /dev/null
+++ b/xos/onboard/fabric/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/onboard/fabric/
+          # 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/services/fabric/models.py b/xos/onboard/fabric/models.py
similarity index 100%
rename from xos/services/fabric/models.py
rename to xos/onboard/fabric/models.py
diff --git a/xos/synchronizers/vtr/vtr-synchronizer.py b/xos/onboard/fabric/synchronizer/fabric-synchronizer.py
similarity index 100%
copy from xos/synchronizers/vtr/vtr-synchronizer.py
copy to xos/onboard/fabric/synchronizer/fabric-synchronizer.py
diff --git a/xos/onboard/fabric/synchronizer/fabric_synchronizer_config b/xos/onboard/fabric/synchronizer/fabric_synchronizer_config
new file mode 100644
index 0000000..2ed56fe
--- /dev/null
+++ b/xos/onboard/fabric/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/onboard/fabric/synchronizer/manifest b/xos/onboard/fabric/synchronizer/manifest
new file mode 100644
index 0000000..62a0722
--- /dev/null
+++ b/xos/onboard/fabric/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/synchronizers/vtr/model-deps b/xos/onboard/fabric/synchronizer/model-deps
similarity index 100%
copy from xos/synchronizers/vtr/model-deps
copy to xos/onboard/fabric/synchronizer/model-deps
diff --git a/xos/onboard/fabric/synchronizer/run.sh b/xos/onboard/fabric/synchronizer/run.sh
new file mode 100755
index 0000000..4e0c214
--- /dev/null
+++ b/xos/onboard/fabric/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/onboard/fabric/synchronizer/start.sh b/xos/onboard/fabric/synchronizer/start.sh
new file mode 100755
index 0000000..8d02bf3
--- /dev/null
+++ b/xos/onboard/fabric/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/onboard/fabric/synchronizer/steps/sync_host.yaml b/xos/onboard/fabric/synchronizer/steps/sync_host.yaml
new file mode 100644
index 0000000..58bccba
--- /dev/null
+++ b/xos/onboard/fabric/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/onboard/fabric/synchronizer/steps/sync_vroutertenant.py b/xos/onboard/fabric/synchronizer/steps/sync_vroutertenant.py
new file mode 100644
index 0000000..fd77ca2
--- /dev/null
+++ b/xos/onboard/fabric/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/onboard/fabric/synchronizer/stop.sh b/xos/onboard/fabric/synchronizer/stop.sh
new file mode 100755
index 0000000..d35b057
--- /dev/null
+++ b/xos/onboard/fabric/synchronizer/stop.sh
@@ -0,0 +1 @@
+pkill -9 -f fabric-synchronizer.py
diff --git a/xos/services/fabric/templates/fabricadmin.html b/xos/onboard/fabric/templates/fabricadmin.html
similarity index 100%
rename from xos/services/fabric/templates/fabricadmin.html
rename to xos/onboard/fabric/templates/fabricadmin.html
diff --git a/xos/tosca/resources/fabricservice.py b/xos/onboard/fabric/tosca/resources/fabricservice.py
similarity index 100%
rename from xos/tosca/resources/fabricservice.py
rename to xos/onboard/fabric/tosca/resources/fabricservice.py
diff --git a/xos/services/onos/admin.py b/xos/onboard/onos/admin.py
similarity index 100%
rename from xos/services/onos/admin.py
rename to xos/onboard/onos/admin.py
diff --git a/xos/api/service/onos.py b/xos/onboard/onos/api/service/onos.py
similarity index 100%
rename from xos/api/service/onos.py
rename to xos/onboard/onos/api/service/onos.py
diff --git a/xos/api/tenant/onos/app.py b/xos/onboard/onos/api/tenant/onos/app.py
similarity index 100%
rename from xos/api/tenant/onos/app.py
rename to xos/onboard/onos/api/tenant/onos/app.py
diff --git a/xos/services/onos/models.py b/xos/onboard/onos/models.py
similarity index 100%
rename from xos/services/onos/models.py
rename to xos/onboard/onos/models.py
diff --git a/xos/onboard/onos/onos-onboard.yaml b/xos/onboard/onos/onos-onboard.yaml
new file mode 100644
index 0000000..1338bb6
--- /dev/null
+++ b/xos/onboard/onos/onos-onboard.yaml
@@ -0,0 +1,27 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    servicecontroller#onos:
+      type: tosca.nodes.ServiceController
+      properties:
+          base_url: file:///opt/xos/onboard/onos/
+          # The following will concatenate with base_url automatically, if
+          # base_url is non-null.
+          models: models.py
+          admin: admin.py
+          admin_template: templates/onosadmin.html
+          synchronizer: synchronizer/manifest
+          synchronizer_run: onos-synchronizer.py
+          #tosca_custom_types: exampleservice.yaml
+          tosca_resource: tosca/resources/onosservice.py, tosca/resources/onosapp.py
+          rest_service: subdirectory:vsg api/service/onos.py
+          rest_tenant: subdirectory:onos api/tenant/onos/app.py
+          private_key: file:///opt/xos/key_import/onos_rsa
+          public_key: file:///opt/xos/key_import/onos_rsa.pub
+
diff --git a/xos/onboard/onos/synchronizer/manifest b/xos/onboard/onos/synchronizer/manifest
new file mode 100644
index 0000000..b96216a
--- /dev/null
+++ b/xos/onboard/onos/synchronizer/manifest
@@ -0,0 +1,16 @@
+manifest
+onos-ext-volt-event-publisher-1.0-SNAPSHOT.oar
+scripts/dockerip.sh
+steps/sync_onosapp.py
+steps/sync_onosapp_nocontainer.yaml
+steps/sync_onosservice.py
+steps/sync_onosservice.yaml
+steps/sync_onosapp.yaml
+onos-ext-notifier-1.0-SNAPSHOT.oar
+start.sh
+stop.sh
+model-deps
+onos_synchronizer_config
+supervisor/onos-observer.conf
+run.sh
+onos-synchronizer.py
diff --git a/xos/synchronizers/onos/model-deps b/xos/onboard/onos/synchronizer/model-deps
similarity index 100%
rename from xos/synchronizers/onos/model-deps
rename to xos/onboard/onos/synchronizer/model-deps
diff --git a/xos/synchronizers/onos/onos-ext-notifier-1.0-SNAPSHOT.oar b/xos/onboard/onos/synchronizer/onos-ext-notifier-1.0-SNAPSHOT.oar
similarity index 100%
rename from xos/synchronizers/onos/onos-ext-notifier-1.0-SNAPSHOT.oar
rename to xos/onboard/onos/synchronizer/onos-ext-notifier-1.0-SNAPSHOT.oar
Binary files differ
diff --git a/xos/synchronizers/onos/onos-ext-volt-event-publisher-1.0-SNAPSHOT.oar b/xos/onboard/onos/synchronizer/onos-ext-volt-event-publisher-1.0-SNAPSHOT.oar
similarity index 100%
rename from xos/synchronizers/onos/onos-ext-volt-event-publisher-1.0-SNAPSHOT.oar
rename to xos/onboard/onos/synchronizer/onos-ext-volt-event-publisher-1.0-SNAPSHOT.oar
Binary files differ
diff --git a/xos/synchronizers/onos/onos-synchronizer.py b/xos/onboard/onos/synchronizer/onos-synchronizer.py
similarity index 100%
rename from xos/synchronizers/onos/onos-synchronizer.py
rename to xos/onboard/onos/synchronizer/onos-synchronizer.py
diff --git a/xos/synchronizers/onos/onos_synchronizer_config b/xos/onboard/onos/synchronizer/onos_synchronizer_config
similarity index 100%
rename from xos/synchronizers/onos/onos_synchronizer_config
rename to xos/onboard/onos/synchronizer/onos_synchronizer_config
diff --git a/xos/synchronizers/onos/run.sh b/xos/onboard/onos/synchronizer/run.sh
similarity index 100%
rename from xos/synchronizers/onos/run.sh
rename to xos/onboard/onos/synchronizer/run.sh
diff --git a/xos/synchronizers/onos/scripts/dockerip.sh b/xos/onboard/onos/synchronizer/scripts/dockerip.sh
similarity index 100%
rename from xos/synchronizers/onos/scripts/dockerip.sh
rename to xos/onboard/onos/synchronizer/scripts/dockerip.sh
diff --git a/xos/synchronizers/onos/start.sh b/xos/onboard/onos/synchronizer/start.sh
similarity index 100%
rename from xos/synchronizers/onos/start.sh
rename to xos/onboard/onos/synchronizer/start.sh
diff --git a/xos/synchronizers/onos/steps/sync_onosapp.py b/xos/onboard/onos/synchronizer/steps/sync_onosapp.py
similarity index 98%
rename from xos/synchronizers/onos/steps/sync_onosapp.py
rename to xos/onboard/onos/synchronizer/steps/sync_onosapp.py
index 3a9abfc..78a8cc8 100644
--- a/xos/synchronizers/onos/steps/sync_onosapp.py
+++ b/xos/onboard/onos/synchronizer/steps/sync_onosapp.py
@@ -18,7 +18,7 @@
 from xos.logger import Logger, logging
 from services.vrouter.models import VRouterService
 from services.vtn.models import VTNService
-from services.cord.models import VOLTService, VOLTDevice, AccessDevice
+from services.volt.models import VOLTService, VOLTDevice, AccessDevice
 
 # hpclibrary will be in steps/..
 parentdir = os.path.join(os.path.dirname(__file__),"..")
@@ -31,7 +31,7 @@
     observes=ONOSApp
     requested_interval=0
     template_name = "sync_onosapp.yaml"
-    service_key_name = "/opt/xos/synchronizers/onos/onos_key"
+    #service_key_name = "/opt/xos/synchronizers/onos/onos_key"
 
     def __init__(self, *args, **kwargs):
         super(SyncONOSApp, self).__init__(*args, **kwargs)
diff --git a/xos/synchronizers/onos/steps/sync_onosapp.yaml b/xos/onboard/onos/synchronizer/steps/sync_onosapp.yaml
similarity index 100%
rename from xos/synchronizers/onos/steps/sync_onosapp.yaml
rename to xos/onboard/onos/synchronizer/steps/sync_onosapp.yaml
diff --git a/xos/synchronizers/onos/steps/sync_onosapp_nocontainer.yaml b/xos/onboard/onos/synchronizer/steps/sync_onosapp_nocontainer.yaml
similarity index 100%
rename from xos/synchronizers/onos/steps/sync_onosapp_nocontainer.yaml
rename to xos/onboard/onos/synchronizer/steps/sync_onosapp_nocontainer.yaml
diff --git a/xos/synchronizers/onos/steps/sync_onosservice.py b/xos/onboard/onos/synchronizer/steps/sync_onosservice.py
similarity index 97%
rename from xos/synchronizers/onos/steps/sync_onosservice.py
rename to xos/onboard/onos/synchronizer/steps/sync_onosservice.py
index 2e6acd9..ce446cf 100644
--- a/xos/synchronizers/onos/steps/sync_onosservice.py
+++ b/xos/onboard/onos/synchronizer/steps/sync_onosservice.py
@@ -24,7 +24,7 @@
     observes=ONOSService
     requested_interval=0
     template_name = "sync_onosservice.yaml"
-    service_key_name = "/opt/xos/synchronizers/onos/onos_key"
+    #service_key_name = "/opt/xos/synchronizers/onos/onos_key"
 
     def __init__(self, *args, **kwargs):
         super(SyncONOSService, self).__init__(*args, **kwargs)
diff --git a/xos/synchronizers/onos/steps/sync_onosservice.yaml b/xos/onboard/onos/synchronizer/steps/sync_onosservice.yaml
similarity index 100%
rename from xos/synchronizers/onos/steps/sync_onosservice.yaml
rename to xos/onboard/onos/synchronizer/steps/sync_onosservice.yaml
diff --git a/xos/synchronizers/onos/stop.sh b/xos/onboard/onos/synchronizer/stop.sh
similarity index 100%
rename from xos/synchronizers/onos/stop.sh
rename to xos/onboard/onos/synchronizer/stop.sh
diff --git a/xos/synchronizers/onos/supervisor/onos-observer.conf b/xos/onboard/onos/synchronizer/supervisor/onos-observer.conf
similarity index 100%
rename from xos/synchronizers/onos/supervisor/onos-observer.conf
rename to xos/onboard/onos/synchronizer/supervisor/onos-observer.conf
diff --git a/xos/services/onos/templates/onosadmin.html b/xos/onboard/onos/templates/onosadmin.html
similarity index 100%
rename from xos/services/onos/templates/onosadmin.html
rename to xos/onboard/onos/templates/onosadmin.html
diff --git a/xos/tosca/resources/onosapp.py b/xos/onboard/onos/tosca/resources/onosapp.py
similarity index 100%
rename from xos/tosca/resources/onosapp.py
rename to xos/onboard/onos/tosca/resources/onosapp.py
diff --git a/xos/tosca/resources/onosservice.py b/xos/onboard/onos/tosca/resources/onosservice.py
similarity index 100%
rename from xos/tosca/resources/onosservice.py
rename to xos/onboard/onos/tosca/resources/onosservice.py
diff --git a/xos/onboard/volt/admin.py b/xos/onboard/volt/admin.py
new file mode 100644
index 0000000..cf5dfa6
--- /dev/null
+++ b/xos/onboard/volt/admin.py
@@ -0,0 +1,237 @@
+from django.contrib import admin
+
+from services.volt.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.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
+
+#-----------------------------------------------------------------------------
+# vOLT
+#-----------------------------------------------------------------------------
+
+class VOLTServiceAdmin(ReadOnlyAwareAdmin):
+    model = VOLTService
+    verbose_name = "vOLT Service"
+    verbose_name_plural = "vOLT Service"
+    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" ], 'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text', )
+    inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline]
+
+    extracontext_registered_admins = True
+
+    user_readonly_fields = ["name", "enabled", "versionNumber", "description"]
+
+    suit_form_tabs =(('general', 'vOLT Service Details'),
+        ('administration', 'Administration'),
+        #('tools', 'Tools'),
+        ('slices','Slices'),
+        ('serviceattrs','Additional Attributes'),
+        ('serviceprivileges','Privileges'),
+    )
+
+    suit_form_includes = (('voltadmin.html', 'top', 'administration'),
+                           ) #('hpctools.html', 'top', 'tools') )
+
+    def queryset(self, request):
+        return VOLTService.get_service_objects_by_user(request.user)
+
+class VOLTTenantForm(forms.ModelForm):
+    s_tag = forms.CharField()
+    c_tag = forms.CharField()
+    creator = forms.ModelChoiceField(queryset=User.objects.all())
+
+    def __init__(self,*args,**kwargs):
+        super (VOLTTenantForm,self ).__init__(*args,**kwargs)
+        self.fields['kind'].widget.attrs['readonly'] = True
+        self.fields['provider_service'].queryset = VOLTService.get_service_objects().all()
+        if self.instance:
+            # fields for the attributes
+            self.fields['c_tag'].initial = self.instance.c_tag
+            self.fields['s_tag'].initial = self.instance.s_tag
+            self.fields['creator'].initial = self.instance.creator
+        if (not self.instance) or (not self.instance.pk):
+            # default fields for an 'add' form
+            self.fields['kind'].initial = VOLT_KIND
+            self.fields['creator'].initial = get_request().user
+            if VOLTService.get_service_objects().exists():
+               self.fields["provider_service"].initial = VOLTService.get_service_objects().all()[0]
+
+    def save(self, commit=True):
+        self.instance.s_tag = self.cleaned_data.get("s_tag")
+        self.instance.c_tag = self.cleaned_data.get("c_tag")
+        self.instance.creator = self.cleaned_data.get("creator")
+        return super(VOLTTenantForm, self).save(commit=commit)
+
+    class Meta:
+        model = VOLTTenant
+
+class VOLTTenantAdmin(ReadOnlyAwareAdmin):
+    list_display = ('backend_status_icon', 'id', 'service_specific_id', 's_tag', 'c_tag', 'subscriber_root' )
+    list_display_links = ('backend_status_icon', 'id')
+    fieldsets = [ (None, {'fields': ['backend_status_text', 'kind', 'provider_service', 'subscriber_root', 'service_specific_id', # 'service_specific_attribute',
+                                     's_tag', 'c_tag', 'creator'],
+                          'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text', 'service_specific_attribute')
+    form = VOLTTenantForm
+
+    suit_form_tabs = (('general','Details'),)
+
+    def queryset(self, request):
+        return VOLTTenant.get_tenant_objects_by_user(request.user)
+
+class AccessDeviceInline(XOSTabularInline):
+    model = AccessDevice
+    fields = ['volt_device','uplink','vlan']
+    readonly_fields = []
+    extra = 0
+#    max_num = 0
+    suit_classes = 'suit-tab suit-tab-accessdevices'
+
+#    @property
+#    def selflink_reverse_path(self):
+#        return "admin:cord_volttenant_change"
+
+class VOLTDeviceAdmin(ReadOnlyAwareAdmin):
+    list_display = ('backend_status_icon', 'name', 'openflow_id', 'driver' )
+    list_display_links = ('backend_status_icon', 'name', 'openflow_id')
+    fieldsets = [ (None, {'fields': ['backend_status_text','name','volt_service','openflow_id','driver','access_agent'],
+                          'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text',)
+    inlines = [AccessDeviceInline]
+
+    suit_form_tabs = (('general','Details'), ('accessdevices','Access Devices'))
+
+class AccessDeviceAdmin(ReadOnlyAwareAdmin):
+    list_display = ('backend_status_icon', 'id', 'volt_device', 'uplink', 'vlan' )
+    list_display_links = ('backend_status_icon', 'id')
+    fieldsets = [ (None, {'fields': ['backend_status_text','volt_device','uplink','vlan'],
+                          'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text',)
+
+    suit_form_tabs = (('general','Details'),)
+
+class AgentPortMappingInline(XOSTabularInline):
+    model = AgentPortMapping
+    fields = ['access_agent', 'mac', 'port']
+    readonly_fields = []
+    extra = 0
+#    max_num = 0
+    suit_classes = 'suit-tab suit-tab-accessportmaps'
+
+#    @property
+#    def selflink_reverse_path(self):
+#        return "admin:cord_volttenant_change"
+
+class AccessAgentAdmin(ReadOnlyAwareAdmin):
+    list_display = ('backend_status_icon', 'name', 'mac' )
+    list_display_links = ('backend_status_icon', 'name')
+    fieldsets = [ (None, {'fields': ['backend_status_text','name','volt_service','mac'],
+                          'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text',)
+    inlines= [AgentPortMappingInline]
+
+    suit_form_tabs = (('general','Details'), ('accessportmaps', 'Port Mappings'))
+
+# -------------------------------------------
+# CORDSubscriberRoot
+# -------------------------------------------
+
+class VOLTTenantInline(XOSTabularInline):
+    model = VOLTTenant
+    fields = ['provider_service', 'subscriber_root', 'service_specific_id']
+    readonly_fields = ['provider_service', 'subscriber_root', 'service_specific_id']
+    extra = 0
+    max_num = 0
+    suit_classes = 'suit-tab suit-tab-volttenants'
+    fk_name = 'subscriber_root'
+    verbose_name = 'subscribed tenant'
+    verbose_name_plural = 'subscribed tenants'
+
+    @property
+    def selflink_reverse_path(self):
+        return "admin:cord_volttenant_change"
+
+    def queryset(self, request):
+        qs = super(VOLTTenantInline, self).queryset(request)
+        return qs.filter(kind=VOLT_KIND)
+
+class CordSubscriberRootForm(forms.ModelForm):
+    url_filter_level = forms.CharField(required = False)
+    uplink_speed = forms.CharField(required = False)
+    downlink_speed = forms.CharField(required = False)
+    status = forms.ChoiceField(choices=CordSubscriberRoot.status_choices, required=True)
+    enable_uverse = forms.BooleanField(required=False)
+    cdn_enable = forms.BooleanField(required=False)
+
+    def __init__(self,*args,**kwargs):
+        super (CordSubscriberRootForm,self ).__init__(*args,**kwargs)
+        self.fields['kind'].widget.attrs['readonly'] = True
+        if self.instance:
+            self.fields['url_filter_level'].initial = self.instance.url_filter_level
+            self.fields['uplink_speed'].initial = self.instance.uplink_speed
+            self.fields['downlink_speed'].initial = self.instance.downlink_speed
+            self.fields['status'].initial = self.instance.status
+            self.fields['enable_uverse'].initial = self.instance.enable_uverse
+            self.fields['cdn_enable'].initial = self.instance.cdn_enable
+        if (not self.instance) or (not self.instance.pk):
+            # default fields for an 'add' form
+            self.fields['kind'].initial = CORD_SUBSCRIBER_KIND
+            self.fields['uplink_speed'].initial = CordSubscriberRoot.get_default_attribute("uplink_speed")
+            self.fields['downlink_speed'].initial = CordSubscriberRoot.get_default_attribute("downlink_speed")
+            self.fields['status'].initial = CordSubscriberRoot.get_default_attribute("status")
+            self.fields['enable_uverse'].initial = CordSubscriberRoot.get_default_attribute("enable_uverse")
+            self.fields['cdn_enable'].initial = CordSubscriberRoot.get_default_attribute("cdn_enable")
+
+    def save(self, commit=True):
+        self.instance.url_filter_level = self.cleaned_data.get("url_filter_level")
+        self.instance.uplink_speed = self.cleaned_data.get("uplink_speed")
+        self.instance.downlink_speed = self.cleaned_data.get("downlink_speed")
+        self.instance.status = self.cleaned_data.get("status")
+        self.instance.enable_uverse = self.cleaned_data.get("enable_uverse")
+        self.instance.cdn_enable = self.cleaned_data.get("cdn_enable")
+        return super(CordSubscriberRootForm, self).save(commit=commit)
+
+    class Meta:
+        model = CordSubscriberRoot
+
+class CordSubscriberRootAdmin(ReadOnlyAwareAdmin):
+    list_display = ('backend_status_icon', 'id',  'name', )
+    list_display_links = ('backend_status_icon', 'id', 'name', )
+    fieldsets = [ (None, {'fields': ['backend_status_text', 'kind', 'name', 'service_specific_id', # 'service_specific_attribute',
+                                     'url_filter_level', "uplink_speed", "downlink_speed", "status", "enable_uverse", "cdn_enable"],
+                          'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text', 'service_specific_attribute',)
+    form = CordSubscriberRootForm
+    inlines = (VOLTTenantInline, TenantRootPrivilegeInline)
+
+    suit_form_tabs =(('general', 'Cord Subscriber Root Details'),
+        ('volttenants','VOLT Tenancy'),
+        ('tenantrootprivileges','Privileges')
+    )
+
+    def queryset(self, request):
+        return CordSubscriberRoot.get_tenant_objects_by_user(request.user)
+
+admin.site.register(VOLTService, VOLTServiceAdmin)
+admin.site.register(VOLTTenant, VOLTTenantAdmin)
+admin.site.register(VOLTDevice, VOLTDeviceAdmin)
+admin.site.register(AccessDevice, AccessDeviceAdmin)
+admin.site.register(AccessAgent, AccessAgentAdmin)
+
+admin.site.register(CordSubscriberRoot, CordSubscriberRootAdmin)
+
diff --git a/xos/api/tenant/cord/subscriber.py b/xos/onboard/volt/api/tenant/cord/subscriber.py
similarity index 99%
rename from xos/api/tenant/cord/subscriber.py
rename to xos/onboard/volt/api/tenant/cord/subscriber.py
index eab6cb3..52f9b63 100644
--- a/xos/api/tenant/cord/subscriber.py
+++ b/xos/onboard/volt/api/tenant/cord/subscriber.py
@@ -10,7 +10,7 @@
 from core.models import *
 from django.forms import widgets
 from django.conf.urls import patterns, url
-from services.cord.models import VOLTTenant, VBNGTenant, CordSubscriberRoot
+from services.volt.models import VOLTTenant, CordSubscriberRoot
 from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
 from django.shortcuts import get_object_or_404
 from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
diff --git a/xos/api/tenant/cord/volt.py b/xos/onboard/volt/api/tenant/cord/volt.py
similarity index 97%
rename from xos/api/tenant/cord/volt.py
rename to xos/onboard/volt/api/tenant/cord/volt.py
index e17cf26..5c9634a 100644
--- a/xos/api/tenant/cord/volt.py
+++ b/xos/onboard/volt/api/tenant/cord/volt.py
@@ -6,7 +6,7 @@
 from rest_framework import status
 from core.models import *
 from django.forms import widgets
-from services.cord.models import VOLTTenant, VOLTService, CordSubscriberRoot
+from services.volt.models import VOLTTenant, VOLTService, CordSubscriberRoot
 from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
 from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
 
diff --git a/xos/onboard/volt/models.py b/xos/onboard/volt/models.py
new file mode 100644
index 0000000..8f3cc1f
--- /dev/null
+++ b/xos/onboard/volt/models.py
@@ -0,0 +1,367 @@
+from django.db import models
+from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber, NetworkParameter, NetworkParameterType, Port, AddressPool, User
+from core.models.plcorebase import StrippedCharField
+import os
+from django.db import models, transaction
+from django.forms.models import model_to_dict
+from django.db.models import Q
+from operator import itemgetter, attrgetter, methodcaller
+from core.models import Tag
+from core.models.service import LeastLoadedNodeScheduler
+from services.vrouter.models import VRouterService, VRouterTenant
+import traceback
+from xos.exceptions import *
+from xos.config import Config
+
+class ConfigurationError(Exception):
+    pass
+
+VOLT_KIND = "vOLT"
+CORD_SUBSCRIBER_KIND = "CordSubscriberRoot"
+
+CORD_USE_VTN = getattr(Config(), "networking_use_vtn", False)
+
+# -------------------------------------------
+# CordSubscriberRoot
+# -------------------------------------------
+
+class CordSubscriberRoot(Subscriber):
+    class Meta:
+        proxy = True
+
+    KIND = CORD_SUBSCRIBER_KIND
+
+    status_choices = (("enabled", "Enabled"),
+                      ("suspended", "Suspended"),
+                      ("delinquent", "Delinquent"),
+                      ("copyrightviolation", "Copyright Violation"))
+
+    # 'simple_attributes' will be expanded into properties and setters that
+    # store the attribute using self.set_attribute / self.get_attribute.
+
+    simple_attributes = ( ("firewall_enable", False),
+                          ("firewall_rules", "accept all anywhere anywhere"),
+                          ("url_filter_enable", False),
+                          ("url_filter_rules", "allow all"),
+                          ("url_filter_level", "PG"),
+                          ("cdn_enable", False),
+                          ("devices", []),
+                          ("is_demo_user", False),
+
+                          ("uplink_speed", 1000000000),  # 1 gigabit, a reasonable default?
+                          ("downlink_speed", 1000000000),
+                          ("enable_uverse", True) )
+
+    default_attributes = {"status": "enabled"}
+
+    sync_attributes = ("firewall_enable",
+                       "firewall_rules",
+                       "url_filter_enable",
+                       "url_filter_rules",
+                       "cdn_enable",
+                       "uplink_speed",
+                       "downlink_speed",
+                       "enable_uverse",
+                       "status")
+
+    def __init__(self, *args, **kwargs):
+        super(CordSubscriberRoot, self).__init__(*args, **kwargs)
+        self.cached_volt = None
+        self._initial_url_filter_enable = self.url_filter_enable
+
+    @property
+    def volt(self):
+        volt = self.get_newest_subscribed_tenant(VOLTTenant)
+        if not volt:
+            return None
+
+        # always return the same object when possible
+        if (self.cached_volt) and (self.cached_volt.id == volt.id):
+            return self.cached_volt
+
+        #volt.caller = self.creator
+        self.cached_volt = volt
+        return volt
+
+    @property
+    def status(self):
+        return self.get_attribute("status", self.default_attributes["status"])
+
+    @status.setter
+    def status(self, value):
+        if not value in [x[0] for x in self.status_choices]:
+            raise Exception("invalid status %s" % value)
+        self.set_attribute("status", value)
+
+    def find_device(self, mac):
+        for device in self.devices:
+            if device["mac"] == mac:
+                return device
+        return None
+
+    def update_device(self, mac, **kwargs):
+        # kwargs may be "level" or "mac"
+        #    Setting one of these to None will cause None to be stored in the db
+        devices = self.devices
+        for device in devices:
+            if device["mac"] == mac:
+                for arg in kwargs.keys():
+                    device[arg] = kwargs[arg]
+                self.devices = devices
+                return device
+        raise ValueError("Device with mac %s not found" % mac)
+
+    def create_device(self, **kwargs):
+        if "mac" not in kwargs:
+            raise XOSMissingField("The mac field is required")
+
+        if self.find_device(kwargs['mac']):
+                raise XOSDuplicateKey("Device with mac %s already exists" % kwargs["mac"])
+
+        device = kwargs.copy()
+
+        devices = self.devices
+        devices.append(device)
+        self.devices = devices
+
+        return device
+
+    def delete_device(self, mac):
+        devices = self.devices
+        for device in devices:
+            if device["mac"]==mac:
+                devices.remove(device)
+                self.devices = devices
+                return
+
+        raise ValueError("Device with mac %s not found" % mac)
+
+    #--------------------------------------------------------------------------
+    # Deprecated -- devices used to be called users
+
+    def find_user(self, uid):
+        return self.find_device(uid)
+
+    def update_user(self, uid, **kwargs):
+        return self.update_device(uid, **kwargs)
+
+    def create_user(self, **kwargs):
+        return self.create_device(**kwargs)
+
+    def delete_user(self, uid):
+        return self.delete_user(uid)
+
+    # ------------------------------------------------------------------------
+
+    @property
+    def services(self):
+        return {"cdn": self.cdn_enable,
+                "url_filter": self.url_filter_enable,
+                "firewall": self.firewall_enable}
+
+    @services.setter
+    def services(self, value):
+        pass
+
+    def save(self, *args, **kwargs):
+        self.validate_unique_service_specific_id(none_okay=True)
+        if (not hasattr(self, 'caller') or not self.caller.is_admin):
+            if (self.has_field_changed("service_specific_id")):
+                raise XOSPermissionDenied("You do not have permission to change service_specific_id")
+        super(CordSubscriberRoot, self).save(*args, **kwargs)
+        if (self.volt) and (self.volt.vcpe): # and (self._initial_url_filter_enabled != self.url_filter_enable):
+            # 1) trigger manage_bbs_account to run
+            # 2) trigger vcpe observer to wake up
+            self.volt.vcpe.save()
+
+CordSubscriberRoot.setup_simple_attributes()
+
+# -------------------------------------------
+# VOLT
+# -------------------------------------------
+
+class VOLTService(Service):
+    KIND = VOLT_KIND
+
+    class Meta:
+        app_label = "volt"
+        verbose_name = "vOLT Service"
+
+class VOLTTenant(Tenant):
+    KIND = VOLT_KIND
+
+    class Meta:
+        app_label = "volt"
+        verbose_name = "vOLT Tenant"
+
+    s_tag = models.IntegerField(null=True, blank=True, help_text="s-tag")
+    c_tag = models.IntegerField(null=True, blank=True, help_text="c-tag")
+
+    # at some point, this should probably end up part of Tenant.
+    creator = models.ForeignKey(User, related_name='created_volts', blank=True, null=True)
+
+    def __init__(self, *args, **kwargs):
+        volt_services = VOLTService.get_service_objects().all()
+        if volt_services:
+            self._meta.get_field("provider_service").default = volt_services[0].id
+        super(VOLTTenant, self).__init__(*args, **kwargs)
+        self.cached_vcpe = None
+
+    @property
+    def vcpe(self):
+        from services.vsg.models import VSGTenant
+        vcpe = self.get_newest_subscribed_tenant(VSGTenant)
+        if not vcpe:
+            return None
+
+        # always return the same object when possible
+        if (self.cached_vcpe) and (self.cached_vcpe.id == vcpe.id):
+            return self.cached_vcpe
+
+        vcpe.caller = self.creator
+        self.cached_vcpe = vcpe
+        return vcpe
+
+    @vcpe.setter
+    def vcpe(self, value):
+        raise XOSConfigurationError("vOLT.vCPE cannot be set this way -- create a new vCPE object and set its subscriber_tenant instead")
+
+    @property
+    def subscriber(self):
+        if not self.subscriber_root:
+            return None
+        subs = CordSubscriberRoot.objects.filter(id=self.subscriber_root.id)
+        if not subs:
+            return None
+        return subs[0]
+
+    def manage_vcpe(self):
+        # Each VOLT object owns exactly one VCPE object
+
+        if self.deleted:
+            return
+
+        if self.vcpe is None:
+            from services.vsg.models import VSGService, VSGTenant
+            vsgServices = VSGService.get_service_objects().all()
+            if not vsgServices:
+                raise XOSConfigurationError("No VSG Services available")
+
+            vcpe = VSGTenant(provider_service = vsgServices[0],
+                              subscriber_tenant = self)
+            vcpe.caller = self.creator
+            vcpe.save()
+
+    def manage_subscriber(self):
+        if (self.subscriber_root is None):
+            # The vOLT is not connected to a Subscriber, so either find an
+            # existing subscriber with the same SSID, or autogenerate a new
+            # subscriber.
+            #
+            # TODO: This probably goes away when we rethink the ONOS-to-XOS
+            # vOLT API.
+
+            subs = CordSubscriberRoot.get_tenant_objects().filter(service_specific_id = self.service_specific_id)
+            if subs:
+                sub = subs[0]
+            else:
+                sub = CordSubscriberRoot(service_specific_id = self.service_specific_id,
+                                         name = "autogenerated-for-vOLT-%s" % self.id)
+                sub.save()
+            self.subscriber_root = sub
+            self.save()
+
+    def cleanup_vcpe(self):
+        if self.vcpe:
+            # print "XXX cleanup vcpe", self.vcpe
+            self.vcpe.delete()
+
+    def cleanup_orphans(self):
+        from services.vsg.models import VSGTenant
+        # ensure vOLT only has one vCPE
+        cur_vcpe = self.vcpe
+        for vcpe in list(self.get_subscribed_tenants(VSGTenant)):
+            if (not cur_vcpe) or (vcpe.id != cur_vcpe.id):
+                # print "XXX clean up orphaned vcpe", vcpe
+                vcpe.delete()
+
+    def save(self, *args, **kwargs):
+        # VOLTTenant probably doesn't need a SSID anymore; that will be handled
+        # by CORDSubscriberRoot...
+        # self.validate_unique_service_specific_id()
+
+        if (self.subscriber_root is not None):
+            subs = self.subscriber_root.get_subscribed_tenants(VOLTTenant)
+            if (subs) and (self not in subs):
+                raise XOSDuplicateKey("Subscriber should only be linked to one vOLT")
+
+        if not self.creator:
+            if not getattr(self, "caller", None):
+                # caller must be set when creating a vCPE since it creates a slice
+                raise XOSProgrammingError("VOLTTenant's self.caller was not set")
+            self.creator = self.caller
+            if not self.creator:
+                raise XOSProgrammingError("VOLTTenant's self.creator was not set")
+
+        super(VOLTTenant, self).save(*args, **kwargs)
+        model_policy_volt(self.pk)
+
+    def delete(self, *args, **kwargs):
+        self.cleanup_vcpe()
+        super(VOLTTenant, self).delete(*args, **kwargs)
+
+def model_policy_volt(pk):
+    # TODO: this should be made in to a real model_policy
+    with transaction.atomic():
+        volt = VOLTTenant.objects.select_for_update().filter(pk=pk)
+        if not volt:
+            return
+        volt = volt[0]
+        volt.manage_vcpe()
+        volt.manage_subscriber()
+        volt.cleanup_orphans()
+
+class VOLTDevice(PlCoreBase):
+    class Meta:
+        app_label = "volt"
+
+    name = models.CharField(max_length=254, help_text="name of device", null=False, blank=False)
+    volt_service = models.ForeignKey(VOLTService, related_name='volt_devices')
+    openflow_id = models.CharField(max_length=254, help_text="OpenFlow ID", null=True, blank=True)
+    driver = models.CharField(max_length=254, help_text="driver", null=True, blank=True)
+    access_agent = models.ForeignKey("AccessAgent", related_name='volt_devices', blank=True, null=True)
+
+    def __unicode__(self): return u'%s' % (self.name)
+
+class AccessDevice(PlCoreBase):
+    class Meta:
+        app_label = "volt"
+
+    volt_device = models.ForeignKey(VOLTDevice, related_name='access_devices')
+    uplink = models.IntegerField(null=True, blank=True)
+    vlan = models.IntegerField(null=True, blank=True)
+
+    def __unicode__(self): return u'%s-%d:%d' % (self.volt_device.name,self.uplink,self.vlan)
+
+class AccessAgent(PlCoreBase):
+    class Meta:
+        app_label = "volt"
+
+    name = models.CharField(max_length=254, help_text="name of agent", null=False, blank=False)
+    volt_service = models.ForeignKey(VOLTService, related_name='access_agents')
+    mac = models.CharField(max_length=32, help_text="MAC Address or Access Agent", null=True, blank=True)
+
+    def __unicode__(self): return u'%s' % (self.name)
+
+class AgentPortMapping(PlCoreBase):
+    class Meta:
+        app_label = "volt"
+
+    access_agent = models.ForeignKey(AccessAgent, related_name='port_mappings')
+    mac = models.CharField(max_length=32, help_text="MAC Address", null=True, blank=True)
+    port = models.CharField(max_length=32, help_text="Openflow port ID", null=True, blank=True)
+
+    def __unicode__(self): return u'%s-%s-%s' % (self.access_agent.name, self.port, self.mac)
+
+
+
diff --git a/xos/services/cord/templates/voltadmin.html b/xos/onboard/volt/templates/voltadmin.html
similarity index 100%
rename from xos/services/cord/templates/voltadmin.html
rename to xos/onboard/volt/templates/voltadmin.html
diff --git a/xos/tosca/resources/CORDSubscriber.py b/xos/onboard/volt/tosca/resources/CORDSubscriber.py
similarity index 93%
rename from xos/tosca/resources/CORDSubscriber.py
rename to xos/onboard/volt/tosca/resources/CORDSubscriber.py
index f013032..5cdb2ef 100644
--- a/xos/tosca/resources/CORDSubscriber.py
+++ b/xos/onboard/volt/tosca/resources/CORDSubscriber.py
@@ -7,7 +7,7 @@
 import pdb
 
 from core.models import User, TenantRootPrivilege, TenantRootRole
-from services.cord.models import CordSubscriberRoot
+from services.volt.models import CordSubscriberRoot
 
 from xosresource import XOSResource
 
diff --git a/xos/tosca/resources/CORDUser.py b/xos/onboard/volt/tosca/resources/CORDUser.py
similarity index 96%
rename from xos/tosca/resources/CORDUser.py
rename to xos/onboard/volt/tosca/resources/CORDUser.py
index ff2dc8f..d1ae1cc 100644
--- a/xos/tosca/resources/CORDUser.py
+++ b/xos/onboard/volt/tosca/resources/CORDUser.py
@@ -7,7 +7,7 @@
 import pdb
 
 from core.models import User
-from services.cord.models import CordSubscriberRoot
+from services.volt.models import CordSubscriberRoot
 
 from xosresource import XOSResource
 
diff --git a/xos/tosca/resources/VOLTTenant.py b/xos/onboard/volt/tosca/resources/VOLTTenant.py
similarity index 96%
rename from xos/tosca/resources/VOLTTenant.py
rename to xos/onboard/volt/tosca/resources/VOLTTenant.py
index ae1692d..cbc3837 100644
--- a/xos/tosca/resources/VOLTTenant.py
+++ b/xos/onboard/volt/tosca/resources/VOLTTenant.py
@@ -7,7 +7,7 @@
 import pdb
 
 from core.models import User
-from services.cord.models import VOLTTenant, VOLTService, CordSubscriberRoot, VOLT_KIND
+from services.volt.models import VOLTTenant, VOLTService, CordSubscriberRoot, VOLT_KIND
 
 from xosresource import XOSResource
 
diff --git a/xos/tosca/resources/accessagent.py b/xos/onboard/volt/tosca/resources/accessagent.py
similarity index 96%
rename from xos/tosca/resources/accessagent.py
rename to xos/onboard/volt/tosca/resources/accessagent.py
index 368ce55..e40a1cb 100644
--- a/xos/tosca/resources/accessagent.py
+++ b/xos/onboard/volt/tosca/resources/accessagent.py
@@ -5,7 +5,7 @@
 sys.path.append("/opt/tosca")
 from translator.toscalib.tosca_template import ToscaTemplate
 
-from services.cord.models import AccessAgent, VOLTDevice, VOLTService, AgentPortMapping
+from services.volt.models import AccessAgent, VOLTDevice, VOLTService, AgentPortMapping
 from xosresource import XOSResource
 
 class XOSAccessAgent(XOSResource):
diff --git a/xos/tosca/resources/accessdevice.py b/xos/onboard/volt/tosca/resources/accessdevice.py
similarity index 95%
rename from xos/tosca/resources/accessdevice.py
rename to xos/onboard/volt/tosca/resources/accessdevice.py
index 94deb86..f31b37a 100644
--- a/xos/tosca/resources/accessdevice.py
+++ b/xos/onboard/volt/tosca/resources/accessdevice.py
@@ -5,7 +5,7 @@
 sys.path.append("/opt/tosca")
 from translator.toscalib.tosca_template import ToscaTemplate
 
-from services.cord.models import AccessDevice, VOLTDevice
+from services.volt.models import AccessDevice, VOLTDevice
 from xosresource import XOSResource
 
 class XOSAccessDevice(XOSResource):
diff --git a/xos/tosca/resources/voltdevice.py b/xos/onboard/volt/tosca/resources/voltdevice.py
similarity index 96%
rename from xos/tosca/resources/voltdevice.py
rename to xos/onboard/volt/tosca/resources/voltdevice.py
index f1c6830..9665b85 100644
--- a/xos/tosca/resources/voltdevice.py
+++ b/xos/onboard/volt/tosca/resources/voltdevice.py
@@ -5,7 +5,7 @@
 sys.path.append("/opt/tosca")
 from translator.toscalib.tosca_template import ToscaTemplate
 
-from services.cord.models import VOLTDevice, VOLTService, AccessDevice, AccessAgent
+from services.volt.models import VOLTDevice, VOLTService, AccessDevice, AccessAgent
 from xosresource import XOSResource
 
 class XOSVOLTDevice(XOSResource):
diff --git a/xos/tosca/resources/voltservice.py b/xos/onboard/volt/tosca/resources/voltservice.py
similarity index 89%
rename from xos/tosca/resources/voltservice.py
rename to xos/onboard/volt/tosca/resources/voltservice.py
index 57cf846..9df4259 100644
--- a/xos/tosca/resources/voltservice.py
+++ b/xos/onboard/volt/tosca/resources/voltservice.py
@@ -5,7 +5,7 @@
 sys.path.append("/opt/tosca")
 from translator.toscalib.tosca_template import ToscaTemplate
 
-from services.cord.models import VOLTService
+from services.volt.models import VOLTService
 
 from service import XOSService
 
diff --git a/xos/onboard/volt/volt-onboard.yaml b/xos/onboard/volt/volt-onboard.yaml
new file mode 100644
index 0000000..e91ea93
--- /dev/null
+++ b/xos/onboard/volt/volt-onboard.yaml
@@ -0,0 +1,24 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    servicecontroller#volt:
+      type: tosca.nodes.ServiceController
+      properties:
+          base_url: file:///opt/xos/onboard/volt/
+          # The following will concatenate with base_url automatically, if
+          # base_url is non-null.
+          models: models.py
+          admin: admin.py
+          admin_template: templates/voltadmin.html
+          #synchronizer: synchronizer/manifest
+          tosca_resource: tosca/resources/voltdevice.py, tosca/resources/voltservice.py, tosca/resources/CORDSubscriber.py, tosca/resources/CORDUser.py, tosca/resources/VOLTTenant.py, tosca/resources/accessagent.py, tosca/resources/accessdevice.py
+          rest_tenant: subdirectory:cord api/tenant/cord/volt.py, subdirectory:cord api/tenant/cord/subscriber.py
+          private_key: file:///opt/xos/key_import/volt_rsa
+          public_key: file:///opt/xos/key_import/volt_rsa.pub
+
diff --git a/xos/services/vrouter/admin.py b/xos/onboard/vrouter/admin.py
similarity index 100%
rename from xos/services/vrouter/admin.py
rename to xos/onboard/vrouter/admin.py
diff --git a/xos/services/vrouter/models.py b/xos/onboard/vrouter/models.py
similarity index 96%
rename from xos/services/vrouter/models.py
rename to xos/onboard/vrouter/models.py
index 05b57e2..d302b13 100644
--- a/xos/services/vrouter/models.py
+++ b/xos/onboard/vrouter/models.py
@@ -15,8 +15,12 @@
 class ConfigurationError(Exception):
     pass
 
+
 VROUTER_KIND = "vROUTER"
 
+# NOTE: don't change VROUTER_KIND unless you also change the reference to it
+#   in tosca/resources/network.py
+
 CORD_USE_VTN = getattr(Config(), "networking_use_vtn", False)
 
 class VRouterService(Service):
diff --git a/xos/services/vrouter/templates/vrouteradmin.html b/xos/onboard/vrouter/templates/vrouteradmin.html
similarity index 100%
rename from xos/services/vrouter/templates/vrouteradmin.html
rename to xos/onboard/vrouter/templates/vrouteradmin.html
diff --git a/xos/tosca/resources/vrouterservice.py b/xos/onboard/vrouter/tosca/resources/vrouterservice.py
similarity index 100%
rename from xos/tosca/resources/vrouterservice.py
rename to xos/onboard/vrouter/tosca/resources/vrouterservice.py
diff --git a/xos/onboard/vrouter/vrouter-onboard.yaml b/xos/onboard/vrouter/vrouter-onboard.yaml
new file mode 100644
index 0000000..e956c96
--- /dev/null
+++ b/xos/onboard/vrouter/vrouter-onboard.yaml
@@ -0,0 +1,20 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the vRouter SErvice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    servicecontroller#vrouter:
+      type: tosca.nodes.ServiceController
+      properties:
+          base_url: file:///opt/xos/onboard/vrouter/
+          # The following will concatenate with base_url automatically, if
+          # base_url is non-null.
+          models: models.py
+          admin: admin.py
+          admin_template: templates/vrouteradmin.html
+          tosca_resource: tosca/resources/vrouterservice.py
+
diff --git a/xos/onboard/vsg/admin.py b/xos/onboard/vsg/admin.py
new file mode 100644
index 0000000..92fa51d
--- /dev/null
+++ b/xos/onboard/vsg/admin.py
@@ -0,0 +1,150 @@
+from django.contrib import admin
+
+from services.vsg.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.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
+
+#-----------------------------------------------------------------------------
+# vSG
+#-----------------------------------------------------------------------------
+
+class VSGServiceForm(forms.ModelForm):
+    bbs_api_hostname = forms.CharField(required=False)
+    bbs_api_port = forms.IntegerField(required=False)
+    bbs_server = forms.CharField(required=False)
+    backend_network_label = forms.CharField(required=False)
+    bbs_slice = forms.ModelChoiceField(queryset=Slice.objects.all(), required=False)
+    dns_servers = forms.CharField(required=False)
+    url_filter_kind = forms.ChoiceField(choices=VSGService.URL_FILTER_KIND_CHOICES, required=False)
+    node_label = forms.CharField(required=False)
+
+    def __init__(self,*args,**kwargs):
+        super (VSGServiceForm,self ).__init__(*args,**kwargs)
+        if self.instance:
+            self.fields['bbs_api_hostname'].initial = self.instance.bbs_api_hostname
+            self.fields['bbs_api_port'].initial = self.instance.bbs_api_port
+            self.fields['bbs_server'].initial = self.instance.bbs_server
+            self.fields['backend_network_label'].initial = self.instance.backend_network_label
+            self.fields['bbs_slice'].initial = self.instance.bbs_slice
+            self.fields['dns_servers'].initial = self.instance.dns_servers
+            self.fields['url_filter_kind']. initial = self.instance.url_filter_kind
+            self.fields['node_label'].initial = self.instance.node_label
+
+    def save(self, commit=True):
+        self.instance.bbs_api_hostname = self.cleaned_data.get("bbs_api_hostname")
+        self.instance.bbs_api_port = self.cleaned_data.get("bbs_api_port")
+        self.instance.bbs_server = self.cleaned_data.get("bbs_server")
+        self.instance.backend_network_label = self.cleaned_data.get("backend_network_label")
+        self.instance.bbs_slice = self.cleaned_data.get("bbs_slice")
+        self.instance.dns_servers = self.cleaned_data.get("dns_servers")
+        self.instance.url_filter_kind = self.cleaned_data.get("url_filter_kind")
+        self.instance.node_label = self.cleaned_data.get("node_label")
+        return super(VSGServiceForm, self).save(commit=commit)
+
+    class Meta:
+        model = VSGService
+
+class VSGServiceAdmin(ReadOnlyAwareAdmin):
+    model = VSGService
+    verbose_name = "vSG Service"
+    verbose_name_plural = "vSG Service"
+    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", "service_specific_attribute", "node_label"],
+                                     'classes':['suit-tab suit-tab-general']}),
+                 ("backend config", {'fields': [ "backend_network_label", "url_filter_kind", "bbs_api_hostname", "bbs_api_port", "bbs_server", "bbs_slice"],
+                                     'classes':['suit-tab suit-tab-backend']}),
+                 ("vSG config", {'fields': ["dns_servers"],
+                                     'classes':['suit-tab suit-tab-vsg']}) ]
+    readonly_fields = ('backend_status_text', "service_specific_attribute")
+    inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline]
+    form = VSGServiceForm
+
+    extracontext_registered_admins = True
+
+    user_readonly_fields = ["name", "enabled", "versionNumber", "description"]
+
+    suit_form_tabs =(('general', 'Service Details'),
+        ('backend', 'Backend Config'),
+        ('vsg', 'vSG Config'),
+        ('administration', 'Administration'),
+        #('tools', 'Tools'),
+        ('slices','Slices'),
+        ('serviceattrs','Additional Attributes'),
+        ('serviceprivileges','Privileges') ,
+    )
+
+    suit_form_includes = (('vcpeadmin.html', 'top', 'administration'),
+                           ) #('hpctools.html', 'top', 'tools') )
+
+    def queryset(self, request):
+        return VSGService.get_service_objects_by_user(request.user)
+
+class VSGTenantForm(forms.ModelForm):
+    bbs_account = forms.CharField(required=False)
+    creator = forms.ModelChoiceField(queryset=User.objects.all())
+    instance = forms.ModelChoiceField(queryset=Instance.objects.all(),required=False)
+    last_ansible_hash = forms.CharField(required=False)
+    wan_container_ip = forms.CharField(required=False)
+    wan_container_mac = forms.CharField(required=False)
+
+    def __init__(self,*args,**kwargs):
+        super (VSGTenantForm,self ).__init__(*args,**kwargs)
+        self.fields['kind'].widget.attrs['readonly'] = True
+        self.fields['provider_service'].queryset = VSGService.get_service_objects().all()
+        if self.instance:
+            # fields for the attributes
+            self.fields['bbs_account'].initial = self.instance.bbs_account
+            self.fields['creator'].initial = self.instance.creator
+            self.fields['instance'].initial = self.instance.instance
+            self.fields['last_ansible_hash'].initial = self.instance.last_ansible_hash
+            self.fields['wan_container_ip'].initial = self.instance.wan_container_ip
+            self.fields['wan_container_mac'].initial = self.instance.wan_container_mac
+        if (not self.instance) or (not self.instance.pk):
+            # default fields for an 'add' form
+            self.fields['kind'].initial = VCPE_KIND
+            self.fields['creator'].initial = get_request().user
+            if VSGService.get_service_objects().exists():
+               self.fields["provider_service"].initial = VSGService.get_service_objects().all()[0]
+
+    def save(self, commit=True):
+        self.instance.creator = self.cleaned_data.get("creator")
+        self.instance.instance = self.cleaned_data.get("instance")
+        self.instance.last_ansible_hash = self.cleaned_data.get("last_ansible_hash")
+        return super(VSGTenantForm, self).save(commit=commit)
+
+    class Meta:
+        model = VSGTenant
+
+class VSGTenantAdmin(ReadOnlyAwareAdmin):
+    list_display = ('backend_status_icon', 'id', 'subscriber_tenant' )
+    list_display_links = ('backend_status_icon', 'id')
+    fieldsets = [ (None, {'fields': ['backend_status_text', 'kind', 'provider_service', 'subscriber_tenant', 'service_specific_id', # 'service_specific_attribute',
+                                     'wan_container_ip', 'wan_container_mac', 'bbs_account', 'creator', 'instance', 'last_ansible_hash'],
+                          'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text', 'service_specific_attribute', 'bbs_account', 'wan_container_ip', 'wan_container_mac')
+    form = VSGTenantForm
+
+    suit_form_tabs = (('general','Details'),)
+
+    def queryset(self, request):
+        return VSGTenant.get_tenant_objects_by_user(request.user)
+
+
+admin.site.register(VSGService, VSGServiceAdmin)
+admin.site.register(VSGTenant, VSGTenantAdmin)
+
diff --git a/xos/api/service/vsg/vsgservice.py b/xos/onboard/vsg/api/service/vsg/vsgservice.py
similarity index 98%
rename from xos/api/service/vsg/vsgservice.py
rename to xos/onboard/vsg/api/service/vsg/vsgservice.py
index 9ab4756..a04fb3e 100644
--- a/xos/api/service/vsg/vsgservice.py
+++ b/xos/onboard/vsg/api/service/vsg/vsgservice.py
@@ -10,7 +10,7 @@
 from core.models import *
 from django.forms import widgets
 from django.conf.urls import patterns, url
-from services.cord.models import VSGService
+from services.vsg.models import VSGService
 from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
 from django.shortcuts import get_object_or_404
 from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
diff --git a/xos/api/tenant/cord/vsg.py b/xos/onboard/vsg/api/tenant/cord/vsg.py
similarity index 95%
rename from xos/api/tenant/cord/vsg.py
rename to xos/onboard/vsg/api/tenant/cord/vsg.py
index 6807e98..c6a4247 100644
--- a/xos/api/tenant/cord/vsg.py
+++ b/xos/onboard/vsg/api/tenant/cord/vsg.py
@@ -6,7 +6,7 @@
 from rest_framework import status
 from core.models import *
 from django.forms import widgets
-from services.cord.models import VSGTenant, VSGService, CordSubscriberRoot
+from services.vsg.models import VSGTenant, VSGService
 from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
 from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
 
diff --git a/xos/onboard/vsg/models.py b/xos/onboard/vsg/models.py
new file mode 100644
index 0000000..ad25c98
--- /dev/null
+++ b/xos/onboard/vsg/models.py
@@ -0,0 +1,448 @@
+from django.db import models
+from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber, NetworkParameter, NetworkParameterType, Port, AddressPool, User
+from core.models.plcorebase import StrippedCharField
+import os
+from django.db import models, transaction
+from django.forms.models import model_to_dict
+from django.db.models import Q
+from operator import itemgetter, attrgetter, methodcaller
+from core.models import Tag
+from core.models.service import LeastLoadedNodeScheduler
+from services.vrouter.models import VRouterService, VRouterTenant
+import traceback
+from xos.exceptions import *
+from xos.config import Config
+
+class ConfigurationError(Exception):
+    pass
+
+VCPE_KIND = "vCPE"
+CORD_SUBSCRIBER_KIND = "CordSubscriberRoot"
+
+CORD_USE_VTN = getattr(Config(), "networking_use_vtn", False)
+
+# -------------------------------------------
+# VCPE
+# -------------------------------------------
+
+class VSGService(Service):
+    KIND = VCPE_KIND
+
+    URL_FILTER_KIND_CHOICES = ( (None, "None"), ("safebrowsing", "Safe Browsing"), ("answerx", "AnswerX") )
+
+    simple_attributes = ( ("bbs_api_hostname", None),
+                          ("bbs_api_port", None),
+                          ("bbs_server", None),
+                          ("backend_network_label", "hpc_client"),
+                          ("dns_servers", "8.8.8.8"),
+                          ("url_filter_kind", None),
+                          ("node_label", None) )
+
+    def __init__(self, *args, **kwargs):
+        super(VSGService, self).__init__(*args, **kwargs)
+
+    class Meta:
+        app_label = "vsg"
+        verbose_name = "vSG Service"
+        proxy = True
+
+    def allocate_bbs_account(self):
+        vcpes = VSGTenant.get_tenant_objects().all()
+        bbs_accounts = [vcpe.bbs_account for vcpe in vcpes]
+
+        # There's a bit of a race here; some other user could be trying to
+        # allocate a bbs_account at the same time we are.
+
+        for i in range(2,21):
+             account_name = "bbs%02d@onlab.us" % i
+             if (account_name not in bbs_accounts):
+                 return account_name
+
+        raise XOSConfigurationError("We've run out of available broadbandshield accounts. Delete some vcpe and try again.")
+
+    @property
+    def bbs_slice(self):
+        bbs_slice_id=self.get_attribute("bbs_slice_id")
+        if not bbs_slice_id:
+            return None
+        bbs_slices=Slice.objects.filter(id=bbs_slice_id)
+        if not bbs_slices:
+            return None
+        return bbs_slices[0]
+
+    @bbs_slice.setter
+    def bbs_slice(self, value):
+        if value:
+            value = value.id
+        self.set_attribute("bbs_slice_id", value)
+
+VSGService.setup_simple_attributes()
+
+class VSGTenant(TenantWithContainer):
+    class Meta:
+        proxy = True
+
+    KIND = VCPE_KIND
+
+    sync_attributes = ("wan_container_ip", "wan_container_mac", "wan_container_netbits",
+                       "wan_container_gateway_ip", "wan_container_gateway_mac",
+                       "wan_vm_ip", "wan_vm_mac")
+
+    default_attributes = {"instance_id": None,
+                          "container_id": None,
+                          "users": [],
+                          "bbs_account": None,
+                          "last_ansible_hash": None,
+                          "wan_container_ip": None}
+
+    def __init__(self, *args, **kwargs):
+        super(VSGTenant, self).__init__(*args, **kwargs)
+        self.cached_vrouter=None
+
+    @property
+    def vbng(self):
+        # not supported
+        return None
+
+    @vbng.setter
+    def vbng(self, value):
+        raise XOSConfigurationError("vCPE.vBNG cannot be set this way -- create a new vBNG object and set it's subscriber_tenant instead")
+
+    @property
+    def vrouter(self):
+        vrouter = self.get_newest_subscribed_tenant(VRouterTenant)
+        if not vrouter:
+            return None
+
+        # always return the same object when possible
+        if (self.cached_vrouter) and (self.cached_vrouter.id == vrouter.id):
+            return self.cached_vrouter
+
+        vrouter.caller = self.creator
+        self.cached_vrouter = vrouter
+        return vrouter
+
+    @vrouter.setter
+    def vrouter(self, value):
+        raise XOSConfigurationError("vCPE.vRouter cannot be set this way -- create a new vRuter object and set its subscriber_tenant instead")
+
+    @property
+    def volt(self):
+        from services.volt.models import VOLTTenant
+        if not self.subscriber_tenant:
+            return None
+        volts = VOLTTenant.objects.filter(id=self.subscriber_tenant.id)
+        if not volts:
+            return None
+        return volts[0]
+
+    @property
+    def bbs_account(self):
+        return self.get_attribute("bbs_account", self.default_attributes["bbs_account"])
+
+    @bbs_account.setter
+    def bbs_account(self, value):
+        return self.set_attribute("bbs_account", value)
+
+    @property
+    def last_ansible_hash(self):
+        return self.get_attribute("last_ansible_hash", self.default_attributes["last_ansible_hash"])
+
+    @last_ansible_hash.setter
+    def last_ansible_hash(self, value):
+        return self.set_attribute("last_ansible_hash", value)
+
+    @property
+    def ssh_command(self):
+        if self.instance:
+            return self.instance.get_ssh_command()
+        else:
+            return "no-instance"
+
+    @ssh_command.setter
+    def ssh_command(self, value):
+        pass
+
+    def get_vrouter_field(self, name, default=None):
+        if self.vrouter:
+            return getattr(self.vrouter, name, default)
+        else:
+            return default
+
+    @property
+    def wan_container_ip(self):
+        return self.get_vrouter_field("public_ip", None)
+
+    @property
+    def wan_container_mac(self):
+        return self.get_vrouter_field("public_mac", None)
+
+    @property
+    def wan_container_netbits(self):
+        return self.get_vrouter_field("netbits", None)
+
+    @property
+    def wan_container_gateway_ip(self):
+        return self.get_vrouter_field("gateway_ip", None)
+
+    @property
+    def wan_container_gateway_mac(self):
+        return self.get_vrouter_field("gateway_mac", None)
+
+    @property
+    def wan_vm_ip(self):
+        tags = Tag.select_by_content_object(self.instance).filter(name="vm_vrouter_tenant")
+        if tags:
+            tenant = VRouterTenant.objects.get(id=tags[0].value)
+            return tenant.public_ip
+        else:
+            raise Exception("no vm_vrouter_tenant tag for instance %s" % o.instance)
+
+    @property
+    def wan_vm_mac(self):
+        tags = Tag.select_by_content_object(self.instance).filter(name="vm_vrouter_tenant")
+        if tags:
+            tenant = VRouterTenant.objects.get(id=tags[0].value)
+            return tenant.public_mac
+        else:
+            raise Exception("no vm_vrouter_tenant tag for instance %s" % o.instance)
+
+    @property
+    def is_synced(self):
+        return (self.enacted is not None) and (self.enacted >= self.updated)
+
+    @is_synced.setter
+    def is_synced(self, value):
+        pass
+
+    def get_vrouter_service(self):
+        vrouterServices = VRouterService.get_service_objects().all()
+        if not vrouterServices:
+            raise XOSConfigurationError("No VROUTER Services available")
+        return vrouterServices[0]
+
+    def manage_vrouter(self):
+        # Each vCPE object owns exactly one vRouterTenant object
+
+        if self.deleted:
+            return
+
+        if self.vrouter is None:
+            vrouter = self.get_vrouter_service().get_tenant(address_pool_name="addresses_vsg", subscriber_tenant = self)
+            vrouter.caller = self.creator
+            vrouter.save()
+
+    def cleanup_vrouter(self):
+        if self.vrouter:
+            # print "XXX cleanup vrouter", self.vrouter
+            self.vrouter.delete()
+
+    def cleanup_orphans(self):
+        # ensure vCPE only has one vRouter
+        cur_vrouter = self.vrouter
+        for vrouter in list(self.get_subscribed_tenants(VRouterTenant)):
+            if (not cur_vrouter) or (vrouter.id != cur_vrouter.id):
+                # print "XXX clean up orphaned vrouter", vrouter
+                vrouter.delete()
+
+        if self.orig_instance_id and (self.orig_instance_id != self.get_attribute("instance_id")):
+            instances=Instance.objects.filter(id=self.orig_instance_id)
+            if instances:
+                # print "XXX clean up orphaned instance", instances[0]
+                instances[0].delete()
+
+    def get_slice(self):
+        if not self.provider_service.slices.count():
+            print self, "dio porco"
+            raise XOSConfigurationError("The service has no slices")
+        slice = self.provider_service.slices.all()[0]
+        return slice
+
+    def get_vsg_service(self):
+        return VSGService.get_service_objects().get(id=self.provider_service.id)
+
+    def find_instance_for_s_tag(self, s_tag):
+        #s_tags = STagBlock.objects.find(s_s_tag)
+        #if s_tags:
+        #    return s_tags[0].instance
+
+        tags = Tag.objects.filter(name="s_tag", value=s_tag)
+        if tags:
+            return tags[0].content_object
+
+        return None
+
+    def find_or_make_instance_for_s_tag(self, s_tag):
+        instance = self.find_instance_for_s_tag(self.volt.s_tag)
+        if instance:
+            return instance
+
+        flavors = Flavor.objects.filter(name="m1.small")
+        if not flavors:
+            raise XOSConfigurationError("No m1.small flavor")
+
+        slice = self.provider_service.slices.all()[0]
+
+        if slice.default_isolation == "container_vm":
+            (node, parent) = ContainerVmScheduler(slice).pick()
+        else:
+            (node, parent) = LeastLoadedNodeScheduler(slice, label=self.get_vsg_service().node_label).pick()
+
+        instance = Instance(slice = slice,
+                        node = node,
+                        image = self.image,
+                        creator = self.creator,
+                        deployment = node.site_deployment.deployment,
+                        flavor = flavors[0],
+                        isolation = slice.default_isolation,
+                        parent = parent)
+
+        self.save_instance(instance)
+
+        return instance
+
+    def manage_container(self):
+        from core.models import Instance, Flavor
+
+        if self.deleted:
+            return
+
+        # For container or container_vm isolation, use what TenantWithCotnainer
+        # provides us
+        slice = self.get_slice()
+        if slice.default_isolation in ["container_vm", "container"]:
+            super(VSGTenant,self).manage_container()
+            return
+
+        if not self.volt:
+            raise XOSConfigurationError("This vCPE container has no volt")
+
+        if self.instance:
+            # We're good.
+            return
+
+        instance = self.find_or_make_instance_for_s_tag(self.volt.s_tag)
+        self.instance = instance
+        super(TenantWithContainer, self).save()
+
+    def cleanup_container(self):
+        if self.get_slice().default_isolation in ["container_vm", "container"]:
+            super(VSGTenant,self).cleanup_container()
+
+        # To-do: cleanup unused instances
+        pass
+
+    def manage_bbs_account(self):
+        if self.deleted:
+            return
+
+        if self.volt and self.volt.subscriber and self.volt.subscriber.url_filter_enable:
+            if not self.bbs_account:
+                # make sure we use the proxied VSGService object, not the generic Service object
+                vcpe_service = VSGService.objects.get(id=self.provider_service.id)
+                self.bbs_account = vcpe_service.allocate_bbs_account()
+                super(VSGTenant, self).save()
+        else:
+            if self.bbs_account:
+                self.bbs_account = None
+                super(VSGTenant, self).save()
+
+    def find_or_make_port(self, instance, network, **kwargs):
+        port = Port.objects.filter(instance=instance, network=network)
+        if port:
+            port = port[0]
+        else:
+            port = Port(instance=instance, network=network, **kwargs)
+            port.save()
+        return port
+
+    def get_lan_network(self, instance):
+        slice = self.provider_service.slices.all()[0]
+        if CORD_USE_VTN:
+            # there should only be one network private network, and its template should not be the management template
+            lan_networks = [x for x in slice.networks.all() if x.template.visibility=="private" and (not "management" in x.template.name)]
+            if len(lan_networks)>1:
+                raise XOSProgrammingError("The vSG slice should only have one non-management private network")
+        else:
+            lan_networks = [x for x in slice.networks.all() if "lan" in x.name]
+        if not lan_networks:
+            raise XOSProgrammingError("No lan_network")
+        return lan_networks[0]
+
+    def save_instance(self, instance):
+        with transaction.atomic():
+            instance.volumes = "/etc/dnsmasq.d,/etc/ufw"
+            super(VSGTenant, self).save_instance(instance)
+
+            if instance.isolation in ["container", "container_vm"]:
+                lan_network = self.get_lan_network(instance)
+                port = self.find_or_make_port(instance, lan_network, ip="192.168.0.1", port_id="unmanaged")
+                port.set_parameter("c_tag", self.volt.c_tag)
+                port.set_parameter("s_tag", self.volt.s_tag)
+                port.set_parameter("device", "eth1")
+                port.set_parameter("bridge", "br-lan")
+
+                wan_networks = [x for x in instance.slice.networks.all() if "wan" in x.name]
+                if not wan_networks:
+                    raise XOSProgrammingError("No wan_network")
+                port = self.find_or_make_port(instance, wan_networks[0])
+                port.set_parameter("next_hop", value="10.0.1.253")   # FIX ME
+                port.set_parameter("device", "eth0")
+
+            if instance.isolation in ["vm"]:
+                lan_network = self.get_lan_network(instance)
+                port = self.find_or_make_port(instance, lan_network)
+                port.set_parameter("c_tag", self.volt.c_tag)
+                port.set_parameter("s_tag", self.volt.s_tag)
+                port.set_parameter("neutron_port_name", "stag-%s" % self.volt.s_tag)
+                port.save()
+
+            # tag the instance with the s-tag, so we can easily find the
+            # instance later
+            if self.volt and self.volt.s_tag:
+                tags = Tag.objects.filter(name="s_tag", value=self.volt.s_tag)
+                if not tags:
+                    tag = Tag(service=self.provider_service, content_object=instance, name="s_tag", value=self.volt.s_tag)
+                    tag.save()
+
+            # VTN-CORD needs a WAN address for the VM, so that the VM can
+            # be configured.
+            if CORD_USE_VTN:
+                tags = Tag.select_by_content_object(instance).filter(name="vm_vrouter_tenant")
+                if not tags:
+                    vrouter = self.get_vrouter_service().get_tenant(address_pool_name="addresses_vsg", subscriber_service = self.provider_service)
+                    vrouter.set_attribute("tenant_for_instance_id", instance.id)
+                    vrouter.save()
+                    tag = Tag(service=self.provider_service, content_object=instance, name="vm_vrouter_tenant", value="%d" % vrouter.id)
+                    tag.save()
+
+    def save(self, *args, **kwargs):
+        if not self.creator:
+            if not getattr(self, "caller", None):
+                # caller must be set when creating a vCPE since it creates a slice
+                raise XOSProgrammingError("VSGTenant's self.caller was not set")
+            self.creator = self.caller
+            if not self.creator:
+                raise XOSProgrammingError("VSGTenant's self.creator was not set")
+
+        super(VSGTenant, self).save(*args, **kwargs)
+        model_policy_vcpe(self.pk)
+
+    def delete(self, *args, **kwargs):
+        self.cleanup_vrouter()
+        self.cleanup_container()
+        super(VSGTenant, self).delete(*args, **kwargs)
+
+def model_policy_vcpe(pk):
+    # TODO: this should be made in to a real model_policy
+    with transaction.atomic():
+        vcpe = VSGTenant.objects.select_for_update().filter(pk=pk)
+        if not vcpe:
+            return
+        vcpe = vcpe[0]
+        vcpe.manage_container()
+        vcpe.manage_vrouter()
+        vcpe.manage_bbs_account()
+        vcpe.cleanup_orphans()
+
+
diff --git a/xos/synchronizers/vcpe/broadbandshield.py b/xos/onboard/vsg/synchronizer/broadbandshield.py
similarity index 100%
rename from xos/synchronizers/vcpe/broadbandshield.py
rename to xos/onboard/vsg/synchronizer/broadbandshield.py
diff --git a/xos/synchronizers/vcpe/files/docker.list b/xos/onboard/vsg/synchronizer/files/docker.list
similarity index 100%
rename from xos/synchronizers/vcpe/files/docker.list
rename to xos/onboard/vsg/synchronizer/files/docker.list
diff --git a/xos/synchronizers/vcpe/files/etc/rc.local b/xos/onboard/vsg/synchronizer/files/etc/rc.local
similarity index 100%
rename from xos/synchronizers/vcpe/files/etc/rc.local
rename to xos/onboard/vsg/synchronizer/files/etc/rc.local
diff --git a/xos/synchronizers/vcpe/files/etc/service/message/run b/xos/onboard/vsg/synchronizer/files/etc/service/message/run
similarity index 100%
rename from xos/synchronizers/vcpe/files/etc/service/message/run
rename to xos/onboard/vsg/synchronizer/files/etc/service/message/run
diff --git a/xos/synchronizers/vcpe/files/etc/ufw/after.init b/xos/onboard/vsg/synchronizer/files/etc/ufw/after.init
similarity index 100%
rename from xos/synchronizers/vcpe/files/etc/ufw/after.init
rename to xos/onboard/vsg/synchronizer/files/etc/ufw/after.init
diff --git a/xos/synchronizers/vcpe/files/etc/ufw/after.rules b/xos/onboard/vsg/synchronizer/files/etc/ufw/after.rules
similarity index 100%
rename from xos/synchronizers/vcpe/files/etc/ufw/after.rules
rename to xos/onboard/vsg/synchronizer/files/etc/ufw/after.rules
diff --git a/xos/synchronizers/vcpe/files/etc/ufw/after6.rules b/xos/onboard/vsg/synchronizer/files/etc/ufw/after6.rules
similarity index 100%
rename from xos/synchronizers/vcpe/files/etc/ufw/after6.rules
rename to xos/onboard/vsg/synchronizer/files/etc/ufw/after6.rules
diff --git a/xos/synchronizers/vcpe/files/etc/ufw/applications.d/openssh-server b/xos/onboard/vsg/synchronizer/files/etc/ufw/applications.d/openssh-server
similarity index 100%
rename from xos/synchronizers/vcpe/files/etc/ufw/applications.d/openssh-server
rename to xos/onboard/vsg/synchronizer/files/etc/ufw/applications.d/openssh-server
diff --git a/xos/synchronizers/vcpe/files/etc/ufw/before.init b/xos/onboard/vsg/synchronizer/files/etc/ufw/before.init
similarity index 100%
rename from xos/synchronizers/vcpe/files/etc/ufw/before.init
rename to xos/onboard/vsg/synchronizer/files/etc/ufw/before.init
diff --git a/xos/synchronizers/vcpe/files/etc/ufw/before6.rules b/xos/onboard/vsg/synchronizer/files/etc/ufw/before6.rules
similarity index 100%
rename from xos/synchronizers/vcpe/files/etc/ufw/before6.rules
rename to xos/onboard/vsg/synchronizer/files/etc/ufw/before6.rules
diff --git a/xos/synchronizers/vcpe/files/etc/ufw/sysctl.conf b/xos/onboard/vsg/synchronizer/files/etc/ufw/sysctl.conf
similarity index 100%
rename from xos/synchronizers/vcpe/files/etc/ufw/sysctl.conf
rename to xos/onboard/vsg/synchronizer/files/etc/ufw/sysctl.conf
diff --git a/xos/synchronizers/vcpe/files/etc/ufw/ufw.conf b/xos/onboard/vsg/synchronizer/files/etc/ufw/ufw.conf
similarity index 100%
rename from xos/synchronizers/vcpe/files/etc/ufw/ufw.conf
rename to xos/onboard/vsg/synchronizer/files/etc/ufw/ufw.conf
diff --git a/xos/synchronizers/vcpe/files/vcpe.conf b/xos/onboard/vsg/synchronizer/files/vcpe.conf
similarity index 100%
rename from xos/synchronizers/vcpe/files/vcpe.conf
rename to xos/onboard/vsg/synchronizer/files/vcpe.conf
diff --git a/xos/synchronizers/vcpe/files/vcpe.dnsmasq b/xos/onboard/vsg/synchronizer/files/vcpe.dnsmasq
similarity index 100%
rename from xos/synchronizers/vcpe/files/vcpe.dnsmasq
rename to xos/onboard/vsg/synchronizer/files/vcpe.dnsmasq
diff --git a/xos/synchronizers/vcpe/files/vm-resolv.conf b/xos/onboard/vsg/synchronizer/files/vm-resolv.conf
similarity index 100%
rename from xos/synchronizers/vcpe/files/vm-resolv.conf
rename to xos/onboard/vsg/synchronizer/files/vm-resolv.conf
diff --git a/xos/onboard/vsg/synchronizer/manifest b/xos/onboard/vsg/synchronizer/manifest
new file mode 100644
index 0000000..d13ee05
--- /dev/null
+++ b/xos/onboard/vsg/synchronizer/manifest
@@ -0,0 +1,49 @@
+templates/bwlimit.sh.j2
+templates/vlan_sample.j2
+templates/before.rules.j2
+templates/start-vcpe.sh.j2
+templates/dnsmasq_safe_servers.j2
+templates/firewall_sample.j2
+templates/rc.local.j2
+templates/vcpe.conf.j2
+templates/message.html.j2
+templates/dnsmasq_servers.j2
+templates/start-vcpe-vtn.sh.j2
+manifest
+broadbandshield.py
+observer_ansible_test.py
+vcpe_synchronizer_config
+start-bbs.sh
+steps/sync_vcpetenant.py
+steps/sync_vcpetenant_new.yaml
+steps/sync_vcpetenant_vtn.yaml
+steps/sync_vcpetenant.yaml
+steps/test.yaml
+steps/ansible_test/README
+steps/ansible_test/test.yaml
+steps/ansible_test/xos.py
+steps/ansible_test/test.sh
+steps/ansible_test/inventory.txt
+start.sh
+files/vcpe.conf
+files/etc/service/message/run
+files/etc/rc.local
+files/etc/ufw/after6.rules
+files/etc/ufw/applications.d/openssh-server
+files/etc/ufw/sysctl.conf
+files/etc/ufw/ufw.conf
+files/etc/ufw/before6.rules
+files/etc/ufw/after.init
+files/etc/ufw/before.init
+files/etc/ufw/after.rules
+files/vm-resolv.conf
+files/docker.list
+files/vcpe.dnsmasq
+run-vtn.sh
+stop.sh
+vcpe-synchronizer.py
+model-deps
+supervisor/vcpe-observer.conf
+run.sh
+vtn_vcpe_synchronizer_config
+vcpe_stats_notifier.py
diff --git a/xos/synchronizers/vbng/model-deps b/xos/onboard/vsg/synchronizer/model-deps
similarity index 100%
rename from xos/synchronizers/vbng/model-deps
rename to xos/onboard/vsg/synchronizer/model-deps
diff --git a/xos/synchronizers/vcpe/observer_ansible_test.py b/xos/onboard/vsg/synchronizer/observer_ansible_test.py
similarity index 100%
rename from xos/synchronizers/vcpe/observer_ansible_test.py
rename to xos/onboard/vsg/synchronizer/observer_ansible_test.py
diff --git a/xos/synchronizers/vcpe/run-vtn.sh b/xos/onboard/vsg/synchronizer/run-vtn.sh
similarity index 100%
rename from xos/synchronizers/vcpe/run-vtn.sh
rename to xos/onboard/vsg/synchronizer/run-vtn.sh
diff --git a/xos/synchronizers/vcpe/run.sh b/xos/onboard/vsg/synchronizer/run.sh
similarity index 100%
rename from xos/synchronizers/vcpe/run.sh
rename to xos/onboard/vsg/synchronizer/run.sh
diff --git a/xos/synchronizers/vcpe/start-bbs.sh b/xos/onboard/vsg/synchronizer/start-bbs.sh
similarity index 100%
rename from xos/synchronizers/vcpe/start-bbs.sh
rename to xos/onboard/vsg/synchronizer/start-bbs.sh
diff --git a/xos/synchronizers/vcpe/start.sh b/xos/onboard/vsg/synchronizer/start.sh
similarity index 100%
rename from xos/synchronizers/vcpe/start.sh
rename to xos/onboard/vsg/synchronizer/start.sh
diff --git a/xos/synchronizers/vcpe/steps/ansible_test/README b/xos/onboard/vsg/synchronizer/steps/ansible_test/README
similarity index 100%
rename from xos/synchronizers/vcpe/steps/ansible_test/README
rename to xos/onboard/vsg/synchronizer/steps/ansible_test/README
diff --git a/xos/synchronizers/vcpe/steps/ansible_test/inventory.txt b/xos/onboard/vsg/synchronizer/steps/ansible_test/inventory.txt
similarity index 100%
rename from xos/synchronizers/vcpe/steps/ansible_test/inventory.txt
rename to xos/onboard/vsg/synchronizer/steps/ansible_test/inventory.txt
diff --git a/xos/synchronizers/vcpe/steps/ansible_test/test.sh b/xos/onboard/vsg/synchronizer/steps/ansible_test/test.sh
similarity index 100%
rename from xos/synchronizers/vcpe/steps/ansible_test/test.sh
rename to xos/onboard/vsg/synchronizer/steps/ansible_test/test.sh
diff --git a/xos/synchronizers/vcpe/steps/ansible_test/test.yaml b/xos/onboard/vsg/synchronizer/steps/ansible_test/test.yaml
similarity index 100%
rename from xos/synchronizers/vcpe/steps/ansible_test/test.yaml
rename to xos/onboard/vsg/synchronizer/steps/ansible_test/test.yaml
diff --git a/xos/synchronizers/vcpe/steps/ansible_test/xos.py b/xos/onboard/vsg/synchronizer/steps/ansible_test/xos.py
similarity index 100%
rename from xos/synchronizers/vcpe/steps/ansible_test/xos.py
rename to xos/onboard/vsg/synchronizer/steps/ansible_test/xos.py
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant.py b/xos/onboard/vsg/synchronizer/steps/sync_vcpetenant.py
similarity index 97%
rename from xos/synchronizers/vcpe/steps/sync_vcpetenant.py
rename to xos/onboard/vsg/synchronizer/steps/sync_vcpetenant.py
index d8bc525..0b777c7 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant.py
+++ b/xos/onboard/vsg/synchronizer/steps/sync_vcpetenant.py
@@ -10,7 +10,7 @@
 from synchronizers.base.ansible import run_template_ssh
 from synchronizers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
 from core.models import Service, Slice, Tag
-from services.cord.models import VSGService, VSGTenant, VOLTTenant
+from services.vsg.models import VSGService, VSGTenant
 from services.hpc.models import HpcService, CDNPrefix
 from xos.logger import Logger, logging
 
@@ -31,7 +31,6 @@
     observes=VSGTenant
     requested_interval=0
     template_name = "sync_vcpetenant.yaml"
-    service_key_name = "/opt/xos/synchronizers/vcpe/vcpe_private_key"
 
     def __init__(self, *args, **kwargs):
         super(SyncVSGTenant, self).__init__(*args, **kwargs)
@@ -67,7 +66,7 @@
         dnsdemux_ip = None
         cdn_prefixes = []
 
-        cdn_config_fn = "/opt/xos/synchronizers/vcpe/cdn_config"
+        cdn_config_fn = "/opt/xos/synchronizers/vsg/cdn_config"
         if os.path.exists(cdn_config_fn):
             # manual CDN configuration
             #   the first line is the address of dnsredir
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml b/xos/onboard/vsg/synchronizer/steps/sync_vcpetenant.yaml
similarity index 83%
rename from xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml
rename to xos/onboard/vsg/synchronizer/steps/sync_vcpetenant.yaml
index 9be0f98..880895e 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml
+++ b/xos/onboard/vsg/synchronizer/steps/sync_vcpetenant.yaml
@@ -63,7 +63,7 @@
   tasks:
 {% if full_setup %}
   - name: Docker repository
-    copy: src=/opt/xos/synchronizers/vcpe/files/docker.list
+    copy: src=/opt/xos/synchronizers/vsg/files/docker.list
       dest=/etc/apt/sources.list.d/docker.list
 
   - name: Import the repository key
@@ -95,7 +95,7 @@
     shell: rm -f /etc/resolv.conf
 
   - name: Install resolv.conf
-    copy: src=/opt/xos/synchronizers/vcpe/files/vm-resolv.conf
+    copy: src=/opt/xos/synchronizers/vsg/files/vm-resolv.conf
       dest=/etc/resolv.conf
 
   - name: Verify if vcpe_stats_notifier ([] is to avoid capturing the shell process) cron job is already running
@@ -110,7 +110,7 @@
 #    when: cron_job_pids_count.stdout == "0"
 
   - name: Copy cron job to destination
-    copy: src=/opt/xos/synchronizers/vcpe/vcpe_stats_notifier.py
+    copy: src=/opt/xos/synchronizers/vsg/vcpe_stats_notifier.py
       dest=/usr/local/sbin/vcpe_stats_notifier.py
     when: cron_job_pids_count.stdout == "0"
 
@@ -126,10 +126,10 @@
 {% endif %}
 
   - name: vCPE upstart
-    template: src=/opt/xos/synchronizers/vcpe/templates/vcpe.conf.j2 dest=/etc/init/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}.conf
+    template: src=/opt/xos/synchronizers/vsg/templates/vcpe.conf.j2 dest=/etc/init/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}.conf
 
   - name: vCPE startup script
-    template: src=/opt/xos/synchronizers/vcpe/templates/start-vcpe.sh.j2 dest=/usr/local/sbin/start-vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}.sh mode=0755
+    template: src=/opt/xos/synchronizers/vsg/templates/start-vcpe.sh.j2 dest=/usr/local/sbin/start-vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}.sh mode=0755
     notify:
 #    - restart vcpe
      - stop vcpe
@@ -140,22 +140,22 @@
     file: path=/etc/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}/dnsmasq.d state=directory owner=root group=root
 
   - name: vCPE basic dnsmasq config
-    copy: src=/opt/xos/synchronizers/vcpe/files/vcpe.dnsmasq dest=/etc/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}/dnsmasq.d/vcpe.conf owner=root group=root
+    copy: src=/opt/xos/synchronizers/vsg/files/vcpe.dnsmasq dest=/etc/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}/dnsmasq.d/vcpe.conf owner=root group=root
     notify:
     - restart dnsmasq
 
   - name: dnsmasq config
-    template: src=/opt/xos/synchronizers/vcpe/templates/dnsmasq_servers.j2 dest=/etc/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}/dnsmasq.d/servers.conf owner=root group=root
+    template: src=/opt/xos/synchronizers/vsg/templates/dnsmasq_servers.j2 dest=/etc/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}/dnsmasq.d/servers.conf owner=root group=root
     notify:
     - restart dnsmasq
 
 # These are samples, not necessary for correct function of demo
 
 #  - name: networking info
-#    template: src=/opt/xos/synchronizers/vcpe/templates/vlan_sample.j2 dest=/etc/vlan_sample owner=root group=root
+#    template: src=/opt/xos/synchronizers/vsg/templates/vlan_sample.j2 dest=/etc/vlan_sample owner=root group=root
 
 #  - name: firewall info
-#    template: src=/opt/xos/synchronizers/vcpe/templates/firewall_sample.j2 dest=/etc/firewall_sample owner=root group=root
+#    template: src=/opt/xos/synchronizers/vsg/templates/firewall_sample.j2 dest=/etc/firewall_sample owner=root group=root
 
   - name: Make sure vCPE service is running
     service: name=vcpe-{{ s_tags[0] }}-{{ c_tags[0] }} state=started
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml b/xos/onboard/vsg/synchronizer/steps/sync_vcpetenant_new.yaml
similarity index 80%
rename from xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml
rename to xos/onboard/vsg/synchronizer/steps/sync_vcpetenant_new.yaml
index 435b721..9c59280 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml
+++ b/xos/onboard/vsg/synchronizer/steps/sync_vcpetenant_new.yaml
@@ -74,7 +74,7 @@
     when: cron_job_pids_count.stdout == "0"
 
   - name: Copy cron job to destination
-    copy: src=/opt/xos/synchronizers/vcpe/vcpe_stats_notifier.py
+    copy: src=/opt/xos/synchronizers/vsg/vcpe_stats_notifier.py
       dest=~/bin/vcpe_stats_notifier.py
     when: cron_job_pids_count.stdout == "0"
 
@@ -89,12 +89,12 @@
     when: cron_job_pids_count.stdout == "0"
 
   - name: vCPE basic dnsmasq config
-    copy: src=/opt/xos/synchronizers/vcpe/files/vcpe.dnsmasq dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/vcpe.conf owner=root group=root
+    copy: src=/opt/xos/synchronizers/vsg/files/vcpe.dnsmasq dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/vcpe.conf owner=root group=root
     notify:
     - restart dnsmasq
 
   - name: dnsmasq config
-    template: src=/opt/xos/synchronizers/vcpe/templates/dnsmasq_servers.j2 dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/servers.conf owner=root group=root
+    template: src=/opt/xos/synchronizers/vsg/templates/dnsmasq_servers.j2 dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/servers.conf owner=root group=root
     notify:
     - restart dnsmasq
 
@@ -102,22 +102,22 @@
     file: path=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/safe state=directory
 
   - name: dnsmasq "safe" config
-    template: src=/opt/xos/synchronizers/vcpe/templates/dnsmasq_safe_servers.j2 dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/safe/servers.conf owner=root group=root
+    template: src=/opt/xos/synchronizers/vsg/templates/dnsmasq_safe_servers.j2 dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/safe/servers.conf owner=root group=root
     notify:
     - restart dnsmasq
 
   - name: copy base ufw files
-    synchronize: src=/opt/xos/synchronizers/vcpe/files/etc/ufw/ dest=/var/container_volumes/{{ container_name }}/etc/ufw/
+    synchronize: src=/opt/xos/synchronizers/vsg/files/etc/ufw/ dest=/var/container_volumes/{{ container_name }}/etc/ufw/
     notify:
     - reload ufw
 
   - name: redirection rules for safe DNS
-    template: src=/opt/xos/synchronizers/vcpe/templates/before.rules.j2 dest=/var/container_volumes/{{ container_name }}/etc/ufw/before.rules owner=root group=root
+    template: src=/opt/xos/synchronizers/vsg/templates/before.rules.j2 dest=/var/container_volumes/{{ container_name }}/etc/ufw/before.rules owner=root group=root
     notify:
     - reload ufw
 
   - name: base ufw setup uses /etc/rc.local
-    copy: src=/opt/xos/synchronizers/vcpe/files/etc/rc.local dest=/var/container_volumes/{{ container_name }}/etc/ owner=root group=root
+    copy: src=/opt/xos/synchronizers/vsg/files/etc/rc.local dest=/var/container_volumes/{{ container_name }}/etc/ owner=root group=root
     notify:
     - copy in /etc/rc.local
 
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant_vtn.yaml b/xos/onboard/vsg/synchronizer/steps/sync_vcpetenant_vtn.yaml
similarity index 81%
rename from xos/synchronizers/vcpe/steps/sync_vcpetenant_vtn.yaml
rename to xos/onboard/vsg/synchronizer/steps/sync_vcpetenant_vtn.yaml
index b24d15a..0226354 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant_vtn.yaml
+++ b/xos/onboard/vsg/synchronizer/steps/sync_vcpetenant_vtn.yaml
@@ -128,7 +128,7 @@
 #    when: cron_job_pids_count.stdout == "0"
 
 #  - name: Copy cron job to destination
-#    copy: src=/opt/xos/synchronizers/vcpe/vcpe_stats_notifier.py
+#    copy: src=/opt/xos/synchronizers/vsg/vcpe_stats_notifier.py
 #      dest=/usr/local/sbin/vcpe_stats_notifier.py
 #    when: cron_job_pids_count.stdout == "0"
 
@@ -144,10 +144,10 @@
 {% endif %}
 
   - name: vCPE upstart
-    template: src=/opt/xos/synchronizers/vcpe/templates/vcpe.conf.j2 dest=/etc/init/{{ container_name }}.conf
+    template: src=/opt/xos/synchronizers/vsg/templates/vcpe.conf.j2 dest=/etc/init/{{ container_name }}.conf
 
   - name: vCPE startup script
-    template: src=/opt/xos/synchronizers/vcpe/templates/start-vcpe-vtn.sh.j2 dest=/usr/local/sbin/start-{{ container_name }}.sh mode=0755
+    template: src=/opt/xos/synchronizers/vsg/templates/start-vcpe-vtn.sh.j2 dest=/usr/local/sbin/start-{{ container_name }}.sh mode=0755
     notify:
 #    - restart vcpe
      - stop vcpe
@@ -158,17 +158,17 @@
     file: path=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/safe state=directory owner=root group=root
 
   - name: vCPE basic dnsmasq config
-    copy: src=/opt/xos/synchronizers/vcpe/files/vcpe.dnsmasq dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/vcpe.conf owner=root group=root
+    copy: src=/opt/xos/synchronizers/vsg/files/vcpe.dnsmasq dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/vcpe.conf owner=root group=root
     notify:
     - restart dnsmasq
 
   - name: dnsmasq config
-    template: src=/opt/xos/synchronizers/vcpe/templates/dnsmasq_servers.j2 dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/servers.conf owner=root group=root
+    template: src=/opt/xos/synchronizers/vsg/templates/dnsmasq_servers.j2 dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/servers.conf owner=root group=root
     notify:
     - restart dnsmasq
 
   - name: dnsmasq "safe" config
-    template: src=/opt/xos/synchronizers/vcpe/templates/dnsmasq_safe_servers.j2 dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/safe/servers.conf owner=root group=root
+    template: src=/opt/xos/synchronizers/vsg/templates/dnsmasq_safe_servers.j2 dest=/var/container_volumes/{{ container_name }}/etc/dnsmasq.d/safe/servers.conf owner=root group=root
     notify:
     - restart dnsmasq
 
@@ -176,12 +176,12 @@
     file: path=/var/container_volumes/{{ container_name }}/mount state=directory owner=root group=root
 
   - name: redirection rules for safe DNS
-    template: src=/opt/xos/synchronizers/vcpe/templates/before.rules.j2 dest=/var/container_volumes/{{ container_name }}/mount/before.rules owner=root group=root mode=0644
+    template: src=/opt/xos/synchronizers/vsg/templates/before.rules.j2 dest=/var/container_volumes/{{ container_name }}/mount/before.rules owner=root group=root mode=0644
     notify:
     - reload ufw
 
   - name: base ufw setup uses /etc/rc.local
-    template: src=/opt/xos/synchronizers/vcpe/templates/rc.local.j2 dest=/var/container_volumes/{{ container_name }}/mount/rc.local owner=root group=root mode=0755
+    template: src=/opt/xos/synchronizers/vsg/templates/rc.local.j2 dest=/var/container_volumes/{{ container_name }}/mount/rc.local owner=root group=root mode=0755
     notify:
     - rerun /etc/rc.local
 
@@ -189,7 +189,7 @@
     file: path=/var/container_volumes/{{ container_name }}/usr/local/sbin state=directory
 
   - name: bandwidth limit script
-    template: src=/opt/xos/synchronizers/vcpe/templates/bwlimit.sh.j2 dest=/var/container_volumes/{{ container_name }}/usr/local/sbin/bwlimit.sh owner=root group=root mode=0755
+    template: src=/opt/xos/synchronizers/vsg/templates/bwlimit.sh.j2 dest=/var/container_volumes/{{ container_name }}/usr/local/sbin/bwlimit.sh owner=root group=root mode=0755
     notify:
     - reset bwlimits
 
@@ -197,7 +197,7 @@
     file: path=/var/container_volumes/{{ container_name }}/etc/service/message state=directory
 
   - name: copy simple webserver
-    copy: src=/opt/xos/synchronizers/vcpe/files/etc/service/ dest=/var/container_volumes/{{ container_name }}/etc/service/ owner=root group=root
+    copy: src=/opt/xos/synchronizers/vsg/files/etc/service/ dest=/var/container_volumes/{{ container_name }}/etc/service/ owner=root group=root
     when: status != "enabled"
 
   - name: make webserver script executable
@@ -205,7 +205,7 @@
     when: status != "enabled"
 
   - name: generate the message page
-    template: src=/opt/xos/synchronizers/vcpe/templates/message.html.j2 dest=/var/container_volumes/{{ container_name }}/etc/service/message/message.html owner=root group=root mode=0644
+    template: src=/opt/xos/synchronizers/vsg/templates/message.html.j2 dest=/var/container_volumes/{{ container_name }}/etc/service/message/message.html owner=root group=root mode=0644
     when: status != "enabled"
     #notify: restart vcpe
 
diff --git a/xos/synchronizers/vcpe/steps/test.yaml b/xos/onboard/vsg/synchronizer/steps/test.yaml
similarity index 100%
rename from xos/synchronizers/vcpe/steps/test.yaml
rename to xos/onboard/vsg/synchronizer/steps/test.yaml
diff --git a/xos/synchronizers/vcpe/stop.sh b/xos/onboard/vsg/synchronizer/stop.sh
similarity index 100%
rename from xos/synchronizers/vcpe/stop.sh
rename to xos/onboard/vsg/synchronizer/stop.sh
diff --git a/xos/onboard/vsg/synchronizer/supervisor/vcpe-observer.conf b/xos/onboard/vsg/synchronizer/supervisor/vcpe-observer.conf
new file mode 100644
index 0000000..2d90293
--- /dev/null
+++ b/xos/onboard/vsg/synchronizer/supervisor/vcpe-observer.conf
@@ -0,0 +1,2 @@
+[program:vcpe-observer]
+command=python /opt/xos/synchronizers/vsg/vcpe-synchronizer.py -C /opt/xos/synchronizers/vsg/vcpe_synchronizer_config
diff --git a/xos/synchronizers/vcpe/templates/before.rules.j2 b/xos/onboard/vsg/synchronizer/templates/before.rules.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/before.rules.j2
rename to xos/onboard/vsg/synchronizer/templates/before.rules.j2
diff --git a/xos/synchronizers/vcpe/templates/bwlimit.sh.j2 b/xos/onboard/vsg/synchronizer/templates/bwlimit.sh.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/bwlimit.sh.j2
rename to xos/onboard/vsg/synchronizer/templates/bwlimit.sh.j2
diff --git a/xos/synchronizers/vcpe/templates/dnsmasq_safe_servers.j2 b/xos/onboard/vsg/synchronizer/templates/dnsmasq_safe_servers.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/dnsmasq_safe_servers.j2
rename to xos/onboard/vsg/synchronizer/templates/dnsmasq_safe_servers.j2
diff --git a/xos/synchronizers/vcpe/templates/dnsmasq_servers.j2 b/xos/onboard/vsg/synchronizer/templates/dnsmasq_servers.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/dnsmasq_servers.j2
rename to xos/onboard/vsg/synchronizer/templates/dnsmasq_servers.j2
diff --git a/xos/synchronizers/vcpe/templates/firewall_sample.j2 b/xos/onboard/vsg/synchronizer/templates/firewall_sample.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/firewall_sample.j2
rename to xos/onboard/vsg/synchronizer/templates/firewall_sample.j2
diff --git a/xos/synchronizers/vcpe/templates/message.html.j2 b/xos/onboard/vsg/synchronizer/templates/message.html.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/message.html.j2
rename to xos/onboard/vsg/synchronizer/templates/message.html.j2
diff --git a/xos/synchronizers/vcpe/templates/rc.local.j2 b/xos/onboard/vsg/synchronizer/templates/rc.local.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/rc.local.j2
rename to xos/onboard/vsg/synchronizer/templates/rc.local.j2
diff --git a/xos/synchronizers/vcpe/templates/start-vcpe-vtn.sh.j2 b/xos/onboard/vsg/synchronizer/templates/start-vcpe-vtn.sh.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/start-vcpe-vtn.sh.j2
rename to xos/onboard/vsg/synchronizer/templates/start-vcpe-vtn.sh.j2
diff --git a/xos/synchronizers/vcpe/templates/start-vcpe.sh.j2 b/xos/onboard/vsg/synchronizer/templates/start-vcpe.sh.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/start-vcpe.sh.j2
rename to xos/onboard/vsg/synchronizer/templates/start-vcpe.sh.j2
diff --git a/xos/synchronizers/vcpe/templates/vcpe.conf.j2 b/xos/onboard/vsg/synchronizer/templates/vcpe.conf.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/vcpe.conf.j2
rename to xos/onboard/vsg/synchronizer/templates/vcpe.conf.j2
diff --git a/xos/synchronizers/vcpe/templates/vlan_sample.j2 b/xos/onboard/vsg/synchronizer/templates/vlan_sample.j2
similarity index 100%
rename from xos/synchronizers/vcpe/templates/vlan_sample.j2
rename to xos/onboard/vsg/synchronizer/templates/vlan_sample.j2
diff --git a/xos/synchronizers/vcpe/vcpe-synchronizer.py b/xos/onboard/vsg/synchronizer/vcpe-synchronizer.py
similarity index 100%
rename from xos/synchronizers/vcpe/vcpe-synchronizer.py
rename to xos/onboard/vsg/synchronizer/vcpe-synchronizer.py
diff --git a/xos/synchronizers/vcpe/vcpe_stats_notifier.py b/xos/onboard/vsg/synchronizer/vcpe_stats_notifier.py
similarity index 100%
rename from xos/synchronizers/vcpe/vcpe_stats_notifier.py
rename to xos/onboard/vsg/synchronizer/vcpe_stats_notifier.py
diff --git a/xos/synchronizers/vcpe/vcpe_synchronizer_config b/xos/onboard/vsg/synchronizer/vcpe_synchronizer_config
similarity index 73%
rename from xos/synchronizers/vcpe/vcpe_synchronizer_config
rename to xos/onboard/vsg/synchronizer/vcpe_synchronizer_config
index 110b8e2..e41dc9a 100644
--- a/xos/synchronizers/vcpe/vcpe_synchronizer_config
+++ b/xos/onboard/vsg/synchronizer/vcpe_synchronizer_config
@@ -23,10 +23,10 @@
 
 [observer]
 name=vcpe
-dependency_graph=/opt/xos/synchronizers/vcpe/model-deps
-steps_dir=/opt/xos/synchronizers/vcpe/steps
-sys_dir=/opt/xos/synchronizers/vcpe/sys
-deleters_dir=/opt/xos/synchronizers/vcpe/deleters
+dependency_graph=/opt/xos/synchronizers/vsg/model-deps
+steps_dir=/opt/xos/synchronizers/vsg/steps
+sys_dir=/opt/xos/synchronizers/vsg/sys
+deleters_dir=/opt/xos/synchronizers/vsg/deleters
 log_file=console
 #/var/log/hpc.log
 driver=None
diff --git a/xos/synchronizers/vcpe/vtn_vcpe_synchronizer_config b/xos/onboard/vsg/synchronizer/vtn_vcpe_synchronizer_config
similarity index 70%
rename from xos/synchronizers/vcpe/vtn_vcpe_synchronizer_config
rename to xos/onboard/vsg/synchronizer/vtn_vcpe_synchronizer_config
index e92786b..b43d831 100644
--- a/xos/synchronizers/vcpe/vtn_vcpe_synchronizer_config
+++ b/xos/onboard/vsg/synchronizer/vtn_vcpe_synchronizer_config
@@ -23,10 +23,10 @@
 
 [observer]
 name=vcpe
-dependency_graph=/opt/xos/synchronizers/vcpe/model-deps
-steps_dir=/opt/xos/synchronizers/vcpe/steps
-sys_dir=/opt/xos/synchronizers/vcpe/sys
-deleters_dir=/opt/xos/synchronizers/vcpe/deleters
+dependency_graph=/opt/xos/synchronizers/vsg/model-deps
+steps_dir=/opt/xos/synchronizers/vsg/steps
+sys_dir=/opt/xos/synchronizers/vsg/sys
+deleters_dir=/opt/xos/synchronizers/vsg/deleters
 log_file=console
 #/var/log/hpc.log
 driver=None
@@ -36,7 +36,7 @@
 # set proxy_ssh to false on cloudlab
 full_setup=True
 proxy_ssh=True
-proxy_ssh_key=/opt/xos/synchronizers/vcpe/node_key
+proxy_ssh_key=/opt/xos/synchronizers/vsg/node_key
 proxy_ssh_user=root
 
 [networking]
diff --git a/xos/services/cord/templates/vcpeadmin.html b/xos/onboard/vsg/templates/vcpeadmin.html
similarity index 100%
rename from xos/services/cord/templates/vcpeadmin.html
rename to xos/onboard/vsg/templates/vcpeadmin.html
diff --git a/xos/tosca/resources/vcpeservice.py b/xos/onboard/vsg/tosca/resources/vcpeservice.py
similarity index 91%
rename from xos/tosca/resources/vcpeservice.py
rename to xos/onboard/vsg/tosca/resources/vcpeservice.py
index 972c13c..956d888 100644
--- a/xos/tosca/resources/vcpeservice.py
+++ b/xos/onboard/vsg/tosca/resources/vcpeservice.py
@@ -5,7 +5,7 @@
 sys.path.append("/opt/tosca")
 from translator.toscalib.tosca_template import ToscaTemplate
 
-from services.cord.models import VSGService
+from services.vsg.models import VSGService
 
 from service import XOSService
 
diff --git a/xos/onboard/vsg/vsg-onboard.yaml b/xos/onboard/vsg/vsg-onboard.yaml
new file mode 100644
index 0000000..48f6ad4
--- /dev/null
+++ b/xos/onboard/vsg/vsg-onboard.yaml
@@ -0,0 +1,27 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    servicecontroller#vsg:
+      type: tosca.nodes.ServiceController
+      properties:
+          base_url: file:///opt/xos/onboard/vsg/
+          # The following will concatenate with base_url automatically, if
+          # base_url is non-null.
+          models: models.py
+          admin: admin.py
+          admin_template: templates/vcpeadmin.html
+          synchronizer: synchronizer/manifest
+          synchronizer_run: vcpe-synchronizer.py
+          #tosca_custom_types: exampleservice.yaml
+          tosca_resource: tosca/resources/vcpeservice.py
+          rest_service: subdirectory:vsg api/service/vsg/vsgservice.py
+          rest_tenant: subdirectory:cord api/tenant/cord/vsg.py
+          private_key: file:///opt/xos/key_import/vsg_rsa
+          public_key: file:///opt/xos/key_import/vsg_rsa.pub
+
diff --git a/xos/services/vtn/admin.py b/xos/onboard/vtn/admin.py
similarity index 97%
rename from xos/services/vtn/admin.py
rename to xos/onboard/vtn/admin.py
index 03ff5cd..464f197 100644
--- a/xos/services/vtn/admin.py
+++ b/xos/onboard/vtn/admin.py
@@ -1,6 +1,5 @@
 from django.contrib import admin
 
-from services.cord.models import *
 from django import forms
 from django.utils.safestring import mark_safe
 from django.contrib.auth.admin import UserAdmin
@@ -14,7 +13,6 @@
 from core.middleware import get_request
 
 from services.vtn.models import *
-from services.cord.models import CordSubscriberRoot
 
 from functools import update_wrapper
 from django.contrib.admin.views.main import ChangeList
diff --git a/xos/api/service/vtn.py b/xos/onboard/vtn/api/service/vtn.py
similarity index 100%
rename from xos/api/service/vtn.py
rename to xos/onboard/vtn/api/service/vtn.py
diff --git a/xos/services/vtn/models.py b/xos/onboard/vtn/models.py
similarity index 96%
rename from xos/services/vtn/models.py
rename to xos/onboard/vtn/models.py
index 52b1633..c805f24 100644
--- a/xos/services/vtn/models.py
+++ b/xos/onboard/vtn/models.py
@@ -8,7 +8,6 @@
 from operator import itemgetter, attrgetter, methodcaller
 from core.models import Tag
 from core.models.service import LeastLoadedNodeScheduler
-from services.cord.models import CordSubscriberRoot
 import traceback
 from xos.exceptions import *
 from xos.config import Config
diff --git a/xos/onboard/vtn/synchronizer/manifest b/xos/onboard/vtn/synchronizer/manifest
new file mode 100644
index 0000000..dccfcdc
--- /dev/null
+++ b/xos/onboard/vtn/synchronizer/manifest
@@ -0,0 +1,10 @@
+manifest
+vtn-synchronizer.py
+steps/sync_tenant.py
+steps/sync_port_addresses.py
+start.sh
+stop.sh
+model-deps
+supervisor/vtn-observer.conf
+run.sh
+vtn_synchronizer_config
diff --git a/xos/synchronizers/vbng/model-deps b/xos/onboard/vtn/synchronizer/model-deps
similarity index 100%
copy from xos/synchronizers/vbng/model-deps
copy to xos/onboard/vtn/synchronizer/model-deps
diff --git a/xos/synchronizers/vtn/run.sh b/xos/onboard/vtn/synchronizer/run.sh
similarity index 100%
rename from xos/synchronizers/vtn/run.sh
rename to xos/onboard/vtn/synchronizer/run.sh
diff --git a/xos/synchronizers/vtn/start.sh b/xos/onboard/vtn/synchronizer/start.sh
similarity index 100%
rename from xos/synchronizers/vtn/start.sh
rename to xos/onboard/vtn/synchronizer/start.sh
diff --git a/xos/synchronizers/vtn/steps/sync_port_addresses.py b/xos/onboard/vtn/synchronizer/steps/sync_port_addresses.py
similarity index 96%
rename from xos/synchronizers/vtn/steps/sync_port_addresses.py
rename to xos/onboard/vtn/synchronizer/steps/sync_port_addresses.py
index bbc6c99..553df6f 100644
--- a/xos/synchronizers/vtn/steps/sync_port_addresses.py
+++ b/xos/onboard/vtn/synchronizer/steps/sync_port_addresses.py
@@ -6,10 +6,9 @@
 from django.db.models import F, Q
 from xos.config import Config
 from synchronizers.base.syncstep import SyncStep
-from core.models import Service, Port, Controller, Tag
+from core.models import Service, Port, Controller, Tag, Tenant
 from core.models.service import COARSE_KIND
-from services.cord.models import VSGTenant
-from services.cord.models import Tenant
+from services.vsg.models import VSGTenant
 from xos.logger import Logger, logging
 from requests.auth import HTTPBasicAuth
 
diff --git a/xos/synchronizers/vtn/steps/sync_tenant.py b/xos/onboard/vtn/synchronizer/steps/sync_tenant.py
similarity index 97%
rename from xos/synchronizers/vtn/steps/sync_tenant.py
rename to xos/onboard/vtn/synchronizer/steps/sync_tenant.py
index cc374be..a0e6cdb 100644
--- a/xos/synchronizers/vtn/steps/sync_tenant.py
+++ b/xos/onboard/vtn/synchronizer/steps/sync_tenant.py
@@ -6,9 +6,8 @@
 from django.db.models import F, Q
 from xos.config import Config
 from synchronizers.base.syncstep import SyncStep
-from core.models import Service
+from core.models import Service, Tenant
 from core.models.service import COARSE_KIND
-from services.cord.models import Tenant
 from xos.logger import Logger, logging
 from requests.auth import HTTPBasicAuth
 
diff --git a/xos/synchronizers/vtn/stop.sh b/xos/onboard/vtn/synchronizer/stop.sh
similarity index 100%
rename from xos/synchronizers/vtn/stop.sh
rename to xos/onboard/vtn/synchronizer/stop.sh
diff --git a/xos/synchronizers/vtn/supervisor/vtn-observer.conf b/xos/onboard/vtn/synchronizer/supervisor/vtn-observer.conf
similarity index 100%
rename from xos/synchronizers/vtn/supervisor/vtn-observer.conf
rename to xos/onboard/vtn/synchronizer/supervisor/vtn-observer.conf
diff --git a/xos/synchronizers/vtn/vtn-synchronizer.py b/xos/onboard/vtn/synchronizer/vtn-synchronizer.py
similarity index 100%
rename from xos/synchronizers/vtn/vtn-synchronizer.py
rename to xos/onboard/vtn/synchronizer/vtn-synchronizer.py
diff --git a/xos/synchronizers/vtn/vtn_synchronizer_config b/xos/onboard/vtn/synchronizer/vtn_synchronizer_config
similarity index 100%
rename from xos/synchronizers/vtn/vtn_synchronizer_config
rename to xos/onboard/vtn/synchronizer/vtn_synchronizer_config
diff --git a/xos/services/vtn/templates/vtnadmin.html b/xos/onboard/vtn/templates/vtnadmin.html
similarity index 100%
rename from xos/services/vtn/templates/vtnadmin.html
rename to xos/onboard/vtn/templates/vtnadmin.html
diff --git a/xos/tosca/resources/vtnservice.py b/xos/onboard/vtn/tosca/resources/vtnservice.py
similarity index 100%
rename from xos/tosca/resources/vtnservice.py
rename to xos/onboard/vtn/tosca/resources/vtnservice.py
diff --git a/xos/onboard/vtn/vtn-onboard.yaml b/xos/onboard/vtn/vtn-onboard.yaml
new file mode 100644
index 0000000..460af5a
--- /dev/null
+++ b/xos/onboard/vtn/vtn-onboard.yaml
@@ -0,0 +1,25 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    servicecontroller#vtn:
+      type: tosca.nodes.ServiceController
+      properties:
+          base_url: file:///opt/xos/onboard/vtn/
+          # The following will concatenate with base_url automatically, if
+          # base_url is non-null.
+          models: models.py
+          admin: admin.py
+          admin_template: templates/vtnadmin.html
+          synchronizer: synchronizer/manifest
+          synchronizer_run: vtn-synchronizer.py
+          tosca_resource: tosca/resources/vtnservice.py
+          rest_service: api/service/vtn.py
+          #private_key: file:///opt/xos/key_import/vsg_rsa
+          #public_key: file:///opt/xos/key_import/vsg_rsa.pub
+
diff --git a/xos/services/vtr/admin.py b/xos/onboard/vtr/admin.py
similarity index 98%
rename from xos/services/vtr/admin.py
rename to xos/onboard/vtr/admin.py
index 5015fc8..0120e66 100644
--- a/xos/services/vtr/admin.py
+++ b/xos/onboard/vtr/admin.py
@@ -1,6 +1,5 @@
 from django.contrib import admin
 
-from services.cord.models import *
 from django import forms
 from django.utils.safestring import mark_safe
 from django.contrib.auth.admin import UserAdmin
@@ -14,7 +13,7 @@
 from core.middleware import get_request
 
 from services.vtr.models import *
-from services.cord.models import CordSubscriberRoot
+from services.volt.models import CordSubscriberRoot
 
 from functools import update_wrapper
 from django.contrib.admin.views.main import ChangeList
diff --git a/xos/api/tenant/truckroll.py b/xos/onboard/vtr/api/tenant/truckroll.py
similarity index 97%
rename from xos/api/tenant/truckroll.py
rename to xos/onboard/vtr/api/tenant/truckroll.py
index b5e9e3f..cc8d62b 100644
--- a/xos/api/tenant/truckroll.py
+++ b/xos/onboard/vtr/api/tenant/truckroll.py
@@ -6,7 +6,6 @@
 from rest_framework import status
 from core.models import *
 from django.forms import widgets
-from services.cord.models import CordSubscriberRoot
 from services.vtr.models import VTRTenant, VTRService
 from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
 from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
diff --git a/xos/services/vtr/models.py b/xos/onboard/vtr/models.py
similarity index 97%
rename from xos/services/vtr/models.py
rename to xos/onboard/vtr/models.py
index 31c26c4..ce2e345 100644
--- a/xos/services/vtr/models.py
+++ b/xos/onboard/vtr/models.py
@@ -8,7 +8,7 @@
 from operator import itemgetter, attrgetter, methodcaller
 from core.models import Tag
 from core.models.service import LeastLoadedNodeScheduler
-from services.cord.models import CordSubscriberRoot
+from services.volt.models import CordSubscriberRoot
 import traceback
 from xos.exceptions import *
 from xos.config import Config
diff --git a/xos/synchronizers/vtr/files/run_tcpdump.sh b/xos/onboard/vtr/synchronizer/files/run_tcpdump.sh
similarity index 100%
rename from xos/synchronizers/vtr/files/run_tcpdump.sh
rename to xos/onboard/vtr/synchronizer/files/run_tcpdump.sh
diff --git a/xos/onboard/vtr/synchronizer/manifest b/xos/onboard/vtr/synchronizer/manifest
new file mode 100644
index 0000000..61ffb39
--- /dev/null
+++ b/xos/onboard/vtr/synchronizer/manifest
@@ -0,0 +1,10 @@
+manifest
+vtr-synchronizer.py
+vtn_vtr_synchronizer_config
+steps/sync_vtrtenant.py
+steps/sync_vtrtenant.yaml
+vtr_synchronizer_config
+files/run_tcpdump.sh
+run-vtn.sh
+model-deps
+run.sh
diff --git a/xos/synchronizers/vbng/model-deps b/xos/onboard/vtr/synchronizer/model-deps
similarity index 100%
copy from xos/synchronizers/vbng/model-deps
copy to xos/onboard/vtr/synchronizer/model-deps
diff --git a/xos/synchronizers/vtr/run-vtn.sh b/xos/onboard/vtr/synchronizer/run-vtn.sh
similarity index 100%
rename from xos/synchronizers/vtr/run-vtn.sh
rename to xos/onboard/vtr/synchronizer/run-vtn.sh
diff --git a/xos/synchronizers/vtr/run.sh b/xos/onboard/vtr/synchronizer/run.sh
similarity index 100%
rename from xos/synchronizers/vtr/run.sh
rename to xos/onboard/vtr/synchronizer/run.sh
diff --git a/xos/synchronizers/vtr/steps/sync_vtrtenant.py b/xos/onboard/vtr/synchronizer/steps/sync_vtrtenant.py
similarity index 87%
rename from xos/synchronizers/vtr/steps/sync_vtrtenant.py
rename to xos/onboard/vtr/synchronizer/steps/sync_vtrtenant.py
index c66f19c..f0f7ef3 100644
--- a/xos/synchronizers/vtr/steps/sync_vtrtenant.py
+++ b/xos/onboard/vtr/synchronizer/steps/sync_vtrtenant.py
@@ -9,7 +9,7 @@
 from synchronizers.base.ansible import run_template_ssh
 from synchronizers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
 from core.models import Service, Slice, Tag
-from services.cord.models import VSGService, VSGTenant, VOLTTenant, CordSubscriberRoot
+from services.vsg.models import VSGService, VCPE_KIND
 from services.vtr.models import VTRService, VTRTenant
 from services.hpc.models import HpcService, CDNPrefix
 from xos.logger import Logger, logging
@@ -27,7 +27,7 @@
     observes=VTRTenant
     requested_interval=0
     template_name = "sync_vtrtenant.yaml"
-    service_key_name = "/opt/xos/synchronizers/vtr/vcpe_private_key"
+    #service_key_name = "/opt/xos/services/vtr/vcpe_private_key"
 
     def __init__(self, *args, **kwargs):
         super(SyncVTRTenant, self).__init__(*args, **kwargs)
@@ -66,6 +66,15 @@
         else:
             return None
 
+    def get_key_name(self, instance):
+        if instance.slice.service and (instance.slice.service.kind==VCPE_KIND):
+            # We need to use the vsg service's private key. Onboarding won't
+            # by default give us another service's private key, so let's assume
+            # onboarding has been configured to add vsg_rsa to the vtr service.
+            return "/opt/xos/services/vtr/keys/vsg_rsa"
+        else:
+            raise Exception("VTR doesn't know how to get the private key for this instance")
+
     def get_extra_attributes(self, o):
         vtr_service = self.get_vtr_service(o)
         vcpe_service = self.get_vcpe_service(o)
diff --git a/xos/synchronizers/vtr/steps/sync_vtrtenant.yaml b/xos/onboard/vtr/synchronizer/steps/sync_vtrtenant.yaml
similarity index 100%
rename from xos/synchronizers/vtr/steps/sync_vtrtenant.yaml
rename to xos/onboard/vtr/synchronizer/steps/sync_vtrtenant.yaml
diff --git a/xos/synchronizers/vtr/vtn_vtr_synchronizer_config b/xos/onboard/vtr/synchronizer/vtn_vtr_synchronizer_config
similarity index 100%
rename from xos/synchronizers/vtr/vtn_vtr_synchronizer_config
rename to xos/onboard/vtr/synchronizer/vtn_vtr_synchronizer_config
diff --git a/xos/synchronizers/vtr/vtr-synchronizer.py b/xos/onboard/vtr/synchronizer/vtr-synchronizer.py
similarity index 100%
rename from xos/synchronizers/vtr/vtr-synchronizer.py
rename to xos/onboard/vtr/synchronizer/vtr-synchronizer.py
diff --git a/xos/synchronizers/vtr/vtr_synchronizer_config b/xos/onboard/vtr/synchronizer/vtr_synchronizer_config
similarity index 100%
rename from xos/synchronizers/vtr/vtr_synchronizer_config
rename to xos/onboard/vtr/synchronizer/vtr_synchronizer_config
diff --git a/xos/services/vtr/templates/vtradmin.html b/xos/onboard/vtr/templates/vtradmin.html
similarity index 100%
rename from xos/services/vtr/templates/vtradmin.html
rename to xos/onboard/vtr/templates/vtradmin.html
diff --git a/xos/onboard/vtr/vtr-onboard.yaml b/xos/onboard/vtr/vtr-onboard.yaml
new file mode 100644
index 0000000..38dddd1
--- /dev/null
+++ b/xos/onboard/vtr/vtr-onboard.yaml
@@ -0,0 +1,24 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    servicecontroller#vtr:
+      type: tosca.nodes.ServiceController
+      properties:
+          base_url: file:///opt/xos/onboard/vtr/
+          # The following will concatenate with base_url automatically, if
+          # base_url is non-null.
+          models: models.py
+          admin: admin.py
+          admin_template: templates/vtradmin.html
+          synchronizer: synchronizer/manifest
+          synchronizer_run: vtr-synchronizer.py
+          rest_tenant: api/tenant/truckroll.py
+          private_key: file:///opt/xos/key_import/vsg_rsa
+          public_key: file:///opt/xos/key_import/vsg_rsa.pub
+
diff --git a/xos/services/ceilometer/__init__.py b/xos/services/ceilometer/__init__.py
deleted file mode 100644
index 8b13789..0000000
--- a/xos/services/ceilometer/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/xos/services/ceilometer/migrations/0001_initial.py b/xos/services/ceilometer/migrations/0001_initial.py
deleted file mode 100644
index 6a3dd15..0000000
--- a/xos/services/ceilometer/migrations/0001_initial.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='CeilometerService',
-            fields=[
-            ],
-            options={
-                'verbose_name': 'Ceilometer Service',
-                'proxy': True,
-            },
-            bases=('core.service',),
-        ),
-        migrations.CreateModel(
-            name='MonitoringChannel',
-            fields=[
-            ],
-            options={
-                'proxy': True,
-            },
-            bases=('core.tenantwithcontainer',),
-        ),
-        migrations.CreateModel(
-            name='SFlowService',
-            fields=[
-            ],
-            options={
-                'verbose_name': 'sFlow Collection Service',
-                'proxy': True,
-            },
-            bases=('core.service',),
-        ),
-        migrations.CreateModel(
-            name='SFlowTenant',
-            fields=[
-            ],
-            options={
-                'proxy': True,
-            },
-            bases=('core.tenant',),
-        ),
-    ]
diff --git a/xos/services/ceilometer/migrations/__init__.py b/xos/services/ceilometer/migrations/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/xos/services/ceilometer/migrations/__init__.py
+++ /dev/null
diff --git a/xos/services/cord/migrations/0001_initial.py b/xos/services/cord/migrations/0001_initial.py
deleted file mode 100644
index 3651371..0000000
--- a/xos/services/cord/migrations/0001_initial.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='CordSubscriberRoot',
-            fields=[
-            ],
-            options={
-                'proxy': True,
-            },
-            bases=('core.subscriber',),
-        ),
-        migrations.CreateModel(
-            name='VBNGService',
-            fields=[
-            ],
-            options={
-                'verbose_name': 'vBNG Service',
-                'proxy': True,
-            },
-            bases=('core.service',),
-        ),
-        migrations.CreateModel(
-            name='VBNGTenant',
-            fields=[
-            ],
-            options={
-                'proxy': True,
-            },
-            bases=('core.tenant',),
-        ),
-        migrations.CreateModel(
-            name='VOLTService',
-            fields=[
-            ],
-            options={
-                'verbose_name': 'vOLT Service',
-                'proxy': True,
-            },
-            bases=('core.service',),
-        ),
-        migrations.CreateModel(
-            name='VOLTTenant',
-            fields=[
-            ],
-            options={
-                'proxy': True,
-            },
-            bases=('core.tenant',),
-        ),
-        migrations.CreateModel(
-            name='VSGService',
-            fields=[
-            ],
-            options={
-                'verbose_name': 'vSG Service',
-                'proxy': True,
-            },
-            bases=('core.service',),
-        ),
-        migrations.CreateModel(
-            name='VSGTenant',
-            fields=[
-            ],
-            options={
-                'proxy': True,
-            },
-            bases=('core.tenantwithcontainer',),
-        ),
-    ]
diff --git a/xos/services/cord/__init__.py b/xos/services/cord_old/__init__.py
similarity index 100%
rename from xos/services/cord/__init__.py
rename to xos/services/cord_old/__init__.py
diff --git a/xos/services/cord/admin.py b/xos/services/cord_old/admin.py
similarity index 100%
rename from xos/services/cord/admin.py
rename to xos/services/cord_old/admin.py
diff --git a/xos/services/cord_old/migrations/0001_initial.py b/xos/services/cord_old/migrations/0001_initial.py
new file mode 100644
index 0000000..75e30f5
--- /dev/null
+++ b/xos/services/cord_old/migrations/0001_initial.py
@@ -0,0 +1,197 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import core.models.plcorebase
+import django.utils.timezone
+from django.conf import settings
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('core', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='AccessAgent',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('updated', models.DateTimeField(default=django.utils.timezone.now)),
+                ('enacted', models.DateTimeField(default=None, null=True, blank=True)),
+                ('policed', models.DateTimeField(default=None, null=True, blank=True)),
+                ('backend_register', models.CharField(default=b'{}', max_length=1024, null=True)),
+                ('backend_status', models.CharField(default=b'0 - Provisioning in progress', max_length=1024)),
+                ('deleted', models.BooleanField(default=False)),
+                ('write_protect', models.BooleanField(default=False)),
+                ('lazy_blocked', models.BooleanField(default=False)),
+                ('no_sync', models.BooleanField(default=False)),
+                ('no_policy', models.BooleanField(default=False)),
+                ('name', models.CharField(help_text=b'name of agent', max_length=254)),
+                ('mac', models.CharField(help_text=b'MAC Address or Access Agent', max_length=32, null=True, blank=True)),
+            ],
+            options={
+            },
+            bases=(models.Model, core.models.plcorebase.PlModelMixIn),
+        ),
+        migrations.CreateModel(
+            name='AccessDevice',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('updated', models.DateTimeField(default=django.utils.timezone.now)),
+                ('enacted', models.DateTimeField(default=None, null=True, blank=True)),
+                ('policed', models.DateTimeField(default=None, null=True, blank=True)),
+                ('backend_register', models.CharField(default=b'{}', max_length=1024, null=True)),
+                ('backend_status', models.CharField(default=b'0 - Provisioning in progress', max_length=1024)),
+                ('deleted', models.BooleanField(default=False)),
+                ('write_protect', models.BooleanField(default=False)),
+                ('lazy_blocked', models.BooleanField(default=False)),
+                ('no_sync', models.BooleanField(default=False)),
+                ('no_policy', models.BooleanField(default=False)),
+                ('uplink', models.IntegerField(null=True, blank=True)),
+                ('vlan', models.IntegerField(null=True, blank=True)),
+            ],
+            options={
+            },
+            bases=(models.Model, core.models.plcorebase.PlModelMixIn),
+        ),
+        migrations.CreateModel(
+            name='AgentPortMapping',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('updated', models.DateTimeField(default=django.utils.timezone.now)),
+                ('enacted', models.DateTimeField(default=None, null=True, blank=True)),
+                ('policed', models.DateTimeField(default=None, null=True, blank=True)),
+                ('backend_register', models.CharField(default=b'{}', max_length=1024, null=True)),
+                ('backend_status', models.CharField(default=b'0 - Provisioning in progress', max_length=1024)),
+                ('deleted', models.BooleanField(default=False)),
+                ('write_protect', models.BooleanField(default=False)),
+                ('lazy_blocked', models.BooleanField(default=False)),
+                ('no_sync', models.BooleanField(default=False)),
+                ('no_policy', models.BooleanField(default=False)),
+                ('mac', models.CharField(help_text=b'MAC Address', max_length=32, null=True, blank=True)),
+                ('port', models.CharField(help_text=b'Openflow port ID', max_length=32, null=True, blank=True)),
+                ('access_agent', models.ForeignKey(related_name=b'port_mappings', to='cord.AccessAgent')),
+            ],
+            options={
+            },
+            bases=(models.Model, core.models.plcorebase.PlModelMixIn),
+        ),
+        migrations.CreateModel(
+            name='VOLTDevice',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('updated', models.DateTimeField(default=django.utils.timezone.now)),
+                ('enacted', models.DateTimeField(default=None, null=True, blank=True)),
+                ('policed', models.DateTimeField(default=None, null=True, blank=True)),
+                ('backend_register', models.CharField(default=b'{}', max_length=1024, null=True)),
+                ('backend_status', models.CharField(default=b'0 - Provisioning in progress', max_length=1024)),
+                ('deleted', models.BooleanField(default=False)),
+                ('write_protect', models.BooleanField(default=False)),
+                ('lazy_blocked', models.BooleanField(default=False)),
+                ('no_sync', models.BooleanField(default=False)),
+                ('no_policy', models.BooleanField(default=False)),
+                ('name', models.CharField(help_text=b'name of device', max_length=254)),
+                ('openflow_id', models.CharField(help_text=b'OpenFlow ID', max_length=254, null=True, blank=True)),
+                ('driver', models.CharField(help_text=b'driver', max_length=254, null=True, blank=True)),
+                ('access_agent', models.ForeignKey(related_name=b'volt_devices', blank=True, to='cord.AccessAgent', null=True)),
+            ],
+            options={
+            },
+            bases=(models.Model, core.models.plcorebase.PlModelMixIn),
+        ),
+        migrations.CreateModel(
+            name='VOLTService',
+            fields=[
+                ('service_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='core.Service')),
+            ],
+            options={
+                'verbose_name': 'vOLT Service',
+            },
+            bases=('core.service',),
+        ),
+        migrations.CreateModel(
+            name='VOLTTenant',
+            fields=[
+                ('tenant_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='core.Tenant')),
+                ('s_tag', models.IntegerField(help_text=b's-tag', null=True, blank=True)),
+                ('c_tag', models.IntegerField(help_text=b'c-tag', null=True, blank=True)),
+                ('creator', models.ForeignKey(related_name=b'created_volts', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
+            ],
+            options={
+                'verbose_name': 'vOLT Tenant',
+            },
+            bases=('core.tenant',),
+        ),
+        migrations.AddField(
+            model_name='voltdevice',
+            name='volt_service',
+            field=models.ForeignKey(related_name=b'volt_devices', to='cord.VOLTService'),
+            preserve_default=True,
+        ),
+        migrations.AddField(
+            model_name='accessdevice',
+            name='volt_device',
+            field=models.ForeignKey(related_name=b'access_devices', to='cord.VOLTDevice'),
+            preserve_default=True,
+        ),
+        migrations.AddField(
+            model_name='accessagent',
+            name='volt_service',
+            field=models.ForeignKey(related_name=b'access_agents', to='cord.VOLTService'),
+            preserve_default=True,
+        ),
+        migrations.CreateModel(
+            name='CordSubscriberRoot',
+            fields=[
+            ],
+            options={
+                'proxy': True,
+            },
+            bases=('core.subscriber',),
+        ),
+        migrations.CreateModel(
+            name='VBNGService',
+            fields=[
+            ],
+            options={
+                'verbose_name': 'vBNG Service',
+                'proxy': True,
+            },
+            bases=('core.service',),
+        ),
+        migrations.CreateModel(
+            name='VBNGTenant',
+            fields=[
+            ],
+            options={
+                'proxy': True,
+            },
+            bases=('core.tenant',),
+        ),
+        migrations.CreateModel(
+            name='VSGService',
+            fields=[
+            ],
+            options={
+                'verbose_name': 'vSG Service',
+                'proxy': True,
+            },
+            bases=('core.service',),
+        ),
+        migrations.CreateModel(
+            name='VSGTenant',
+            fields=[
+            ],
+            options={
+                'proxy': True,
+            },
+            bases=('core.tenantwithcontainer',),
+        ),
+    ]
diff --git a/xos/services/cord/migrations/__init__.py b/xos/services/cord_old/migrations/__init__.py
similarity index 100%
rename from xos/services/cord/migrations/__init__.py
rename to xos/services/cord_old/migrations/__init__.py
diff --git a/xos/services/cord/models.py b/xos/services/cord_old/models.py
similarity index 100%
rename from xos/services/cord/models.py
rename to xos/services/cord_old/models.py
diff --git a/xos/services/cord/rest_examples/add_truckroll.sh b/xos/services/cord_old/rest_examples/add_truckroll.sh
similarity index 100%
rename from xos/services/cord/rest_examples/add_truckroll.sh
rename to xos/services/cord_old/rest_examples/add_truckroll.sh
diff --git a/xos/services/cord/rest_examples/add_volt_tenant.sh b/xos/services/cord_old/rest_examples/add_volt_tenant.sh
similarity index 100%
rename from xos/services/cord/rest_examples/add_volt_tenant.sh
rename to xos/services/cord_old/rest_examples/add_volt_tenant.sh
diff --git a/xos/services/cord/rest_examples/config.sh b/xos/services/cord_old/rest_examples/config.sh
similarity index 100%
rename from xos/services/cord/rest_examples/config.sh
rename to xos/services/cord_old/rest_examples/config.sh
diff --git a/xos/services/cord/rest_examples/delete_volt_tenant.sh b/xos/services/cord_old/rest_examples/delete_volt_tenant.sh
similarity index 100%
rename from xos/services/cord/rest_examples/delete_volt_tenant.sh
rename to xos/services/cord_old/rest_examples/delete_volt_tenant.sh
diff --git a/xos/services/cord/rest_examples/list_cord_subscribers.sh b/xos/services/cord_old/rest_examples/list_cord_subscribers.sh
similarity index 100%
rename from xos/services/cord/rest_examples/list_cord_subscribers.sh
rename to xos/services/cord_old/rest_examples/list_cord_subscribers.sh
diff --git a/xos/services/cord/rest_examples/list_truckrolls.sh b/xos/services/cord_old/rest_examples/list_truckrolls.sh
similarity index 100%
rename from xos/services/cord/rest_examples/list_truckrolls.sh
rename to xos/services/cord_old/rest_examples/list_truckrolls.sh
diff --git a/xos/services/cord/rest_examples/list_volt_tenants.sh b/xos/services/cord_old/rest_examples/list_volt_tenants.sh
similarity index 100%
rename from xos/services/cord/rest_examples/list_volt_tenants.sh
rename to xos/services/cord_old/rest_examples/list_volt_tenants.sh
diff --git a/xos/services/cord/templates/vbngadmin.html b/xos/services/cord_old/templates/vbngadmin.html
similarity index 100%
rename from xos/services/cord/templates/vbngadmin.html
rename to xos/services/cord_old/templates/vbngadmin.html
diff --git a/xos/services/fabric/__init__.py b/xos/services/fabric/__init__.py
deleted file mode 100644
index 8b13789..0000000
--- a/xos/services/fabric/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/xos/services/mcord/migrations/0001_initial.py b/xos/services/mcord/migrations/0001_initial.py
index c53e548..a11fe30 100644
--- a/xos/services/mcord/migrations/0001_initial.py
+++ b/xos/services/mcord/migrations/0001_initial.py
@@ -31,4 +31,14 @@
             },
             bases=('core.tenantwithcontainer',),
         ),
+        migrations.CreateModel(
+            name='VPGWCComponent',
+            fields=[
+            ],
+            options={
+                'verbose_name': 'VPGWC MCORD Service Component',
+                'proxy': True,
+            },
+            bases=('core.tenantwithcontainer',),
+        ),
     ]
diff --git a/xos/services/onos/__init__.py b/xos/services/onos/__init__.py
deleted file mode 100644
index 8b13789..0000000
--- a/xos/services/onos/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/xos/services/onos/migrations/0001_initial.py b/xos/services/onos/migrations/0001_initial.py
deleted file mode 100644
index 1df9da7..0000000
--- a/xos/services/onos/migrations/0001_initial.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='ONOSApp',
-            fields=[
-            ],
-            options={
-                'proxy': True,
-            },
-            bases=('core.tenant',),
-        ),
-        migrations.CreateModel(
-            name='ONOSService',
-            fields=[
-            ],
-            options={
-                'verbose_name': 'ONOS Service',
-                'proxy': True,
-            },
-            bases=('core.service',),
-        ),
-    ]
diff --git a/xos/services/onos/migrations/__init__.py b/xos/services/onos/migrations/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/xos/services/onos/migrations/__init__.py
+++ /dev/null
diff --git a/xos/services/vrouter/__init__.py b/xos/services/vrouter/__init__.py
deleted file mode 100644
index 8b13789..0000000
--- a/xos/services/vrouter/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/xos/services/vrouter/migrations/0001_initial.py b/xos/services/vrouter/migrations/0001_initial.py
deleted file mode 100644
index f11fc91..0000000
--- a/xos/services/vrouter/migrations/0001_initial.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='VRouterService',
-            fields=[
-            ],
-            options={
-                'verbose_name': 'vRouter Service',
-                'proxy': True,
-            },
-            bases=('core.service',),
-        ),
-        migrations.CreateModel(
-            name='VRouterTenant',
-            fields=[
-            ],
-            options={
-                'proxy': True,
-            },
-            bases=('core.tenant',),
-        ),
-    ]
diff --git a/xos/services/vrouter/migrations/__init__.py b/xos/services/vrouter/migrations/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/xos/services/vrouter/migrations/__init__.py
+++ /dev/null
diff --git a/xos/services/vtn/__init__.py b/xos/services/vtn/__init__.py
deleted file mode 100644
index 8b13789..0000000
--- a/xos/services/vtn/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/xos/services/vtn/migrations/0001_initial.py b/xos/services/vtn/migrations/0001_initial.py
deleted file mode 100644
index 90bf43f..0000000
--- a/xos/services/vtn/migrations/0001_initial.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='VTNService',
-            fields=[
-            ],
-            options={
-                'verbose_name': 'VTN Service',
-                'proxy': True,
-            },
-            bases=('core.service',),
-        ),
-    ]
diff --git a/xos/services/vtn/migrations/__init__.py b/xos/services/vtn/migrations/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/xos/services/vtn/migrations/__init__.py
+++ /dev/null
diff --git a/xos/services/vtr/__init__.py b/xos/services/vtr/__init__.py
deleted file mode 100644
index 8b13789..0000000
--- a/xos/services/vtr/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/xos/services/vtr/migrations/0001_initial.py b/xos/services/vtr/migrations/0001_initial.py
deleted file mode 100644
index 540eccb..0000000
--- a/xos/services/vtr/migrations/0001_initial.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='VTRService',
-            fields=[
-            ],
-            options={
-                'verbose_name': 'vTR Service',
-                'proxy': True,
-            },
-            bases=('core.service',),
-        ),
-        migrations.CreateModel(
-            name='VTRTenant',
-            fields=[
-            ],
-            options={
-                'proxy': True,
-            },
-            bases=('core.tenant',),
-        ),
-    ]
diff --git a/xos/services/vtr/migrations/__init__.py b/xos/services/vtr/migrations/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/xos/services/vtr/migrations/__init__.py
+++ /dev/null
diff --git a/xos/synchronizers/base/SyncInstanceUsingAnsible.py b/xos/synchronizers/base/SyncInstanceUsingAnsible.py
index 49ca23b..dd7e5c6 100644
--- a/xos/synchronizers/base/SyncInstanceUsingAnsible.py
+++ b/xos/synchronizers/base/SyncInstanceUsingAnsible.py
@@ -82,6 +82,21 @@
     def get_node_key(self, node):
         return "/root/setup/node_key"
 
+    def get_key_name(self, instance):
+        if instance.isolation=="vm":
+            if (instance.slice) and (instance.slice.service) and (instance.slice.service.private_key_fn):
+                key_name = instance.slice.service.private_key_fn
+            else:
+                raise Exception("Make sure to set private_key_fn in the service")
+        elif instance.isolation=="container":
+            node = self.get_node(instance)
+            key_name = self.get_node_key(node)
+        else:
+            # container in VM
+            key_name = instance.parent.slice.service.private_key_fn
+
+        return key_name
+
     def get_ansible_fields(self, instance):
         # return all of the fields that tell Ansible how to talk to the context
         # that's setting up the container.
@@ -95,10 +110,7 @@
                        "username": "ubuntu",
                        "ssh_ip": instance.get_ssh_ip(),
                      }
-            if (instance.slice) and (instance.slice.service) and (instance.slice.service.private_key_fn):
-                key_name = instance.slice.service.private_key_fn
-            else:
-                raise Exception("Make sure to set private_key_fn in the service")
+
         elif (instance.isolation == "container"):
             # container on bare metal
             node = self.get_node(instance)
@@ -110,7 +122,6 @@
                        "container_name": "%s-%s" % (instance.slice.name, str(instance.id))
                        # ssh_ip is not used for container-on-metal
                      }
-            key_name = self.get_node_key(node)
         else:
             # container in a VM
             if not instance.parent:
@@ -128,8 +139,8 @@
                        "ssh_ip": instance.parent.get_ssh_ip(),
                        "container_name": "%s-%s" % (instance.slice.name, str(instance.id))
                          }
-            key_name = instance.parent.slice.service.private_key_fn
 
+        key_name = self.get_key_name(instance)
         if not os.path.exists(key_name):
             raise Exception("Node key %s does not exist" % key_name)
 
diff --git a/xos/synchronizers/base/backend.py b/xos/synchronizers/base/backend.py
index af51e73..206c27f 100644
--- a/xos/synchronizers/base/backend.py
+++ b/xos/synchronizers/base/backend.py
@@ -3,7 +3,7 @@
 import threading
 import time
 from synchronizers.base.event_loop import XOSObserver
-from synchronizers.base.event_manager import EventListener
+#from synchronizers.base.event_manager import EventListener
 from xos.logger import Logger, logging
 from synchronizers.model_policy import run_policy
 from xos.config import Config
diff --git a/xos/synchronizers/monitoring_channel/model-deps b/xos/synchronizers/monitoring_channel/model-deps
deleted file mode 100644
index 0967ef4..0000000
--- a/xos/synchronizers/monitoring_channel/model-deps
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/xos/synchronizers/onboarding/steps/sync_xos.py b/xos/synchronizers/onboarding/steps/sync_xos.py
index dec7a34..567e0ad 100644
--- a/xos/synchronizers/onboarding/steps/sync_xos.py
+++ b/xos/synchronizers/onboarding/steps/sync_xos.py
@@ -29,6 +29,9 @@
     def sync_record(self, xos):
         logger.info("Sync'ing XOS %s" % xos)
 
+        if not xos.docker_project_name:
+            raise Exception("xos.docker_project_name is not set")
+
         if (not xos.enable_build):
             raise DeferredException("XOS build is currently disabled")
 
diff --git a/xos/synchronizers/onboarding/xosbuilder.py b/xos/synchronizers/onboarding/xosbuilder.py
index ffb66ee..51499bd 100644
--- a/xos/synchronizers/onboarding/xosbuilder.py
+++ b/xos/synchronizers/onboarding/xosbuilder.py
@@ -14,12 +14,11 @@
 logger = Logger(level=logging.INFO)
 
 class XOSBuilder(object):
-    UI_KINDS=["models", "admin", "django_library", "rest_service", "rest_tenant", "tosca_custom_types", "tosca_resource","public_key"]
+    UI_KINDS=["models", "admin", "admin_template", "django_library", "rest_service", "rest_tenant", "tosca_custom_types", "tosca_resource","public_key"]
     SYNC_CONTROLLER_KINDS=["synchronizer", "private_key", "public_key"]
     SYNC_ALLCONTROLLER_KINDS=["models", "django_library"]
 
     def __init__(self):
-        self.source_ui_image = "xosproject/xos"
         self.source_sync_image = "xosproject/xos-synchronizer-openstack"
         self.build_dir = "/opt/xos/BUILD/"
 
@@ -30,15 +29,21 @@
         service_name = scr.service_controller.name
         base_dirs = {"models": "%s/services/%s/" % (xos_base, service_name),
                      "admin": "%s/services/%s/" % (xos_base, service_name),
+                     "admin_template": "%s/services/%s/templates/" % (xos_base, service_name),
                      "django_library": "%s/services/%s/" % (xos_base, service_name),
                      "synchronizer": "%s/synchronizers/%s/" % (xos_base, service_name),
                      "tosca_custom_types": "%s/tosca/custom_types/" % (xos_base),
                      "tosca_resource": "%s/tosca/resources/" % (xos_base),
                      "rest_service": "%s/api/service/" % (xos_base),
                      "rest_tenant": "%s/api/tenant/" % (xos_base),
-                     "private_key": "%s/services/%s/keys" % (xos_base, service_name),
+                     "private_key": "%s/services/%s/keys/" % (xos_base, service_name),
                      "public_key": "%s/services/%s/keys/" % (xos_base, service_name)}
-        return base_dirs[scr.kind]
+        dest_dir = base_dirs[scr.kind]
+
+        if scr.subdirectory:
+            dest_dir = os.path.join(dest_dir, scr.subdirectory)
+
+        return dest_dir
 
     def get_build_fn(self, scr):
         dest_dir = self.get_dest_dir(scr)
@@ -86,33 +91,69 @@
         else:
             self.download_file(scr.full_url, self.get_download_fn(scr))
 
-    def get_docker_lines(self, scr):
+# XXX docker creates a new container and commits it for every single COPY
+# line in the dockerfile. This causes services with many files (for example,
+# vsg) to take ~ 10-15 minutes to build the docker file. So instead we'll copy
+# the whole build directory, and then run a script that copies the files
+# we want.
+
+#    def get_docker_lines(self, scr):
+#        if scr.format == "manifest":
+#            manifest_fn = self.get_download_fn(scr)
+#            manifest = self.read_manifest(scr, manifest_fn)
+#            lines = []
+#            for (url, download_fn, build_fn) in manifest:
+#               script.append("mkdir -p
+#               #lines.append("COPY %s /%s" % (build_fn, build_fn))
+#            return lines
+#        else:
+#            build_fn = self.get_build_fn(scr)
+#            #return ["COPY %s /%s" % (build_fn, build_fn)]
+
+#    def get_controller_docker_lines(self, controller, kinds):
+#        need_service_init_py = False
+#        dockerfile=[]
+#        for scr in controller.service_controller_resources.all():
+#            if scr.kind in kinds:
+#                lines = self.get_docker_lines(scr)
+#                dockerfile = dockerfile + lines
+#            if scr.kind in ["admin", "models"]:
+#                need_service_init_py = True
+#
+#        if need_service_init_py:
+#            file(os.path.join(self.build_dir, "opt/xos/empty__init__.py"),"w").write("")
+#            dockerfile.append("COPY opt/xos/empty__init__.py /opt/xos/services/%s/__init__.py" % controller.name)
+#
+#        return dockerfile
+
+    def get_script_lines(self, scr):
         if scr.format == "manifest":
             manifest_fn = self.get_download_fn(scr)
             manifest = self.read_manifest(scr, manifest_fn)
             lines = []
             for (url, download_fn, build_fn) in manifest:
-               lines.append("ADD %s /%s" % (build_fn, build_fn))
+               lines.append("mkdir -p /%s" % os.path.dirname(build_fn))
+               lines.append("cp /build/%s /%s" % (build_fn, build_fn))
             return lines
         else:
             build_fn = self.get_build_fn(scr)
-            return ["ADD %s /%s" % (build_fn, build_fn)]
+            return ["mkdir -p /%s" % os.path.dirname(build_fn),
+                    "cp /build/%s /%s" % (build_fn, build_fn)]
 
-    def get_controller_docker_lines(self, controller, kinds):
+    def get_controller_script_lines(self, controller, kinds):
         need_service_init_py = False
-        dockerfile=[]
+        script=[]
         for scr in controller.service_controller_resources.all():
             if scr.kind in kinds:
-                lines = self.get_docker_lines(scr)
-                dockerfile = dockerfile + lines
+                lines = self.get_script_lines(scr)
+                script = script + lines
             if scr.kind in ["admin", "models"]:
                 need_service_init_py = True
 
         if need_service_init_py:
-            file(os.path.join(self.build_dir, "opt/xos/empty__init__.py"),"w").write("")
-            dockerfile.append("ADD opt/xos/empty__init__.py /opt/xos/services/%s/__init__.py" % controller.name)
+            script.append("echo > /opt/xos/services/%s/__init__.py" % controller.name)
 
-        return dockerfile
+        return script
 
     def check_controller_unready(self, controller):
         unready_resources=[]
@@ -124,36 +165,47 @@
 
     # stuff that has to do with building
 
-    def create_xos_app_data(self, name, dockerfile, app_list, migration_list):
+    def create_xos_app_data(self, name, script, app_list, migration_list):
         if not os.path.exists(os.path.join(self.build_dir,"opt/xos/xos")):
             os.makedirs(os.path.join(self.build_dir,"opt/xos/xos"))
 
         if app_list:
-            dockerfile.append("COPY opt/xos/xos/%s_xosbuilder_app_list /opt/xos/xos/xosbuilder_app_list" % name)
+            script.append("mkdir -p /opt/xos/xos")
+            script.append("cp /build/opt/xos/xos/%s_xosbuilder_app_list /opt/xos/xos/xosbuilder_app_list" % name)
+            #dockerfile.append("COPY opt/xos/xos/%s_xosbuilder_app_list /opt/xos/xos/xosbuilder_app_list" % name)
             file(os.path.join(self.build_dir, "opt/xos/xos/%s_xosbuilder_app_list") % name, "w").write("\n".join(app_list)+"\n")
 
         if migration_list:
-            dockerfile.append("COPY opt/xos/xos/%s_xosbuilder_migration_list /opt/xos/xos/xosbuilder_migration_list" % name)
+            script.append("mkdir -p /opt/xos/xos")
+            script.append("cp /build/opt/xos/xos/%s_xosbuilder_migration_list /opt/xos/xos/xosbuilder_migration_list" % name)
+            #dockerfile.append("COPY opt/xos/xos/%s_xosbuilder_migration_list /opt/xos/xos/xosbuilder_migration_list" % name)
             file(os.path.join(self.build_dir, "opt/xos/xos/%s_xosbuilder_migration_list") % name, "w").write("\n".join(migration_list)+"\n")
 
     def create_ui_dockerfile(self):
+        xos = XOS.objects.all()[0]
         dockerfile_fn = "Dockerfile.UI"
 
         app_list = []
         migration_list = []
 
-        dockerfile = ["FROM %s" % self.source_ui_image]
+        dockerfile = ["FROM %s" % xos.source_ui_image]
+        script = []
         for controller in ServiceController.objects.all():
             if self.check_controller_unready(controller):
                  logger.warning("Controller %s has unready resources" % str(controller))
                  continue
 
-            dockerfile = dockerfile + self.get_controller_docker_lines(controller, self.UI_KINDS)
+            #dockerfile = dockerfile + self.get_controller_docker_lines(controller, self.UI_KINDS)
+            script = script + self.get_controller_script_lines(controller, self.UI_KINDS)
             if controller.service_controller_resources.filter(kind="models").exists():
                 app_list.append("services." + controller.name)
                 migration_list.append(controller.name)
 
-        self.create_xos_app_data("ui", dockerfile, app_list, migration_list)
+        self.create_xos_app_data("ui", script, app_list, migration_list)
+
+        file(os.path.join(self.build_dir, "install-xos.sh"), "w").write("\n".join(script)+"\n")
+        dockerfile.append("COPY . /build/")
+        dockerfile.append("RUN bash /build/install-xos.sh")
 
         file(os.path.join(self.build_dir, dockerfile_fn), "w").write("\n".join(dockerfile)+"\n")
 
@@ -162,25 +214,32 @@
 
     def create_synchronizer_dockerfile(self, controller):
         # bake in the synchronizer from this controller
-        sync_lines = self.get_controller_docker_lines(controller, self.SYNC_CONTROLLER_KINDS)
+        sync_lines = self.get_controller_script_lines(controller, self.SYNC_CONTROLLER_KINDS)
         if not sync_lines:
             return []
 
         dockerfile_fn = "Dockerfile.%s" % controller.name
         dockerfile = ["FROM %s" % self.source_sync_image]
+        script = []
 
         # Now bake in models from this controller as well as the others
         # It's important to bake all services in, because some services'
         # synchronizers may depend on models from another service.
         app_list = []
         for c in ServiceController.objects.all():
-            dockerfile = dockerfile + self.get_controller_docker_lines(c, self.SYNC_ALLCONTROLLER_KINDS)
+            #dockerfile = dockerfile + self.get_controller_docker_lines(c, self.SYNC_ALLCONTROLLER_KINDS)
+            script = script + self.get_controller_script_lines(c, self.SYNC_ALLCONTROLLER_KINDS)
             if controller.service_controller_resources.filter(kind="models").exists():
-                app_list.append("services." + controller.name)
+                app_list.append("services." + c.name)
 
-        self.create_xos_app_data(controller.name, dockerfile, app_list, None)
+        self.create_xos_app_data(controller.name, script, app_list, None)
 
-        dockerfile = dockerfile + sync_lines
+        script = script + sync_lines
+
+        file(os.path.join(self.build_dir, "install-%s.sh" % controller.name), "w").write("\n".join(script)+"\n")
+        dockerfile.append("COPY . /build/")
+        dockerfile.append("RUN bash /build/install-%s.sh" % controller.name)
+
         file(os.path.join(self.build_dir, dockerfile_fn), "w").write("\n".join(dockerfile)+"\n")
 
         return {"dockerfile_fn": dockerfile_fn,
@@ -218,17 +277,24 @@
 #                             "links": ["xos_db"],
 #                             "volumes": volume_list}
 
-         for c in ServiceController.objects.all():
-             if self.check_controller_unready(c):
-                 logger.warning("Controller %s has unready resources" % str(c))
-                 continue
+         if not xos.frontend_only:
+             for c in ServiceController.objects.all():
+                 if self.check_controller_unready(c):
+                     logger.warning("Controller %s has unready resources" % str(c))
+                     continue
 
-             containers["xos_synchronizer_%s" % c.name] = \
-                            {"image": "xosproject/xos-synchronizer-%s" % c.name,
-                             "command": 'bash -c "sleep 120; cd /opt/xos/synchronizers/%s; bash ./run.sh"' % c.name,
-                             #"external_links": [db_container_name],
-                             "links": ["xos_db"],
-                             "volumes": volume_list}
+                 if c.service_controller_resources.filter(kind="synchronizer").exists():
+                     if c.synchronizer_run and c.synchronizer_config:
+                         command = 'bash -c "sleep 120; cd /opt/xos/synchronizers/%s; python ./%s -C %s"' % (c.name, c.synchronizer_run, c.synchronizer_config)
+                     else:
+                         command = 'bash -c "sleep 120; cd /opt/xos/synchronizers/%s; bash ./run.sh"' % c.name
+
+                     containers["xos_synchronizer_%s" % c.name] = \
+                                    {"image": "xosproject/xos-synchronizer-%s" % c.name,
+                                     "command": command,
+                                     #"external_links": [db_container_name],
+                                     "links": ["xos_db"],
+                                     "volumes": volume_list}
 
          vars = { "containers": containers }
 
diff --git a/xos/synchronizers/openstack/steps/sync_container.py b/xos/synchronizers/openstack/steps/sync_container.py
index 84a2c61..41e1305 100644
--- a/xos/synchronizers/openstack/steps/sync_container.py
+++ b/xos/synchronizers/openstack/steps/sync_container.py
@@ -10,7 +10,6 @@
 from synchronizers.base.syncstep import SyncStep, DeferredException
 from synchronizers.base.ansible import run_template_ssh
 from core.models import Service, Slice, Instance
-from services.onos.models import ONOSService, ONOSApp
 from xos.logger import Logger, logging
 
 # hpclibrary will be in steps/..
diff --git a/xos/synchronizers/vbng/run.sh b/xos/synchronizers/vbng/run.sh
deleted file mode 100755
index de3ed7c..0000000
--- a/xos/synchronizers/vbng/run.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#if [[ ! -e ./vbng-observer.py ]]; then
-#    ln -s ../../xos-observer.py vbng-observer.py
-#fi
-
-export XOS_DIR=/opt/xos
-python vbng-synchronizer.py  -C $XOS_DIR/synchronizers/vbng/vbng_synchronizer_config
diff --git a/xos/synchronizers/vbng/start.sh b/xos/synchronizers/vbng/start.sh
deleted file mode 100755
index 9553610..0000000
--- a/xos/synchronizers/vbng/start.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#if [[ ! -e ./vbng-observer.py ]]; then
-#    ln -s ../../xos-observer.py vbng-observer.py
-#fi
-
-export XOS_DIR=/opt/xos
-nohup python vbng-synchronizer.py  -C $XOS_DIR/synchronizers/vbng/vbng_synchronizer_config > /dev/null 2>&1 &
diff --git a/xos/synchronizers/vbng/steps/sync_vbngtenant.py b/xos/synchronizers/vbng/steps/sync_vbngtenant.py
deleted file mode 100644
index 89e7bc0..0000000
--- a/xos/synchronizers/vbng/steps/sync_vbngtenant.py
+++ /dev/null
@@ -1,142 +0,0 @@
-import os
-import requests
-import socket
-import sys
-import base64
-from django.db.models import F, Q
-from xos.config import Config
-from synchronizers.base.syncstep import SyncStep
-from synchronizers.base.ansible import run_template_ssh
-from core.models import Service
-from services.cord.models import VSGService, VSGTenant, VBNGTenant, VBNGService
-from services.hpc.models import HpcService, CDNPrefix
-from xos.logger import Logger, logging
-
-# VBNG_API = "http://10.0.3.136:8181/onos/virtualbng/privateip/"
-
-# hpclibrary will be in steps/..
-parentdir = os.path.join(os.path.dirname(__file__),"..")
-sys.path.insert(0,parentdir)
-
-logger = Logger(level=logging.INFO)
-
-class SyncVBNGTenant(SyncStep):
-    provides=[VSGTenant]
-    observes=VSGTenant
-    requested_interval=0
-
-    def __init__(self, **args):
-        SyncStep.__init__(self, **args)
-
-    def fetch_pending(self, deleted):
-        if (not deleted):
-            objs = VBNGTenant.get_tenant_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
-        else:
-            objs = VBNGTenant.get_deleted_tenant_objects()
-
-        return objs
-
-    def defer_sync(self, o, reason):
-        logger.info("defer object %s due to %s" % (str(o), reason),extra=o.tologdict())
-        raise Exception("defer object %s due to %s" % (str(o), reason))
-
-    def get_vbng_service(self, o):
-        if not o.provider_service:
-             raise Exception("vBNG tenant %s has no provider_service" % str(o.id))
-        services = VBNGService.get_service_objects().filter(id = o.provider_service.id)
-        if not services:
-             raise Exception("vBNG tenant %s is associated with the wrong kind of provider_service" % str(o.id))
-        return services[0]
-
-    def get_vbng_url(self, o):
-        service = self.get_vbng_service(o)
-
-        # if the service object specifies a vbng_url, then use it
-        if service.vbng_url:
-            return service.vbng_url
-
-        # otherwise, see if the service has tenancy in ONOS
-        for tenant in service.subscribed_tenants.all():
-            if tenant.provider_service and tenant.provider_service.kind == "onos":
-                onos_service = tenant.provider_service
-                if not onos_service.slices.exists():
-                    raise Exception("vBNG service is linked to an ONOSApp, but the App's Service has no slices")
-                onos_slice = onos_service.slices.all()[0]
-                if not onos_slice.instances.exists():
-                    raise Exception("vBNG service is linked to an ONOSApp, but the App's Service's Slice has no instances")
-                instance = onos_slice.instances.all()[0]
-
-                #onos_app = ONOSApp.objects.filter(id = tenant.id)
-                #instance = onos_app.instance
-                #if not instance:
-                #    raise Exception("ONOSApp has no instance")
-
-                if not instance.instance_name:
-                    raise Exception("vBNG service is linked to an ONOSApp, but the App's Service's Slice's first instance is not instantiated")
-                ip = instance.get_network_ip("nat")
-                if not ip:
-                    raise Exception("vBNG service is linked to an ONOSApp, but the App's Service's Slice's first instance does not have an ip")
-
-                logger.info("Using ip %s from ONOS Instance %s" % (ip, instance),extra=o.tologdict())
-
-                return "http://%s:8181/onos/virtualbng/" % ip
-
-        raise Exception("vBNG service does not have vbng_url set, and is not linked to an ONOSApp")
-
-    def get_private_interface(self, o):
-        vcpes = VSGTenant.get_tenant_objects().all()
-        vcpes = [x for x in vcpes if (x.vbng is not None) and (x.vbng.id == o.id)]
-        if not vcpes:
-            raise Exception("No vCPE tenant is associated with vBNG %s" % str(o.id))
-        if len(vcpes)>1:
-            raise Exception("More than one vCPE tenant is associated with vBNG %s" % str(o.id))
-
-        vcpe = vcpes[0]
-        instance = vcpe.instance
-
-        if not instance:
-            raise Exception("No instance associated with vBNG %s" % str(o.id))
-
-        if not vcpe.wan_ip:
-            self.defer_sync(o, "does not have a WAN IP yet")
-
-        if not vcpe.wan_container_mac:
-            # this should never happen; container MAC is computed from WAN IP
-            self.defer_sync(o, "does not have a WAN container MAC yet")
-
-        return (vcpe.wan_ip, vcpe.wan_container_mac, vcpe.instance.node.name)
-
-    def sync_record(self, o):
-        logger.info("sync'ing VBNGTenant %s" % str(o),extra=o.tologdict())
-
-        if not o.routeable_subnet:
-            (private_ip, private_mac, private_hostname) = self.get_private_interface(o)
-            logger.info("contacting vBNG service to request mapping for private ip %s mac %s host %s" % (private_ip, private_mac, private_hostname) ,extra=o.tologdict())
-
-            url = self.get_vbng_url(o) + "privateip/%s/%s/%s" % (private_ip, private_mac, private_hostname)
-            logger.info( "vbng url: %s" % url ,extra=o.tologdict())
-            r = requests.post(url )
-            if (r.status_code != 200):
-                raise Exception("Received error from bng service (%d)" % r.status_code)
-            logger.info("received public IP %s from private IP %s" % (r.text, private_ip),extra=o.tologdict())
-
-            if r.text == "0":
-                raise Exception("VBNG service failed to return a routeable_subnet (probably ran out)")
-
-            o.routeable_subnet = r.text
-            o.mapped_ip = private_ip
-            o.mapped_mac = private_mac
-            o.mapped_hostname = private_hostname
-
-        o.save()
-
-    def delete_record(self, o):
-        logger.info("deleting VBNGTenant %s" % str(o),extra=o.tologdict())
-
-        if o.mapped_ip:
-            private_ip = o.mapped_ip
-            logger.info("contacting vBNG service to delete private ip %s" % private_ip,extra=o.tologdict())
-            r = requests.delete(self.get_vbng_url(o) + "privateip/%s" % private_ip, )
-            if (r.status_code != 200):
-                raise Exception("Received error from bng service (%d)" % r.status_code)
-
diff --git a/xos/synchronizers/vbng/stop.sh b/xos/synchronizers/vbng/stop.sh
deleted file mode 100755
index d49591e..0000000
--- a/xos/synchronizers/vbng/stop.sh
+++ /dev/null
@@ -1 +0,0 @@
-pkill -9 -f vbng-observer.py
diff --git a/xos/synchronizers/vbng/supervisor/vbng-observer.conf b/xos/synchronizers/vbng/supervisor/vbng-observer.conf
deleted file mode 100644
index a999318..0000000
--- a/xos/synchronizers/vbng/supervisor/vbng-observer.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-[program:vbng-observer]
-command=python /opt/xos/synchronizers/vbng/vbng-synchronizer.py -C /opt/xos/synchronizers/vbng/vbng_synchronizer_config
diff --git a/xos/synchronizers/vbng/vbng-synchronizer.py b/xos/synchronizers/vbng/vbng-synchronizer.py
deleted file mode 100755
index 84bec4f..0000000
--- a/xos/synchronizers/vbng/vbng-synchronizer.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/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/synchronizers/vbng/vbng_synchronizer_config b/xos/synchronizers/vbng/vbng_synchronizer_config
deleted file mode 100644
index d613ce3..0000000
--- a/xos/synchronizers/vbng/vbng_synchronizer_config
+++ /dev/null
@@ -1,38 +0,0 @@
-
-[plc]
-name=plc
-deployment=VICCI
-
-[db]
-name=xos
-user=postgres
-password=password
-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]
-name=vbng
-dependency_graph=/opt/xos/synchronizers/vbng/model-deps
-steps_dir=/opt/xos/synchronizers/vbng/steps
-sys_dir=/opt/xos/synchronizers/vbng/sys
-deleters_dir=/opt/xos/synchronizers/vbng/deleters
-log_file=console
-#/var/log/hpc.log
-driver=None
-pretend=False
-backoff_disabled=True
-
-[feefie]
-client_id='vicci_dev_central'
-user_id='pl'
diff --git a/xos/synchronizers/vcpe/model-deps b/xos/synchronizers/vcpe/model-deps
deleted file mode 100644
index 0967ef4..0000000
--- a/xos/synchronizers/vcpe/model-deps
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/xos/synchronizers/vcpe/supervisor/vcpe-observer.conf b/xos/synchronizers/vcpe/supervisor/vcpe-observer.conf
deleted file mode 100644
index 13d797a..0000000
--- a/xos/synchronizers/vcpe/supervisor/vcpe-observer.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-[program:vcpe-observer]
-command=python /opt/xos/synchronizers/vcpe/vcpe-synchronizer.py -C /opt/xos/synchronizers/vcpe/vcpe_synchronizer_config
diff --git a/xos/synchronizers/vtn/model-deps b/xos/synchronizers/vtn/model-deps
deleted file mode 100644
index 0967ef4..0000000
--- a/xos/synchronizers/vtn/model-deps
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/xos/tests/api/helpers/before_test.py b/xos/tests/api/helpers/before_test.py
index d45f4e5..a977564 100644
--- a/xos/tests/api/helpers/before_test.py
+++ b/xos/tests/api/helpers/before_test.py
@@ -9,7 +9,8 @@
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
 import django
 from core.models import *
-from services.cord.models import *
+from services.volt.models import *
+from services.vsg.models import *
 from services.vtr.models import *
 import urllib2
 import json
diff --git a/xos/tests/api/helpers/flavors.py b/xos/tests/api/helpers/flavors.py
index e16d41f..dca4d77 100644
--- a/xos/tests/api/helpers/flavors.py
+++ b/xos/tests/api/helpers/flavors.py
@@ -9,8 +9,6 @@
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
 import django
 from core.models import *
-from services.cord.models import *
-from services.vtr.models import *
 import urllib2
 import json
 django.setup()
diff --git a/xos/tests/api/helpers/subscriber.py b/xos/tests/api/helpers/subscriber.py
index 4ede030..320c73c 100644
--- a/xos/tests/api/helpers/subscriber.py
+++ b/xos/tests/api/helpers/subscriber.py
@@ -9,7 +9,8 @@
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
 import django
 from core.models import *
-from services.cord.models import *
+from services.volt.models import *
+from services.vsg.models import *
 from services.vtr.models import *
 from django.contrib.auth import authenticate, login
 from django.core.exceptions import PermissionDenied
diff --git a/xos/tests/api/hooks.py b/xos/tests/api/hooks.py
index 43756c9..707b258 100644
--- a/xos/tests/api/hooks.py
+++ b/xos/tests/api/hooks.py
@@ -9,7 +9,8 @@
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
 import django
 from core.models import *
-from services.cord.models import *
+from services.volt.models import *
+from services.vsg.models import *
 from services.vtr.models import *
 import urllib2
 import json
@@ -18,7 +19,7 @@
 
 
 def doLogin(username, password):
-    url = "http://127.0.0.1:8000/xoslib/login?username=%s&password=%s" % (username, password)
+    url = "http://127.0.0.1:9999/xoslib/login?username=%s&password=%s" % (username, password)
     res = urllib2.urlopen(url).read()
     parsed = json.loads(res)
     return {'token': parsed['xoscsrftoken'], 'sessionid': parsed['xossessionid']}
@@ -385,4 +386,4 @@
 
 @hooks.before("Utility > Logout > Log a user out of the system")
 def skip_for_now(transaction):
-    transaction['skip'] = True
\ No newline at end of file
+    transaction['skip'] = True
diff --git a/xos/tools/cleanup_unique.py b/xos/tools/cleanup_unique.py
index 4df82f4..97710ec 100644
--- a/xos/tools/cleanup_unique.py
+++ b/xos/tools/cleanup_unique.py
@@ -4,8 +4,6 @@
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
 import django
 from core.models import *
-from services.hpc.models import *
-from services.cord.models import *
 django.setup()
 
 for obj in ControllerNetwork.deleted_objects.all():
diff --git a/xos/tools/dmdot b/xos/tools/dmdot
index a57c0b1..9cde0ed 100755
--- a/xos/tools/dmdot
+++ b/xos/tools/dmdot
@@ -20,7 +20,7 @@
       sys.exit(-1)
 
 # defaults
-apps = ["core", "services.hpc", "services.cord", "services.requestrouter", "services.onos"]
+apps = ["core", "services.hpc", "services.requestrouter", "services.onos"]
 output = "-json"
 
 # syntax: dmdot [-json | -dot] [app_name]
diff --git a/xos/tools/purge.py b/xos/tools/purge.py
index 023c2fe..8c081e6 100644
--- a/xos/tools/purge.py
+++ b/xos/tools/purge.py
@@ -4,8 +4,6 @@
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
 import django
 from core.models import *
-from services.hpc.models import *
-from services.cord.models import *
 django.setup()
 
 def purge(cls):
diff --git a/xos/tools/wait_for_object_creation.py b/xos/tools/wait_for_object_creation.py
index 354a213..b2af38f 100755
--- a/xos/tools/wait_for_object_creation.py
+++ b/xos/tools/wait_for_object_creation.py
@@ -5,7 +5,8 @@
 import django
 from core.models import *
 from services.hpc.models import *
-from services.cord.models import *
+from services.volt.models import *
+from services.vsg.models import *
 import time
 django.setup()
 
diff --git a/xos/tools/xos-manage b/xos/tools/xos-manage
index a4705d9..2ed85f3 100755
--- a/xos/tools/xos-manage
+++ b/xos/tools/xos-manage
@@ -142,16 +142,23 @@
     python ./manage.py makemigrations hpc
     python ./manage.py makemigrations requestrouter
     python ./manage.py makemigrations syndicate_storage
-    python ./manage.py makemigrations cord
     python ./manage.py makemigrations mcord
-    python ./manage.py makemigrations ceilometer
-    python ./manage.py makemigrations onos
+#    python ./manage.py makemigrations ceilometer
+#    python ./manage.py makemigrations onos
     python ./manage.py makemigrations openvpn
-    python ./manage.py makemigrations vtr
-    python ./manage.py makemigrations vrouter
-    python ./manage.py makemigrations vtn
-    python ./manage.py makemigrations fabric
+#    python ./manage.py makemigrations vtr
+#    python ./manage.py makemigrations vrouter
+#    python ./manage.py makemigrations vtn
+#    python ./manage.py makemigrations fabric
     #python ./manage.py makemigrations servcomp
+
+    if [[ -e /opt/xos/xos/xosbuilder_migration_list ]]; then
+        cat /opt/xos/xos/xosbuilder_migration_list | while read line; do
+            if [[ ! -z "$line" ]]; then
+                python ./manage.py makemigrations $line
+            fi
+        done
+    fi
 }
 
 function remigrate {
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 9497b6d..04d7641 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -23,10 +23,18 @@
                 type: string
                 required: false
                 description: Docker project name
+            source_ui_image:
+                type: string
+                required: false
+                description: Source UI docker image name
             enable_build:
                 type: boolean
                 required: false
                 description: True if XOS build should be enabled
+            frontend_only:
+                type: boolean
+                required: false
+                description: True if XOS should not start synchronizer containers
 
 
     tosca.nodes.XOSVolume:
@@ -72,14 +80,30 @@
                 type: string
                 required: false
                 description: url of admin.py
+            admin_template:
+                type: string
+                required: false
+                description: url of admin html template
             synchronizer:
                 type: string
                 required: false
                 description: url of synchronizer manifest
+            synchronizer_run:
+                type: string
+                required: false
+                description: synchronizer run command
+            synchronizer_config:
+                type: string
+                required: false
+                description: synchronizer config filename
             tosca_custom_types:
                 type: string
                 required: false
                 description: url of tosca custom_types
+            tosca_resource:
+                type: string
+                required: false
+                description: url of tosca resource
             rest_service:
                 type: string
                 required: false
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 66229d5..e52c0e1 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -53,10 +53,18 @@
                 type: string
                 required: false
                 description: Docker project name
+            source_ui_image:
+                type: string
+                required: false
+                description: Source UI docker image name
             enable_build:
                 type: boolean
                 required: false
                 description: True if XOS build should be enabled
+            frontend_only:
+                type: boolean
+                required: false
+                description: True if XOS should not start synchronizer containers
 
 
     tosca.nodes.XOSVolume:
@@ -180,14 +188,30 @@
                 type: string
                 required: false
                 description: url of admin.py
+            admin_template:
+                type: string
+                required: false
+                description: url of admin html template
             synchronizer:
                 type: string
                 required: false
                 description: url of synchronizer manifest
+            synchronizer_run:
+                type: string
+                required: false
+                description: synchronizer run command
+            synchronizer_config:
+                type: string
+                required: false
+                description: synchronizer config filename
             tosca_custom_types:
                 type: string
                 required: false
                 description: url of tosca custom_types
+            tosca_resource:
+                type: string
+                required: false
+                description: url of tosca resource
             rest_service:
                 type: string
                 required: false
diff --git a/xos/tosca/resources/network.py b/xos/tosca/resources/network.py
index fc143d0..8672b76 100644
--- a/xos/tosca/resources/network.py
+++ b/xos/tosca/resources/network.py
@@ -72,8 +72,8 @@
             if existing_tenancy:
                 self.info("Tenancy relationship from %s to %s already exists" % (str(obj), str(provider_service)))
             else:
-                from services.vrouter.models import VROUTER_KIND, VRouterService
-                if provider_service.kind == VROUTER_KIND:
+                if provider_service.kind == "vROUTER":
+                    from services.vrouter.models import VRouterService
                     tenancy = VRouterService.objects.get(id=provider_service.id).get_tenant(address_pool_name="addresses_"+obj.name, subscriber_network=obj)
                     tenancy.save()
                     obj.subnet = tenancy.cidr
diff --git a/xos/tosca/resources/servicecontroller.py b/xos/tosca/resources/servicecontroller.py
index 34b95c2..d7e894a 100644
--- a/xos/tosca/resources/servicecontroller.py
+++ b/xos/tosca/resources/servicecontroller.py
@@ -12,28 +12,53 @@
 class XOSServiceController(XOSResource):
     provides = "tosca.nodes.ServiceController"
     xos_model = ServiceController
-    copyin_props = ["base_url"]
+    copyin_props = ["base_url", "synchronizer_run", "synchronizer_config"]
 
     def postprocess_resource_prop(self, obj, kind, format):
-        value = self.get_property(kind)
-        if value:
-            scr = ServiceControllerResource.objects.filter(service_controller=obj, kind=kind, format=format)
-            if scr:
-                scr=scr[0]
-                if scr.url != value:
-                    self.info("updating resource %s" % kind)
-                    scr.url = value
+        values = self.get_property(kind)
+        if values:
+            for i,value in enumerate(values.split(",")):
+                value = value.strip()
+                subdirectory = None
+
+                name=kind
+                if i>0:
+                    name = "%s_%d" %( name, i)
+
+                if (" " in value):
+                    parts=value.split()
+                    for part in parts[:-1]:
+                       if ":" in part:
+                           (lhs, rhs) = part.split(":", 1)
+                           if lhs=="subdirectory":
+                               subdirectory=rhs
+                           else:
+                               raise Exception("Malformed value %s" % value)
+                       else:
+                           raise Exception("Malformed value %s" % value)
+                    value = parts[-1]
+
+
+                scr = ServiceControllerResource.objects.filter(service_controller=obj, name=name, kind=kind, format=format)
+                if scr:
+                    scr=scr[0]
+                    if (scr.url != value) or (scr.subdirectory!=subdirectory):
+                        self.info("updating resource %s" % kind)
+                        scr.url = value
+                        scr.subdirectory = subdirectory
+                        scr.save()
+                else:
+                    self.info("adding resource %s" % kind)
+                    scr = ServiceControllerResource(service_controller=obj, name=name, kind=kind, format=format, url=value, subdirectory=subdirectory)
                     scr.save()
-            else:
-                self.info("adding resource %s" % kind)
-                scr = ServiceControllerResource(service_controller=obj, name=kind, kind=kind, format=format, url=value)
-                scr.save()
 
     def postprocess(self, obj):
         # allow these common resource to be specified directly by the ServiceController tosca object
         self.postprocess_resource_prop(obj, "models", "python")
         self.postprocess_resource_prop(obj, "admin", "python")
+        self.postprocess_resource_prop(obj, "admin_template", "raw")
         self.postprocess_resource_prop(obj, "tosca_custom_types", "yaml")
+        self.postprocess_resource_prop(obj, "tosca_resource", "python")
         self.postprocess_resource_prop(obj, "synchronizer", "manifest")
         self.postprocess_resource_prop(obj, "private_key", "raw")
         self.postprocess_resource_prop(obj, "public_key", "raw")
diff --git a/xos/tosca/resources/vbngservice.py b/xos/tosca/resources/vbngservice.py
deleted file mode 100644
index 28d4a1d..0000000
--- a/xos/tosca/resources/vbngservice.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import os
-import pdb
-import sys
-import tempfile
-sys.path.append("/opt/tosca")
-from translator.toscalib.tosca_template import ToscaTemplate
-
-from services.cord.models import VBNGService
-
-from service import XOSService
-
-class XOSVBGNService(XOSService):
-    provides = "tosca.nodes.VBNGService"
-    xos_model = VBNGService
-    copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key", "versionNumber", "vbng_url"]
-
diff --git a/xos/tosca/resources/xosmodel.py b/xos/tosca/resources/xosmodel.py
index 188bb4f..86aa8a8 100644
--- a/xos/tosca/resources/xosmodel.py
+++ b/xos/tosca/resources/xosmodel.py
@@ -12,7 +12,7 @@
 class XOSXOS(XOSResource):
     provides = "tosca.nodes.XOS"
     xos_model = XOS
-    copyin_props = ["ui_port", "bootstrap_ui_port", "docker_project_name", "enable_build"]
+    copyin_props = ["ui_port", "bootstrap_ui_port", "docker_project_name", "enable_build", "frontend_only", "source_ui_image"]
 
 class XOSVolume(XOSResource):
     provides = "tosca.nodes.XOSVolume"
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index 9f20937..796aac2 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -182,17 +182,16 @@
     'django_extensions',
     'core',
     'services.hpc',
-    'services.cord',
     'services.mcord',
-    'services.onos',
-    'services.ceilometer',
+#    'services.onos',
+#    'services.ceilometer',
     'services.requestrouter',
     'services.syndicate_storage',
     'services.openvpn',
-    'services.vtr',
-    'services.vrouter',
-    'services.vtn',
-    'services.fabric',
+#    'services.vtr',
+#    'services.vrouter',
+#    'services.vtn',
+#    'services.fabric',
     'geoposition',
     'rest_framework_swagger',
 )