Updating login structure

Updated login structure with a field where user can manually add server hostname if it is not populated automatically

Change-Id: I147c2c15869131540e327bda26c05b59d78e01d5
Signed-off-by: Iftekharul Islam <iffy.ryan@ibm.com>
diff --git a/app/common/directives/app-header.html b/app/common/directives/app-header.html
index 9388bb6..0ba8607 100644
--- a/app/common/directives/app-header.html
+++ b/app/common/directives/app-header.html
@@ -6,9 +6,9 @@
 	</header>
 	<div class="header__functions-wrapper" role="heading">
 		<div class="logo__wrapper"><img src="assets/images/logo.svg" class="header__logo" alt="company logo"/></div>
-		<button class="inline header__multi-server" aria-label="multi server select" ng-class="{'active': multi_server_recent}" ng-click="multiRecent();">
+		<!-- <button class="inline header__multi-server" aria-label="multi server select" ng-class="{'active': multi_server_recent}" ng-click="multiRecent();">
 			<span class="icon icon-angle" aria-hidden="true"></span><span class="accessible-text">Multi server switcher</span>
-		</button>
+		</button>-->
 		<div class="inline header__server-name">
 			<p class="header__hostname">{{dataService.hostname}}</p>
 			<p class="header__server-ip courier-bold">BMC IP address {{dataService.server_id}}</p>
diff --git a/app/common/directives/app-navigation.html b/app/common/directives/app-navigation.html
index 4e75a0d..3213345 100644
--- a/app/common/directives/app-navigation.html
+++ b/app/common/directives/app-navigation.html
@@ -64,7 +64,7 @@
 				<span>Users</span>
 			</button>
 		</li>
-		<li class="btn-multi-server">
+		<!--<li class="btn-multi-server">
 			<a ng-class="{opened: firstLevel == 'multi-server'}" href="#/multi-server/overview" ng-click="change('multi-server')" tabindex="6">
 				<span>
 					<svg class="nav-icon" version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 24 24" xml:space="preserve">
@@ -75,7 +75,7 @@
 	s4.7,2.1,4.7,4.7s-2.1,4.7-4.7,4.7S2.2,9.5,2.2,6.9z"/>
 </svg>
 				All Servers</span></a>
-		</li>
+		</li> -->
 	</ul>
 	<ul class="nav__second-level btn-health" ng-style="navStyle" ng-class="{opened: (showSubMenu && firstLevel == 'server-health')}">
 		<li ng-class="{'active': (path == '/server-health/event-log')}">
diff --git a/app/common/directives/firmware-list.html b/app/common/directives/firmware-list.html
index 2f1d3fc..c53a417 100644
--- a/app/common/directives/firmware-list.html
+++ b/app/common/directives/firmware-list.html
@@ -21,16 +21,23 @@
 			</div>
 		</div>
 		<div class="table__body">
-			<div class="table__row" ng-class="firmware.active ? 'firmware__primary' : ''" ng-repeat="firmware in firmwares|filter:filterBy">
+			<div class="table__row" ng-class="firmware.functional ? 'firmware__primary' : ''" ng-repeat="firmware in firmwares|filter:filterBy|orderBy:'+Priority'">
 				<div class="table__cell">
 					<span class="table__cell-label">Boot priority:</span>
-					<div class="icon icon__up-arrow icon-as-spacer" aria-hidden="true">
+					<div class="icon icon__up-arrow" aria-hidden="true" ng-class="{'icon-as-spacer':$first}"
+					     ng-click="!$first && changePriority(firmware.imageId, firmware.Priority, firmware.Priority - 1)"
+					     ng-show="firmware.activationFlags.functional || firmware.activationFlags.ready">
 						<span class="accessible-text">firmware up in priority</span></div>
-					<div class="icon icon__down-arrow" aria-hidden="true">
+					<div class="icon icon__down-arrow" aria-hidden="true" ng-class="{'icon-as-spacer':$last}"
+					    ng-click="!$last && changePriority(firmware.imageId, firmware.Priority, firmware.Priority + 1)"
+					    ng-hide="firmware.activationFlags.ready">
 						<span class="accessible-text">firmware down in priority</span></div>
 				</div>
 				<div class="table__cell firmware__active">
-					<span class="table__cell-label">Image state:</span><span ng-if="firmware.active">Active</span>
+					<span class="table__cell-label">Image state:</span>
+					<span ng-if="firmware.activationFlags.functional">Functional</span>
+					<span ng-if="firmware.activationFlags.active">Active</span>
+					<span ng-if="firmware.activationFlags.ready">Ready</span>
 				</div>
 				<div class="table__cell firmware__version" ng-class="{'active':firmware.isExtended}">
 					<span class="table__cell-label">Version:</span>{{firmware.Version}}
@@ -52,8 +59,8 @@
 				</div>
 				<div class="table__cell">
 				    <span class="table__cell-label">Action:</span>
-				    <button class="firmware__action-link" ng-show="!firmware.active" ng-click="activate(firmware.imageId)">Activate</button>
-				    <button class="firmware__action-link" ng-show="!firmware.active" ng-click="delete(firmware.imageId)">Delete</button>
+				    <button class="firmware__action-link" ng-show="firmware.activationFlags.ready" ng-click="activate(firmware.imageId)">Activate</button>
+				    <button class="firmware__action-link" ng-show="!firmware.functional" ng-click="delete(firmware.imageId)">Delete</button>
 				</div>
 			</div>
 		</div>
diff --git a/app/common/directives/firmware-list.js b/app/common/directives/firmware-list.js
index f4cc94f..6cfa3a1 100644
--- a/app/common/directives/firmware-list.js
+++ b/app/common/directives/firmware-list.js
@@ -22,6 +22,10 @@
                     $scope.delete = function(imageId){
                         $scope.$parent.deleteImage(imageId);
                     }
+
+                    $scope.changePriority = function(imageId, from, to){
+                        $scope.$parent.changePriority(imageId, from, to);
+                    }
                 }]
             };
         }]);
diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js
index 46caf90..c17577c 100644
--- a/app/common/services/api-utils.js
+++ b/app/common/services/api-utils.js
@@ -11,7 +11,7 @@
     'use strict';
     angular
         .module('app.common.services')
-        .factory('APIUtils', ['$http', 'Constants', '$q', function($http, Constants, $q){
+        .factory('APIUtils', ['$http', 'Constants', '$q', 'dataService',function($http, Constants, $q, DataService){
           var SERVICE = {
               LOGIN_CREDENTIALS: Constants.LOGIN_CREDENTIALS,
               API_CREDENTIALS: Constants.API_CREDENTIALS,
@@ -21,10 +21,11 @@
               HOST_STATE: Constants.HOST_STATE,
               LED_STATE: Constants.LED_STATE,
               LED_STATE_TEXT: Constants.LED_STATE_TEXT,
+              HOST_SESSION_STORAGE_KEY: Constants.API_CREDENTIALS.host_storage_key,
               getChassisState: function(callback){
                 $http({
                   method: 'GET',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/state/chassis0",
+                  url: DataService.getHost() + "/xyz/openbmc_project/state/chassis0",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -41,7 +42,7 @@
               getHostState: function(callback){
                 $http({
                   method: 'GET',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/state/host0",
+                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -59,7 +60,7 @@
                 var deferred = $q.defer();
                 $http({
                   method: 'GET',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/network/enumerate",
+                  url: DataService.getHost() + "/xyz/openbmc_project/network/enumerate",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -98,7 +99,7 @@
                 var deferred = $q.defer();
                 $http({
                   method: 'GET',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/led/groups/enclosure_identify",
+                  url: DataService.getHost() + "/xyz/openbmc_project/led/groups/enclosure_identify",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -117,7 +118,7 @@
               login: function(username, password, callback){
                 $http({
                   method: 'POST',
-                  url: SERVICE.API_CREDENTIALS.host + "/login",
+                  url: DataService.getHost() + "/login",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -142,7 +143,7 @@
               logout: function(callback){
                 $http({
                   method: 'POST',
-                  url: SERVICE.API_CREDENTIALS.host + "/logout",
+                  url: DataService.getHost() + "/logout",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -163,7 +164,7 @@
               chassisPowerOn: function(callback){
                 $http({
                   method: 'POST',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/state/host0",
+                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -187,7 +188,7 @@
               chassisPowerOff: function(callback){
                 $http({
                   method: 'POST',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/state/host0",
+                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -211,7 +212,7 @@
               setLEDState: function(state, callback){
                 $http({
                   method: 'PUT',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted",
+                  url: DataService.getHost() + "/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -235,7 +236,7 @@
               bmcReboot: function(callback){
                 $http({
                   method: 'PUT',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/state/bmc0/attr/RequestedBmcTransition",
+                  url: DataService.getHost() + "/xyz/openbmc_project/state/bmc0/attr/RequestedBmcTransition",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -259,7 +260,7 @@
               hostPowerOn: function(callback){
                 $http({
                   method: 'PUT',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition",
+                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -283,7 +284,7 @@
               hostPowerOff: function(callback){
                 $http({
                   method: 'PUT',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition",
+                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -307,7 +308,7 @@
               hostReboot: function(callback){
                 $http({
                   method: 'POST',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/state/host0",
+                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -331,7 +332,7 @@
               hostShutdown: function(callback){
                 $http({
                   method: 'POST',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/state/host0",
+                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -356,7 +357,7 @@
                 var deferred = $q.defer();
                 $http({
                   method: 'GET',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/logging/enumerate",
+                  url: DataService.getHost() + "/xyz/openbmc_project/logging/enumerate",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -414,7 +415,7 @@
               getAllSensorStatus: function(callback){
                 $http({
                   method: 'GET',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/sensors/enumerate",
+                  url: DataService.getHost() + "/xyz/openbmc_project/sensors/enumerate",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -543,7 +544,7 @@
                 var deferred = $q.defer();
                 $http({
                   method: 'GET',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/software/enumerate",
+                  url: DataService.getHost() + "/xyz/openbmc_project/software/enumerate",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -554,6 +555,9 @@
                       var content = JSON.parse(json);
                       var data = [];
                       var active = false;
+                      var functional = false;
+                      var ready = false;
+                      var activationStatus = {active: false, ready: false, functional: false};
                       var isExtended = false;
                       var bmcActiveVersion = "";
                       var hostActiveVersion = "";
@@ -588,7 +592,11 @@
 
                       for(var key in content.data){
                         if(content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Version')){
+
+                          functional = (content.data[key].Priority == 0);
                           active = (/\.Active$/).test(content.data[key].Activation);
+                          ready = (/\.Ready$/).test(content.data[key].Activation);
+                          activationStatus = {functional: functional, active: active, ready: ready};
                           imageType = content.data[key].Purpose.split(".").pop();
                           isExtended = content.data[key].hasOwnProperty('ExtendedVersion') && content.data[key].ExtendedVersion != "";
                           if(isExtended){
@@ -596,7 +604,8 @@
                           }
                           data.push(Object.assign({
                             path: key,
-                            active: active,
+                            functional: functional,
+                            activationFlags: activationStatus,
                             imageId: key.split("/").pop(),
                             imageType: imageType,
                             isExtended: isExtended,
@@ -607,11 +616,11 @@
                             data: {key: key, value: content.data[key]}
                           }, content.data[key]));
 
-                          if(active && imageType == 'BMC'){
+                          if(functional && imageType == 'BMC'){
                             bmcActiveVersion = content.data[key].Version;
                           }
 
-                          if(active && imageType == 'Host'){
+                          if(functional && imageType == 'Host'){
                             hostActiveVersion = content.data[key].Version;
                           }
                         }
@@ -629,12 +638,34 @@
 
                 return deferred.promise;
               },
-              uploadImage: function(file, callback){
+              changePriority: function(imageId, priority){
+                var deferred = $q.defer();
+                $http({
+                  method: 'PUT',
+                  url: DataService.getHost() + "/xyz/openbmc_project/software/" + imageId + "/attr/Priority",
+                  headers: {
+                      'Accept': 'application/octet-stream',
+                      'Content-Type': 'application/octet-stream'
+                  },
+                  withCredentials: true,
+                  data: JSON.stringify({"data": priority})
+                }).success(function(response){
+                      var json = JSON.stringify(response);
+                      var content = JSON.parse(json);
+                      deferred.resolve(content);
+                }).error(function(error){
+                  console.log(error);
+                  deferred.reject(error);
+                });
+
+                return deferred.promise;
+              },
+              uploadImage: function(file){
+                var deferred = $q.defer();
                 $http({
                   method: 'PUT',
                   timeout: 5 * 60 * 1000,
-                  //url: 'http://localhost:3002/upload',
-                  url: SERVICE.API_CREDENTIALS.host + "/upload/image/",
+                  url: DataService.getHost() + "/upload/image/",
                   headers: {
                       'Accept': 'application/octet-stream',
                       'Content-Type': 'application/octet-stream'
@@ -644,22 +675,44 @@
                 }).success(function(response){
                       var json = JSON.stringify(response);
                       var content = JSON.parse(json);
-                      if(callback){
-                          return callback(content);
-                      }
+                      deferred.resolve(content);
                 }).error(function(error){
-                  if(callback){
-                      callback(error);
-                  }else{
-                      console.log(error);
-                  }
+                  console.log(error);
+                  deferred.reject(error);
                 });
+
+                return deferred.promise;
+              },
+              downloadImage: function(host, filename){
+                var deferred = $q.defer();
+                $http({
+                  method: 'POST',
+                  url: DataService.getHost() + "/org/openbmc/control/flash/bmc/action/updateViaTftp",
+                  headers: {
+                      'Accept': 'application/json',
+                      'Content-Type': 'application/json'
+                  },
+                  withCredentials: true,
+                  data: JSON.stringify({"data": [host, filename]}),
+                  responseType: 'arraybuffer'
+                }).success(function(response, status, headers){
+                  deferred.resolve({
+                    data: response,
+                    status: status,
+                    headers: headers
+                  });
+                }).error(function(error){
+                  console.log(error);
+                  deferred.reject(error);
+                });
+
+                return deferred.promise;
               },
               getBMCEthernetInfo: function(){
                 var deferred = $q.defer();
                 $http({
                   method: 'GET',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc/ethernet",
+                  url: DataService.getHost() + "/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc/ethernet",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -680,7 +733,7 @@
                 var deferred = $q.defer();
                 $http({
                   method: 'GET',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc",
+                  url: DataService.getHost() + "/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -699,7 +752,7 @@
               getHardwares: function(callback){
                 $http({
                   method: 'GET',
-                  url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/inventory/enumerate",
+                  url: DataService.getHost() + "/xyz/openbmc_project/inventory/enumerate",
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
@@ -815,7 +868,7 @@
                   logs.forEach(function(item){
                     promises.push($http({
                                       method: 'POST',
-                                      url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/logging/entry/"+item.Id+"/action/Delete",
+                                      url: DataService.getHost() + "/xyz/openbmc_project/logging/entry/"+item.Id+"/action/Delete",
                                       headers: {
                                           'Accept': 'application/json',
                                           'Content-Type': 'application/json'
@@ -840,7 +893,7 @@
                   logs.forEach(function(item){
                     promises.push($http({
                                       method: 'PUT',
-                                      url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/logging/entry/"+item.Id+"/attr/Resolved",
+                                      url: DataService.getHost() + "/xyz/openbmc_project/logging/entry/"+item.Id+"/attr/Resolved",
                                       headers: {
                                           'Accept': 'application/json',
                                           'Content-Type': 'application/json'
diff --git a/app/common/services/constants.js b/app/common/services/constants.js
index 2c48822..4852954 100644
--- a/app/common/services/constants.js
+++ b/app/common/services/constants.js
@@ -20,8 +20,8 @@
                     password: "testpass",
                 },
                 API_CREDENTIALS: {
-                    host: 'https://9.3.181.64',
-                    mock_host: 'http://localhost:3000'
+                    host_storage_key: 'API_HOST_KEY',
+                    default_protocol: 'https'
                 },
                 API_RESPONSE: {
                     ERROR_STATUS: 'error',
@@ -109,7 +109,15 @@
                    'xyz.openbmc_project.Sensor.Value.Unit.Joules',
                    'xyz.openbmc_project.Sensor.Value.Unit.Meters'
                 ],
-                SENSOR_SORT_ORDER_DEFAULT: 8
+                SENSOR_SORT_ORDER_DEFAULT: 8,
+                FIRMWARE: {
+                  FALLBACK_DOWNLOAD_FILENAME: 'firmware_download.tar',
+                  TYPES: {
+                    Functional: 'Functional',
+                    Active: 'Active',
+                    Ready: 'Ready'
+                  }
+                }
             };
         });
 
diff --git a/app/common/services/dataService.js b/app/common/services/dataService.js
index 00ea1ba..51e67bf 100644
--- a/app/common/services/dataService.js
+++ b/app/common/services/dataService.js
@@ -20,7 +20,6 @@
             this.server_status = -2;
             this.chassis_state = 'On';
             this.LED_state = Constants.LED_STATE_TEXT.off;
-            this.server_id = Constants.API_CREDENTIALS.host.replace(/[^\d]+/m,"");
             this.last_updated = new Date();
 
             this.loading = false;
@@ -35,6 +34,35 @@
             this.mac_address = "";
             this.remote_window_active = false;
 
+            this.getServerId = function(){
+                 return this.host.replace(/[^\d]+/m,"");
+            }
+
+            this.reloadServerId = function(){
+                this.server_id = this.getServerId();
+            }
+
+            this.getHost = function(){
+                if(sessionStorage.getItem(Constants.API_CREDENTIALS.host_storage_key) !== null){
+                    return sessionStorage.getItem(Constants.API_CREDENTIALS.host_storage_key);
+                }else{
+                    return Constants.API_CREDENTIALS.default_protocol + "://" +
+                           window.location.hostname + ':' +
+                           window.location.port;
+                }
+            }
+
+            this.setHost = function(hostWithPort){
+                hostWithPort = hostWithPort.replace(/^https?\:\/\//ig, '');
+                var hostURL = Constants.API_CREDENTIALS.default_protocol + "://" + hostWithPort;
+                sessionStorage.setItem(Constants.API_CREDENTIALS.host_storage_key, hostURL);
+                this.host = hostURL;
+                this.reloadServerId();
+            }
+
+            this.host = this.getHost();
+            this.server_id = this.getServerId();
+
             this.setNetworkInfo = function(data){
                 this.hostname = data.hostname;
                 this.mac_address = data.mac_address;
diff --git a/app/common/services/userModel.js b/app/common/services/userModel.js
index 747b288..a3fc277 100644
--- a/app/common/services/userModel.js
+++ b/app/common/services/userModel.js
@@ -40,6 +40,7 @@
                         if(response &&
                            response.status == APIUtils.API_RESPONSE.SUCCESS_STATUS){
                             sessionStorage.removeItem('LOGIN_ID');
+                            sessionStorage.removeItem(APIUtils.HOST_SESSION_STORAGE_KEY);
                             callback(true);
                         }else if(response.status == APIUtils.API_RESPONSE.ERROR_STATUS){
                             callback(false);
diff --git a/app/configuration/controllers/firmware-controller.html b/app/configuration/controllers/firmware-controller.html
index 1f67caa..c305047 100644
--- a/app/configuration/controllers/firmware-controller.html
+++ b/app/configuration/controllers/firmware-controller.html
@@ -1,3 +1,4 @@
+<loader loading="loading"></loader>
 <div class="row column">
 	<h1>Firmware</h1>
 	<div class="column small-12 page-header">
@@ -34,14 +35,14 @@
 				<div class="row">
 					<div class="column small-12 large-4">
 						<label for="tftp-ip">TFTP Server IP address</label>
-						<input name="tftp-ip" id="tftp-ip" type="number"/>
+						<input name="tftp-ip" id="tftp-ip" type="text"  ng-model="download_host"/>
 					</div>
 					<div class="column small-12 large-4">
 						<label for="tftp-file-name">File name</label>
-						<input name="tftp-file-name" id="tftp-file-name" type="text"/>
+						<input name="tftp-file-name" id="tftp-file-name" type="text"  ng-model="download_filename"/>
 					</div>
 					<div class="column small-12 large-4">
-						<input type="submit" value="Download firmware" class="inline button btn-primary float-right"/>
+						<input type="button" value="Download firmware" class="inline button btn-primary float-right" ng-click="download()"/>
 					</div>
 				</div>
 				<div class="inline uploading" ng-show="downloading">Downloading in progress...</div>
@@ -67,6 +68,23 @@
 	</div>
 </section>
 
+<section class="modal" aria-hidden="true" aria-labelledby="modalTitle" aria-describedby="modalDescription" role="dialog" ng-class="{'active': confirm_priority}">
+	<div class="modal__tftp-unreachable" role="document">
+		<div class="screen-reader-offscreen modal-description">Update image priority</div><!-- accessibility only; used for screen readers -->
+		<div class="page-header ">
+			<span class="icon icon__warning inline"><span class="accessible-text" role="alert">Warning</span></span>
+			<h1 class="modal-title h4 inline">Change image priority</h1>
+		</div>
+		<div class="modal__content">
+			<p>Change firmware {{priority_image_id}} priority?</p>
+		</div>
+		<div class="modal__button-wrapper">
+			<button class="inline btn-secondary" ng-click="confirm_priority=false;">Cancel</button>
+			<button class="inline btn-primary" ng-click="confirmChangePriority()">Continue</button>
+		</div>
+	</div>
+</section>
+
 <section class="modal" aria-hidden="true" aria-labelledby="modalTitle" aria-describedby="modalDescription" role="dialog" ng-class="{'active': confirm_delete}">
 	<div class="modal__tftp-unreachable" role="document">
 		<div class="screen-reader-offscreen modal-description">Delete firmware image</div><!-- accessibility only; used for screen readers -->
diff --git a/app/configuration/controllers/firmware-controller.js b/app/configuration/controllers/firmware-controller.js
index 66c4297..50df4f0 100644
--- a/app/configuration/controllers/firmware-controller.js
+++ b/app/configuration/controllers/firmware-controller.js
@@ -19,7 +19,8 @@
                 'dataService',
                 '$location',
                 '$anchorScroll',
-                function ($scope, $window, APIUtils, dataService, $location, $anchorScroll) {
+                'Constants',
+                function ($scope, $window, APIUtils, dataService, $location, $anchorScroll, Constants) {
                     $scope.dataService = dataService;
 
                     //Scroll to target anchor
@@ -37,6 +38,10 @@
                     $scope.preserve_settings_confirm = false;
                     $scope.delete_image_id = "";
                     $scope.activate_image_id = "";
+                    $scope.priority_image_id = "";
+                    $scope.priority_from = -1;
+                    $scope.priority_to = -1;
+                    $scope.confirm_priority = false;
                     $scope.file_empty = true;
                     $scope.uploading = false;
 
@@ -73,7 +78,7 @@
                     }
                     $scope.confirmUpload = function(){
                         $scope.uploading = true;
-                        APIUtils.uploadImage($scope.file, function(response){
+                        APIUtils.uploadImage($scope.file).then(function(response){
                             $scope.uploading = false; 
                             if(response.status == 'error'){
                                 $scope.displayError({
@@ -89,6 +94,69 @@
                         $scope.confirm_upload_image = false;
                     }
 
+                    $scope.download = function(){
+                        $scope.downloading = true;
+                        APIUtils.downloadImage($scope.download_host, $scope.download_filename).then(function(response){
+                            var data = response.data;
+                            $scope.downloading = false;
+                            var headers = response.headers();
+
+                            var filename = headers['x-filename'];
+                            var contentType = headers['content-type'];
+
+                            if(!headers['x-filename']){
+                                filename = Constants.FIRMWARE.FALLBACK_DOWNLOAD_FILENAME;
+                            }
+
+                            var linkElement = document.createElement('a');
+                            try {
+                                var blob = new Blob([data], { type: contentType });
+                                var url = window.URL.createObjectURL(blob);
+
+                                linkElement.setAttribute('href', url);
+                                linkElement.setAttribute("download", filename);
+
+                                var clickEvent = new MouseEvent("click", {
+                                    "view": window,
+                                    "bubbles": true,
+                                    "cancelable": false
+                                });
+                                linkElement.dispatchEvent(clickEvent);
+                            } catch (ex) {
+                                console.log(ex);
+                            }
+                        });
+                    }
+
+                    $scope.changePriority = function(imageId, from, to){
+                        $scope.priority_image_id = imageId;
+                        $scope.priority_from = from;
+                        $scope.priority_to = to;
+
+                        if((from + to) == 1){
+                            $scope.confirm_priority = true;
+                        }else{
+                            $scope.confirmChangePriority();
+                        }
+                    }
+
+                    $scope.confirmChangePriority = function(){
+                        $scope.loading = true;
+                        APIUtils.changePriority($scope.priority_image_id, $scope.priority_to).then(function(response){
+                            $scope.loading = false;
+                            if(response.status == 'error'){
+                                $scope.displayError({
+                                    modal_title: response.data.description,
+                                    title: response.data.description,
+                                    desc: response.data.exception,
+                                    type: 'Error'
+                                });
+                            }else{
+                                $scope.loadFirmwares();
+                            }
+                        });
+                        $scope.confirm_priority = false;
+                    }
                     $scope.deleteImage = function(imageId){
                         $scope.delete_image_id = imageId;
                         $scope.confirm_delete = true;
diff --git a/app/login/controllers/login-controller.html b/app/login/controllers/login-controller.html
index 162ede3..77ca583 100644
--- a/app/login/controllers/login-controller.html
+++ b/app/login/controllers/login-controller.html
@@ -9,23 +9,19 @@
     <div class="row">
         <div class="columns large-6 login__desc">
             <h1>OpenBMC for IBM Power Systems</h1>
-            <ul class="login__server-info">
-                <li><p class="login__info-label">API version</p><p>X.XX.XXX</p></li>
-                <li><p class="login__info-label">Server ID</p><p>XXXXXXXXXXXXXXXX</p></li>
-                <li><p class="login__info-label">Server model</p><p>Power XX-XXXXX</p></li>
-                <li><p class="login__info-label">Server power</p><p class="status-light__disabled">Indeterminate</p></li>
-                <li><p class="login__info-label">Status message</p><!--<p>BMC was reset by user</p>--></li>
-            </ul>
         </div>
         <div class="columns large-6 disabled">
             <form id="login__form" action="">
+                <label >Host</label>
+                <input type="text" ng-model="host" required  ng-class="{error: error}" autofocus ng-keydown="tryLogin(host, username, password, $event)" ng-disabled="dataService.loading">
+
                 <label for="username">Username</label>
-                <input type="text" id="username" name="username" required ng-model="username" ng-class="{error: error}" ng-keydown="tryLogin(username, password, $event)" ng-disabled="dataService.loading" autofocus>
+                <input type="text" id="username" name="username" required ng-model="username" ng-class="{error: error}" ng-keydown="tryLogin(host, username, password, $event)" ng-disabled="dataService.loading">
 
                 <label for="password">Password</label>
-                <input type="password" id="password" name="password" class="" required ng-model="password" ng-keydown="tryLogin(username, password, $event)" ng-disabled="dataService.loading">
+                <input type="password" id="password" name="password" class="" required ng-model="password" ng-keydown="tryLogin(host, username, password, $event)" ng-disabled="dataService.loading">
 
-                <input id="login__submit" class="btn-primary submit" type="button" value="Log in" role="button" ng-click="login(username, password)" ng-class="{error: error}" ng-disabled="dataService.loading">
+                <input id="login__submit" class="btn-primary submit" type="button" value="Log in" role="button" ng-click="login(host, username, password)" ng-class="{error: error}" ng-disabled="dataService.loading">
 
                 <p class="login__error-msg" role="alert" ng-if="error">Incorrect username or password</p>
                 <p class="login__error-msg" role="alert" ng-if="server_unreachable">Server unreachable</p>
diff --git a/app/login/controllers/login-controller.js b/app/login/controllers/login-controller.js
index d8e8951..79ee477 100644
--- a/app/login/controllers/login-controller.js
+++ b/app/login/controllers/login-controller.js
@@ -21,6 +21,7 @@
             '$routeParams',
             function($scope, $window, APIUtils, dataService, userModel, $routeParams){
                 $scope.dataService = dataService;
+                $scope.host = $scope.dataService.host.replace(/^https?\:\/\//ig, '');
 
                 if($routeParams.fake_login &&
                    $routeParams.fake_login === 'fake_login'){
@@ -28,19 +29,22 @@
                     $window.location.hash = '#/overview/server';
                 }
 
-                $scope.tryLogin = function(username, password, event){
+                $scope.tryLogin = function(host, username, password, event){
                     if(event.keyCode === 13){
-                        $scope.login(username, password);
+                        $scope.login(host, username, password);
                     }
                 }; 
-                $scope.login = function(username, password){
+                $scope.login = function(host, username, password){
                     $scope.error = false;
                     $scope.server_unreachable = false;
 
                     if(!username || username == "" ||
-                       !password || password == ""){
+                       !password || password == "" ||
+                       !host || host == ""
+                       ){
                         return false;
                     }else{
+                        $scope.dataService.setHost(host);
                         userModel.login(username, password, function(status, unreachable){
                             if(status){
                                 $scope.$emit('user-logged-in',{});