I. Déploiement de l'API :▲
<?php
//
Liste
complète
des
appels
possibles
:
http://download.cloud.com/releases/3.0.6/api_3.0.6/TOC_User.html
#
###############################
#
Paramètres
généraux
de
l'API
#
#
###############################
//
Renseignez
ici
votre
clef
API
ainsi
que
votre
clef
secrète
//
Nous
conseillons
de
déporter
cette
information
au
sein
d'un
autre
fichier
PHP
dont
on
restreindra
l'accès
define("
APIKEY
"
,
"
d1Ii4ON33yqUahgtlsjnzK0o7QXNzXZONZKcW_rDcOV4jln48b5ujsSvU
-
mo9KsoLbp631VyCI4fLb3u176JZg
"
);
define("
SECRETKEY
"
,
"
fBenapO2hjOd3Vaj
-
NDmrekTIK85B8Jl_m8wFld4gi0XvLXy4w0iJz
-
2srztoVqkGVoblT25DyG4709gibo_TA
"
);
//
On
définit
l'URL
d'appel
de
l'API
(ou
'EndPoint')
define("
ENDPOINT
"
,
"
https
:
/
/
cloudstack
.
ikoula
.
com
/
client
/
api
"
);
#
############################################################
#
Paramètres
utilisateur
de
configuration
d(es)
instance(s)
#
#
############################################################
//
Première
instance
:
/*
UUID(s)
du
réseau
auquel
sera
connectée
votre
instance.
Utilisez
la
requête
API
'listNetworks'
ou
l'interface
pour
lister
les
réseaux
existants
et
déterminer
le
réseau
voulu
*/
$
vm01
[
'
conf
'
]
[
'
networkid
'
]
=
"
&
lt
;
ID
DU
RESEAU
QUE
VOUS
SOUHAITEZ
UTILISER
>
"
;
/*
UUID
de
l'offre
de
service
(configuration
matérielle)
voulue.
Utilisez
la
requête
API
'listServiceOfferings'
pour
lister
les
offres
existantes.
Actuellement
:
-
m1.small
:
c6b89fea-1242-4f54-b15e-9d8ec8a0b7e8
-
m1.medium
:
8dae8be9-5dae-4f81-89d1-b171f25ef3fd
-
m1.large
:
d2b2e7b9-4ffa-419e-9ef1-6d413f08deab
-
m1.extralarge
:
1412009f-0e89-4cfc-a681-1cda0631094b
*/
$
vm01
[
'
conf
'
]
[
'
serviceofferingid
'
]
=
"
&
lt
;
ID
DE
L
'
OFFRE
DE
SERVICE
A
UTILISER
>
"
;
/*
UUID
du
modèle
de
systeme
d'exploitation.
Vous
pouvez
aussi
utiliser
la
requête
API
'listTemplates'
pour
lister
les
modèles
existants.
Dans
notre
exemple
nous
allons
nous
baser
sur
le
template
'Debian
7
-
Minimal
-
64bits'
*/
$
vm01
[
'
conf
'
]
[
'
templateid
'
]
=
"
6d5b069b
-
4268
-
4c7c
-
810f
-
2793c2ac44fb
"
;
/*
Nom
de
votre
choix
pour
l'instance
(Nom
de
la
machine
et
d'affichage
dans
l'interface)
Caractères
alphanumériques
uniquement.
Ce
nom
doit
être
unique
au
sein
de
votre
réseau.
*/
$
vm01
[
'
conf
'
]
[
'
hostname
'
]
=
"
&
lt
;
NOM
DE
VOTRE
INSTANCE
>
"
;
/*
------------------------------
NE
PLUS
RIEN
MODIFIER
APRES
CETTE
LIGNE
-----------------------------------
*/
$
json_response
=
null;
#
###############################################
#
Récupération
de
l'ID
de
zone
pour
ce
network
#
#
###############################################
//
Requête
API
$
args
[
'
command
'
]
=
"
listNetworks
"
;
//
On
reprend
l'ID
de
réseau
renseigné
plus
tôt
$
args
[
'
id
'
]
=
$
vm01
[
'
conf
'
]
[
'
networkid
'
]
;
//
Execution
de
la
requête
sendRequest($
args
,
$
json_response
);
//
Stockage
de
l'ID
de
zone
pour
ce
réseau
$
vm01
[
'
conf
'
]
[
'
zoneid
'
]
=
$
json_response
[
'
listnetworksresponse
'
]
[
"
network
"
]
[
0
]
[
'
zoneid
'
]
;
//
On
réinitialise
les
variables
utilisées
pour
l'envoi
de
requêtes
API
unset($
args
);
#
#####################################################
#
Récupération
de
l'id
de
l'adresse
IP
de
ce
network
#
#
#####################################################
//
Requête
API
$
args
[
'
command
'
]
=
"
listPublicIpAddresses
"
;
$
args
[
'
associatednetworkid
'
]
=
$
vm01
[
'
conf
'
]
[
'
networkid
'
]
;
//
Execution
de
la
requête
sendRequest($
args
,
$
json_response
);
//
Stockage
de
l'ID
de
l'adresse
IP
publique
du
réseau
$
vm01
[
'
conf
'
]
[
'
publicIPid
'
]
=
$
json_response
[
'
listpublicipaddressesresponse
'
]
[
"
publicipaddress
"
]
[
0
]
[
'
id
'
]
;
//
On
réinitialise
les
variables
utilisées
pour
l'envoi
de
requêtes
API
unset($
args
);
#
###################################
#
Création
de
la
première
instance
#
#
###################################
//
Requête
API
$
args
[
'
command
'
]
=
"
deployVirtualMachine
"
;
$
args
[
'
zoneid
'
]
=
$
vm01
[
'
conf
'
]
[
'
zoneid
'
]
;
$
args
[
'
serviceofferingid
'
]
=
$
vm01
[
'
conf
'
]
[
'
serviceofferingid
'
]
;
$
args
[
'
templateid
'
]
=
$
vm01
[
'
conf
'
]
[
'
templateid
'
]
;
$
args
[
'
networkids
'
]
=
$
vm01
[
'
conf
'
]
[
'
networkid
'
]
;
$
args
[
'
name
'
]
=
$
vm01
[
'
conf
'
]
[
'
hostname
'
]
;
//
Hostname
$
args
[
'
displayname
'
]
=
$
args
[
'
name
'
]
;
//
Nom
d'affichage
//
Type
de
retour
:
JSON
ou
XML
(par
défaut
:
XML)
$
args
[
'
response
'
]
=
"
json
"
;
//
On
réinitialise
les
variables
avant
l'appel
API
//
Initialisation
du
client
API
sendRequest($
args
,
$
json_response
);
//
On
vérifie
la
presence
d'un
Job
if(preg_match("
/
^
[
0
-
9a
-
f\
-
]
+
$
/
"
,
$
json_response
[
'
deployvirtualmachineresponse
'
]
[
'
jobid
'
]
) >
0
)
{
$
jobs
[
]
=
$
json_response
[
'
deployvirtualmachineresponse
'
]
[
'
jobid
'
]
;
}
else{
echo "
ID
de
job
non
trouvé
.
\n
"
;
}
//
On
mémorise
la
correspondance
name/id
de
l'instance
au
sein
d'un
tableau
$
vm01
[
'
conf
'
]
[
'
id
'
]
=
$
json_response
[
'
deployvirtualmachineresponse
'
]
[
'
id
'
]
;
//
On
utilise
la
fonction
de
vérification
des
jobs
asynchrones
if(!
checkJobs($
jobs
))
exit;
/*
--------------------------------
Création
des
règles
de
sortie
--------------------------------
*/
//
On
réinitialise
les
variables
utilisées
pour
l'envoi
de
requêtes
API
unset($
args
);
#
###############
#
Ping
sortant
#
#
###############
$
args
[
'
command
'
]
=
"
createEgressFirewallRule
"
;
$
args
[
'
networkid
'
]
=
$
vm01
[
'
conf
'
]
[
'
networkid
'
]
;
//
Définition
du
protocole
a
filtrer
ici
ICMP
(utiliser
pour
les
ping),
les
protocole
sont
ICMP/UDP/TCP
$
args
[
'
protocol
'
]
=
"
ICMP
"
;
//
Définition
du
masque
réseau
qui
nous
permet
d'autoriser
certainne
IP,
//
ici
nous
acceptons
"le
ping"
vers
toute
les
IPs
$
args
[
'
cidrlist
'
]
=
"
0
.
0
.
0
.
0
/
0
"
;
//
On
définit
le
type
ICMP
le
code
8
et
une
demande
d'ECHO
(echo-request)
cela
permet
le
ping
$
args
[
'
icmptype
'
]
=
8
;
//
On
définit
le
code
ICMP
le
code
0
doit
être
défini
à
0
pour
l'utilisation
du
type
8
pour
l'ICMP
$
args
[
'
icmpcode
'
]
=
0
;
//
Execution
de
la
requête
sendRequest($
args
,
$
json_response
);
//
Traitement
de
la
requête
if(preg_match("
/
^
[
0
-
9a
-
f\
-
]
+
$
/
"
,
$
json_response
[
'
createegressfirewallruleresponse
'
]
[
'
jobid
'
]
) >
0
)
{
$
jobs
[
]
=
$
json_response
[
'
createegressfirewallruleresponse
'
]
[
'
jobid
'
]
;
}
else{
echo "
ID
de
job
non
trouvé
.
\n
"
;
}
if(!
checkJobs($
jobs
))
exit;
//
On
réinitialise
les
variables
utilisées
pour
l'envoi
de
requêtes
API
unset($
args
);
#
#########################
#
Protocole
HTTP
sortant
#
#
#########################
$
args
[
'
command
'
]
=
"
createEgressFirewallRule
"
;
$
args
[
'
networkid
'
]
=
$
vm01
[
'
conf
'
]
[
'
networkid
'
]
;
//
Définition
du
protocole
a
filtrer
ici
TCP
(utiliser
par
le
protocole
HTTP),
les
protocole
sont
ICMP/UDP/TCP
$
args
[
'
protocol
'
]
=
"
TCP
"
;
//
Définition
du
masque
réseau
qui
nous
permet
d'autoriser
certainne
IP,
//
ici
nous
accepton
la
connection
vers
toute
les
IP
$
args
[
'
cidrlist
'
]
=
"
0
.
0
.
0
.
0
/
0
"
;
//
Le
port
de
début
(port
80
port
standart
pour
le
HTTP)
$
args
[
'
startport
'
]
=
80
;
//
Le
port
de
fin
(port
80
port
standart
pour
le
HTTP)
$
args
[
'
endport
'
]
=
80
;
//
Execution
de
la
requête
sendRequest($
args
,
$
json_response
);
//
Traitement
de
la
requête
if(preg_match("
/
^
[
0
-
9a
-
f\
-
]
+
$
/
"
,
$
json_response
[
'
createegressfirewallruleresponse
'
]
[
'
jobid
'
]
) >
0
)
{
$
jobs
[
]
=
$
json_response
[
'
createegressfirewallruleresponse
'
]
[
'
jobid
'
]
;
}
else{
echo "
ID
de
job
non
trouvé
.
\n
"
;
}
//
On
réinitialise
les
variables
utilisées
pour
l'envoi
de
requêtes
API
unset($
args
);
#
##########################
#
Protocole
HTTPS
sortant
#
#
##########################
//
Requête
API
$
args
[
'
command
'
]
=
"
createEgressFirewallRule
"
;
$
args
[
'
networkid
'
]
=
$
vm01
[
'
conf
'
]
[
'
networkid
'
]
;
//
Définition
du
protocole
a
filtrer
ici
TCP
(utiliser
par
le
protocole
HTTPS),
les
protocole
sont
ICMP/UDP/TCP
$
args
[
'
protocol
'
]
=
"
TCP
"
;
//
Définition
du
masque
réseau
qui
nous
permet
d'autoriser
certainne
IP,
//
ici
nous
accepton
la
connection
vers
toute
les
IP
$
args
[
'
cidrlist
'
]
=
"
0
.
0
.
0
.
0
/
0
"
;
//
Le
port
de
début
(port
443
port
standart
pour
le
HTTPs)
$
args
[
'
startport
'
]
=
443
;
//
Le
port
de
fin
(port
443
port
standart
pour
le
HTTPs)
$
args
[
'
endport
'
]
=
443
;
//
Execution
de
la
requête
sendRequest($
args
,
$
json_response
);
//
Traitement
de
la
requête
if(preg_match("
/
^
[
0
-
9a
-
f\
-
]
+
$
/
"
,
$
json_response
[
'
createegressfirewallruleresponse
'
]
[
'
jobid
'
]
) >
0
)
{
$
jobs
[
]
=
$
json_response
[
'
createegressfirewallruleresponse
'
]
[
'
jobid
'
]
;
}
else{
echo "
ID
de
job
non
trouvé
.
\n
"
;
}
//
On
réinitialise
les
variables
utilisées
pour
l'envoi
de
requêtes
API
unset($
args
);
#
########################
#
Protocole
DNS
sortant
#
#
########################
//
Requête
API
$
args
[
'
command
'
]
=
"
createEgressFirewallRule
"
;
$
args
[
'
networkid
'
]
=
$
vm01
[
'
conf
'
]
[
'
networkid
'
]
;
//
Définition
du
protocole
a
filtrer
ici
UDP
(utiliser
par
le
protocole
DNS),
les
protocole
sont
ICMP/UDP/TCP
$
args
[
'
protocol
'
]
=
"
UDP
"
;
//
Définition
du
masque
réseau
qui
nous
permet
d'autoriser
certainne
IP,
//
ici
nous
accepton
la
connection
vers
toute
les
IP
$
args
[
'
cidrlist
'
]
=
"
0
.
0
.
0
.
0
/
0
"
;
//
Le
port
de
début
(port
443
port
standart
pour
le
HTTPs)
$
args
[
'
startport
'
]
=
53
;
//
Le
port
de
fin
(port
443
port
standart
pour
le
HTTPs)
$
args
[
'
endport
'
]
=
53
;
//
Execution
de
la
requête
sendRequest($
args
,
$
json_response
);
//
Traitement
de
la
requête
if(preg_match("
/
^
[
0
-
9a
-
f\
-
]
+
$
/
"
,
$
json_response
[
'
createegressfirewallruleresponse
'
]
[
'
jobid
'
]
) >
0
)
{
$
jobs
[
]
=
$
json_response
[
'
createegressfirewallruleresponse
'
]
[
'
jobid
'
]
;
}
else{
echo "
ID
de
job
non
trouvé
.
\n
"
;
}
//
On
réinitialise
les
variables
utilisées
pour
l'envoi
de
requêtes
API
unset($
args
);
#
#######################################
#
Ouverture
du
port
public
pour
le
SSH
#
#
#######################################
//
Requête
API
$
args
[
'
command
'
]
=
"
createFirewallRule
"
;
$
args
[
'
ipaddressid
'
]
=
$
vm01
[
'
conf
'
]
[
'
publicIPid
'
]
;
//
Définition
du
protocole
a
filtrer
ici
TCP
(utiliser
par
le
protocole
SSH),
les
protocole
sont
ICMP/UDP/TCP
$
args
[
'
protocol
'
]
=
"
TCP
"
;
//
Définition
du
masque
réseau
qui
nous
permet
d'autoriser
certainne
IP,
//
ici
nous
accepton
la
connection
vers
toute
les
IP
$
args
[
'
cidrlist
'
]
=
"
0
.
0
.
0
.
0
/
0
"
;
//
Le
port
de
début
(port
2222
port
qui
sera
plus
tard
rediriger
vers
le
port
22(ssh)
de
votre
VM)
$
args
[
'
startport
'
]
=
2222
;
//
Le
port
de
fin
(port
2222
port
qui
sera
plus
tard
rediriger
vers
le
port
22(ssh)
de
votre
VM)
$
args
[
'
endport
'
]
=
2222
;
//
Execution
de
la
requête
sendRequest($
args
,
$
json_response
);
//
Traitement
de
la
requête
if(preg_match("
/
^
[
0
-
9a
-
f\
-
]
+
$
/
"
,
$
json_response
[
'
createfirewallruleresponse
'
]
[
'
jobid
'
]
) >
0
)
{
$
jobs
[
]
=
$
json_response
[
'
createfirewallruleresponse
'
]
[
'
jobid
'
]
;
}
else{
echo "
ID
de
job
non
trouvé
.
\n
"
;
}
//
On
réinitialise
les
variables
utilisées
pour
l'envoi
de
requêtes
API
unset($
args
);
#
##################################
#
Redirection
de
port
pour
le
SSH
#
#
##################################
//
Requête
API
$
args
[
'
command
'
]
=
"
createPortForwardingRule
"
;
$
args
[
'
ipaddressid
'
]
=
$
vm01
[
'
conf
'
]
[
'
publicIPid
'
]
;
$
args
[
'
virtualmachineid
'
]
=
$
vm01
[
'
conf
'
]
[
'
id
'
]
;
//
Définition
du
protocole
a
filtrer
ici
TCP
(utiliser
par
le
protocole
SSH),
les
protocole
sont
ICMP/UDP/TCP
$
args
[
'
protocol
'
]
=
"
TCP
"
;
//
Le
Port
public
sur
lequels
vous
allez
initialiser
la
connection
et
définie
plus
tôt
comme
ouvert
$
args
[
'
publicport
'
]
=
2222
;
//
Le
SSH
de
votre
VM
$
args
[
'
privateport
'
]
=
22
;
//
Execution
de
la
requête
sendRequest($
args
,
$
json_response
);
//
Traitement
de
la
requête
if(preg_match("
/
^
[
0
-
9a
-
f\
-
]
+
$
/
"
,
$
json_response
[
'
createportforwardingruleresponse
'
]
[
'
jobid
'
]
) >
0
)
{
$
jobs
[
]
=
$
json_response
[
'
createportforwardingruleresponse
'
]
[
'
jobid
'
]
;
}
else{
echo "
ID
de
job
non
trouvé
.
\n
"
;
}
//
On
réinitialise
les
variables
utilisées
pour
l'envoi
de
requêtes
API
unset($
args
);
if(!
checkJobs($
jobs
))
exit;
/*
-----------------------------------------------------------------------------------------------------------
*/
#
############
#
Fonctions
#
#
############
//
Fonction
de
gestion
d'erreur(s)
API
function apiErrorCheck($
json_response
)
{
if(is_array($
json_response
))
{
$
key
=
array_keys($
json_response
);
if(isset($
json_response
[
'
errorcode
'
]
))
{
echo "
ERREUR
:
"
.
$
json_response
[
'
errorcode
'
]
.
"
-
"
.
$
json_response
[
'
errortext
'
]
.
"
\n
"
;
exit;
}
if(isset($
json_response
[
'
errorcode
'
]
) |
|
(isset($
key
[
0
]
) &
amp;
&
amp;
isset($
json_response
[
$
key
[
0
]
]
[
'
errorcode
'
]
)))
{
echo "
ERREUR
:
"
.
$
json_response
[
$
key
[
0
]
]
[
'
errorcode
'
]
.
"
-
"
.
$
json_response
[
$
key
[
0
]
]
[
'
errortext
'
]
.
"
\n
"
;
exit;
}
}
else
{
echo "
ERREUR
:
PARAMETRE
INVALIDE
"
;
exit;
}
}
//
Fonction
d'envoi
de
requête
à
l'API
function sendRequest($
args
,
&
amp;
$
json_response
)
{
$
json_response
=
null;
//
Clef
API
$
args
[
'
apikey
'
]
=
APIKEY;
$
args
[
'
response
'
]
=
"
json
"
;
//
On
classe
les
paramètres
ksort($
args
);
//
On
construit
la
requête
HTTP
basée
sur
les
paramètres
contenus
dans
$args
$
query
=
http_build_query($
args
);
//
On
s'assure
de
bien
remplacer
toutes
les
occurences
de
'+'
par
des
'%20'
$
query
=
str_replace("
+
"
,
"
%
20
"
,
$
query
);
//
On
utilise
la
clef
secrète
et
un
algorithme
HMAC
SHA-1
sur
la
requête
pour
encoder
la
signature
$
hash
=
hash_hmac("
SHA1
"
,
strtolower($
query
),
SECRETKEY,
true);
$
base64encoded
=
base64_encode($
hash
);
$
signature
=
urlencode($
base64encoded
);
//
Construction
de
la
requête
finale
sous
la
forme
'URL
API
+
Requête
API
et
paramètres
+
Signature'
$
query
.
=
"
&
amp
;
signature
=
"
.
$
signature
;
//
$jobs
=
null;
//
Initialisation
du
client
API
try
{
//
Construction
de
la
requête
$httpRequest
=
new HttpRequest();
$httpRequest
->setMethod
(HTTP_METH_POST);
$httpRequest
->setUrl
(ENDPOINT .
"
?
"
.
$
query
);
//
Envoi
de
la
requête
au
serveur
:
$httpRequest
->send
();
//
Récupération
du
retour
de
l'API
$
response
=
$httpRequest
->getResponseData
();
//
retour
de
la
réponse
$
json_response
=
json_decode($
response
[
'
body
'
]
,
true);
apiErrorCheck($
json_response
);
}
catch (Exception $
e
)
{
echo "
Probleme
lors
de
l
'
envoi
de
la
requête
.
ERREUR
=
"
.
$e
->getMessage
();
exit;
}
}
//
Fonction
de
vérification
des
jobs
asynchrones
function checkJobs($
jobs
)
{
$
json_response
=
null;
$
error_msg
=
"
"
;
if(is_array($
jobs
) &
amp;
&
amp;
count($
jobs
) >
0
)
{
//
La
tâche
est
asynchrone,
on
doit
donc
régulièrement
vérifier
les
tâches
avec
une
sécurité
$
secu
=
0
;
//
On
indexe
les
tâches
$
ij
=
0
;
//
Tant
qu'il
y
a
des
tâches
asynchrones
non-terminées
dans
la
pile
de
vérification,
on
boucle
et
on
vérifie
le
statut
while(count($
jobs
) >
0
&
amp;
&
amp;
$
secu
&
lt;
100
)
{
try
{
//
On
interroge
le
statut
de
la
tâche
asynchrone
//
http://download.cloud.com/releases/3.0.6/api_3.0.6/root_admin/queryAsyncJobResult.html
$
args
[
'
apikey
'
]
=
APIKEY;
$
args
[
'
command
'
]
=
"
queryAsyncJobResult
"
;
$
args
[
'
jobid
'
]
=
$
jobs
[
$
ij
]
;
$
args
[
'
response
'
]
=
"
json
"
;
$
json_response
=
null;
sendRequest($
args
,
$
json_response
);
if(is_array($
json_response
[
'
queryasyncjobresultresponse
'
]
))
{
//
Si
OK...
if($
json_response
[
'
queryasyncjobresultresponse
'
]
[
'
jobstatus
'
]
=
=
1
)
{
//
...On
retire
simplement
la
tâche
du
tableau
a
surveiller
//
return("JOB
OK\n");
array_splice($
jobs
,
$
ij
,
1
);
}
//
Sinon...
elseif($
json_response
[
'
queryasyncjobresultresponse
'
]
[
'
jobstatus
'
]
=
=
2
)
{
//
...On
mémorise
l'erreur
et
on
retire
la
tâche
du
tableau
à
surveiller
//
return("JOB
ERREUR\n");
array_splice($
jobs
,
$
ij
,
1
);
$
error_msg
.
=
"
ERREUR
!
RESULT_CODE
=
"
.
$
json_response
[
'
queryasyncjobresultresponse
'
]
[
'
jobresultcode
'
]
;
}
//
Cette
tâche
est
encore
en
cours,
on
passe
à
la
suivante
et
on
temporise
elseif($
json_response
[
'
queryasyncjobresultresponse
'
]
[
'
jobstatus
'
]
=
=
0
)
{
//
Tâche
suivante
$
ij
+
+
;
//
Temporisation
entre
chaque
interrogation
pour
ne
pas
charger
inutilement
l'API
sleep(5
);
}
}
}
catch(Exception $
e
)
{
$
error_msg
.
=
"
EXCEPTION
Lors
de
la
verification
la
tache
asynchrone
.
JOB_UUID
:
"
.
$
jobs
[
$
ij
]
.
"
ERREUR
=
"
.
$e
->getMessage
().
"
\n
"
;
}
//
Si
l'index
arrive
en
bout
de
tableau,
on
le
réinitialise
if($
ij
=
=
count($
jobs
))
{
$
ij
=
0
;
$
secu
+
+
;
}
}
if($
error_msg
)
{
echo "
ERRORS
:
"
.
$
error_msg
.
"
\n
"
;
return false;
}
return true;
}
echo "
No
job\n
"
;
return false;
}
?>
II. Remerciements Developpez▲
L'équipe Cloud Computing tient à remercier Ikoula pour la rédaction de ce tutoriel.
Nos remerciements à Wiztricks pour sa relecture technique et à Zoom61 pour sa gabarisation.
N'hésitez pas à commenter cet article ! Commentez