001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *      http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.oozie;
020
021import java.util.ArrayList;
022import java.util.Collections;
023import java.util.Iterator;
024import java.util.List;
025import java.util.Properties;
026
027import org.apache.oozie.client.CoordinatorAction;
028import org.apache.oozie.client.CoordinatorJob;
029import org.apache.oozie.client.OozieClient;
030import org.apache.oozie.client.OozieClientException;
031import org.apache.oozie.client.WorkflowJob;
032import org.apache.oozie.client.rest.RestConstants;
033import org.apache.oozie.command.CommandException;
034import org.apache.oozie.coord.CoordUtils;
035import org.apache.oozie.util.XConfiguration;
036
037/**
038 * Client API to submit and manage Oozie coordinator jobs against an Oozie
039 * intance.
040 * <p>
041 * This class is thread safe.
042 * <p>
043 * Syntax for filter for the {@link #getJobsInfo(String)}
044 * {@link #getJobsInfo(String, int, int)} methods:
045 * <code>[NAME=VALUE][;NAME=VALUE]*</code>.
046 * <p>
047 * Valid filter names are:
048 * <p>
049 * <ul>
050 * <li>name: the coordinator application name from the coordinator definition.</li>
051 * <li>user: the user that submitted the job.</li>
052 * <li>group: the group for the job.</li>
053 * <li>status: the status of the job.</li>
054 * </ul>
055 * <p>
056 * The query will do an AND among all the filter names. The query will do an OR
057 * among all the filter values for the same name. Multiple values must be
058 * specified as different name value pairs.
059 */
060public class LocalOozieClientCoord extends OozieClient {
061
062    private final CoordinatorEngine coordEngine;
063
064    /**
065     * Create a coordinator client for Oozie local use.
066     * <p>
067     *
068     * @param coordEngine the engine instance to use.
069     */
070    public LocalOozieClientCoord(CoordinatorEngine coordEngine) {
071        this.coordEngine = coordEngine;
072    }
073
074    /**
075     * Return the Oozie URL of the coordinator client instance.
076     * <p>
077     * This URL is the base URL fo the Oozie system, with not protocol
078     * versioning.
079     *
080     * @return the Oozie URL of the coordinator client instance.
081     */
082    @Override
083    public String getOozieUrl() {
084        return "localoozie";
085    }
086
087    /**
088     * Return the Oozie URL used by the client and server for WS communications.
089     * <p>
090     * This URL is the original URL plus the versioning element path.
091     *
092     * @return the Oozie URL used by the client and server for communication.
093     * @throws org.apache.oozie.client.OozieClientException thrown in the client
094     *         and the server are not protocol compatible.
095     */
096    @Override
097    public String getProtocolUrl() throws OozieClientException {
098        return "localoozie";
099    }
100
101    /**
102     * Validate that the Oozie client and server instances are protocol
103     * compatible.
104     *
105     * @throws org.apache.oozie.client.OozieClientException thrown in the client
106     *         and the server are not protocol compatible.
107     */
108    @Override
109    public synchronized void validateWSVersion() throws OozieClientException {
110    }
111
112    /**
113     * Create an empty configuration with just the {@link #USER_NAME} set to the
114     * JVM user name and the {@link #GROUP_NAME} set to 'other'.
115     *
116     * @return an empty configuration.
117     */
118    @Override
119    public Properties createConfiguration() {
120        Properties conf = new Properties();
121        if (coordEngine != null) {
122            conf.setProperty(USER_NAME, coordEngine.getUser());
123        }
124        conf.setProperty(GROUP_NAME, "users");
125        return conf;
126    }
127
128    /**
129     * Set a HTTP header to be used in the WS requests by the coordinator
130     * instance.
131     *
132     * @param name header name.
133     * @param value header value.
134     */
135    @Override
136    public void setHeader(String name, String value) {
137    }
138
139    /**
140     * Get the value of a set HTTP header from the coordinator instance.
141     *
142     * @param name header name.
143     * @return header value, <code>null</code> if not set.
144     */
145    @Override
146    public String getHeader(String name) {
147        return null;
148    }
149
150    /**
151     * Remove a HTTP header from the coordinator client instance.
152     *
153     * @param name header name.
154     */
155    @Override
156    public void removeHeader(String name) {
157    }
158
159    /**
160     * Return an iterator with all the header names set in the coordinator
161     * instance.
162     *
163     * @return header names.
164     */
165    @Override
166    @SuppressWarnings("unchecked")
167    public Iterator<String> getHeaderNames() {
168        return Collections.EMPTY_SET.iterator();
169    }
170
171    /**
172     * Submit a coordinator job.
173     *
174     * @param conf job configuration.
175     * @return the job Id.
176     * @throws org.apache.oozie.client.OozieClientException thrown if the job
177     *         could not be submitted.
178     */
179    @Override
180    public String submit(Properties conf) throws OozieClientException {
181        try {
182            return coordEngine.submitJob(new XConfiguration(conf), false);
183        }
184        catch (CoordinatorEngineException ex) {
185            throw new OozieClientException(ex.getErrorCode().toString(), ex);
186        }
187    }
188
189    /**
190     * Start a coordinator job.
191     *
192     * @param jobId job Id.
193     * @throws org.apache.oozie.client.OozieClientException thrown if the job
194     *         could not be started.
195     */
196    @Override
197    @Deprecated
198    public void start(String jobId) throws OozieClientException {
199        try {
200            coordEngine.start(jobId);
201        }
202        catch (CoordinatorEngineException ex) {
203            throw new OozieClientException(ex.getErrorCode().toString(), ex);
204        }
205        catch (BaseEngineException bex) {
206            throw new OozieClientException(bex.getErrorCode().toString(), bex);
207        }
208    }
209
210    /**
211     * Submit and start a coordinator job.
212     *
213     * @param conf job configuration.
214     * @return the job Id.
215     * @throws org.apache.oozie.client.OozieClientException thrown if the job
216     *         could not be submitted.
217     */
218    @Override
219    public String run(Properties conf) throws OozieClientException {
220        try {
221            return coordEngine.submitJob(new XConfiguration(conf), true);
222        }
223        catch (CoordinatorEngineException ex) {
224            throw new OozieClientException(ex.getErrorCode().toString(), ex);
225        }
226    }
227
228    /**
229     * Rerun a workflow job.
230     *
231     * @param jobId job Id to rerun.
232     * @param conf configuration information for the rerun.
233     * @throws org.apache.oozie.client.OozieClientException thrown if the job
234     *         could not be started.
235     */
236    @Override
237    @Deprecated
238    public void reRun(String jobId, Properties conf) throws OozieClientException {
239        throw new OozieClientException(ErrorCode.E0301.toString(), "no-op");
240    }
241
242    /**
243     * Rerun coordinator actions.
244     *
245     * @param jobId coordinator jobId
246     * @param rerunType rerun type 'date' if -date is used, 'action-id' if
247     *        -action is used
248     * @param scope rerun scope for date or actionIds
249     * @param refresh true if -refresh is given in command option
250     * @param noCleanup true if -nocleanup is given in command option
251     * @throws OozieClientException
252     */
253    @Override
254    public List<CoordinatorAction> reRunCoord(String jobId, String rerunType, String scope, boolean refresh,
255                                              boolean noCleanup) throws OozieClientException {
256        return getCoordinatorActions(jobId, rerunType, scope, refresh, noCleanup, false, null);
257    }
258
259    /**
260     * Rerun coordinator actions with failed option.
261     *
262     * @param jobId coordinator jobId
263     * @param rerunType rerun type 'date' if -date is used, 'action-id' if
264     *        -action is used
265     * @param scope rerun scope for date or actionIds
266     * @param refresh true if -refresh is given in command option
267     * @param noCleanup true if -nocleanup is given in command option
268     * @param failed true if -failed is given in command option
269     * @param conf configuration information for the rerun
270     * @throws OozieClientException
271     */
272    @Override
273    public List<CoordinatorAction> reRunCoord(String jobId, String rerunType, String scope, boolean refresh,
274            boolean noCleanup, boolean failed, Properties conf ) throws OozieClientException {
275        return getCoordinatorActions(jobId, rerunType, scope, refresh, noCleanup, failed, conf);
276    }
277
278    private List<CoordinatorAction> getCoordinatorActions(String jobId, String rerunType, String scope, boolean refresh,
279            boolean noCleanup, boolean failed, Properties prop) throws OozieClientException {
280        try {
281            XConfiguration conf = null;
282            if (prop != null) {
283                conf = new XConfiguration(prop);
284            }
285            if (!(rerunType.equals(RestConstants.JOB_COORD_SCOPE_DATE) || rerunType
286                    .equals(RestConstants.JOB_COORD_SCOPE_ACTION))) {
287                throw new CommandException(ErrorCode.E1018, "date or action expected.");
288            }
289            CoordinatorActionInfo coordInfo = coordEngine.reRun(jobId, rerunType, scope, Boolean.valueOf(refresh),
290                    Boolean.valueOf(noCleanup), Boolean.valueOf(failed), conf);
291            List<CoordinatorActionBean> actionBeans;
292            if (coordInfo != null) {
293                actionBeans = coordInfo.getCoordActions();
294            }
295            else {
296                actionBeans = CoordUtils.getCoordActions(rerunType, jobId, scope, false);
297            }
298            List<CoordinatorAction> actions = new ArrayList<CoordinatorAction>();
299            for (CoordinatorActionBean actionBean : actionBeans) {
300                actions.add(actionBean);
301            }
302            return actions;
303        }
304        catch(CommandException ce){
305            throw new OozieClientException(ce.getErrorCode().toString(), ce);
306        }
307        catch (BaseEngineException ex) {
308            throw new OozieClientException(ex.getErrorCode().toString(), ex);
309        }
310    }
311
312    /**
313     * Suspend a coordinator job.
314     *
315     * @param jobId job Id.
316     * @throws org.apache.oozie.client.OozieClientException thrown if the job
317     *         could not be suspended.
318     */
319    @Override
320    public void suspend(String jobId) throws OozieClientException {
321        try {
322            coordEngine.suspend(jobId);
323        }
324        catch (CoordinatorEngineException ex) {
325            throw new OozieClientException(ex.getErrorCode().toString(), ex);
326        }
327    }
328
329    /**
330     * Resume a coordinator job.
331     *
332     * @param jobId job Id.
333     * @throws org.apache.oozie.client.OozieClientException thrown if the job
334     *         could not be resume.
335     */
336    @Override
337    public void resume(String jobId) throws OozieClientException {
338        try {
339            coordEngine.resume(jobId);
340        }
341        catch (CoordinatorEngineException ex) {
342            throw new OozieClientException(ex.getErrorCode().toString(), ex);
343        }
344    }
345
346    /**
347     * Kill a coordinator job.
348     *
349     * @param jobId job Id.
350     * @throws org.apache.oozie.client.OozieClientException thrown if the job
351     *         could not be killed.
352     */
353    @Override
354    public void kill(String jobId) throws OozieClientException {
355        try {
356            coordEngine.kill(jobId);
357        }
358        catch (CoordinatorEngineException ex) {
359            throw new OozieClientException(ex.getErrorCode().toString(), ex);
360        }
361    }
362
363    /**
364     * Get the info of a workflow job.
365     *
366     * @param jobId job Id.
367     * @return the job info.
368     * @throws org.apache.oozie.client.OozieClientException thrown if the job
369     *         info could not be retrieved.
370     */
371    @Override
372    @Deprecated
373    public WorkflowJob getJobInfo(String jobId) throws OozieClientException {
374        throw new OozieClientException(ErrorCode.E0301.toString(), "no-op");
375    }
376
377    /**
378     * Get the info of a coordinator job.
379     *
380     * @param jobId job Id.
381     * @return the job info.
382     * @throws org.apache.oozie.client.OozieClientException thrown if the job
383     *         info could not be retrieved.
384     */
385    @Override
386    public CoordinatorJob getCoordJobInfo(String jobId) throws OozieClientException {
387        try {
388            return coordEngine.getCoordJob(jobId);
389        }
390        catch (CoordinatorEngineException ex) {
391            throw new OozieClientException(ex.getErrorCode().toString(), ex);
392        }
393        catch (BaseEngineException bex) {
394            throw new OozieClientException(bex.getErrorCode().toString(), bex);
395        }
396    }
397
398    /**
399     * Get the info of a coordinator job.
400     *
401     * @param jobId job Id.
402     * @param filter filter the status filter
403     * @param start starting index in the list of actions belonging to the job
404     * @param len number of actions to be returned
405     * @return the job info.
406     * @throws org.apache.oozie.client.OozieClientException thrown if the job
407     *         info could not be retrieved.
408     */
409    @Override
410    public CoordinatorJob getCoordJobInfo(String jobId, String filter, int start, int len)
411            throws OozieClientException {
412        try {
413            return coordEngine.getCoordJob(jobId, filter, start, len, false);
414        }
415        catch (CoordinatorEngineException ex) {
416            throw new OozieClientException(ex.getErrorCode().toString(), ex);
417        }
418        catch (BaseEngineException bex) {
419            throw new OozieClientException(bex.getErrorCode().toString(), bex);
420        }
421    }
422
423    /**
424     * Get the info of a coordinator action.
425     *
426     * @param actionId Id.
427     * @return the coordinator action info.
428     * @throws OozieClientException thrown if the job info could not be
429     *         retrieved.
430     */
431    @Override
432    public CoordinatorAction getCoordActionInfo(String actionId) throws OozieClientException {
433        try {
434            return coordEngine.getCoordAction(actionId);
435        }
436        catch (CoordinatorEngineException ex) {
437            throw new OozieClientException(ex.getErrorCode().toString(), ex);
438        }
439        catch (BaseEngineException bex) {
440            throw new OozieClientException(bex.getErrorCode().toString(), bex);
441        }
442    }
443
444    /**
445     * Return the info of the workflow jobs that match the filter.
446     *
447     * @param filter job filter. Refer to the {@link OozieClient} for the filter
448     *        syntax.
449     * @param start jobs offset, base 1.
450     * @param len number of jobs to return.
451     * @return a list with the workflow jobs info, without node details.
452     * @throws OozieClientException thrown if the jobs info could not be
453     *         retrieved.
454     */
455    @Override
456    @Deprecated
457    public List<WorkflowJob> getJobsInfo(String filter, int start, int len) throws OozieClientException {
458        throw new OozieClientException(ErrorCode.E0301.toString(), "no-op");
459    }
460
461    /**
462     * Return the info of the coordinator jobs that match the filter.
463     *
464     * @param filter job filter. Refer to the {@link OozieClient} for the filter
465     *        syntax.
466     * @param start jobs offset, base 1.
467     * @param len number of jobs to return.
468     * @return a list with the coordinator jobs info
469     * @throws OozieClientException thrown if the jobs info could not be
470     *         retrieved.
471     */
472    @Override
473    public List<CoordinatorJob> getCoordJobsInfo(String filter, int start, int len) throws OozieClientException {
474        try {
475            CoordinatorJobInfo info = coordEngine.getCoordJobs(filter, start, len);
476            List<CoordinatorJob> jobs = new ArrayList<CoordinatorJob>();
477            List<CoordinatorJobBean> jobBeans = info.getCoordJobs();
478            for (CoordinatorJobBean jobBean : jobBeans) {
479                jobs.add(jobBean);
480            }
481            return jobs;
482
483        }
484        catch (CoordinatorEngineException ex) {
485            throw new OozieClientException(ex.getErrorCode().toString(), ex);
486        }
487    }
488
489    /**
490     * Return the info of the workflow jobs that match the filter.
491     * <p>
492     * It returns the first 100 jobs that match the filter.
493     *
494     * @param filter job filter. Refer to the {@link LocalOozieClient} for the
495     *        filter syntax.
496     * @return a list with the workflow jobs info, without node details.
497     * @throws org.apache.oozie.client.OozieClientException thrown if the jobs
498     *         info could not be retrieved.
499     */
500    @Override
501    @Deprecated
502    public List<WorkflowJob> getJobsInfo(String filter) throws OozieClientException {
503        throw new OozieClientException(ErrorCode.E0301.toString(), "no-op");
504    }
505
506}