Exemple #1
0
    def _launchNode(self):
        if self.label.diskimage:
            diskimage = self.provider_config.diskimages[
                self.label.diskimage.name]
        else:
            diskimage = None

        if diskimage:
            # launch using diskimage
            cloud_image = self.handler.zk.getMostRecentImageUpload(
                diskimage.name, self.provider_config.name)

            if not cloud_image:
                raise exceptions.LaunchNodepoolException(
                    "Unable to find current cloud image %s in %s" %
                    (diskimage.name, self.provider_config.name)
                )

            config_drive = diskimage.config_drive
            image_external = dict(id=cloud_image.external_id)
            image_id = "{path}/{upload_id}".format(
                path=self.handler.zk._imageUploadPath(
                    cloud_image.image_name,
                    cloud_image.build_id,
                    cloud_image.provider_name),
                upload_id=cloud_image.id)
            image_name = diskimage.name
            username = cloud_image.username
            connection_type = diskimage.connection_type
            connection_port = diskimage.connection_port

        else:
            # launch using unmanaged cloud image
            config_drive = self.label.cloud_image.config_drive

            image_external = self.label.cloud_image.external
            image_id = self.label.cloud_image.name
            image_name = self.label.cloud_image.name
            username = self.label.cloud_image.username
            connection_type = self.label.cloud_image.connection_type
            connection_port = self.label.cloud_image.connection_port

        hostname = self.provider_config.hostname_format.format(
            label=self.label, provider=self.provider_config, node=self.node
        )

        self.log.info("Creating server with hostname %s in %s from image %s "
                      "for node id: %s" % (hostname,
                                           self.provider_config.name,
                                           image_name,
                                           self.node.id))

        # NOTE: We store the node ID in the server metadata to use for leaked
        # instance detection. We cannot use the external server ID for this
        # because that isn't available in ZooKeeper until after the server is
        # active, which could cause a race in leak detection.

        server = self.handler.manager.createServer(
            hostname,
            image=image_external,
            min_ram=self.label.min_ram,
            flavor_name=self.label.flavor_name,
            key_name=self.label.key_name,
            az=self.node.az,
            config_drive=config_drive,
            nodepool_node_id=self.node.id,
            nodepool_node_label=self.node.type[0],
            nodepool_image_name=image_name,
            networks=self.pool.networks,
            security_groups=self.pool.security_groups,
            boot_from_volume=self.label.boot_from_volume,
            volume_size=self.label.volume_size)

        self.node.external_id = server.id
        self.node.hostname = hostname
        self.node.image_id = image_id
        if username:
            self.node.username = username
        self.node.connection_type = connection_type
        self.node.connection_port = connection_port

        # Checkpoint save the updated node info
        self.zk.storeNode(self.node)

        self.log.debug("Waiting for server %s for node id: %s" %
                       (server.id, self.node.id))
        server = self.handler.manager.waitForServer(
            server, self.provider_config.launch_timeout,
            auto_ip=self.pool.auto_floating_ip)

        if server.status != 'ACTIVE':
            raise exceptions.LaunchStatusException("Server %s for node id: %s "
                                                   "status: %s" %
                                                   (server.id, self.node.id,
                                                    server.status))

        # If we didn't specify an AZ, set it to the one chosen by Nova.
        # Do this after we are done waiting since AZ may not be available
        # immediately after the create request.
        if not self.node.az:
            self.node.az = server.location.zone

        # Use private_ipv4 on clouds where no public IP is configured.
        if self.pool.use_private_ip:
            interface_ip = server.private_ipv4
            interface_type = 'private'
        else:
            interface_ip = server.interface_ip
            interface_type = 'public'

        if not interface_ip:
            self.log.debug(
                "Server data for failed IP: %s" % pprint.pformat(
                    server))
            raise exceptions.LaunchNetworkException(
                "Unable to find %s IP of server" % (interface_type))

        self.node.interface_ip = interface_ip
        self.node.public_ipv4 = server.public_v4
        self.node.public_ipv6 = server.public_v6
        self.node.private_ipv4 = server.private_v4
        # devstack-gate multi-node depends on private_v4 being populated
        # with something. On clouds that don't have a private address, use
        # the public.
        if not self.node.private_ipv4:
            self.node.private_ipv4 = server.public_v4

        # Checkpoint save the updated node info
        self.zk.storeNode(self.node)

        self.log.debug(
            "Node %s is running [region: %s, az: %s, ip: %s ipv4: %s, "
            "ipv6: %s]" %
            (self.node.id, self.node.region, self.node.az,
             self.node.interface_ip, self.node.public_ipv4,
             self.node.public_ipv6))

        # wait and scan the new node and record in ZooKeeper
        host_keys = []
        if self.pool.host_key_checking:
            try:
                self.log.debug(
                    "Gathering host keys for node %s", self.node.id)
                # only gather host keys if the connection type is ssh
                gather_host_keys = connection_type == 'ssh'
                host_keys = utils.nodescan(
                    interface_ip,
                    timeout=self.provider_config.boot_timeout,
                    gather_hostkeys=gather_host_keys,
                    port=connection_port)

                if gather_host_keys and not host_keys:
                    raise exceptions.LaunchKeyscanException(
                        "Unable to gather host keys")
            except exceptions.ConnectionTimeoutException:
                self._logConsole(self.node.external_id, self.node.hostname)
                raise

        self.node.host_keys = host_keys
        self.zk.storeNode(self.node)
Exemple #2
0
    def launch(self):
        self.log.debug("Starting %s instance" % self.node.type)
        attempts = 1
        while attempts <= self.retries:
            try:
                instance = self.handler.manager.createInstance(self.label)
                break
            except Exception:
                if attempts <= self.retries:
                    self.log.exception(
                        "Launch attempt %d/%d failed for node %s:", attempts,
                        self.retries, self.node.id)
                if attempts == self.retries:
                    raise
                attempts += 1
            time.sleep(1)

        instance_id = instance.id
        self.node.external_id = instance_id
        self.zk.storeNode(self.node)

        boot_start = time.monotonic()
        while time.monotonic() - boot_start < self.boot_timeout:
            state = instance.state.get('Name')
            self.log.debug("Instance %s is %s" % (instance_id, state))
            if state == 'running':
                instance.create_tags(Tags=[{
                    'Key': 'nodepool_id',
                    'Value': str(self.node.id)
                }])
                instance.create_tags(Tags=[{
                    'Key': 'nodepool_pool',
                    'Value': str(self.pool.name)
                }])
                instance.create_tags(Tags=[{
                    'Key': 'nodepool_provider',
                    'Value': str(self.provider_name)
                }])
                break
            time.sleep(0.5)
            instance.reload()
        if state != 'running':
            raise exceptions.LaunchStatusException(
                "Instance %s failed to start: %s" % (instance_id, state))

        server_ip = instance.public_ip_address
        if not server_ip:
            raise exceptions.LaunchStatusException(
                "Instance %s doesn't have a public ip" % instance_id)

        self.node.connection_port = self.label.cloud_image.connection_port
        self.node.connection_type = self.label.cloud_image.connection_type
        if self.pool.host_key_checking:
            try:
                if (self.node.connection_type == 'ssh'
                        or self.node.connection_type == 'network_cli'):
                    gather_hostkeys = True
                else:
                    gather_hostkeys = False
                keys = nodescan(server_ip,
                                port=self.node.connection_port,
                                timeout=180,
                                gather_hostkeys=gather_hostkeys)
            except Exception:
                raise exceptions.LaunchKeyscanException(
                    "Can't scan instance %s key" % instance_id)

        self.log.info("Instance %s ready" % instance_id)
        self.node.state = zk.READY
        self.node.external_id = instance_id
        self.node.hostname = server_ip
        self.node.interface_ip = server_ip
        self.node.public_ipv4 = server_ip
        self.node.host_keys = keys
        self.node.username = self.label.cloud_image.username
        self.node.python_path = self.label.cloud_image.python_path
        self.zk.storeNode(self.node)
        self.log.info("Instance %s is ready", instance_id)