Index: /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/avx/models/system/ntp.py
===================================================================
--- /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/avx/models/system/ntp.py	(revision 8916)
+++ /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/avx/models/system/ntp.py	(working copy)
@@ -3,10 +3,12 @@
 from hive.model.query import mark_expire_all
 from ast import literal_eval
 from hive.model.legacycli import cli_parse
+import re
 
 class NTPSettings(ANModel):
     enable_ntp = BooleanField(verbose_name=_('Enable NTP'))
     ntp_server = AssoField2(verbose_name=_('NTP Servers'), tgt='system.NTPServer.asso', mul=1, pos='left', optional=True)
+    ntp_key = AssoField2(verbose_name=_('NTP Keys'), tgt='system.NTPKey.asso', mul=1, pos='left', optional=True)
 
     ntp_stats = FieldGroup(writable=False, verbose_name=_('NTP Statistics'), level=STATS,
                         fields={
@@ -45,7 +47,7 @@
         def _get_query_set(self):
             self.cli.set_enable()
             self.cli.set_enable()
-            result = self.cli.cmd('show ntp',
+            result = self.cli.cmd('show ntp status',
                                    RegexParser('Chrony daemon (?P<enable_ntp>is running|is not running)', MATCHONE, reflags=re.S))
             if result:
                 rtn_dict = {
@@ -76,12 +78,13 @@
 
         def _get_ntp_stats(self):
             self.cli.set_enable()
-            result = self.cli.cmd('show ntp')
+            result = self.cli.cmd('show ntp status')
             return result
 
 class NTPServer(ANModel):
     ip = CharField(verbose_name=_('NTP Server IP or Hostname'), primary_key=True)
     options = CharField(verbose_name=_('NTP Server Options'), default='', optional=True)
+    key_id = IntegerField(verbose_name=_('NTP Key ID'), optional=True)
     asso = AssoField2(tgt='system.NTPSettings.ntp_server', mul='*', pos='right', hidden=True, default=[{}])
 
     class Meta:
@@ -90,12 +93,30 @@
     class Manager(CLIManager):
         def _get_query_set(self):
             self.cli.set_enable()
-            result = self.cli.cmd('show ntp\n',
-                        EasyParser('server ', ['?ip', '?options']))
-            return QuerySet(self._model, result)
+            output = self.cli.cmd('show ntp status')
+            result = re.findall(r"^server.*$", output, re.MULTILINE)
+            res = []
+            for each in result:
+                columns = each.split()
+                options = ""
+                key_id = 0
+                if "nts" in each:
+                    options = "nts"
+                elif "iburst" in each:
+                    options = "iburst"
+                if "key" in each:
+                    key_ind = columns.index("key")
+                    key_id = int(columns[key_ind + 1])
+                row = {
+                    "ip": columns[1],
+                    "options": options,
+                    "key_id": key_id
+                }
+                res.append(row)
+            return QuerySet(self._model, res)
 
         def _insert(self, instance):
-            available_options = ['', 'nts']
+            available_options = ['', 'nts', 'iburst']
             data = instance.get_field_dict()
             ip_str = ""
             ip_dict = literal_eval(data["ip"])
@@ -105,17 +126,18 @@
                 ip_str = ip_dict["ipv4"]
             elif "ipv6" in ip_dict:
                 ip_str = ip_dict["ipv6"]
-            options_str = ""
+            options_str = '""'
             if "options" in data and data["options"]:
-                options_list = literal_eval(data["options"])
-                for option in options_list:
-                    if option not in available_options:
-                        return cli_parse("Invalid options", BlankParser(nonblank_exception=CLICmdError, nonblank_msg="Invalid options"))
-                    options_str = str(option)
+                if data["options"] not in available_options:
+                    return cli_parse("Invalid options", BlankParser(nonblank_exception=CLICmdError, nonblank_msg="Invalid options"))
+                options_str = '"' + str(data["options"]) + '"'
             if not ip_str:
                 return cli_parse("Please check fields", BlankParser(nonblank_exception=CLICmdError, nonblank_msg="Please check fields"))
+            key_str = ""
+            if "key_id" in data and data["key_id"]:
+                key_str = data["key_id"]
             self.cli.set_config()
-            result = self.cli.cmd('ntp server "%s" "%s"' % (ip_str, options_str),
+            result = self.cli.cmd('ntp server "%s" %s %s' % (ip_str, options_str, key_str),
                                   BlankParser(nonblank_exception=CLICmdError, supplement=True))
             mark_expire_all(NTPSettings)
             return result
@@ -128,3 +150,37 @@
                                       BlankParser(nonblank_exception=CLICmdError, supplement=True))
             mark_expire_all(NTPSettings)
             return
+
+class NTPKey(ANModel):
+    key_id = IntegerField(verbose_name=_('Key ID'), primary_key=True)
+    auth_key = CharField(verbose_name=_('Authentication Key'), length='1..32')
+    asso = AssoField2(tgt='system.NTPSettings.ntp_key', mul='*', pos='right', hidden=True, default=[{}])
+
+    class Meta:
+        verbose_name = _('NTP Key')
+
+    class Manager(CLIManager):
+        def _get_query_set(self):
+            self.cli.set_enable()
+            output = self.cli.cmd('show ntp keys\n')
+            split_newline = output.splitlines()
+            target_content = "\n".join(split_newline[2:])
+            result = cli_parse(target_content,
+                               RegexParser(r"(?P<key_id>[^\s]+)\s*(?P<auth_key>[^\s]+)\s*", MATCHALL, reflags=re.S))
+            return QuerySet(self._model, result)
+
+        def _insert(self, instance):
+            data = instance.get_field_dict()
+            self.cli.set_config()
+            result = self.cli.cmd('ntp key %s %s' % (data["key_id"], data["auth_key"]),
+                                BlankParser(nonblank_exception=CLICmdError, supplement=True))
+            mark_expire_all(NTPKey)
+            return result
+
+        def _delete(self, pk_list):
+            self.cli.set_config()
+            for each_pk in pk_list:
+                result = self.cli.cmd('no ntp key %s' % each_pk['key_id'],
+                                      BlankParser(nonblank_exception=CLICmdError, supplement=True))
+            mark_expire_all(NTPKey)
+            return
Index: /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/key-add.html
===================================================================
--- /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/key-add.html	(revision 0)
+++ /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/key-add.html	(working copy)
@@ -0,0 +1,29 @@
+<div class="modal-header">
+    <button type="button" class="close" ng-click="ntpKey.modalClose()">&times;</button>
+    <h4 class="modal-title">{{'Add NTP Key'|T}}</h4>
+</div>
+
+<div class="modal-body">
+    <div class="row">
+        <div class="col-lg-12">
+            <form class="form-horizontal" name="general" verify-scope="tipStyle: 1">
+                <div class="form-group">
+                    <label class="col-md-3 control-label">{{'Key ID'|T}}</label>
+                    <div class="col-md-9">
+                        <input ng-verify="union_require:true" type="number" min="1" max="65535" class="form-control" placeholder="" ng-model="ntpKey.data.key_id" name="key_id" >
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-md-3 control-label">{{'Authentication Key'|T}}</label>
+                    <div class="col-md-9">
+                        <input ng-verify="union_require:true" type="text" maxlength="32" class="form-control" placeholder="" ng-model="ntpKey.data.auth_key" name="auth_key" >
+                    </div>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
+<div class="modal-footer">
+    <button type="button" class="btn btn-default" ng-click="ntpKey.modalClose()">{{'Cancel'|T}}</button>
+    <button ng-verify="control:'general'" type="button" class="btn btn-primary" ng-click="ntpKey.add(ntpKey.data)">{{'Save'|T}}</button>
+</div>
Index: /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/ntp-add.html
===================================================================
--- /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/ntp-add.html	(revision 8916)
+++ /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/ntp-add.html	(working copy)
@@ -38,8 +38,17 @@
                 <div class="form-group">
                     <label class="col-md-3 control-label">{{'NTP Server Options'|T}}</label>
                     <div class="col-md-9">
-                        <select bs-select class="form-control selectpicker" placeholder="" ng-model="ntpAdd.data.options" name="options" multiple>
+                        <select bs-select class="form-control selectpicker" placeholder="" ng-model="ntpAdd.data.options" name="options">
                             <option value="nts">NTS</option>
+                            <option value="iburst">iBurst</option>
+                        </select>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-md-3 control-label">{{'Authentication Key'|T}}</label>
+                    <div class="col-md-9">
+                        <select ng-if="ntpAdd.key_list.length > 0" bs-select class="form-control selectpicker" placeholder="" ng-model="ntpAdd.data.key_id" name="key_id">
+                            <option ng-repeat="each in ntpAdd.key_list" value="{{each.key_id}}">{{each.key_id}}</option>
                         </select>
                     </div>
                 </div>
@@ -49,5 +58,5 @@
 </div>
 <div class="modal-footer">
     <button type="button" class="btn btn-default" ng-click="ntpAdd.modalClose()">{{'Cancel'|T}}</button>
-    <button ng-verify="control:'general'" type="button" class="btn btn-primary" ng-click="ntpAdd.add(ntpAdd.data)">{{'Save'|T}}</button>
+    <button ng-verify="control:'general'" type="button" disabled="ntpAdd.loading" class="btn btn-primary" ng-click="ntpAdd.add(ntpAdd.data)">{{'Save'|T}}</button>
 </div>
Index: /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/ntp.controller.js
===================================================================
--- /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/ntp.controller.js	(revision 8916)
+++ /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/ntp.controller.js	(working copy)
@@ -38,6 +38,16 @@
                     avxViewModel.refresh();
                 });
             };
+            avxViewModel.showKeyModal = function() {
+                var modalInstance = $uibModal.open({
+                    templateUrl: 'app/modules/system/submenu/general/ntp/key-add.html',
+                    controller: 'ntpKeyCtrl',
+                    controllerAs: 'ntpKey'
+                });
+                modalInstance.result.then(function(){
+                    avxViewModel.refresh();
+                });
+            };
             var showProgressBar = function() {
                 var modalInstance = $uibModal.open({
                     templateUrl: 'app/modules/common/templates/progress.html',
@@ -86,6 +96,24 @@
                         }
                 });
             };
+            avxViewModel.deleteKey = function(data) {
+                showProgressBar();
+                var post_data={"key_id":data["key_id"]};
+                sysResourceService
+                    .delete_ntp_key(post_data)
+                    .then(function(res) {
+                        $rootScope.$broadcast('endLoading', true);
+                        if (res&&res.status === 200) {
+                            if (!res.data[0]) {
+                                alert(res.data[1]);
+                            } else {
+                                avxViewModel.refresh();
+                            }
+                        } else {
+                            alert("Internal error.");
+                        }
+                });
+            };
             avxViewModel.clean = function() {
                 var delete_reminder = confirm($filter('T')("Are you sure you want to clear all the NTP server?"));
                 if (delete_reminder) {
@@ -103,6 +131,7 @@
             };
             avxViewModel.refresh = function() {
                 $scope.ntp_data.ntp_server = [];
+                $scope.ntp_data.ntp_key = [];
                 get_info();
             };
             avxViewModel.optionsConvert = function(options) {
@@ -145,6 +174,7 @@
                 modalViewModel.chooseIpv6 = false;
                 modalViewModel.chooseHostname = true;
             };
+            modalViewModel.key_id = "";
             var showProgressBar = function() {
                 var modalInstance = $uibModal.open({
                     templateUrl: 'app/modules/common/templates/progress.html',
@@ -153,9 +183,22 @@
                     backdrop: false
                 });
             };
+            modalViewModel.loading = true;
+            modalViewModel.key_list = [];
+            modalViewModel.get_key_list = function() {
+                sysResourceService
+                    .get_ntp_key()
+                    .then(function(res) {
+                        modalViewModel.loading = false;
+                        if (res && res.status === 200) {
+                            modalViewModel.key_list = res.data.ntp_key;
+                        }
+                });
+            };
+            modalViewModel.get_key_list();
             modalViewModel.add = function(data) {
                 showProgressBar();
-                var post_data={"options":data["options"]};
+                var post_data={"options":data["options"], "key_id":parseInt(data["key_id"])};
                 if (modalViewModel.chooseIpv4) {
                     post_data['ip'] = {'ipv4':data['ipv4']};
                 } else if (modalViewModel.chooseIpv6) {
@@ -179,4 +222,59 @@
                 });
             };
         }
+    ])
+    .controller('ntpKeyCtrl', [
+        '$scope',
+        '$rootScope',
+        '$state',
+        '$uibModalInstance',
+        '$uibModal',
+        'sysResourceService',
+        function($scope, $rootScope, $state, $uibModalInstance, $uibModal, sysResourceService) {
+            var ntpKeyModel = this;
+            ntpKeyModel.data={};
+            ntpKeyModel.modalClose = function() {
+                $uibModalInstance.dismiss();
+            };
+            ntpKeyModel.key_id = 0;
+            ntpKeyModel.auth_key = "";
+            var showProgressBar = function() {
+                var modalInstance = $uibModal.open({
+                    templateUrl: 'app/modules/common/templates/progress.html',
+                    controller: 'showProgressCtrl',
+                    controllerAs: 'progress',
+                    backdrop: false
+                });
+            };
+            ntpKeyModel.add = function(data) {
+                if (isNaN(data["key_id"])
+                    || parseInt(data["key_id"]) > 65535
+                    || parseInt(data["key_id"]) < 1) {
+                    alert("Key ID should be in the range 1 to 65535");
+                    return;
+                }
+                showProgressBar();
+                var post_data={"key_id":parseInt(data["key_id"]), "auth_key":data["auth_key"]};
+                sysResourceService
+                .add_ntp_key(post_data)
+                .then(function(res) {
+                    $rootScope.$broadcast('endLoading', true);
+                    if (res&&res.status === 200) {
+                        if (!res.data[0]) {
+                            alert(res.data[1]);
+                        } else {
+                            $uibModalInstance.close();
+                        }
+                    } else {
+                        alert("Internal error.");
+                    }
+                });
+            };
+            $scope.$watch('ntpKey.data.auth_key', function (now, old) {
+                var re = /^\w+$/;
+                if (!re.test(now)) {
+                    ntpKeyModel.data.auth_key = old;
+                }
+            });
+        }
     ]);
\ No newline at end of file
Index: /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/ntp.html
===================================================================
--- /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/ntp.html	(revision 8916)
+++ /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/general/ntp/ntp.html	(working copy)
@@ -49,6 +49,7 @@
                             <th>#</th>
                             <th st-sort="ip">{{'NTP Server IP'|T}}</th>
                             <th st-sort="options">{{'NTP Server Options'|T}}</th>
+                            <th st-sort="key_id">{{'Authentication Key'|T}}</th>
                             <th>{{'Action'|T}}</th>
                         </tr>
                         </thead>
@@ -57,6 +58,7 @@
                             <td>{{$index + 1}}</td>
                             <td>{{row.ip}}</td>
                             <td>{{generalNTP.optionsConvert(row.options)}}</td>
+                            <td>{{row.key_id ? row.key_id : ""}}</td>
                             <td>
                                 <div class="btn-group">
                                     <button  ng-show="allow_config" title="{{'Delete'|T}}" class="btn btn-link" ng-click="generalNTP.delete(row)"><i class="fa fa-times-circle"></i></button>
@@ -70,6 +72,52 @@
                 <div class="table-pagination">
                     <div class="pagination-detail"></div>
                     <div class="pagination" st-pagination="" st-items-by-page="5"></div>
+                </div>
+            </div>
+        </rd-widget>
+    </div>
+    <div class="row">
+        <rd-widget>
+            <rd-widget-header title="{{'NTP Key'|T}}">
+            </rd-widget-header>
+            <div class="table-toolbar">
+                <div class="">
+                    <div class="btn-group">
+                        <button title="{{'Refresh'|T}}" class="btn btn-link hive_enable_active" ng-click="generalNTP.refresh()"><i class="fa fa-refresh"></i></button>
+                        <button title="{{'Add'|T}}" class="btn btn-link" ng-click="generalNTP.showKeyModal()"><i class="fa fa-plus-circle"></i></button>
+                    </div>
+                </div>
+                <div class="btn-group pull-right"></div>
+            </div>
+            <div class="table-container" st-table="displayedCollection" st-safe-src="ntp_data.ntp_key">
+                <div class="table-responsive table-content">
+                    <table class="table table-striped table-hover">
+                        <thead>
+                        <tr>
+                            <th>#</th>
+                            <th st-sort="key_id">{{'Key ID'|T}}</th>
+                            <th st-sort="auth_key">{{'Authentication Key'|T}}</th>
+                            <th>{{'Action'|T}}</th>
+                        </tr>
+                        </thead>
+                        <tbody>
+                        <tr ng-repeat="row in displayedCollection">
+                            <td>{{$index + 1}}</td>
+                            <td>{{row.key_id}}</td>
+                            <td>{{row.auth_key}}</td>
+                            <td>
+                                <div class="btn-group">
+                                    <button  ng-show="allow_config" title="{{'Delete'|T}}" class="btn btn-link" ng-click="generalNTP.deleteKey(row)"><i class="fa fa-times-circle"></i></button>
+                                </div>
+                            </td>
+                        </tr>
+                        </tbody>
+                    </table>
+                </div>
+                <div style="margin-bottom: 15px;text-align: center" ng-hide="ntp_data.ntp_key!==undefined"><img src="app/images/loading.gif"></div>
+                <div class="table-pagination">
+                    <div class="pagination-detail"></div>
+                    <div class="pagination" st-pagination="" st-items-by-page="5"></div>
                 </div>
             </div>
         </rd-widget>
Index: /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/system.service.js
===================================================================
--- /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/system.service.js	(revision 8916)
+++ /branches/rel_avx_2_7_3/src/webui/webui/htdocs/new/src/client/app/modules/system/system.service.js	(working copy)
@@ -113,6 +113,9 @@
                 clear_aaa_data: clear_aaa_data,
                 delete_aaa_data: delete_aaa_data,
                 clean_all_ntp: clean_all_ntp,
+                add_ntp_key: add_ntp_key,
+                delete_ntp_key: delete_ntp_key,
+                get_ntp_key: get_ntp_key,
             };
             function get_udisk_files() {
                 return apiService.get('/api/avx/system/config_mgmt/UdiskFileConfig/_get_list_data');
@@ -145,7 +148,7 @@
                 return apiService.post(url, post_data);
             }
             function get_ntp() {
-                return apiService.get('/api/avx/system/NTPSettings/_fields?fields=[%22enable_ntp%22,%20%22ntp_server%22,%20%22ntp_stats%22]');
+                return apiService.get('/api/avx/system/NTPSettings/_fields?fields=[%22enable_ntp%22,%20%22ntp_server%22,%20%22ntp_stats%22,%20%22ntp_key%22]');
             }
             function update_ntp(onoff) {
                 var url = '/api/avx/system/NTPSettings/_update';
@@ -154,7 +157,7 @@
             }
             function add_ntp_server(data) {
                 var url = '/api/avx/system/NTPServer/_add';
-                var post_data = {"post_data": JSON.stringify({"ip":data["ip"], "options":data["options"]})};
+                var post_data = {"post_data": JSON.stringify({"ip":data["ip"], "options":data["options"], "key_id":data["key_id"]})};
                 return apiService.post(url, post_data);
             }
             function delete_ntp_server(data) {
@@ -734,5 +737,18 @@
                 };
                 return apiService.post(url, post_data);
             }
+            function add_ntp_key(data) {
+                var url = '/api/avx/system/NTPKey/_add';
+                var post_data = {"post_data": JSON.stringify({"key_id":data["key_id"], "auth_key":data["auth_key"]})};
+                return apiService.post(url, post_data);
+            }
+            function delete_ntp_key(data) {
+                var url = '/api/avx/system/NTPKey/_delete';
+                var post_data = {"pk": JSON.stringify({"key_id":data["key_id"]})};
+                return apiService.post(url, post_data);
+            }
+            function get_ntp_key() {
+                return apiService.get('/api/avx/system/NTPSettings/_fields?fields=[%22ntp_key%22]');
+            }
         }
 ]);
\ No newline at end of file
