浏览代码

HUE-2214 [fb] Display and set replication

Added displaying of a replication factor in file/folder summary
Implemented setting of a replication factor for files
Fixed review remarks
Adrian Yavorskyy 8 年之前
父节点
当前提交
a539ad0

+ 5 - 0
apps/filebrowser/src/filebrowser/forms.py

@@ -106,6 +106,11 @@ class BaseCopyFormSet(FormSet):
 
 
 CopyFormSet = formset_factory(CopyForm, formset=BaseCopyFormSet, extra=0)
 CopyFormSet = formset_factory(CopyForm, formset=BaseCopyFormSet, extra=0)
 
 
+class SetReplicationFactorForm(forms.Form):
+  op = "setreplication"
+  src_path = CharField(label=_("File to set replication factor"), help_text=_("The file to set replication factor."))
+  replication_factor = CharField(label=_("Value of replication factor"), help_text=_("The value of replication factor."))
+
 class UploadFileForm(forms.Form):
 class UploadFileForm(forms.Form):
   op = "upload"
   op = "upload"
   # The "hdfs" prefix in "hdfs_file" triggers the HDFSfileUploadHandler
   # The "hdfs" prefix in "hdfs_file" triggers the HDFSfileUploadHandler

+ 2 - 0
apps/filebrowser/src/filebrowser/templates/listdir.mako

@@ -68,6 +68,8 @@ ${ fb_components.menubar() }
               isCurrentDirSelected().length == 0"><i class="fa fa-fw fa-random"></i> ${_('Move')}</a></li>
               isCurrentDirSelected().length == 0"><i class="fa fa-fw fa-random"></i> ${_('Move')}</a></li>
               <li><a href="javascript: void(0)" title="${_('Copy')}" data-bind="click: copy, enable: selectedFiles().length > 0 &&
               <li><a href="javascript: void(0)" title="${_('Copy')}" data-bind="click: copy, enable: selectedFiles().length > 0 &&
               isCurrentDirSelected().length == 0"><i class="fa fa-fw fa-files-o"></i> ${_('Copy')}</a></li>
               isCurrentDirSelected().length == 0"><i class="fa fa-fw fa-files-o"></i> ${_('Copy')}</a></li>
+              <li><a href="javascript: void(0)" title="${_('Set Replication Factor')}" data-bind="visible: !inTrash() && !isS3() && selectedFiles().length == 1 && selectedFile().type == 'file', click: setReplicationFactor"
+              ><i class="fa fa-fw fa-hdd-o"></i>${_('Set replication factor')}</a></li>
               % if show_download_button:
               % if show_download_button:
               <li>
               <li>
                 <a href="javascript: void(0)" title="${_('Download')}" data-bind="visible: !inTrash() && selectedFiles().length == 1 && selectedFile().type == 'file', click: downloadFile">
                 <a href="javascript: void(0)" title="${_('Download')}" data-bind="visible: !inTrash() && selectedFiles().length == 1 && selectedFile().type == 'file', click: downloadFile">

+ 77 - 1
apps/filebrowser/src/filebrowser/templates/listdir_components.mako

@@ -237,6 +237,28 @@ from filebrowser.conf import ENABLE_EXTRACT_UPLOADED_ARCHIVE
     </div>
     </div>
   </form>
   </form>
 
 
+  <!-- set replication factor modal -->
+  <form id="setReplicationFactorForm" action="/filebrowser/set_replication_factor?next=${current_request_path | n,unicode }"  method="POST" enctype="multipart/form-data" class="form-inline form-padding-fix">
+    ${ csrf_token(request) | n,unicode }
+    <div id="setReplicationModal" class="modal hide fade">
+      <div class="modal-header">
+        <a href="#" class="close" data-dismiss="modal">&times;</a>
+        <h3>${_('Setting replication factor for :')} <span id="setReplFileName">file name</span></h3>
+      </div>
+      <div class="modal-body">
+        <label>${_('Replication factor')} <input id="newRepFactorInput" name="replication_factor" value="" type="number" class="input-xlarge"/></label>
+      </div>
+      <div class="modal-footer">
+        <div id="replicationFactorRequiredAlert" class="hide" style="position: absolute; left: 10px;">
+          <span class="label label-important">${_('Replication factor is required.')}</span>
+        </div>
+        <input id="SrcPath" type="hidden" name="src_path" type="text">
+        <a class="btn" data-dismiss="modal">${_('Cancel')}</a>
+        <input type="submit" value="${_('Submit')}" class="btn btn-primary" />
+      </div>
+    </div>
+  </form>
+
   <!-- chown modal -->
   <!-- chown modal -->
   % if is_fs_superuser:
   % if is_fs_superuser:
   <form id="chownForm" action="/filebrowser/chown" method="POST" enctype="multipart/form-data" class="form-stacked form-padding-fix">
   <form id="chownForm" action="/filebrowser/chown" method="POST" enctype="multipart/form-data" class="form-stacked form-padding-fix">
@@ -502,6 +524,10 @@ from filebrowser.conf import ENABLE_EXTRACT_UPLOADED_ARCHIVE
           <th>${ _('Disk space quota') }</th>
           <th>${ _('Disk space quota') }</th>
           <td data-bind="text: formatBytes(contentSummary().spaceQuota(), 4)"></td>
           <td data-bind="text: formatBytes(contentSummary().spaceQuota(), 4)"></td>
         </tr>
         </tr>
+        <tr>
+          <th>${ _('Replication factor') }</th>
+          <td data-bind="text: contentSummary().replication()"></td>
+        </tr>
         <tr>
         <tr>
           <th>${ _('Number of directories') }</th>
           <th>${ _('Number of directories') }</th>
           <td data-bind="text: contentSummary().directoryCount()"></td>
           <td data-bind="text: contentSummary().directoryCount()"></td>
@@ -1108,7 +1134,8 @@ from filebrowser.conf import ENABLE_EXTRACT_UPLOADED_ARCHIVE
         spaceQuota: -1,
         spaceQuota: -1,
         length: 0,
         length: 0,
         directoryCount: 0,
         directoryCount: 0,
-        fileCount: 0
+        fileCount: 0,
+        replication: 0
       }));
       }));
       self.showSummary = function () {
       self.showSummary = function () {
         self.isLoadingSummary(true);
         self.isLoadingSummary(true);
@@ -1349,6 +1376,27 @@ from filebrowser.conf import ENABLE_EXTRACT_UPLOADED_ARCHIVE
         });
         });
       };
       };
 
 
+      self.setReplicationFactor = function () {
+        $("#SrcPath").attr("value", self.selectedFile().path);
+
+        $("#setReplFileName").text(self.selectedFile().path);
+
+        $("#setReplicationFactorForm").attr("action", "/filebrowser/set_replication_factor?next=${url('filebrowser.views.view', path='')}" + self.currentPath());
+
+        $('#setReplicationFactorForm').ajaxForm({
+          dataType: 'json',
+          success: function() {
+            $("#setReplicationModal").modal('hide');
+            self.retrieveData(true);
+          }
+        });
+
+        $("#setReplicationModal").modal({
+          keyboard:true,
+          show:true
+        });
+      };
+
       self.move = function (mode, unselectedDrag) {
       self.move = function (mode, unselectedDrag) {
         var paths = [];
         var paths = [];
 
 
@@ -1996,6 +2044,20 @@ from filebrowser.conf import ENABLE_EXTRACT_UPLOADED_ARCHIVE
         hideContextMenu();
         hideContextMenu();
       });
       });
 
 
+      // Allow only numeric symbols for setting replication factor
+      $("#newRepFactorInput").keydown(function (e) {
+        if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110, 190]) !== -1 ||
+          (e.keyCode == 65 && (e.ctrlKey === true || e.metaKey === true)) ||
+          (e.keyCode == 67 && (e.ctrlKey === true || e.metaKey === true)) ||
+          (e.keyCode == 88 && (e.ctrlKey === true || e.metaKey === true)) ||
+          (e.keyCode >= 35 && e.keyCode <= 39)) {
+            return;
+        }
+        if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
+          e.preventDefault();
+        }
+      });
+
       // Drag and drop uploads from anywhere on filebrowser screen
       // Drag and drop uploads from anywhere on filebrowser screen
       if (window.FileReader) {
       if (window.FileReader) {
         var showHoverMsg = function (msg) {
         var showHoverMsg = function (msg) {
@@ -2250,6 +2312,20 @@ from filebrowser.conf import ENABLE_EXTRACT_UPLOADED_ARCHIVE
         }
         }
        });
        });
 
 
+      $("#setReplicationFactorForm").submit(function () {
+        if ($("#newRepFactorInput").val() == "") {
+          $("#replicationFactorRequiredAlert").show();
+          $("#newRepFactorInput").addClass("fieldError");
+          resetPrimaryButtonsStatus(); //globally available
+          return false;
+        }
+      });
+
+      $("#newRepFactorInput").focus(function () {
+        $("#replicationFactorRequiredAlert").hide();
+        $("#newRepFactorInput").removeClass("fieldError");
+      });
+
       huePubSub.subscribe('update.autocompleters', function(){
       huePubSub.subscribe('update.autocompleters', function(){
         $("#moveDestination").jHueHdfsAutocomplete({
         $("#moveDestination").jHueHdfsAutocomplete({
           showOnFocus: true,
           showOnFocus: true,

+ 1 - 0
apps/filebrowser/src/filebrowser/urls.py

@@ -47,6 +47,7 @@ urlpatterns = patterns('filebrowser.views',
   url(r'^touch$', 'touch', name='touch'),
   url(r'^touch$', 'touch', name='touch'),
   url(r'^move$', 'move', name='move'),
   url(r'^move$', 'move', name='move'),
   url(r'^copy$', 'copy', name='copy'),
   url(r'^copy$', 'copy', name='copy'),
+  url(r'^set_replication_factor$', 'set_replication_factor', name='set_replication_factor'),
   url(r'^rmtree$', 'rmtree', name='rmtree'),
   url(r'^rmtree$', 'rmtree', name='rmtree'),
   url(r'^chmod$', 'chmod', name='chmod'),
   url(r'^chmod$', 'chmod', name='chmod'),
   url(r'^chown$', 'chown', name='chown'),
   url(r'^chown$', 'chown', name='chown'),

+ 11 - 2
apps/filebrowser/src/filebrowser/views.py

@@ -69,7 +69,7 @@ from filebrowser.lib.rwx import filetype, rwx
 from filebrowser.lib import xxd
 from filebrowser.lib import xxd
 from filebrowser.forms import RenameForm, UploadFileForm, UploadArchiveForm, MkDirForm, EditorForm, TouchForm,\
 from filebrowser.forms import RenameForm, UploadFileForm, UploadArchiveForm, MkDirForm, EditorForm, TouchForm,\
                               RenameFormSet, RmTreeFormSet, ChmodFormSet, ChownFormSet, CopyFormSet, RestoreFormSet,\
                               RenameFormSet, RmTreeFormSet, ChmodFormSet, ChownFormSet, CopyFormSet, RestoreFormSet,\
-                              TrashPurgeForm
+                              TrashPurgeForm, SetReplicationFactorForm
 
 
 
 
 DEFAULT_CHUNK_SIZE_BYTES = 1024 * 4 # 4KB
 DEFAULT_CHUNK_SIZE_BYTES = 1024 * 4 # 4KB
@@ -528,10 +528,11 @@ def stat(request, path):
 def content_summary(request, path):
 def content_summary(request, path):
     if not request.fs.exists(path):
     if not request.fs.exists(path):
         raise Http404(_("File not found: %(path)s") % {'path': escape(path)})
         raise Http404(_("File not found: %(path)s") % {'path': escape(path)})
-
     response = {'status': -1, 'message': '', 'summary': None}
     response = {'status': -1, 'message': '', 'summary': None}
     try:
     try:
         stats = request.fs.get_content_summary(path)
         stats = request.fs.get_content_summary(path)
+        replication_factor = request.fs.stats(path)['replication']
+        stats.summary.update({'replication': replication_factor})
         response['status'] = 0
         response['status'] = 0
         response['summary'] = stats.summary
         response['summary'] = stats.summary
     except WebHdfsException, e:
     except WebHdfsException, e:
@@ -1054,6 +1055,14 @@ def rename(request):
 
 
     return generic_op(RenameForm, request, smart_rename, ["src_path", "dest_path"], None)
     return generic_op(RenameForm, request, smart_rename, ["src_path", "dest_path"], None)
 
 
+def set_replication_factor(request):
+    def smart_set_replication_factor(src_path, replication_factor):
+        result = request.fs.set_replication_factor(src_path, replication_factor)
+        if not result:
+            raise PopupException(_("Setting of replication factor failed"))
+
+    return generic_op(SetReplicationFactorForm, request, smart_set_replication_factor, ["src_path", "replication_factor"], None)
+
 
 
 def mkdir(request):
 def mkdir(request):
     def smart_mkdir(path, name):
     def smart_mkdir(path, name):

+ 9 - 0
desktop/libs/hadoop/src/hadoop/fs/webhdfs.py

@@ -36,6 +36,7 @@ from hadoop.fs.webhdfs_types import WebHdfsStat, WebHdfsContentSummary
 from hadoop.conf import UPLOAD_CHUNK_SIZE
 from hadoop.conf import UPLOAD_CHUNK_SIZE
 from hadoop.hdfs_site import get_nn_sentry_prefixes, get_umask_mode, get_supergroup
 from hadoop.hdfs_site import get_nn_sentry_prefixes, get_umask_mode, get_supergroup
 
 
+
 import hadoop.conf
 import hadoop.conf
 import desktop.conf
 import desktop.conf
 
 
@@ -416,6 +417,14 @@ class WebHdfs(Hdfs):
     for dirent in ls:
     for dirent in ls:
       self.rename(Hdfs.join(old_dir, dirent), Hdfs.join(new_dir, dirent))
       self.rename(Hdfs.join(old_dir, dirent), Hdfs.join(new_dir, dirent))
 
 
+  def set_replication_factor(self, filename, repl_factor):
+    """set replication factor(filename, repl_factor)"""
+    params = self._getparams()
+    params['op'] = 'SETREPLICATION'
+    params['replication'] = repl_factor
+    result = self._root.put(filename, params)
+    return result['boolean']
+
   def chown(self, path, user=None, group=None, recursive=False):
   def chown(self, path, user=None, group=None, recursive=False):
     """chown(path, user=None, group=None, recursive=False)"""
     """chown(path, user=None, group=None, recursive=False)"""
     path = Hdfs.normpath(path)
     path = Hdfs.normpath(path)