예제 #1
0
def _get_configdrive(configdrive, node_uuid, tempdir=None):
    """Get the information about size and location of the configdrive.

    :param configdrive: Base64 encoded Gzipped configdrive content or
        configdrive HTTP URL.
    :param node_uuid: Node's uuid. Used for logging.
    :param tempdir: temporary directory for the temporary configdrive file
    :raises: InstanceDeployFailure if it can't download or decode the
       config drive.
    :returns: A tuple with the size in MiB and path to the uncompressed
        configdrive file.

    """
    # Check if the configdrive option is a HTTP URL or the content directly
    is_url = utils.is_http_url(configdrive)
    if is_url:
        try:
            data = requests.get(configdrive).content
        except requests.exceptions.RequestException as e:
            raise exception.InstanceDeployFailure(
                _("Can't download the configdrive content for node %(node)s "
                  "from '%(url)s'. Reason: %(reason)s") %
                {'node': node_uuid, 'url': configdrive, 'reason': e})
    else:
        data = configdrive

    try:
        data = six.BytesIO(base64.b64decode(data))
    except TypeError:
        error_msg = (_('Config drive for node %s is not base64 encoded '
                       'or the content is malformed.') % node_uuid)
        if is_url:
            error_msg += _(' Downloaded from "%s".') % configdrive
        raise exception.InstanceDeployFailure(error_msg)

    configdrive_file = tempfile.NamedTemporaryFile(delete=False,
                                                   prefix='configdrive',
                                                   dir=tempdir)
    configdrive_mb = 0
    with gzip.GzipFile('configdrive', 'rb', fileobj=data) as gunzipped:
        try:
            shutil.copyfileobj(gunzipped, configdrive_file)
        except EnvironmentError as e:
            # Delete the created file
            utils.unlink_without_raise(configdrive_file.name)
            raise exception.InstanceDeployFailure(
                _('Encountered error while decompressing and writing '
                  'config drive for node %(node)s. Error: %(exc)s') %
                {'node': node_uuid, 'exc': e})
        else:
            # Get the file size and convert to MiB
            configdrive_file.seek(0, os.SEEK_END)
            bytes_ = configdrive_file.tell()
            configdrive_mb = int(math.ceil(float(bytes_) / units.Mi))
        finally:
            configdrive_file.close()

        return (configdrive_mb, configdrive_file.name)
예제 #2
0
def _get_configdrive(configdrive, node_uuid, tempdir=None):
    """Get the information about size and location of the configdrive.

    :param configdrive: Base64 encoded Gzipped configdrive content or
        configdrive HTTP URL.
    :param node_uuid: Node's uuid. Used for logging.
    :param tempdir: temporary directory for the temporary configdrive file
    :raises: InstanceDeployFailure if it can't download or decode the
       config drive.
    :returns: A tuple with the size in MiB and path to the uncompressed
        configdrive file.

    """
    # Check if the configdrive option is a HTTP URL or the content directly
    is_url = utils.is_http_url(configdrive)
    if is_url:
        try:
            data = requests.get(configdrive).content
        except requests.exceptions.RequestException as e:
            raise exception.InstanceDeployFailure(
                _("Can't download the configdrive content for node %(node)s "
                  "from '%(url)s'. Reason: %(reason)s") %
                {'node': node_uuid, 'url': configdrive, 'reason': e})
    else:
        data = configdrive

    try:
        data = six.BytesIO(base64.decode_as_bytes(data))
    except TypeError:
        error_msg = (_('Config drive for node %s is not base64 encoded '
                       'or the content is malformed.') % node_uuid)
        if is_url:
            error_msg += _(' Downloaded from "%s".') % configdrive
        raise exception.InstanceDeployFailure(error_msg)

    configdrive_file = tempfile.NamedTemporaryFile(delete=False,
                                                   prefix='configdrive',
                                                   dir=tempdir)
    configdrive_mb = 0
    with gzip.GzipFile('configdrive', 'rb', fileobj=data) as gunzipped:
        try:
            shutil.copyfileobj(gunzipped, configdrive_file)
        except EnvironmentError as e:
            # Delete the created file
            utils.unlink_without_raise(configdrive_file.name)
            raise exception.InstanceDeployFailure(
                _('Encountered error while decompressing and writing '
                  'config drive for node %(node)s. Error: %(exc)s') %
                {'node': node_uuid, 'exc': e})
        else:
            # Get the file size and convert to MiB
            configdrive_file.seek(0, os.SEEK_END)
            bytes_ = configdrive_file.tell()
            configdrive_mb = int(math.ceil(float(bytes_) / units.Mi))
        finally:
            configdrive_file.close()

        return (configdrive_mb, configdrive_file.name)
 def test_is_http_url(self):
     self.assertTrue(utils.is_http_url('http://127.0.0.1'))
     self.assertTrue(utils.is_http_url('https://127.0.0.1'))
     self.assertTrue(utils.is_http_url('HTTP://127.1.2.3'))
     self.assertTrue(utils.is_http_url('HTTPS://127.3.2.1'))
     self.assertFalse(utils.is_http_url('Zm9vYmFy'))
     self.assertFalse(utils.is_http_url('11111111'))
예제 #4
0
 def test_is_http_url(self):
     self.assertTrue(utils.is_http_url("http://127.0.0.1"))
     self.assertTrue(utils.is_http_url("https://127.0.0.1"))
     self.assertTrue(utils.is_http_url("HTTP://127.1.2.3"))
     self.assertTrue(utils.is_http_url("HTTPS://127.3.2.1"))
     self.assertFalse(utils.is_http_url("Zm9vYmFy"))
     self.assertFalse(utils.is_http_url("11111111"))
예제 #5
0
 def test_is_http_url(self):
     self.assertTrue(utils.is_http_url('http://127.0.0.1'))
     self.assertTrue(utils.is_http_url('https://127.0.0.1'))
     self.assertTrue(utils.is_http_url('HTTP://127.1.2.3'))
     self.assertTrue(utils.is_http_url('HTTPS://127.3.2.1'))
     self.assertFalse(utils.is_http_url('Zm9vYmFy'))
     self.assertFalse(utils.is_http_url('11111111'))
def get_configdrive(configdrive, node_uuid, tempdir=None):
    """Get the information about size and location of the configdrive.

    :param configdrive: Base64 encoded Gzipped configdrive content or
        configdrive HTTP URL.
    :param node_uuid: Node's uuid. Used for logging.
    :param tempdir: temporary directory for the temporary configdrive file
    :raises: InstanceDeployFailure if it can't download or decode the
       config drive.
    :returns: A tuple with the size in MiB and path to the uncompressed
        configdrive file.

    """
    # Check if the configdrive option is a HTTP URL or the content directly
    is_url = utils.is_http_url(configdrive)
    if is_url:
        verify, cert = ipa_utils.get_ssl_client_options(CONF)
        timeout = CONF.image_download_connection_timeout
        # TODO(dtantsur): support proxy parameters from instance_info
        try:
            resp = requests.get(configdrive, verify=verify, cert=cert,
                                timeout=timeout)
        except requests.exceptions.RequestException as e:
            raise exception.InstanceDeployFailure(
                "Can't download the configdrive content for node %(node)s "
                "from '%(url)s'. Reason: %(reason)s" %
                {'node': node_uuid, 'url': configdrive, 'reason': e})

        if resp.status_code >= 400:
            raise exception.InstanceDeployFailure(
                "Can't download the configdrive content for node %(node)s "
                "from '%(url)s'. Got status code %(code)s, response "
                "body %(body)s" %
                {'node': node_uuid, 'url': configdrive,
                 'code': resp.status_code, 'body': resp.text})

        data = resp.content
    else:
        data = configdrive

    configdrive_file = tempfile.NamedTemporaryFile(delete=False,
                                                   prefix='configdrive',
                                                   dir=tempdir)

    try:
        data = io.BytesIO(base64.b64decode(data))
    except Exception as exc:
        if isinstance(data, bytes):
            LOG.debug('Config drive for node %(node)s is not base64 encoded '
                      '(%(error)s), assuming binary',
                      {'node': node_uuid, 'error': exc})
            configdrive_mb = int(math.ceil(len(data) / units.Mi))
            configdrive_file.write(data)
            configdrive_file.close()
            return (configdrive_mb, configdrive_file.name)
        else:
            configdrive_file.close()
            utils.unlink_without_raise(configdrive_file.name)

            error_msg = ('Config drive for node %(node)s is not base64 '
                         'encoded or the content is malformed. '
                         '%(cls)s: %(err)s.'
                         % {'node': node_uuid, 'err': exc,
                            'cls': type(exc).__name__})
            if is_url:
                error_msg += ' Downloaded from "%s".' % configdrive
            raise exception.InstanceDeployFailure(error_msg)

    configdrive_mb = 0
    with gzip.GzipFile('configdrive', 'rb', fileobj=data) as gunzipped:
        try:
            shutil.copyfileobj(gunzipped, configdrive_file)
        except EnvironmentError as e:
            # Delete the created file
            utils.unlink_without_raise(configdrive_file.name)
            raise exception.InstanceDeployFailure(
                'Encountered error while decompressing and writing '
                'config drive for node %(node)s. Error: %(exc)s' %
                {'node': node_uuid, 'exc': e})
        else:
            # Get the file size and convert to MiB
            configdrive_file.seek(0, os.SEEK_END)
            bytes_ = configdrive_file.tell()
            configdrive_mb = int(math.ceil(float(bytes_) / units.Mi))
        finally:
            configdrive_file.close()

        return (configdrive_mb, configdrive_file.name)