diff --git a/README.md b/README.md index f7a40d5a6a..19e276b252 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ everything is done using CloudFormation or resources within AWS. ### Installation -The current working version is cfncluster-0.0.5. The CLI is written in python and uses BOTO for AWS actions. You can install the CLI with the following command: +The current working version is cfncluster-0.0.8. The CLI is written in python and uses BOTO for AWS actions. You can install the CLI with the following command: #### Linux/OSX @@ -77,7 +77,4 @@ Once all of those settings contain valid values, you can launch the cluster by r ``` $ cfncluster create mycluster ``` -Once the cluster reaches the "CREATE_COMPLETE" status, you can connect using your normal SSH client/settings or via the cfncluster CLI. -``` -$ cfncluster sshmaster mycluster -``` +Once the cluster reaches the "CREATE_COMPLETE" status, you can connect using your normal SSH client/settings. For more details on connecting to EC2 instances, check the EC2 User Guide - http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-connect-to-instance-linux.html#using-ssh-client diff --git a/cli/cfncluster/cfncluster.py b/cli/cfncluster/cfncluster.py index 4ccc09cb40..14833e45fc 100644 --- a/cli/cfncluster/cfncluster.py +++ b/cli/cfncluster/cfncluster.py @@ -15,9 +15,7 @@ import boto.exception import time import os -import paramiko import socket -import interactive import logging import cfnconfig @@ -277,74 +275,3 @@ def delete(args): print('\nExiting...') sys.exit(0) -def sshmaster(args): - stack = ('cfncluster-' + args.cluster_name) - config = cfnconfig.CfnClusterConfig(args) - cfnconn = boto.cloudformation.connect_to_region(config.region,aws_access_key_id=config.aws_access_key_id, - aws_secret_access_key=config.aws_secret_access_key) - outputs = cfnconn.describe_stacks(stack)[0].outputs - if args.useprivateip: - hostname = [ o for o in outputs if o.key == 'MasterPrivateIP' ][0].value - else: - hostname = [ o for o in outputs if o.key == 'MasterPublicIP' ][0].value - port = 22 - - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect((hostname, port)) - except Exception, e: - print '*** Connect failed: ' + str(e) - traceback.print_exc() - sys.exit(1) - - try: - t = paramiko.Transport(sock) - try: - t.start_client() - except paramiko.SSHException: - print '*** SSH negotiation failed.' - sys.exit(1) - - try: - keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts')) - except IOError: - try: - keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts')) - except IOError: - print '*** Unable to open host keys file' - keys = {} - - # check server's host key -- this is important. - key = t.get_remote_server_key() - if not keys.has_key(hostname): - print '*** WARNING: Unknown host key!' - elif not keys[hostname].has_key(key.get_name()): - print '*** WARNING: Unknown host key!' - elif keys[hostname][key.get_name()] != key: - print '*** WARNING: Host key has changed!!!' - sys.exit(1) - else: - print '*** Host key OK.' - - key = paramiko.RSAKey.from_private_key_file(config.key_location) - username = 'ec2-user' - t.auth_publickey(username, key) - - chan = t.open_session() - chan.get_pty() - chan.invoke_shell() - print '*** Here we go!' - print - interactive.interactive_shell(chan) - chan.close() - t.close() - - except Exception, e: - print '*** Caught exception: ' + str(e.__class__) + ': ' + str(e) - ##traceback.print_exc() - try: - t.close() - except: - pass - sys.exit(1) - diff --git a/cli/cfncluster/cfnconfig.py b/cli/cfncluster/cfnconfig.py index 8d6af9ded4..7d0d828de0 100644 --- a/cli/cfncluster/cfnconfig.py +++ b/cli/cfncluster/cfnconfig.py @@ -15,6 +15,8 @@ import inspect import pkg_resources import logging +import json +import urllib2 class CfnClusterConfig: @@ -57,6 +59,20 @@ def __init__(self, args): self.__cluster_template = __config.get('global', 'cluster_template') self.__cluster_section = ('cluster %s' % self.__cluster_template) + # Check if package updates should be checked + try: + self.__update_check = __config.get('global', 'update_check') + except ConfigParser.NoOptionError: + self.__update_check = True + + if self.__update_check == True: + try: + __latest = json.loads(urllib2.urlopen("http://pypi.python.org/pypi/cfncluster/json").read())['info']['version'] + if self.version < __latest: + print('warning: There is a newer version %s of cfncluster available.' % __latest) + except Exception: + pass + # Get the EC2 keypair name to be used, exit if not set try: self.key_name = __config.get(self.__cluster_section, 'key_name') diff --git a/cli/cfncluster/cli.py b/cli/cfncluster/cli.py index 4fc33c2b1b..075f06d71f 100644 --- a/cli/cfncluster/cli.py +++ b/cli/cfncluster/cli.py @@ -31,9 +31,6 @@ def list(args): def delete(args): cfncluster.delete(args) -def sshmaster(args): - cfncluster.sshmaster(args) - def instances(args): cfncluster.instances(args) @@ -123,13 +120,6 @@ def main(): help='show the status of cfncluster with the provided name.') pinstances.set_defaults(func=instances) - psshmaster = subparsers.add_parser('sshmaster', help='ssh to Master instance') - psshmaster.add_argument("cluster_name", type=str, default=None, - help='ssh to the Master of the cfncluster with the provided name.') - psshmaster.add_argument("--privateip", action='store_true', dest="useprivateip", - help='connect to the private IP of the MasterServer') - psshmaster.set_defaults(func=sshmaster) - args = parser.parse_args() logging.debug(args) args.func(args) \ No newline at end of file diff --git a/cli/cfncluster/examples/config b/cli/cfncluster/examples/config index a9a8dffa7a..f431251091 100644 --- a/cli/cfncluster/examples/config +++ b/cli/cfncluster/examples/config @@ -2,6 +2,8 @@ [global] # Default cluster config section. cluster_template = default +# Check for updates +update_check = false [aws] # This is the AWS credentials section (required). diff --git a/cli/cfncluster/interactive.py b/cli/cfncluster/interactive.py deleted file mode 100644 index c95cea946d..0000000000 --- a/cli/cfncluster/interactive.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2003-2007 Robey Pointer -# -# This file is part of paramiko. -# -# Paramiko is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2.1 of the License, or (at your option) -# any later version. -# -# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Paramiko; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - -import socket -import sys - -# windows does not have termios... -try: - import termios - import tty - has_termios = True -except ImportError: - has_termios = False - - -def interactive_shell(chan): - if has_termios: - posix_shell(chan) - else: - windows_shell(chan) - - -def posix_shell(chan): - import select - - oldtty = termios.tcgetattr(sys.stdin) - try: - tty.setraw(sys.stdin.fileno()) - tty.setcbreak(sys.stdin.fileno()) - chan.settimeout(0.0) - - while True: - r, w, e = select.select([chan, sys.stdin], [], []) - if chan in r: - try: - x = chan.recv(1024) - if len(x) == 0: - print '\r\n*** EOF\r\n', - break - sys.stdout.write(x) - sys.stdout.flush() - except socket.timeout: - pass - if sys.stdin in r: - x = sys.stdin.read(1) - if len(x) == 0: - break - chan.send(x) - - finally: - termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) - - -# thanks to Mike Looijmans for this code -def windows_shell(chan): - import threading - - sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n") - - def writeall(sock): - while True: - data = sock.recv(256) - if not data: - sys.stdout.write('\r\n*** EOF ***\r\n\r\n') - sys.stdout.flush() - break - sys.stdout.write(data) - sys.stdout.flush() - - writer = threading.Thread(target=writeall, args=(chan,)) - writer.start() - - try: - while True: - d = sys.stdin.read(1) - if not d: - break - chan.send(d) - except EOFError: - # user hit ^Z or F6 - pass \ No newline at end of file diff --git a/cli/setup.py b/cli/setup.py index 7d7d4112a4..aac5b02d6a 100644 --- a/cli/setup.py +++ b/cli/setup.py @@ -31,7 +31,7 @@ def read(fname): url = ("https://github.com/awslabs/cfncluster"), license = "Amazon Software License", packages = find_packages(), - install_requires=['boto >= 2.28.0', 'paramiko >= 1.14.0', 'argparse'], + install_requires=['boto', 'argparse'], entry_points=dict(console_scripts=console_scripts), include_package_data = True, zip_safe = False,