github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/public/static/js/spawned_hosts.js (about)

     1  mciModule.controller('SpawnedHostsCtrl', ['$scope','$window', '$timeout', 'mciSpawnRestService', 'notificationService', function($scope, $window, $timeout, mciSpawnRestService, notificationService) {
     2      $scope.userTz = $window.userTz;
     3      $scope.hosts = null;
     4      $scope.modalOpen = false;
     5      $scope.spawnTask = $window.spawnTask;
     6      $scope.spawnDistro = $window.spawnDistro;
     7  
     8      // variables for spawning a new host
     9      $scope.spawnableDistros = [];
    10      $scope.selectedDistro = {};
    11      $scope.userKeys = [];
    12      $scope.selectedKey = {};
    13      $scope.userData = {};
    14      $scope.spawnInfo = {};
    15      $scope.extensionLength = {};
    16      $scope.curHostData;
    17      $scope.hostExtensionLengths = {};
    18      $scope.maxHostsPerUser = $window.maxHostsPerUser;
    19      $scope.spawnReqSent = false;
    20  
    21      // max of 7 days time to expiration
    22      $scope.maxHoursToExpiration = 24*7;
    23      $scope.saveKey = false;
    24      $scope.currKeyName = '';
    25      $scope.newKey = {
    26        'name': 'New Key...',
    27        'key': '',
    28      };
    29  
    30      var epochTime = moment('Jan 1, 1970');
    31  
    32      $scope.sortOrders = [
    33        { name: 'Status', by: 'status' },
    34        { name: 'Uptime', by: 'uptime' },
    35        { name: 'Create Time', by: 'creation_time', reverse: false },
    36        { name: 'Distro', by: 'distro' }
    37      ];
    38  
    39      $scope.sortBy = $scope.sortOrders[0];
    40  
    41      $scope.extensionLengths = [
    42        {display: "1 hour", hours: 1},
    43        {display: "2 hours", hours: 2},
    44        {display: "4 hours", hours: 4},
    45        {display: "6 hours", hours: 6},
    46        {display: "8 hours", hours: 8},
    47        {display: "10 hours", hours: 10},
    48        {display: "12 hours", hours: 12},
    49        {display: "1 day", hours: 24},
    50        {display: "2 days", hours: 24*2},
    51        {display: "3 days", hours: 24*3},
    52        {display: "4 days", hours: 24*4},
    53        {display: "5 days", hours: 24*5},
    54        {display: "6 days", hours: 24*6},
    55        {display: "7 days", hours: 24*7},
    56      ];
    57  
    58      $scope.setSortBy = function(order) {
    59        $scope.sortBy = order;
    60      };
    61  
    62      // Spawn REST API calls
    63      $scope.fetchSpawnedHosts = function() {
    64        mciSpawnRestService.getSpawnedHosts(
    65          'hosts', {}, {
    66            success: function(hosts, status) {
    67              _.each(hosts, function(host) {
    68                host.isTerminated = host.status == 'terminated';
    69                var terminateTime = moment(host.termination_time);
    70                // check if the host is terminated to determine uptime
    71                if (terminateTime > epochTime) {
    72                  var uptime = terminateTime.diff(host.creation_time, 'seconds');
    73                  host.uptime = moment.duration(uptime, 'seconds').humanize();
    74                } else {
    75                  var uptime = moment().diff(host.creation_time, 'seconds');
    76                  host.uptime = moment.duration(uptime, 'seconds').humanize();
    77                  var expiretime = moment().diff(host.expiration_time, 'seconds');
    78                  if(+new Date(host.expiration_time) > +new Date("0001-01-01T00:00:00Z")){
    79                    host.expires_in = moment.duration(expiretime, 'seconds').humanize();
    80                  }
    81                }
    82                if ($scope.lastSelected && $scope.lastSelected.id == host.id) {
    83                  $scope.setSelected(host);
    84                }
    85             });
    86              $scope.hosts = hosts
    87            },
    88            error: function(jqXHR, status, errorThrown) {
    89              // Avoid errors when leaving the page because of a background refresh
    90              if ($scope.hosts == null && !$scope.errorFetchingHosts) {
    91                  notificationService.pushNotification('Error fetching spawned hosts: ' + jqXHR, 'errorHeader');
    92                  $scope.errorFetchingHosts = true;
    93              }
    94            }
    95          }
    96        );
    97      }
    98  
    99      // Load immediately, load again in 5 seconds to pick up any slow
   100      // spawns / terminates from the pervious post since they are async, and
   101      // every 60 seconds after that to pick up changes.
   102      $timeout($scope.fetchSpawnedHosts, 1);
   103      $timeout($scope.fetchSpawnedHosts, 5000);
   104      setInterval(function(){$scope.fetchSpawnedHosts();}, 60000);
   105  
   106      // Returns true if the user can spawn another host. If hosts has not been initialized it
   107      // assumes true.
   108      $scope.availableHosts = function() {
   109        return ($scope.hosts == null) || ($scope.hosts.length < $scope.maxHostsPerUser)
   110      }
   111  
   112      $scope.fetchSpawnableDistros = function(selectDistro, cb) {
   113        mciSpawnRestService.getSpawnableDistros(
   114          'distros', {}, {
   115            success: function(distros, status) {
   116              $scope.setSpawnableDistros(distros, selectDistro);
   117              // If there is a callback to run after the distros were fetched, 
   118              // execute it.
   119              if(cb){
   120                cb();
   121              }
   122            },
   123            error: function(jqXHR, status, errorThrown) {
   124              notificationService.pushNotification('Error fetching spawnable distros: ' + jqXHR,'errorHeader');
   125            }
   126          }
   127        );
   128      };
   129  
   130      $scope.fetchUserKeys = function() {
   131        mciSpawnRestService.getUserKeys(
   132          'keys', {}, {
   133            success: function(keys, status) {
   134              $scope.setUserKeys(keys);
   135            },
   136            error: function(jqXHR, status, errorThrown) {
   137              notificationService.pushNotification('Error fetching user keys: ' + jqXHR,'errorHeader');
   138            }
   139          }
   140        );
   141      };
   142  
   143      $scope.spawnHost = function() {
   144        $scope.spawnReqSent = true;
   145        $scope.spawnInfo.spawnKey = $scope.selectedKey;
   146        $scope.spawnInfo.saveKey = $scope.saveKey;
   147        $scope.spawnInfo.userData = $scope.userData.text;
   148        if($scope.spawnTaskChecked && !!$scope.spawnTask){
   149          $scope.spawnInfo.task_id = $scope.spawnTask.id;
   150        }
   151        mciSpawnRestService.spawnHost(
   152          $scope.spawnInfo, {}, {
   153            success: function(data, status) {
   154              window.location.href = "/spawn";
   155            },
   156            error: function(jqXHR, status, errorThrown) {
   157              $scope.spawnReqSent = false;
   158              notificationService.pushNotification('Error spawning host: ' + jqXHR,'errorHeader');
   159            }
   160          }
   161        );
   162      };
   163  
   164      $scope.updateRDPPassword = function () {
   165        mciSpawnRestService.updateRDPPassword(
   166          'updateRDPPassword',
   167          $scope.curHostData.id,
   168          $scope.curHostData.password, {}, {
   169            success: function (data, status) {
   170              window.location.href = "/spawn";
   171            },
   172            error: function (jqXHR, status, errorThrown) {
   173              notificationService.pushNotification('Error setting host RDP password: ' + jqXHR,'errorHeader');
   174            }
   175          }
   176        );
   177      };
   178  
   179      $scope.updateHostExpiration = function() {
   180        mciSpawnRestService.extendHostExpiration(
   181          'extendHostExpiration',
   182          $scope.curHostData.id,
   183          $scope.extensionLength.hours.toString(), {}, {
   184            success: function (data, status) {
   185              window.location.href = "/spawn";
   186            },
   187            error: function (jqXHR, status, errorThrown) {
   188              notificationService.pushNotification('Error extending host expiration: ' + jqXHR,'errorHeader');
   189            }
   190          }
   191        );
   192      };
   193  
   194      $scope.terminateHost = function() {
   195        mciSpawnRestService.terminateHost(
   196          'terminate',
   197          $scope.curHostData.id, {}, {
   198            success: function(data, status) {
   199              window.location.href = "/spawn";
   200            },
   201            error: function(jqXHR, status, errorThrown) {
   202              notificationService.pushNotification('Error terminating host: ' + jqXHR,'errorHeader');
   203            }
   204          }
   205        );
   206      };
   207  
   208      // API helper methods
   209      $scope.setSpawnableDistros = function(distros, selectDistroId) {
   210        if (distros.length == 0) {
   211          distros = [];
   212        }
   213        distros.forEach(function(spawnableDistro) {
   214          $scope.spawnableDistros.push({
   215            'distro': spawnableDistro
   216          });
   217        });
   218        if (distros.length > 0) {
   219          $scope.spawnableDistros.sort(function(a, b) {
   220            if (a.distro.name < b.distro.name) return -1;
   221            if (a.distro.name > b.distro.name) return 1;
   222            return 0;
   223          });
   224          $scope.selectedDistro = $scope.spawnableDistros[0].distro;
   225          $scope.spawnInfo = {
   226            'distroId': $scope.selectedDistro.name,
   227            'spawnKey': $scope.newKey,
   228          };
   229          if(selectDistroId){
   230            var selectedIndex = _.findIndex($scope.spawnableDistros, 
   231              function(x){return x.distro.name == selectDistroId}
   232            )
   233            if(selectedIndex>=0){
   234              $scope.selectedDistro = $scope.spawnableDistros[selectedIndex].distro;
   235              $scope.spawnInfo.distroId = $scope.selectedDistro.name;
   236            }
   237  
   238          }
   239        };
   240      };
   241  
   242      $scope.setExtensionLength = function(extensionLength) {
   243        $scope.extensionLength = extensionLength;
   244      };
   245  
   246      $scope.setUserKeys = function(publicKeys) {
   247        if (publicKeys == 'null') {
   248          publicKeys = [];
   249        }
   250        _.each(publicKeys, function(publicKey) {
   251          $scope.userKeys.push({ 'name': publicKey.name, 'key': publicKey.key });
   252        });
   253        if (publicKeys.length > 0) {
   254          $scope.userKeys.sort(function(a, b) {
   255            if (a.name < b.name) return -1;
   256            if (a.name > b.name) return 1;
   257            return 0;
   258          });
   259          $scope.updateSelectedKey($scope.userKeys[0]);
   260        } else {
   261          $scope.updateSelectedKey($scope.newKey);
   262        }
   263        // disable key name text field by default
   264        $('#input-key-name').attr('disabled', true);
   265      };
   266  
   267  
   268      // User Interface helper functions
   269      // set the spawn request distro based on user selection
   270      $scope.setSpawnableDistro = function(spawnableDistro) {
   271        $scope.selectedDistro = spawnableDistro
   272        $scope.spawnInfo.distroId = spawnableDistro.name;
   273      };
   274  
   275      // toggle spawn key based on user selection
   276      $scope.updateSelectedKey = function(selectedKey) {
   277        $scope.selectedKey.name = selectedKey.name;
   278        $scope.selectedKey.key = selectedKey.key;
   279        $scope.currKeyName = $scope.selectedKey.name;
   280      };
   281  
   282      // indicates if user wishes to save this key
   283      $scope.toggleSaveKey = function() {
   284        $scope.saveKey = !$scope.saveKey;
   285      }
   286  
   287      $scope.getSpawnStatusLabel = function(host) {
   288        if (host) {
   289          switch (host.status) {
   290          case 'running':
   291            return 'label success';
   292            break;
   293          case 'provisioning':
   294          case 'starting':
   295            return 'label block-status-started';
   296            break;
   297          case 'decommissioned':
   298          case 'unreachable':
   299          case 'quarantined':
   300          case 'provision failed':
   301            return 'label block-status-cancelled';
   302            break;
   303          case 'terminated':
   304            return 'label block-status-failed';
   305            break;
   306          default:
   307            return '';
   308          }
   309        }
   310      }
   311  
   312      // populate for selected host; highlight selected host
   313      $scope.setSelected = function(host) {
   314        if ($scope.lastSelected) {
   315          $scope.lastSelected.selected = '';
   316        }
   317        host.selected = 'active-host';
   318        host.password = '';
   319        host.cPassword = '';
   320        $scope.lastSelected = host;
   321        $scope.curHostData = host;
   322        $scope.curHostData.isTerminated = host.isTerminated;
   323        // check if this is a windows host
   324        $scope.curHostData.isWinHost = false;
   325        if (host.distro.arch.indexOf('win') != -1) {
   326          $scope.curHostData.isWinHost = true;
   327        }
   328        $scope.updateExtensionOptions($scope.curHostData);
   329      };
   330  
   331      $scope.updateExtensionOptions = function(host) {
   332        $scope.hostExtensionLengths = [];
   333        _.each($scope.extensionLengths, function(extensionLength) {
   334          var remainingTimeSec = moment(host.expiration_time).diff(moment(), 'seconds');
   335          var remainingTimeDur = moment.duration(remainingTimeSec, 'seconds');
   336          remainingTimeDur.add(extensionLength.hours, 'hours');
   337  
   338          // you should only be able to extend duration for a max of 7 days
   339          if (remainingTimeDur.as('hours') < $scope.maxHoursToExpiration) {
   340            $scope.hostExtensionLengths.push(extensionLength);
   341          }
   342        });
   343        if ($scope.hostExtensionLengths.length > 0) {
   344          $scope.setExtensionLength($scope.hostExtensionLengths[0]);
   345        }
   346      }
   347  
   348      $scope.setExtensionLength = function(extensionLength) {
   349        $scope.extensionLength = extensionLength;
   350      }
   351  
   352      $scope.openSpawnModal = function(opt) {
   353        $scope.modalOption = opt;
   354        $scope.modalOpen = true;
   355  
   356        var modal = $('#spawn-modal').modal('show');
   357        if ($scope.modalOption === 'spawnHost') {
   358          $scope.fetchUserKeys();
   359          if ($scope.spawnableDistros.length == 0) {
   360            $scope.fetchSpawnableDistros();
   361          }
   362          $scope.modalTitle = 'Spawn Host';
   363          modal.on('shown.bs.modal', function() {
   364            $scope.modalOpen = true;
   365            $scope.$apply();
   366          });
   367  
   368          modal.on('hide.bs.modal', function() {
   369            $scope.modalOpen = false;
   370            $scope.$apply();
   371          });
   372        } else if ($scope.modalOption === 'terminateHost') {
   373          $scope.modalTitle = 'Terminate Host';
   374          modal.on('shown.bs.modal', function() {
   375            $scope.modalOpen = true;
   376            $scope.$apply();
   377          });
   378  
   379          modal.on('hide.bs.modal', function() {
   380            $scope.modalOpen = false;
   381            $scope.$apply();
   382          });
   383        } else if ($scope.modalOption === 'updateRDPPassword') {
   384          $scope.modalTitle = 'Set RDP Password';
   385          modal.on('shown.bs.modal', function () {
   386            $('#password-input').focus();
   387            $scope.modalOpen = true;
   388            $scope.$apply();
   389          });
   390  
   391          modal.on('hide.bs.modal', function () {
   392            $scope.modalOpen = false;
   393            $scope.$apply();
   394          });
   395        }
   396  
   397      };
   398  
   399      $(document).keyup(function(ev) {
   400        if ($scope.modalOpen && ev.keyCode === 13) {
   401          if ($scope.modalOption === 'terminateHost') {
   402            $scope.terminateHost();
   403            $('#spawn-modal').modal('hide');
   404          }
   405        }
   406      });
   407  
   408      if($scope.spawnTask && $scope.spawnDistro){
   409        // find the spawn distro in the spawnable distros list, if it's there, 
   410        // pre-select it in the modal.
   411        $scope.spawnTaskChecked = true 
   412        setTimeout(function(){
   413          $scope.fetchSpawnableDistros($scope.spawnDistro._id, function(){
   414            $scope.openSpawnModal('spawnHost')
   415          });
   416        }, 0)
   417      }
   418    }
   419  
   420  ]);