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.构建过程


源码已上传到CODE.CSDN

4.5.Restart host功能及等待


源码已上传到CODE.CSDN

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&#187; 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



Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐