python commit and push to git in Jenkins

I’ve looked all over the internet and can’t find anything regarding pushing to a remote repo via python…. particularly in Jenkins where your upstream is not set.

So I finally found the only helpful link and it was saying: don’t use gitpython.

But after trying multiple methods, I finally got this working. Note: It uses a few args from Jenkins && the point of this script is nothing more than to modify a file and commit it. With this functionality, I can now do real work.

import git
import os
import time
import yaml
import sys
import re
from git import Repo
print os.environ["GIT_BRANCH"]
workspace=os.environ['WORKSPACE']
m = re.search("origin/(.*)", os.environ["GIT_BRANCH"])
if m:
    git_branch = m.group(1)
else:
    sys.exit("COULD NOT LOAD SOURCE BRANCH")
# UPDATE VERSION FILE
with open(workspace + '/deploy_automation/config/int/versions.yaml', 'r') as f:
    versions_yaml = yaml.load(f)
versions_yaml["a.component"] = time.time()
with open(workspace + '/deploy_automation/config/int/versions.yaml', 'w') as f:
    yaml.dump(versions_yaml, f, default_flow_style=False)
# OTHER WAY
git_repo = Repo(workspace + "/deploy_automation")
git_repo.git.status()
git_repo.git.add(workspace + '/deploy_automation/config/int/versions.yaml')
git_repo.git.config('--global', "user.name", "user name")
git_repo.git.config('--global', "user.email", "user@domain.com")
git_repo.git.status()
git_repo.git.commit(m=' DEPLOY SCRIPT Updating versions.yaml for ENV jamestest2 and Service test')
git_repo.git.push('--set-upstream', 'origin', git_branch)

					

Multiline find / replace

I need to configure Jenkins jobs, which are currently configured to run anywhere to work on a specific label. Sure I could do it via the gui but in a SOA, I don’t want to manually do this in 100+ jobs.
So the files currently has in it:

   </scm>
   <canRoam>true</canRoam>
   <disabled>false</disabled>

I want it to be:

   </scm>
   <canRoam>false</canRoam>
   <disabled>false</disabled>

I run:

server:~/jenkins/jobs> perl -pi -e 'BEGIN{undef $/;} s/<\/scm>.+?true<\/canRoam>/<\/scm>\nbuild<\/assignedNode>\nfalse<\/canRoam>/smg' app*/config.xml

Many thanks to aks and StackOverflow for the help

Watch SVN tags & update Jenkins options when new tag created

Jenkins job…. put it running every 5 minutes…


from objects import Jenkins
import logging
import sys
import re
import pysvn
import os


jenkins_uid="brand_admin"
jenkins_pwd="1qazxsw2"
jenkins_url="http://jenkins.company.com"
jenkins_job_file="config.xml"

device_list=("android", "ios", "blackberry")

svn_url="https://test.freerange360.com/svn/"


jenkins_project_list={}
jenkins_project_list["android"] = "android_trunk"
jenkins_project_list["ios"] = "ios_trunk"
jenkins_project_list["blackberry"] = "blackberry_trunk"

"""
get_svn_login is required for pysvn to set credentials
"""
def get_svn_login(realm, username, may_save):
   return True, "svninfoforbuild", "g3tV3rs10n", False
   
"""
query SVN for a list of tags. Look through that list for tags matching regex. 
figure out which of these was created last. return this tag.
"""
def svn_get_latest_tag_list(device, client, quantity):
   print("svn_get_latest_tag_list(" + device + ", " + str(client) + ", " + quantity + ")")
   reponame = svn_url + device + "/tags"
   # Get list of svn tags in the repo.
   svn_tag_list = client.list(reponame)
   svn_tag_coll = {}
   to_return = []
   
   # Create a collection of tags & sort the keys (timestamp)
   for tag in svn_tag_list:     
      m = re.search(r"" + reponame + "/(" + device + "-\d+\.\d+\.\d+\.\d+)$", tag[0]["path"])
      if m is not None:
         svn_tag_coll[tag[0]["time"]] = m.group(1)
   sorted_keys = sorted(svn_tag_coll)
   key_count = len(sorted_keys)
   # Pull only the quantity specified as an arg.
   startnum = key_count - int(quantity)
   endnum = key_count
   for l in reversed(range(startnum, endnum)):
      to_return.append(svn_tag_coll[sorted_keys[l]])
      
   # Reverse the order.
   return to_return


# Define initial variables.
device_type = None
quantity = 10

# Get args provided by user.
for arg in sys.argv:
   args = re.search(r"^--(\S+)=(\S+)$", arg)
   if args is not None:
      if re.search(r"^device_type$", args.group(1)):
         device_type = args.group(2).lower()
         
      if re.search(r"^quantity$", args.group(1)):
         quantity = args.group(2).lower()

if device_type in device_list:
   print(device_type + " is valid device")
else:
   sys.exit("ERROR: device_type does not match the required list of options (android, ios, blackberry)")


svn_trunk_url=svn_url + device_type + "/trunk"


jenkins_job_name = device_type + "_batch"


# accept arg: blackberry, android, ios
# use this arg. look in SVN//tags & get list of tags
# populate _batch job_to_execute with this list.

logging.basicConfig(level=logging.DEBUG)
jenkins = Jenkins.Jenkins(jenkins_url, jenkins_uid, jenkins_pwd, logging)


client = pysvn.Client()
client.callback_get_login = get_svn_login
tag_list =  svn_get_latest_tag_list(device_type, client, quantity)
#tag_list.insert(0, device_type + "_trunk")
tag_list.append(device_type + "_trunk")
xml_file_orig = jenkins.get_project_xml(jenkins_job_name)
xml_file_new = jenkins.batch_project_replace_job_list(xml_file_orig, tag_list, jenkins_job_name)
if(xml_file_new):
   print(jenkins.push_xml_to_project(jenkins_job_name, xml_file_new))
   os.remove(xml_file_new)
os.remove(xml_file_orig)

objects/Jenkins.py

import re
import time
import xml.etree.ElementTree as ET
#from xml.etree.ElementTree import ElementTree, Element, SubElement
import logging
import base64
import urllib
import urllib2
import JenkinsJob
import Brand
from urllib2 import URLError, HTTPError

class Jenkins:
   
   url = None
   username = None
   password = None
   logging = None
   base64string = None
   job_list_all = None
   logging = None
   et = None
   
   def __init__(self, url, username, password, logging):
      self = self
      self.url = url
      self.username = username
      self.password = password
      self.logging = logging
      self.base64string = base64.encodestring("%s:%s" % (username, password))[:-1]
      self.job_list_all = {}
      self.et = ET.ElementTree()
      
   def fetch_url(self, url):
      req = urllib2.Request(url)
      req.add_header("Authorization", "Basic %s" % self.base64string)
      results = None
      try:
         response = urllib2.urlopen(req)
         results = response.read()
      except URLError, e:
         #self.logging.debug("ERROR in Jenkins.fetchurl(" + url + ") => " + str(e))
         return False
      except HTTPError, e:
         #self.logging.debug("ERROR in Jenkins.fetchurl(" + url + ") => " + str(e))
         return False
      return results
      
   def get_project_xml(self, job_name):
      time_str = time.strftime("%Y-%m-%d_%H%M%S", time.localtime())
      jobxmlurl = self.url + "/job/" + job_name + "/config.xml"
      self.logging.debug("jobxmlurl = " + jobxmlurl)
      jobxml = self.fetch_url(jobxmlurl)
      if(jobxml):
         #self.logging.debug("jobxml = " + str(jobxml))
         filename = "./" + job_name + "_" + time_str + ".xml"
         f = open(filename, "w")
         f.write(jobxml)
         f.close()
         return filename
      else:
         return False
      #print jobxmlurl
   
   
   '''
   project_xml_replace_brand_list takes 2 args:
   xml_file_orig => the path to your xml file you would like modified.
   blist => a list of Brand objects which you would like as options in the dropdown.
   The XML will be modified to have all brands as options.
   XML STRUCTURE:
   
      ...
      
         
            
               ...
               
                  brand
                  ...
                  
                     
                        choice1
                        choice2
                     
                  
               
            
         
      
      ...
   
   '''
   def project_xml_replace_brand_list(self, xml_file_orig, blist, job_name):
      time_str = time.strftime("%Y-%m-%d_%H%M%S", time.localtime())
      project_elem = self.et.parse(xml_file_orig)
      if project_elem.find("properties") is not None:
         if project_elem.find("properties").find("hudson.model.ParametersDefinitionProperty") is not None:
            if project_elem.find("properties").find("hudson.model.ParametersDefinitionProperty").find("parameterDefinitions") is not None:
               try:
                  parameterDef = project_elem.find("properties").find("hudson.model.ParametersDefinitionProperty").find("parameterDefinitions")
                  parameters = list(parameterDef)
                  for param in parameters:
                     if param.find("name").text == "brand":
                        # THIS IS THE brand VAR
                        try:
                           # LOAD CORRECT PORTION OF XML
                           paramchoicesa = param.find("choices").find("a")
                           allchoices = list(paramchoicesa)
                           self.logging.debug("ORIGINAL CHOICE COUNT = " + str(len(allchoices)))
                           
                           # DELETE ALL PARAM CHOICES
                           paramchoicesa.clear()
                           
                           # DEFINE ALL PARAM CHOICES
                           paramchoicesa.set("class", "string-array")
                           #elem = ElementTree.Element("string")
                           #elem.text = "foo"
                           #paramchoicesa.append(elem)
                           for b in blist:
                              elem = ET.Element("string")
                              elem.text = b
                              paramchoicesa.append(elem)
                           #for b in blist.keys():
                           #   #print blist[b]
                           #   elem = Element("string")
                           #   elem.text = blist[b].id
                           #   paramchoicesa.append(elem)
                           allchoices = list(paramchoicesa)
                           print len(allchoices)
                           self.logging.debug("FINAL CHOICE COUNT = " + str(len(allchoices)))
                        except Exception, e:
                           self.logging.exception("EXCEPTION IN project_xml_replace_brand_list: " + str(e))
                  # MODIFICATION IS DONE. WRITE TO FILE.
                  newxmlname = "./" + job_name + "_new_" + time_str + ".xml"
                  self.et.write(newxmlname)
                  return newxmlname
               except Exception, e:
                  logging.exception(job_name + " does not follow appropriate xml format")
      return False
      

   def batch_project_replace_job_list(self, job_xml, job_list, job_name):
      time_str = time.strftime("%Y-%m-%d_%H%M%S", time.localtime())
      # 1) fetch job xml
      #jobxml = self.get_project_xml(job_name)
      project_elem = self.et.parse(job_xml)
      # 2) replace job_to_execute options with job_list
      if project_elem.find("properties") is not None:
         if project_elem.find("properties").find("hudson.model.ParametersDefinitionProperty") is not None:
            if project_elem.find("properties").find("hudson.model.ParametersDefinitionProperty").find("parameterDefinitions") is not None:
               try:
                  parameterDef = project_elem.find("properties").find("hudson.model.ParametersDefinitionProperty").find("parameterDefinitions")
                  parameters = list(parameterDef)
                  for param in parameters:
                     if param.find("name").text == "job_to_execute":
                        try:
                           # LOAD CORRECT PORTION OF XML
                           paramchoicesa = param.find("choices").find("a")
                           allchoices = list(paramchoicesa)
                           self.logging.debug("ORIGINAL CHOICE COUNT = " + str(len(allchoices)))
                           
                           # DELETE ALL PARAM CHOICES
                           paramchoicesa.clear()
                           
                           # DEFINE ALL PARAM CHOICES
                           paramchoicesa.set("class", "string-array")
                           for b in job_list:
                              elem = ET.Element("string")
                              elem.text = b
                              paramchoicesa.append(elem)
                           allchoices = list(paramchoicesa)
                           self.logging.debug("FINAL CHOICE COUNT = " + str(len(allchoices)))
                           print "job_to_execute"
                        except Exception, e:
                           self.logging.exception("EXCEPTION IN batch_project_replace_job_list: " + str(e))
                  # MODIFICATION IS DONE. WRITE TO FILE.
                  newxmlname = "./" + job_name + "_new_" + time_str + ".xml"
                  self.et.write(newxmlname)
                  return newxmlname
               except Exception, e:
                  logging.exception(job_name + " does not follow appropriate xml format")
      
   '''
   XML STRUCTURE:
   
      ...
      
         
            
               ...
               
                  brand
                     
                        http://test.freerange360.com/freenews/brandadmin?user=brandadmin&pw=s247-brand&type=brand
                     
                  
               
            
         
      
      ...
   
   
   REPLACE THE StringParameterDefinition WITH:
   
   
      name
      
         The brand you would like to build.
      
      
         
            JayHiggs
         
      
   
   
   '''
   def project_xml_replace_brand_with_choice(self, xml_file_orig, blist, job_name):
      #self.logging.debug("project_xml_replace_brand_with_choice(self, " + xml_file_orig + ", " + job_name + ")")
      # 1) Create the element which will be inserted.
      choicedef = ET.Element("hudson.model.ChoiceParameterDefinition")
      
      namedef = ET.Element("name")
      namedef.text = "brand"
      
      descdef = ET.Element("description")
      descdef.text = "The brand you would like to build"
      
      choicesdef = ET.Element("choices")
      choicesdef.set("class", "java.util.Arrays$ArrayList")
      
      adef = ET.Element("a")
      adef.set("class", "string-array")
      
      
      #choice1 = ET.Element("string")
      #choice1.text = "foo"
      
      choicedef.append(namedef)
      choicedef.append(descdef)
      
      
      for b in blist:
         choice = ET.Element("string")
         choice.text = b
         adef.append(choice)
      #adef.append(choice1)
      choicesdef.append(adef)
      choicedef.append(choicesdef)
      
      # AT THIS POINT, choicedef IS THE XML WHICH MUST BE INSERTED. 
      
      # NOW IT'S TIME TO DELETE THE APPROPRIATE PARAM FROM THE XML
      project_elem = self.et.parse(xml_file_orig)
      if project_elem.find("properties") is not None:
         if project_elem.find("properties").find("hudson.model.ParametersDefinitionProperty") is not None:
            if project_elem.find("properties").find("hudson.model.ParametersDefinitionProperty").find("parameterDefinitions") is not None:
               try:
                  parameterDef = project_elem.find("properties").find("hudson.model.ParametersDefinitionProperty").find("parameterDefinitions")
                  parameters = list(parameterDef)
                  for param in parameters:
                     if param.tag == "hudson.model.StringParameterDefinition" and param.find("name").text == "brand" :
                        self.logging.debug("---------------------------------------------------------")
                        print job_name
                        print str(param.tag)
                        # DELETE THIS PARAM 
                        parameterDef.remove(param)
                        # ADD OUR NEW PARAM
                        parameterDef.insert(0, choicedef)
                        #if param.find("name").text == "brand":
                        #   parameters.remove(param)
                        self.logging.debug("---------------------------------------------------------")
                  time_str = time.strftime("%Y-%m-%d_%H%M%S", time.localtime())
                  newxmlname = "./" + job_name + "_new_" + time_str + ".xml"
                  self.et.write(newxmlname)
                  return newxmlname
               except Exception, e:
                  logging.exception(job_name + " does not follow appropriate xml format")
      return False
      
      
      
      
      


   def copy_project_xml(self, new_proj_name, source_proj, new_proj_xml):
      # READ XML INTO MEMORY
      xml_contents = ""
      file = open(new_proj_xml, "r")
      for line in file:
         xml_contents += line
      file.close()
      # 1) CREATE A NEW JOB IN JENKINS
      job_create_url = self.url + "/createItem?name=" + new_proj_name
      self.logging.debug(job_create_url)
      req = urllib2.Request(job_create_url, data=xml_contents, headers={"Content-Type":"text/xml"})
      #base64string = base64.encodestring("%s:%s" % (jenkins_id, jenkins_pwd))[:-1]
      req.add_header("Authorization", "Basic %s" % self.base64string)
      response = urllib2.urlopen(req)
      create_results = response.read()
      
      
   def push_xml_to_project(self, proj_name, proj_xml):
      self.logging.debug("push_xml_to_project(self, " + proj_name + ", " + proj_xml + ")")
      jobxmlurl = self.url + "/job/" + proj_name + "/config.xml"
      #jobxmlurl = self.url + "/createItem?name=" + proj_name
      #jobxmlurl = self.url + "/job/" + proj_name + "/api/?"
      #jobxmlurl = "http://jenkins.freerange360.lan:8080/job/android_build_james/config.xml"
      xml_contents = ""
      file = open(proj_xml, "r")
      for line in file:
         xml_contents += line
      file.close()
      try:
         req = urllib2.Request(jobxmlurl, data=xml_contents, headers={"Content-Type":"text/xml"})
         #req = urllib2.Request(jobxmlurl, data=proj_xml)
         #req.get_method = lambda: 'POST'
         base64string = base64.encodestring("%s:%s" % (self.username, self.password))[:-1]
         req.add_header("Authorization", "Basic %s" % base64string)
         
         response = urllib2.urlopen(req)
         create_results = response.read()
         return create_results
      except Exception, e:
         logging.exception(str(e))
         return False
      
      
   def project_exists(self, pname):
      jobxmlurl = self.url + "/job/" + pname
      results = self.fetch_url(jobxmlurl)
      if results:
         return True
      else:
         return False
      
   def load_job_list_all(self):
      jl = {}
      myurl = self.url + "/api/xml"
      results = self.fetch_url(myurl)
      hudson_elem = ET.fromstring(results)
      jobs = hudson_elem.findall("job")
      for j in jobs:
         #self.logging.debug("j = " + str(j))
         self.logging.debug("job = JenkinsJob.JenkinsJob(" + j.find("name").text + ", " + j.find("url").text + ", " + self.username + ", " + self.password + ", self.logging.getLogger())")
         job = JenkinsJob.JenkinsJob(j.find("name").text, j.find("url").text, self.username, self.password, self.logging.getLogger())
         self.job_list_all[j.find("name").text] = job
         #self.logging.debug("name = " + j.find("name").text)
         #self.logging.debug("url = " + j.find("url").text)
      return len(self.job_list_all)
   
   def get_job_list_xml_view(self, view):
      myurl = self.url + "/view/" + view + "/api/xml"
      results = self.fetch_url(myurl)
      #print results

objects/JenkinsJob.py

import logging
import os
import re
import base64
import urllib
import urllib2
import xml.etree.ElementTree as ET
from objects import Helper
from objects import JenkinsBuild


class JenkinsJob:
   name = None
   url = None
   builds = {}  
   logdir = None
   base64string = None
   username = None
   password = None
   
   def __init__(self, name, url, username, password, logger):
      self = self
      self.name = name
      self.url = url
      self.logger = logger
      self.username = username
      self.password = password
      self.base64string = base64.encodestring("%s:%s" % (username, password))[:-1]
      self.helper = Helper.Helper(self.logger)
      
   def fetch_url(self, url):
      req = urllib2.Request(url)
      req.add_header("Authorization", "Basic %s" % self.base64string)
      results = None
      try:
         response = urllib2.urlopen(req)
         results = response.read()
      except URLError, e:
         #self.logging.debug("ERROR in Jenkins.fetchurl(" + url + ") => " + str(e))
         return False
      except HTTPError, e:
         #self.logging.debug("ERROR in Jenkins.fetchurl(" + url + ") => " + str(e))
         return False
      return results
      
   '''
   Load a list of all executions of this job
   '''
   def load_build_list_all(self):
      self.logger.debug("START JenkinsJob.load_build_list_all()")
      xmlurl = self.url + "/api/xml"
      results = self.fetch_url(xmlurl)
      jenkins_elem = ET.fromstring(results)
      builds = jenkins_elem.findall("build")
      temp_build_list = {}
      for b in builds:
         num =  b.find("number").text
         url =  b.find("url").text
         jb = JenkinsBuild.JenkinsBuild(int(num), url, self.username, self.password, self.logger)
         self.logger.debug("jb.number = '" + str(jb.number) + "'")
         #self.builds[k] = temp_build_list[k]
         #temp_build_list[jb.number] = jb
         self.builds[jb.number] = jb
      # This list is out of order. Order list based on jb.number
      #sorted_keys = sorted(temp_build_list)
      #for k in sorted_keys:
      #   self.logger.debug(k)
      #   self.builds[k] = temp_build_list[k]
      self.logger.debug("END JenkinsJob.load_build_list_all() => " + str(len(self.builds)))   
      
   '''
      Iterate through self.builds & load detail xml of each.
   '''
   def load_build_list_details(self):
      
      for bk in self.builds.keys():
         b = self.builds[bk]
         b.fetch_details_via_xml()

objects/JenkinsBuild.py

import base64
import urllib
import urllib2
import re
from objects import Helper
import xml.etree.ElementTree as ET
#import JenkinsJob

class JenkinsBuild:
   
   def __init__(self, number, url, username, password, logger):
      self = self
      self.number = number
      self.started_by = None
      self.timestamp = None
      self.fullDisplayName = None
      self.result = None
      self.building = None
      self.builtOn=None
      self.failure_reason = None
      self.url = url
      self.logger = logger
      self.username = username
      self.password = password
      self.parameters = {}
      
      self.base64string = base64.encodestring("%s:%s" % (username, password))[:-1]
      self.helper = Helper.Helper(self.logger)
      
   
   
   def fetch_url(self, url):
      req = urllib2.Request(url)
      req.add_header("Authorization", "Basic %s" % self.base64string)
      results = None
      try:
         response = urllib2.urlopen(req)
         results = response.read()                          
      except URLError, e:
         #self.logging.debug("ERROR in Jenkins.fetchurl(" + url + ") => " + str(e))
         return False
      except HTTPError, e:
         #self.logging.debug("ERROR in Jenkins.fetchurl(" + url + ") => " + str(e))
         return False
      return results
      
   def fetch_details_via_xml(self):
      self.logger.debug("START JenkinsBuild.fetch_details_via_xml")
      tempurl = self.url + "/api/xml"
      #http://jenkins.freerange360.lan:8080/job/android-4.0.0.16/47/api/xml
      self.logger.debug("fetch_url(" + tempurl + ")")
      xml = self.fetch_url(tempurl)
      fsb = ET.fromstring(xml)
      try:
         actions = fsb.findall("action")
         for a in actions:
            if a.findall("parameter"):
               parameters = a.findall("parameter")
               for p in parameters:
                  self.parameters[p.find("name").text] = p.find("value").text
            elif a.findall("cause"):
               cause = a.find("cause")
               self.started_by = cause.find("userName").text           
         #parameters = fsb.find("action").findall("parameter")
         #for p in parameters:
         #   self.parameters[p.find("name").text = p.find("value").text
            #print p.find("name").text + " = " + p.find("value").text
         #self.started_by = fsb.find("action").find("cause").find("userName")
         self.building = fsb.find("building").text
         self.duration = fsb.find("duration").text
         self.timestamp = fsb.find("id").text
         self.result = fsb.find("result").text
         self.builtOn = fsb.find("builtOn").text
         if self.result == "FAILURE":
            self.fetch_why_project_failed()
      except AttributeError, e:
         self.logger.debug("ERROR -> " + str(e))
         return False
              
            
      #self.logger.debug("END JenkinsBuild.fetch_details_via_xml")
      
   def fetch_why_project_failed(self):
      self.logger.debug("START JenkinsBuild.fetch_why_project_failed")
      tempurl = self.url + "/consoleText"
      self.logger.debug(tempurl)
      log = self.fetch_url(tempurl)
      self.log = log
      m = re.search("(No resource found that matches the given name)", log)
      if re.search("SVNException.*request\sfailed", log):
         self.failure_reason = "SVNException"
      elif re.search("UnknownHostException:\sfreerangeinc3\.virtual\.vps-host\.net", log):
         self.failure_reason = "Unable to FTP build"
      elif re.search("\[BEROR\]Code\sSign\serror", log):
         self.failure_reason = "Signing error"
      elif re.search("No\sresource\sidentifier\sfound\sfor\sattribute", log):
         self.failure_reason = "No resource identifier found error"
      elif re.search("(\[ERROR\]\sclient\.config\skey.*)", log):
         n = re.search("(\[ERROR\]\sclient\.config\skey.*)", log)
         self.failure_reason = n.group(1)
      elif re.search("error:\sError:\sNo\sresource\sfound\sthat\smatches\sthe\sgiven\sname", log):
         n = re.search("(error:\sError:\sNo\sresource\sfound\sthat\smatches\sthe\sgiven\sname.*)", log)
         self.failure_reason = n.group(1)
      elif re.search("ABORTED", log):
         self.failure_reason = "Aborted"
      elif m is not None:
         self.failure_reason = m.group(1)
         self.logger.debug("END JenkinsBuild.fetch_why_project_failed => " + self.failure_reason)
      elif re.search("Failure", log):
         self.failure_reason = "Unknown - look @ job"

objects/Helper.py

import os
import re
import time
import logging
class Helper:
   def __init__(self, logger):
      self = self
      self.logger = logger
   #def get_subdir_list(self, branddir):
   #   #print "get_subdir_list(self, " + branddir + ")"
   #   subdirs = []
   #   for adir in os.listdir(branddir):
   #      if re.search(r"^\.", adir):
   #         pass
   #      else:
   #         if os.path.isdir(os.path.join(branddir,adir)):
   #            subdirs.append(adir)
   #   subdirs.append(".")
   #   return subdirs
      
   def get_timestamp(self):
      return time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())
      
   def dir_get_file_list(self, parentdir):
      self.logger.debug("START Helper.dir_get_file_list(self, " + parentdir + ")")
      files = []
      for f in os.listdir(parentdir):
         self.logger.debug("f = " + str(f))
         if os.path.isfile(os.path.join(parentdir, f)):
            self.logger.debug("files.append(" + str(f) + ")")
            files.append(f)
      self.logger.debug("END Helper.dir_get_file_list(self, " + parentdir + ")")
      return files
               
   
   def dir_get_subdir_list(self, branddir):
      self.logger.debug("START get_subdir_list(self, " + branddir + ")")
      subdirs = []
      for adir in os.listdir(branddir):
         self.logger.debug("adir = " + str(adir))
         if re.search(r"^\.", adir):
            pass
         else:
            if os.path.isdir(os.path.join(branddir,adir)):
               self.logger.debug("subdirs.append(" + str(adir) + ")")
               subdirs.append(adir)
            else:
               self.logger.debug(str(adir) + " is not a dir")
      self.logger.debug("END get_subdir_list(self, " + branddir + ")")
      return subdirs
      
   def milliseconds_to_human_readable(self, millis):
      millis = int(millis)
      seconds_total = millis / 1000
      seconds = seconds_total % 60
      minutes_total = seconds_total / 60
      minutes = minutes_total % 60
      hours = minutes_total / 60
      return (hours, minutes, seconds)
   

objects/Brand.py


class Brand:
   id = None
   name = None
   
   def __init__(self, id, name):
      self = self
      self.id = id
      self.name = name
      
      

objects/Subversion.py

import pysvn
import re
import sys
import time
import datetime
import logging
class Subversion:
   user = ""
   pwd = ""
   url = ""
   checkout_path = None
   url = None
   client = None
   # status_list will be a collection of status_list[${file_path}] = ${is_versioned}
   status_list = {}
   logging = None
   def __init__(self, logging):
      self.user = "brandcreation"
      self.pwd = "newbrand"
      self.checkout_path = ""
      self.url = ""
      self.client = pysvn.Client()
      self.logging = logging
      try:
         self.client.callback_get_login = self.get_svn_login
      except Exception, e:
         sys.exit("Error: " + str(e))


   '''
   get_svn_login is required for pysvn to set credentials
   '''
   def get_svn_login(self, realm, username, may_save):
      return True, "brandcreation", "newbrand", False
      #return True, "cmuser@freerangeinc.com", "D3pl0y", False
   

   '''
   get_log_message is required for pysvn to for certain activities (such as copy)
   '''
   def get_log_message(self):
      #return True, "brandadmin created activity " + time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())
      return True, "FB-9390 - brandadmin created activity " + time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())
   
   '''
   Get the svn status of self.checkout_path
   Used to determine a list of modified / new files which need to be committed.
   Return size of list loaded.
   '''
   def load_status(self):
      self.status_list = self.client.status(self.checkout_path)
   
   def test_credentials(self):
      return 0   
       
   '''
   Get a list of only modified files. 
   REQUIRE: load_status must be called first.
   '''
   def get_changedfile_list(self):
      if len(self.status_list) is 0:
         return 0
      else:
         toreturn = {}
         for stat in self.status_list:
            if(str(stat.text_status) == "modified"):
               toreturn.append(stat)
         return toreturn
            
            
   '''
   Get a list of only new files. 
   REQUIRE: load_status must be called first.
   '''
   #def get_newfile_list(self):
   #   if len(self.status_list) is 0:
   #      return 0
   #   else:
   #      toreturn = {}
   #      for change in self.status_list.keys():
   #         if self.status_list[change] is "unversioned":
   #            toreturn[change] = self.status_list[change]
   #      return toreturn
         
   '''
   Add new files to SVN 
   REQUIRE: load_status must be called first.
   '''      
   #def commit_new_and_modded_files(self, message):
   #   if len(self.status_list) is 0:
   #      return 0
   #   else:
   #      for change in self.status_list.keys():
   #         if self.status_list[change] is 0:
   #            # SVN ADD
   #            self.client.add(change)
   #      result = self.client.checkin(self.checkout_path, message)
   #      return(result)
               
   def get_subdir_list(self):
      subdirlist = self.client.list(self.url)
      toreturn = []
      for d in subdirlist:
         bn = re.search(r".*/([\w\-]*)$", d[0]["path"])
         if bn is not None:
            toreturn.append(bn.group(1))
      return toreturn
   
   '''
   Add new files to svn
   REQUIRE: load_status must be called first.
   '''   
   def add_new_files(self):
      self.logging.debug("Subversion.add_new_files(self)")
      self.logging.debug("status_list size = " + str(len(self.status_list)))
      count = 0
      if len(self.status_list) is 0:
         return 0
      else:
         for stat in self.status_list:
            if(str(stat.text_status) == "unversioned"):
               self.client.add(stat.path)
               count = count + 1
      self.logging.debug("END Subversion.add_new_files(self) => " + str(count))
      return count
      
   def commit(self, message):
      log_message = message
      self.callback_get_log_message = self.get_log_message
      self.client.checkin(self.checkout_path, message)
      
   def checkout(self, url, path):
      self.logging.info("checkout(self, " + url + ", " + path + ")")
      try:
         self.callback_get_login = self.get_svn_login
         results = self.client.checkout(url, path)
         return results
      except pysvn.ClientError, e:
         self.logging.exception("ERROR CHECKING OUT " + url + " -> " +  str(e))
         sys.exit("ERROR CHECKING OUT " + url + " -> " +  str(e))
      
   def copy(self, source, dest, message):
      try:
         log_message = "SVN copy " + source + " to " + dest
         self.client.callback_get_log_message = self.get_log_message
         self.client.copy(source, dest)
      except Exception, e:
         sys.exit("ERROR in Subversion.copy: " + str(e))
   
   def remove(self, filepath):
      self.logging.debug("Subversion.remove(self, " + filepath + ")")
      try:
         self.client.callback_get_log_message = self.get_log_message
         self.client.remove(filepath)
      except Exception, e:
         self.logging.exception("ERROR in Subversion.remove of " + filepath + " => " + str(e))
         sys.exit("ERROR in Subversion.remove of " + filepath + " => " + str(e))
         
         
         
   def get_change_log(self, from_date):
      self.logging.debug("START get_change_log(" + str(from_date) + ")")
      
      rev = pysvn.Revision(pysvn.opt_revision_kind.date, from_date) 
      change_list = {}
      try:
         #change_list = self.client.log(self.url, revision_start=rev)
         change_list = self.client.log(self.url, revision_end=rev, discover_changed_paths=True)
               
      except Exception, e:
         sys.exit("ERROR in Subversion.log: " + str(e))
      self.logging.debug("END get_change_log(" + str(from_date) + ") => " + str(len(change_list)))   
      return change_list

Python script – Jenkins job copy

This is a script which uses the XML parsing tool ElementTree to copy one Jenkins job to another & replaces the SVN location to be the latest created tag.

import urllib
import urllib2
from urllib2 import URLError
import logging
import re
import os
import base64
import sys
import time
import pysvn
import xml.etree.ElementTree
from xml.etree.ElementTree import ElementTree, Element, SubElement

# ElementTree XML tutorial -> http://www.bigfatalien.com/?p=223

"""
get_svn_login is required for pysvn to set credentials
"""
def get_svn_login(realm, username, may_save):
   return True, "svninfoforbuild", "svninfoforbuild", False
   
"""
query SVN for a list of tags. Look through that list for tags matching regex. 
figure out which of these was created last. return this tag.
"""
def svn_get_latest_tag(device, client):
   logging.debug( "svn_get_latest_tag(" + device + ", Client)")
   reponame = svn_url + "/" + svn_repo_list[device] + "/tags"
   logging.debug( "reponame = " + reponame)
   taglist = client.list(reponame)
   logging.debug("taglist = " + str(taglist))
   maxtime = 0
   maxtag = None
   tagname = None
   for tag in taglist:
      #for x in tag[0]:
      #   logging.debug( str(x) + " = " + str(tag[0][x]))
      m = re.search(r"/(" + device + "-d+.d+.d+.d+)$", tag[0]["path"])
      if m is not None:
         if tag[0]["time"] > maxtime:
            tagname = m.group(1)
            maxtime = tag[0]["time"]
            maxtag = tag[0]["path"]
   logging.debug( "maxtime = " + str(maxtime))
   logging.debug( "maxtag = " + str(maxtag))
   logging.debug( "tagname = " + str(tagname))
   return maxtime, maxtag, tagname

"""
query SVN for a list of branchs. Look through that list for branchs matching regex. 
figure out which of these was created last. return this branch.
"""
def svn_get_latest_branch(device, client):
   logging.debug( "svn_get_latest_tag(" + device + ", Client)")
   reponame = svn_url + "/" + svn_repo_list[device] + "/branches"
   logging.debug( "reponame = " + reponame)
   branchlist = client.list(reponame)
   maxtime = 0
   maxtag = None
   branchname = None
   for branch in branchlist:
      logging.debug( "------------------------")
      for x in branch[0]:
         logging.debug( str(x) + " = " + str(branch[0][x]))
      logging.debug( str(branch[0]["time"]) + " > " + str(maxtime))
      m = re.search(r"/(" + device + "-d+.d+.d+.[dw]+)$", branch[0]["path"])
      if m is not None:
         logging.debug( "m is not None")
         if branch[0]["time"] > maxtime:
            branchname = m.group(1)
            maxtime = branch[0]["time"]
            maxbranch = branch[0]["path"]
            logging.debug( "********* branchname == " + branchname)
            logging.debug( "------ maxtime == " + str(maxtime))
      logging.debug( "------------------------")
      
   logging.debug( "maxtime = " + str(maxtime))
   logging.debug( "maxbranch = " + str(maxbranch))
   logging.debug( "branchname = " + str(branchname))
   return maxtime, maxbranch, branchname

def jenkins_get_project_xml(device, timestr):
   jobxmlurl = jenkins_url + "/job/" + jenkins_project_list[device] + "/config.xml"
   req = urllib2.Request(jobxmlurl)
   base64string = base64.encodestring("%s:%s" % (jenkins_id, jenkins_pwd))[:-1]
   req.add_header("Authorization", "Basic %s" % base64string)
   response = urllib2.urlopen(req)
   jobxml = response.read()
   f = open("./" + device + "_config_" + timestr + ".xml", "w")
   f.write(jobxml)
   f.close()
   return "./" + device + "_config_" + timestr + ".xml"
   #logging.debug( jobxmlurl)

def jenkins_push_project_xml(new_proj_name, source_proj, new_proj_xml):
   # READ XML INTO MEMORY
   xml_contents = ""
   file = open(new_proj_xml, "r")
   for line in file:
      xml_contents += line
   file.close()
   
   # 1) CREATE A NEW JOB IN JENKINS
   job_create_url = jenkins_url + "/createItem?name=" + new_proj_name
   logging.debug( job_create_url)
   req = urllib2.Request(job_create_url, data=xml_contents, headers={"Content-Type":"text/xml"})
   base64string = base64.encodestring("%s:%s" % (jenkins_id, jenkins_pwd))[:-1]
   req.add_header("Authorization", "Basic %s" % base64string)
   response = urllib2.urlopen(req)
   create_results = response.read()
   
def jenkins_project_exists(pname):
   logging.debug("jenkins_project_exists(" + pname + ")")
   jobxmlurl = jenkins_url + "/job/" + pname
   logging.debug( "jobxmlurl = " + jobxmlurl)
   req = urllib2.Request(jobxmlurl)
   base64string = base64.encodestring("%s:%s" % (jenkins_id, jenkins_pwd))[:-1]
   req.add_header("Authorization", "Basic %s" % base64string)
   try:
      response = urllib2.urlopen(req)
   except URLError, e:
      return False
   return True
   
def svn_get_trunk_url(device):
   return svn_url + "/" + svn_repo_list[device] + "/trunk"

def process_xml(device, tagname, jobxml, svn_trunk_url, svn_maxtag_url, timestr):
   
   # Element - XML elements containing:
   #           the label (tag), 
   #           a list of attributes
   #           a list of chilren elements (forming the XML tree hierarchy)
   # Elementtree - The wrappers around Element objects which provide facilities to output the Element as an xml file
   #               You can also read an xml file into an ElementTree then access teh Elements within.
   
   # CREATE AN ELEMENT TREE OBJECT
   et = ElementTree()
   # PARSE THE XML FILE.
   project_elem = et.parse(jobxml)
   
   
   logging.debug( "--------------------------------------------")
   # REPLACE THE SCM LOCATION POINTING TO TRUNK WITH ONE POINTING TO THE NEW TAG
   # Structure = 
   #
   #  ...
   #  projectname
   #  ...
   #  
   #     
   #        
   #           ...
   #           ...
   #        
   #        ...
   #     
   #     ...
   #  
   #  ...
   #
   # FIND THE FIRST description ELEMENT 
   de = project_elem.find("description")
   de.text = device + " TAG " + tagname
   scme = project_elem.find("scm")
   loce = scme.find("locations")
   location_children = list(loce)
   logging.debug( "svn_trunk_url = " + svn_trunk_url)
   for l in location_children:
      remote = l.find("remote")
      local = l.find("local")
      m = re.search(r"^" + svn_trunk_url + "(/src)?$", remote.text) 
      if m is not None:
         newstr = svn_maxtag_url
         if m.group(1) is not None:
            newstr += m.group(1)
         logging.debug( newstr)
         remote.text=newstr
   newxmlname = "./" + device + "_config_new_" + timestr + ".xml" 
   et.write(newxmlname);
   return(newxmlname);
   
   
   
svn_url="https://svn.company.com"
#device_type="ios"
jenkins_url="http://jenkins.corp.company.com:8080"
job_sub_http="job"

svn_repo_list={}
svn_repo_list["android"] = "android"
svn_repo_list["ios"] = "ios"
svn_repo_list["blackberry"] = "blackberry"

jenkins_project_list={}
jenkins_project_list["android"] = "android_trunk"
jenkins_project_list["ios"] = "ios_trunk"
jenkins_project_list["blackberry"] = "blackberry_trunk"

jenkins_id = "tag_creator"
jenkins_pwd = "1qazxsw2"

job_file="config.xml"

logging.basicConfig(level=logging.DEBUG)

timestr = time.strftime("%Y-%m-%d_%H%M%S", time.localtime())

device_type = None
svn_loc = "tags"
for arg in sys.argv:
   args = re.search(r"^--(S+)=(S+)$", arg)
   if args is not None:
      if re.search(r"^device_type$", args.group(1)):
         device_type = args.group(2).lower()
         logging.debug("device_type = " + device_type)
      elif re.search(r"^svn_loc$", args.group(1)):
         svn_loc = args.group(2)
         logging.debug("svn_loc = " + svn_loc)


try:
   repo = svn_repo_list[device_type]
   logging.debug("repo = " + repo)
except KeyError, e:
   sys.exit("ERROR: device_type does not match the required list of options (android, ios, blackberry)")
   
svn_trunk_url=svn_url +  repo + "/trunk"
logging.debug("svn_trunk_url = " + svn_trunk_url)

client = pysvn.Client()
client.callback_get_login = get_svn_login

maxtime = None
svn_maxtag_url = None
reponame = None


if svn_loc == "tags":
   maxtime, svn_maxtag_url, reponame =  svn_get_latest_tag(device_type, client)
elif svn_loc == "branches":
   maxtime, svn_maxtag_url, reponame =  svn_get_latest_branch(device_type, client)
else:
   sys.exit("ERROR: You cannot use svn_loc = " + svn_loc)
   
logging.debug("maxtime = " + str(maxtime))
logging.debug("svn_maxtag_url = " + str(svn_maxtag_url))
logging.debug("reponame = " + str(reponame))


project_exists = jenkins_project_exists(reponame)
logging.debug("project_exists = " + str(project_exists))
if project_exists:
   sys.exit("ERROR: The Jenkins job " + reponame + " already exists.")
   
origxml = jenkins_get_project_xml(device_type, timestr)
newxml = process_xml(device_type, reponame, origxml, svn_trunk_url, svn_maxtag_url, timestr)
jenkins_push_project_xml(reponame, jenkins_project_list[device_type], newxml)

os.remove(origxml)
os.remove(newxml)

Jenkins slave in Windows 7

  1. In Windows Services, turn on “Remote Registry”
  2. In your firewall, open ports for inbound connections: TCP – 135,139,445; UDP – 137,138
  3. Overcome Windows 7 “security” problem via instructions
  4. Run powershell as an Administrator.
    1. Type Enable-PSRemoting
    2. Enter Yes for All
  5. Reboot
  6. Install the slave through Jenkins
  7. Modify the slave service’s “Log on as:” to be the same credentials as the Jenkins client.
  8. Reboot

Command /usr/bin/codesign failed with exit code 1

When signing an ios app via ANT cmd

<exec executable="/usr/bin/open">
<arg value="${env.WORKSPACE}/provisioning_profiles/${provisioning_profile}.mobileprovision"/>
</exec>
<echo>
Sleep 10 secs
</echo>
<exec executable="/bin/sleep">
<arg value="10"/>
</exec>
<echo>
/usr/bin/osascript -e tell application "Xcode" to quit
</echo>
<exec executable="/usr/bin/osascript">
<arg value="-e"/>
<arg value='tell application "Xcode" to quit'/>
</exec>
<echo>
Sleep 10 secs
</echo>
<exec executable="/bin/sleep">
<arg value="10"/>
</exec>
<echo>
/usr/bin/security unlock-keychain -p password ${keychain}
</echo>
<exec executable="/usr/bin/security" failonerror="true">
<arg value="unlock-keychain"/>
<arg value="-p"/>
<arg value="password"/>
<arg value="${keychain}"/>
</exec>
<echo>iPhone-build starting</echo>
<echo>xcodebuild clean -project MyCompany.xcodeproj -target Aggregate -configuration ${buildTarget} CODE_SIGN_IDENTITY=${codeSignIdentity} OTHER_CODE_SIGN_FLAGS="--keychain ${keychain}" PROVISIONING_PROFILE=${mopro_key}</echo>
<exec executable="xcodebuild" failonerror="true">
<arg value="clean"/>
<arg value="-project"/>
<arg value="MyCompany.xcodeproj"/>
<arg value="-target"/>
<arg value="Aggregate"/>
<arg value="-configuration"/>
<arg value="${buildTarget}"/>
<arg value="CODE_SIGN_IDENTITY=${codeSignIdentity}"/>
<arg line="OTHER_CODE_SIGN_FLAGS=&quot;--keychain ${keychain}&quot;"/>
<arg value="PROVISIONING_PROFILE=${mopro_key}"/>
</exec>
<echo>xcodebuild -project MyCompany.xcodeproj -target Aggregate -configuration ${buildTarget} CODE_SIGN_IDENTITY=${codeSignIdentity} OTHER_CODE_SIGN_FLAGS="--keychain ${keychain}" PROVISIONING_PROFILE=${mopro_key} GCC_PREPROCESSOR_DEFINITIONS='${preprocdefs}'</echo>
<echo>
SVN_INFO_URL = ${svn.info.url}
SVN_INFO_REV ="${svn.info.rev}
</echo>
<exec executable="xcodebuild" failonerror="true">
<arg value="-project"/>
<arg value="MyCompany.xcodeproj"/>
<arg value="-target"/>
<arg value="Aggregate"/>
<arg value="-configuration"/>
<arg value="${buildTarget}"/>
<arg value="CODE_SIGN_IDENTITY=${codeSignIdentity}"/>
<arg line="OTHER_CODE_SIGN_FLAGS=&quot;--keychain ${keychain}&quot;"/>
<arg value="PROVISIONING_PROFILE=${mopro_key}"/>
<arg value="GCC_PREPROCESSOR_DEFINITIONS='${preprocdefs}'"/>
</exec>

I see the error:

     [exec] CodeSign build/AdHoc-iphoneos/myapp.app
     [exec]     cd /opt/jenkins/workspace/iOS_build_3.4/client/iOS
     [exec]     setenv CODESIGN_ALLOCATE /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate
     [exec]     setenv PATH "/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin"
     [exec]     /usr/bin/codesign --force --sign "iPhone Distribution: My Company" --resource-rules=/opt/jenkins/workspace/iOS_build_3.4/client/iOS/build/AdHoc-iphoneos/myapp.app/ResourceRules.plist --keychain /Users/cmuser/Library/Keychains/login.keychain --entitlements /opt/jenkins/workspace/iOS_build_3.4/client/iOS/build/company.build/AdHoc-iphoneos/iPhoneClient.build/myapp.xcent /opt/jenkins/workspace/iOS_build_3.4/client/iOS/build/AdHoc-iphoneos/myapp.app
     [exec] /opt/jenkins/workspace/iOS_build_3.4/client/iOS/build/AdHoc-iphoneos/myapp.app: User interaction is not allowed.
     [exec] Command /usr/bin/codesign failed with exit code 1
     [exec] 
     [exec] ** BUILD FAILED **
     [exec] 
     [exec] 
     [exec] The following build commands failed:
     [exec] 	CodeSign build/AdHoc-iphoneos/myapp.app
     [exec] (1 failure)
     [exec] 

BUILD FAILED
/opt/jenkins/workspace/iOS_build_3.4/clientBuildPackager/build_osx_CM.xml:136: The following error occurred while executing this line:
/opt/jenkins/workspace/iOS_build_3.4/clientBuildPackager/build_osx_CM.xml:141: The following error occurred while executing this line:
/opt/jenkins/workspace/iOS_build_3.4/clientBuildPackager/build_osx_CM.xml:147: The following error occurred while executing this line:
/opt/jenkins/workspace/iOS_build_3.4/clientBuildPackager/build_osx_CM.xml:157: The following error occurred while executing this line:
/opt/jenkins/workspace/iOS_build_3.4/clientBuildPackager/build_osx_CM.xml:283: The following error occurred while executing this line:
/opt/jenkins/workspace/iOS_build_3.4/clientBuildPackager/build_osx_CM.xml:518: The following error occurred while executing this line:
/opt/jenkins/workspace/iOS_build_3.4/client/iOS/build_CM.xml:580: The following error occurred while executing this line:
/opt/jenkins/workspace/iOS_build_3.4/client/iOS/build_CM.xml:523: The following error occurred while executing this line:
/opt/jenkins/workspace/iOS_build_3.4/client/iOS/build_CM.xml:397: exec returned: 65

Note I am already unlocking the keychain. Solution: The Key used by ${codeSignIdentity} “iPhone Distribution: My Company” Certificate does not have Access Control granted to codesign

  1. Open your keychain in Keychain Access
  2. Select Certificates category
  3. Maximize so you can see the Key under the Cert
  4. Double click the key then select “Access Control”
  5. Ensure codesign is listed in the “Always allow access by these applications:”

— If it is not:

  1. Click the +
  2. HitG & in the popup window, enter /usr/bin then click Go
  3. Select codesign & click Add
  4. Click Save Changes then enter your password

Enable SSH on OSX for Jenkins Client

In order to have a Jenkins client running on OSX, you must edit the RSAAuthentication. If you try to setup an OSX box as a Jenkins client & see the following error:

[08/16/11 11:26:46] [SSH] Opening SSH connection to cmosx01:22.
[08/16/11 11:26:46] [SSH] Authenticating as cmuser/******.
java.io.IOException: Password authentication failed.
	at com.trilead.ssh2.auth.AuthenticationManager.authenticatePassword(AuthenticationManager.java:319)
	at com.trilead.ssh2.Connection.authenticateWithPassword(Connection.java:314)
	at hudson.plugins.sshslaves.SSHLauncher.openConnection(SSHLauncher.java:590)
	at hudson.plugins.sshslaves.SSHLauncher.launch(SSHLauncher.java:198)
	at hudson.slaves.SlaveComputer$1.call(SlaveComputer.java:199)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
	at java.util.concurrent.FutureTask.run(FutureTask.java:166)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:679)
Caused by: java.io.IOException: Authentication method password not supported by the server at this stage.
	at com.trilead.ssh2.auth.AuthenticationManager.authenticatePassword(AuthenticationManager.java:289)
	... 9 more
[08/16/11 11:26:46] [SSH] Connection closed.
...

Then you need to ensure you enabled PasswordAuthentication in your sshd_config file. Edit /etc/sshd_config, adding PasswordAuthentication yes

...
# To disable tunneled clear text passwords both PasswordAuthentication and
# ChallengeResponseAuthentication must be set to "no".
PasswordAuthentication yes
#PasswordAuthentication no
#PermitEmptyPasswords no
...