1.简要回顾
1.1.简述
不容易啊,学习的东西很多,接触到的新东西也很多。这个项目可以做得很成熟,该工具对于机群的维护也很重要。项目中基于Jenkins的Foreman plugin插件开发在Windows系统下实现,Foreman服务的搭建在CentOS系统中。涉及到工具或技术有JDK,Maven,Jenkins,NetBeans,Ruby,Foreman,Git等。
通过大量测试,竭尽所能,日臻完善,其间解决了很多BUG,大大增强了该plugin应用的鲁棒性。
UI界面设计是一流的,代码风格清爽、规整,封装结构合理、易读,基本测试良好,要求功能都实现了。
1.2.构建测试历史
一把辛酸泪啊!
2.学习历程
2.1.Git,Maven工具
Git是代码管理工具,此次项目所有源码要求上传到CODE.CSDN上,这个工具是实现源码各种操作的重要手段,在项目之初就熟悉了这个工具。Maven是项目构建工具,多属Java集成开发环境的内嵌或者支持该工具。Maven强大的源码仓库使开发者能够做易于交流、合作和可移植的项目。
2.2.Jenkins Plug-in开发
Jenkins是开源的持续集成开发环境,具有Web前端,其插件资源丰富并且都是开源的。Jenkins的Plug-in具有优秀的UI,易于实现,可扩展性强。
2.3.Foreman服务
Foreman是对物理机或虚拟机进行生命周期管理的工具,其灵活的接口可以管理机器的安装、配置、运行时的软件包管理、监控。Foreman提供RESTful API,在接口实现上比较简单,但是对机器的配置却是另外一门学问,具有复杂性。
2.4.HttpURLConnection实现REST客户端
相对HttpClient而言,HttpURLConnection更为底层一些,但实现REST客户端功能也是相当容易的。在实现REST接口过程中,接触到服务端的接口开发包,也都支持客户端功能。
2.5.Json
JSON(Javascript ObjectNotation)是一种轻量级的数据交换语言,以文字为基础,且易于让人阅读。尽管JSON是在Javascript的一个子集,但JSON是独立于语言的文本格式,并且采用了类似于C语言家族的一些习惯。实现Json解析的开发包很多,我采用的是org.net的开发包,学习起来比较容易,且很有用处。
3.实现情况
3.1.界面设计
3.1.1初始风格
3.1.2.填入基本信息
3.1.3.Restart host界面
3.1.4.配置信息输入
3.1.5.控制台输出过程
3.2.主要功能
3.2.1.勾选查询功能
实时返回RespondCode,以便判断网络连接情况。
3.2.2.更新查询功能及输出
3.2.3.配置信息保存及选择构建
通过Build or Not选择是否构建,可以便捷管理配置信息。
3.2.4.Restarthost等待及控制台输出内容
4.重要实现详解
4.1.UI中的Tag
User, Password, URL界面jelly具体实现:
<f:entry title="User" field="user">
<f:textbox />
</f:entry>
<f:entry title="Password" field="password">
<f:textbox />
</f:entry>
<f:entry title="URL" field="url">
<f:textbox />
</f:entry>
动态查询实现:
<f:entry title="Look up Exist Templates Config" field="templatesExist">
<f:checkbox />
<div>${instance.templatesNum}</div>
<div>${instance.templatesConfig}</div>
</f:entry>
其他内容参见CODE.CSDN源码。
4.2.动态渲染支持的查询功能
Jenkins支持表单域自动Check功能,下面通过Check函数实现查询Hosts,Hostgroups和Templates功能:
public FormValidation doCheckHostgroupsExist(@QueryParameter boolean value)
throws IOException, ServletException {
String userln;
String passwordln;
String urlln;
int RespondCode = 0;
userln =adminInfo.user;
passwordln =adminInfo.password;
urlln =adminInfo.url;
if (value){
try {
RespondCode=HttpMethod.getAPI(urlln + "/api/hostgroups",userln, passwordln);
} catch (Exception ex) {
Logger.getLogger(ForemanSetup.class.getName()).log(Level.SEVERE, null, ex);
}
return FormValidation.ok("HostgroupsConfig:" +
"\nUser: " +
userln +
"\nPassword: " +
passwordln +
"\nURL: " +
urlln +
"\nRespondCode: " +
RespondCode);
}
if (!value)
return FormValidation.warning("勾选查询Hostgroups\n“应用”后刷新");
return FormValidation.ok();
}
public FormValidation doCheckHostsExist(@QueryParameter boolean value)
throws IOException, ServletException {
String userln;
String passwordln;
String urlln;
int RespondCode = 0;
userln =adminInfo.user;
passwordln =adminInfo.password;
urlln =adminInfo.url;
if (value){
try {
RespondCode=HttpMethod.getAPI(urlln + "/api/hosts",userln, passwordln);
} catch (Exception ex) {
Logger.getLogger(ForemanSetup.class.getName()).log(Level.SEVERE, null, ex);
}
return FormValidation.ok("HostsConfig:" +
"\nUser: " +
userln +
"\nPassword: " +
passwordln +
"\nURL: " +
urlln +
"\nRespondCode: " +
RespondCode);
}
if (!value)
return FormValidation.warning("勾选查询Hosts\n“应用”后刷新");
return FormValidation.ok();
}
public FormValidation doCheckTemplatesExist(@QueryParameter boolean value)
throws IOException, ServletException {
String userln;
String passwordln;
String urlln;
int RespondCode = 0;
userln =adminInfo.user;
passwordln =adminInfo.password;
urlln =adminInfo.url;
if (value){
try {
RespondCode=HttpMethod.getAPI(urlln + "/api/config_templates?per_page=100",userln, passwordln);
} catch (Exception ex) {
Logger.getLogger(ForemanSetup.class.getName()).log(Level.SEVERE, null, ex);
}
return FormValidation.ok("TemplatesConfig:" +
"\nUser: " +
userln +
"\nPassword: " +
passwordln +
"\nURL: " +
urlln +
"\nRespondCode: " +
RespondCode);
}
if (!value)
return FormValidation.warning("勾选查询Templates\n“应用”后刷新");
return FormValidation.ok();
}
4.3.Hosts,Hostgroups和Templates配置管理
4.3.1.Json配置信息保存和读取
Jenkins界面上的表单域通过内部.xml保存,添加对应Field的get函数可自动读取保存内容,添加函数如下:
public List<Templates> getTemplates(){
return templates;
}
public List<Hosts> getHosts(){
return hosts;
}
public List<Hostgroups> getHostgroups(){
return hostgroups;
}
public String getUser(){
return user;
}
public String getUrl(){
return url;
}
public String getPassword(){
return password;
}
public boolean getTemplatesExist(){
return templatesExist;
}
public boolean getHostsExist(){
return hostsExist;
}
public boolean getHostgroupsExist(){
return hostgroupsExist;
}
由于表单域保存值自动添加内部配置信息保存为JSONObject,通过org.net的Json开发包读取输入的Json配置信息:
JSONObject jsonM = new JSONObject(json.get("Method").toString());
4.3.2.Build管理逻辑
增加的Host, HostGroup或Template可以通过对应复选框选择是否构建,具体实现代码如下:
int i;
if(templates==null){
listener.getLogger().println("No template building.");
}
else{
for(i=0;i<templates.size();i++){
if(templates.get(i).templateBoN){
try {
ForemanHandle.listener.getLogger().println("Templates " + i + " building.");
listener.getLogger().println(toJSONObject(templates.get(i).template).toString());
ForemanHandle.configTemplate(url + "/api/config_templates", user, password, toJSONObject(templates.get(i).template));
} catch (JSONException ex) {
Logger.getLogger(ForemanSetup.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception ex) {
Logger.getLogger(ForemanSetup.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
if(hosts==null){
listener.getLogger().println("No host building.");
}
else{
for(i=0;i<hosts.size();i++){
if(hosts.get(i).hostBoN){
try {
ForemanHandle.listener.getLogger().println("Host " + i + " building.");
listener.getLogger().println(toJSONObject(hosts.get(i).host).toString());
ForemanHandle.buildHost(url + "/api/hosts", user, password, toJSONObject(hosts.get(i).host));
} catch (JSONException ex) {
Logger.getLogger(ForemanSetup.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception ex) {
Logger.getLogger(ForemanSetup.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
if(hostgroups==null){
listener.getLogger().println("No hostgroup building.");
}
else{
for(i=0;i<hostgroups.size();i++){
if(hostgroups.get(i).hostgroupBoN){
try {
ForemanHandle.listener.getLogger().println("Hostgroups " + i + " building.");
listener.getLogger().println(toJSONObject(hostgroups.get(i).hostgroup).toString());
ForemanHandle.buildHostgroup(url + "/api/hostgroups", user, password, toJSONObject(hostgroups.get(i).hostgroup));
} catch (JSONException ex) {
Logger.getLogger(ForemanSetup.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception ex) {
Logger.getLogger(ForemanSetup.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
4.4.构建过程
4.5.Restart host功能及等待
5.深入开发
5.1.界面优化
增加plug-in支持Foreman的功能,也需要一个十分合理的界面。没有最好,只有更合理的设计,更好用的界面,所以要不断优化改进。
5.2.Foreman配置功能的全面实现
Foreman是一个全面的工具,系统庞大不是一朝一夕能全部实现的,争取在以后不断增加新功能并持续维护和修正Bug。
5.3.机群配置
Foreman的应用很广,设计思路也很实用,我准备在以后研究超级计算,而Foreman可以帮我实现机群的配置,使得工作效率大大提高。
Acknowledges
感谢CSDN提供了这个平台让我有了这次参与项目的机会,感谢红帽软件公司的支持,感谢边导和我深入探讨这个项目。感谢所有为开源事业做出贡献的人和正在努力贡献的人。感谢360搜索和百度搜索提供了便捷的资料搜索功能。
References
官方资源:
1. The Foreman :: API
http://theforeman.org/api.html
2. Plugins - Jenkins - Jenkins Wiki
https://wiki.jenkins-ci.org/display/JENKINS/Plugins
3. Overview (Jenkins main module 1.574 API)
http://javadoc.jenkins-ci.org/
4. Maven Repository: com.sun.jersey» jersey-client
http://mvnrepository.com/artifact/com.sun.jersey/jersey-client
5. Restlet - REST Framework for Java &PaaS for Web APIs
http://restlet.com/
个人博客:
6. 构建Restful 的Java客户端-sherrylso-ITPUB博客
http://blog.itpub.net/17131144/viewspace-1015430/
7. Hudson插件开发简介 -littleatp2008的专栏 - 博客频道 - CSDN.NET
http://blog.csdn.net/littleatp2008/article/details/7001793
8. 第一个 Jenkins Maven Git测试项目 hello world 成功运行 « 翠滴竹,火烧花
http://www.freekongjian.com/2012-06/jenkins-maven-git.html
9. Jenkins的plugin开发 - 为程序员服务
http://ju.outofmemory.cn/entry/43025
10. Jenkins插件开发 - 混世魔王 - 开源中国社区
http://my.oschina.net/songcser/blog/159170
11. OutOfMemory.CN - 为程序员服务
http://outofmemory.cn/wr/?u=http%3A%2F%2Fplkong.iteye.com%2Fblog%2F1780121
12. RESTLET开发实例(一)基于JAX-RS的REST服务 - JYY 开源CODEING之路 - 开源中国社区
http://my.oschina.net/jiyayun/blog/146439
13. json-simple - 青春丶冭柔情 - 博客园
http://www.cnblogs.com/wh-king/archive/2012/10/26/2740466.html
14. blog.csdn.net/kkdelta/article/details/28419625
http://blog.csdn.net/kkdelta/article/details/28419625
15. 网络编程之HttpURLConnection- slider - 博客园
http://www.cnblogs.com/slider/archive/2012/06/07/2540470.html
16. [JAVA]使用HttpURLConnection进行POST方式提交 -sunfruit[请访问http://www.fruitres.cn] - BlogJava
http://www.blogjava.net/sunfruit/archive/2006/03/13/35048.html
17. Java中利用HttpURLConnection发送post和get请求 - Java综合 - Java -ITeye论坛
http://www.iteye.com/topic/1060450
18. [热门]Java HttpURLConnection 的简单用法_java三匠_新浪博客
http://blog.sina.com.cn/s/blog_7abbe6580100t51j.html