예제 #1
0
파일: base.py 프로젝트: s0undt3ch/libcloud
    def deploy_node(self, **kwargs):
        """
        Create a new node, and start deployment.

        In order to be able to SSH into a created node access credentials are
        required.

        A user can pass either a :class:`NodeAuthPassword` or
        :class:`NodeAuthSSHKey` to the ``auth`` argument. If the
        ``create_node`` implementation supports that kind if credential (as
        declared in ``self.features['create_node']``) then it is passed on to
        ``create_node``. Otherwise it is not passed on to ``create_node`` and
        it is only used for authentication.

        If the ``auth`` parameter is not supplied but the driver declares it
        supports ``generates_password`` then the password returned by
        ``create_node`` will be used to SSH into the server.

        Finally, if the ``ssh_key_file`` is supplied that key will be used to
        SSH into the server.

        This function may raise a :class:`DeploymentException`, if a create_node
        call was successful, but there is a later error (like SSH failing or
        timing out).  This exception includes a Node object which you may want
        to destroy if incomplete deployments are not desirable.

        >>> from libcloud.compute.drivers.dummy import DummyNodeDriver
        >>> from libcloud.compute.deployment import ScriptDeployment
        >>> from libcloud.compute.deployment import MultiStepDeployment
        >>> from libcloud.compute.base import NodeAuthSSHKey
        >>> driver = DummyNodeDriver(0)
        >>> key = NodeAuthSSHKey('...') # read from file
        >>> script = ScriptDeployment("yum -y install emacs strace tcpdump")
        >>> msd = MultiStepDeployment([key, script])
        >>> def d():
        ...     try:
        ...         node = driver.deploy_node(deploy=msd)
        ...     except NotImplementedError:
        ...         print ("not implemented for dummy driver")
        >>> d()
        not implemented for dummy driver

        Deploy node is typically not overridden in subclasses.  The
        existing implementation should be able to handle most such.

        :param deploy: Deployment to run once machine is online and
                            availble to SSH.
        :type deploy: :class:`Deployment`

        :param ssh_username: Optional name of the account which is used
                                  when connecting to
                                  SSH server (default is root)
        :type ssh_username: ``str``

        :param ssh_alternate_usernames: Optional list of ssh usernames to
                                             try to connect with if using the
                                             default one fails
        :type ssh_alternate_usernames: ``list``

        :param ssh_port: Optional SSH server port (default is 22)
        :type ssh_port: ``int``

        :param ssh_timeout: Optional SSH connection timeout in seconds
                                 (default is 10)
        :type ssh_timeout: ``float``

        :param auth:   Initial authentication information for the node
                            (optional)
        :type auth:   :class:`NodeAuthSSHKey` or :class:`NodeAuthPassword`

        :param ssh_key: A path (or paths) to an SSH private key with which
                             to attempt to authenticate. (optional)
        :type ssh_key: ``str`` or ``list`` of ``str``

        :param timeout: How many seconds to wait before timing out.
                             (default is 600)
        :type timeout: ``int``

        :param max_tries: How many times to retry if a deployment fails
                               before giving up (default is 3)
        :type max_tries: ``int``

        :param ssh_interface: The interface to wait for. Default is
                                   'public_ips', other option is 'private_ips'.
        :type ssh_interface: ``str``
        """
        if not libcloud.compute.ssh.have_paramiko:
            raise RuntimeError('paramiko is not installed. You can install ' +
                               'it using pip: pip install paramiko')

        if 'auth' in kwargs:
            auth = kwargs['auth']
            if not isinstance(auth, (NodeAuthSSHKey, NodeAuthPassword)):
                raise NotImplementedError(
                    'If providing auth, only NodeAuthSSHKey or'
                    'NodeAuthPassword is supported')
        elif 'ssh_key' in kwargs:
            # If an ssh_key is provided we can try deploy_node
            pass
        elif 'create_node' in self.features:
            f = self.features['create_node']
            if not 'generates_password' in f and not "password" in f:
                raise NotImplementedError(
                    'deploy_node not implemented for this driver')
        else:
            raise NotImplementedError(
                'deploy_node not implemented for this driver')

        node = self.create_node(**kwargs)
        max_tries = kwargs.get('max_tries', 3)

        password = None
        if 'auth' in kwargs:
            if isinstance(kwargs['auth'], NodeAuthPassword):
                password = kwargs['auth'].password
        elif 'password' in node.extra:
            password = node.extra['password']

        ssh_interface = kwargs.get('ssh_interface', 'public_ips')

        # Wait until node is up and running and has IP assigned
        try:
            node, ip_addresses = self.wait_until_running(
                nodes=[node],
                wait_period=3,
                timeout=kwargs.get('timeout', NODE_ONLINE_WAIT_TIMEOUT),
                ssh_interface=ssh_interface)[0]
        except Exception:
            e = sys.exc_info()[1]
            raise DeploymentError(node=node, original_exception=e, driver=self)

        ssh_username = kwargs.get('ssh_username', 'root')
        ssh_alternate_usernames = kwargs.get('ssh_alternate_usernames', [])
        ssh_port = kwargs.get('ssh_port', 22)
        ssh_timeout = kwargs.get('ssh_timeout', 10)
        ssh_key_file = kwargs.get('ssh_key', None)
        timeout = kwargs.get('timeout', SSH_CONNECT_TIMEOUT)

        deploy_error = None

        for username in ([ssh_username] + ssh_alternate_usernames):
            try:
                self._connect_and_run_deployment_script(
                    task=kwargs['deploy'],
                    node=node,
                    ssh_hostname=ip_addresses[0],
                    ssh_port=ssh_port,
                    ssh_username=username,
                    ssh_password=password,
                    ssh_key_file=ssh_key_file,
                    ssh_timeout=ssh_timeout,
                    timeout=timeout,
                    max_tries=max_tries)
            except Exception:
                # Try alternate username
                # Todo: Need to fix paramiko so we can catch a more specific
                # exception
                e = sys.exc_info()[1]
                deploy_error = e
            else:
                # Script sucesfully executed, don't try alternate username
                deploy_error = None
                break

        if deploy_error is not None:
            raise DeploymentError(node=node,
                                  original_exception=deploy_error,
                                  driver=self)

        return node
예제 #2
0
파일: base.py 프로젝트: bsbarkur/libcloud
    def deploy_node(self, **kwargs):
        """
        Create a new node, and start deployment.

        Depends on a Provider Driver supporting either using a specific
        password or returning a generated password.

        This function may raise a L{DeploymentException}, if a create_node
        call was successful, but there is a later error (like SSH failing or
        timing out).  This exception includes a Node object which you may want
        to destroy if incomplete deployments are not desirable.

        >>> from libcloud.compute.drivers.dummy import DummyNodeDriver
        >>> from libcloud.compute.deployment import ScriptDeployment
        >>> from libcloud.compute.deployment import MultiStepDeployment
        >>> from libcloud.compute.base import NodeAuthSSHKey
        >>> driver = DummyNodeDriver(0)
        >>> key = NodeAuthSSHKey('...') # read from file
        >>> script = ScriptDeployment("yum -y install emacs strace tcpdump")
        >>> msd = MultiStepDeployment([key, script])
        >>> def d():
        ...     try:
        ...         node = driver.deploy_node(deploy=msd)
        ...     except NotImplementedError:
        ...         print ("not implemented for dummy driver")
        >>> d()
        not implemented for dummy driver

        Deploy node is typically not overridden in subclasses.  The
        existing implementation should be able to handle most such.

        @inherits: L{NodeDriver.create_node}

        @keyword    deploy: Deployment to run once machine is online and
                            availble to SSH.
        @type       deploy: L{Deployment}

        @keyword    ssh_username: Optional name of the account which is used
                                  when connecting to
                                  SSH server (default is root)
        @type       ssh_username: C{str}

        @keyword    ssh_alternate_usernames: Optional list of ssh usernames to
                                             try to connect with if using the
                                             default one fails
        @type       ssh_alternate_usernames: C{list}

        @keyword    ssh_port: Optional SSH server port (default is 22)
        @type       ssh_port: C{int}

        @keyword    ssh_timeout: Optional SSH connection timeout in seconds
                                 (default is None)
        @type       ssh_timeout: C{float}

        @keyword    auth:   Initial authentication information for the node
                            (optional)
        @type       auth:   L{NodeAuthSSHKey} or L{NodeAuthPassword}

        @keyword    ssh_key: A path (or paths) to an SSH private key with which
                             to attempt to authenticate. (optional)
        @type       ssh_key: C{str} or C{list} of C{str}

        @keyword    timeout: How many seconds to wait before timing out.
                             (default is 600)
        @type       timeout: C{int}

        @keyword    max_tries: How many times to retry if a deployment fails
                               before giving up (default is 3)
        @type       max_tries: C{int}

        @keyword    ssh_interface: The interface to wait for. Default is
                                   'public_ips', other option is 'private_ips'.
        @type       ssh_interface: C{str}
        """
        if not libcloud.compute.ssh.have_paramiko:
            raise RuntimeError('paramiko is not installed. You can install ' +
                               'it using pip: pip install paramiko')

        password = None

        if 'create_node' not in self.features:
            raise NotImplementedError(
                'deploy_node not implemented for this driver')
        elif 'generates_password' not in self.features["create_node"]:
            if 'password' not in self.features["create_node"] and \
               'ssh_key' not in self.features["create_node"]:
                raise NotImplementedError(
                    'deploy_node not implemented for this driver')

            if 'auth' not in kwargs:
                value = os.urandom(16)
                kwargs['auth'] = NodeAuthPassword(binascii.hexlify(value))

            if 'ssh_key' not in kwargs:
                password = kwargs['auth'].password

        node = self.create_node(**kwargs)
        max_tries = kwargs.get('max_tries', 3)

        if 'generates_password' in self.features['create_node']:
            password = node.extra.get('password')

        ssh_interface = kwargs.get('ssh_interface', 'public_ips')

        # Wait until node is up and running and has IP assigned
        try:
            node, ip_addresses = self.wait_until_running(
                nodes=[node],
                wait_period=3,
                timeout=NODE_ONLINE_WAIT_TIMEOUT,
                ssh_interface=ssh_interface)[0]
        except Exception:
            e = sys.exc_info()[1]
            raise DeploymentError(node=node, original_exception=e, driver=self)

        if password:
            node.extra['password'] = password

        ssh_username = kwargs.get('ssh_username', 'root')
        ssh_alternate_usernames = kwargs.get('ssh_alternate_usernames', [])
        ssh_port = kwargs.get('ssh_port', 22)
        ssh_timeout = kwargs.get('ssh_timeout', 10)
        ssh_key_file = kwargs.get('ssh_key', None)
        timeout = kwargs.get('timeout', SSH_CONNECT_TIMEOUT)

        deploy_error = None

        for username in ([ssh_username] + ssh_alternate_usernames):
            try:
                self._connect_and_run_deployment_script(
                    task=kwargs['deploy'],
                    node=node,
                    ssh_hostname=ip_addresses[0],
                    ssh_port=ssh_port,
                    ssh_username=username,
                    ssh_password=password,
                    ssh_key_file=ssh_key_file,
                    ssh_timeout=ssh_timeout,
                    timeout=timeout,
                    max_tries=max_tries)
            except Exception:
                # Try alternate username
                # Todo: Need to fix paramiko so we can catch a more specific
                # exception
                e = sys.exc_info()[1]
                deploy_error = e
            else:
                # Script sucesfully executed, don't try alternate username
                deploy_error = None
                break

        if deploy_error is not None:
            raise DeploymentError(node=node,
                                  original_exception=deploy_error,
                                  driver=self)

        return node
예제 #3
0
    def deploy_node(self, **kwargs):
        """
        Create a new node, and start deployment.

        Depends on a Provider Driver supporting either using a specific password
        or returning a generated password.

        This function may raise a L{DeploymentException}, if a create_node
        call was successful, but there is a later error (like SSH failing or
        timing out).  This exception includes a Node object which you may want
        to destroy if incomplete deployments are not desirable.

        @keyword    deploy: Deployment to run once machine is online and availble to SSH.
        @type       deploy: L{Deployment}

        @keyword    ssh_username: Optional name of the account which is used when connecting to
                                  SSH server (default is root)
        @type       ssh_username: C{str}

        @keyword    ssh_port: Optional SSH server port (default is 22)
        @type       ssh_port: C{int}

        @keyword    ssh_timeout: Optional SSH connection timeout in seconds
                                 (default is None)
        @type       ssh_timeout: C{float}

        See L{NodeDriver.create_node} for more keyword args.

        >>> from libcloud.compute.drivers.dummy import DummyNodeDriver
        >>> from libcloud.deployment import ScriptDeployment, MultiStepDeployment
        >>> from libcloud.compute.base import NodeAuthSSHKey
        >>> driver = DummyNodeDriver(0)
        >>> key = NodeAuthSSHKey('...') # read from file
        >>> script = ScriptDeployment("yum -y install emacs strace tcpdump")
        >>> msd = MultiStepDeployment([key, script])
        >>> def d():
        ...     try:
        ...         node = driver.deploy_node(deploy=msd)
        ...     except NotImplementedError:
        ...         print "not implemented for dummy driver"
        >>> d()
        not implemented for dummy driver

        Deploy node is typically not overridden in subclasses.  The
        existing implementation should be able to handle most such.
        """
        # TODO: support ssh keys
        # FIX: this method is too long and complicated
        WAIT_PERIOD = 3
        password = None

        if 'generates_password' not in self.features["create_node"]:
            if 'password' not in self.features["create_node"]:
                raise NotImplementedError, \
                    'deploy_node not implemented for this driver'

            if not kwargs.has_key('auth'):
                kwargs['auth'] = NodeAuthPassword(os.urandom(16).encode('hex'))

            password = kwargs['auth'].password
        node = self.create_node(**kwargs)
        try:
            if 'generates_password' in self.features["create_node"]:
                password = node.extra.get('password')
                start = time.time()
                end = start + (60 * 15)  # FIX: this should be soft-coded
                while time.time() < end:
                    # need to wait until we get a public IP address.
                    # TODO: there must be a better way of doing this
                    time.sleep(WAIT_PERIOD)
                    nodes = self.list_nodes()
                    nodes = filter(lambda n: n.uuid == node.uuid, nodes)
                    if len(nodes) == 0:
                        raise DeploymentError(node,
                                              ("Booted node[%s] " % node +
                                               "is missing from list_nodes."))
                    if len(nodes) > 1:
                        raise DeploymentError(
                            node, ("Booted single node[%s], " % node +
                                   "but multiple nodes have same UUID"))

                    node = nodes[0]

                    if (node.public_ip is not None and node.public_ip != ""
                            and node.state == NodeState.RUNNING):
                        break

                    ssh_username = kwargs.get('ssh_username', 'root')
                    ssh_port = kwargs.get('ssh_port', 22)
                    ssh_timeout = kwargs.get('ssh_timeout', 20)

                    client = SSHClient(hostname=node.public_ip[0],
                                       port=ssh_port,
                                       username=ssh_username,
                                       password=password,
                                       timeout=ssh_timeout)

                    while time.time() < end:
                        try:
                            client.connect()
                        except (IOError, socket.gaierror, socket.error), e:
                            # Retry if a connection is refused or timeout
                            # occured
                            client.close()
                            time.sleep(WAIT_PERIOD)
                            continue

                        max_tries, tries = 3, 0
                        while tries < max_tries:
                            try:
                                n = kwargs["deploy"].run(node, client)
                                client.close()
                                raise
                            except Exception, e:
                                tries += 1
                                if tries >= max_tries:
                                    raise DeploymentError(
                                        node,
                                        'Failed after %d tries' % (max_tries))
예제 #4
0
                        while tries < max_tries:
                            try:
                                n = kwargs["deploy"].run(node, client)
                                client.close()
                                raise
                            except Exception, e:
                                tries += 1
                                if tries >= max_tries:
                                    raise DeploymentError(
                                        node,
                                        'Failed after %d tries' % (max_tries))

        except DeploymentError:
            raise
        except Exception, e:
            raise DeploymentError(node, e)
        return n

    def _get_size_price(self, size_id):
        return get_size_price(driver_type='compute',
                              driver_name=self.api_name,
                              size_id=size_id)


def is_private_subnet(ip):
    """
    Utility function to check if an IP address is inside a private subnet.

    @type ip: C{str}
    @keyword ip: IP address to check
예제 #5
0
파일: base.py 프로젝트: firefoxxy8/libcloud
    def deploy_node(self, **kwargs):
        """
        Create a new node, and start deployment.

        Depends on a Provider Driver supporting either using a specific
        password or returning a generated password.

        This function may raise a L{DeploymentException}, if a create_node
        call was successful, but there is a later error (like SSH failing or
        timing out).  This exception includes a Node object which you may want
        to destroy if incomplete deployments are not desirable.

        @keyword    deploy: Deployment to run once machine is online and
                            availble to SSH.
        @type       deploy: L{Deployment}

        @keyword    ssh_username: Optional name of the account which is used
                                  when connecting to
                                  SSH server (default is root)
        @type       ssh_username: C{str}

        @keyword    ssh_port: Optional SSH server port (default is 22)
        @type       ssh_port: C{int}

        @keyword    ssh_timeout: Optional SSH connection timeout in seconds
                                 (default is None)
        @type       ssh_timeout: C{float}

        @keyword    auth:   Initial authentication information for the node
                            (optional)
        @type       auth:   L{NodeAuthSSHKey} or L{NodeAuthPassword}

        See L{NodeDriver.create_node} for more keyword args.

        >>> from libcloud.compute.drivers.dummy import DummyNodeDriver
        >>> from libcloud.deployment import ScriptDeployment
        >>> from libcloud.deployment import MultiStepDeployment
        >>> from libcloud.compute.base import NodeAuthSSHKey
        >>> driver = DummyNodeDriver(0)
        >>> key = NodeAuthSSHKey('...') # read from file
        >>> script = ScriptDeployment("yum -y install emacs strace tcpdump")
        >>> msd = MultiStepDeployment([key, script])
        >>> def d():
        ...     try:
        ...         node = driver.deploy_node(deploy=msd)
        ...     except NotImplementedError:
        ...         print "not implemented for dummy driver"
        >>> d()
        not implemented for dummy driver

        Deploy node is typically not overridden in subclasses.  The
        existing implementation should be able to handle most such.
        """
        if not libcloud.compute.ssh.have_paramiko:
            raise RuntimeError('paramiko is not installed. You can install ' +
                               'it using pip: pip install paramiko')

        # TODO: support ssh keys
        password = None

        if 'create_node' not in self.features:
            raise NotImplementedError(
                'deploy_node not implemented for this driver')
        elif 'generates_password' not in self.features["create_node"]:
            if 'password' not in self.features["create_node"]:
                raise NotImplementedError(
                    'deploy_node not implemented for this driver')

            if 'auth' not in kwargs:
                kwargs['auth'] = NodeAuthPassword(os.urandom(16).encode('hex'))

            password = kwargs['auth'].password

        node = self.create_node(**kwargs)

        if 'generates_password' in self.features['create_node']:
            password = node.extra.get('password')

        try:
            # Wait until node is up and running and has public IP assigned
            self._wait_until_running(node=node,
                                     wait_period=3,
                                     timeout=NODE_ONLINE_WAIT_TIMEOUT)

            ssh_username = kwargs.get('ssh_username', 'root')
            ssh_port = kwargs.get('ssh_port', 22)
            ssh_timeout = kwargs.get('ssh_timeout', 10)

            ssh_client = SSHClient(hostname=node.public_ip[0],
                                   port=ssh_port,
                                   username=ssh_username,
                                   password=password,
                                   timeout=ssh_timeout)

            # Connect to the SSH server running on the node
            ssh_client = self._ssh_client_connect(ssh_client=ssh_client,
                                                  timeout=SSH_CONNECT_TIMEOUT)

            # Execute the deployment task
            self._run_deployment_script(task=kwargs['deploy'],
                                        node=node,
                                        ssh_client=ssh_client,
                                        max_tries=3)
        except Exception, e:
            raise DeploymentError(node, e)
예제 #6
0
    def deploy_node(self, **kwargs):
        """Create a new node, and start deployment.

        This function may raise a :class:`DeploymentException`, if a
        create_node call was successful, but there is a later error (like SSH
        failing or timing out).  This exception includes a Node object which
        you may want to destroy if incomplete deployments are not desirable.

        We use ``vagrant ssh-config <node>`` in order to get the SSH
        connection parameters for the deployment task. In order to do that,
        the node must be created first.

        The base implementation makes use of the SSH connection parameters
        *before* creating the node. Therefore we have to override it.

        :param deploy: Deployment to run once machine is online and available
                       to SSH.
        :type deploy: :class:`Deployment`

        :param ssh_timeout: Optional SSH connection timeout in seconds
                            (default is 10).
        :type ssh_timeout: ``float``

        :param timeout: How many seconds to wait before timing out (default is
                        600).
        :type timeout: ``int``

        :param max_tries: How many times to retry if a deployment fails before
                          giving up (default is 3).
        :type max_tries: ``int``

        :return: The node object for the new node.
        :rtype:  :class:`VagrantNode`

        """
        task = kwargs["deploy"]
        max_tries = kwargs.get("max_tries", 3)
        ssh_timeout = kwargs.get("ssh_timeout", 10)
        timeout = kwargs.get("timeout", SSH_CONNECT_TIMEOUT)

        node = self.create_node(**kwargs)
        ssh_config = self._vagrant_ssh_config(node.name)

        try:
            _, ip_addresses = self.wait_until_running(
                nodes=[node],
                wait_period=3,
                timeout=kwargs.get("timeout", NODE_ONLINE_WAIT_TIMEOUT),
                ssh_interface=ssh_config["host"])[0]

            self.log.info("Running deployment script on '%s' ..", node.name)
            self._connect_and_run_deployment_script(
                task=task,
                node=node,
                ssh_hostname=ip_addresses[0],
                ssh_port=ssh_config["port"],
                ssh_username=ssh_config["user"],
                ssh_password=None,
                ssh_key_file=ssh_config["key"],
                ssh_timeout=ssh_timeout,
                timeout=timeout,
                max_tries=max_tries)
            self.log.info(".. Finished deployment script on '%s' ..",
                          node.name)
        except Exception as exc:
            raise DeploymentError(node=node,
                                  original_exception=exc,
                                  driver=self)
        return node