Jboss Fuse deployer on Windows system.
In addition to the post title. Fuse , or RedHat Jboss Fuse is a server for Osgi bundles. Basically when you want to deploys bundles or features to the server you can do something like
osgi:install -s mvn:com.kone.cth/camel-kid/0.0.1-SNAPSHOTThat is simple, and that is the point! During development phase, we, developer want to focus on problems at hand and willing to let alone monotonous tasks and it should be done automatically. An example on one of those is deployment.
That is why ant, maven and sort of tools are indispensable. However, we cannot find a magic bullet for everything. And that is also the case for deploying features or bundles to Fuse server.
Manual steps I have to do.
1. Build project with maven
2. Delete {fuse_home}/data/*
3. Start Fuse. Usually I need to stop first because of the last run. So , some waiting occurred here.
4. Wait for it to start successfully... in the mean time, go and get coffee and usually forget.
5. Add feature urls, install features/ bundles etc... repeatably for days
Would it be nice if there was a tool doing that for us in a repeatable, reliable and consistent manner ?
And now we want to automate those steps. First thing came up on my mind . Jenkins , yes that is right. I started of by have it up and running , config maven, jdk etc. and try to run a simple build. It was cool. Yes Jenkins can answer my question partially. I couldn't manage Jenkins to start local fuse server and have it install bundles as I wanted. Maybe Jenkins expert can, if you do, please enlighten us in the comment. That could be a huge benefit to many people who comes by.
When Jenkins wasn't the choice. I then had a tried on Ansible. Well, if a host is *nix system, things would be a whole lot easier as we could have many choices here, i.e. simple shell script, even on the giant's shoulder like Ansible too. Though Ansible seems to be the right choice but I have some problem in hosting Ansible on Windows machine. There are couples solution here, firstly, we could use Cygwin and have it installs Ansible's necessary. Secondly, spin up some vm *nix box and host Ansible there and make it control the host of it's host. Funny!
I pause myself for a while, stop finding any further magic bullet. Then a bright idea came up. Python. Yes, that is right, because ultimately Ansible is gonna compile our playbook into python's bytecode anyway. In spite of working around and preparing host for Ansible, yet learning Ansible's module. Why don't I just roll up some tools that's just enough to automate those five steps.
Base on those five tasks, that is enough to form an abstraction. It could be like the following method.
def main(): setupVariables() showVariables() mvn('-T ' + threads + ' clean install -e' , fuse_project) prepareFuseServer() startFuseServer() installCommand() if should_open_plink == 'yes': openPutty()Without any further ado , I finished up those methods and result quite acceptable.
What is could do though. It let me write my code, and whenever I want to deploy to the server, I don't have to care whether or not fuse server would start or stop. The script will take care the rest of the problems.
If the fuse started, then stop it > delete data folder > start fuse > installs commands I wanted > open ssh client for me.
If the fuse stop. Just do continuous the rest of the step as above. You can check out the project from here https://gitlab.com/charnnarong.chomthiang/fuseBuilder.git
Now many people don't just really want to use it, but rather than just wanna sneaking into and have a look with one eye close instead. Ladies and gentlemen, for your convenience, I paste the project's source code here as you wish. (Please note that, the code you see here may quickly outdated from the one in gitlab repo)
There are three components on this project.
1. Config file: The only place that you have to configure in order to make it works. More details are describe inside the file itself.
2. Python code: The file that will read value from the config file and do the magic.
3. External tools: packed with putty.exe and plink.exe. If you have any question on those files, you are free to replace them with yours, make sure they are having the same name, or alternatively you can change the name or path from python code itself - easy thing to do so.
{project}/src/fib.cfg
############################################################### # Fuse Builder Configuration. # The script was design to be easy to work with. # All you have to do is check it out the project from # https://gitlab.com/charnnarong.chomthiang/fuseBuilder.git # # Prerequisite # ------------ # 1. Python 2.7 # 2. Window platform # 3. mvn command avaliable # # Usage # ---------- # boolean values { yes , no } # # [fuseCommands] are off free style (key,value) # You can have any numbers of commands here. # key: will be use to log as information # value: will be use as a command which will run in Fuse. # # # Create by Charnnarong Chomthiang. # ################################################################ [userSetting] fuse_server = E:\DevTools\jboss-fuse-6.2.1.redhat-084 fuse_project = D:\ws\marlodevops\camel-kid [mvnCommand] maven_command_agaist_project = -T 8 clean install -e [fuseCommands] install features url = osgi:install -s mvn:com.kone.cth/camel-kid/0.0.1-SNAPSHOT show list = list grep all for cth = list | grep cth [optional] fuse_checking_privisioning_period = 2 [postInstall] open_plink_after_install = yes
{project}/src/fib.py
import os import ConfigParser import subprocess import socket from subprocess import call from shutil import rmtree from time import sleep DETACHED_PROCESS = 0x00000008 fuse_serers = "" fuse_project = "" fuseCommands = [] threads = 1 checking_period = 2 should_open_plink = 'yes' maven_command_agaist_project = '' def main(): setupVariables() showVariables() mvn( maven_command_agaist_project , fuse_project) prepareFuseServer() startFuseServer() installCommand() if should_open_plink == 'yes': openPutty() def setupVariables(): global fuse_serers , fuse_project, threads, fuseCommands, checking_period , should_open_plink , maven_command_agaist_project config = ConfigParser.RawConfigParser() config.read('fib.cfg') fuse_serers = config.get('userSetting', 'fuse_server') fuse_project = config.get('userSetting', 'fuse_project') checking_period = config.getfloat('optional', 'fuse_checking_privisioning_period') should_open_plink = config.get('postInstall','open_plink_after_install') maven_command_agaist_project = config.get('mvnCommand','maven_command_agaist_project') fuseCommands = config.items('fuseCommands') def showVariables(): print fuse_serers print fuse_project print fuseCommands def mvn(command , project_path): print 'mvn ' + command + ' -f ' + project_path call('mvn ' + command + ' -f ' + project_path , shell=True) def prepareFuseServer(): if isFuseServerRunning(): print "Fuse is running...." stopFuseServer() while True: if not isFuseServerRunning(): _is_data_deleted = False while True: try: if os.path.isdir(fuse_serers + "\\data\\"): rmtree(fuse_serers + "\\data\\") _is_data_deleted = True break except: print "gracefully stopping fuse server... " sleep(checking_period) continue if _is_data_deleted: break sleep(checking_period) # Fuse status report running.. even a server is provisioning. When checking # the server's state if it ready for the next task: checking port fuse port # is more appropriate. def isFuseServerRunning(): return isPortOpen('localhost', 8101) def isPortOpen(host, port): _socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) return_code = _socket.connect_ex((host, port)) return return_code == 0 def stopFuseServer(): print "Stopping fuse..." call(fuse_serers + "\\bin\\stop.bat", shell=True) def startFuseServer(): # pid = subprocess.Popen([fuse_serers+"\\bin\\fuse.bat","server"]).pid pid = subprocess.Popen([fuse_serers + "\\bin\\fuse.bat", "server"], creationflags=DETACHED_PROCESS).pid print "Fuse start with process id = " + str(pid) while True: print "Fuse is starting..." if isFuseServerRunning(): print "Fuse is ready" break sleep (checking_period) def installCommand(): print "Provisioning fuse with the following commands" for i in fuseCommands : print i print "------------------------" print "Starting execute fuse commands" for i in fuseCommands : sshToFuse(i) def sshToFuse(command): plink = os.getcwd() +'\\tools\\plink.exe' print "Executing task " + command[0] output = subprocess.call(plink + ' -P 8101 localhost -l admin -pw admin -C "' + command[1] + '"' , shell=True) print "Success" if output == 0 else "Fail" def openPutty(): putty = os.getcwd() +'\\tools\\putty.exe' subprocess.call(putty + ' -P 8101 localhost -l admin -pw admin', shell=True) if __name__ == '__main__': main()