예제 #1
0
    def _decrypt_image(self, context, encrypted_filename, encrypted_key,
                       encrypted_iv, decrypted_filename):
        elevated = context.elevated()
        try:
            key = self.cert_rpcapi.decrypt_text(elevated,
                    project_id=context.project_id,
                    text=base64.b64encode(encrypted_key))
        except Exception as exc:
            msg = _('Failed to decrypt private key: %s') % exc
            raise exception.NovaException(msg)
        try:
            iv = self.cert_rpcapi.decrypt_text(elevated,
                    project_id=context.project_id,
                    text=base64.b64encode(encrypted_iv))
        except Exception as exc:
            raise exception.NovaException(_('Failed to decrypt initialization '
                                    'vector: %s') % exc)

        try:
            utils.execute('openssl', 'enc',
                          '-d', '-aes-128-cbc',
                          '-in', '%s' % (encrypted_filename,),
                          '-K', '%s' % (key,),
                          '-iv', '%s' % (iv,),
                          '-out', '%s' % (decrypted_filename,))
        except processutils.ProcessExecutionError as exc:
            raise exception.NovaException(_('Failed to decrypt image file '
                                    '%(image_file)s: %(err)s') %
                                    {'image_file': encrypted_filename,
                                     'err': exc.stdout})
예제 #2
0
파일: utils.py 프로젝트: bopopescu/jacket
def create_shadow_table(migrate_engine,
                        table_name=None,
                        table=None,
                        **col_name_col_instance):
    """This method create shadow table for table with name ``table_name``
    or table instance ``table``.
    :param table_name: Autoload table with this name and create shadow table
    :param table: Autoloaded table, so just create corresponding shadow table.
    :param col_name_col_instance:   contains pair column_name=column_instance.
    column_instance is instance of Column. These params are required only for
    columns that have unsupported types by sqlite. For example BigInteger.
    :returns: The created shadow_table object.
    """
    meta = MetaData(bind=migrate_engine)

    if table_name is None and table is None:
        raise exception.NovaException(
            _("Specify `table_name` or `table` "
              "param"))
    if not (table_name is None or table is None):
        raise exception.NovaException(
            _("Specify only one param `table_name` "
              "`table`"))

    if table is None:
        table = Table(table_name, meta, autoload=True)

    columns = []
    for column in table.columns:
        if isinstance(column.type, NullType):
            new_column = oslodbutils._get_not_supported_column(
                col_name_col_instance, column.name)
            columns.append(new_column)
        else:
            columns.append(column.copy())

    shadow_table_name = db._SHADOW_TABLE_PREFIX + table.name
    shadow_table = Table(shadow_table_name,
                         meta,
                         *columns,
                         mysql_engine='InnoDB')
    try:
        shadow_table.create()
        return shadow_table
    except (db_exc.DBError, OperationalError):
        # NOTE(ekudryashova): At the moment there is a case in oslo.db code,
        # which raises unwrapped OperationalError, so we should catch it until
        # oslo.db would wraps all such exceptions
        LOG.info(repr(shadow_table))
        LOG.exception(_LE('Exception while creating table.'))
        raise exception.ShadowTableExists(name=shadow_table_name)
    except Exception:
        LOG.info(repr(shadow_table))
        LOG.exception(_LE('Exception while creating table.'))
예제 #3
0
def get_my_linklocal(interface):
    try:
        if_str = execute('ip', '-f', 'inet6', '-o', 'addr', 'show', interface)
        condition = '\s+inet6\s+([0-9a-f:]+)/\d+\s+scope\s+link'
        links = [re.search(condition, x) for x in if_str[0].split('\n')]
        address = [w.group(1) for w in links if w is not None]
        if address[0] is not None:
            return address[0]
        else:
            msg = _('Link Local address is not found.:%s') % if_str
            raise exception.NovaException(msg)
    except Exception as ex:
        msg = _("Couldn't get Link Local IP of %(interface)s"
                " :%(ex)s") % {'interface': interface, 'ex': ex}
        raise exception.NovaException(msg)
예제 #4
0
파일: rpcapi.py 프로젝트: bopopescu/jacket
def _compute_host(host, instance):
    '''Get the destination host for a message.

    :param host: explicit host to send the message to.
    :param instance: If an explicit host was not specified, use
                     instance['host']

    :returns: A host
    '''
    if host:
        return host
    if not instance:
        raise exception.NovaException(_('No compute host specified'))
    if not instance.host:
        raise exception.NovaException(_('Unable to find host for '
                                        'Instance %s') % instance.uuid)
    return instance.host
예제 #5
0
 def _test_for_malicious_tarball(path, filename):
     """Raises exception if extracting tarball would escape extract path."""
     tar_file = tarfile.open(filename, 'r|gz')
     for n in tar_file.getnames():
         if not os.path.abspath(os.path.join(path, n)).startswith(path):
             tar_file.close()
             raise exception.NovaException(_('Unsafe filenames in image'))
     tar_file.close()
예제 #6
0
파일: utils.py 프로젝트: bopopescu/jacket
def check_shadow_table(migrate_engine, table_name):
    """This method checks that table with ``table_name`` and
    corresponding shadow table have same columns.
    """
    meta = MetaData()
    meta.bind = migrate_engine

    table = Table(table_name, meta, autoload=True)
    shadow_table = Table(db._SHADOW_TABLE_PREFIX + table_name,
                         meta,
                         autoload=True)

    columns = {c.name: c for c in table.columns}
    shadow_columns = {c.name: c for c in shadow_table.columns}

    for name, column in columns.items():
        if name not in shadow_columns:
            raise exception.NovaException(
                _("Missing column %(table)s.%(column)s in shadow table") % {
                    'column': name,
                    'table': shadow_table.name
                })
        shadow_column = shadow_columns[name]

        if not isinstance(shadow_column.type, type(column.type)):
            raise exception.NovaException(
                _("Different types in %(table)s.%(column)s and shadow table: "
                  "%(c_type)s %(shadow_c_type)s") % {
                      'column': name,
                      'table': table.name,
                      'c_type': column.type,
                      'shadow_c_type': shadow_column.type
                  })

    for name, column in shadow_columns.items():
        if name not in columns:
            raise exception.NovaException(
                _("Extra column %(table)s.%(column)s in shadow table") % {
                    'column': name,
                    'table': shadow_table.name
                })
    return True
예제 #7
0
    def register_extension(self, ext):
        if not self._check_extension(ext):
            return False

        alias = ext.alias

        if alias in self.extensions:
            raise exception.NovaException("Found duplicate extension: %s" %
                                          alias)
        self.extensions[alias] = ext
        return True
예제 #8
0
    def register(self, ext):
        # Do nothing if the extension doesn't check out
        if not self._check_extension(ext):
            return

        alias = ext.alias
        if alias in self.extensions:
            raise exception.NovaException("Found duplicate extension: %s"
                                          % alias)
        self.extensions[alias] = ext
        self.sorted_ext_list = None
예제 #9
0
파일: manager.py 프로젝트: bopopescu/jacket
    def _get_resource_tracker(self, nodename):
        rt = self._resource_tracker_dict.get(nodename)
        if not rt:
            if not self.driver.node_is_available(nodename):
                raise exception.NovaException(
                    _("%s is not a valid node managed by this "
                      "compute host.") % nodename)

            rt = resource_tracker.ResourceTracker(self.host, self.driver,
                                                  nodename)
            self._resource_tracker_dict[nodename] = rt
        return rt
예제 #10
0
    def call(self, method, *args, **kwargs):
        """Call an Ironic client method and retry on errors.

        :param method: Name of the client method to call as a string.
        :param args: Client method arguments.
        :param kwargs: Client method keyword arguments.
        :param retry_on_conflict: Boolean value. Whether the request should be
                                  retried in case of a conflict error
                                  (HTTP 409) or not. If retry_on_conflict is
                                  False the cached instance of the client
                                  won't be used. Defaults to True.
        :raises: NovaException if all retries failed.
        """
        # TODO(dtantsur): drop these once ironicclient 0.8.0 is out and used in
        # global-requirements.
        retry_excs = (ironic.exc.ServiceUnavailable,
                      ironic.exc.ConnectionRefused)
        retry_on_conflict = kwargs.pop('retry_on_conflict', True)

        # num_attempts should be the times of retry + 1
        # eg. retry==0 just means  run once and no retry
        num_attempts = max(0, CONF.ironic.api_max_retries) + 1

        for attempt in range(1, num_attempts + 1):
            client = self._get_client(retry_on_conflict=retry_on_conflict)

            try:
                return self._multi_getattr(client, method)(*args, **kwargs)
            except ironic.exc.Unauthorized:
                # In this case, the authorization token of the cached
                # ironic-client probably expired. So invalidate the cached
                # client and the next try will start with a fresh one.
                self._invalidate_cached_client()
                LOG.debug("The Ironic client became unauthorized. "
                          "Will attempt to reauthorize and try again.")
            except retry_excs:
                pass

            # We want to perform this logic for all exception cases listed
            # above.
            msg = (_("Error contacting Ironic server for "
                     "'%(method)s'. Attempt %(attempt)d of %(total)d") % {
                         'method': method,
                         'attempt': attempt,
                         'total': num_attempts
                     })
            if attempt == num_attempts:
                LOG.error(msg)
                raise exception.NovaException(msg)
            LOG.warning(msg)
            time.sleep(CONF.ironic.api_retry_interval)
예제 #11
0
def db_sync(version=None, database='main'):
    if version is not None:
        try:
            version = int(version)
        except ValueError:
            raise exception.NovaException(_("version should be an integer"))

    current_version = db_version(database)
    repository = _find_migrate_repo(database)
    if version is None or version > current_version:
        return versioning_api.upgrade(get_engine(database), repository,
                version)
    else:
        return versioning_api.downgrade(get_engine(database), repository,
                version)
예제 #12
0
def db_version(database='main'):
    repository = _find_migrate_repo(database)
    try:
        return versioning_api.db_version(get_engine(database), repository)
    except versioning_exceptions.DatabaseNotControlledError as exc:
        meta = sqlalchemy.MetaData()
        engine = get_engine(database)
        meta.reflect(bind=engine)
        tables = meta.tables
        if len(tables) == 0:
            db_version_control(INIT_VERSION[database], database)
            return versioning_api.db_version(get_engine(database), repository)
        else:
            LOG.exception(exc)
            # Some pre-Essex DB's may not be version controlled.
            # Require them to upgrade using Essex first.
            raise exception.NovaException(
                _("Upgrade DB using Essex release first."))
예제 #13
0
    def _get_client(self, retry_on_conflict=True):
        max_retries = CONF.ironic.api_max_retries if retry_on_conflict else 1
        retry_interval = (CONF.ironic.api_retry_interval
                          if retry_on_conflict else 0)

        # If we've already constructed a valid, authed client, just return
        # that.
        if retry_on_conflict and self._cached_client is not None:
            return self._cached_client

        auth_token = CONF.ironic.admin_auth_token
        if auth_token is None:
            kwargs = {
                'os_username': CONF.ironic.admin_username,
                'os_password': CONF.ironic.admin_password,
                'os_auth_url': CONF.ironic.admin_url,
                'os_tenant_name': CONF.ironic.admin_tenant_name,
                'os_service_type': 'baremetal',
                'os_endpoint_type': 'public',
                'ironic_url': CONF.ironic.api_endpoint
            }
        else:
            kwargs = {
                'os_auth_token': auth_token,
                'ironic_url': CONF.ironic.api_endpoint
            }

        # Retries for Conflict exception
        kwargs['max_retries'] = max_retries
        kwargs['retry_interval'] = retry_interval
        kwargs['os_ironic_api_version'] = '%d.%d' % IRONIC_API_VERSION
        try:
            cli = ironic.client.get_client(IRONIC_API_VERSION[0], **kwargs)
            # Cache the client so we don't have to reconstruct and
            # reauthenticate it every time we need it.
            if retry_on_conflict:
                self._cached_client = cli

        except ironic.exc.Unauthorized:
            msg = _("Unable to authenticate Ironic client.")
            LOG.error(msg)
            raise exception.NovaException(msg)

        return cli
예제 #14
0
    def new_websocket_client(self):
        """Called after a new WebSocket connection has been established."""
        # Reopen the eventlet hub to make sure we don't share an epoll
        # fd with parent and/or siblings, which would be bad
        from eventlet import hubs
        hubs.use_hub()

        # The compute expected behavior is to have token
        # passed to the method GET of the request
        parse = urlparse.urlparse(self.path)
        if parse.scheme not in ('http', 'https'):
            # From a bug in urlparse in Python < 2.7.4 we cannot support
            # special schemes (cf: http://bugs.python.org/issue9374)
            if sys.version_info < (2, 7, 4):
                raise exception.NovaException(
                    _("We do not support scheme '%s' under Python < 2.7.4, "
                      "please use http or https") % parse.scheme)

        query = parse.query
        token = urlparse.parse_qs(query).get("token", [""]).pop()
        if not token:
            # NoVNC uses it's own convention that forward token
            # from the request to a cookie header, we should check
            # also for this behavior
            hcookie = self.headers.getheader('cookie')
            if hcookie:
                cookie = Cookie.SimpleCookie()
                cookie.load(hcookie)
                if 'token' in cookie:
                    token = cookie['token'].value

        ctxt = context.get_admin_context()
        rpcapi = consoleauth_rpcapi.ConsoleAuthAPI()
        connect_info = rpcapi.check_token(ctxt, token=token)

        if not connect_info:
            raise exception.InvalidToken(token=token)

        # Verify Origin
        expected_origin_hostname = self.headers.getheader('Host')
        if ':' in expected_origin_hostname:
            e = expected_origin_hostname
            if '[' in e and ']' in e:
                expected_origin_hostname = e.split(']')[0][1:]
            else:
                expected_origin_hostname = e.split(':')[0]
        expected_origin_hostnames = CONF.console_allowed_origins
        expected_origin_hostnames.append(expected_origin_hostname)
        origin_url = self.headers.getheader('Origin')
        # missing origin header indicates non-browser client which is OK
        if origin_url is not None:
            origin = urlparse.urlparse(origin_url)
            origin_hostname = origin.hostname
            origin_scheme = origin.scheme
            if origin_hostname == '' or origin_scheme == '':
                detail = _("Origin header not valid.")
                raise exception.ValidationError(detail=detail)
            if origin_hostname not in expected_origin_hostnames:
                detail = _("Origin header does not match this host.")
                raise exception.ValidationError(detail=detail)
            if not self.verify_origin_proto(connect_info, origin_scheme):
                detail = _("Origin header protocol does not match this host.")
                raise exception.ValidationError(detail=detail)

        self.msg(_('connect info: %s'), str(connect_info))
        host = connect_info['host']
        port = int(connect_info['port'])

        # Connect to the target
        self.msg(
            _("connecting to: %(host)s:%(port)s") % {
                'host': host,
                'port': port
            })
        tsock = self.socket(host, port, connect=True)

        # Handshake as necessary
        if connect_info.get('internal_access_path'):
            tsock.send("CONNECT %s HTTP/1.1\r\n\r\n" %
                       connect_info['internal_access_path'])
            while True:
                data = tsock.recv(4096, socket.MSG_PEEK)
                if data.find("\r\n\r\n") != -1:
                    if data.split("\r\n")[0].find("200") == -1:
                        raise exception.InvalidConnectionInfo()
                    tsock.recv(len(data))
                    break

        # Start proxying
        try:
            self.do_proxy(tsock)
        except Exception:
            if tsock:
                tsock.shutdown(socket.SHUT_RDWR)
                tsock.close()
                self.vmsg(
                    _("%(host)s:%(port)s: Target closed") % {
                        'host': host,
                        'port': port
                    })
            raise