add datasource kerberos auth and FAQ modify

dev-1.1.0
qiaozhanwei 2019-06-28 14:39:02 +08:00
parent a0e1495f27
commit 3f217f5d00
13 changed files with 383 additions and 82 deletions

View File

@ -1,96 +1,283 @@
Q:单机运行服务老挂应该是内存不够测试机器4核8G。生产环境需要分布式如果单机的话建议的配置是
## QEasyScheduler服务介绍及建议运行内存
A: Easy Scheduler有5个服务组成这些服务本身需要的内存和cpu不多
| 服务 | 内存 | cpu核数 |
| ------------ | ---- | ------- |
| MasterServer | 2G | 2核 |
| WorkerServer | 2G | 2核 |
| ApiServer | 512M | 1核 |
| AlertServer | 512M | 1核 |
| LoggerServer | 512M | 1核 |
注意由于如果任务较多WorkServer所在机器建议物理内存在16G以上
A EasyScheduler由5个服务组成MasterServer、WorkerServer、ApiServer、AlertServer、LoggerServer和UI。
| 服务 | 说明 |
| ------------------------- | ------------------------------------------------------------ |
| MasterServer | 主要负责 **DAG** 的切分和任务状态的监控 |
| WorkerServer/LoggerServer | 主要负责任务的提交、执行和任务状态的更新。LoggerServer用于Rest Api通过 **RPC** 查看日志 |
| ApiServer | 提供Rest Api服务供UI进行调用 |
| AlertServer | 提供告警服务 |
| UI | 前端页面展示 |
注意:**由于服务比较多建议单机部署最好是4核16G以上**
---
Q: 管理员为什么不能创建项目?
## Q 管理员为什么不能创建项目
A: 管理员目前属于"纯管理", 没有租户即没有linux上对应的用户所以没有执行权限, 但是有所有的查看权限。如果需要创建项目等业务操作,请使用管理员创建租户和普通用户,然后使用普通用户登录进行操作
A:管理员目前属于"**纯管理**", 没有租户即没有linux上对应的用户所以没有执行权限, **故没有所属的项目、资源及数据源**,所以没有创建权限。**但是有所有的查看权限**。如果需要创建项目等业务操作,**请使用管理员创建租户和普通用户,然后使用普通用户登录进行操作**。我们将会在1.1.0版本中将管理员的创建和执行权限放开,管理员将会有所有的权限
---
Q: 系统支持哪些邮箱?
## Q系统支持哪些邮箱?
A: 支持绝大多数邮箱qq、163、126、139、outlook、aliyun等皆可支持
A支持绝大多数邮箱qq、163、126、139、outlook、aliyun等皆支持。支持**TLS和SSL**协议可以在alert.properties中选择性配置
---
Q:常用的系统变量时间参数有哪些,如何使用?
## Q常用的系统变量时间参数有哪些如何使用?
A: 请参考使用手册中的系统参数
A:请参考 https://analysys.github.io/easyscheduler_docs_cn/%E7%B3%BB%E7%BB%9F%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C.html#%E7%B3%BB%E7%BB%9F%E5%8F%82%E6%95%B0
---
Qpip install kazoo 这个安装报错。是必须安装的吗?
## Qpip install kazoo 这个安装报错。是必须安装的吗?
A: 这个是python连接zookeeper需要使用到的
A 这个是python连接zookeeper需要使用到的必须要安装
---
Q: 如果alert、api、logger服务任意一个宕机任何还会正常执行吧
## Q: 怎么指定机器运行任务
A: 不影响影响正在运行中的任务的服务有Master和Worker服务
A:使用 **管理员** 创建Worker分组**流程定义启动** 的时候可**指定Worker分组**或者在**任务节点上指定Worker分组**。如果不指定则使用Default**Default默认是使用的集群里所有的Worker中随机选取一台来进行任务提交、执行**
---
Q: 这个怎么指定机器运行任务的啊 」
## Q任务的优先级
A: 通过worker分组 这个流程只能在指定的机器组里执行。默认是Default可以在任一worker上执行。
---
Q: 跨用户的任务依赖怎么实现呢, 比如A用户写了一个任务B用户需要依赖这个任务
就比如说 我们数仓组 写了一个 中间宽表的任务, 其他业务部门想要使用这个中间表的时候,他们应该是另外一个用户,怎么依赖这个中间表呢
A: 有两种情况,一个是要运行这个宽表任务,可以使用子工作流把宽表任务放到自己的工作流里面。另一个是检查这个宽表任务有没有完成,可以使用依赖节点来检查这个宽表任务在指定的时间周期有没有完成。
---
Q: 启动WorkerServer服务时不能正常启动报以下信息是什么原因
```
[INFO] 2019-05-06 16:39:31.492 cn.escheduler.server.zk.ZKWorkerClient:[155] - register failure , worker already started on : 127.0.0.1, please wait for a moment and try again
```
AWorker/Master Server在启动时会向Zookeeper注册自己的启动信息是Zookeeper的临时节点如果两次启动时间间隔较短的情况上次启动的Worker/Master Server在Zookeeper的会话还未过期会出现上述信息处理办法是等待session过期一般是1分钟左右
A我们同时 **支持流程和任务的优先级**。优先级我们有 **HIGHEST、HIGH、MEDIUM、LOW和LOWEST** 五种级别。**可以设置不同流程实例之间的优先级,也可以设置同一个流程实例中不同任务实例的优先级**。详细内容请参考任务优先级设计 https://analysys.github.io/easyscheduler_docs_cn/%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1.html#%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1
----
Q: 编译时escheduler-grpc模块一直报错Information:java: Errors occurred while compiling module 'escheduler-rpc' 找不到LogParameter、RetStrInfo、RetByteInfo等class类
## Qescheduler-grpc报错
A: 这是因为rpc源码包是google Grpc实现的需要使用maven进行编译在根目录下执行mvn -U clean package assembly:assembly -Dmaven.test.skip=true 然后刷新下整个项目
A在根目录下执行mvn -U clean package assembly:assembly -Dmaven.test.skip=true 然后刷新下整个项目
----
QEasyScheduler支持windows上运行么
## QEasyScheduler支持windows上运行么
A: 建议在Ubuntu、Centos上运行暂不支持windows上运行不过windows上可以进行编译。开发调试的话建议Ubuntu或者mac上进行。
A 理论上只有**Worker是需要在Linux上运行的**其它的服务都是可以在windows上正常运行的。但是还是建议最好能在linux上部署使用
-----
Q任务为什么不执行
## QUI 在 linux 编译node-sass提示ErrorEACCESS:permission deniedmkdir xxxx
A: 不执行的原因:
A单独安装 **npm install node-sass --unsafe-perm**,之后再 **npm install**
查看command表里有没有内容
---
查看Master server的运行日志
## QUI 不能正常登陆访问
查看Worker Server的运行日志
A 1如果是node启动的查看escheduler-ui下的.env API_BASE配置是否是Api Server服务地址
2如果是nginx启动的并且是通过 **install-escheduler-ui.sh** 安装的,查看 **/etc/nginx/conf.d/escheduler.conf** 中的proxy_pass配置是否是Api Server服务地址
3如果以上配置都是正确的那么请查看Api Server服务是否是正常的curl http://192.168.xx.xx:12345/escheduler/users/get-user-info查看Api Server日志如果提示 cn.escheduler.api.interceptor.LoginHandlerInterceptor:[76] - session info is null则证明Api Server服务是正常的
4如果以上都没有问题需要查看一下 **application.properties** 中的 **server.context-path 和 server.port 配置**是否正确
---
## Q 流程定义手动启动或调度启动之后,没有流程实例生成
A 1首先通过**jps 查看MasterServer服务是否存在**或者从服务监控直接查看zk中是否存在master服务
2如果存在master服务查看 **命令状态统计** 或者 **t_escheduler_error_command** 中是否增加的新记录,如果增加了,**请查看 message 字段定位启动异常原因**
---
## Q 任务状态一直处于提交成功状态
A 1首先通过**jps 查看WorkerServer服务是否存在**或者从服务监控直接查看zk中是否存在worker服务
2如果 **WorkerServer** 服务正常,需要 **查看MasterServer是否把task任务放到zk队列中** **需要查看MasterServer日志及zk队列中是否有任务阻塞**
3如果以上都没有问题需要定位是否指定了Worker分组但是 **Worker分组的机器不是在线状态**
---
## Q 是否提供Docker镜像及Dockerfile
A 提供Docker镜像及Dockerfile。
Docker镜像地址https://hub.docker.com/r/escheduler/escheduler_images
Dockerfile地址https://github.com/qiaozhanwei/escheduler_dockerfile/tree/master/docker_escheduler
---
## Q install.sh 中需要注意问题
A 1如果替换变量中包含特殊字符**请用 \ 转移符进行转移**
2installPath="/data1_1T/escheduler"**这个目录不能和当前要一键安装的install.sh目录是一样的**
3deployUser="escheduler"**部署用户必须具有sudo权限**因为worker是通过sudo -u 租户 sh xxx.command进行执行的
4monitorServerState="false",服务监控脚本是否启动,默认是不启动服务监控脚本的。**如果启动服务监控脚本则每5分钟定时来监控master和worker的服务是否down机如果down机则会自动重启**
5hdfsStartupSate="false"是否开启HDFS资源上传功能。默认是不开启的**如果不开启则资源中心是不能使用的**。如果开启需要conf/common/hadoop/hadoop.properties中配置fs.defaultFS和yarn的相关配置如果使用namenode HA需要将core-site.xml和hdfs-site.xml复制到conf根目录下
注意:**1.0.x版本是不会自动创建hdfs根目录的需要自行创建并且需要部署用户有hdfs的操作权限**
---
## Q 流程定义和流程实例下线异常
A 对于 **1.0.4 以前的版本中**修改escheduler-api cn.escheduler.api.quartz包下的代码即可
```
public boolean deleteJob(String jobName, String jobGroupName) {
lock.writeLock().lock();
try {
JobKey jobKey = new JobKey(jobName,jobGroupName);
if(scheduler.checkExists(jobKey)){
logger.info("try to delete job, job name: {}, job group name: {},", jobName, jobGroupName);
return scheduler.deleteJob(jobKey);
}else {
return true;
}
} catch (SchedulerException e) {
logger.error(String.format("delete job : %s failed",jobName), e);
} finally {
lock.writeLock().unlock();
}
return false;
}
```
---
## Q HDFS启动之前创建的租户能正常使用资源中心吗
A 不能。因为在未启动HDFS创建的租户不会在HDFS中注册租户目录。所以上次资源会报错
## Q : 多Master和多Worker状态下服务掉了怎么容错
A **注意Master监控Master及Worker服务。**
1如果Master服务掉了其它的Master会接管挂掉的Master的流程继续监控Worker task状态
2如果Worker服务掉Master会监控到Worker服务掉了如果存在Yarn任务Kill Yarn任务之后走重试
具体请看容错设计https://analysys.github.io/easyscheduler_docs_cn/%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1.html#%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1
---
## Q 对于Master和Worker一台机器伪分布式下的容错
A 1.0.3 版本只实现了Master启动流程容错不走Worker容错。也就是说如果Worker挂掉的时候没有Master存在。这流程将会出现问题。我们会在 **1.1.0** 版本中增加Master和Worker启动自容错修复这个问题。如果想手动修改这个问题需要针对 **跨重启正在运行流程** **并且已经掉的正在运行的Worker任务需要修改为失败****同时跨重启正在运行流程设置为失败状态**。然后从失败节点进行流程恢复即可
---
## Q 定时容易设置成每秒执行
A 设置定时的时候需要注意,如果第一位(* * * * * ? *)设置成 \* ,则表示每秒执行。**我们将会在1.1.0版本中加入显示最近调度的时间列表** 使用http://cron.qqe2.com/ 可以在线看近5次运行时间
## Q 定时有有效时间范围吗
A有的**如果定时的起止时间是同一个时间,那么此定时将是无效的定时**。**如果起止时间的结束时间比当前的时间小,很有可能定时会被自动删除**
## Q 任务依赖有几种实现
A 1**DAG** 之间的任务依赖关系,是从 **入度为零** 进行DAG切分的
2**任务依赖节点** ,可以实现跨流程的任务或者流程依赖,具体请参考 依赖(DEPENDENT)节点https://analysys.github.io/easyscheduler_docs_cn/%E7%B3%BB%E7%BB%9F%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C.html#%E4%BB%BB%E5%8A%A1%E8%8A%82%E7%82%B9%E7%B1%BB%E5%9E%8B%E5%92%8C%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE
注意:**不支持跨项目的流程或任务依赖**
## Q 流程定义有几种启动方式
A 1**流程定义列表**,点击 **启动** 按钮
2**流程定义列表添加定时器**,调度启动流程定义
3流程定义 **查看或编辑** DAG 页面,任意 **任务节点右击** 启动流程定义
4可以对流程定义 DAG 编辑,设置某些任务的运行标志位 **禁止运行**则在启动流程定义的时候将该节点的连线将从DAG中去掉
## Q Python任务设置Python版本
A 1对于1**.0.3之后的版本**只需要修改 conf/env/.escheduler_env.sh中的PYTHON_HOME
```
export PYTHON_HOME=/bin/python
```
注意:这了 **PYTHON_HOME** 是python命令的绝对路径而不是单纯的 PYTHON_HOME还需要注意的是 export PATH 的时候,需要直接
```
export PATH=$HADOOP_HOME/bin:$SPARK_HOME1/bin:$SPARK_HOME2/bin:$PYTHON_HOME:$JAVA_HOME/bin:$HIVE_HOME/bin:$PATH
```
2对 1.0.3 之前的版本Python任务只能支持系统的Python版本不支持指定Python版本
## Q Worker Task 通过sudo -u 租户 sh xxx.command会产生子进程在kill的时候是否会杀掉
A 我们会在1.0.4中增加kill任务同时kill掉任务产生的各种所有子进程
## Q EasyScheduler中的队列怎么用用户队列和租户队列是什么意思
A EasyScheduler 中的队列可以在用户或者租户上指定队列,**用户指定的队列优先级是高于租户队列的优先级的。**例如对MR任务指定队列是通过 mapreduce.job.queuename 来指定队列的。
注意MR在用以上方法指定队列的时候传递参数请使用如下方式
```
Configuration conf = new Configuration();
GenericOptionsParser optionParser = new GenericOptionsParser(conf, args);
String[] remainingArgs = optionParser.getRemainingArgs();
```
如果是Spark任务 --queue 方式指定队列
## Q : Master 后者 Worker报如下告警
![1560847965302](C:\Users\Administrator\Desktop\FAQ\1560847965302.png)
A 修改conf下的 master.properties **master.reserved.memory** 的值为更小的值比如说0.1 或者
worker.properties **worker.reserved.memory** 的值为更小的值比如说0.1
## Q : hive版本是1.1.0+cdh5.15.0SQL hive任务连接报错
![EF4DA613-5129-4c7a-A0AB-61E5A866A919](C:\Users\Administrator\Desktop\FAQ\EF4DA613-5129-4c7a-A0AB-61E5A866A919.png)
A 将 hive pom
```
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>2.1.0</version>
</dependency>
```
修改为
```
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>1.1.0</version>
</dependency>
```

View File

@ -18,10 +18,13 @@ package cn.escheduler.api.controller;
import cn.escheduler.api.enums.Status;
import cn.escheduler.api.service.DataSourceService;
import cn.escheduler.api.utils.CheckUtils;
import cn.escheduler.api.utils.Constants;
import cn.escheduler.api.utils.Result;
import cn.escheduler.common.enums.DbType;
import cn.escheduler.common.enums.ResUploadType;
import cn.escheduler.common.utils.ParameterUtils;
import cn.escheduler.common.utils.PropertyUtils;
import cn.escheduler.dao.model.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@ -56,12 +59,16 @@ public class DataSourceController extends BaseController {
/**
* create data source
*
*
* @param loginUser
* @param name
* @param note
* @param type
* @param host
* @param port
* @param database
* @param principal
* @param userName
* @param password
* @param other
* @return
*/
@ -86,13 +93,14 @@ public class DataSourceController extends BaseController {
@RequestParam(value = "host") String host,
@RequestParam(value = "port") String port,
@RequestParam(value = "database") String database,
@RequestParam(value = "principal") String principal,
@RequestParam(value = "userName") String userName,
@RequestParam(value = "password") String password,
@RequestParam(value = "other") String other) {
logger.info("login user {} create datasource ame: {}, note: {}, type: {}, other: {}",
loginUser.getUserName(), name, note, type, other);
logger.info("login user {} create datasource name: {}, note: {}, type: {}, host: {},port: {},database : {},principal: {},userName : {} other: {}",
loginUser.getUserName(), name, note, type, host,port,database,principal,userName,other);
try {
String parameter = dataSourceService.buildParameter(name, note, type, host, port, database, userName, password, other);
String parameter = dataSourceService.buildParameter(name, note, type, host, port, database,principal,userName, password, other);
Map<String, Object> result = dataSourceService.createDataSource(loginUser, name, note, type, parameter);
return returnDataList(result);
@ -136,13 +144,14 @@ public class DataSourceController extends BaseController {
@RequestParam(value = "host") String host,
@RequestParam(value = "port") String port,
@RequestParam(value = "database") String database,
@RequestParam(value = "principal") String principal,
@RequestParam(value = "userName") String userName,
@RequestParam(value = "password") String password,
@RequestParam(value = "other") String other) {
logger.info("login user {} updateProcessInstance datasource name: {}, note: {}, type: {}, other: {}",
loginUser.getUserName(), name, note, type, other);
try {
String parameter = dataSourceService.buildParameter(name, note, type, host, port, database, userName, password, other);
String parameter = dataSourceService.buildParameter(name, note, type, host, port, database,principal, userName, password, other);
Map<String, Object> dataSource = dataSourceService.updateDataSource(id, loginUser, name, note, type, parameter);
return returnDataList(dataSource);
} catch (Exception e) {
@ -271,13 +280,14 @@ public class DataSourceController extends BaseController {
@RequestParam(value = "host") String host,
@RequestParam(value = "port") String port,
@RequestParam(value = "database") String database,
@RequestParam(value = "principal") String principal,
@RequestParam(value = "userName") String userName,
@RequestParam(value = "password") String password,
@RequestParam(value = "other") String other) {
logger.info("login user {}, connect datasource: {} failure, note: {}, type: {}, other: {}",
loginUser.getUserName(), name, note, type, other);
try {
String parameter = dataSourceService.buildParameter(name, note, type, host, port, database, userName, password, other);
String parameter = dataSourceService.buildParameter(name, note, type, host, port, database,principal,userName, password, other);
Boolean isConnection = dataSourceService.checkConnection(type, parameter);
Result result = new Result();
@ -442,10 +452,10 @@ public class DataSourceController extends BaseController {
@GetMapping(value="/kerberos-startup-state")
@ResponseStatus(HttpStatus.OK)
public Result getKerberosStartupState(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser){
logger.info("login user {},get user info : {}", loginUser.getUserName());
logger.info("login user {},get kerberos startup state : {}", loginUser.getUserName());
try{
Boolean kerberosStartupState = getBoolean(cn.escheduler.common.Constants.HADOOP_SECURITY_AUTHENTICATION_STARTUP_STATE);
return success(Status.SUCCESS.getMsg(),kerberosStartupState);
// if upload resource is HDFS and kerberos startup is true , else false
return success(Status.SUCCESS.getMsg(), CheckUtils.getKerberosStartupState());
}catch (Exception e){
logger.error(KERBEROS_STARTUP_STATE.getMsg(),e);
return error(Status.KERBEROS_STARTUP_STATE.getCode(), Status.KERBEROS_STARTUP_STATE.getMsg());

View File

@ -17,12 +17,15 @@
package cn.escheduler.api.service;
import cn.escheduler.api.enums.Status;
import cn.escheduler.api.utils.CheckUtils;
import cn.escheduler.api.utils.Constants;
import cn.escheduler.api.utils.PageInfo;
import cn.escheduler.api.utils.Result;
import cn.escheduler.common.enums.DbType;
import cn.escheduler.common.enums.ResUploadType;
import cn.escheduler.common.enums.UserType;
import cn.escheduler.common.job.db.*;
import cn.escheduler.common.utils.PropertyUtils;
import cn.escheduler.dao.mapper.DataSourceMapper;
import cn.escheduler.dao.mapper.DatasourceUserMapper;
import cn.escheduler.dao.mapper.ProjectMapper;
@ -31,6 +34,8 @@ import cn.escheduler.dao.model.Resource;
import cn.escheduler.dao.model.User;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -42,6 +47,9 @@ import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.*;
import static cn.escheduler.common.utils.PropertyUtils.getBoolean;
import static cn.escheduler.common.utils.PropertyUtils.getString;
/**
* datasource service
*/
@ -55,6 +63,7 @@ public class DataSourceService extends BaseService{
public static final String TYPE = "type";
public static final String HOST = "host";
public static final String PORT = "port";
public static final String PRINCIPAL = "principal";
public static final String DATABASE = "database";
public static final String USER_NAME = "userName";
public static final String PASSWORD = "password";
@ -240,6 +249,7 @@ public class DataSourceService extends BaseService{
map.put(TYPE, dataSourceType);
map.put(HOST, host);
map.put(PORT, port);
map.put(PRINCIPAL, datasourceForm.getPrincipal());
map.put(DATABASE, database);
map.put(USER_NAME, datasourceForm.getUser());
map.put(PASSWORD, datasourceForm.getPassword());
@ -363,11 +373,21 @@ public class DataSourceService extends BaseService{
Class.forName(Constants.COM_MYSQL_JDBC_DRIVER);
break;
case HIVE:
datasource = JSONObject.parseObject(parameter, HiveDataSource.class);
Class.forName(Constants.ORG_APACHE_HIVE_JDBC_HIVE_DRIVER);
break;
case SPARK:
datasource = JSONObject.parseObject(parameter, SparkDataSource.class);
if (CheckUtils.getKerberosStartupState()) {
System.setProperty(cn.escheduler.common.Constants.JAVA_SECURITY_KRB5_CONF,
getString(cn.escheduler.common.Constants.JAVA_SECURITY_KRB5_CONF_PATH));
Configuration configuration = new Configuration();
configuration.set(cn.escheduler.common.Constants.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
UserGroupInformation.setConfiguration(configuration);
UserGroupInformation.loginUserFromKeytab(getString(cn.escheduler.common.Constants.LOGIN_USER_KEY_TAB_USERNAME),
getString(cn.escheduler.common.Constants.LOGIN_USER_KEY_TAB_PATH));
}
if (dbType == DbType.HIVE){
datasource = JSONObject.parseObject(parameter, HiveDataSource.class);
}else if (dbType == DbType.SPARK){
datasource = JSONObject.parseObject(parameter, SparkDataSource.class);
}
Class.forName(Constants.ORG_APACHE_HIVE_JDBC_HIVE_DRIVER);
break;
case CLICKHOUSE:
@ -443,10 +463,18 @@ public class DataSourceService extends BaseService{
* @param other
* @return
*/
public String buildParameter(String name, String desc, DbType type, String host, String port, String database, String userName, String password, String other) {
public String buildParameter(String name, String desc, DbType type, String host,
String port, String database,String principal,String userName,
String password, String other) {
String address = buildAddress(type, host, port);
String jdbcUrl = address + "/" + database;
if (CheckUtils.getKerberosStartupState() &&
(type == DbType.HIVE || type == DbType.SPARK)){
jdbcUrl += ";principal=" + principal;
}
String separator = "";
if (Constants.MYSQL.equals(type.name())
|| Constants.POSTGRESQL.equals(type.name())
@ -465,6 +493,7 @@ public class DataSourceService extends BaseService{
parameterMap.put(Constants.JDBC_URL, jdbcUrl);
parameterMap.put(Constants.USER, userName);
parameterMap.put(Constants.PASSWORD, password);
parameterMap.put(Constants.PRINCIPAL,principal);
if (other != null && !"".equals(other)) {
Map map = JSONObject.parseObject(other, new TypeReference<LinkedHashMap<String, String>>() {
});

View File

@ -18,8 +18,10 @@ package cn.escheduler.api.utils;
import cn.escheduler.api.enums.Status;
import cn.escheduler.common.enums.ResUploadType;
import cn.escheduler.common.task.AbstractParameters;
import cn.escheduler.common.utils.JSONUtils;
import cn.escheduler.common.utils.PropertyUtils;
import cn.escheduler.common.utils.TaskParametersUtils;
import org.apache.commons.lang.StringUtils;
@ -28,6 +30,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import static cn.escheduler.common.utils.PropertyUtils.getBoolean;
/**
@ -158,4 +161,15 @@ public class CheckUtils {
return pattern.matcher(str).matches();
}
/**
* if upload resource is HDFS and kerberos startup is true , else false
* @return
*/
public static boolean getKerberosStartupState(){
String resUploadStartupType = PropertyUtils.getString(cn.escheduler.common.Constants.RES_UPLOAD_STARTUP_TYPE);
ResUploadType resUploadType = ResUploadType.valueOf(resUploadStartupType);
Boolean kerberosStartupState = getBoolean(cn.escheduler.common.Constants.HADOOP_SECURITY_AUTHENTICATION_STARTUP_STATE);
return resUploadType == ResUploadType.HDFS && kerberosStartupState;
}
}

View File

@ -111,6 +111,7 @@ public class Constants {
public static final String ADDRESS = "address";
public static final String DATABASE = "database";
public static final String JDBC_URL = "jdbcUrl";
public static final String PRINCIPAL = "principal";
public static final String USER = "user";
public static final String PASSWORD = "password";
public static final String OTHER = "other";

View File

@ -45,6 +45,18 @@ public abstract class BaseDataSource {
*/
private String other;
/**
* principal
*/
private String principal;
public String getPrincipal() {
return principal;
}
public void setPrincipal(String principal) {
this.principal = principal;
}
/**
* test whether the data source can be connected successfully
* @throws Exception
@ -73,14 +85,14 @@ public abstract class BaseDataSource {
this.password = password;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
public String getDatabase() {
return database;
}

View File

@ -17,12 +17,12 @@
package cn.escheduler.common.job.db;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.*;
/**
* data source of hive
@ -32,6 +32,8 @@ public class HiveDataSource extends BaseDataSource {
private static final Logger logger = LoggerFactory.getLogger(HiveDataSource.class);
/**
* gets the JDBC url for the data source connection
* @return
@ -43,7 +45,7 @@ public class HiveDataSource extends BaseDataSource {
jdbcUrl += "/";
}
jdbcUrl += getDatabase();
jdbcUrl += getDatabase() + ";principal=" + getPrincipal();
if (StringUtils.isNotEmpty(getOther())) {
jdbcUrl += ";" + getOther();
@ -67,11 +69,10 @@ public class HiveDataSource extends BaseDataSource {
try {
con.close();
} catch (SQLException e) {
logger.error("Postgre datasource try conn close conn error", e);
logger.error("hive datasource try conn close conn error", e);
throw e;
}
}
}
}
}

View File

@ -31,7 +31,6 @@ public class SparkDataSource extends BaseDataSource {
private static final Logger logger = LoggerFactory.getLogger(SparkDataSource.class);
/**
* gets the JDBC url for the data source connection
* @return
@ -43,7 +42,7 @@ public class SparkDataSource extends BaseDataSource {
jdbcUrl += "/";
}
jdbcUrl += getDatabase();
jdbcUrl += getDatabase() + ";principal=" + getPrincipal();
if (StringUtils.isNotEmpty(getOther())) {
jdbcUrl += ";" + getOther();

View File

@ -63,6 +63,17 @@
</x-input>
</template>
</m-list-box-f>
<m-list-box-f :class="{hidden:showPrincipal}">
<template slot="name"><b>*</b>Principal</template>
<template slot="content">
<x-input
type="input"
v-model="principal"
:placeholder="$t('Please enter Principal')"
autocomplete="off">
</x-input>
</template>
</m-list-box-f>
<m-list-box-f>
<template slot="name"><b>*</b>{{$t('User Name')}}</template>
<template slot="content">
@ -143,6 +154,8 @@
port: '',
// data storage name
database: '',
// principal
principal:'',
// database username
userName: '',
// Database password
@ -150,12 +163,15 @@
// Jdbc connection parameter
other: '',
// btn test loading
testLoading: false
testLoading: false,
showPrincipal: true,
isShowPrincipal:true
}
},
props: {
item: Object
},
methods: {
_rtOtherPlaceholder () {
return `${i18n.$t('Please enter format')} {"key1":"value1","key2":"value2"...} ${i18n.$t('connection parameter')}`
@ -187,6 +203,7 @@
host: this.host,
port: this.port,
database: this.database,
principal:this.principal,
userName: this.userName,
password: this.password,
other: this.other
@ -289,6 +306,7 @@
this.note = res.note
this.host = res.host
this.port = res.port
this.principal = res.principal
this.database = res.database
this.userName = res.userName
this.password = res.password
@ -298,12 +316,31 @@
})
}
},
watch: {},
watch: {
'type'(value){
if((value =='HIVE'||value == 'SPARK')&&this.isShowPrincipal== true){
this.showPrincipal = false
}else{
this.showPrincipal = true
}
}
},
created () {
// Backfill
if (this.item.id) {
this._getEditDatasource()
}
return new Promise((resolve, reject) => {
this.store.dispatch('datasource/getKerberosStartupState').then(res => {
this.isShowPrincipal=res
}).catch(e => {
this.$message.error(e.msg || '')
reject(e)
})
})
},
mounted () {
},

View File

@ -116,5 +116,14 @@ export default {
reject(e)
})
})
},
getKerberosStartupState ({ state }, payload) {
return new Promise((resolve, reject) => {
io.get(`datasources/kerberos-startup-state`, payload, res => {
resolve(res.data)
}).catch(e => {
reject(e)
})
})
}
}

View File

@ -458,5 +458,6 @@ export default {
'Post Statement': 'Post Statement',
'Statement cannot be empty': 'Statement cannot be empty',
'Process Define Count': 'Process Define Count',
'Process Instance Running Count': 'Process Instance Running Count'
'Process Instance Running Count': 'Process Instance Running Count',
'Please enter Principal':'Please enter Principal'
}

View File

@ -460,4 +460,5 @@ export default {
'Process Define Count': '',
'Process Instance Running Count': '',
'Please select a queue': '',
'Please enter Principal':'Principal'
}

View File

@ -189,7 +189,7 @@ workersLock="/escheduler/lock/workers"
mastersFailover="/escheduler/lock/failover/masters"
# zk worker容错分布式锁
workersFailover="/escheduler/lock/failover/masters"
workersFailover="/escheduler/lock/failover/workers"
# zk master启动容错分布式锁
mastersStartupFailover="/escheduler/lock/failover/startup-masters"