├── .gitignore ├── src └── main │ ├── resources │ ├── db.properties │ ├── logback.xml │ ├── config.properties │ ├── script │ │ ├── create.sql │ │ └── init.sql │ └── logger-prod.xml │ └── java │ └── com │ └── qianmi │ ├── DeployException.java │ ├── Constants.java │ ├── service │ ├── BaseService.java │ ├── AliyunRegionService.java │ ├── AliyunEipService.java │ ├── AliyunImageService.java │ ├── ApiUtil.java │ └── AliyunInstanceService.java │ ├── models │ ├── BaseHelper.java │ ├── Region.java │ ├── UserInstanceHelper.java │ ├── RegionHelper.java │ ├── SystemType.java │ ├── SystemTypeHelper.java │ ├── UserInstance.java │ ├── SystemOSHelper.java │ ├── SystemOS.java │ └── DBUtil.java │ ├── Bootstrap.java │ ├── form │ ├── InstanceResult.java │ ├── InstanceStatus.java │ └── InstanceForm.java │ ├── proxy │ └── InstanceProxy.java │ └── controller │ └── WebController.java ├── README.md └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | *.iml 4 | -------------------------------------------------------------------------------- /src/main/resources/db.properties: -------------------------------------------------------------------------------- 1 | jdbc.url=jdbc:h2:./cloudeploy;INIT=runscript from 'classpath:/script/create.sql'\\;runscript from 'classpath:/script/init.sql' 2 | jdbc.user=sa 3 | jdbc.password= -------------------------------------------------------------------------------- /src/main/java/com/qianmi/DeployException.java: -------------------------------------------------------------------------------- 1 | package com.qianmi; 2 | 3 | /** 4 | * 自定义接口异常 5 | */ 6 | public class DeployException extends Exception { 7 | private String code; 8 | public DeployException(String code, String message) { 9 | super(message); 10 | this.code = code; 11 | } 12 | public String getCode() { 13 | return code; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/Constants.java: -------------------------------------------------------------------------------- 1 | package com.qianmi; 2 | 3 | /** 4 | * Created by li on 15/5/16. 5 | */ 6 | public class Constants { 7 | private Constants() { 8 | 9 | } 10 | 11 | /** 12 | * 阿里云平台 13 | */ 14 | public static final String PLATFORM_ALIYUN = "aliyun"; 15 | /** 16 | * UCLOUD平台 17 | */ 18 | public static final String PLATFORM_UCLOUD = "ucloud"; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/service/BaseService.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.service; 2 | 3 | import com.aliyun.api.AliyunClient; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | public class BaseService { 8 | protected final transient Logger logger = LoggerFactory.getLogger(getClass()); 9 | 10 | protected AliyunClient client; 11 | 12 | public BaseService() { 13 | this.client = ApiUtil.getInstance().getAliyunClient(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/models/BaseHelper.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.models; 2 | 3 | import org.apache.commons.dbutils.QueryRunner; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | public class BaseHelper { 8 | protected final transient Logger logger = LoggerFactory.getLogger(getClass()); 9 | 10 | protected QueryRunner runner = null; 11 | protected String tableName; 12 | 13 | public BaseHelper(String tableName) { 14 | this.tableName = tableName; 15 | this.runner = DBUtil.getInstance().getRunner(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/resources/config.properties: -------------------------------------------------------------------------------- 1 | aliyun.serverUrl=http://ecs.aliyuncs.com/ 2 | aliyun.accessKeyId=xxxxx 3 | aliyun.accessKeySecret=xxxxx 4 | platform.default=aliyun 5 | 6 | # instance default value 7 | aliyun.instance.RegionId=cn-hangzhou 8 | aliyun.instance.ImageId=centos6u5_64_20G_aliaegis_20150130.vhd 9 | aliyun.instance.InstanceType=ecs.t1.small 10 | aliyun.instance.SecurityGroupId=sg-237gsmw7r 11 | aliyun.instance.InternetChargeType=PayByTraffic 12 | aliyun.instance.InternetMaxBandwidthOut=1 13 | aliyun.instance.password=pwd123 14 | 15 | ucloud.instance.RegionId= 16 | -------------------------------------------------------------------------------- /src/main/resources/script/create.sql: -------------------------------------------------------------------------------- 1 | -- os 2 | CREATE TABLE system_os( 3 | name VARCHAR(50), 4 | `bit` VARCHAR(10), 5 | version VARCHAR(50), 6 | platform VARCHAR(50), 7 | image VARCHAR(255) 8 | ); 9 | 10 | CREATE TABLE system_type( 11 | cpu INT(10), 12 | memory INT(10), 13 | platform VARCHAR(50), 14 | code VARCHAR(255) 15 | ); 16 | 17 | CREATE TABLE user_instance ( 18 | user VARCHAR(100), 19 | instanceId VARCHAR(255), 20 | instanceIp VARCHAR(255), 21 | platform VARCHAR(50) 22 | ); 23 | 24 | CREATE TABLE region ( 25 | id VARCHAR(100), 26 | name VARCHAR(100), 27 | platform VARCHAR(50) 28 | ); 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/Bootstrap.java: -------------------------------------------------------------------------------- 1 | package com.qianmi; 2 | 3 | import com.qianmi.controller.WebController; 4 | import com.qianmi.models.DBUtil; 5 | import com.qianmi.service.ApiUtil; 6 | import org.h2.tools.Server; 7 | 8 | import java.io.IOException; 9 | import java.sql.SQLException; 10 | 11 | /** 12 | * 应用入口 13 | */ 14 | public class Bootstrap { 15 | 16 | public static void main(String[] args) throws NullPointerException, IOException, SQLException { 17 | 18 | // db console 19 | Server.createWebServer().start(); 20 | 21 | // web 22 | new WebController(); 23 | 24 | ApiUtil.getInstance(); 25 | DBUtil.getInstance(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/form/InstanceResult.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.form; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | 5 | /** 6 | * 实例创建结果 7 | */ 8 | public class InstanceResult { 9 | 10 | /** 11 | * 实例ID 12 | */ 13 | private String instanceId; 14 | 15 | /** 16 | * 实例IP 17 | */ 18 | private String ip; 19 | 20 | public InstanceResult(String instanceId, String ip) { 21 | this.instanceId = instanceId; 22 | this.ip = ip; 23 | } 24 | 25 | public String getInstanceId() { 26 | return instanceId; 27 | } 28 | 29 | public void setInstanceId(String instanceId) { 30 | this.instanceId = instanceId; 31 | } 32 | 33 | public String getIp() { 34 | return ip; 35 | } 36 | 37 | public void setIp(String ip) { 38 | this.ip = ip; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return new ToStringBuilder(this) 44 | .append("instanceId", instanceId) 45 | .append("ip", ip) 46 | .toString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/models/Region.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.models; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | 5 | /** 6 | * 区域 7 | */ 8 | public class Region { 9 | /** 10 | * 区域id 11 | */ 12 | private String id; 13 | /** 14 | * 区域名称 15 | */ 16 | private String name; 17 | /** 18 | * 平台名称 19 | */ 20 | private String platform; 21 | 22 | public String getId() { 23 | return id; 24 | } 25 | 26 | public void setId(String id) { 27 | this.id = id; 28 | } 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public void setName(String name) { 35 | this.name = name; 36 | } 37 | 38 | public String getPlatform() { 39 | return platform; 40 | } 41 | 42 | public void setPlatform(String platform) { 43 | this.platform = platform; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return new ToStringBuilder(this) 49 | .append("id", id) 50 | .append("name", name) 51 | .append("platform", platform) 52 | .toString(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/models/UserInstanceHelper.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.models; 2 | 3 | import org.apache.commons.dbutils.ResultSetHandler; 4 | import org.apache.commons.dbutils.handlers.BeanHandler; 5 | 6 | import java.sql.SQLException; 7 | 8 | /** 9 | * Created by li on 15/5/14. 10 | */ 11 | public class UserInstanceHelper extends BaseHelper { 12 | 13 | public UserInstanceHelper() { 14 | super("user_instance"); 15 | } 16 | 17 | public UserInstance findByUser(String user) { 18 | logger.debug("find {} By user:{}", tableName, user); 19 | ResultSetHandler h = new BeanHandler(UserInstance.class); 20 | UserInstance ui = null; 21 | try { 22 | ui = runner.query("SELECT * FROM " + tableName + " WHERE user=?", h, user); 23 | } catch (SQLException e) { 24 | logger.error("findByUser {} error:", tableName, e); 25 | } 26 | return ui; 27 | } 28 | 29 | public int add(UserInstance u) { 30 | logger.debug("add user:{}", u); 31 | try { 32 | return runner.update("INSERT INTO " + tableName + "(user, instanceId, instanceIp, platform) VALUES(?,?,?,?)", 33 | u.getUser(), u.getInstanceId(), u.getInstanceIp(), u.getPlatform()); 34 | } catch (SQLException e) { 35 | logger.error("insert {} error:", tableName, e); 36 | } 37 | return 0; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/service/AliyunRegionService.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.service; 2 | 3 | import com.aliyun.api.domain.Region; 4 | import com.aliyun.api.ecs.ecs20130110.request.DescribeRegionsRequest; 5 | import com.aliyun.api.ecs.ecs20130110.response.DescribeRegionsResponse; 6 | import com.qianmi.DeployException; 7 | import com.taobao.api.ApiException; 8 | import org.apache.commons.lang3.StringUtils; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by li on 15/5/15. 14 | */ 15 | public class AliyunRegionService extends BaseService { 16 | 17 | public List describeRegions() throws DeployException { 18 | DescribeRegionsRequest request = new DescribeRegionsRequest(); 19 | try { 20 | DescribeRegionsResponse response = client.execute(request); 21 | if (StringUtils.isNotEmpty(response.getErrorCode())) { 22 | logger.error("code:{}, msg:{}", response.getErrorCode(), response.getMessage()); 23 | throw new DeployException(response.getErrorCode(), response.getMessage()); 24 | } 25 | // return list.stream().configCache(Region::getLocalName).collect(Collectors.toList()); 26 | return response.getRegions(); 27 | } catch (ApiException e) { 28 | logger.error("code:{}, msg:{}", e.getErrCode(), e.getMessage(), e); 29 | throw new DeployException(e.getErrCode(), e.getErrMsg()); 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/models/RegionHelper.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.models; 2 | 3 | import org.apache.commons.dbutils.ResultSetHandler; 4 | import org.apache.commons.dbutils.handlers.BeanHandler; 5 | import org.apache.commons.dbutils.handlers.BeanListHandler; 6 | 7 | import java.sql.SQLException; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by li on 15/5/15. 12 | */ 13 | public class RegionHelper extends BaseHelper { 14 | public RegionHelper() { 15 | super("region"); 16 | } 17 | 18 | public List all() { 19 | ResultSetHandler> h = new BeanListHandler(Region.class); 20 | List regions = null; 21 | try { 22 | regions = runner.query("SELECT * FROM " + tableName, h); 23 | } catch (SQLException e) { 24 | logger.error("select all {} error:", tableName, e); 25 | } 26 | return regions; 27 | } 28 | 29 | public Region findOne(String id, String platform) { 30 | logger.debug("find {} By id:{}, platform:{}", tableName, id, platform); 31 | ResultSetHandler h = new BeanHandler(Region.class); 32 | Region region = null; 33 | try { 34 | region = runner.query("SELECT * FROM " + tableName + " WHERE id=? AND platform=?", 35 | h, id, platform); 36 | } catch (SQLException e) { 37 | logger.error("find {} error:", tableName, e); 38 | } 39 | return region; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/models/SystemType.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.models; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | 5 | /** 6 | * 平台机器配置类型 7 | */ 8 | public class SystemType implements java.io.Serializable { 9 | /** 10 | * cpu个数 11 | */ 12 | private int cpu; 13 | /** 14 | * 内存大小 15 | */ 16 | private int memory; 17 | 18 | /** 19 | * 平台(aliyun,ucloud) 20 | */ 21 | private String platform; 22 | 23 | /** 24 | * 规格类型代码 25 | */ 26 | private String code; 27 | 28 | public int getCpu() { 29 | return cpu; 30 | } 31 | 32 | public void setCpu(int cpu) { 33 | this.cpu = cpu; 34 | } 35 | 36 | public int getMemory() { 37 | return memory; 38 | } 39 | 40 | public void setMemory(int memory) { 41 | this.memory = memory; 42 | } 43 | 44 | public String getPlatform() { 45 | return platform; 46 | } 47 | 48 | public void setPlatform(String platform) { 49 | this.platform = platform; 50 | } 51 | 52 | public String getCode() { 53 | return code; 54 | } 55 | 56 | public void setCode(String code) { 57 | this.code = code; 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return new ToStringBuilder(this) 63 | .append("cpu", cpu) 64 | .append("memory", memory) 65 | .append("platform", platform) 66 | .append("code", code) 67 | .toString(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/service/AliyunEipService.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.service; 2 | 3 | import com.aliyun.api.ecs.ecs20130110.request.AllocatePublicIpAddressRequest; 4 | import com.aliyun.api.ecs.ecs20130110.response.AllocatePublicIpAddressResponse; 5 | import com.qianmi.DeployException; 6 | import com.taobao.api.ApiException; 7 | import org.apache.commons.lang3.StringUtils; 8 | 9 | /** 10 | * 公网ip 11 | */ 12 | public class AliyunEipService extends BaseService { 13 | 14 | /** 15 | * 给实例分配IP 16 | * @param instanceId 实例ID 17 | * @return 分配的IP 18 | * @throws DeployException 19 | */ 20 | public String allocatePublicIpAddress(String instanceId) throws DeployException { 21 | logger.debug("allocate ip to instanceId:{}", instanceId); 22 | AllocatePublicIpAddressRequest request = new AllocatePublicIpAddressRequest(); 23 | request.setInstanceId(instanceId); 24 | try { 25 | AllocatePublicIpAddressResponse response = client.execute(request); 26 | if (StringUtils.isNotEmpty(response.getErrorCode())) { 27 | logger.error("code:{}, msg:{}", response.getErrorCode(), response.getMessage()); 28 | throw new DeployException(response.getErrorCode(), response.getMessage()); 29 | } 30 | return response.getIpAddress(); 31 | } catch (ApiException e) { 32 | logger.error("code:{}, msg:{}", e.getErrCode(), e.getMessage(), e); 33 | throw new DeployException(e.getErrCode(), e.getErrMsg()); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/models/SystemTypeHelper.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.models; 2 | 3 | import org.apache.commons.dbutils.ResultSetHandler; 4 | import org.apache.commons.dbutils.handlers.BeanHandler; 5 | import org.apache.commons.dbutils.handlers.BeanListHandler; 6 | 7 | import java.sql.SQLException; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by li on 15/5/14. 12 | */ 13 | public class SystemTypeHelper extends BaseHelper { 14 | 15 | public SystemTypeHelper() { 16 | super("system_type"); 17 | } 18 | 19 | public List all() { 20 | ResultSetHandler> hos = new BeanListHandler(SystemType.class); 21 | List types = null; 22 | try { 23 | types = runner.query("SELECT * FROM " + tableName, hos); 24 | } catch (SQLException e) { 25 | logger.error("select all {} error:", tableName, e); 26 | } 27 | return types; 28 | } 29 | 30 | public SystemType findOne(int cpu, int memory, String platform) { 31 | logger.debug("find {} By cpu:{}, memory:{}, platform:{}", tableName, cpu, memory, platform); 32 | ResultSetHandler h = new BeanHandler(SystemType.class); 33 | SystemType type = null; 34 | try { 35 | type = runner.query( 36 | "SELECT * FROM " + tableName + " WHERE cpu=? AND memory=? AND platform=?", 37 | h, cpu, memory, platform); 38 | } catch (SQLException e) { 39 | logger.error("find {} error:", tableName, e); 40 | } 41 | return type; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/models/UserInstance.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.models; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | 5 | /** 6 | * 用户实例关系 7 | */ 8 | public class UserInstance { 9 | /** 10 | * 用户标示 11 | */ 12 | private String user; 13 | /** 14 | * 实例ID 15 | */ 16 | private String instanceId; 17 | /** 18 | * 实例IP 19 | */ 20 | private String instanceIp; 21 | /** 22 | * 平台名称 23 | */ 24 | private String platform; 25 | 26 | public String getUser() { 27 | return user; 28 | } 29 | 30 | public void setUser(String user) { 31 | this.user = user; 32 | } 33 | 34 | public String getInstanceId() { 35 | return instanceId; 36 | } 37 | 38 | public void setInstanceId(String instanceId) { 39 | this.instanceId = instanceId; 40 | } 41 | 42 | public String getInstanceIp() { 43 | return instanceIp; 44 | } 45 | 46 | public void setInstanceIp(String instanceIp) { 47 | this.instanceIp = instanceIp; 48 | } 49 | 50 | public String getPlatform() { 51 | return platform; 52 | } 53 | 54 | public void setPlatform(String platform) { 55 | this.platform = platform; 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | return new ToStringBuilder(this) 61 | .append("user", user) 62 | .append("instanceId", instanceId) 63 | .append("instanceIp", instanceIp) 64 | .append("platform", platform) 65 | .toString(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/service/AliyunImageService.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.service; 2 | 3 | import com.aliyun.api.domain.Image; 4 | import com.aliyun.api.ecs.ecs20130110.request.DescribeImagesRequest; 5 | import com.aliyun.api.ecs.ecs20130110.response.DescribeImagesResponse; 6 | import com.qianmi.DeployException; 7 | import com.taobao.api.ApiException; 8 | import org.apache.commons.lang3.StringUtils; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by li on 15/5/14. 14 | */ 15 | public class AliyunImageService extends BaseService { 16 | 17 | /** 18 | * 查询可用镜像列表 19 | * @param regionId 区域ID 20 | * @throws DeployException 21 | */ 22 | public List describeImages(String regionId) throws DeployException { 23 | logger.debug("list images By regionId:{}", regionId); 24 | DescribeImagesRequest request = new DescribeImagesRequest(); 25 | request.setRegionId(regionId); 26 | request.setPageSize(50L); 27 | try { 28 | DescribeImagesResponse response = client.execute(request); 29 | if (StringUtils.isNotEmpty(response.getErrorCode())) { 30 | logger.error("code:{}, msg:{}", response.getErrorCode(), response.getMessage()); 31 | throw new DeployException(response.getErrorCode(), response.getMessage()); 32 | } 33 | return response.getImages(); 34 | } catch (ApiException e) { 35 | logger.error("code:{}, msg:{}", e.getErrCode(), e.getMessage(), e); 36 | throw new DeployException(e.getErrCode(), e.getErrMsg()); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/models/SystemOSHelper.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.models; 2 | 3 | import org.apache.commons.dbutils.ResultSetHandler; 4 | import org.apache.commons.dbutils.handlers.BeanHandler; 5 | import org.apache.commons.dbutils.handlers.BeanListHandler; 6 | 7 | import java.sql.SQLException; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by li on 15/5/14. 12 | */ 13 | public class SystemOSHelper extends BaseHelper { 14 | 15 | public SystemOSHelper() { 16 | super("system_os"); 17 | } 18 | 19 | public List all() { 20 | ResultSetHandler> h = new BeanListHandler(SystemOS.class); 21 | List oses = null; 22 | try { 23 | oses = runner.query("SELECT * FROM " + tableName, h); 24 | } catch (SQLException e) { 25 | logger.error("select all {} error:", tableName, e); 26 | } 27 | return oses; 28 | } 29 | 30 | public SystemOS findOne(String name, String bit, String version, String platform) { 31 | logger.debug("find {} By name:{}, bit:{}, version:{}, platform:{}", tableName, name, bit, version, platform); 32 | ResultSetHandler h = new BeanHandler(SystemOS.class); 33 | SystemOS os = null; 34 | try { 35 | os = runner.query( 36 | "SELECT * FROM " + tableName + " WHERE name=? AND bit=? AND version=? AND platform=?", 37 | h, name, bit, version, platform); 38 | } catch (SQLException e) { 39 | logger.error("find {} error:", tableName, e); 40 | } 41 | return os; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/models/SystemOS.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.models; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | 5 | /** 6 | * 平台操作系统配置 7 | */ 8 | public class SystemOS implements java.io.Serializable { 9 | /** 10 | * 操作系统 11 | * CentOS 12 | */ 13 | private String name; 14 | /** 15 | * 操作系统位数(64,32) 16 | * 64 17 | */ 18 | private String bit; 19 | /** 20 | * 操作系统版本(14.04) 21 | */ 22 | private String version; 23 | 24 | /** 25 | * 平台(aliyun,ucloud) 26 | */ 27 | private String platform; 28 | 29 | /** 30 | * 平台的image名称 31 | */ 32 | private String image; 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | 42 | public String getBit() { 43 | return bit; 44 | } 45 | 46 | public void setBit(String bit) { 47 | this.bit = bit; 48 | } 49 | 50 | public String getVersion() { 51 | return version; 52 | } 53 | 54 | public void setVersion(String version) { 55 | this.version = version; 56 | } 57 | 58 | public String getPlatform() { 59 | return platform; 60 | } 61 | 62 | public void setPlatform(String platform) { 63 | this.platform = platform; 64 | } 65 | 66 | public String getImage() { 67 | return image; 68 | } 69 | 70 | public void setImage(String image) { 71 | this.image = image; 72 | } 73 | 74 | @Override 75 | public String toString() { 76 | return new ToStringBuilder(this) 77 | .append("name", name) 78 | .append("bit", bit) 79 | .append("version", version) 80 | .append("platform", platform) 81 | .append("image", image) 82 | .toString(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/form/InstanceStatus.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.form; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | 5 | /** 6 | * 实例查询结果 7 | */ 8 | public class InstanceStatus { 9 | /** 10 | * 实例ID 11 | */ 12 | private String instanceId; 13 | /** 14 | * 实例状态 15 | * Running 16 | * Stopped 17 | * 18 | */ 19 | private String status; 20 | 21 | /** 22 | * 公网ip 23 | */ 24 | private String publicIp; 25 | 26 | /** 27 | * 内网ip 28 | */ 29 | private String innerIp; 30 | 31 | public InstanceStatus(String instanceId, String status, String publicIp, String innerIp) { 32 | this.instanceId = instanceId; 33 | this.status = status; 34 | this.publicIp = publicIp; 35 | this.innerIp = innerIp; 36 | } 37 | 38 | public String getInstanceId() { 39 | return instanceId; 40 | } 41 | 42 | public void setInstanceId(String instanceId) { 43 | this.instanceId = instanceId; 44 | } 45 | 46 | public String getStatus() { 47 | return status; 48 | } 49 | 50 | public void setStatus(String status) { 51 | this.status = status; 52 | } 53 | 54 | public String getPublicIp() { 55 | return publicIp; 56 | } 57 | 58 | public void setPublicIp(String publicIp) { 59 | this.publicIp = publicIp; 60 | } 61 | 62 | public String getInnerIp() { 63 | return innerIp; 64 | } 65 | 66 | public void setInnerIp(String innerIp) { 67 | this.innerIp = innerIp; 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return new ToStringBuilder(this) 73 | .append("instanceId", instanceId) 74 | .append("status", status) 75 | .append("publicIp", publicIp) 76 | .append("innerIp", innerIp) 77 | .toString(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/resources/logger-prod.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | WARN 8 | 9 | ${path}/logs/error.log 10 | 11 | ${path}/logs/error-%d{yyyy-MM-dd}.gz 12 | 10 13 | 14 | 15 | %d{yyyy-MM-dd HH:mm:ss} - %-5level - from %logger in %thread %n%message%n%xException%n 16 | 17 | 18 | 19 | 20 | ${path}/logs/access.log 21 | 22 | ${path}/logs/access-%i.log 23 | 1 24 | 10 25 | 26 | 27 | 50MB 28 | 29 | 30 | %d{MM-dd HH:mm:ss.SSS} - %-5level - from %logger in %thread %msg%n 31 | true 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/main/resources/script/init.sql: -------------------------------------------------------------------------------- 1 | 2 | -- aliyun 3 | INSERT INTO system_os(name, bit, version, platform, image) VALUES ('centos','64','7.0','aliyun','centos7u0_64_20G_aliaegis_20150130.vhd'); 4 | INSERT INTO system_os(name, bit, version, platform, image) VALUES ('centos','64','6.5','aliyun','centos6u5_64_20G_aliaegis_20150130.vhd'); 5 | INSERT INTO system_os(name, bit, version, platform, image) VALUES ('centos','32','6.5','aliyun','centos6u5_32_20G_aliaegis_20150130.vhd'); 6 | INSERT INTO system_os(name, bit, version, platform, image) VALUES ('centos','64','5.8','aliyun','centos5u8_64_20G_aliaegis_20150130.vhd'); 7 | INSERT INTO system_os(name, bit, version, platform, image) VALUES ('centos','64','5.10','aliyun','centos5u10_64_20G_aliaegis_20150130.vhd'); 8 | INSERT INTO system_os(name, bit, version, platform, image) VALUES ('centos','32','5.10','aliyun','centos5u10_32_20G_aliaegis_20150130.vhd'); 9 | 10 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (1,1,'aliyun','ecs.t1.small'); 11 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (1,2,'aliyun','ecs.s1.small'); 12 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (1,4,'aliyun','ecs.s1.medium'); 13 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (1,8,'aliyun','ecs.s1.large'); 14 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (2,2,'aliyun','ecs.s2.small'); 15 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (2,4,'aliyun','ecs.s2.large'); 16 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (2,8,'aliyun','ecs.s2.xlarge'); 17 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (2,16,'aliyun','ecs.s2.2xlarge'); 18 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (4,4,'aliyun','ecs.s3.medium'); 19 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (4,8,'aliyun','ecs.s3.large'); 20 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (4,16,'aliyun','ecs.m1.medium'); 21 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (4,32,'aliyun','ecs.m2.medium'); 22 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (8,32,'aliyun','ecs.m1.xlarge'); 23 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (8,8,'aliyun','ecs.c1.small'); 24 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (8,16,'aliyun','ecs.c1.large'); 25 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (16,16,'aliyun','ecs.c2.medium'); 26 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (16,32,'aliyun','ecs.c2.large'); 27 | INSERT INTO system_type(cpu, memory, platform, code) VALUES (16,64,'aliyun','ecs.c2.xlarge'); 28 | 29 | INSERT INTO region(id, name, platform) VALUES ('cn-shenzhen','深圳', 'aliyun'); 30 | INSERT INTO region(id, name, platform) VALUES ('cn-qingdao','青岛', 'aliyun'); 31 | INSERT INTO region(id, name, platform) VALUES ('cn-beijing','北京', 'aliyun'); 32 | INSERT INTO region(id, name, platform) VALUES ('cn-hongkong','香港', 'aliyun'); 33 | INSERT INTO region(id, name, platform) VALUES ('cn-hangzhou','杭州', 'aliyun'); 34 | INSERT INTO region(id, name, platform) VALUES ('us-west-1','美国硅谷', 'aliyun'); 35 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/models/DBUtil.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.models; 2 | 3 | import org.apache.commons.dbutils.QueryRunner; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.h2.jdbcx.JdbcConnectionPool; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.io.File; 10 | import java.io.FileInputStream; 11 | import java.io.IOException; 12 | import java.sql.SQLException; 13 | import java.util.Properties; 14 | 15 | /** 16 | * 数据库操作实例 17 | */ 18 | public class DBUtil { 19 | 20 | private final transient Logger logger = LoggerFactory.getLogger(getClass()); 21 | 22 | private static DBUtil instance = null; 23 | 24 | private JdbcConnectionPool connectionPool = null; 25 | 26 | private DBUtil() throws IOException { 27 | final Properties properties = new Properties(); 28 | String dbFile = System.getProperty("db.file"); 29 | if (dbFile != null) { 30 | properties.load(new FileInputStream(new File(dbFile))); 31 | } else { 32 | properties.load(Thread.currentThread().getClass().getResourceAsStream("/db.properties")); 33 | } 34 | 35 | String url = properties.getProperty("jdbc.url"); 36 | String initSql = System.getProperty("init.sql"); 37 | 38 | logger.debug("jdbc.url:{}", url); 39 | logger.debug("init.sql:{}", initSql); 40 | 41 | if (initSql == null || !initSql.toLowerCase().equals("true")) { 42 | url = url.substring(0, url.toLowerCase().indexOf("init")); 43 | } 44 | logger.debug("convert.jdbc.url:{}", url); 45 | 46 | this.connectionPool = JdbcConnectionPool.create( 47 | url, 48 | properties.getProperty("jdbc.user"), 49 | properties.getProperty("jdbc.password")); 50 | } 51 | 52 | public static synchronized DBUtil getInstance() { 53 | if (instance == null) { 54 | try { 55 | instance = new DBUtil(); 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | return instance; 61 | } 62 | 63 | /** 64 | * H2内存数据库 65 | * @return 数据库链接,操作对象 66 | * @throws SQLException 67 | */ 68 | public QueryRunner getRunner() { 69 | return new QueryRunner(connectionPool); 70 | } 71 | 72 | public static void main(String[] args) throws SQLException { 73 | SystemOSHelper systemOSHelper = new SystemOSHelper(); 74 | // systemOSHelper.all().forEach(o -> System.out.println(o)); 75 | 76 | SystemOS os = systemOSHelper.findOne(null, null, "7.0", "aliyun"); 77 | System.out.println(os); 78 | // 79 | // SystemTypeHelper systemTypeHelper = new SystemTypeHelper(); 80 | // SystemType type = systemTypeHelper.findOne(1, 1, "aliyun"); 81 | // System.out.println(type); 82 | // 83 | // UserInstanceHelper uHelper = new UserInstanceHelper(); 84 | // UserInstance ui = new UserInstance(); 85 | // ui.setUser("zhangsan123"); 86 | // ui.setInstanceId("fsdfsdf13323"); 87 | // ui.setInstanceIp("123.902.22.222"); 88 | // int result = uHelper.add(ui); 89 | // System.out.println("insert.result=" + result); 90 | //// systemTypeHelper.all().forEach(t -> System.out.println(t)); 91 | // 92 | // RegionHelper regionHelper = new RegionHelper(); 93 | // regionHelper.all().forEach(r -> System.out.println("r.id=" + r.getId())); 94 | // System.out.println(regionHelper.findOne("cn-qingdao", "a2liyun") == null); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > Cloudeploy基于bugatti理念的极简云部署系统。 2 | 3 | 简介 4 | --- 5 | Cluodeploy是为解决客户私有云部署与监控,应用维护等问题统一处理平台。使用Cloudeploy可以快速创建主流云实例,安装等各种简化发布工作。 6 | 7 | 特性 8 | --- 9 | - 支持多平台创建实例 10 | - 阿里云 11 | - Ucloud 12 | - 极简接口,仅有3个RESTful API 13 | - 内嵌数据库 14 | - 可配置化 15 | - 小巧方便,仅8M大小的jar文件 16 | 17 | 安装 18 | --- 19 | 1. Oracle官方下载最新的[JDK8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) 20 | 2. [版本发布页](https://github.com/QianmiOpen/cloudeploy/releases)下载最新的 **cloudeploy-1.0-RELEASE.jar** 21 | 3. 访问 **http://[hostname]:[port]/**在你的浏览器中,默认port:4567 22 | 23 | 默认是直接访问(没做任何限制),为了安全起见请配置iptable策略。 24 | 25 | 然后你用`java -jar cloudeploy-1.0-RELEASE.jar`即可启动应用。如果是首次启动请增加`-Dinit.sql=true`参数用于初始化数据库脚本,下面一些参数做更多自定义配置: 26 | - -Dconfig.file=[默认配置文件] 27 | - -Ddb.file=[数据库连接] 28 | - -Dlogback.configurationFile=[logback配置文件] 29 | 30 | Cloudeploy的升级只需替换cloudeploy.jar。所有的数据存储在./cloudeploy.mv.db,所以你想备份cloudepoy数据,拷贝一份该文件即可。 31 | 32 | 另外./cloudeploy.mv.db默认数据路径和初始化脚本是可以自定义的,在`-Ddb.file=[数据库连接]`中设置`jdbc.url=`参数值, 33 | ##### Database URLs 34 | *Embedded* 35 | 36 | `jdbc:h2:~/test` 'test' in the user home directory 37 | `jdbc:h2:/data/test` 'test' in the directory /data 38 | `jdbc:h2:./test` in the current(!) working directory 39 | 更多数据库知识请参考[H2 Database官方文档](http://www.h2database.com/)。 40 | 41 | 访问数据库:http://127.0.0.1:8082/ 42 | 43 | 数据库文件./cloudeploy.mv.db应该妥善保管 44 | 45 | 接口 46 | --- 47 | **注意:** 48 | - 返回内容为json格式,通过响应状态码判断是否成功 49 | - 默认值参考相关表位于`/resources/script/init.sql` 50 | - 所有请求编码为UTF-8 51 | 52 | ### 创建新主机 53 | ```http 54 | POST http://localhost:4567/host/new 55 | ``` 56 | 参数 | 意义 | 备注 57 | :--------------------------- | :--------------- | :---------------- 58 | user | 客户标示 | 必填 59 | platform | 接口平台 | 默认为aliyun,还支持UCloud 60 | region | 实例创建所在区域 | 默认为cn-hangzhou,更多参考region表id字段 61 | osName | 操作系统名称 | 默认为CentOS,更多参考system_os表name字段 62 | osBit | 操作系统位数 | 默认为64,更多参考system_os表bit字段 63 | osVersion | 操作系统版本 | 默认为6.5,更多参考system_os表version字段 64 | cpu | cpu数量 | 默认为1,更多参考system_type表cpu字段 65 | memory | 内存大小 | 默认为1,更多参考system_type表memory字段 66 | password | 主机root密码 | 默认为pwd123 67 | internetChargeType | 网络类型 | 默认为流量计费PayByTraffic,还有固定带宽计费PayByBandwidth 68 | internetMaxBandwidthOut | 网络出口带宽 | 默认为1,即为1M 69 | 70 | *成功返回: status = 200* 71 | ```json 72 | { 73 | "instanceId":"xxx" # 实例ID, 74 | "ip":"xxx" # 实例IP 75 | } 76 | ``` 77 | *参数错误:status = 400* 78 | ```json 79 | { 80 | "field1": "error_msg", 81 | "field2": "error_msg" 82 | ... 83 | } 84 | ``` 85 | *系统异常:status = 500* 86 | ```json 87 | { 88 | "code": "xxx", 89 | "message": "xxx" 90 | } 91 | ``` 92 | ### 查询主机状态 93 | ```http 94 | GET http://localhost:4567/host/status 95 | ``` 96 | 参数 | 意义 | 备注 97 | :----------- | :------------ | :---------------- 98 | instanceId | 实例(主机)ID | 必填,创建新主机时返回 99 | 100 | *成功返回: status = 200*,实例状态包括:运行中`Running` 启动中`Starting` 停止`Stopped` 101 | ```json 102 | { 103 | "instanceId":"xxx", 104 | "status":"xxx" 105 | } 106 | 107 | ``` 108 | *参数错误:status = 400* 109 | ```json 110 | { 111 | "instanceId": "param is not empty" 112 | } 113 | ``` 114 | *系统异常:status = 500* 115 | ```json 116 | { 117 | "code": "xxx", 118 | "message": "xxx" 119 | } 120 | ``` 121 | ### 执行ansible命令 122 | ```http 123 | POST http://localhost:4567/ansible/send 124 | Content-Type:application/x-www-form-urlencoded 125 | ``` 126 | 参数 | 意义 | 备注 127 | :----------- | :------------ | :---------------- 128 | command | 命令行内容 | 必填,需要Base64.encode("command", "UTF-8")编码 129 | 130 | *成功返回: status = 200* 131 | ```json 132 | { 133 | "result":"xxx", 134 | } 135 | ``` 136 | *参数错误:status = 400* 137 | ```json 138 | { 139 | "command": "param is not empty" 140 | } 141 | ``` 142 | *系统异常:status = 500* 143 | ```json 144 | { 145 | "error": "xxx" 146 | } 147 | ``` 148 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/form/InstanceForm.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.form; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | 5 | /** 6 | * 实例接口参数 7 | */ 8 | public class InstanceForm { 9 | 10 | /** 11 | * 用户 12 | */ 13 | private String user; 14 | /** 15 | * 平台 16 | * aliyun,ucloud 17 | */ 18 | private String platform; 19 | /** 20 | * 区域 21 | */ 22 | private String region; 23 | /** 24 | * 操作系统名称 25 | * centos 26 | */ 27 | private String osName; 28 | /** 29 | * 操作系统位数(64,32) 30 | * 64 31 | */ 32 | private String osBit; 33 | /** 34 | * 操作系统版本(6.5) 35 | */ 36 | private String osVersion; 37 | /** 38 | * cpu数量 39 | * 1,2,4,8,16 40 | */ 41 | private String cpu; 42 | /** 43 | * 内存大小 44 | * 1,2,4,8,16,32,64 45 | */ 46 | private String memory; 47 | /** 48 | * 机器密码 49 | * pwd123 50 | */ 51 | private String password; 52 | /** 53 | * 计费方式 54 | * 按流量计费 55 | */ 56 | private String internetChargeType; 57 | /** 58 | * 出口宽带大小 59 | * 1~200,默认1M,最大支持到20M. 60 | */ 61 | private String internetMaxBandwidthOut; 62 | 63 | public String getUser() { 64 | return user; 65 | } 66 | 67 | public void setUser(String user) { 68 | this.user = user; 69 | } 70 | 71 | public String getPlatform() { 72 | return platform; 73 | } 74 | 75 | public void setPlatform(String platform) { 76 | this.platform = platform; 77 | } 78 | 79 | public String getRegion() { 80 | return region; 81 | } 82 | 83 | public void setRegion(String region) { 84 | this.region = region; 85 | } 86 | 87 | public String getOsName() { 88 | return osName; 89 | } 90 | 91 | public void setOsName(String osName) { 92 | this.osName = osName; 93 | } 94 | 95 | public String getOsBit() { 96 | return osBit; 97 | } 98 | 99 | public void setOsBit(String osBit) { 100 | this.osBit = osBit; 101 | } 102 | 103 | public String getOsVersion() { 104 | return osVersion; 105 | } 106 | 107 | public void setOsVersion(String osVersion) { 108 | this.osVersion = osVersion; 109 | } 110 | 111 | public String getCpu() { 112 | return cpu; 113 | } 114 | 115 | public void setCpu(String cpu) { 116 | this.cpu = cpu; 117 | } 118 | 119 | public String getMemory() { 120 | return memory; 121 | } 122 | 123 | public void setMemory(String memory) { 124 | this.memory = memory; 125 | } 126 | 127 | public String getPassword() { 128 | return password; 129 | } 130 | 131 | public void setPassword(String password) { 132 | this.password = password; 133 | } 134 | 135 | public String getInternetChargeType() { 136 | return internetChargeType; 137 | } 138 | 139 | public void setInternetChargeType(String internetChargeType) { 140 | this.internetChargeType = internetChargeType; 141 | } 142 | 143 | public String getInternetMaxBandwidthOut() { 144 | return internetMaxBandwidthOut; 145 | } 146 | 147 | public void setInternetMaxBandwidthOut(String internetMaxBandwidthOut) { 148 | this.internetMaxBandwidthOut = internetMaxBandwidthOut; 149 | } 150 | 151 | @Override 152 | public String toString() { 153 | return new ToStringBuilder(this) 154 | .append("user", user) 155 | .append("platform", platform) 156 | .append("region", region) 157 | .append("osName", osName) 158 | .append("osBit", osBit) 159 | .append("osVersion", osVersion) 160 | .append("cpu", cpu) 161 | .append("memory", memory) 162 | .append("password", password) 163 | .append("internetChargeType", internetChargeType) 164 | .append("internetMaxBandwidthOut", internetMaxBandwidthOut) 165 | .toString(); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/proxy/InstanceProxy.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.proxy; 2 | 3 | import com.aliyun.api.ecs.ecs20140526.request.CreateInstanceRequest; 4 | import com.qianmi.Constants; 5 | import com.qianmi.DeployException; 6 | import com.qianmi.form.InstanceForm; 7 | import com.qianmi.form.InstanceResult; 8 | import com.qianmi.models.SystemOS; 9 | import com.qianmi.models.SystemOSHelper; 10 | import com.qianmi.models.SystemType; 11 | import com.qianmi.models.SystemTypeHelper; 12 | import com.qianmi.service.AliyunEipService; 13 | import com.qianmi.service.AliyunInstanceService; 14 | import com.qianmi.service.ApiUtil; 15 | import org.apache.commons.lang3.StringUtils; 16 | import org.apache.commons.lang3.builder.ReflectionToStringBuilder; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | /** 21 | * 实例代理 22 | */ 23 | public class InstanceProxy { 24 | 25 | private final transient Logger logger = LoggerFactory.getLogger(InstanceProxy.class); 26 | 27 | /** 28 | * 新建实例(初始化机器,分配ip,启动) 29 | * @return 实例ID,IP 30 | */ 31 | public InstanceResult newInstance(InstanceForm instanceForm) throws DeployException { 32 | instanceForm.setPlatform(StringUtils.defaultString(instanceForm.getPlatform(), 33 | ApiUtil.getInstance().getConfigCache().get("platform.default"))); 34 | 35 | if (StringUtils.equalsIgnoreCase(Constants.PLATFORM_ALIYUN, instanceForm.getPlatform())) { 36 | CreateInstanceRequest request = new CreateInstanceRequest(); 37 | logger.info("platform:{}", Constants.PLATFORM_ALIYUN); 38 | 39 | // image 40 | SystemOS os = new SystemOSHelper().findOne(instanceForm.getOsName(), instanceForm.getOsBit(), 41 | instanceForm.getOsVersion(), instanceForm.getPlatform()); 42 | logger.debug("osName:{}, osBit:{}, osVersion:{}, platform:{}", 43 | instanceForm.getOsName(), instanceForm.getOsBit(), instanceForm.getOsVersion(), instanceForm.getPlatform()); 44 | if (os != null) { 45 | logger.debug("systemOs:{}", os); 46 | request.setImageId(os.getImage()); 47 | } 48 | 49 | // instanceType 50 | if (StringUtils.isNumeric(instanceForm.getCpu()) && StringUtils.isNumeric(instanceForm.getMemory())) { 51 | logger.debug("cpu.number:{}, memory.number:{}", instanceForm.getCpu(), instanceForm.getMemory()); 52 | SystemType type = new SystemTypeHelper().findOne( 53 | Integer.parseInt(instanceForm.getCpu()), Integer.parseInt(instanceForm.getMemory()), instanceForm.getPlatform()); 54 | if (type != null) { 55 | logger.debug("systemType:{}", type); 56 | request.setInstanceType(type.getCode()); 57 | } 58 | } 59 | 60 | request.setRegionId(instanceForm.getRegion()); 61 | request.setInternetChargeType(instanceForm.getInternetChargeType()); 62 | request.setPassword(instanceForm.getPassword()); 63 | if (StringUtils.isNumeric(instanceForm.getInternetMaxBandwidthOut())) { 64 | request.setInternetMaxBandwidthOut(Long.valueOf(instanceForm.getInternetMaxBandwidthOut())); 65 | } 66 | 67 | logger.debug("requestParam:{}", ReflectionToStringBuilder.toString(request)); 68 | 69 | // 创建实例 70 | AliyunInstanceService instanceService = new AliyunInstanceService(); 71 | String instanceId = instanceService.createInstance(request); 72 | logger.info("create instance({}) success", instanceId); 73 | 74 | // 分配公网IP 75 | AliyunEipService eipService = new AliyunEipService(); 76 | String ip = eipService.allocatePublicIpAddress(instanceId); 77 | logger.info("allocate ip:{} to instance", ip); 78 | 79 | // 启动实例 80 | instanceService.startInstance(instanceId); 81 | logger.info("instance start..."); 82 | 83 | return new InstanceResult(instanceId, ip); 84 | } 85 | // else if { } 86 | return new InstanceResult(Constants.PLATFORM_UCLOUD, "暂未启动该平台api"); 87 | } 88 | 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/service/ApiUtil.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.service; 2 | 3 | import com.aliyun.api.AliyunClient; 4 | import com.aliyun.api.DefaultAliyunClient; 5 | import com.aliyun.api.ecs.ecs20140526.request.CreateInstanceRequest; 6 | import com.qianmi.DeployException; 7 | 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.IOException; 11 | import java.util.Map; 12 | import java.util.Properties; 13 | import java.util.concurrent.ConcurrentHashMap; 14 | 15 | /** 16 | * cloud api连接配置 17 | */ 18 | public class ApiUtil { 19 | 20 | private static ApiUtil instance = null; 21 | private static AliyunClient aliyunClient = null; 22 | private static final Map configCache = new ConcurrentHashMap<>(); 23 | 24 | private ApiUtil() throws IOException { 25 | final Properties properties = new Properties(); 26 | String configFile = System.getProperty("config.file"); 27 | if (configFile != null) { 28 | properties.load(new FileInputStream(new File(configFile))); 29 | } else { 30 | properties.load(Thread.currentThread().getClass().getResourceAsStream("/config.properties")); 31 | } 32 | // init config cache 33 | properties.stringPropertyNames().forEach(key -> configCache.put(key, properties.getProperty(key))); 34 | 35 | // aliyun client 36 | String serverUrl = configCache.get("aliyun.serverUrl"); 37 | String accessKeyId = configCache.get("aliyun.accessKeyId"); 38 | String accessKeySecret = configCache.get("aliyun.accessKeySecret"); 39 | aliyunClient = new DefaultAliyunClient(serverUrl, accessKeyId, accessKeySecret); 40 | 41 | // ucloud client 42 | } 43 | 44 | public static synchronized ApiUtil getInstance() { 45 | if (instance == null) { 46 | try { 47 | instance = new ApiUtil(); 48 | } catch (IOException e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | return instance; 53 | } 54 | 55 | public AliyunClient getAliyunClient() { 56 | return aliyunClient; 57 | } 58 | 59 | public Map getConfigCache() { 60 | return configCache; 61 | } 62 | 63 | public static void main(String[] args) { 64 | 65 | AliyunInstanceService aliyunInstanceService = new AliyunInstanceService(); 66 | CreateInstanceRequest request = new CreateInstanceRequest(); 67 | request.setImageId("centos6u5_64_20G_aliaegis_20150130.vhd"); 68 | request.setInstanceType("ecs.t1.small"); 69 | request.setRegionId("cn-hangzhou"); 70 | request.setSecurityGroupId("sg-237gsmw7r"); 71 | request.setInternetChargeType("PayByTraffic"); // 按量付费 72 | request.setInternetMaxBandwidthOut(1L); 73 | 74 | // try { 75 | // String instanceId = aliyunInstanceService.createInstance(request); 76 | // 77 | // // 分配公网IP 78 | // AliyunEipService eipService = new AliyunEipService(); 79 | // String ip = eipService.allocatePublicIpAddress(instanceId); 80 | // } catch (DeployException e) { 81 | // e.printStackTrace(); 82 | // } 83 | 84 | // 分配公网IP 85 | // AliyunEipService eipService = new AliyunEipService(); 86 | // try { 87 | // String ip = eipService.allocatePublicIpAddress(""); 88 | // } catch (DeployException e) { 89 | // e.printStackTrace(); 90 | // } 91 | 92 | // 启动实例 93 | try { 94 | aliyunInstanceService.startInstance("i-23n9gwnle"); 95 | } catch (DeployException e) { 96 | e.printStackTrace(); 97 | } 98 | 99 | // try { 100 | // aliyunInstanceService.stopInstance("i-23k3edxjr"); 101 | // } catch (DeployException e) { 102 | // // response error json 103 | // } 104 | 105 | // try { 106 | // InstanceStatus r = aliyunInstanceService.describeInstanceAttribute("i-23bnskcin"); 107 | // System.out.println("r.id=" + r.getInstanceId() + ",status=" + r.getStatus()); 108 | // } catch (DeployException e) { 109 | // e.printStackTrace(); 110 | // } 111 | 112 | // AliyunRegionService regionService = new AliyunRegionService(client); 113 | // try { 114 | // regionService.describeRegions().forEach(r -> System.out.println("('"+r.getRegionId()+"','"+r.getLocalName()+"')")); 115 | // } catch (DeployException e) { 116 | // e.printStackTrace(); 117 | // } 118 | 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/service/AliyunInstanceService.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.service; 2 | 3 | import com.aliyun.api.ecs.ecs20130110.request.DescribeInstanceAttributeRequest; 4 | import com.aliyun.api.ecs.ecs20130110.request.StartInstanceRequest; 5 | import com.aliyun.api.ecs.ecs20130110.request.StopInstanceRequest; 6 | import com.aliyun.api.ecs.ecs20130110.response.DescribeInstanceAttributeResponse; 7 | import com.aliyun.api.ecs.ecs20130110.response.StartInstanceResponse; 8 | import com.aliyun.api.ecs.ecs20130110.response.StopInstanceResponse; 9 | import com.aliyun.api.ecs.ecs20140526.request.CreateInstanceRequest; 10 | import com.aliyun.api.ecs.ecs20140526.response.CreateInstanceResponse; 11 | import com.qianmi.DeployException; 12 | import com.qianmi.form.InstanceStatus; 13 | import com.taobao.api.ApiException; 14 | import org.apache.commons.lang3.StringUtils; 15 | 16 | /** 17 | * 实例 18 | */ 19 | public class AliyunInstanceService extends BaseService { 20 | 21 | /** 22 | * 创建实例 23 | * @return 实例ID 24 | */ 25 | public String createInstance(CreateInstanceRequest request) throws DeployException { 26 | if (StringUtils.isEmpty(request.getImageId())) { 27 | request.setImageId(ApiUtil.getInstance().getConfigCache().get("aliyun.instance.ImageId")); 28 | } 29 | if (StringUtils.isEmpty(request.getInstanceType())) { 30 | request.setInstanceType(ApiUtil.getInstance().getConfigCache().get("aliyun.instance.InstanceType")); 31 | } 32 | if (StringUtils.isEmpty(request.getRegionId())) { 33 | request.setRegionId(ApiUtil.getInstance().getConfigCache().get("aliyun.instance.RegionId")); 34 | } 35 | if (StringUtils.isEmpty(request.getSecurityGroupId())) { 36 | request.setSecurityGroupId(ApiUtil.getInstance().getConfigCache().get("aliyun.instance.SecurityGroupId")); 37 | } 38 | if (StringUtils.isEmpty(request.getInternetChargeType())) { 39 | request.setInternetChargeType(ApiUtil.getInstance().getConfigCache().get("aliyun.instance.InternetChargeType")); // 按量付费 40 | } 41 | if (request.getInternetMaxBandwidthOut() == null) { 42 | request.setInternetMaxBandwidthOut(Long.parseLong(ApiUtil.getInstance().getConfigCache().get("aliyun.instance.InternetMaxBandwidthOut"))); 43 | } 44 | if (StringUtils.isEmpty(request.getPassword())) { 45 | request.setPassword(ApiUtil.getInstance().getConfigCache().get("aliyun.instance.password")); 46 | } 47 | try { 48 | CreateInstanceResponse response = client.execute(request); 49 | if (StringUtils.isNotEmpty(response.getErrorCode())) { 50 | logger.error("code:{}, msg:{}", response.getErrorCode(), response.getMessage()); 51 | throw new DeployException(response.getErrorCode(), response.getMessage()); 52 | } 53 | return response.getInstanceId(); 54 | } catch (ApiException e) { 55 | logger.error("code:{}, msg:{}", e.getErrCode(), e.getMessage(), e); 56 | throw new DeployException(e.getErrCode(), e.getErrMsg()); 57 | } 58 | } 59 | 60 | /** 61 | * 启动实例 62 | * @param instanceId 实例ID 63 | * @throws DeployException 64 | */ 65 | public void startInstance(String instanceId) throws DeployException { 66 | StartInstanceRequest request = new StartInstanceRequest(); 67 | request.setInstanceId(instanceId); 68 | try { 69 | StartInstanceResponse response = client.execute(request); 70 | if (StringUtils.isNotEmpty(response.getErrorCode())) { 71 | logger.error("code:{}, msg:{}", response.getErrorCode(), response.getMessage()); 72 | throw new DeployException(response.getErrorCode(), response.getMessage()); 73 | } 74 | } catch (ApiException e) { 75 | logger.error("code:{}, msg:{}", e.getErrCode(), e.getMessage(), e); 76 | throw new DeployException(e.getErrCode(), e.getErrMsg()); 77 | } 78 | } 79 | 80 | /** 81 | * 停止实例 82 | * @param instanceId 实例ID 83 | * @throws DeployException 84 | */ 85 | public void stopInstance(String instanceId) throws DeployException { 86 | StopInstanceRequest request = new StopInstanceRequest(); 87 | request.setInstanceId(instanceId); 88 | try { 89 | StopInstanceResponse response = client.execute(request); 90 | if (StringUtils.isNotEmpty(response.getErrorCode())) { 91 | logger.error("code:{}, msg:{}", response.getErrorCode(), response.getMessage()); 92 | throw new DeployException(response.getErrorCode(), response.getMessage()); 93 | } 94 | } catch (ApiException e) { 95 | logger.error("code:{}, msg:{}", e.getErrCode(), e.getMessage(), e); 96 | throw new DeployException(e.getErrCode(), e.getErrMsg()); 97 | } 98 | } 99 | 100 | /** 101 | * 查询实例状态 102 | * @param instanceId 实例ID 103 | * @throws DeployException 104 | */ 105 | public InstanceStatus describeInstanceAttribute(String instanceId) throws DeployException { 106 | logger.debug("find instanceId:{} status", instanceId); 107 | DescribeInstanceAttributeRequest request = new DescribeInstanceAttributeRequest(); 108 | request.setInstanceId(instanceId); 109 | try { 110 | DescribeInstanceAttributeResponse response = client.execute(request); 111 | if (StringUtils.isNotEmpty(response.getErrorCode())) { 112 | logger.error("code:{}, msg:{}", response.getErrorCode(), response.getMessage()); 113 | throw new DeployException(response.getErrorCode(), response.getMessage()); 114 | } 115 | 116 | Object publicIp = response.getPublicIpAddress().size() > 0 ? response.getPublicIpAddress().get(0) : ""; 117 | Object innerIp = response.getInnerIpAddress().size() > 0 ? response.getInnerIpAddress().get(0) : ""; 118 | return new InstanceStatus(response.getInstanceId(), response.getStatus(), (String)publicIp, (String)innerIp); 119 | } catch (ApiException e) { 120 | logger.error("code:{}, msg:{}", e.getErrCode(), e.getMessage(), e); 121 | throw new DeployException(e.getErrCode(), e.getErrMsg()); 122 | } 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | com.ofpay 7 | of-parent 8 | 1.1.4-RELEASE 9 | 10 | 11 | com.qianmi 12 | cloudeploy 13 | 1.0-RELEASE 14 | jar 15 | 16 | cloudeploy 17 | http://maven.apache.org 18 | 19 | 20 | 1.8 21 | 1.8 22 | UTF-8 23 | http://git.dev.qianmi.com/tda/cloudeploy.git 24 | 25 | 26 | 27 | scm:git:${git.url} 28 | scm:git:${git.url} 29 | ${git.url} 30 | HEAD 31 | 32 | 33 | 34 | 35 | com.sparkjava 36 | spark-core 37 | 2.1 38 | 39 | 40 | org.slf4j 41 | slf4j-simple 42 | 43 | 44 | 45 | 46 | 47 | commons-logging 48 | commons-logging 49 | 1.2 50 | 51 | 52 | 53 | org.slf4j 54 | slf4j-api 55 | 1.7.12 56 | 57 | 58 | 59 | ch.qos.logback 60 | logback-classic 61 | 1.1.2 62 | 63 | 64 | 65 | ch.qos.logback 66 | logback-core 67 | 1.1.2 68 | 69 | 70 | 71 | org.apache.commons 72 | commons-lang3 73 | 3.4 74 | 75 | 76 | 77 | commons-io 78 | commons-io 79 | 2.4 80 | 81 | 82 | 83 | commons-codec 84 | commons-codec 85 | 1.10 86 | 87 | 88 | 89 | commons-dbutils 90 | commons-dbutils 91 | 1.6 92 | 93 | 94 | 95 | com.h2database 96 | h2 97 | 1.4.187 98 | 99 | 100 | 101 | junit 102 | junit 103 | 3.8.1 104 | test 105 | 106 | 107 | 108 | com.qianmi 109 | aliyun-java-sdk-ecs 110 | 2014-11-17 111 | 112 | 113 | 114 | com.eclipsesource.minimal-json 115 | minimal-json 116 | 0.9.2 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | org.apache.maven.plugins 125 | maven-release-plugin 126 | 127 | ${git.username} 128 | ${git.password} 129 | 130 | 131 | 132 | 133 | org.apache.maven.plugins 134 | maven-compiler-plugin 135 | 3.2 136 | 137 | ${maven.compiler.source} 138 | ${maven.compiler.target} 139 | ${project.build.sourceEncoding} 140 | 141 | 142 | 143 | 144 | org.apache.maven.plugins 145 | maven-assembly-plugin 146 | 2.5.4 147 | 148 | false 149 | 150 | 151 | true 152 | com.qianmi.Bootstrap 153 | 154 | 155 | 156 | jar-with-dependencies 157 | 158 | 159 | 160 | 161 | assemble-all 162 | package 163 | 164 | single 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | nexus repository 175 | intranet public groups 176 | http://nexus.dev.ofpay.com/nexus/content/groups/public 177 | 178 | false 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /src/main/java/com/qianmi/controller/WebController.java: -------------------------------------------------------------------------------- 1 | package com.qianmi.controller; 2 | 3 | import com.eclipsesource.json.JsonObject; 4 | import com.qianmi.DeployException; 5 | import com.qianmi.form.InstanceForm; 6 | import com.qianmi.form.InstanceResult; 7 | import com.qianmi.form.InstanceStatus; 8 | import com.qianmi.models.UserInstance; 9 | import com.qianmi.models.UserInstanceHelper; 10 | import com.qianmi.proxy.InstanceProxy; 11 | import com.qianmi.service.AliyunInstanceService; 12 | import org.apache.commons.codec.binary.Base64; 13 | import org.apache.commons.io.IOUtils; 14 | import org.apache.commons.lang3.StringUtils; 15 | import org.eclipse.jetty.http.HttpStatus; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | import java.io.IOException; 20 | import java.nio.charset.Charset; 21 | 22 | import static spark.Spark.*; 23 | 24 | public class WebController { 25 | 26 | protected final transient Logger logger = LoggerFactory.getLogger(getClass()); 27 | 28 | public WebController() { 29 | 30 | get("/", (request, response) -> "

Welcome Cloudeply!

"); 31 | 32 | /** 33 | * 创建新主机 34 | * POST /host/new 35 | */ 36 | post("/host/new", (request, response) -> { 37 | InstanceForm form = new InstanceForm(); 38 | form.setUser(request.queryParams("user")); 39 | form.setPlatform(request.queryParams("platform")); 40 | form.setRegion(request.queryParams("region")); 41 | form.setOsName(StringUtils.defaultString(request.queryParams("osName"), "CentOS").toLowerCase()); 42 | form.setOsBit(request.queryParams("osBit")); 43 | form.setOsVersion(request.queryParams("osVersion")); 44 | form.setCpu(request.queryParams("cpu")); 45 | form.setMemory(request.queryParams("memory")); 46 | form.setPassword(request.queryParams("password")); 47 | form.setInternetChargeType(request.queryParams("internetChargeType")); 48 | form.setInternetMaxBandwidthOut(request.queryParams("internetMaxBandwidthOut")); 49 | logger.debug("new host param:{}", form); 50 | JsonObject result2json = new JsonObject(); 51 | // validate 52 | if (StringUtils.isEmpty(form.getUser())) { 53 | result2json.add("user", "is not empty"); 54 | } 55 | if (form.getOsBit() != null && !StringUtils.isNumeric(form.getOsBit())) { 56 | result2json.add("osBit", "is not number"); 57 | } 58 | if (form.getCpu() != null && !StringUtils.isNumeric(form.getCpu())) { 59 | result2json.add("cpu", "is not number"); 60 | } 61 | if (form.getMemory() != null && !StringUtils.isNumeric(form.getMemory())) { 62 | result2json.add("memory", "is not number"); 63 | } 64 | if (!result2json.isEmpty()) { 65 | response.status(HttpStatus.BAD_REQUEST_400); 66 | return result2json; 67 | } 68 | 69 | InstanceProxy instanceProxy = new InstanceProxy(); 70 | try { 71 | InstanceResult r = instanceProxy.newInstance(form); 72 | // add user record 73 | UserInstance u = new UserInstance(); 74 | u.setInstanceId(r.getInstanceId()); 75 | u.setInstanceIp(r.getIp()); 76 | u.setUser(form.getUser()); 77 | u.setPlatform(form.getPlatform()); 78 | UserInstanceHelper userInstanceHelper = new UserInstanceHelper(); 79 | userInstanceHelper.add(u); 80 | return result2json.add("instanceId", r.getInstanceId()).add("ip", r.getIp()); 81 | } catch (DeployException de) { 82 | response.status(HttpStatus.INTERNAL_SERVER_ERROR_500); 83 | return result2json.add("code", de.getCode()).add("message", de.getMessage()); 84 | } 85 | 86 | }); 87 | 88 | /** 89 | * 查询主机状态 90 | * GET /host/status 91 | * Param: instanceId 92 | * 93 | * json: {result: Running, Starting, Stopped} 94 | */ 95 | get("/host/status", (request, response) -> { 96 | String instanceId = request.queryParams("instanceId"); 97 | logger.debug("param instanceId:{}", instanceId); 98 | JsonObject result2json = new JsonObject(); 99 | if (StringUtils.isEmpty(instanceId)) { 100 | response.status(HttpStatus.BAD_REQUEST_400); 101 | result2json.add("instanceId", "param is not empty"); 102 | return result2json; 103 | } 104 | 105 | AliyunInstanceService instanceService = new AliyunInstanceService(); 106 | try { 107 | InstanceStatus status = instanceService.describeInstanceAttribute(instanceId); 108 | 109 | return result2json.add("instanceId", status.getInstanceId()) 110 | .add("status", status.getStatus()) 111 | .add("publicIp", status.getPublicIp()) 112 | .add("innerIp", status.getInnerIp()); 113 | } catch (DeployException de) { 114 | response.status(HttpStatus.INTERNAL_SERVER_ERROR_500); 115 | return result2json.add("code", de.getCode()).add("message", de.getMessage()); 116 | } 117 | }); 118 | 119 | /** 120 | * 执行ansible命令 121 | * POST /ansible/send 122 | * Content-Type:application/x-www-form-urlencoded 123 | * Param: command 124 | * 125 | * Result: 126 | * responseStatus == 200:成功, 400:参数错误, 500:系统错误 127 | * responseBody 128 | */ 129 | post("/ansible/send", (request, response) -> { 130 | JsonObject result2json = new JsonObject(); 131 | String command = request.queryParams("command"); 132 | logger.debug("command param:{}", command); 133 | if (StringUtils.isEmpty(command)) { 134 | response.status(HttpStatus.BAD_REQUEST_400); 135 | return result2json.add("command", "param is not empty"); 136 | } 137 | command = StringUtils.toEncodedString(Base64.decodeBase64(command), Charset.defaultCharset()); 138 | logger.debug("command decode:{}", command); 139 | ProcessBuilder pb = new ProcessBuilder(); 140 | pb.command("/bin/sh", "-c", command); 141 | try { 142 | Process p = pb.start(); 143 | String result = IOUtils.toString(p.getErrorStream(), Charset.defaultCharset()); 144 | logger.info("command process:\n{}", result); 145 | return result2json.add("result", result); 146 | } catch (IOException ioe) { 147 | logger.error("command execute error", ioe); 148 | response.status(HttpStatus.INTERNAL_SERVER_ERROR_500); 149 | return result2json.add("error", ioe.getMessage()); 150 | } 151 | }); 152 | 153 | } 154 | 155 | } 156 | --------------------------------------------------------------------------------