# R0904: Too many public methods
import os
-import socket
import logging
import zlib
import base64
calls we can't raise an exception just because one one out of many
failed, and therefore we use this class to encapsulate the result.
- @ivar data: the data payload, for successfull results, or None
- @type failed: boolean
- @ivar failed: whether the operation failed at transport level (not
- application level on the remote node)
+ @ivar data: the data payload, for successful results, or None
@ivar call: the name of the RPC call
@ivar node: the name of the node to which we made the call
@ivar offline: whether the operation failed because the node was
"""
def __init__(self, data=None, failed=False, offline=False,
call=None, node=None):
- self.failed = failed
self.offline = offline
self.call = call
self.node = node
if offline:
- self.failed = True
self.fail_msg = "Node is marked offline"
self.data = self.payload = None
elif failed:
ec = errors.OpExecError
raise ec(msg)
- def RemoteFailMsg(self):
- """Check if the remote procedure failed.
-
- @return: the fail_msg attribute
-
- """
- return self.fail_msg
-
class Client:
"""RPC Client class.
list of nodes, will contact (in parallel) all nodes, and return a
dict of results (key: node name, value: result).
- One current bug is that generic failure is still signalled by
+ One current bug is that generic failure is still signaled by
'False' result, which is not good. This overloading of values can
cause bugs.
@return: List of RPC results
"""
- assert _http_manager, "RPC module not intialized"
+ assert _http_manager, "RPC module not initialized"
_http_manager.ExecRequests(self.nc.values())
"""
self._cfg = cfg
- self.port = utils.GetNodeDaemonPort()
+ self.port = utils.GetDaemonPort(constants.NODED)
def _InstDict(self, instance, hvp=None, bep=None):
"""Convert the given instance to a dict.
@type instance: L{objects.Instance}
@param instance: an Instance object
@type hvp: dict or None
- @param hvp: a dictionary with overriden hypervisor parameters
+ @param hvp: a dictionary with overridden hypervisor parameters
@type bep: dict or None
- @param bep: a dictionary with overriden backend parameters
+ @param bep: a dictionary with overridden backend parameters
@rtype: dict
@return: the instance dict, with the hvparams filled with the
cluster defaults
def _ConnectList(self, client, node_list, call):
"""Helper for computing node addresses.
- @type client: L{Client}
+ @type client: L{ganeti.rpc.Client}
@param client: a C{Client} instance
@type node_list: list
@param node_list: the node list we should connect
def _ConnectNode(self, client, node, call):
"""Helper for computing one node's address.
- @type client: L{Client}
+ @type client: L{ganeti.rpc.Client}
@param client: a C{Client} instance
@type node: str
@param node: the node we should connect
"""
body = serializer.DumpJson(args, indent=False)
- c = Client(procedure, body, utils.GetNodeDaemonPort())
+ c = Client(procedure, body, utils.GetDaemonPort(constants.NODED))
c.ConnectList(node_list, address_list=address_list)
return c.GetResults()
"""
body = serializer.DumpJson(args, indent=False)
- c = Client(procedure, body, utils.GetNodeDaemonPort())
+ c = Client(procedure, body, utils.GetDaemonPort(constants.NODED))
c.ConnectNode(node)
return c.GetResults()[node]
# Begin RPC calls
#
- def call_volume_list(self, node_list, vg_name):
+ def call_lv_list(self, node_list, vg_name):
"""Gets the logical volumes present in a given volume group.
This is a multi-node call.
"""
- return self._MultiNodeCall(node_list, "volume_list", [vg_name])
+ return self._MultiNodeCall(node_list, "lv_list", [vg_name])
def call_vg_list(self, node_list):
"""Gets the volume group list.
"""
return self._MultiNodeCall(node_list, "vg_list", [])
+ def call_storage_list(self, node_list, su_name, su_args, name, fields):
+ """Get list of storage units.
+
+ This is a multi-node call.
+
+ """
+ return self._MultiNodeCall(node_list, "storage_list",
+ [su_name, su_args, name, fields])
+
+ def call_storage_modify(self, node, su_name, su_args, name, changes):
+ """Modify a storage unit.
+
+ This is a single-node call.
+
+ """
+ return self._SingleNodeCall(node, "storage_modify",
+ [su_name, su_args, name, changes])
+
+ def call_storage_execute(self, node, su_name, su_args, name, op):
+ """Executes an operation on a storage unit.
+
+ This is a single-node call.
+
+ """
+ return self._SingleNodeCall(node, "storage_execute",
+ [su_name, su_args, name, op])
+
def call_bridges_exist(self, node, bridges_list):
"""Checks if a node has all the bridges given.
[checkdict, cluster_name])
@classmethod
- def call_node_start_master(cls, node, start_daemons):
+ def call_node_start_master(cls, node, start_daemons, no_voting):
"""Tells a node to activate itself as a master.
This is a single-node call.
"""
return cls._StaticSingleNodeCall(node, "node_start_master",
- [start_daemons])
+ [start_daemons, no_voting])
@classmethod
def call_node_stop_master(cls, node, stop_daemons):
This is a single-node call.
"""
- return self._SingleNodeCall(node, "blockdev_getmirrorstatus",
- [dsk.ToDict() for dsk in disks])
+ result = self._SingleNodeCall(node, "blockdev_getmirrorstatus",
+ [dsk.ToDict() for dsk in disks])
+ if not result.fail_msg:
+ result.payload = [objects.BlockDevStatus.FromDict(i)
+ for i in result.payload]
+ return result
def call_blockdev_find(self, node, disk):
"""Request identification of a given block device.
This is a single-node call.
"""
- return self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
+ result = self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
+ if not result.fail_msg and result.payload is not None:
+ result.payload = objects.BlockDevStatus.FromDict(result.payload)
+ return result
def call_blockdev_close(self, node, instance_name, disks):
"""Closes the given block devices.
params = [instance_name, [cf.ToDict() for cf in disks]]
return self._SingleNodeCall(node, "blockdev_close", params)
+ def call_blockdev_getsizes(self, node, disks):
+ """Returns the size of the given disks.
+
+ This is a single-node call.
+
+ """
+ params = [[cf.ToDict() for cf in disks]]
+ return self._SingleNodeCall(node, "blockdev_getsize", params)
+
def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
"""Disconnects the network of the given drbd devices.
"""
result = self._SingleNodeCall(node, "os_get", [name])
- if not result.failed and isinstance(result.data, dict):
+ if not result.fail_msg and isinstance(result.data, dict):
result.data = objects.OS.FromDict(result.data)
return result
return self._SingleNodeCall(node, "blockdev_grow",
[cf_bdev.ToDict(), amount])
+ def call_blockdev_export(self, node, cf_bdev,
+ dest_node, dest_path, cluster_name):
+ """Export a given disk to another node.
+
+ This is a single-node call.
+
+ """
+ return self._SingleNodeCall(node, "blockdev_export",
+ [cf_bdev.ToDict(), dest_node, dest_path,
+ cluster_name])
+
def call_blockdev_snapshot(self, node, cf_bdev):
"""Request a snapshot of the given block device.
"""
flat_disks = []
for disk in snap_disks:
- flat_disks.append(disk.ToDict())
+ if isinstance(disk, bool):
+ flat_disks.append(disk)
+ else:
+ flat_disks.append(disk.ToDict())
return self._SingleNodeCall(node, "finalize_export",
[self._InstDict(instance), flat_disks])