OpenNebula XML-RPC API client
This commit is contained in:
parent
30d1bed8a5
commit
3173bf5db3
|
@ -0,0 +1,181 @@
|
||||||
|
@Grab('org.codehaus.groovy:groovy-xmlrpc:0.8')
|
||||||
|
import groovy.net.xmlrpc.*
|
||||||
|
import groovy.util.XmlSlurper
|
||||||
|
import groovy.util.slurpersupport.GPathResult
|
||||||
|
import groovy.util.slurpersupport.NodeChild
|
||||||
|
import groovy.xml.XmlUtil
|
||||||
|
|
||||||
|
class Client {
|
||||||
|
|
||||||
|
String oneAuth
|
||||||
|
String url
|
||||||
|
Script script
|
||||||
|
|
||||||
|
// Voir http://groovy-lang.org/processing-xml.html pour plus d'informations
|
||||||
|
// sur le traitement du XML en Groovy
|
||||||
|
|
||||||
|
// OpenNebula RPC API
|
||||||
|
|
||||||
|
@NonCPS
|
||||||
|
XMLRPCServerProxy createProxy() {
|
||||||
|
return new XMLRPCServerProxy(url, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Voir https://docs.opennebula.org/5.6/integration/system_interfaces/api.html#one-templatepool-info
|
||||||
|
@NonCPS
|
||||||
|
GPathResult templatepoolInfo(int filter = -2, int start = -1, int end = -1) {
|
||||||
|
def proxy = createProxy()
|
||||||
|
def results = proxy."one.templatepool.info"(oneAuth, filter, start, end)
|
||||||
|
assert results[0] : results[1]
|
||||||
|
return new XmlSlurper().parseText(results[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Voir https://docs.opennebula.org/5.6/integration/system_interfaces/api.html#one-vm-allocate
|
||||||
|
@NonCPS
|
||||||
|
Integer vmAllocate(String template, Boolean hold = false) {
|
||||||
|
def proxy = createProxy()
|
||||||
|
def results = proxy."one.vm.allocate"(oneAuth, template, hold)
|
||||||
|
assert results[0] : results[1]
|
||||||
|
return results[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Voir https://docs.opennebula.org/5.6/integration/system_interfaces/api.html#one-vm-action
|
||||||
|
@NonCPS
|
||||||
|
Integer vmAction(String actionName, Integer objectId) {
|
||||||
|
def proxy = createProxy()
|
||||||
|
def results = proxy."one.vm.action"(oneAuth, actionName, objectId)
|
||||||
|
assert results[0] : results[1]
|
||||||
|
return results[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Voir https://docs.opennebula.org/5.6/integration/system_interfaces/api.html#one-vm-info
|
||||||
|
@NonCPS
|
||||||
|
GPathResult vmInfo(Integer objectId) {
|
||||||
|
def proxy = createProxy()
|
||||||
|
def results = proxy."one.vm.info"(oneAuth, objectId)
|
||||||
|
assert results[0] : results[1]
|
||||||
|
return new XmlSlurper().parseText(results[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utilitaires de haut niveau pour les pipelines Jenkins
|
||||||
|
|
||||||
|
// Retrouve un template de VM via son nom
|
||||||
|
@NonCPS
|
||||||
|
NodeChild findVMTemplate(String name) {
|
||||||
|
def templates = templatepoolInfo()
|
||||||
|
def result = null
|
||||||
|
templates.'*'.each {
|
||||||
|
if (it.NAME.text().trim() == name) {
|
||||||
|
result = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Démarre une VM, exécute les étapes passées en paramètres
|
||||||
|
// puis supprime la VM
|
||||||
|
@NonCPS
|
||||||
|
void withNewVM(String templateName, Boolean terminateOnExit = true, Closure body) {
|
||||||
|
|
||||||
|
def tmpl = findVMTemplate(templateName)
|
||||||
|
def id = vmAllocate(XmlUtil.serialize(tmpl.TEMPLATE))
|
||||||
|
tmpl = null
|
||||||
|
|
||||||
|
script.println("Démarrage de la VM '${id}'...")
|
||||||
|
|
||||||
|
def info = vmInfo(id)
|
||||||
|
|
||||||
|
script.println("En attente du démarrage de la VM...")
|
||||||
|
while(info.STATE.toInteger() != 3 || info.LCM_STATE.toInteger() != 3) {
|
||||||
|
sleep(5000)
|
||||||
|
info = vmInfo(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
script.println("VM démarrée.")
|
||||||
|
|
||||||
|
def ip = info.TEMPLATE.NIC.IP.text()
|
||||||
|
info = null
|
||||||
|
|
||||||
|
runThenTerminate(id, ip, terminateOnExit, body)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void runThenTerminate(Integer id, String ip, Boolean terminateOnExit, Closure body) {
|
||||||
|
try {
|
||||||
|
body(ip)
|
||||||
|
} finally {
|
||||||
|
if (terminateOnExit) {
|
||||||
|
script.println("Suppression de la VM '${id}'...")
|
||||||
|
vmAction("terminate", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonCPS
|
||||||
|
def init(String url, String username, String password, Closure body) {
|
||||||
|
def oneAuth = "${username}:${password}"
|
||||||
|
def client = new Client(oneAuth: oneAuth, url: url, script: this)
|
||||||
|
proxy = null
|
||||||
|
body.call(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
def initWithCredentials(String urlCredentialsId, String userCredentialsId, Closure body) {
|
||||||
|
withCredentials([
|
||||||
|
string(credentialsId: urlCredentialsId, variable: 'NEBULA_URL'),
|
||||||
|
usernamePassword(credentialsId: userCredentialsId, usernameVariable: 'NEBULA_USERNAME', passwordVariable: 'NEBULA_PASSWORD')
|
||||||
|
]) {
|
||||||
|
init(env.NEBULA_URL, env.NEBULA_USERNAME, env.NEBULA_PASSWORD, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def runInNewVM(Map args) {
|
||||||
|
|
||||||
|
def urlCredentialsId = args.get('urlCredentialsId', 'opennebula-dev-url')
|
||||||
|
def userCredentialsId = args.get('userCredentialsId', 'kipp-credentials')
|
||||||
|
def sshCredentialsId = args.get('sshCredentialsId', 'kipp-opennebula-dev-ssh-keypair')
|
||||||
|
def vmTemplate = args.get('vmTemplate', '')
|
||||||
|
def terminateOnExit = args.get('terminateOnExit', true)
|
||||||
|
def shell = args.get("shell", "/bin/sh")
|
||||||
|
def script = args.get('script', '')
|
||||||
|
|
||||||
|
// On récupère les identifiants de connexion SSH pour la VM
|
||||||
|
withCredentials([
|
||||||
|
sshUserPrivateKey(credentialsId: sshCredentialsId, keyFileVariable: 'VM_SSH_KEY')
|
||||||
|
]) {
|
||||||
|
initWithCredentials(urlCredentialsId, userCredentialsId) { client ->
|
||||||
|
client.withNewVM(vmTemplate, terminateOnExit) { host ->
|
||||||
|
|
||||||
|
def sshArgs = "-i ${VM_SSH_KEY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
||||||
|
|
||||||
|
// On attend que la connexion SSH soit disponible
|
||||||
|
println "En attente de l'accès SSH..."
|
||||||
|
waitUntil {
|
||||||
|
try {
|
||||||
|
sh "ssh -q ${sshArgs} -o ConnectTimeout=1 root@${host} exit"
|
||||||
|
return true
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// On créait un script temporaire à exécuter sur la machine distante
|
||||||
|
def now = System.currentTimeMillis()
|
||||||
|
def tempScriptFile = "script_${env.BUILD_ID}_${now}.sh"
|
||||||
|
writeFile(file: tempScriptFile, text: """
|
||||||
|
#!${shell}
|
||||||
|
${script.stripIndent()}
|
||||||
|
""")
|
||||||
|
|
||||||
|
// On transfère le script sur la machine distante et on l'exécute
|
||||||
|
sh """
|
||||||
|
scp ${sshArgs} '${tempScriptFile}' 'root@${host}:/tmp/${tempScriptFile}'
|
||||||
|
ssh ${sshArgs} root@${host} 'chmod +x /tmp/${tempScriptFile}; /tmp/${tempScriptFile}'
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue