cluster: STABLE3 - rgmanager: Fix erroneous bind mount warning in fs.sh
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 1274ca603ef82051898009ec3b99df9b982b7578
Parent: bc09c990a910a6ade0f11890cf906fa053d62d33
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Tue Dec 15 11:28:51 2009 -0500
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Mon Dec 21 13:35:01 2009 -0500
rgmanager: Fix erroneous bind mount warning in fs.sh
The previous patch 32bed24ef00dc5df5474d0287ffbb3e4eceb1226
produced an incorrect error when mounting the file system.
Resolves: bz526286
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
rgmanager/src/resources/fs.sh.in | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/rgmanager/src/resources/fs.sh.in b/rgmanager/src/resources/fs.sh.in
index a6238fd..51f8f48 100644
--- a/rgmanager/src/resources/fs.sh.in
+++ b/rgmanager/src/resources/fs.sh.in
@@ -600,7 +600,7 @@ isMounted () {
fi
done < /proc/mounts
- if [ $found -ne 0 ]; then
+ if [ $ret -eq $YES ] && [ $found -ne 0 ]; then
ocf_log warn "Device $dev is mounted on $poss_mp instead of $mp"
fi
14 years, 5 months
cluster: STABLE3 - fence-agents: Add missing state handling to fence_virsh
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: bc09c990a910a6ade0f11890cf906fa053d62d33
Parent: 82fff3bae8f627470cea7e04c2fbe1f93620937e
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Mon Dec 21 11:25:12 2009 -0500
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Mon Dec 21 13:33:37 2009 -0500
fence-agents: Add missing state handling to fence_virsh
Resolves: rhbz#544664
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
Signed-off-by: Marek 'marx' Grac <mgrac(a)redhat.com>
---
fence/agents/virsh/fence_virsh.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fence/agents/virsh/fence_virsh.py b/fence/agents/virsh/fence_virsh.py
index 1d8afea..13099da 100644
--- a/fence/agents/virsh/fence_virsh.py
+++ b/fence/agents/virsh/fence_virsh.py
@@ -36,7 +36,7 @@ def get_outlets_status(conn, options):
if ((fa_status==0) and (domain.group(1).lower()=="id") and (domain.group(2).lower()=="name")):
fa_status=1
elif (fa_status==1):
- result[domain.group(2)]=("",(domain.group(3).lower() in ["running","blocked"] and "on" or "off"))
+ result[domain.group(2)]=("",(domain.group(3).lower() in ["running","blocked","idle","no state","paused"] and "on" or "off"))
return result
def get_power_status(conn, options):
14 years, 5 months
cluster: RHEL55 - rgmanager: Fix erroneous bind mount warning in fs.sh
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 8d523d56d6d36b7b84ebafb923908a3a79b72938
Parent: 9bfaeaebb9a359d1edbe7bc411e1393a7806117f
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Tue Dec 15 11:28:51 2009 -0500
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Mon Dec 21 13:29:27 2009 -0500
rgmanager: Fix erroneous bind mount warning in fs.sh
The previous patch b5be828615a2ed7bd95a3796d96f5cc536e2adc7
produced an incorrect error when mounting the file system.
Resolves: bz526286
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
rgmanager/src/resources/fs.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/rgmanager/src/resources/fs.sh b/rgmanager/src/resources/fs.sh
index 477391c..03cd59a 100755
--- a/rgmanager/src/resources/fs.sh
+++ b/rgmanager/src/resources/fs.sh
@@ -620,7 +620,7 @@ isMounted () {
fi
done < /proc/mounts
- if [ $found -ne 0 ]; then
+ if [ $ret -eq $YES ] && [ $found -ne 0 ]; then
ocf_log warn "Device $dev is mounted on $poss_mp instead of $mp"
fi
14 years, 5 months
cluster: RHEL55 - gfs2_convert: Conversion of inodes that are of different metatree heights in gfs and gfs2 is incorrect
by Abhijith Das
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 9bfaeaebb9a359d1edbe7bc411e1393a7806117f
Parent: 3e342bdbf969d977b0a1b09c8bb8ecdbeb04369b
Author: Abhijith Das <adas(a)redhat.com>
AuthorDate: Mon Dec 21 11:44:41 2009 -0600
Committer: Abhijith Das <adas(a)redhat.com>
CommitterDate: Mon Dec 21 11:44:41 2009 -0600
gfs2_convert: Conversion of inodes that are of different metatree heights in gfs and gfs2 is incorrect
Resolves bz 548588 - The first hunk of the patch fixes a possible typo
where the gfs1 height was being used instead of gfs2 height to compute
the fan-out factors. When both heights at gfs1 and gfs2 are the same,
this really doesn't matter, but at different heights, I get a floating
point exception and gfs2_convert crashes.
The second part of the fix has to do with updating the height
information of a given block after it's revised metapath is computed
according to gfs2 parameters. Without this line, gfs2_convert was using
the same height as that of gfs1 for the converted file and weird blocks
were included in the file's data and metadata, thereby corrupting it.
---
gfs2/convert/gfs2_convert.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index e624ace..cea8496 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -289,7 +289,7 @@ void mp_gfs1_to_gfs2(struct gfs2_sbd *sbp, int gfs1_h, int gfs2_h,
/* figure out multiplication factors for each height - gfs2 */
memset(&gfs2factor, 0, sizeof(gfs2factor));
- gfs2factor[gfs1_h - 1] = 1ull;
+ gfs2factor[gfs2_h - 1] = 1ull;
for (h = gfs2_h - 1; h > 0; h--)
gfs2factor[h - 1] = gfs2factor[h] * gfs2_inptrs;
@@ -577,6 +577,7 @@ int adjust_indirect_blocks(struct gfs2_sbd *sbp, struct gfs2_buffer_head *dibh,
blk->mp.mp_list[di_height - 1] = ptrnum;
mp_gfs1_to_gfs2(sbp, di_height, gfs2_hgt, &blk->mp, &gfs2mp);
memcpy(&blk->mp, &gfs2mp, sizeof(struct metapath));
+ blk->height -= di_height - gfs2_hgt;
if (len)
fix_metatree(sbp, ip, blk, ptr1, len);
osi_list_del(tmp);
14 years, 5 months
cluster: RHEL55 - gfs2_convert: interrupted rgrp conversion does not allow re-converts
by Abhijith Das
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 3e342bdbf969d977b0a1b09c8bb8ecdbeb04369b
Parent: 4a1e13adcb7d5380b676380cc555d04f7b30a836
Author: Abhijith Das <adas(a)redhat.com>
AuthorDate: Mon Dec 21 11:41:45 2009 -0600
Committer: Abhijith Das <adas(a)redhat.com>
CommitterDate: Mon Dec 21 11:41:45 2009 -0600
gfs2_convert: interrupted rgrp conversion does not allow re-converts
Resolves bz 548585. Zero out gfs1 rgrp's rg_freemeta field after
adding it to gfs2 rgrp's free blocks. This should only be done once.
If convert fails or is interrupted and is restarted later on, adding
a non-zero rg_freemeta to the free blocks again throws off the
numbers and breaks allocation.
---
gfs2/convert/gfs2_convert.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 1b4b1bd..e624ace 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -219,6 +219,9 @@ static int convert_rgs(struct gfs2_sbd *sbp)
/* rg_freemeta is a gfs1 structure, so libgfs2 doesn't know to */
/* convert from be to cpu. We must do it now. */
rgd->rg.rg_free = rgd1->rg_free + be32_to_cpu(rgd1->rg_freemeta);
+ /* Zero it out so we don't add it again in case something breaks */
+ /* later on in the process and we have to re-run convert */
+ rgd1->rg_freemeta = 0;
sbp->blks_total += rgd->ri.ri_data;
sbp->blks_alloced += (rgd->ri.ri_data - rgd->rg.rg_free);
14 years, 5 months
cluster: RHEL55 - Revert "gfs2_convert: interrupted rgrp conversion does not allow re-converts"
by Abhijith Das
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 4a1e13adcb7d5380b676380cc555d04f7b30a836
Parent: 84babaef6376740c882ef1f51ce0b8cf9f15abba
Author: Abhijith Das <adas(a)redhat.com>
AuthorDate: Mon Dec 21 11:39:27 2009 -0600
Committer: Abhijith Das <adas(a)redhat.com>
CommitterDate: Mon Dec 21 11:39:27 2009 -0600
Revert "gfs2_convert: interrupted rgrp conversion does not allow re-converts"
This reverts commit 84babaef6376740c882ef1f51ce0b8cf9f15abba.
---
gfs2/convert/gfs2_convert.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index e624ace..1b4b1bd 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -219,9 +219,6 @@ static int convert_rgs(struct gfs2_sbd *sbp)
/* rg_freemeta is a gfs1 structure, so libgfs2 doesn't know to */
/* convert from be to cpu. We must do it now. */
rgd->rg.rg_free = rgd1->rg_free + be32_to_cpu(rgd1->rg_freemeta);
- /* Zero it out so we don't add it again in case something breaks */
- /* later on in the process and we have to re-run convert */
- rgd1->rg_freemeta = 0;
sbp->blks_total += rgd->ri.ri_data;
sbp->blks_alloced += (rgd->ri.ri_data - rgd->rg.rg_free);
14 years, 5 months
cluster: RHEL55 - gfs2_convert: interrupted rgrp conversion does not allow re-converts
by Abhijith Das
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 84babaef6376740c882ef1f51ce0b8cf9f15abba
Parent: 70a541bd76cfb45d7c97ad47d984e5ace9dbea98
Author: Abhijith Das <adas(a)redhat.com>
AuthorDate: Mon Dec 21 11:37:23 2009 -0600
Committer: Abhijith Das <adas(a)redhat.com>
CommitterDate: Mon Dec 21 11:37:23 2009 -0600
gfs2_convert: interrupted rgrp conversion does not allow re-converts
Zero out gfs1 rgrp's rg_freemeta field after adding it to gfs2 rgrp's
free blocks. This should only be done once. If convert fails or is
interrupted and is restarted later on, adding a non-zero rg_freemeta
to the free blocks again throws off the numbers and breaks allocation.
---
gfs2/convert/gfs2_convert.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 1b4b1bd..e624ace 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -219,6 +219,9 @@ static int convert_rgs(struct gfs2_sbd *sbp)
/* rg_freemeta is a gfs1 structure, so libgfs2 doesn't know to */
/* convert from be to cpu. We must do it now. */
rgd->rg.rg_free = rgd1->rg_free + be32_to_cpu(rgd1->rg_freemeta);
+ /* Zero it out so we don't add it again in case something breaks */
+ /* later on in the process and we have to re-run convert */
+ rgd1->rg_freemeta = 0;
sbp->blks_total += rgd->ri.ri_data;
sbp->blks_alloced += (rgd->ri.ri_data - rgd->rg.rg_free);
14 years, 5 months
cluster: RHEL55 - ccsd: Improve error messages from ccsd
by Christine Caulfield
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 70a541bd76cfb45d7c97ad47d984e5ace9dbea98
Parent: 4cb022366d43ecc763c3add78afdaa17c7e530a9
Author: Christine Caulfield <ccaulfie(a)redhat.com>
AuthorDate: Mon Dec 21 17:13:59 2009 +0000
Committer: Christine Caulfield <ccaulfie(a)redhat.com>
CommitterDate: Mon Dec 21 17:13:59 2009 +0000
ccsd: Improve error messages from ccsd
Resolves rhbz#517399
Signed-off-by: Christine Caulfield <ccaulfie(a)redhat.com>
---
ccs/daemon/ccsd.c | 34 +++++++++++++++++++++++++++++++---
ccs/daemon/cnx_mgr.c | 20 ++++++++++++++++++--
2 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/ccs/daemon/ccsd.c b/ccs/daemon/ccsd.c
index f2325fd..82d7bae 100644
--- a/ccs/daemon/ccsd.c
+++ b/ccs/daemon/ccsd.c
@@ -57,6 +57,7 @@ int main(int argc, char *argv[]){
struct sockaddr_storage addr;
struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+ char addrbuf[64], *res;
int addr_size=0;
fd_set rset, tmp_set;
char *msg;
@@ -124,9 +125,22 @@ int main(int argc, char *argv[]){
inet_aton("127.0.0.1", (struct in_addr *)&(addr4->sin_addr.s_addr));
addr4->sin_port = htons(frontend_port);
}
-
if(bind(sfds[0], (struct sockaddr *)&addr, addr_size) < 0){
- log_sys_err("Unable to bind socket");
+ if(IPv6) {
+ res = inet_ntop(AF_INET6,&addr6->sin6_addr, addrbuf, sizeof(addrbuf));
+ if (!res) {
+ log_sys_err("Unable to bind socket addr: %s, port: %d, scope: %d", addrbuf, addr6->sin6_port, addr6->sin6_scope_id);
+ } else {
+ log_sys_err("Unable to bind to ipv6 frontend socket, but inet_ntop returned NULL pointer");
+ }
+ } else {
+ res = inet_ntop(AF_INET,&addr4->sin_addr, addrbuf, sizeof(addrbuf));
+ if (!res) {
+ log_sys_err("Unable to bind socket addr: %s, port: %d, proto: %d", addrbuf, addr4->sin_port, addr4->sin_family);
+ } else {
+ log_sys_err("Unable to bind to ipv4 frontend socket, but inet_ntop returned NULL pointer");
+ }
+ }
close(sfds[0]);
exit(EXIT_FAILURE);
}
@@ -158,7 +172,21 @@ int main(int argc, char *argv[]){
}
if(bind(sfds[1], (struct sockaddr *)&addr, addr_size) < 0){
- log_sys_err("Unable to bind socket");
+ if(IPv6) {
+ res = inet_ntop(AF_INET6,&addr6->sin6_addr, addrbuf, sizeof(addrbuf));
+ if (!res) {
+ log_sys_err("Unable to bind socket addr: %s, port: %d, scope: %d", addrbuf, addr6->sin6_port, addr6->sin6_scope_id);
+ } else {
+ log_sys_err("Unable to bind to backend ipv6 socket, but inet_ntop returned NULL pointer");
+ }
+ } else {
+ res = inet_ntop(AF_INET,&addr4->sin_addr, addrbuf, sizeof(addrbuf));
+ if (!res) {
+ log_sys_err("Unable to bind socket addr: %s, port: %d, proto: %d", addrbuf, addr4->sin_port, addr4->sin_family);
+ } else {
+ log_sys_err("Unable to bind to backend ipv4 socket, but inet_ntop returned NULL pointer");
+ }
+ }
close(sfds[1]);
return -errno;
}
diff --git a/ccs/daemon/cnx_mgr.c b/ccs/daemon/cnx_mgr.c
index 6366e4b..078df85 100644
--- a/ccs/daemon/cnx_mgr.c
+++ b/ccs/daemon/cnx_mgr.c
@@ -167,7 +167,7 @@ static int broadcast_for_doc(char *cluster_name, int blocking){
int trueint;
int v1, v2;
int write_to_disk = 0;
- char *tmp_name = NULL;
+ char *tmp_name = NULL, addrbuf[64], *res;
struct sockaddr_storage addr, recv_addr;
struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
@@ -297,7 +297,23 @@ static int broadcast_for_doc(char *cluster_name, int blocking){
if(sendto(sfd, (char *)ch, sizeof(comm_header_t), 0,
(struct sockaddr *)&addr, addr_size) < 0){
- log_sys_err("Unable to perform sendto");
+
+ if(IPv6) {
+ res = inet_ntop(AF_INET6,&addr6->sin6_addr, addrbuf, sizeof(addrbuf));
+ if (!res) {
+ log_sys_err("Unable to perform sendto addr: %s, port: %d, scope: %d", addrbuf, addr6->sin6_port, addr6->sin6_scope_id);
+ } else {
+ log_sys_err("Unable to sendto broadcast ipv6 socket, but inet_ntop returned NULL pointer");
+ }
+ } else {
+ res = inet_ntop(AF_INET,&addr4->sin_addr, addrbuf, sizeof(addrbuf));
+ if (!res) {
+ log_sys_err("Unable to perform sendto addr: %s, port: %d, proto: %d", addrbuf, addr4->sin_port, addr4->sin_family);
+ } else {
+ log_sys_err("Unable to sendto broadcast ipv4 socket, but inet_ntop returned NULL pointer");
+ }
+ }
+
if(retry > 0){
retry--;
close(sfd);
14 years, 5 months
cluster: RHEL55 - fencing: Modify VMWare fence agent to be in sync with others
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 4cb022366d43ecc763c3add78afdaa17c7e530a9
Parent: 0886ca800604fa1db013446af27ef715e7658952
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Sun Dec 20 19:37:44 2009 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Sun Dec 20 19:37:44 2009 +0100
fencing: Modify VMWare fence agent to be in sync with others
Remove features which are not part of RHEL5 yet.
---
fence/agents/vmware/fence_vmware.py | 32 ++++----------------------------
1 files changed, 4 insertions(+), 28 deletions(-)
diff --git a/fence/agents/vmware/fence_vmware.py b/fence/agents/vmware/fence_vmware.py
index 75fd887..0d16ad9 100644
--- a/fence/agents/vmware/fence_vmware.py
+++ b/fence/agents/vmware/fence_vmware.py
@@ -23,11 +23,11 @@
#
import sys, re, pexpect, exceptions
-sys.path.append("@FENCEAGENTSLIBDIR@")
+sys.path.append("/usr/bin/fence")
from fencing import *
#BEGIN_VERSION_GENERATION
-RELEASE_VERSION="VMware Agent using VI Perl API and/or VIX vmrun command"
+FENCE_RELEASE_NAME="VMware Agent using VI Perl API and/or VIX vmrun command"
REDHAT_COPYRIGHT=""
BUILD_DATE=""
#END_VERSION_GENERATION
@@ -299,30 +299,7 @@ def main():
# Default is secure connection
options["-x"] = 1
- docs = { }
- docs["shortdesc"] = "Fence agent for VMWare"
- docs["longdesc"] = "fence_vmware is an I/O Fencing agent \
-which can be used with the VMware ESX, VMware ESXi or VMware Server \
-to fence virtual machines.\
-\n.P\n\
-Before you can use this agent, it must be installed VI Perl Toolkit or \
-vmrun command on every node you want to make fencing.\
-\n.P\n\
-VI Perl Toolkit is preferred for VMware ESX/ESXi and Virtual Center. Vmrun \
-command is only solution for VMware Server 1/2 (this command will works against \
-ESX/ESXi 3.5 up2 and VC up2 too, but not cluster aware!) and is available as part \
-of VMware VIX API SDK package. VI Perl and VIX API SDK are both available from \
-VMware web pages (not int RHEL repository!). \
-\n.P\n\
-You can specify type of VMware you are connecting to with \\fB-d\\fP switch \
-(or \\fIvmware_type\\fR for stdin). Possible values are esx, server2 and server1.\
-Default value is esx, which will use VI Perl. With server1 and server2, vmrun \
-command is used.\
-\n.P\n\
-After you have successfully installed VI Perl Toolkit or VIX API, you should \
-be able to run fence_vmware_helper (part of this agent) or vmrun command. \
-This agent supports only vmrun from version 2.0.0 (VIX API 1.6.0)."
- show_docs(options, docs)
+ show_docs(options)
# Check vmware type and set path
vmware_check_vmware_type(options)
@@ -333,9 +310,8 @@ This agent supports only vmrun from version 2.0.0 (VIX API 1.6.0)."
fail_usage("Unsupported version of vmrun command! You must use at least version %d!"%(VMRUN_MINIMUM_REQUIRED_VERSION))
# Operate the fencing device
- result = fence_action(None, options, set_power_status, get_power_status, get_outlets_status)
+ fence_action(None, options, set_power_status, get_power_status, get_outlets_status)
- sys.exit(result)
if __name__ == "__main__":
main()
14 years, 5 months
cluster: RHEL55 - fencing: New fence agent for VMWare
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 0886ca800604fa1db013446af27ef715e7658952
Parent: 396d6cf068f8844e08e76bf6471b28504b0b129b
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Sun Dec 20 19:33:17 2009 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Sun Dec 20 19:33:17 2009 +0100
fencing: New fence agent for VMWare
Current version of vmware fence agent (techpreview) is not cluster aware. New
fence agent should support VMware ESX/ESXi/VC/Server 1/Server 2 and be cluster
aware. That will require that user must install VI Perl or VIX API to every
node which do fencing.
Resolve: rhbz#548577
---
fence/agents/lib/fencing.py.py | 51 ++--
fence/agents/vmware/Makefile | 17 +-
fence/agents/vmware/fence_vmware.pl | 337 ----------------------
fence/agents/vmware/fence_vmware.py | 426 ++++++++++++++++++++--------
fence/agents/vmware/fence_vmware_helper.pl | 276 ++++++++++++++++++
5 files changed, 619 insertions(+), 488 deletions(-)
diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index 647011a..711e17d 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -224,22 +224,27 @@ all_opt = {
"help" : "",
"order" : 1,
"obsolete" : "use -o status instead" },
- "vmipaddr" : {
- "getopt" : "A:",
- "help" : "-A <ip> IP address or hostname of managed VMware ESX (default localhost)",
- "order" : 2 },
- "vmlogin" : {
- "getopt" : "L:",
- "help" : "-L <name> VMware ESX management login name",
- "order" : 2 },
- "vmpasswd" : {
- "getopt" : "P:",
- "help" : "-P <password> VMware ESX management login password",
- "order" : 2 },
- "vmpasswd_script" : {
- "getopt" : "B:",
- "help" : "-B <script> Script to run to retrieve VMware ESX management password",
- "order" : 2 },
+ "exec" : {
+ "getopt" : "e:",
+ "longopt" : "exec",
+ "help" : "-e, --exec=<command> Command to execute",
+ "required" : "0",
+ "shortdesc" : "Command to execute",
+ "order" : 1 },
+ "vmware_type" : {
+ "getopt" : "d:",
+ "longopt" : "vmware_type",
+ "help" : "-d, --vmware_type=<type> Type of VMware to connect",
+ "required" : "0",
+ "shortdesc" : "Type of VMware to connect",
+ "order" : 1 },
+ "vmware_datacenter" : {
+ "getopt" : "s:",
+ "longopt" : "vmware_datacenter",
+ "help" : "-s, --vmware_datacenter=<dc> VMWare datacenter filter",
+ "required" : "0",
+ "shortdesc" : "Show only machines in specified datacenter",
+ "order" : 2 },
"snmp_version" : {
"getopt" : "d:",
"longopt" : "snmp-version",
@@ -656,20 +661,6 @@ def check_input(device_opt, opt):
if options.has_key("-R"):
options["-P"] = os.popen(options["-R"]).read().rstrip()
- ## VMware
- #######
- if options.has_key("-B"):
- options["-P"] = os.popen(options["-B"]).read().rstrip()
-
- if (device_opt.count("vmlogin") and (not options.has_key("-L"))):
- fail_usage("Failed: You have to set login name for VMware ESX management console")
-
- if (options.has_key("-L") and (not (options.has_key("-P") or options.has_key("-B")))):
- fail_usage("Failed: You have to enter password or password script for VMware ESX management console")
-
- if (["list", "monitor"].count(options["-o"])==0 and (options.has_key("-L") and (not (options.has_key("-n"))))):
- fail_usage("Failed: You have to enter virtual machine name")
-
if options.has_key("-u") == False:
if options.has_key("-x"):
options["-u"] = 22
diff --git a/fence/agents/vmware/Makefile b/fence/agents/vmware/Makefile
index ea0a207..f0259b8 100644
--- a/fence/agents/vmware/Makefile
+++ b/fence/agents/vmware/Makefile
@@ -14,10 +14,13 @@
SOURCE= fence_vmware.py
TARGET= fence_vmware
+SOURCE2= fence_vmware_helper.pl
+TARGET2= fence_vmware_helper
+
top_srcdir=../..
include ${top_srcdir}/make/defines.mk
-all: $(TARGET)
+all: $(TARGET) $(TARGET2)
$(TARGET): $(SOURCE)
: > $(TARGET)
@@ -28,12 +31,22 @@ $(TARGET): $(SOURCE)
awk -v p=0 "(\$$1 ~ /#END_VERSION_GENERATION/){p = 1} {if(p==1)print}" $(SOURCE) >> $(TARGET)
chmod +x $(TARGET)
+$(TARGET2): $(SOURCE2)
+ : > $(TARGET2)
+ awk "{print}(\$$1 ~ /#BEGIN_VERSION_GENERATION/){exit 0}" $(SOURCE2) >> $(TARGET2)
+ echo "FENCE_RELEASE_NAME=\"${RELEASE}\";" >> $(TARGET2)
+ ${top_srcdir}/scripts/define2var ${top_srcdir}/config/copyright.cf sh REDHAT_COPYRIGHT >> $(TARGET2)
+ echo "BUILD_DATE=\"(built `date`)\";" >> $(TARGET2)
+ awk -v p=0 "(\$$1 ~ /#END_VERSION_GENERATION/){p = 1} {if(p==1)print}" $(SOURCE2) >> $(TARGET2)
+ chmod +x $(TARGET2)
+
install: all
if [ ! -d ${sbindir} ]; then \
install -d ${sbindir}; \
fi
install -m755 ${TARGET} ${sbindir}
+ install -m755 ${TARGET2} ${sbindir}
clean:
- rm -f $(TARGET)
+ rm -f $(TARGET) $(TARGET2)
diff --git a/fence/agents/vmware/fence_vmware.pl b/fence/agents/vmware/fence_vmware.pl
deleted file mode 100755
index 3c08312..0000000
--- a/fence/agents/vmware/fence_vmware.pl
+++ /dev/null
@@ -1,337 +0,0 @@
-#!/usr/bin/perl
-
-###############################################################################
-###############################################################################
-##
-## Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-## Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
-##
-## This copyrighted material is made available to anyone wishing to use,
-## modify, copy, or redistribute it subject to the terms and conditions
-## of the GNU General Public License v.2.
-##
-## VMWare ESX Server fencing support by Zach Lowry <zach(a)zachlowry.net>
-##
-###############################################################################
-###############################################################################
-
-use strict;
-use Getopt::Std;
-use VMware::VmPerl;
-use VMware::VmPerl::VM;
-use VMware::VmPerl::Server;
-use VMware::VmPerl::ConnectParams;
-use vars qw( $opt_L $opt_v $opt_V $opt_h $opt_T $opt_n $opt_o $opt_p $opt_P $opt_S $opt_l $opt_a $opt_q $vm_product $vm_platform $vm_build $vm_version_major $vm_version_minor $vm_version_revision );
-
-# Get the program name from $0 and strip directory names
-$_=$0;
-s/.*\///;
-my $pname = $_;
-
-# Change these if the text returned by your equipment is different.
-# Test by running script with options -t -v and checking /tmp/vmlog
-
-my $immediate = 'immediate'; # # Or 'delayed' - action string prefix on menu
-
-my $max_open_tries = 3; # How many attempts to make.
-my $open_wait = 5; # Seconds to wait between each attempt
-my $debuglog = '/tmp/apclog';# Location of debugging log when in verbose mode
-my $powerop_mode = VM_POWEROP_MODE_TRYSOFT;
-$opt_o = 'Reboot'; # Default fence action.
-
-
-my $logged_in = 0;
-
-my $vm = VMware::VmPerl::VM::new();
-my $server = VMware::VmPerl::Server::new();
-
-# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and
-# "#END_VERSION_GENERATION" It is generated by the Makefile
-
-#BEGIN_VERSION_GENERATION
-#END_VERSION_GENERATION
-
-sub usage
-{
- print "Usage:\n";
- print "\n";
- print "$pname [options]\n";
- print "\n";
- print "Options:\n";
- print " -a <ip>:<port> IP address or hostname of VMware ESX Server\n";
- print " -h usage\n";
- print " -l <name> Login name\n";
- print " -p <string> Login password\n";
- print " -S <path> Script to run to retrieve login password\n";
- print " -n <name> Name of VM to change \n";
- print " -o <string> Action: Reboot (default), Off or On\n";
- print " -q quiet mode\n";
- print " -T Test mode (cancels action)\n";
- print " -V version\n";
- print " -v Log to file /tmp/vmlog\n";
- print " -L List VMs on Server\n";
-
- exit 0;
-}
-
-sub fail
-{
- my ($msg)=@_;
- print $msg."\n" unless defined $opt_q;
-
- if (defined $vm)
- {
- # make sure we don't get stuck in a loop due to errors
-
- logout() if $logged_in;
- undef $vm;
- }
- exit 1;
-}
-
-sub fail_usage
-{
- my ($msg)=@_;
- print STDERR $msg."\n" if $msg;
- print STDERR "Please use '-h' for usage.\n";
- exit 1;
-}
-
-sub version
-{
- print "$pname $FENCE_RELEASE_NAME $BUILD_DATE\n";
- print "$REDHAT_COPYRIGHT\n" if ( $REDHAT_COPYRIGHT );
- exit 0;
-}
-
-
-sub login
-{
- my $connect_params = VMware::VmPerl::ConnectParams::new($opt_a, $opt_P, $opt_l, $opt_p);
- for (my $i=0; $i<$max_open_tries; $i++)
- {
- if (defined $opt_L) {
- if (! $server->connect($connect_params)) {
- my ($error_number, $error_string) = $server->get_last_error();
- fail "$error_number, $error_string";
- }
- return;
- } else {
- if (! $vm->connect($connect_params, $opt_n)) {
- my ($error_number, $error_string) = $vm->get_last_error();
- fail "$error_number, $error_string";
- }
- return;
- }
- }
- if (defined $opt_L) {
- fail "failed: connect failed: ". $server->get_last_error() ."\n";
- } else {
- fail "failed: connect failed: ". $vm->get_last_error() ."\n";
- }
-}
-
-# Determine if the switch is a working state. Also check to make sure that
-# the switch has been specified in the case that there are slave switches
-# present. This assumes that we are at the main menu.
-sub identify_vmware
-{
- if (! defined $opt_L) {
- $vm_product = $vm->get_product_info(VM_PRODINFO_PRODUCT);
- $vm_platform = $vm->get_product_info(VM_PRODINFO_PLATFORM);
- $vm_build = $vm->get_product_info(VM_PRODINFO_BUILD);
- $vm_version_major = $vm->get_product_info(VM_PRODINFO_VERSION_MAJOR);
- $vm_version_minor = $vm->get_product_info(VM_PRODINFO_VERSION_MINOR);
- $vm_version_revision = $vm->get_product_info(VM_PRODINFO_VERSION_REVISION);
- }
-}
-
-
-sub logout
-{
- undef $vm, $server;
-}
-
-
-sub action
-{
- if (defined $opt_L) {
- foreach my $name ($server->registered_vm_names()) {
- print "$name\n";
- }
- logout();
-
- exit 0;
- }
- if (defined $opt_T) {
- print "success: test outlet $opt_n $opt_o\n" unless defined $opt_q;
- logout();
-
- exit 0;
- } elsif ( $vm->is_connected() ) {
- my $cur_state = $vm->get_execution_state();
- if ( $opt_o =~ /Reboot/i ) {
- $vm->reset($powerop_mode);
- } elsif ( $opt_o =~ /On/i ) {
- $vm->start($powerop_mode);
- } elsif ( $opt_o =~ /Off/i ) {
- $vm->stop($powerop_mode);
- }
- if ($_) {
- my ($error_number, $error_string) = $vm->get_last_error();
- if ($error_number != 0) {
- fail "$error_number, $error_string";
- } else {
- print "success: outlet $opt_n $opt_o\n" unless defined $opt_q;
- }
- logout();
-
- exit 0;
- }
- }
-
- fail "failed: unrecognised action response\n";
-}
-
-
-sub get_options_stdin
-{
- my $opt;
- my $line = 0;
- my $in;
- while( defined($in = <>) )
- {
- $_ = $in;
- chomp;
-
- # strip leading and trailing whitespace
- s/^\s*//;
- s/\s*$//;
-
- # skip comments
- next if /^#/;
-
- $line+=1;
- $opt=$_;
- next unless $opt;
-
- my ($name,$val)=split /\s*=\s*/, $opt;
-
- if ( $name eq "" )
- {
- print STDERR "parse error: illegal name in option $line\n";
- exit 2;
- }
- # DO NOTHING -- this field is used by fenced
- elsif ($name eq "agent" )
- {
- }
- elsif ($name eq "ipaddr" )
- {
- $opt_a = $val;
- }
- elsif ($name eq "login" )
- {
- $opt_l = $val;
- }
- elsif ($name eq "option" )
- {
- $opt_o = $val;
- }
- elsif ($name eq "passwd" )
- {
- $opt_p = $val;
- }
- elsif ($name eq "passwd_script" )
- {
- $opt_S = $val;
- }
- elsif ($name eq "port" )
- {
- $opt_n = $val;
- }
- elsif ($name eq "switch" )
- {
- $opt_P = $val;
- }
- elsif ($name eq "test" )
- {
- $opt_T = $val;
- }
- elsif ($name eq "verbose" )
- {
- $opt_v = $val;
- }
- # Excess name/vals will fail
- else
- {
- fail "parse error: unknown option \"$opt\"";
- }
- }
-}
-
-
-sub connect_error
-{
- fail "failed: connect returned: ".$vm->get_last_error()."\n";
-}
-
-
-### MAIN #######################################################
-
-if (@ARGV > 0) {
- getopts("a:hl:n:o:p:S:qTvVL") || fail_usage ;
-
- usage if defined $opt_h;
- version if defined $opt_V;
-
- fail_usage "Unkown parameter." if (@ARGV > 0);
-
- fail_usage "No '-a' flag specified." unless defined $opt_a;
- fail_usage "No '-n' flag specified." unless defined $opt_n or defined $opt_L;
- fail_usage "No '-l' flag specified." unless defined $opt_l;
-
- if (defined $opt_S) {
- $pwd_script_out = `$opt_S`;
- chomp($pwd_script_out);
- if ($pwd_script_out) {
- $opt_p = $pwd_script_out;
- }
- }
-
- fail_usage "No '-p' or '-S' flag specified." unless defined $opt_p;
- fail_usage "Unrecognized action '$opt_o' for '-o' flag"
- unless $opt_o =~ /^(Off|On|Reboot)$/i;
-
- ($opt_a, $opt_P) = split(/:/, $opt_a);
- fail_usage "No port number specified." unless defined $opt_P;
-
-} else {
- get_options_stdin();
-
- fail "failed: no IP address" unless defined $opt_a;
- fail "failed: no vm name" unless defined $opt_n;
- fail "failed: no login name" unless defined $opt_l;
-
- if (defined $opt_S) {
- $pwd_script_out = `$opt_S`;
- chomp($pwd_script_out);
- if ($pwd_script_out) {
- $opt_p = $pwd_script_out;
- }
- }
-
- fail "failed: no password" unless defined $opt_p;
- fail "failed: unrecognized action: $opt_o"
- unless $opt_o =~ /^(Off|On|Reboot)$/i;
-}
-
-&login;
-
-&identify_vmware;
-
-&action;
-
-exit 0;
-
-
diff --git a/fence/agents/vmware/fence_vmware.py b/fence/agents/vmware/fence_vmware.py
old mode 100755
new mode 100644
index a6ce9ef..75fd887
--- a/fence/agents/vmware/fence_vmware.py
+++ b/fence/agents/vmware/fence_vmware.py
@@ -1,153 +1,341 @@
#!/usr/bin/python
-##
-## Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
-##
-## The Following Agent Has Been Tested On VMware ESX 3.5 and VMware Server 1.0.7
-##
-#####
+#
+# The Following agent has been tested on:
+# vmrun 2.0.0 build-116503 (from VMware Server 2.0) against:
+# VMware ESX 4.0.0
+# VMware vCenter 4.0.0
+# VMware ESX 3.5
+# VMware Server 2.0.0
+# VMware ESXi 3.5 update 2
+# VMware Server 1.0.7 (works but list/status show only running VMs)
+#
+# VI Perl API 1.6 against:
+# VMware ESX 4.0.0
+# VMware vCenter 4.0.0
+# VMware ESX 3.5
+# VMware ESXi 3.5 update 2
+# VMware Virtual Center 2.5
+#
+# VMware vSphere SDK for Perl 4.0.0 against:
+# VMware ESX 4.0.0
+# VMware vCenter 4.0.0
+#
import sys, re, pexpect, exceptions
-sys.path.append("/usr/lib/fence")
+sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
#BEGIN_VERSION_GENERATION
-FENCE_RELEASE_NAME=""
+RELEASE_VERSION="VMware Agent using VI Perl API and/or VIX vmrun command"
REDHAT_COPYRIGHT=""
BUILD_DATE=""
#END_VERSION_GENERATION
-VMWARE_COMMAND="/usr/bin/vmware-cmd"
-COMMAND_PROMPT_REG="\[PEXPECT\]\$ "
-COMMAND_PROMPT_NEW="[PEXPECT]\$ "
+### CONSTANTS ####
+# VMware type is ESX/ESXi/VC
+VMWARE_TYPE_ESX=0
+# VMware type is Server 1.x
+VMWARE_TYPE_SERVER1=1
+# VMware type is Server 2.x and/or ESX 3.5 up2, ESXi 3.5 up2, VC 2.5 up2
+VMWARE_TYPE_SERVER2=2
+
+# Minimum required version of vmrun command
+VMRUN_MINIMUM_REQUIRED_VERSION=2
+
+# Default path to vmhelper command
+VMHELPER_COMMAND="fence_vmware_helper"
+# Default path to vmrun command
+VMRUN_COMMAND="/usr/bin/vmrun"
+# Default type of vmware
+VMWARE_DEFAULT_TYPE="esx"
+
+#### GLOBAL VARIABLES ####
+# Internal type. One of VMWARE_TYPE_, set by #vmware_check_vmware_type
+vmware_internal_type=VMWARE_TYPE_ESX
+
+# If ESX is disconnected, say, that VM is off (don't return previous state)
+vmware_disconnected_hack=False
+
+### FUNCTIONS ####
+
+#Split string in simplified DSV format to array of items
+def dsv_split(dsv_str):
+ delimiter_c=':'
+ escape_c='\\'
+
+ res=[]
+ status=0
+ tmp_str=""
+
+ for x in dsv_str:
+ if (status==0):
+ if (x==delimiter_c):
+ res.append(tmp_str)
+ tmp_str=""
+ elif (x==escape_c):
+ status=1
+ else:
+ tmp_str+=x
+ elif (status==1):
+ if (x==delimiter_c):
+ tmp_str+=delimiter_c
+ elif (x==escape_c):
+ tmp_str+=escape_c
+ else:
+ tmp_str+=escape_c+x
+ status=0
+
+ if (tmp_str!=""):
+ res.append(tmp_str)
+
+ return res
+
+# Quote string for proper existence in quoted string used for pexpect.run function
+# Ex. test'this will return test'\''this. So pexpect run will really pass ' to argument
+def quote_for_run(str):
+ dstr=''
+
+ for c in str:
+ if c==r"'":
+ dstr+="'\\''"
+ else:
+ dstr+=c
+
+ return dstr
+
+# Return string with command and additional parameters (something like vmrun -h 'host'
+def vmware_prepare_command(options,add_login_params,additional_params):
+ res=options["-e"]
+
+ if (add_login_params):
+ if (vmware_internal_type==VMWARE_TYPE_ESX):
+ res+=" --server '%s' --username '%s' --password '%s' "%(quote_for_run(options["-a"]),
+ quote_for_run(options["-l"]),
+ quote_for_run(options["-p"]))
+ elif (vmware_internal_type==VMWARE_TYPE_SERVER2):
+ res+=" -h 'https://%s/sdk' -u '%s' -p '%s' -T server "%(quote_for_run(options["-a"]),
+ quote_for_run(options["-l"]),
+ quote_for_run(options["-p"]))
+ elif (vmware_internal_type==VMWARE_TYPE_SERVER1):
+ host_name_array=options["-a"].split(':')
+
+ res+=" -h '%s' -u '%s' -p '%s' -T server1 "%(quote_for_run(host_name_array[0]),
+ quote_for_run(options["-l"]),
+ quote_for_run(options["-p"]))
+ if (len(host_name_array)>1):
+ res+="-P '%s' "%(quote_for_run(host_name_array[1]))
+
+ if ((options.has_key("-s")) and (vmware_internal_type==VMWARE_TYPE_ESX)):
+ res+="--datacenter '%s' "%(quote_for_run(options["-s"]))
+
+ if (additional_params!=""):
+ res+=additional_params
+
+ return res
+
+# Log message if user set verbose option
+def vmware_log(options, message):
+ if options["log"] >= LOG_MODE_VERBOSE:
+ options["debug_fh"].write(message+"\n")
+
+# Run command with timeout and parameters. Internaly uses vmware_prepare_command. Returns string
+# with output from vmrun command. If something fails (command not found, exit code is not 0), fail_usage
+# function is called (and never return).
+def vmware_run_command(options,add_login_params,additional_params,additional_timeout):
+ command=vmware_prepare_command(options,add_login_params,additional_params)
-# Start comunicating after login. Prepare good environment.
-def start_communication(conn, options):
- conn.sendline ("PS1='"+COMMAND_PROMPT_NEW+"'");
- conn.log_expect(options,COMMAND_PROMPT_REG,SHELL_TIMEOUT)
-
-# Prepare command line for vmware-cmd with parameters.
-def prepare_cmdline(conn,options,add_vm_name):
- cmd_line=VMWARE_COMMAND+" -H '"+options["-A"]+"' -U '"+options["-L"]+"' -P '"+options["-P"]+"'"
- if (add_vm_name):
- cmd_line+=" '"+options["-n"]+"'"
-
- if options.has_key("-v"):
- cmd_line+=" -v"
-
- return cmd_line
-
-def get_power_status(conn, options):
- result = ""
try:
- start_communication(conn,options)
-
- cmd_line=prepare_cmdline(conn,options,True)
-
- cmd_line+=" getstate"
+ vmware_log(options,command)
- conn.sendline(cmd_line)
-
- conn.log_expect(options,COMMAND_PROMPT_REG,SHELL_TIMEOUT)
- status_err = re.search("vmcontrol\ error\ ([-+]?\d+)\:(.*)",conn.before.lower())
- if (status_err!=None):
- fail_usage("VMware error "+status_err.group(1)+": "+status_err.group(2))
-
- status = re.search("getstate\(\)\ =\ on",conn.before.lower())
-
- result=(status==None and "off" or "on")
-
- except pexpect.EOF:
- fail(EC_CONNECTION_LOST)
- except pexpect.TIMEOUT:
- fail(EC_TIMED_OUT)
-
- return result
-
-def get_outlet_list(conn,options):
- result={}
-
- try:
- start_communication(conn,options)
+ (res_output,res_code)=pexpect.run(command,int(options["-Y"])+int(options["-y"])+additional_timeout,True)
- cmd_line=prepare_cmdline(conn,options,False)
- cmd_line+=" -l"
+ if (res_code==None):
+ fail(EC_TIMED_OUT)
+ if ((res_code!=0) and (add_login_params)):
+ vmware_log(options,res_output)
+ fail_usage("%s returned %s"%(options["-e"],res_output))
+ else:
+ vmware_log(options,res_output)
- conn.sendline(cmd_line)
-
- conn.log_expect(options,COMMAND_PROMPT_REG,SHELL_TIMEOUT)
- status_err = re.search("vmcontrol\ error\ ([-+]?\d+)\:(.*)",conn.before.lower())
- if (status_err!=None):
- fail_usage("VMware error "+status_err.group(1)+": "+status_err.group(2))
-
- lines=conn.before.splitlines()
+ except pexpect.ExceptionPexpect:
+ fail_usage("Cannot run command %s"%(options["-e"]))
- for line in lines[(options.has_key("-v") and 3 or 1):-1]:
- if (line!=""):
- result[line]=("","")
+ return res_output
- except pexpect.EOF:
- fail(EC_CONNECTION_LOST)
- except pexpect.TIMEOUT:
- fail(EC_TIMED_OUT)
+# Get outlet list with status as hash table. If you will use add_vm_name, only VM with vmname is
+# returned. This is used in get_status function
+def vmware_get_outlets_vi(conn, options, add_vm_name):
+ outlets={}
- return result
+ if (add_vm_name):
+ all_machines=vmware_run_command(options,True,("--operation status --vmname '%s'"%(quote_for_run(options["-n"]))),0)
+ else:
+ all_machines=vmware_run_command(options,True,"--operation list",int(options["-g"]))
+
+ all_machines_array=all_machines.splitlines()
+
+ for machine in all_machines_array:
+ machine_array=dsv_split(machine)
+ if (len(machine_array)==4):
+ if (machine_array[0] in outlets):
+ fail_usage("Failed. More machines with same name %s found!"%(machine_array[0]))
+
+ if (vmware_disconnected_hack):
+ outlets[machine_array[0]]=("",(
+ ((machine_array[2].lower() in ["poweredon"]) and
+ (machine_array[3].lower()=="connected"))
+ and "on" or "off"))
+ else:
+ outlets[machine_array[0]]=("",((machine_array[2].lower() in ["poweredon"]) and "on" or "off"))
+ return outlets
+
+# Get outlet list with status as hash table.
+def vmware_get_outlets_vix(conn,options):
+ outlets={}
+
+ running_machines=vmware_run_command(options,True,"list",0)
+ running_machines_array=running_machines.splitlines()[1:]
+
+ if (vmware_internal_type==VMWARE_TYPE_SERVER2):
+ all_machines=vmware_run_command(options,True,"listRegisteredVM",0)
+ all_machines_array=all_machines.splitlines()[1:]
+ elif (vmware_internal_type==VMWARE_TYPE_SERVER1):
+ all_machines_array=running_machines_array
+
+ for machine in all_machines_array:
+ if (machine!=""):
+ outlets[machine]=("",((machine in running_machines_array) and "on" or "off"))
+
+ return outlets
+
+def get_outlets_status(conn, options):
+ if (vmware_internal_type==VMWARE_TYPE_ESX):
+ return vmware_get_outlets_vi(conn,options,False)
+ if ((vmware_internal_type==VMWARE_TYPE_SERVER1) or (vmware_internal_type==VMWARE_TYPE_SERVER2)):
+ return vmware_get_outlets_vix(conn,options)
+
+def get_power_status(conn,options):
+ if (vmware_internal_type==VMWARE_TYPE_ESX):
+ outlets=vmware_get_outlets_vi(conn,options,True)
+ else:
+ outlets=get_outlets_status(conn,options)
+
+ if ((vmware_internal_type==VMWARE_TYPE_SERVER2) or (vmware_internal_type==VMWARE_TYPE_ESX)):
+ if (not (options["-n"] in outlets)):
+ fail_usage("Failed: You have to enter existing name of virtual machine!")
+ else:
+ return outlets[options["-n"]][1]
+ elif (vmware_internal_type==VMWARE_TYPE_SERVER1):
+ return ((options["-n"] in outlets) and "on" or "off")
def set_power_status(conn, options):
- try:
- start_communication(conn,options)
+ if (vmware_internal_type==VMWARE_TYPE_ESX):
+ additional_params="--operation %s --vmname '%s'"%((options["-o"]=="on" and "on" or "off"),quote_for_run(options["-n"]))
+ elif ((vmware_internal_type==VMWARE_TYPE_SERVER1) or (vmware_internal_type==VMWARE_TYPE_SERVER2)):
+ additional_params="%s '%s'"%((options["-o"]=="on" and "start" or "stop"),quote_for_run(options["-n"]))
+ if (options["-o"]=="off"):
+ additional_params+=" hard"
- cmd_line=prepare_cmdline(conn,options,True)
+ vmware_run_command(options,True,additional_params,int(options["-g"]))
- cmd_line+=" "+(options["-o"]=="on" and "start" or "stop hard")
+# Returns True, if user uses supported vmrun version (currently >=2.0.0) otherwise False.
+def vmware_is_supported_vmrun_version(options):
+ vmware_help_str=vmware_run_command(options,False,"",0)
+ version_re=re.search("vmrun version (\d\.(\d[\.]*)*)",vmware_help_str.lower())
+ if (version_re==None):
+ return False # Looks like this "vmrun" is not real vmrun
- conn.sendline(cmd_line)
+ version_array=version_re.group(1).split(".")
- conn.log_expect(options,COMMAND_PROMPT_REG,POWER_TIMEOUT)
-
- except pexpect.EOF:
- fail(EC_CONNECTION_LOST)
- except pexpect.TIMEOUT:
- fail(EC_TIMED_OUT)
-
+ try:
+ if (int(version_array[0])<VMRUN_MINIMUM_REQUIRED_VERSION):
+ return False
+ except Exception:
+ return False
+
+ return True
+
+# Define new options
+def vmware_define_defaults():
+ all_opt["vmware_type"]["default"]=VMWARE_DEFAULT_TYPE
+
+# Check vmware type, set vmware_internal_type to one of VMWARE_TYPE_ value and
+# options["-e"] to path (if not specified)
+def vmware_check_vmware_type(options):
+ global vmware_internal_type
+
+ options["-d"]=options["-d"].lower()
+
+ if (options["-d"]=="esx"):
+ vmware_internal_type=VMWARE_TYPE_ESX
+ if (not options.has_key("-e")):
+ options["-e"]=VMHELPER_COMMAND
+ elif (options["-d"]=="server2"):
+ vmware_internal_type=VMWARE_TYPE_SERVER2
+ if (not options.has_key("-e")):
+ options["-e"]=VMRUN_COMMAND
+ elif (options["-d"]=="server1"):
+ vmware_internal_type=VMWARE_TYPE_SERVER1
+ if (not options.has_key("-e")):
+ options["-e"]=VMRUN_COMMAND
+ else:
+ fail_usage("vmware_type can be esx,server2 or server1!")
+
+# Main agent method
def main():
- device_opt = [ "help", "version", "agent", "quiet", "verbose", "debug",
- "action", "ipaddr", "login", "passwd", "passwd_script",
- "secure", "identity_file", "test" , "vmipaddr", "vmlogin",
- "vmpasswd", "port", "vmpasswd_script", "separator" ]
+ device_opt = [ "help", "version", "agent", "quiet", "verbose", "debug",
+ "action", "ipaddr", "login", "passwd", "passwd_script",
+ "test", "port", "separator", "exec", "vmware_type",
+ "vmware_datacenter", "secure",
+ "power_timeout", "shell_timeout", "login_timeout", "power_wait" ]
atexit.register(atexit_handler)
+ vmware_define_defaults()
+
options = check_input(device_opt, process_input(device_opt))
- ##
- ## Fence agent specific defaults
- #####
- if 0 == options.has_key("-c"):
- options["-c"] = "\$ "
-
- if 0 == options.has_key("-A"):
- options["-A"] = "localhost"
-
- options["-x"] = 1
-
- show_docs(options)
- ##
- ## Operate the fencing device
- ####
- conn = fence_login(options)
- fence_action(conn, options, set_power_status, get_power_status, get_outlet_list)
-
- ##
- ## Logout from system
- ######
- try:
- conn.sendline("logout")
- conn.close()
- except exceptions.OSError:
- pass
- except pexpect.ExceptionPexpect:
- pass
+ # Default is secure connection
+ options["-x"] = 1
+
+ docs = { }
+ docs["shortdesc"] = "Fence agent for VMWare"
+ docs["longdesc"] = "fence_vmware is an I/O Fencing agent \
+which can be used with the VMware ESX, VMware ESXi or VMware Server \
+to fence virtual machines.\
+\n.P\n\
+Before you can use this agent, it must be installed VI Perl Toolkit or \
+vmrun command on every node you want to make fencing.\
+\n.P\n\
+VI Perl Toolkit is preferred for VMware ESX/ESXi and Virtual Center. Vmrun \
+command is only solution for VMware Server 1/2 (this command will works against \
+ESX/ESXi 3.5 up2 and VC up2 too, but not cluster aware!) and is available as part \
+of VMware VIX API SDK package. VI Perl and VIX API SDK are both available from \
+VMware web pages (not int RHEL repository!). \
+\n.P\n\
+You can specify type of VMware you are connecting to with \\fB-d\\fP switch \
+(or \\fIvmware_type\\fR for stdin). Possible values are esx, server2 and server1.\
+Default value is esx, which will use VI Perl. With server1 and server2, vmrun \
+command is used.\
+\n.P\n\
+After you have successfully installed VI Perl Toolkit or VIX API, you should \
+be able to run fence_vmware_helper (part of this agent) or vmrun command. \
+This agent supports only vmrun from version 2.0.0 (VIX API 1.6.0)."
+ show_docs(options, docs)
+
+ # Check vmware type and set path
+ vmware_check_vmware_type(options)
+
+ # Test user vmrun command version
+ if ((vmware_internal_type==VMWARE_TYPE_SERVER1) or (vmware_internal_type==VMWARE_TYPE_SERVER2)):
+ if (not (vmware_is_supported_vmrun_version(options))):
+ fail_usage("Unsupported version of vmrun command! You must use at least version %d!"%(VMRUN_MINIMUM_REQUIRED_VERSION))
+
+ # Operate the fencing device
+ result = fence_action(None, options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/fence/agents/vmware/fence_vmware_helper.pl b/fence/agents/vmware/fence_vmware_helper.pl
new file mode 100644
index 0000000..a0b5cea
--- /dev/null
+++ b/fence/agents/vmware/fence_vmware_helper.pl
@@ -0,0 +1,276 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my $ME = $0;
+
+END {
+ defined fileno STDOUT or return;
+ close STDOUT and return;
+ warn "$ME: failed to close standard output: $!\n";
+ $? ||= 1;
+}
+
+my ($RELEASE_VERSION, $REDHAT_COPYRIGHT, $BUILD_DATE);
+
+#BEGIN_VERSION_GENERATION
+$RELEASE_VERSION="";
+$REDHAT_COPYRIGHT="";
+$BUILD_DATE="";
+#END_VERSION_GENERATION
+
+#### FUNCTIONS #####
+# Show error message
+sub show_error {
+ print STDERR @_;
+}
+
+sub my_exit {
+ my ($exit_code)=@_;
+
+ # Disconnect from server
+ Util::disconnect();
+
+ exit $exit_code;
+}
+
+# Convert one field (string) to format acceptable by DSV. This
+# means replace any : with \: and \ with \\.
+sub convert_field_to_dsv {
+ my ($input_line)=@_;
+
+ $input_line =~ s/([\\:])/\\$1/g;
+ return $input_line
+}
+
+#### Global variables #####
+# Aditional options
+my %opts = (
+ 'operation' => {
+ type => "=s",
+ help => "The operation to perform (on,off,list,status). "
+ . "Operations on/off/status require name of the virtual machine",
+ default => "list",
+ required => 0,
+ },
+ 'vmname' => {
+ type => "=s",
+ help => "The name of the virtual machine",
+ required => 0,
+ },
+ 'datacenter' => {
+ type => "=s",
+ help => "The name of the datacenter",
+ required => 0,
+ }
+);
+
+#################
+##### MAIN ######
+#################
+
+# Conditional use of VIRuntime
+eval "use VMware::VIRuntime;";
+
+if ($@) {
+ show_error "Please install VI Perl API package to use this tool!\nPerl error: $@";
+ exit 1;
+}
+
+# Parse options
+Opts::add_options(%opts);
+Opts::parse();
+Opts::validate();
+
+if (!(Opts::get_option('operation')=~/^(on|off|list|status)$/i)) {
+ show_error "Operation should be on, off, list or status!\n";
+ exit 2;
+}
+
+my $operation=lc(Opts::get_option('operation'));
+
+if (($operation ne 'list') && (!defined Opts::get_option('vmname'))) {
+ show_error "Operation on, off, status require vmname parameter!\n";
+ exit 2;
+}
+
+
+# Try connect to machine
+eval {
+ Util::connect();
+};
+
+if ($@) {
+ show_error "Cannot connect to server!\nVMware error:".$@;
+ exit 3;
+}
+
+my ($datacenter, $datacenter_view, $vm_views,$vm);
+# We are connected to machine
+
+# If user want's datacenter, we must first find datacenter
+my %filter=(view_type => 'VirtualMachine');
+
+if( defined (Opts::get_option('datacenter')) ) {
+ $datacenter = Opts::get_option('datacenter');
+ $datacenter_view = Vim::find_entity_view(view_type => 'Datacenter',
+ filter => { name => $datacenter });
+ if (!$datacenter_view) {
+ show_error "Cannot find datacenter ".$datacenter."!\n";
+
+ my_exit 4;
+ }
+
+ $filter{'begin_entity'}=$datacenter_view;
+}
+
+if ($operation ne 'list') {
+ $filter{'filter'}= {"config.name" => Opts::get_option('vmname')};
+}
+
+$vm_views = Vim::find_entity_views(%filter);
+
+my $found=0;
+
+# Traverse all found vm
+foreach $vm(@$vm_views) {
+ if (($operation eq 'list') or ($operation eq 'status')) {
+ if (!$vm->summary->config->template) {
+ print convert_field_to_dsv($vm->name).":".
+ convert_field_to_dsv($vm->summary->config->vmPathName).":".
+ convert_field_to_dsv($vm->runtime->powerState->val).":".
+ convert_field_to_dsv($vm->runtime->connectionState->val)."\n";
+ }
+ } elsif ($operation eq 'on') {
+ eval {
+ $vm->PowerOnVM();
+ };
+
+ if ($@) {
+ # If error is SoapFault with InvalidPowerState, user maybe use some auto power on tool.
+ # This is not error, warning is enought.
+ if (ref($@) eq 'SoapFault') {
+ if (ref($@->detail) eq 'InvalidPowerState') {
+ show_error "Warning: Cannot power on vm (somebody done it before???) ".Opts::get_option('vmname').
+ "!\nVMware error:".$@."\n";
+ }
+ } else {
+ # Some other more serious problem
+ show_error "Cannot power on vm ".Opts::get_option('vmname')."!\nVMware error:".$@."\n";
+ my_exit 6;
+ }
+ }
+ } elsif ($operation eq 'off') {
+ eval {
+ $vm->PowerOffVM();
+ };
+
+ if ($@) {
+ # If error is SoapFault with InvalidPowerState, user maybe use some auto power off tool.
+ # This is not error, warning is enought.
+ if (ref($@) eq 'SoapFault') {
+ if (ref($@->detail) eq 'InvalidPowerState') {
+ show_error "Warning: Cannot power off vm (somebody done it before???) ".Opts::get_option('vmname').
+ "!\nVMware error:".$@."\n";
+ }
+ } else {
+ # Some other more serious problem
+ show_error "Cannot power off vm ".Opts::get_option('vmname')."!\nVMware error:".$@."\n";
+ my_exit 6;
+ }
+ }
+ } else {
+ show_error "Operation should be on, off or list!\n";
+ my_exit 2;
+ }
+ $found++;
+}
+
+if ((!$found) && ($operation ne 'list')) {
+ show_error "Cannot find vm ".Opts::get_option('vmname')."!\n";
+ my_exit 5;
+}
+
+# Should be 0 -> success all, or 6 in case of error
+my_exit 0;
+
+__END__
+
+=head1 NAME
+
+fence_vmware_helper - Perform list of virtual machines and
+ poweron, poweroff of operations on virtual machines.
+
+=head1 SYNOPSIS
+
+ fence_vmware_helper --operation <on|off|list|status> [options]
+
+=head1 DESCRIPTION
+
+This VI Perl command-line utility provides an interface for
+seven common provisioning operations on one or more virtual
+machines: powering on, powering off and listing virtual mode.
+
+=head1 OPTIONS
+
+=head2 GENERAL OPTIONS
+
+=over
+
+=item B<operation>
+
+Operation to be performed. One of the following:
+
+ <on> (power on one or more virtual machines),
+ <off> (power off one or more virtual machines),
+ <list> (list virtual machines and their status)
+ <status> (same as list, but show only machines with vmname)
+
+=item B<vmname>
+
+Optional. Name of the virtual machine on which the
+operation is to be performed.
+
+=item B<datacenter>
+
+Optional. Name of the datacenter for the virtual machine(s).
+Operations will be performed on all the virtual machines under the given datacenter.
+
+=back
+
+=head1 EXAMPLES
+
+Power on a virtual machine
+
+ fence_vmware_helper --username administrator --password administrator --operation on
+ --vmname rhel --server win1
+
+ fence_vmware_helper --username administrator --password administrator --operation on
+ --vmname rhel --server win1 --datacenter Datacenter
+
+Power off a virtual machine
+
+ fence_vmware_helper --username administrator --password administrator --operation off
+ --vmname rhel --server win1
+
+ perl fence_vmware_helper --username administrator --password administrator --operation off
+ --vmname rhel --server win1 --datacenter Datacenter
+
+List of virtual machines
+
+ fence_vmware_helper --username administrator --password administrator --server win1
+
+ fence_vmware_helper --username administrator --password administrator --server win1
+ --operation list
+
+Get status of virtual machine
+
+ fence_vmware_helper --username administrator --password administrator --server win1
+ --vmname rhel --operation status
+
+=head1 SUPPORTED PLATFORMS
+
+All operations supported on ESX 3.0.1
+
+All operations supported on Virtual Center 2.0.1
14 years, 5 months