Bläddra i källkod

HUE-1701 [oozie] Import coordinator button

Import coordinator exactly the same way import workflow works.
Need to choose the workflow that will be associated with this
coordinator because coordinator.xml files point to workflow deployment
directories only.
Abraham Elmahrek 12 år sedan
förälder
incheckning
f12f1ad
25 ändrade filer med 243 tillägg och 21 borttagningar
  1. 16 0
      apps/oozie/src/oozie/forms.py
  2. 67 0
      apps/oozie/src/oozie/templates/editor/import_coordinator.mako
  3. 1 0
      apps/oozie/src/oozie/templates/editor/list_coordinators.mako
  4. 51 0
      apps/oozie/src/oozie/test_data/coordinators/0.2/test-basic.xml
  5. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-basic-global-config.xml
  6. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-basic-namespace-missing.xml
  7. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-basic.xml
  8. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-decision-complex.xml
  9. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-decision.xml
  10. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-distcp.0.1.xml
  11. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-email.0.1.xml
  12. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-forks.xml
  13. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-fs.xml
  14. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-generic.xml
  15. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-java-different-error-links.xml
  16. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-java-multiple-kill.xml
  17. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-java.xml
  18. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-mapreduce.xml
  19. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-pig.xml
  20. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-shell.xml
  21. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-sqoop.0.2.xml
  22. 0 0
      apps/oozie/src/oozie/test_data/workflows/0.4/test-subworkflow.xml
  23. 57 19
      apps/oozie/src/oozie/tests.py
  24. 1 0
      apps/oozie/src/oozie/urls.py
  25. 50 2
      apps/oozie/src/oozie/views/editor.py

+ 16 - 0
apps/oozie/src/oozie/forms.py

@@ -360,6 +360,22 @@ class CoordinatorForm(forms.ModelForm):
     self.fields['workflow'].queryset = qs
 
 
+class ImportCoordinatorForm(CoordinatorForm):
+  definition_file = forms.FileField(label=_t("Local coordinator.xml file"))
+  resource_archive = forms.FileField(label=_t("Coordinator resource archive (zip)"), required=False)
+  start = forms.SplitDateTimeField(input_time_formats=[TIME_FORMAT],
+                                   widget=SplitDateTimeWidget(attrs={'class': 'input-small', 'id': 'coordinator_start'},
+                                                              date_format=DATE_FORMAT, time_format=TIME_FORMAT),
+                                   required=False)
+  end = forms.SplitDateTimeField(input_time_formats=[TIME_FORMAT],
+                                 widget=SplitDateTimeWidget(attrs={'class': 'input-small', 'id': 'coordinator_end'},
+                                                            date_format=DATE_FORMAT, time_format=TIME_FORMAT),
+                                 required=False)
+
+  class Meta(CoordinatorForm.Meta):
+    exclude = ('owner', 'deployment_dir', 'timezone', 'frequency_number', 'frequency_unit', 'schema_version', 'job_properties', 'parameters')
+
+
 class DatasetForm(forms.ModelForm):
   start = forms.SplitDateTimeField(input_time_formats=[TIME_FORMAT],
                                    widget=SplitDateTimeWidget(attrs={'class': 'short'},

+ 67 - 0
apps/oozie/src/oozie/templates/editor/import_coordinator.mako

@@ -0,0 +1,67 @@
+## Licensed to Cloudera, Inc. under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  Cloudera, Inc. licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License.  You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+
+<%!
+  from desktop.views import commonheader, commonfooter
+  from django.utils.translation import ugettext as _
+%>
+
+<%namespace name="layout" file="../navigation-bar.mako" />
+<%namespace name="utils" file="../utils.inc.mako" />
+
+${ commonheader(_("Import Coordinator"), "oozie", user) | n,unicode }
+${ layout.menubar(section='coordinators') }
+
+
+<div class="container-fluid">
+  <div class="card card-small">
+  <h1 class="card-heading simple">${ _('Import Coordinator') }</h1>
+  <div class="card-body">
+    <p>
+
+      <p>${_("You can import an external Oozie coordinator by providing the coordinator definition file.")}</p>
+      <p>
+        ${ _('Supported coordinator versions are 0.2. Other versions might work depending on their complexity.') }
+      </p>
+
+    <div style="min-height:300px">
+      <form class="form-horizontal" id="coordinatorForm" action="${ url('oozie:import_coordinator') }" method="POST" enctype="multipart/form-data">
+        <div class="row-fluid">
+          <div class="span12">
+            <fieldset>
+            ${ utils.render_field(coordinator_form['name']) }
+            ${ utils.render_field(coordinator_form['description']) }
+            ${ utils.render_field(coordinator_form['definition_file']) }
+            ${ utils.render_field(coordinator_form['resource_archive']) }
+            ${ utils.render_field(coordinator_form['workflow']) }
+            ${ utils.render_field(coordinator_form['is_shared']) }
+           </fieldset>
+          </div>
+        </div>
+
+        <div class="form-actions" style="padding-left: 20px !important;">        
+          <a class="btn" onclick="history.back()">${ _('Back') }</a>
+          <input class="btn btn-primary" type="submit" value="${ _('Import') }" />
+        </div>
+      </form>
+    </div>
+
+    </p>
+  </div>
+</div>
+</div>
+
+${ commonfooter(messages) | n,unicode }

+ 1 - 0
apps/oozie/src/oozie/templates/editor/list_coordinators.mako

@@ -59,6 +59,7 @@ ${ layout.menubar(section='coordinators') }
 
     <%def name="creation()">
       <a href="${ url('oozie:create_coordinator') }" class="btn"><i class="fa fa-plus-circle"></i> ${ _('Create') }</a>
+      <a href="${ url('oozie:import_coordinator') }" class="btn"><i class="fa fa-download"></i> ${ _('Import') }</a>
       &nbsp;&nbsp;
       <a href="${ url('oozie:list_trashed_coordinators') }" class="btn"><i class="fa fa-trash-o"></i> ${ _('View trash') }</a>
     </%def>

+ 51 - 0
apps/oozie/src/oozie/test_data/coordinators/0.2/test-basic.xml

@@ -0,0 +1,51 @@
+<coordinator-app name="DailyAnalytics"
+  frequency="${coord:days(1)}"
+  start="2013-06-03T00:00Z" end="2013-06-05T00:00Z" timezone="America/Los_Angeles"
+  xmlns="uri:oozie:coordinator:0.2">
+  <datasets>
+    <dataset name="daily_shakespeare" frequency="${coord:days(1)}"
+             initial-instance="2012-05-31T00:00Z" timezone="America/Los_Angeles">
+      <uri-template>${nameNode}/user/hue/oozie/workspaces/data/${YEAR}${MONTH}${DAY}</uri-template>
+      <done-flag></done-flag>
+    </dataset>
+    <dataset name="daily_aggregated_shakespeare" frequency="${coord:days(1)}"
+             initial-instance="2012-05-31T00:00Z" timezone="America/Los_Angeles">
+      <uri-template>${nameNode}/tmp/test-coord-${coord:user()}/${YEAR}${MONTH}${DAY}</uri-template>
+      <done-flag></done-flag>
+    </dataset>
+  </datasets>
+  <input-events>
+    <data-in name="input" dataset="daily_shakespeare">
+    <start-instance>
+        ${coord:current(-1)}
+    </start-instance>
+    <end-instance>
+        ${coord:current(0)}
+    </end-instance>
+    </data-in>
+  </input-events>
+  <output-events>
+    <data-out name="output" dataset="daily_aggregated_shakespeare">
+    <instance>${coord:current(0)}</instance>
+    </data-out>
+  </output-events>
+  <action>
+    <workflow>
+      <app-path>${wf_application_path}</app-path>
+      <configuration>
+          <property>
+            <name>input</name>
+            <value>${coord:dataIn('input')}</value>
+          </property>
+        <property>
+          <name>output</name>
+          <value>${coord:dataOut('output')}</value>
+        </property>
+        <property>
+          <name>oozie.use.system.libpath</name>
+          <value>true</value>
+        </property>
+      </configuration>
+   </workflow>
+  </action>
+</coordinator-app>

+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-basic-global-config.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-basic-global-config.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-basic-namespace-missing.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-basic-namespace-missing.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-basic.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-basic.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-decision-complex.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-decision-complex.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-decision.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-decision.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-distcp.0.1.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-distcp.0.1.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-email.0.1.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-email.0.1.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-forks.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-forks.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-fs.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-fs.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-generic.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-generic.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-java-different-error-links.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-java-different-error-links.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-java-multiple-kill.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-java-multiple-kill.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-java.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-java.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-mapreduce.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-mapreduce.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-pig.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-pig.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-shell.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-shell.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-sqoop.0.2.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-sqoop.0.2.xml


+ 0 - 0
apps/oozie/src/oozie/test_data/0.4/test-subworkflow.xml → apps/oozie/src/oozie/test_data/workflows/0.4/test-subworkflow.xml


+ 57 - 19
apps/oozie/src/oozie/tests.py

@@ -24,6 +24,7 @@ import StringIO
 import shutil
 import tempfile
 import zipfile
+from datetime import datetime
 
 from itertools import chain
 
@@ -1833,7 +1834,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-basic-namespace-missing.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-basic-namespace-missing.xml')
     contents = f.read()
     f.close()
 
@@ -1847,7 +1848,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-basic.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-basic.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -1864,7 +1865,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-basic-global-config.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-basic-global-config.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -1881,7 +1882,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-decision.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-decision.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -1897,7 +1898,7 @@ class TestImportWorkflow04(OozieMockBase):
   def test_import_workflow_decision_complex(self):
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-decision-complex.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-decision-complex.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -1916,7 +1917,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-distcp.0.1.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-distcp.0.1.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -1929,7 +1930,7 @@ class TestImportWorkflow04(OozieMockBase):
   def test_import_workflow_forks(self):
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-forks.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-forks.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -1947,7 +1948,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-mapreduce.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-mapreduce.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -1963,7 +1964,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-pig.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-pig.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -1981,7 +1982,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-sqoop.0.2.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-sqoop.0.2.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -2000,7 +2001,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-java.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-java.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -2020,7 +2021,7 @@ class TestImportWorkflow04(OozieMockBase):
   def test_import_workflow_shell(self):
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-shell.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-shell.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -2044,7 +2045,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-fs.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-fs.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -2065,7 +2066,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-email.0.1.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-email.0.1.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -2085,7 +2086,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-generic.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-generic.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -2104,7 +2105,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-java-multiple-kill.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-java-multiple-kill.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -2129,7 +2130,7 @@ class TestImportWorkflow04(OozieMockBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-java-different-error-links.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-java-different-error-links.xml')
     import_workflow(workflow, f.read())
     f.close()
     workflow.save()
@@ -2148,6 +2149,43 @@ class TestImportWorkflow04(OozieMockBase):
     workflow.delete(skip_trash=True)
 
 
+class TestImportCoordinator02(OozieMockBase):
+
+  def setUp(self):
+    super(TestImportCoordinator02, self).setUp()
+    self.setup_simple_workflow()
+
+  def test_import_coordinator_simple(self):
+    coordinator_count = Document.objects.available_docs(Coordinator, self.user).count()
+
+    # Create
+    filename = os.path.abspath(os.path.dirname(__file__) + "/test_data/coordinators/0.2/test-basic.xml")
+    fh = open(filename)
+    response = self.c.post(reverse('oozie:import_coordinator'), {
+      'name': ['test_coordinator'],
+      'workflow': Workflow.objects.get(name='wf-name-1').pk,
+      'definition_file': [fh],
+      'description': ['test description']
+    }, follow=True)
+    fh.close()
+
+    assert_equal(coordinator_count + 1, Document.objects.available_docs(Coordinator, self.user).count(), response)
+    coordinator = Coordinator.objects.get(name='test_coordinator')
+    assert_equal('[{"name":"oozie.use.system.libpath","value":"true"}]', coordinator.parameters)
+    assert_equal('uri:oozie:coordinator:0.2', coordinator.schema_version)
+    assert_equal('test description', coordinator.description)
+    assert_equal(datetime.strptime('2013-06-03T00:00Z', '%Y-%m-%dT%H:%MZ'), coordinator.start)
+    assert_equal(datetime.strptime('2013-06-05T00:00Z', '%Y-%m-%dT%H:%MZ'), coordinator.end)
+    assert_equal('America/Los_Angeles', coordinator.timezone)
+    assert_equal('days', coordinator.frequency_unit)
+    assert_equal(1, coordinator.frequency_number)
+    assert_equal(None, coordinator.timeout)
+    assert_equal(None, coordinator.concurrency)
+    assert_equal(None, coordinator.execution)
+    assert_equal(None, coordinator.throttle)
+    assert_not_equal(None, coordinator.deployment_dir)
+
+
 class TestPermissions(OozieBase):
 
   def setUp(self):
@@ -2614,7 +2652,7 @@ class TestEditorWithOozie(OozieBase):
     workflow_count = Document.objects.available_docs(Workflow, self.user).count()
 
     # Create
-    filename = os.path.abspath(os.path.dirname(__file__) + "/test_data/0.4/test-mapreduce.xml")
+    filename = os.path.abspath(os.path.dirname(__file__) + "/test_data/workflows/0.4/test-mapreduce.xml")
     fh = open(filename)
     response = self.c.post(reverse('oozie:import_workflow'), {
       'job_xml': [''],
@@ -2664,7 +2702,7 @@ class TestImportWorkflow04WithOozie(OozieBase):
     """
     workflow = Workflow.objects.new_workflow(self.user)
     workflow.save()
-    f = open('apps/oozie/src/oozie/test_data/0.4/test-subworkflow.xml')
+    f = open('apps/oozie/src/oozie/test_data/workflows/0.4/test-subworkflow.xml')
     import_workflow(workflow, f.read(), None, self.cluster.fs)
     f.close()
     workflow.save()

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

@@ -34,6 +34,7 @@ urlpatterns = patterns(
   url(r'^submit_workflow/(?P<workflow>\d+)$', 'submit_workflow', name='submit_workflow'),
   url(r'^schedule_workflow/(?P<workflow>\d+)$', 'schedule_workflow', name='schedule_workflow'),
   url(r'^import_workflow/$', 'import_workflow', name='import_workflow'),
+  url(r'^import_coordinator/$', 'import_coordinator', name='import_coordinator'),
   url(r'^export_workflow/(?P<workflow>\d+)$', 'export_workflow', name='export_workflow'),
 
   url(r'^list_coordinators/(?P<workflow_id>[-\w]+)?$', 'list_coordinators', name='list_coordinators'),

+ 50 - 2
apps/oozie/src/oozie/views/editor.py

@@ -41,14 +41,16 @@ from filebrowser.lib.archives import archive_factory
 from oozie.decorators import check_job_access_permission, check_job_edition_permission,\
                              check_dataset_access_permission, check_dataset_edition_permission
 from oozie.importlib.workflows import import_workflow as _import_workflow
+from oozie.importlib.coordinators import import_coordinator as _import_coordinator
 from oozie.management.commands import oozie_setup
 from oozie.models import Workflow, History, Coordinator,\
                          Dataset, DataInput, DataOutput,\
                          ACTION_TYPES, Bundle, BundledCoordinator, Job
 from oozie.forms import WorkflowForm, CoordinatorForm, DatasetForm,\
                         DataInputForm, DataOutputForm, LinkForm,\
-                        DefaultLinkForm, ParameterForm, ImportWorkflowForm,\
-                        NodeForm, BundleForm, BundledCoordinatorForm, design_form_by_type
+                        DefaultLinkForm, ParameterForm, NodeForm,\
+                        BundleForm, BundledCoordinatorForm, design_form_by_type,\
+                        ImportWorkflowForm, ImportCoordinatorForm
 
 
 LOG = logging.getLogger(__name__)
@@ -180,6 +182,52 @@ def import_workflow(request):
     'workflow': workflow,
   })
 
+
+def import_coordinator(request):
+  coordinator = Coordinator(owner=request.user, schema_version="uri:oozie:coordinator:0.2")
+
+  if request.method == 'POST':
+    coordinator_form = ImportCoordinatorForm(request.POST, request.FILES, instance=coordinator, user=request.user)
+
+    if coordinator_form.is_valid():
+      coordinator_definition = coordinator_form.cleaned_data['definition_file'].read()
+
+      try:
+        _import_coordinator(coordinator=coordinator, coordinator_definition=coordinator_definition)
+        coordinator.managed = True
+        coordinator.name = coordinator_form.cleaned_data.get('name')
+        coordinator.save()
+      except Exception, e:
+        request.error(_('Could not import coordinator: %s' % e))
+        raise PopupException(_('Could not import coordinator.'), detail=e)
+
+      if coordinator_form.cleaned_data.get('resource_archive'):
+        # Upload resources to workspace
+        source = coordinator_form.cleaned_data.get('resource_archive')
+        if source.name.endswith('.zip'):
+          temp_path = archive_factory(source).extract()
+          request.fs.copyFromLocal(temp_path, coordinator.deployment_dir)
+          shutil.rmtree(temp_path)
+        else:
+          Coordinator.objects.filter(id=coordinator.id).delete()
+          raise PopupException(_('Archive should be a Zip.'))
+      
+      Document.objects.link(coordinator, owner=request.user, name=coordinator.name, description=coordinator.description)
+      request.info(_('Coordinator imported'))
+      return redirect(reverse('oozie:edit_coordinator', kwargs={'coordinator': coordinator.id}))
+
+    else:
+      request.error(_('Errors on the form'))
+
+  else:
+    coordinator_form = ImportCoordinatorForm(instance=coordinator, user=request.user)
+
+  return render('editor/import_coordinator.mako', request, {
+    'coordinator_form': coordinator_form,
+    'coordinator': coordinator,
+  })
+
+
 @check_job_access_permission()
 def export_workflow(request, workflow):
   zip_file = workflow.compress(mapping=dict([(param['name'], param['value']) for param in workflow.find_all_parameters()]))