LGTM
On Wed, Jul 30, 2014 at 11:31 AM, 'Helga Velroyen' via ganeti-devel < ganeti-devel@googlegroups.com> wrote: > On adding a new node, a new public/private SSH key pair > will be generated. The public key pair needs (possibly) > to be added to the 'ganeti_pub_keys' file and the > 'authorized_keys' file of other cluster nodes. This patch > provides the mechanism to fetch the new node's public > SSH key via ssh. Node that at this point, no new > public/private key pair is generated yet. This will come > in a later patch of this series as we first want to have > all infrastructure in place. > > Signed-off-by: Helga Velroyen <hel...@google.com> > --- > lib/client/gnt_node.py | 51 > ++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 51 insertions(+) > > diff --git a/lib/client/gnt_node.py b/lib/client/gnt_node.py > index d77d031..264c07b 100644 > --- a/lib/client/gnt_node.py > +++ b/lib/client/gnt_node.py > @@ -40,6 +40,7 @@ from ganeti import netutils > from ganeti import pathutils > from ganeti import ssh > from ganeti import compat > +from ganeti import ssconf > > from ganeti import confd > from ganeti.confd import client as confd_client > @@ -183,6 +184,47 @@ def _ReadSshKeys(keyfiles, _tostderr_fn=ToStderr): > return result > > > +def _ReadRemoteSshPubKeys(keyfiles, node, cluster_name, port, ask_key, > + strict_host_check, _tosterr_fn=ToStderr): > + """Fetches the public SSH keys from a node via SSH. > + > + @type keyfiles: dict from string to (string, string) tuples > + @param keyfiles: a dictionary mapping the type of key (e.g. rsa, dsa) > to a > + tuple consisting of the file name of the private and public key > + > + """ > + family = ssconf.SimpleStore().GetPrimaryIPFamily() > + ssh_runner = ssh.SshRunner(cluster_name, > + ipv6=(family == netutils.IP6Address.family)) > + > + failed_results = {} > + fetched_keys = {} > + for (kind, (_, public_key_file)) in keyfiles.items(): > + cmd = ["cat", public_key_file] > + ssh_cmd = ssh_runner.BuildCmd(node, constants.SSH_LOGIN_USER, > + utils.ShellQuoteArgs(cmd), > + batch=False, ask_key=ask_key, > quiet=False, > + strict_host_check=strict_host_check, > + use_cluster_key=False, > + port=port) > + > + result = utils.RunCmd(ssh_cmd) > + if result.failed: > + failed_results[kind] = (result.cmd, result.fail_reason) > + else: > + fetched_keys[kind] = result.stdout > + > + if len(fetched_keys.keys()) < 1: > + error_msg = "Could not fetch any public SSH key." > + for (kind, (cmd, fail_reason)) in failed_results.items(): > + error_msg += "Could not fetch the public '%s' SSH key from node > '%s':" \ > + " ran command '%s', failure reason: '%s'. " % \ > + (kind, node, cmd, fail_reason) > + raise errors.OpPrereqError(error_msg) > + > + return fetched_keys > + > + > def _SetupSSH(options, cluster_name, node, ssh_port, cl): > """Configures a destination node's SSH daemon. > > @@ -232,6 +274,15 @@ def _SetupSSH(options, cluster_name, node, ssh_port, > cl): > options.ssh_key_check, options.ssh_key_check, > ssh_port, data) > > + fetched_keys = _ReadRemoteSshPubKeys(root_keyfiles, node, cluster_name, > + ssh_port, options.ssh_key_check, > + options.ssh_key_check) > + for pub_key in fetched_keys.values(): > + # Unfortunately, we have to add the key with the node name rather than > + # the node's UUID here, because at this point, we do not have a UUID > yet. > + # The entry will be corrected in noded later. > + ssh.AddPublicKey(node, pub_key) > + > > @UsesRPC > def AddNode(opts, args): > -- > 2.0.0.526.g5318336 > >