Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4511846
fence_ovm.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
fence_ovm.py
View Options
#!@PYTHON@ -tt
import
sys
,
time
import
requests
from
requests.adapters
import
HTTPAdapter
from
requests.exceptions
import
ConnectionError
,
Timeout
,
RequestException
from
json.decoder
import
JSONDecodeError
import
logging
import
atexit
import
itertools
sys
.
path
.
append
(
"@FENCEAGENTSLIBDIR@"
)
from
fencing
import
*
from
fencing
import
fail
,
fail_usage
,
run_delay
,
EC_GENERIC_ERROR
,
EC_CONNECTION_LOST
,
EC_TIMED_OUT
state
=
{
"RUNNING"
:
"on"
,
"STOPPED"
:
"off"
,
"SUSPENDED"
:
"off"
}
class
SSLAdapter
(
HTTPAdapter
):
def
__init__
(
self
,
certfile
,
password
):
import
ssl
from
ssl
import
SSLError
self
.
context
=
ssl
.
create_default_context
(
ssl
.
Purpose
.
CLIENT_AUTH
)
try
:
self
.
context
.
load_cert_chain
(
certfile
=
certfile
,
password
=
password
)
except
SSLError
as
e
:
logging
.
error
(
"Failed: The private key doesn't match with the certificate"
)
fail
(
EC_GENERIC_ERROR
)
except
OSError
as
e
:
logging
.
error
(
"
%s
:
%s
"
,
certfile
,
str
(
e
))
fail
(
EC_GENERIC_ERROR
)
super
()
.
__init__
()
def
init_poolmanager
(
self
,
*
args
,
**
kwargs
):
kwargs
[
"ssl_context"
]
=
self
.
context
return
super
()
.
init_poolmanager
(
*
args
,
**
kwargs
)
def
get_power_status
(
connection
,
options
):
vm
=
send_command
(
connection
,
options
,
"/Vm/{}"
.
format
(
options
[
"--plug"
]))
return
state
.
get
(
vm
[
"vmRunState"
])
def
sync_set_power_status
(
connection
,
options
):
action
=
{
"on"
:
"start"
,
"off"
:
"kill"
}[
options
[
"--action"
]]
job
=
send_command
(
connection
,
options
,
"/Vm/{}/{}"
.
format
(
options
[
"--plug"
],
action
),
"PUT"
)
for
_
in
itertools
.
count
(
1
):
if
not
job
[
"summaryDone"
]:
job
=
send_command
(
connection
,
options
,
"/Job/{}"
.
format
(
job
[
"id"
][
"value"
]))
if
job
[
"summaryDone"
]:
if
job
[
"jobRunState"
]
.
upper
()
==
"FAILURE"
:
logging
.
error
(
"Job failed:
%s
"
,
job
[
"error"
])
return
False
elif
job
[
"jobRunState"
]
.
upper
()
==
"SUCCESS"
:
status
=
get_power_status
(
connection
,
options
)
if
status
!=
options
[
"--action"
]:
logging
.
debug
(
"Job succeed, but '
%s
' power status is
%s
"
,
options
[
"--plug"
],
status
)
else
:
return
True
time
.
sleep
(
int
(
options
[
"--stonith-status-sleep"
]))
if
int
(
options
[
"--power-timeout"
])
>
0
and
_
>=
int
(
options
[
"--power-timeout"
]):
logging
.
error
(
"Job failed: Timed out waiting for
%s
to power
%s
"
,
options
[
"--plug"
],
options
[
"--action"
])
return
False
def
get_outlet_list
(
connection
,
options
):
virtual_machines
=
send_command
(
connection
,
options
,
"/Vm"
)
result
=
{}
for
vm
in
virtual_machines
:
status
=
state
.
get
(
vm
[
"vmRunState"
])
result
[
vm
[
"id"
][
"value"
]]
=
(
vm
[
"name"
],
status
)
return
result
def
connect
(
options
):
connection
=
requests
.
Session
()
password
=
options
.
get
(
"--password"
)
if
"--username"
in
options
:
connection
.
auth
=
(
options
[
"--username"
],
password
)
else
:
base_uri
=
"https://{}:{}/ovm/core/wsapi/rest"
.
format
(
options
[
"--ip"
],
options
[
"--ipport"
])
connection
.
mount
(
base_uri
,
SSLAdapter
(
options
[
"--ssl-client-certificate-file"
],
password
))
connection
.
verify
=
(
"--ssl-secure"
in
options
)
or
(
"--ssl-insecure"
not
in
options
)
if
connection
.
verify
:
if
"--ssl-insecure"
in
options
:
logging
.
warning
(
"The option '--ssl-insecure' is ignored"
)
else
:
import
urllib3
urllib3
.
disable_warnings
(
urllib3
.
exceptions
.
InsecureRequestWarning
)
connection
.
headers
.
update
({
"Accept"
:
"application/json"
,
"Content-Type"
:
"application/json"
})
return
connection
def
send_command
(
connection
,
options
,
resources_path
,
method
=
"GET"
):
uri
=
"https://{}:{}/ovm/core/wsapi/rest{}"
.
format
(
options
[
"--ip"
],
options
[
"--ipport"
],
resources_path
)
timeout
=
int
(
options
[
"--shell-timeout"
])
timeout
=
timeout
if
timeout
!=
0
else
None
try
:
if
method
==
"GET"
:
response
=
connection
.
get
(
uri
,
timeout
=
timeout
)
elif
method
==
"PUT"
:
response
=
connection
.
put
(
uri
,
timeout
=
timeout
)
else
:
logging
.
error
(
"The method '
%s
' is not supported yet"
,
method
)
fail
(
EC_GENERIC_ERROR
)
except
ConnectionError
as
e
:
logging
.
error
(
str
(
e
))
fail
(
EC_CONNECTION_LOST
)
except
Timeout
as
e
:
logging
.
error
(
str
(
e
))
fail
(
EC_TIMED_OUT
)
except
RequestException
as
e
:
logging
.
error
(
str
(
e
))
fail
(
EC_GENERIC_ERROR
)
try
:
result
=
response
.
json
()
except
JSONDecodeError
as
e
:
logging
.
error
(
"
%s
is not valid JSON. Status code is
%d
"
,
repr
(
str
(
response
.
content
,
response
.
encoding
or
"utf-8"
)),
response
.
status_code
)
fail
(
EC_GENERIC_ERROR
)
logging
.
debug
(
result
)
if
(
method
==
"GET"
and
response
.
status_code
!=
200
)
or
(
method
==
"PUT"
and
response
.
status_code
!=
201
):
message
=
result
.
get
(
"message"
)
if
type
(
result
)
is
dict
else
None
if
message
is
None
:
logging
.
error
(
"Failed: Remote returned
%d
for '
%s
' request to
%s
"
,
response
.
status_code
,
method
,
uri
)
else
:
logging
.
error
(
"Failed:
%s
:
%d
:
%s
"
,
method
,
response
.
status_code
,
result
[
"message"
])
fail
(
EC_GENERIC_ERROR
)
return
result
def
define_new_opts
():
all_opt
[
"ssl_client_certificate_file"
]
=
{
"getopt"
:
":"
,
"longopt"
:
"ssl-client-certificate-file"
,
"help"
:
"--ssl-client-certificate-file=[filename] SSL client certificate file"
,
"required"
:
"0"
,
"order"
:
1
}
def
validate_input
(
opt
,
stop
=
True
):
valid_input
=
True
if
"--username"
not
in
opt
and
"--ssl-client-certificate-file"
not
in
opt
:
valid_input
=
False
fail_usage
(
"Failed: You have to enter username or ssl client certificate file"
,
stop
)
if
"--username"
in
opt
and
"--ssl-client-certificate-file"
in
opt
:
valid_input
=
False
fail_usage
(
"Failed: You have to enter eather username or ssl client certificate file"
,
stop
)
if
"--username"
in
opt
and
(
"--password"
not
in
opt
and
"--password-script"
not
in
opt
):
valid_input
=
False
fail_usage
(
"Failed: You have to enter password or password script"
,
stop
)
if
"--shell-timeout"
in
opt
:
try
:
timeout
=
int
(
opt
[
"--shell-timeout"
])
if
timeout
<
0
:
valid_input
=
False
fail_usage
(
"Failed: Attempted to set --shell-timeout to
%d
, but the timeout cannot be set to a value less than 0"
%
timeout
,
stop
)
except
ValueError
:
# Expect ValueError of --shell-timeout to be checked by fencing.check_input function
pass
return
valid_input
def
main
():
device_opt
=
[
"ipaddr"
,
"ipport"
,
"login"
,
"no_login"
,
"passwd"
,
"no_password"
,
"port"
,
"ssl"
,
"ssl_client_certificate_file"
]
atexit
.
register
(
atexit_handler
)
define_new_opts
()
all_opt
[
"ipport"
][
"default"
]
=
"7002"
opt
=
process_input
(
device_opt
)
if
not
(
opt
.
get
(
"--action"
)
in
[
"metadata"
,
"manpage"
]
or
any
(
k
in
opt
for
k
in
(
"--help"
,
"--version"
))):
if
opt
.
get
(
"--action"
)
==
"validate-all"
:
if
not
validate_input
(
opt
,
False
):
fail_usage
(
"validate-all failed"
)
else
:
validate_input
(
opt
,
True
)
options
=
check_input
(
device_opt
,
opt
)
docs
=
{}
docs
[
"shortdesc"
]
=
"Fence agent for Oracle VM"
docs
[
"longdesc"
]
=
"fence_ovm is a Power Fencing agent
\
which can be used with the virtual machines managed by Oracle VM Manager."
docs
[
"vendorurl"
]
=
"https://www.oracle.com/virtualization/technologies/vm/"
show_docs
(
options
,
docs
)
run_delay
(
options
)
connection
=
connect
(
options
)
result
=
fence_action
(
connection
,
options
,
None
,
get_power_status
,
get_outlet_list
=
get_outlet_list
,
sync_set_power_fn
=
sync_set_power_status
)
sys
.
exit
(
result
)
if
__name__
==
"__main__"
:
main
()
File Metadata
Details
Attached
Mime Type
text/x-script.python
Expires
Wed, Jun 25, 2:56 AM (20 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1951926
Default Alt Text
fence_ovm.py (6 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment