merged master

Change-Id: I2498e2572b7bad691bc705e81e8fb2758115340f
diff --git a/views/ngXosLib/karma.conf.ci.js b/views/ngXosLib/karma.conf.ci.js
index 3bd017c..0726edd 100644
--- a/views/ngXosLib/karma.conf.ci.js
+++ b/views/ngXosLib/karma.conf.ci.js
@@ -18,8 +18,7 @@
 // hack to avoid testing backbone implementation (they need to be removed)
 viewFiles = viewFiles
               .filter(f => f.indexOf('xosAdminSite') === -1)
-              .filter(f => f.indexOf('xosCord') === -1)
-              .filter(f => f.indexOf('xosHpc') === -1);
+              .filter(f => f.indexOf('xosCord') === -1);
 
 viewFiles = viewFiles.filter(f => f.indexOf('js') >= 0).filter(f => f.match(/^xos[A-Z][a-z]+/)).map(f => `${viewDir}${f}`);
 
@@ -99,7 +98,7 @@
     // test results reporter to use
     // possible values: 'dots', 'progress'
     // available reporters: https://npmjs.org/browse/keyword/karma-reporter
-    reporters: ['dots', 'junit', 'coverage'],
+    reporters: ['dots', 'mocha', 'junit', 'coverage'],
 
     junitReporter: {
       outputDir: 'test-result',
diff --git a/views/ngXosLib/xosHelpers/spec/ui/table.test.js b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
index 321a476..0ecdd2f 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/table.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
@@ -292,6 +292,7 @@
                 {categories: ['Film', 'Music']}
               ];
               scope.config = {
+                filter: 'field',
                 columns: [
                   {
                     label: 'Categories',
@@ -342,11 +343,17 @@
             });
 
             it('should format data using the formatter property', () => {
-              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('Formatted Content');
               // the custom formatted should receive the entire object, otherwise is not so custom
               expect(formatterFn).toHaveBeenCalledWith({categories: ['Film', 'Music']});
             });
+
+            it('should not render the filter field', () => {
+              // displayed value is different from model val, filter would not work
+              let filter = $(element).find('tbody tr td')[0];
+              expect($(filter)).not.toContainElement('input');
+            });
           });
 
           describe('and is icon', () => {
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 89ef192..4d9169b 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
@@ -42,7 +42,7 @@
     *       label: 'Field Label',
     *       type: 'string' // options are: [date, boolean, number, email, string, select],
     *       validators: {
-    *               minlength: number,
+    *         minlength: number,
               maxlength: number,
               required: boolean,
               min: number,
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 94e2ab3..1e60458 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
@@ -369,7 +369,7 @@
                 <tr>
                   <td ng-repeat="col in vm.columns">
                     <input
-                      ng-if="col.type !== 'boolean' && col.type !== 'array' && col.type !== 'object'"
+                      ng-if="col.type !== 'boolean' && col.type !== 'array' && col.type !== 'object' && col.type !== 'custom'"
                       class="form-control"
                       placeholder="Type to search by {{col.label}}"
                       type="text"
diff --git a/views/ngXosViews/hpc/.bowerrc b/views/ngXosViews/hpc/.bowerrc
new file mode 100644
index 0000000..e491038
--- /dev/null
+++ b/views/ngXosViews/hpc/.bowerrc
@@ -0,0 +1,3 @@
+{
+  "directory": "src/vendor/"
+}
\ No newline at end of file
diff --git a/views/ngXosViews/hpc/.eslintrc b/views/ngXosViews/hpc/.eslintrc
new file mode 100644
index 0000000..c852748
--- /dev/null
+++ b/views/ngXosViews/hpc/.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": [1, {"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/hpc/.gitignore b/views/ngXosViews/hpc/.gitignore
new file mode 100644
index 0000000..567aee4
--- /dev/null
+++ b/views/ngXosViews/hpc/.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/hpc/bower.json b/views/ngXosViews/hpc/bower.json
new file mode 100644
index 0000000..085650b
--- /dev/null
+++ b/views/ngXosViews/hpc/bower.json
@@ -0,0 +1,33 @@
+{
+  "name": "xos-hpc",
+  "version": "0.0.0",
+  "authors": [
+    "Matteo Scandolo <matteo.scandolo@gmail.com>"
+  ],
+  "description": "The hpc 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/hpc/gulp/build.js b/views/ngXosViews/hpc/gulp/build.js
new file mode 100644
index 0000000..3cefc6b
--- /dev/null
+++ b/views/ngXosViews/hpc/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.hpc')
+.run(['$location', function(a){
+  a.path('/');
+}])
+`
+
+module.exports = function(options){
+  
+  // delete previous builded file
+  gulp.task('clean', function(){
+    return del(
+      [
+        options.dashboards + 'xosHpc.html',
+        options.static + 'css/xosHpc.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('xosHpc.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('xosHpc.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.hpc',
+        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/xosHpcVendor.js',
+            options.static + 'js/xosHpc.js',
+            options.static + 'css/xosHpc.css'
+          ]),
+          {ignorePath: '/../../../xos/core/xoslib'}
+        )
+      )
+      .pipe(rename('xosHpc.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('xosHpcVendor.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/hpc/gulp/server.js b/views/ngXosViews/hpc/gulp/server.js
new file mode 100644
index 0000000..c748eb6
--- /dev/null
+++ b/views/ngXosViews/hpc/gulp/server.js
@@ -0,0 +1,171 @@
+'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');
+var fs = require('fs');
+var path = require('path');
+
+const environment = process.env.NODE_ENV;
+
+if(!fs.existsSync(path.join(__dirname, `../../../env/${environment || 'default'}.js`))){
+  if(!environment){
+    throw new Error('You should define a default.js config in /views/env folder.');
+  }
+  else{
+    throw new Error(`Since you are loading a custom environment, you should define a ${environment}.js config in /views/env folder.`);
+  }
+}
+
+var conf = require(path.join(__dirname, `../../../env/${environment || 'default'}.js`));
+
+var proxy = httpProxy.createProxyServer({
+  target: conf.host
+});
+
+
+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(
+            req.url.indexOf('/api/') !== -1,
+            req.url.indexOf('/xoslib/hpcview') !== -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/hpc/gulpfile.js b/views/ngXosViews/hpc/gulpfile.js
new file mode 100644
index 0000000..08df554
--- /dev/null
+++ b/views/ngXosViews/hpc/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/hpc/karma.conf.js b/views/ngXosViews/hpc/karma.conf.js
new file mode 100644
index 0000000..4123be9
--- /dev/null
+++ b/views/ngXosViews/hpc/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/hpc/package.json b/views/ngXosViews/hpc/package.json
new file mode 100644
index 0000000..ab43380
--- /dev/null
+++ b/views/ngXosViews/hpc/package.json
@@ -0,0 +1,63 @@
+{
+  "name": "xos-hpc",
+  "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": "Matteo Scandolo",
+  "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/hpc/spec/sample.test.js b/views/ngXosViews/hpc/spec/sample.test.js
new file mode 100644
index 0000000..9949b08
--- /dev/null
+++ b/views/ngXosViews/hpc/spec/sample.test.js
@@ -0,0 +1,24 @@
+'use strict';
+
+describe('The Hpc View', () => {
+  
+  var scope, element, isolatedScope, httpBackend;
+
+  beforeEach(module('xos.hpc'));
+  beforeEach(module('templates'));
+
+  beforeEach(inject(function($httpBackend, $compile, $rootScope){
+
+    scope = $rootScope.$new();
+    element = angular.element('<hpcs-list></hpcs-list>');
+    $compile(element)(scope);
+    scope.$digest();
+    isolatedScope = element.isolateScope().vm;
+  }));
+
+  it('should define 2 tables', () => {
+    expect(isolatedScope.routerConfig).toBeDefined();
+    expect(isolatedScope.cacheConfig).toBeDefined();
+  });
+
+});
\ No newline at end of file
diff --git a/views/ngXosViews/hpc/src/css/main.css b/views/ngXosViews/hpc/src/css/main.css
new file mode 100644
index 0000000..24f5982
--- /dev/null
+++ b/views/ngXosViews/hpc/src/css/main.css
@@ -0,0 +1,2 @@
+#xosHpc .btn.btn-reload {
+  margin-top: 20px; }
diff --git a/views/ngXosViews/hpc/src/index.html b/views/ngXosViews/hpc/src/index.html
new file mode 100644
index 0000000..c945c27
--- /dev/null
+++ b/views/ngXosViews/hpc/src/index.html
@@ -0,0 +1,35 @@
+<!-- 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.hpc" id="xosHpc" 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/hpc/src/js/main.js b/views/ngXosViews/hpc/src/js/main.js
new file mode 100644
index 0000000..ca6a5a0
--- /dev/null
+++ b/views/ngXosViews/hpc/src/js/main.js
@@ -0,0 +1,134 @@
+'use strict';
+
+angular.module('xos.hpc', [
+  'ngResource',
+  'ngCookies',
+  'ui.router',
+  'xos.helpers'
+])
+.config(($stateProvider) => {
+  $stateProvider
+  .state('hpc-list', {
+    url: '/',
+    template: '<hpcs-list></hpcs-list>'
+  });
+})
+.config(function($httpProvider){
+  $httpProvider.interceptors.push('NoHyperlinks');
+})
+.service('Hpc', function($q, $http){
+  this.query = (params) => {
+    const d = $q.defer();
+
+    $http.get('/xoslib/hpcview', {params: params})
+      .then((res) => {
+        d.resolve(res.data);
+      })
+      .catch(d.reject);
+
+    return {$promise: d.promise};
+  };
+})
+.directive('hpcsList', function(){
+  return {
+    restrict: 'E',
+    scope: {},
+    bindToController: true,
+    controllerAs: 'vm',
+    templateUrl: 'templates/hpc-list.tpl.html',
+    controller: function(Hpc){
+
+      const secondsToHms = d => {
+        d = Number(d);
+        var h = Math.floor(d / 3600);
+        var m = Math.floor(d % 3600 / 60);
+        var s = Math.floor(d % 3600 % 60);
+        return ((h > 0 ? h + 'h ' + (m < 10 ? '0' :'') :'') + m + 'm ' + (s < 10 ? '0' :'') + s + 's');
+      };
+
+      const toDuration = (property) => {
+        return (item) => {
+          if(!angular.isNumber(item[property])){
+            return item[property]
+          }
+          return secondsToHms(item[property]);
+        }
+      };
+
+      this.routerConfig = {
+        filter: 'field',
+        order: true,
+        columns: [
+          {
+            label: 'Name',
+            prop: 'name'
+          },
+          {
+            label: 'Ip Address',
+            prop: 'ip'
+          },
+          {
+            label: 'Record Checker',
+            prop: 'watcher.DNS.msg'
+          },
+          {
+            label: 'Name Servers',
+            prop: 'nameservers',
+            type: 'array'
+          },
+          {
+            label: 'Dns Demux Config Age',
+            prop: 'dnsdemux_config_age',
+            type: 'custom',
+            formatter: toDuration('dnsdemux_config_age')
+          },
+          {
+            label: 'Dns Redir Config Age',
+            prop: 'dnsredir_config_age',
+            type: 'custom',
+            formatter: toDuration('dnsredir_config_age')
+          }
+        ]
+      };
+
+      this.cacheConfig = {
+        filter: 'field',
+        order: true,
+        columns: [
+          {
+            label: 'Name',
+            prop: 'name'
+          },
+          {
+            label: 'Prober',
+            prop: 'watcher.HPC-hb.msg'
+          },
+          {
+            label: 'Fetcher',
+            prop: 'watcher.HPC-fetch.msg'
+          },
+          {
+            label: 'Config Age',
+            prop: 'config_age',
+            type: 'custom',
+            formatter: toDuration('config_age')
+          }
+        ]
+      };
+
+
+      this.fetch = () => {
+        Hpc.query().$promise
+        .then((hpcs) => {
+          this.routers = hpcs[0].dnsdemux;
+          this.caches = hpcs[0].hpc;
+        })
+        .catch((e) => {
+          throw new Error(e);
+        });
+      };
+
+      this.fetch();
+    }
+  };
+});
\ No newline at end of file
diff --git a/views/ngXosViews/hpc/src/sass/main.scss b/views/ngXosViews/hpc/src/sass/main.scss
new file mode 100644
index 0000000..c646843
--- /dev/null
+++ b/views/ngXosViews/hpc/src/sass/main.scss
@@ -0,0 +1,7 @@
+@import '../../../../style/sass/lib/_variables.scss';
+
+#xosHpc {
+  .btn.btn-reload {
+    margin-top: $line-height-computed;
+  }
+}
\ No newline at end of file
diff --git a/views/ngXosViews/hpc/src/templates/hpc-list.tpl.html b/views/ngXosViews/hpc/src/templates/hpc-list.tpl.html
new file mode 100644
index 0000000..138323f
--- /dev/null
+++ b/views/ngXosViews/hpc/src/templates/hpc-list.tpl.html
@@ -0,0 +1,28 @@
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-xs-10">
+            <h1>Request Routers</h1>
+        </div>
+        <div class="col-xs-2 text-right">
+            <a href="" ng-click="vm.fetch()" class="btn btn-primary btn-reload">
+                <i class="glyphicon glyphicon-refresh"></i>
+                Refresh
+            </a>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-xs-12">
+            <xos-table config="vm.routerConfig" data="vm.routers"></xos-table>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-xs-12">
+            <h1>HyperCache</h1>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-xs-12">
+            <xos-table config="vm.cacheConfig" data="vm.caches"></xos-table>
+        </div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/xos/configurations/common/wait_for_onboarding_ready.sh b/xos/configurations/common/wait_for_onboarding_ready.sh
index 9606dbb..dbfdde8 100755
--- a/xos/configurations/common/wait_for_onboarding_ready.sh
+++ b/xos/configurations/common/wait_for_onboarding_ready.sh
@@ -17,6 +17,7 @@
         echo "$2 is onboarded"
         exit 0
     fi
+    echo -ne "."
     sleep 1
 #    RUNNING_CONTAINER=`sudo docker ps|grep "xos"|awk '{print $$NF}'`
 #    if [[ $RUNNING_CONTAINER == "" ]]; then
diff --git a/xos/configurations/cord-pod/docker-compose-bootstrap.yml b/xos/configurations/cord-pod/docker-compose-bootstrap.yml
index 83bb685..93ccb71 100644
--- a/xos/configurations/cord-pod/docker-compose-bootstrap.yml
+++ b/xos/configurations/cord-pod/docker-compose-bootstrap.yml
@@ -40,100 +40,6 @@
             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_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
-    command: bash -c "sleep 120; python /opt/xos/synchronizers/monitoring_channel/monitoring_channel_synchronizer.py -C /root/setup/files/monitoring_channel_synchronizer_config"
-    labels:
-        org.xosproject.kind: synchronizer
-        org.xosproject.target: monitoring_channel
-    links:
-        - xos_db
-    volumes:
-        - .:/root/setup:ro
-        - ./id_rsa:/opt/xos/synchronizers/monitoring_channel/monitoring_channel_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_bootstrap_ui:
     command: python /opt/xos/manage.py runserver 0.0.0.0:81 --insecure --makemigrations
     image: xosproject/xos
@@ -146,9 +52,6 @@
         - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config:ro
         - ./xos_cord_config:/opt/xos/xos_configuration/xos_cord_config:ro
         - ../vtn/files/xos_vtn_config:/opt/xos/xos_configuration/xos_vtn_config:ro
-#        - ./id_rsa.pub:/opt/xos/synchronizers/onos/onos_key.pub:ro
-#        - ./id_rsa.pub:/opt/xos/synchronizers/vcpe/vcpe_public_key:ro
-#        - ./id_rsa.pub:/opt/xos/synchronizers/monitoring_channel/monitoring_channel_public_key:ro
     log_driver: "json-file"
     log_opt:
             max-size: "100k"
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index 8845196..b322ffe 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -41,7 +41,7 @@
 	sudo docker-compose -f $(BOOTSTRAP_YML) stop
 
 showlogs:
-	sudo docker-compose logs
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) logs
 
 rm: stop
 	test ! -s $(DOCKER_COMPOSE_YML) || sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) rm
diff --git a/xos/configurations/test-standalone/Makefile b/xos/configurations/test-standalone/Makefile
index 9807e5d..3566d80 100644
--- a/xos/configurations/test-standalone/Makefile
+++ b/xos/configurations/test-standalone/Makefile
@@ -44,16 +44,20 @@
 	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 bash -c "echo somekey > key_import/onos_rsa"
+	sudo bash -c "echo somekey > 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/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/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/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 services/onos
 	bash ../common/wait_for_onboarding_ready.sh 9998 xos
 	bash ../common/wait_for_xos_port.sh 9999
 
@@ -97,8 +101,8 @@
 	sudo docker-compose logs
 
 rm: stop
-	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
+	test ! -s $(DOCKER_COMPOSE_YML) || sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) rm -f
+	sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) rm -f
 
 docker-clean:
 	sudo docker rm -f $(shell sudo docker ps -aq)
diff --git a/xos/core/xoslib/dashboards/xosHpc.html b/xos/core/xoslib/dashboards/xosHpc.html
index 138a9a1..78a7639 100644
--- a/xos/core/xoslib/dashboards/xosHpc.html
+++ b/xos/core/xoslib/dashboards/xosHpc.html
@@ -1,37 +1,16 @@
-<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 'suit/css/jquery-ui.min.css' %}" media="all" >
-<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/xosHpc.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/xosHpc.js"></script>
-
-<div id="xos-hpc-view-panel"> <!-- contentPanel"> -->
-<div id="contentTitle">
+<div ng-app="xos.hpc" id="xosHpc" class="container-fluid">
+  <div ui-view></div>
 </div>
 
-<div id="contentInner">
 
-<dic id="warnings"></div>
-
-<h2>Request Routers</h2>
-<div id="xos-hpc-dns"></div>
-
-<br>
-<h2>HyperCache</h2>
-<div id="xos-hpc-hpc"></div>
-
-</div> <!-- end contentInner -->
-</div> <!-- end contentPanel -->
-
-{% include 'xosAdmin.html' %}
+<!-- endjs -->
+<!-- inject:js -->
+<script src="/static/js/xosHpc.js"></script>
+<!-- endinject -->
diff --git a/xos/core/xoslib/static/css/xosHpc.css b/xos/core/xoslib/static/css/xosHpc.css
new file mode 100644
index 0000000..e9458ad
--- /dev/null
+++ b/xos/core/xoslib/static/css/xosHpc.css
@@ -0,0 +1 @@
+#xosHpc .btn.btn-reload{margin-top:20px}
\ 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 f511337..eebc675 100644
--- a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
+++ b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
@@ -1,2 +1,2 @@
-"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
+"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"])}(),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)}();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(){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\' && col.type !== \'custom\'"\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("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        <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("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("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/xosHpc.js b/xos/core/xoslib/static/js/xosHpc.js
index e0b0437..a1eb26e 100644
--- a/xos/core/xoslib/static/js/xosHpc.js
+++ b/xos/core/xoslib/static/js/xosHpc.js
@@ -1,105 +1 @@
-/* eslint-disable */
-SC_RR = 60;
-SC_HPC_PROBE = 600;
-SC_HPC_FETCH = 3600;
-
-function staleCheck(row, time_key, msg_key, seconds) {
-    if (parseInt(row[time_key])>seconds) {
-        return "stale";
-    } else {
-        if (! row[msg_key]) {
-            return "null";
-        } else {
-            return row[msg_key];
-        }
-    }
-}
-
-function updateDnsDemuxTable(dnsdemux) {
-    $('#xos-hpc-dns').html( '<table cellpadding="0" cellspacing="0" border="0" class="display" id="dynamic_dnsdemux"></table>' );
-    var actualEntries = [];
-
-    //console.log(dnsdemux);
-
-    for (rowkey in dnsdemux) {
-        row = dnsdemux[rowkey];
-
-        actualEntries.push( [row.name, row.ip, staleCheck(row, "watcher.DNS.time", "watcher.DNS.msg", SC_RR), row.nameservers.join(","),
-                             row.dnsredir_config_age + "," + row.dnsdemux_config_age] );
-    }
-    console.log(actualEntries);
-    oTable = $('#dynamic_dnsdemux').dataTable( {
-        "bJQueryUI": true,
-        "aaData":  actualEntries ,
-        "bStateSave": true,
-        "bFilter": false,
-        "bPaginate": false,
-        "aoColumns": [
-            { "sTitle": "Node" },
-            { "sTitle": "IP Address" },
-            { "sTitle": "Record Checker" },
-            { "sTitle": "Nameservers" },
-            { "sTitle": "Config Age" },
-        ]
-    } );
-}
-
-function updateHpcTable(hpcnodes) {
-    $('#xos-hpc-hpc').html( '<table cellpadding="0" cellspacing="0" border="0" class="display" id="dynamic_hpc"></table>' );
-    var actualEntries = [];
-
-    //console.log(hpcnodes);
-
-    for (rowkey in hpcnodes) {
-        row = hpcnodes[rowkey];
-
-        actualEntries.push( [row.name, staleCheck(row, "watcher.HPC-hb.time", "watcher.HPC-hb.msg", SC_HPC_PROBE),
-                                       staleCheck(row, "watcher.HPC-fetch.time", "watcher.HPC-fetch.msg", SC_HPC_FETCH),
-                                       row.config_age, ] );
-    }
-    console.log(actualEntries);
-    oTable = $('#dynamic_hpc').dataTable( {
-        "bJQueryUI": true,
-        "aaData":  actualEntries ,
-        "bStateSave": true,
-        "bFilter": false,
-        "bPaginate": false,
-        "aoColumns": [
-            { "sTitle": "Node", },
-            { "sTitle": "Prober" },
-            { "sTitle": "Fetcher" },
-            { "sTitle": "Config Age" },
-        ]
-    } );
-}
-
-function updateWarnings(data) {
-    nameservers = data.attributes.nameservers;
-    warnings = [];
-    for (rowKey in nameservers) {
-        nameserver = nameservers[rowKey]
-        if (!nameserver.hit) {
-            warnings.push("<B>WARNING:</B> nameserver " + nameserver.name + " does not map to a request router");
-        }
-    }
-
-    console.log(warnings);
-
-    $("#warnings").html(warnings.join("<BR>"));
-}
-
-function updateHpcView(data) {
-    data = data[0];
-    updateDnsDemuxTable( data.attributes.dnsdemux );
-    updateHpcTable( data.attributes.hpc );
-    updateWarnings( data );
-}
-
-$(document).ready(function(){
-    xos.hpcview.on("change", function() { console.log("change"); updateHpcView(xos.hpcview.models); });
-    xos.hpcview.on("remove", function() { console.log("sort"); updateHpcView(xos.hpcview.models); });
-    xos.hpcview.on("sort", function() { console.log("sort"); updateHpcView(xos.hpcview.models); });
-
-    xos.hpcview.startPolling();
-});
-/* eslint-enable */
+"use strict";angular.module("xos.hpc",["ngResource","ngCookies","ui.router","xos.helpers"]).config(["$stateProvider",function(e){e.state("hpc-list",{url:"/",template:"<hpcs-list></hpcs-list>"})}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).service("Hpc",["$q","$http",function(e,r){this.query=function(t){var n=e.defer();return r.get("/xoslib/hpcview",{params:t}).then(function(e){n.resolve(e.data)})["catch"](n.reject),{$promise:n.promise}}}]).directive("hpcsList",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/hpc-list.tpl.html",controller:["Hpc",function(e){var r=this,t=function(e){e=Number(e);var r=Math.floor(e/3600),t=Math.floor(e%3600/60),n=Math.floor(e%3600%60);return(r>0?r+"h "+(10>t?"0":""):"")+t+"m "+(10>n?"0":"")+n+"s"},n=function(e){return function(r){return angular.isNumber(r[e])?t(r[e]):r[e]}};this.routerConfig={filter:"field",order:!0,columns:[{label:"Name",prop:"name"},{label:"Ip Address",prop:"ip"},{label:"Record Checker",prop:"watcher.DNS.msg"},{label:"Name Servers",prop:"nameservers",type:"array"},{label:"Dns Demux Config Age",prop:"dnsdemux_config_age",type:"custom",formatter:n("dnsdemux_config_age")},{label:"Dns Redir Config Age",prop:"dnsredir_config_age",type:"custom",formatter:n("dnsredir_config_age")}]},this.cacheConfig={filter:"field",order:!0,columns:[{label:"Name",prop:"name"},{label:"Prober",prop:"watcher.HPC-hb.msg"},{label:"Fetcher",prop:"watcher.HPC-fetch.msg"},{label:"Config Age",prop:"config_age",type:"custom",formatter:n("config_age")}]},this.fetch=function(){e.query().$promise.then(function(e){r.routers=e[0].dnsdemux,r.caches=e[0].hpc})["catch"](function(e){throw new Error(e)})},this.fetch()}]}}),angular.module("xos.hpc").run(["$templateCache",function(e){e.put("templates/hpc-list.tpl.html",'<div class="container-fluid">\n    <div class="row">\n        <div class="col-xs-10">\n            <h1>Request Routers</h1>\n        </div>\n        <div class="col-xs-2 text-right">\n            <a href="" ng-click="vm.fetch()" class="btn btn-primary btn-reload">\n                <i class="glyphicon glyphicon-refresh"></i>\n                Refresh\n            </a>\n        </div>\n    </div>\n    <div class="row">\n        <div class="col-xs-12">\n            <xos-table config="vm.routerConfig" data="vm.routers"></xos-table>\n        </div>\n    </div>\n    <div class="row">\n        <div class="col-xs-12">\n            <h1>HyperCache</h1>\n        </div>\n    </div>\n    <div class="row">\n        <div class="col-xs-12">\n            <xos-table config="vm.cacheConfig" data="vm.caches"></xos-table>\n        </div>\n    </div>\n</div>')}]),angular.module("xos.hpc").run(["$location",function(e){e.path("/")}]);
\ No newline at end of file
diff --git a/xos/onboard/onos/onos-onboard.yaml b/xos/onboard/onos/onos-onboard.yaml
index 1338bb6..3d4ac3b 100644
--- a/xos/onboard/onos/onos-onboard.yaml
+++ b/xos/onboard/onos/onos-onboard.yaml
@@ -20,7 +20,7 @@
           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_service: 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/services/openvpn/admin.py b/xos/onboard/openvpn/admin.py
similarity index 100%
rename from xos/services/openvpn/admin.py
rename to xos/onboard/openvpn/admin.py
diff --git a/xos/api/tenant/openvpn/openvpn.py b/xos/onboard/openvpn/api/tenant/openvpn/openvpn.py
similarity index 100%
rename from xos/api/tenant/openvpn/openvpn.py
rename to xos/onboard/openvpn/api/tenant/openvpn/openvpn.py
diff --git a/xos/services/openvpn/models.py b/xos/onboard/openvpn/models.py
similarity index 100%
rename from xos/services/openvpn/models.py
rename to xos/onboard/openvpn/models.py
diff --git a/xos/onboard/openvpn/openvpn-onboard.yaml b/xos/onboard/openvpn/openvpn-onboard.yaml
new file mode 100644
index 0000000..980e0b5
--- /dev/null
+++ b/xos/onboard/openvpn/openvpn-onboard.yaml
@@ -0,0 +1,25 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the OpenVPN Service
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    servicecontroller#openvpn:
+      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/connect.vpn.j2
+          synchronizer: synchronizer/manifest
+          synchronizer_run: openvpn-synchronizer.py
+          #tosca_custom_types: exampleservice.yaml
+          rest_tenant: subdirectory:openvpn api/tenant/openvpn/openvpn.py
+          private_key: file:///opt/xos/key_import/openvpn_rsa
+          public_key: file:///opt/xos/key_import/openvpn_rsa.pub
+
diff --git a/xos/services/cord_old/migrations/__init__.py b/xos/onboard/openvpn/synchronizer/__init__.py
similarity index 100%
rename from xos/services/cord_old/migrations/__init__.py
rename to xos/onboard/openvpn/synchronizer/__init__.py
diff --git a/xos/onboard/openvpn/synchronizer/manifest b/xos/onboard/openvpn/synchronizer/manifest
new file mode 100644
index 0000000..44d6986
--- /dev/null
+++ b/xos/onboard/openvpn/synchronizer/manifest
@@ -0,0 +1,14 @@
+manifest
+openvpn_config
+__init__.py
+steps/sync_tenantprivilege.py
+steps/sync_openvpntenant.yaml
+steps/__init__.py
+steps/roles/openvpn/templates/server.conf.j2
+steps/roles/openvpn/handlers/main.yml
+steps/roles/openvpn/tasks/main.yml
+steps/sync_openvpntenant.py
+stop.sh
+model-deps
+openvpn-synchronizer.py
+run.sh
diff --git a/xos/synchronizers/openvpn/model-deps b/xos/onboard/openvpn/synchronizer/model-deps
similarity index 100%
rename from xos/synchronizers/openvpn/model-deps
rename to xos/onboard/openvpn/synchronizer/model-deps
diff --git a/xos/synchronizers/openvpn/openvpn-synchronizer.py b/xos/onboard/openvpn/synchronizer/openvpn-synchronizer.py
similarity index 100%
rename from xos/synchronizers/openvpn/openvpn-synchronizer.py
rename to xos/onboard/openvpn/synchronizer/openvpn-synchronizer.py
diff --git a/xos/synchronizers/openvpn/openvpn_config b/xos/onboard/openvpn/synchronizer/openvpn_config
similarity index 100%
rename from xos/synchronizers/openvpn/openvpn_config
rename to xos/onboard/openvpn/synchronizer/openvpn_config
diff --git a/xos/synchronizers/openvpn/run.sh b/xos/onboard/openvpn/synchronizer/run.sh
similarity index 100%
rename from xos/synchronizers/openvpn/run.sh
rename to xos/onboard/openvpn/synchronizer/run.sh
diff --git a/xos/synchronizers/openvpn/steps/__init__.py b/xos/onboard/openvpn/synchronizer/steps/__init__.py
similarity index 100%
rename from xos/synchronizers/openvpn/steps/__init__.py
rename to xos/onboard/openvpn/synchronizer/steps/__init__.py
diff --git a/xos/synchronizers/openvpn/steps/roles/openvpn/handlers/main.yml b/xos/onboard/openvpn/synchronizer/steps/roles/openvpn/handlers/main.yml
similarity index 100%
rename from xos/synchronizers/openvpn/steps/roles/openvpn/handlers/main.yml
rename to xos/onboard/openvpn/synchronizer/steps/roles/openvpn/handlers/main.yml
diff --git a/xos/synchronizers/openvpn/steps/roles/openvpn/tasks/main.yml b/xos/onboard/openvpn/synchronizer/steps/roles/openvpn/tasks/main.yml
similarity index 100%
rename from xos/synchronizers/openvpn/steps/roles/openvpn/tasks/main.yml
rename to xos/onboard/openvpn/synchronizer/steps/roles/openvpn/tasks/main.yml
diff --git a/xos/synchronizers/openvpn/steps/roles/openvpn/templates/server.conf.j2 b/xos/onboard/openvpn/synchronizer/steps/roles/openvpn/templates/server.conf.j2
similarity index 100%
rename from xos/synchronizers/openvpn/steps/roles/openvpn/templates/server.conf.j2
rename to xos/onboard/openvpn/synchronizer/steps/roles/openvpn/templates/server.conf.j2
diff --git a/xos/synchronizers/openvpn/steps/sync_openvpntenant.py b/xos/onboard/openvpn/synchronizer/steps/sync_openvpntenant.py
similarity index 100%
rename from xos/synchronizers/openvpn/steps/sync_openvpntenant.py
rename to xos/onboard/openvpn/synchronizer/steps/sync_openvpntenant.py
diff --git a/xos/synchronizers/openvpn/steps/sync_openvpntenant.yaml b/xos/onboard/openvpn/synchronizer/steps/sync_openvpntenant.yaml
similarity index 100%
rename from xos/synchronizers/openvpn/steps/sync_openvpntenant.yaml
rename to xos/onboard/openvpn/synchronizer/steps/sync_openvpntenant.yaml
diff --git a/xos/synchronizers/openvpn/steps/sync_tenantprivilege.py b/xos/onboard/openvpn/synchronizer/steps/sync_tenantprivilege.py
similarity index 100%
rename from xos/synchronizers/openvpn/steps/sync_tenantprivilege.py
rename to xos/onboard/openvpn/synchronizer/steps/sync_tenantprivilege.py
diff --git a/xos/synchronizers/openvpn/stop.sh b/xos/onboard/openvpn/synchronizer/stop.sh
similarity index 100%
rename from xos/synchronizers/openvpn/stop.sh
rename to xos/onboard/openvpn/synchronizer/stop.sh
diff --git a/xos/services/openvpn/templates/connect.vpn.j2 b/xos/onboard/openvpn/templates/connect.vpn.j2
similarity index 100%
rename from xos/services/openvpn/templates/connect.vpn.j2
rename to xos/onboard/openvpn/templates/connect.vpn.j2
diff --git a/xos/services/cord_old/__init__.py b/xos/services/cord_old/__init__.py
deleted file mode 100644
index 8b13789..0000000
--- a/xos/services/cord_old/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/xos/services/cord_old/admin.py b/xos/services/cord_old/admin.py
deleted file mode 100644
index 5bccd11..0000000
--- a/xos/services/cord_old/admin.py
+++ /dev/null
@@ -1,471 +0,0 @@
-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
-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 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 get_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
-        fields = '__all__'
-
-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 get_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'))
-
-#-----------------------------------------------------------------------------
-# vCPE
-#-----------------------------------------------------------------------------
-
-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
-        fields = '__all__'
-
-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 get_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
-        fields = '__all__'
-
-
-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 get_queryset(self, request):
-        return VSGTenant.get_tenant_objects_by_user(request.user)
-
-#-----------------------------------------------------------------------------
-# vBNG
-#-----------------------------------------------------------------------------
-
-class VBNGServiceForm(forms.ModelForm):
-    vbng_url = forms.CharField(required=False)
-
-    def __init__(self,*args,**kwargs):
-        super (VBNGServiceForm,self ).__init__(*args,**kwargs)
-        if self.instance:
-            self.fields['vbng_url'].initial = self.instance.vbng_url
-
-    def save(self, commit=True):
-        self.instance.vbng_url = self.cleaned_data.get("vbng_url")
-        return super(VBNGServiceForm, self).save(commit=commit)
-
-    class Meta:
-        model = VBNGService
-        fields = '__all__'
-
-
-class VBNGServiceAdmin(ReadOnlyAwareAdmin):
-    model = VBNGService
-    verbose_name = "vBNG Service"
-    verbose_name_plural = "vBNG 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",
-                                    'vbng_url' ],
-                         'classes':['suit-tab suit-tab-general']})]
-    readonly_fields = ('backend_status_text', )
-    inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline]
-    form = VBNGServiceForm
-
-    extracontext_registered_admins = True
-
-    user_readonly_fields = ["name", "enabled", "versionNumber", "description"]
-
-    suit_form_tabs =(('general', 'vBNG Service Details'),
-        ('administration', 'Administration'),
-        #('tools', 'Tools'),
-        ('slices','Slices'),
-        ('serviceattrs','Additional Attributes'),
-        ('serviceprivileges','Privileges'),
-    )
-
-    suit_form_includes = (('vbngadmin.html', 'top', 'administration'),
-                           ) #('hpctools.html', 'top', 'tools') )
-
-    def get_queryset(self, request):
-        return VBNGService.get_service_objects_by_user(request.user)
-
-class VBNGTenantForm(forms.ModelForm):
-    routeable_subnet = forms.CharField(required=False)
-    mapped_hostname = forms.CharField(required=False)
-    mapped_ip = forms.CharField(required=False)
-    mapped_mac =  forms.CharField(required=False)
-
-    def __init__(self,*args,**kwargs):
-        super (VBNGTenantForm,self ).__init__(*args,**kwargs)
-        self.fields['kind'].widget.attrs['readonly'] = True
-        self.fields['provider_service'].queryset = VBNGService.get_service_objects().all()
-        if self.instance:
-            # fields for the attributes
-            self.fields['routeable_subnet'].initial = self.instance.routeable_subnet
-            self.fields['mapped_hostname'].initial = self.instance.mapped_hostname
-            self.fields['mapped_ip'].initial = self.instance.mapped_ip
-            self.fields['mapped_mac'].initial = self.instance.mapped_mac
-        if (not self.instance) or (not self.instance.pk):
-            # default fields for an 'add' form
-            self.fields['kind'].initial = VBNG_KIND
-            if VBNGService.get_service_objects().exists():
-               self.fields["provider_service"].initial = VBNGService.get_service_objects().all()[0]
-
-    def save(self, commit=True):
-        self.instance.routeable_subnet = self.cleaned_data.get("routeable_subnet")
-        self.instance.mapped_hostname = self.cleaned_data.get("mapped_hostname")
-        self.instance.mapped_ip = self.cleaned_data.get("mapped_ip")
-        self.instance.mapped_mac = self.cleaned_data.get("mapped_mac")
-        return super(VBNGTenantForm, self).save(commit=commit)
-
-    class Meta:
-        model = VBNGTenant
-        fields = '__all__'
-
-class VBNGTenantAdmin(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',
-                                     'routeable_subnet', 'mapped_hostname', 'mapped_ip', 'mapped_mac'],
-                          'classes':['suit-tab suit-tab-general']})]
-    readonly_fields = ('backend_status_text', 'service_specific_attribute')
-    form = VBNGTenantForm
-
-    suit_form_tabs = (('general','Details'),)
-
-    def get_queryset(self, request):
-        return VBNGTenant.get_tenant_objects_by_user(request.user)
-
-#-----------------------------------------------------------------------------
-# 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 get_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
-        fields = '__all__'
-
-
-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 get_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(VSGService, VSGServiceAdmin)
-admin.site.register(VSGTenant, VSGTenantAdmin)
-admin.site.register(VBNGService, VBNGServiceAdmin)
-admin.site.register(VBNGTenant, VBNGTenantAdmin)
-admin.site.register(CordSubscriberRoot, CordSubscriberRootAdmin)
-
diff --git a/xos/services/cord_old/migrations/0001_initial.py b/xos/services/cord_old/migrations/0001_initial.py
deleted file mode 100644
index 75e30f5..0000000
--- a/xos/services/cord_old/migrations/0001_initial.py
+++ /dev/null
@@ -1,197 +0,0 @@
-# -*- 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_old/models.py b/xos/services/cord_old/models.py
deleted file mode 100644
index 19b3ba6..0000000
--- a/xos/services/cord_old/models.py
+++ /dev/null
@@ -1,846 +0,0 @@
-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"
-VCPE_KIND = "vCPE"
-VBNG_KIND = "vBNG"
-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 = "cord"
-        verbose_name = "vOLT Service"
-
-class VOLTTenant(Tenant):
-    KIND = VOLT_KIND
-
-    class Meta:
-        app_label = "cord"
-        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):
-        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:
-            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):
-        # 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 = "cord"
-
-    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 = "cord"
-
-    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 = "cord"
-
-    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 = "cord"
-
-    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)
-
-
-# -------------------------------------------
-# 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 = "cord"
-        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):
-        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()
-
-#----------------------------------------------------------------------------
-# vBNG
-#----------------------------------------------------------------------------
-
-class VBNGService(Service):
-    KIND = VBNG_KIND
-
-    simple_attributes = ( ("vbng_url", ""), )  # "http://10.0.3.136:8181/onos/virtualbng/"
-
-    class Meta:
-        app_label = "cord"
-        verbose_name = "vBNG Service"
-        proxy = True
-
-VBNGService.setup_simple_attributes()
-
-class VBNGTenant(Tenant):
-    class Meta:
-        proxy = True
-
-    KIND = VBNG_KIND
-
-    default_attributes = {"routeable_subnet": "",
-                          "mapped_ip": "",
-                          "mapped_mac": "",
-                          "mapped_hostname": ""}
-
-    @property
-    def routeable_subnet(self):
-        return self.get_attribute("routeable_subnet", self.default_attributes["routeable_subnet"])
-
-    @routeable_subnet.setter
-    def routeable_subnet(self, value):
-        self.set_attribute("routeable_subnet", value)
-
-    @property
-    def mapped_ip(self):
-        return self.get_attribute("mapped_ip", self.default_attributes["mapped_ip"])
-
-    @mapped_ip.setter
-    def mapped_ip(self, value):
-        self.set_attribute("mapped_ip", value)
-
-    @property
-    def mapped_mac(self):
-        return self.get_attribute("mapped_mac", self.default_attributes["mapped_mac"])
-
-    @mapped_mac.setter
-    def mapped_mac(self, value):
-        self.set_attribute("mapped_mac", value)
-
-    @property
-    def mapped_hostname(self):
-        return self.get_attribute("mapped_hostname", self.default_attributes["mapped_hostname"])
-
-    @mapped_hostname.setter
-    def mapped_hostname(self, value):
-        self.set_attribute("mapped_hostname", value)
diff --git a/xos/services/cord_old/templates/vbngadmin.html b/xos/services/cord_old/templates/vbngadmin.html
deleted file mode 100644
index cceaee0..0000000
--- a/xos/services/cord_old/templates/vbngadmin.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<div class = "row text-center">
-    <div class="col-xs-12">
-        <a class="btn btn-primary" href="/admin/cord/vbngtenant/">vBNG Tenants</a>
-    </div>
-</div>
-
diff --git a/xos/services/openvpn/__init__.py b/xos/services/openvpn/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/xos/services/openvpn/__init__.py
+++ /dev/null
diff --git a/xos/synchronizers/onboarding/xosbuilder.py b/xos/synchronizers/onboarding/xosbuilder.py
index 51499bd..6e24a28 100644
--- a/xos/synchronizers/onboarding/xosbuilder.py
+++ b/xos/synchronizers/onboarding/xosbuilder.py
@@ -256,9 +256,9 @@
 
          containers = {}
 
-         containers["xos_db"] = \
-                            {"image": "xosproject/xos-postgres",
-                             "expose": [5432]}
+#         containers["xos_db"] = \
+#                            {"image": "xosproject/xos-postgres",
+#                             "expose": [5432]}
 
          db_container_name = xos.docker_project_name + "_xos_db_1"
 
@@ -266,14 +266,14 @@
                             {"image": "xosproject/xos-ui",
                              "command": "python /opt/xos/manage.py runserver 0.0.0.0:%d --insecure --makemigrations" % xos.ui_port,
                              "ports": {"%d"%xos.ui_port : "%d"%xos.ui_port},
-                             "links": ["xos_db"],
-                             #"external_links": [db_container_name],
+                             #"links": ["xos_db"],
+                             "external_links": ["%s:%s" % (db_container_name, "xos_db")],
                              "volumes": volume_list}
 
 #         containers["xos_bootstrap_ui"] = {"image": "xosproject/xos",
 #                             "command": "python /opt/xos/manage.py runserver 0.0.0.0:%d --insecure --makemigrations" % xos.bootstrap_ui_port,
 #                             "ports": {"%d"%xos.bootstrap_ui_port : "%d"%xos.bootstrap_ui_port},
-#                             #"external_links": [db_container_name],
+#                             #"external_links": ["%s:%s" % (db_container_name, "xos_db")],
 #                             "links": ["xos_db"],
 #                             "volumes": volume_list}
 
@@ -292,8 +292,8 @@
                      containers["xos_synchronizer_%s" % c.name] = \
                                     {"image": "xosproject/xos-synchronizer-%s" % c.name,
                                      "command": command,
-                                     #"external_links": [db_container_name],
-                                     "links": ["xos_db"],
+                                     "external_links": ["%s:%s" % (db_container_name, "xos_db")],
+                                     #"links": ["xos_db"],
                                      "volumes": volume_list}
 
          vars = { "containers": containers }
diff --git a/xos/synchronizers/openvpn/__init__.py b/xos/synchronizers/openvpn/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/xos/synchronizers/openvpn/__init__.py
+++ /dev/null
diff --git a/xos/tests/api/dredd.yml b/xos/tests/api/dredd.yml
index a214c7c..9e32eba 100644
--- a/xos/tests/api/dredd.yml
+++ b/xos/tests/api/dredd.yml
@@ -32,4 +32,4 @@
 hooks-worker-handler-host: localhost
 hooks-worker-handler-port: 61321
 blueprint: apiary.apib
-endpoint: 'http://127.0.0.1:8000/'
+endpoint: 'http://127.0.0.1:9999/'
diff --git a/xos/tests/api/hooks.py b/xos/tests/api/hooks.py
index 707b258..e7ba705 100644
--- a/xos/tests/api/hooks.py
+++ b/xos/tests/api/hooks.py
@@ -153,13 +153,6 @@
 
     # print 'vcpe network relation added'
 
-    # vbng service
-    vbng_service = VBNGService()
-    vbng_service.name = 'service_vbng'
-    vbng_service.save()
-
-    # print 'vbng_service creater'
-
     # volt tenant
     vt = VOLTTenant(subscriber=subscriber.id, id=1)
     vt.s_tag = "222"
diff --git a/xos/services/cord_old/rest_examples/add_truckroll.sh b/xos/tests/rest_examples/add_truckroll.sh
similarity index 100%
rename from xos/services/cord_old/rest_examples/add_truckroll.sh
rename to xos/tests/rest_examples/add_truckroll.sh
diff --git a/xos/services/cord_old/rest_examples/add_volt_tenant.sh b/xos/tests/rest_examples/add_volt_tenant.sh
similarity index 100%
rename from xos/services/cord_old/rest_examples/add_volt_tenant.sh
rename to xos/tests/rest_examples/add_volt_tenant.sh
diff --git a/xos/services/cord_old/rest_examples/config.sh b/xos/tests/rest_examples/config.sh
similarity index 100%
rename from xos/services/cord_old/rest_examples/config.sh
rename to xos/tests/rest_examples/config.sh
diff --git a/xos/services/cord_old/rest_examples/delete_volt_tenant.sh b/xos/tests/rest_examples/delete_volt_tenant.sh
similarity index 100%
rename from xos/services/cord_old/rest_examples/delete_volt_tenant.sh
rename to xos/tests/rest_examples/delete_volt_tenant.sh
diff --git a/xos/services/cord_old/rest_examples/list_cord_subscribers.sh b/xos/tests/rest_examples/list_cord_subscribers.sh
similarity index 100%
rename from xos/services/cord_old/rest_examples/list_cord_subscribers.sh
rename to xos/tests/rest_examples/list_cord_subscribers.sh
diff --git a/xos/services/cord_old/rest_examples/list_truckrolls.sh b/xos/tests/rest_examples/list_truckrolls.sh
similarity index 100%
rename from xos/services/cord_old/rest_examples/list_truckrolls.sh
rename to xos/tests/rest_examples/list_truckrolls.sh
diff --git a/xos/services/cord_old/rest_examples/list_volt_tenants.sh b/xos/tests/rest_examples/list_volt_tenants.sh
similarity index 100%
rename from xos/services/cord_old/rest_examples/list_volt_tenants.sh
rename to xos/tests/rest_examples/list_volt_tenants.sh
diff --git a/xos/tools/xos-manage b/xos/tools/xos-manage
index 3478da3..e10a47e 100755
--- a/xos/tools/xos-manage
+++ b/xos/tools/xos-manage
@@ -143,14 +143,6 @@
     python ./manage.py makemigrations requestrouter
     python ./manage.py makemigrations syndicate_storage
     python ./manage.py makemigrations mcord
-#    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 servcomp
 
     if [[ -e /opt/xos/xos/xosbuilder_migration_list ]]; then
         cat /opt/xos/xos/xosbuilder_migration_list | while read line; do
diff --git a/xos/tosca/resources/xosmodel.py b/xos/tosca/resources/xosmodel.py
index 86aa8a8..343fb1f 100644
--- a/xos/tosca/resources/xosmodel.py
+++ b/xos/tosca/resources/xosmodel.py
@@ -17,7 +17,7 @@
 class XOSVolume(XOSResource):
     provides = "tosca.nodes.XOSVolume"
     xos_model = XOSVolume
-    copyin_props = ["host_path"]
+    copyin_props = ["host_path", "read_only"]
     name_field = "container_path"
 
     def get_xos_args(self, throw_exception=True):
diff --git a/xos/xos/config.py b/xos/xos/config.py
index 8ae7816..154ba20 100644
--- a/xos/xos/config.py
+++ b/xos/xos/config.py
@@ -81,8 +81,12 @@
 		if filename:
 			try:
 				if os.path.isdir(filename):
-					config_list = list(reversed(os.listdir(filename)))
- 					config_list.remove('README.md')
+					config_list = list(sorted(os.listdir(filename)))
+                                        config_list = [x for x in config_list if not x.endswith(".md")]
+                                        if "xos_common_config" in config_list:
+                                            # move xos_common_config to the front of the list
+                                            config_list.remove("xos_common_config")
+                                            config_list=["xos_common_config"] + config_list
 					config_list = [os.path.join(filename, s) for s in config_list]
 					self.config.read(config_list)
 				else:
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index 53d9c2c..85b5128 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -183,15 +183,8 @@
     'core',
     'services.hpc',
     'services.mcord',
-#    'services.onos',
-#    'services.ceilometer',
     'services.requestrouter',
     'services.syndicate_storage',
-    'services.openvpn',
-#    'services.vtr',
-#    'services.vrouter',
-#    'services.vtn',
-#    'services.fabric',
     'geoposition',
     'rest_framework_swagger',
 )