Fixes bug 942556 and bug 944105
Ensures the calls in the xenhost plugin work when the host is in a xenserver pool managed by the host aggregates feature. Change-Id: I51ca6b9f6d0e8d86d53afde5bf46cfabde17a44e
This commit is contained in:
parent
45146b337b
commit
37a392dc4c
@ -510,27 +510,40 @@ class XenAPISession(object):
|
|||||||
self.XenAPI = self.get_imported_xenapi()
|
self.XenAPI = self.get_imported_xenapi()
|
||||||
self._sessions = queue.Queue()
|
self._sessions = queue.Queue()
|
||||||
self.host_uuid = None
|
self.host_uuid = None
|
||||||
|
self.is_slave = False
|
||||||
exception = self.XenAPI.Failure(_("Unable to log in to XenAPI "
|
exception = self.XenAPI.Failure(_("Unable to log in to XenAPI "
|
||||||
"(is the Dom0 disk full?)"))
|
"(is the Dom0 disk full?)"))
|
||||||
is_slave = False
|
url = self._create_first_session(url, user, pw, exception)
|
||||||
for i in xrange(FLAGS.xenapi_connection_concurrent):
|
self._populate_session_pool(url, user, pw, exception)
|
||||||
try:
|
self._populate_host_uuid()
|
||||||
session = self._create_session(url)
|
|
||||||
with timeout.Timeout(FLAGS.xenapi_login_timeout, exception):
|
def _create_first_session(self, url, user, pw, exception):
|
||||||
session.login_with_password(user, pw)
|
try:
|
||||||
except self.XenAPI.Failure, e:
|
session = self._create_session(url)
|
||||||
# if user and pw of the master are different, we're doomed!
|
with timeout.Timeout(FLAGS.xenapi_login_timeout, exception):
|
||||||
if e.details[0] == 'HOST_IS_SLAVE':
|
session.login_with_password(user, pw)
|
||||||
master = e.details[1]
|
except self.XenAPI.Failure, e:
|
||||||
session = self.XenAPI.Session(pool.swap_xapi_host(url,
|
# if user and pw of the master are different, we're doomed!
|
||||||
master))
|
if e.details[0] == 'HOST_IS_SLAVE':
|
||||||
session.login_with_password(user, pw)
|
master = e.details[1]
|
||||||
is_slave = True
|
url = pool.swap_xapi_host(url, master)
|
||||||
else:
|
session = self.XenAPI.Session(url)
|
||||||
raise
|
session.login_with_password(user, pw)
|
||||||
|
self.is_slave = True
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
self._sessions.put(session)
|
||||||
|
return url
|
||||||
|
|
||||||
|
def _populate_session_pool(self, url, user, pw, exception):
|
||||||
|
for _ in xrange(FLAGS.xenapi_connection_concurrent - 1):
|
||||||
|
session = self._create_session(url)
|
||||||
|
with timeout.Timeout(FLAGS.xenapi_login_timeout, exception):
|
||||||
|
session.login_with_password(user, pw)
|
||||||
self._sessions.put(session)
|
self._sessions.put(session)
|
||||||
|
|
||||||
if is_slave:
|
def _populate_host_uuid(self):
|
||||||
|
if self.is_slave:
|
||||||
try:
|
try:
|
||||||
aggr = db.aggregate_get_by_host(context.get_admin_context(),
|
aggr = db.aggregate_get_by_host(context.get_admin_context(),
|
||||||
FLAGS.host)
|
FLAGS.host)
|
||||||
@ -539,6 +552,10 @@ class XenAPISession(object):
|
|||||||
LOG.exception(_('Host is member of a pool, but DB '
|
LOG.exception(_('Host is member of a pool, but DB '
|
||||||
'says otherwise'))
|
'says otherwise'))
|
||||||
raise
|
raise
|
||||||
|
else:
|
||||||
|
with self._get_session() as session:
|
||||||
|
host_ref = session.xenapi.session.get_this_host(session.handle)
|
||||||
|
self.host_uuid = session.xenapi.host.get_uuid(host_ref)
|
||||||
|
|
||||||
def get_product_version(self):
|
def get_product_version(self):
|
||||||
"""Return a tuple of (major, minor, rev) for the host version"""
|
"""Return a tuple of (major, minor, rev) for the host version"""
|
||||||
@ -569,10 +586,7 @@ class XenAPISession(object):
|
|||||||
def get_xenapi_host(self):
|
def get_xenapi_host(self):
|
||||||
"""Return the xenapi host on which nova-compute runs on."""
|
"""Return the xenapi host on which nova-compute runs on."""
|
||||||
with self._get_session() as session:
|
with self._get_session() as session:
|
||||||
if self.host_uuid:
|
return session.xenapi.host.get_by_uuid(self.host_uuid)
|
||||||
return session.xenapi.host.get_by_uuid(self.host_uuid)
|
|
||||||
else:
|
|
||||||
return session.xenapi.session.get_this_host(session.handle)
|
|
||||||
|
|
||||||
def call_xenapi(self, method, *args):
|
def call_xenapi(self, method, *args):
|
||||||
"""Call the specified XenAPI method on a background thread."""
|
"""Call the specified XenAPI method on a background thread."""
|
||||||
@ -599,8 +613,7 @@ class XenAPISession(object):
|
|||||||
host = self.get_xenapi_host()
|
host = self.get_xenapi_host()
|
||||||
# NOTE(armando): pass the host uuid along with the args so that
|
# NOTE(armando): pass the host uuid along with the args so that
|
||||||
# the plugin gets executed on the right host when using XS pools
|
# the plugin gets executed on the right host when using XS pools
|
||||||
if self.host_uuid:
|
args['host_uuid'] = self.host_uuid
|
||||||
args['host_uuid'] = self.host_uuid
|
|
||||||
with self._get_session() as session:
|
with self._get_session() as session:
|
||||||
return tpool.execute(self._unwrap_plugin_exceptions,
|
return tpool.execute(self._unwrap_plugin_exceptions,
|
||||||
session.xenapi.Async.host.call_plugin,
|
session.xenapi.Async.host.call_plugin,
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
#
|
#
|
||||||
# XenAPI plugin for reading/writing information to xenstore
|
# XenAPI plugin for host operations
|
||||||
#
|
#
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -122,12 +122,6 @@ def _resume_compute(session, compute_ref, compute_uuid):
|
|||||||
% (DEFAULT_SLEEP * (DEFAULT_TRIES + 1)))
|
% (DEFAULT_SLEEP * (DEFAULT_TRIES + 1)))
|
||||||
|
|
||||||
|
|
||||||
def _get_host_uuid():
|
|
||||||
cmd = "xe host-list | grep uuid"
|
|
||||||
resp = _run_command(cmd)
|
|
||||||
return resp.split(":")[-1].strip()
|
|
||||||
|
|
||||||
|
|
||||||
@jsonify
|
@jsonify
|
||||||
def set_host_enabled(self, arg_dict):
|
def set_host_enabled(self, arg_dict):
|
||||||
"""Sets this host's ability to accept new instances.
|
"""Sets this host's ability to accept new instances.
|
||||||
@ -137,17 +131,18 @@ def set_host_enabled(self, arg_dict):
|
|||||||
if enabled is None:
|
if enabled is None:
|
||||||
raise pluginlib.PluginError(
|
raise pluginlib.PluginError(
|
||||||
_("Missing 'enabled' argument to set_host_enabled"))
|
_("Missing 'enabled' argument to set_host_enabled"))
|
||||||
|
|
||||||
|
host_uuid = arg_dict['host_uuid']
|
||||||
if enabled == "true":
|
if enabled == "true":
|
||||||
result = _run_command("xe host-enable")
|
result = _run_command("xe host-enable uuid=%s" % host_uuid)
|
||||||
elif enabled == "false":
|
elif enabled == "false":
|
||||||
result = _run_command("xe host-disable")
|
result = _run_command("xe host-disable uuid=%s" % host_uuid)
|
||||||
else:
|
else:
|
||||||
raise pluginlib.PluginError(_("Illegal enabled status: %s") % enabled)
|
raise pluginlib.PluginError(_("Illegal enabled status: %s") % enabled)
|
||||||
# Should be empty string
|
# Should be empty string
|
||||||
if result:
|
if result:
|
||||||
raise pluginlib.PluginError(result)
|
raise pluginlib.PluginError(result)
|
||||||
# Return the current enabled status
|
# Return the current enabled status
|
||||||
host_uuid = _get_host_uuid()
|
|
||||||
cmd = "xe host-param-list uuid=%s | grep enabled" % host_uuid
|
cmd = "xe host-param-list uuid=%s | grep enabled" % host_uuid
|
||||||
resp = _run_command(cmd)
|
resp = _run_command(cmd)
|
||||||
# Response should be in the format: "enabled ( RO): true"
|
# Response should be in the format: "enabled ( RO): true"
|
||||||
@ -243,20 +238,21 @@ def iptables_config(session, args):
|
|||||||
raise pluginlib.PluginError(_("Invalid iptables command"))
|
raise pluginlib.PluginError(_("Invalid iptables command"))
|
||||||
|
|
||||||
|
|
||||||
def _power_action(action):
|
def _power_action(action, arg_dict):
|
||||||
host_uuid = _get_host_uuid()
|
|
||||||
# Host must be disabled first
|
# Host must be disabled first
|
||||||
result = _run_command("xe host-disable")
|
host_uuid = arg_dict['host_uuid']
|
||||||
|
result = _run_command("xe host-disable uuid=%s" % host_uuid)
|
||||||
if result:
|
if result:
|
||||||
raise pluginlib.PluginError(result)
|
raise pluginlib.PluginError(result)
|
||||||
# All running VMs must be shutdown
|
# All running VMs must be shutdown
|
||||||
result = _run_command("xe vm-shutdown --multiple power-state=running")
|
result = _run_command("xe vm-shutdown --multiple "
|
||||||
|
"resident-on=%s" % host_uuid)
|
||||||
if result:
|
if result:
|
||||||
raise pluginlib.PluginError(result)
|
raise pluginlib.PluginError(result)
|
||||||
cmds = {"reboot": "xe host-reboot",
|
cmds = {"reboot": "xe host-reboot uuid=%s",
|
||||||
"startup": "xe host-power-on",
|
"startup": "xe host-power-on uuid=%s",
|
||||||
"shutdown": "xe host-shutdown"}
|
"shutdown": "xe host-shutdown uuid=%s"}
|
||||||
result = _run_command(cmds[action])
|
result = _run_command(cmds[action] % host_uuid)
|
||||||
# Should be empty string
|
# Should be empty string
|
||||||
if result:
|
if result:
|
||||||
raise pluginlib.PluginError(result)
|
raise pluginlib.PluginError(result)
|
||||||
@ -266,13 +262,13 @@ def _power_action(action):
|
|||||||
@jsonify
|
@jsonify
|
||||||
def host_reboot(self, arg_dict):
|
def host_reboot(self, arg_dict):
|
||||||
"""Reboots the host."""
|
"""Reboots the host."""
|
||||||
return _power_action("reboot")
|
return _power_action("reboot", arg_dict)
|
||||||
|
|
||||||
|
|
||||||
@jsonify
|
@jsonify
|
||||||
def host_shutdown(self, arg_dict):
|
def host_shutdown(self, arg_dict):
|
||||||
"""Reboots the host."""
|
"""Reboots the host."""
|
||||||
return _power_action("shutdown")
|
return _power_action("shutdown", arg_dict)
|
||||||
|
|
||||||
|
|
||||||
@jsonify
|
@jsonify
|
||||||
@ -280,7 +276,7 @@ def host_start(self, arg_dict):
|
|||||||
"""Starts the host. Currently not feasible, since the host
|
"""Starts the host. Currently not feasible, since the host
|
||||||
runs on the same machine as Xen.
|
runs on the same machine as Xen.
|
||||||
"""
|
"""
|
||||||
return _power_action("startup")
|
return _power_action("startup", arg_dict)
|
||||||
|
|
||||||
|
|
||||||
@jsonify
|
@jsonify
|
||||||
@ -316,9 +312,8 @@ def host_data(self, arg_dict):
|
|||||||
"""Runs the commands on the xenstore host to return the current status
|
"""Runs the commands on the xenstore host to return the current status
|
||||||
information.
|
information.
|
||||||
"""
|
"""
|
||||||
host_uuid = arg_dict.get('host_uuid', _get_host_uuid())
|
host_uuid = arg_dict['host_uuid']
|
||||||
cmd = "xe host-param-list uuid=%s" % host_uuid
|
resp = _run_command("xe host-param-list uuid=%s" % host_uuid)
|
||||||
resp = _run_command(cmd)
|
|
||||||
parsed_data = parse_response(resp)
|
parsed_data = parse_response(resp)
|
||||||
# We have the raw dict of values. Extract those that we need,
|
# We have the raw dict of values. Extract those that we need,
|
||||||
# and convert the data types as needed.
|
# and convert the data types as needed.
|
||||||
|
Loading…
Reference in New Issue
Block a user