module documentation

Module encapsulating ssh functionality.

Class SshRunner Wrapper for SSH commands.
Function AddAuthorizedKey Adds an SSH public key to an authorized_keys file.
Function AddAuthorizedKeys Adds a list of SSH public key to an authorized_keys file.
Function AddPublicKey Adds a new key to the list of public keys.
Function CheckForMultipleKeys Check if there is at most one key per host in 'authorized_keys' file.
Function ClearPubKeyFile Resets the content of the public key file.
Function DetermineKeyBits Checks the key bits to be used for a given key type, or provides defaults.
Function GetAllUserFiles Wrapper over GetUserFiles to retrieve files for all SSH key types.
Function GetUserFiles Return the paths of a user's SSH files.
Function HasAuthorizedKey Check if a particular key is in the 'authorized_keys' file.
Function InitPubKeyFile Creates the public key file and adds the master node's SSH key.
Function InitSSHSetup Setup the SSH configuration for the node.
Function OverridePubKeyFile Overrides the public key file with a list of given keys.
Function QueryPubKeyFile Retrieves a map of keys for the requested node UUIDs.
Function ReadRemoteSshPubKeys Fetches a public SSH key from a node via SSH.
Function RemoveAuthorizedKey Removes an SSH public key from an authorized_keys file.
Function RemoveAuthorizedKeys Removes public SSH keys from an authorized_keys file.
Function RemovePublicKey Removes a key from the list of public keys.
Function ReplaceNameByUuid Replaces a host name with the node's corresponding UUID.
Function RunSshCmdWithStdin Runs a command on a remote machine via SSH and provides input in stdin.
Function WriteKnownHostsFile Writes the cluster-wide equally known_hosts file.
Constant SSH_KEY_VALID_BITS Undocumented
Variable KeyBitInfo Undocumented
Function _AddPublicKeyElse Adds a new SSH key to the key file if it did not exist already.
Function _AddPublicKeyProcessLine Processes one line of the public key file when adding a key.
Function _EnsureCorrectGanetiVersion Ensured the correct Ganeti version before running a command via SSH.
Function _ManipulatePubKeyFile Manipulates the list of public SSH keys of the cluster.
Function _ParseKeyLine Parses a line of the public key file.
Function _RemovePublicKeyElse Logs when we tried to remove a key that does not exist.
Function _RemovePublicKeyProcessLine Processes a line in the public key file when aiming for removing a key.
Function _ReplaceNameByUuidElse Logs a debug message when we try to replace a key that is not there.
Function _ReplaceNameByUuidProcessLine Replaces a node's name with its UUID on a matching line in the key file.
Function _SplitSshKey Splits a line for SSH's authorized_keys file.
def AddAuthorizedKey(file_obj, key):

Adds an SSH public key to an authorized_keys file.

Parameters
file_obj:str or file handlepath to authorized_keys file
key:strstring containing key
def AddAuthorizedKeys(file_obj, keys):

Adds a list of SSH public key to an authorized_keys file.

Parameters
file_obj:str or file handlepath to authorized_keys file
keys:list of strlist of strings containing keys
def AddPublicKey(new_uuid, new_key, key_file=pathutils.SSH_PUB_KEYS, error_fn=errors.ProgrammerError):

Adds a new key to the list of public keys.

See Also
_ManipulatePubKeyFile for parameter descriptions.
def CheckForMultipleKeys(file_obj, node_names):

Check if there is at most one key per host in 'authorized_keys' file.

Parameters
file_obj:str or file handlepath to authorized_keys file
node_names:list of strlist of names of nodes of the cluster
Returns
a dictionary with hostnames which occur more than once
def ClearPubKeyFile(key_file=pathutils.SSH_PUB_KEYS, mode=384):

Resets the content of the public key file.

def DetermineKeyBits(key_type, key_bits, old_key_type, old_key_bits):

Checks the key bits to be used for a given key type, or provides defaults.

Parameters
key_type:one of constants.SSHK_ALLThe key type to use.
key_bits:positive int or NoneThe number of bits to use, if supplied by user.
old_key_type:one of constants.SSHK_ALL or NoneThe previously used key type, if any.
old_key_bits:positive int or NoneThe previously used number of bits, if any.
Returns
positive intThe number of bits to use.
def GetAllUserFiles(user, mkdir=False, dircheck=True, _homedir_fn=None):

Wrapper over GetUserFiles to retrieve files for all SSH key types.

See GetUserFiles for details.

Returns
tuple; (string, dict with string as key, tuple of (string, string) as value)Undocumented
def GetUserFiles(user, mkdir=False, dircheck=True, kind=constants.SSHK_DSA, _homedir_fn=None):

Return the paths of a user's SSH files.

Parameters
user:stringUsername
mkdir:boolWhether to create ".ssh" directory if it doesn't exist
dircheck:boolWhether to check if ".ssh" directory exists
kind:stringOne of constants.SSHK_ALL
_homedir_fnUndocumented
Returns
tuple; (string, string, string)Tuple containing three file system paths; the private SSH key file, the public SSH key file and the user's authorized_keys file
Raises
errors.OpExecErrorWhen home directory of the user can not be determined
errors.OpExecErrorRegardless of the mkdir parameters, this exception is raised if ~$user/.ssh is not a directory and dircheck is set to True
def HasAuthorizedKey(file_obj, key):

Check if a particular key is in the 'authorized_keys' file.

Parameters
file_obj:str or file handlepath to authorized_keys file
key:strstring containing key
def InitPubKeyFile(master_uuid, key_type, key_file=pathutils.SSH_PUB_KEYS):

Creates the public key file and adds the master node's SSH key.

Parameters
master_uuid:strthe master node's UUID
key_type:one of constants.SSHK_ALLthe type of ssh key to be used
key_file:strname of the file containing the public keys
def InitSSHSetup(key_type, key_bits, error_fn=errors.OpPrereqError, _homedir_fn=None, _suffix=''):

Setup the SSH configuration for the node.

This generates a dsa keypair for root, adds the pub key to the permitted hosts and adds the hostkey to its own known hosts.

Parameters
key_typethe type of SSH keypair to be generated
key_bitsthe key length, in bits, to be used
error_fnUndocumented
_homedir_fnUndocumented
_suffixUndocumented
def OverridePubKeyFile(key_map, key_file=pathutils.SSH_PUB_KEYS):

Overrides the public key file with a list of given keys.

Parameters
key_map:dict from str to list of strdictionary mapping uuids to lists of SSH keys
key_fileUndocumented
def QueryPubKeyFile(target_uuids, key_file=pathutils.SSH_PUB_KEYS, error_fn=errors.ProgrammerError):

Retrieves a map of keys for the requested node UUIDs.

Parameters
target_uuids:str or list of strUUID of the node to retrieve the key for or a list of UUIDs of nodes to retrieve the keys for
key_file:strfilename of the file of public node keys (optional parameter for testing)
error_fn:functionFunction that returns an exception, used to customize exception types depending on the calling context
Returns
dict mapping strings to list of stringsdictionary mapping node uuids to their ssh keys
def ReadRemoteSshPubKeys(pub_key_file, node, cluster_name, port, ask_key, strict_host_check):

Fetches a public SSH key from a node via SSH.

Parameters
pub_key_file:stringa tuple consisting of the file name of the public DSA key
nodeUndocumented
cluster_nameUndocumented
portUndocumented
ask_keyUndocumented
strict_host_checkUndocumented
def RemoveAuthorizedKey(file_name, key):

Removes an SSH public key from an authorized_keys file.

Parameters
file_name:strpath to authorized_keys file
key:strstring containing key
def RemoveAuthorizedKeys(file_name, keys):

Removes public SSH keys from an authorized_keys file.

Parameters
file_name:strpath to authorized_keys file
keys:list of strlist of strings containing keys
def RemovePublicKey(target_uuid, key_file=pathutils.SSH_PUB_KEYS, error_fn=errors.ProgrammerError):

Removes a key from the list of public keys.

See Also
_ManipulatePubKeyFile for parameter descriptions.
def ReplaceNameByUuid(node_uuid, node_name, key_file=pathutils.SSH_PUB_KEYS, error_fn=errors.ProgrammerError):

Replaces a host name with the node's corresponding UUID.

When a node is added to the cluster, we don't know it's UUID yet. So first its SSH key gets added to the public key file and in a second step, the node's name gets replaced with the node's UUID as soon as we know the UUID.

Parameters
node_uuid:stringthe node's UUID to replace the node's name
node_name:stringthe node's name to be replaced by the node's UUID
key_fileUndocumented
error_fnUndocumented
See Also
_ManipulatePubKeyFile for the other parameter descriptions.
def RunSshCmdWithStdin(cluster_name, node, basecmd, port, data, debug=False, verbose=False, use_cluster_key=False, ask_key=False, strict_host_check=False, ensure_version=False):

Runs a command on a remote machine via SSH and provides input in stdin.

Parameters
cluster_name:stringCluster name
node:stringNode name
basecmd:stringBase command (path on the remote machine)
port:intThe SSH port of the remote machine or None for the default
dataJSON-serializable input data for script (passed to stdin)
debug:boolEnable debug output
verbose:boolEnable verbose output
use_cluster_key:boolSee ssh.SshRunner.BuildCmd
ask_key:boolSee ssh.SshRunner.BuildCmd
strict_host_check:boolSee ssh.SshRunner.BuildCmd
ensure_versionUndocumented
def WriteKnownHostsFile(cfg, file_name):

Writes the cluster-wide equally known_hosts file.

SSH_KEY_VALID_BITS =

Undocumented

Value
{constants.SSHK_DSA: KeyBitInfo(1024, (lambda b: b == 1024)),
 constants.SSHK_RSA: KeyBitInfo(2048, (lambda b: b >= 768)),
 constants.SSHK_ECDSA: KeyBitInfo(384, (lambda b: b in [256, 384, 521]))}
KeyBitInfo =

Undocumented

def _AddPublicKeyElse(new_uuid, new_key):

Adds a new SSH key to the key file if it did not exist already.

This is an auxiliary function for _ManipulatePublicKeyFile which is carried out when a new key is added to the public key file and after processing the whole file, we found out that the key does not exist in the file yet but needs to be appended at the end.

Parameters
new_uuid:stringthe UUID of the node whose key is added
new_key:stringthe SSH key to be added
Returns
stringa new line to be added to the file
def _AddPublicKeyProcessLine(new_uuid, new_key, line_uuid, line_key, found):

Processes one line of the public key file when adding a key.

This is a sub function that can be called within the _ManipulatePublicKeyFile function. It processes one line of the public key file, checks if this line contains the key to add already and if so, notes the occurrence in the return value.

Parameters
new_uuid:stringthe node UUID of the node whose key is added
new_key:stringthe SSH key to be added
line_uuid:the UUID of the node whose line in the public key file is processed in this function callUndocumented
line_keythe SSH key of the node whose line in the public key file is processed in this function call
found:booleanwhether or not the (UUID, key) pair of the node whose key is being added was found in the public key file already.
Returns
(boolean, string)a possibly updated value of found and the processed line
def _EnsureCorrectGanetiVersion(cmd):

Ensured the correct Ganeti version before running a command via SSH.

Before a command is run on a node via SSH, it makes sense in some situations to ensure that this node is indeed running the correct version of Ganeti like the rest of the cluster.

Parameters
cmd:stringstring
Returns
list of stringsa list of commands with the newly added ones at the beginning
def _ManipulatePubKeyFile(target_identifier, target_key, key_file=pathutils.SSH_PUB_KEYS, error_fn=errors.ProgrammerError, process_line_fn=None, process_else_fn=None):

Manipulates the list of public SSH keys of the cluster.

This is a general function to manipulate the public key file. It needs two auxiliary functions process_line_fn and process_else_fn to work. Generally, the public key file is processed as follows: 1) The function processes each line of the original ganeti public key file, applies the process_line_fn function on it, which returns a possibly manipulated line and an indicator whether the line in question was found. If a line is returned, it is added to a list of lines for later writing to the file. 2) If all lines are processed and the 'found' variable is False, the seconds auxiliary function process_else_fn is called to possibly add more lines to the list of lines. 3) Finally, the list of lines is assembled to a string and written atomically to the public key file, thereby overriding it.

If the public key file does not exist, we create it. This is necessary for a smooth transition after an upgrade.

Parameters
target_identifier:stridentifier of the node whose key is added; in most cases this is the node's UUID, but in some it is the node's host name
target_key:strstring containing a public SSH key (a complete line possibly including more parameters than just the key)
key_file:strfilename of the file of public node keys (optional parameter for testing)
error_fn:functionFunction that returns an exception, used to customize exception types depending on the calling context
process_line_fn:functionfunction to process one line of the public key file
process_else_fn:functionfunction to be called if no line of the key file matches the target uuid
def _ParseKeyLine(line, error_fn):

Parses a line of the public key file.

Parameters
line:stringline of the public key file
error_fn:functionfunction to process error messages
Returns
tuple (string, string)a tuple containing the UUID of the node and a string containing the SSH key and possible more parameters for the key
def _RemovePublicKeyElse(target_uuid, _target_key):

Logs when we tried to remove a key that does not exist.

This is an auxiliary function for _ManipulatePublicKeyFile which is run after we have processed the complete public key file and did not find the key to be removed.

Parameters
target_uuid:stringthe UUID of the node whose key was supposed to be removed
_target_key:stringthe key of the node which was supposed to be removed (not used)
Returns
stringin this case, always None
def _RemovePublicKeyProcessLine(target_uuid, _target_key, line_uuid, line_key, found):

Processes a line in the public key file when aiming for removing a key.

This is an auxiliary function for _ManipulatePublicKeyFile when we are removing a key from the public key file. This particular function only checks if the current line contains the UUID of the node in question and writes the line to the temporary file otherwise.

Parameters
target_uuid:stringUUID of the node whose key is being removed
_target_key:stringSSH key of the node (not used)
line_uuid:stringUUID of the node whose line is processed in this call
line_key:stringSSH key of the nodes whose line is processed in this call
found:booleanwhether or not the UUID was already found.
Returns
(boolean, string)a tuple, indicating if the target line was found and the processed line; the line is 'None', if the original line is removed
def _ReplaceNameByUuidElse(node_uuid, node_name, _key):

Logs a debug message when we try to replace a key that is not there.

This is an implementation of the auxiliary process_else_fn function for the _ManipulatePubKeyFile function when we use it to replace a line in the public key file that is indexed by the node's name instead of the node's UUID.

Parameters
node_uuid:stringthe node's UUID
node_name:stringthe node's UUID
_key:string (not used)the node's SSH key (not used)
Returns
stringin this case, always None
def _ReplaceNameByUuidProcessLine(node_name, _key, line_identifier, line_key, found, node_uuid=None):

Replaces a node's name with its UUID on a matching line in the key file.

This is an auxiliary function for _ManipulatePublicKeyFile which processes a line of the ganeti public key file. If the line in question matches the node's name, the name will be replaced by the node's UUID.

Parameters
node_name:stringname of the node to be replaced by the UUID
_key:stringSSH key of the node (not used)
line_identifier:stringan identifier of a node in a line of the public key file. This can be either a node name or a node UUID, depending on if it got replaced already or not.
line_key:stringSSH key of the node whose line is processed
found:booleanwhether or not the line matches the node's name
node_uuid:stringthe node's UUID which will replace the node name
Returns
(boolean, string)a tuple indicating whether the target line was found and the processed line
def _SplitSshKey(key):

Splits a line for SSH's authorized_keys file.

If the line has no options (e.g. no command="..."), only the significant parts, the key type and its hash, are used. Otherwise the whole line is used (split at whitespace).

Parameters
key:stringKey line
Returns
tupleUndocumented