Beispiel #1
0
    def setUp(self):
        super(AuthWithTrust, self).setUp()
        self.opt_in_group('trust', enabled=True)

        trust.Manager()
        self.trust_controller = trust.controllers.TrustV3()
        self.auth_v3_controller = auth.controllers.Auth()
        self.trustor = self.user_foo
        self.trustee = self.user_two
        self.assigned_roles = [self.role_member['id'],
                               self.role_browser['id']]
        for assigned_role in self.assigned_roles:
            self.assignment_api.add_role_to_user_and_project(
                self.trustor['id'], self.tenant_bar['id'], assigned_role)

        self.sample_data = {'trustor_user_id': self.trustor['id'],
                            'trustee_user_id': self.trustee['id'],
                            'project_id': self.tenant_bar['id'],
                            'impersonation': True,
                            'roles': [{'id': self.role_browser['id']},
                                      {'name': self.role_member['name']}]}
        expires_at = timeutils.strtime(timeutils.utcnow() +
                                       datetime.timedelta(minutes=10),
                                       fmt=TIME_FORMAT)
        self.create_trust(expires_at=expires_at)
Beispiel #2
0
    def new_trust_ref(self, trustor_user_id, trustee_user_id, project_id=None,
                      impersonation=None, expires=None, role_ids=None,
                      role_names=None):
        ref = self.new_ref()

        ref['trustor_user_id'] = trustor_user_id
        ref['trustee_user_id'] = trustee_user_id
        ref['impersonation'] = impersonation or False
        ref['project_id'] = project_id

        if isinstance(expires, basestring):
            ref['expires_at'] = expires
        elif isinstance(expires, dict):
            ref['expires_at'] = timeutils.strtime(
                timeutils.utcnow() + datetime.timedelta(**expires),
                fmt=TIME_FORMAT)
        elif expires is None:
            pass
        else:
            raise NotImplementedError('Unexpected value for "expires"')

        role_ids = role_ids or []
        role_names = role_names or []
        if role_ids or role_names:
            ref['roles'] = []
            for role_id in role_ids:
                ref['roles'].append({'id': role_id})
            for role_name in role_names:
                ref['roles'].append({'name': role_name})

        return ref
Beispiel #3
0
 def format_token(cls, token_ref, roles_ref, catalog_ref=None):
     user_ref = token_ref["user"]
     metadata_ref = token_ref["metadata"]
     expires = token_ref["expires"]
     if expires is not None:
         if not isinstance(expires, unicode):
             expires = timeutils.isotime(expires)
     o = {
         "access": {
             "token": {"id": token_ref["id"], "expires": expires, "issued_at": timeutils.strtime()},
             "user": {
                 "id": user_ref["id"],
                 "name": user_ref["name"],
                 "username": user_ref["name"],
                 "roles": roles_ref,
                 "roles_links": metadata_ref.get("roles_links", []),
             },
         }
     }
     if "tenant" in token_ref and token_ref["tenant"]:
         token_ref["tenant"]["enabled"] = True
         o["access"]["token"]["tenant"] = token_ref["tenant"]
     if catalog_ref is not None:
         o["access"]["serviceCatalog"] = Auth.format_catalog(catalog_ref)
     if metadata_ref:
         if "is_admin" in metadata_ref:
             o["access"]["metadata"] = {"is_admin": metadata_ref["is_admin"]}
         else:
             o["access"]["metadata"] = {"is_admin": 0}
     if "roles" in metadata_ref:
         o["access"]["metadata"]["roles"] = metadata_ref["roles"]
     return o
Beispiel #4
0
    def setUp(self):
        super(AuthWithTrust, self).setUp()
        self.opt_in_group('trust', enabled=True)

        trust.Manager()
        self.trust_controller = trust.controllers.TrustV3()
        self.auth_v3_controller = auth.controllers.Auth()
        self.trustor = self.user_foo
        self.trustee = self.user_two
        self.assigned_roles = [self.role_member['id'], self.role_browser['id']]
        for assigned_role in self.assigned_roles:
            self.assignment_api.add_role_to_user_and_project(
                self.trustor['id'], self.tenant_bar['id'], assigned_role)

        self.sample_data = {
            'trustor_user_id':
            self.trustor['id'],
            'trustee_user_id':
            self.trustee['id'],
            'project_id':
            self.tenant_bar['id'],
            'impersonation':
            True,
            'roles': [{
                'id': self.role_browser['id']
            }, {
                'name': self.role_member['name']
            }]
        }
        expires_at = timeutils.strtime(timeutils.utcnow() +
                                       datetime.timedelta(minutes=10),
                                       fmt=TIME_FORMAT)
        self.create_trust(expires_at=expires_at)
Beispiel #5
0
    def new_trust_ref(self, trustor_user_id, trustee_user_id, project_id=None,
                      impersonation=None, expires=None, role_ids=None,
                      role_names=None, remaining_uses=None):
        ref = self.new_ref()

        ref['trustor_user_id'] = trustor_user_id
        ref['trustee_user_id'] = trustee_user_id
        ref['impersonation'] = impersonation or False
        ref['project_id'] = project_id
        ref['remaining_uses'] = remaining_uses

        if isinstance(expires, six.string_types):
            ref['expires_at'] = expires
        elif isinstance(expires, dict):
            ref['expires_at'] = timeutils.strtime(
                timeutils.utcnow() + datetime.timedelta(**expires),
                fmt=TIME_FORMAT)
        elif expires is None:
            pass
        else:
            raise NotImplementedError('Unexpected value for "expires"')

        role_ids = role_ids or []
        role_names = role_names or []
        if role_ids or role_names:
            ref['roles'] = []
            for role_id in role_ids:
                ref['roles'].append({'id': role_id})
            for role_name in role_names:
                ref['roles'].append({'name': role_name})

        return ref
Beispiel #6
0
 def format_token(cls, token_ref, roles_ref, catalog_ref=None):
     user_ref = token_ref['user']
     metadata_ref = token_ref['metadata']
     expires = token_ref['expires']
     if expires is not None:
         if not isinstance(expires, unicode):
             expires = timeutils.isotime(expires)
     o = {'access': {'token': {'id': token_ref['id'],
                               'expires': expires,
                               'issued_at': timeutils.strtime()
                               },
                     'user': {'id': user_ref['id'],
                              'name': user_ref['name'],
                              'username': user_ref['name'],
                              'roles': roles_ref,
                              'roles_links': metadata_ref.get('roles_links',
                                                              [])
                              }
                     }
          }
     if 'tenant' in token_ref and token_ref['tenant']:
         token_ref['tenant']['enabled'] = True
         o['access']['token']['tenant'] = token_ref['tenant']
     if catalog_ref is not None:
         o['access']['serviceCatalog'] = Auth.format_catalog(catalog_ref)
     if metadata_ref:
         if 'is_admin' in metadata_ref:
             o['access']['metadata'] = {'is_admin':
                                        metadata_ref['is_admin']}
         else:
             o['access']['metadata'] = {'is_admin': 0}
     if 'roles' in metadata_ref:
             o['access']['metadata']['roles'] = metadata_ref['roles']
     return o
 def _populate_token(self, token_data, expires=None):
     if not expires:
         expires = token_module.default_expire_time()
     if not isinstance(expires, unicode):
         expires = timeutils.isotime(expires)
     token_data['expires'] = expires
     token_data['issued_at'] = timeutils.strtime()
Beispiel #8
0
 def format_token(cls, token_ref, roles_ref=None, catalog_ref=None):
     user_ref = token_ref['user']
     metadata_ref = token_ref['metadata']
     if roles_ref is None:
         roles_ref = []
     expires = token_ref.get('expires', token.default_expire_time())
     if expires is not None:
         if not isinstance(expires, unicode):
             expires = timeutils.isotime(expires)
     o = {
         'access': {
             'token': {
                 'id': token_ref['id'],
                 'expires': expires,
                 'issued_at': timeutils.strtime()
             },
             'user': {
                 'id': user_ref['id'],
                 'name': user_ref['name'],
                 'username': user_ref['name'],
                 'roles': roles_ref,
                 'roles_links': metadata_ref.get('roles_links', [])
             }
         }
     }
     if 'bind' in token_ref:
         o['access']['token']['bind'] = token_ref['bind']
     if 'tenant' in token_ref and token_ref['tenant']:
         token_ref['tenant']['enabled'] = True
         o['access']['token']['tenant'] = token_ref['tenant']
     if catalog_ref is not None:
         o['access']['serviceCatalog'] = V2TokenDataHelper.format_catalog(
             catalog_ref)
     if metadata_ref:
         if 'is_admin' in metadata_ref:
             o['access']['metadata'] = {
                 'is_admin': metadata_ref['is_admin']
             }
         else:
             o['access']['metadata'] = {'is_admin': 0}
     if 'roles' in metadata_ref:
         o['access']['metadata']['roles'] = metadata_ref['roles']
     if CONF.trust.enabled and 'trust_id' in metadata_ref:
         o['access']['trust'] = {
             'trustee_user_id': metadata_ref['trustee_user_id'],
             'id': metadata_ref['trust_id']
         }
     return o
Beispiel #9
0
    def format_token(cls, token_ref, roles_ref=None, catalog_ref=None):
        user_ref = token_ref['user']
        metadata_ref = token_ref['metadata']
        if roles_ref is None:
            roles_ref = []
        expires = token_ref.get('expires', token.default_expire_time())
        if expires is not None:
            if not isinstance(expires, six.text_type):
                expires = timeutils.isotime(expires)
        o = {'access': {'token': {'id': token_ref['id'],
                                  'expires': expires,
                                  'issued_at': timeutils.strtime()
                                  },
                        'user': {'id': user_ref['id'],
                                 'name': user_ref['name'],
                                 'username': user_ref['name'],
                                 'roles': roles_ref,
                                 'roles_links': metadata_ref.get('roles_links',
                                                                 [])
                                 }
                        }
             }
        if 'bind' in token_ref:
            o['access']['token']['bind'] = token_ref['bind']
        if 'tenant' in token_ref and token_ref['tenant']:
            token_ref['tenant']['enabled'] = True
            o['access']['token']['tenant'] = token_ref['tenant']
        if catalog_ref is not None:
            o['access']['serviceCatalog'] = V2TokenDataHelper.format_catalog(
                catalog_ref)
        if metadata_ref:
            if 'is_admin' in metadata_ref:
                o['access']['metadata'] = {'is_admin':
                                           metadata_ref['is_admin']}
            else:
                o['access']['metadata'] = {'is_admin': 0}
        if 'roles' in metadata_ref:
            o['access']['metadata']['roles'] = metadata_ref['roles']
        if CONF.trust.enabled and 'trust_id' in metadata_ref:
            o['access']['trust'] = {'trustee_user_id':
                                    metadata_ref['trustee_user_id'],
                                    'id': metadata_ref['trust_id']
                                    }
	# Kerberos 
	#o['access']['kerberos'] = token_ref['kerberos']

        return o
Beispiel #10
0
    def test_create_trust(self):
        expires_at = timeutils.strtime(timeutils.utcnow() +
                                       datetime.timedelta(minutes=10),
                                       fmt=TIME_FORMAT)
        new_trust = self.create_trust(self.sample_data, self.trustor['name'],
                                      expires_at=expires_at)
        self.assertEqual(self.trustor['id'], new_trust['trustor_user_id'])
        self.assertEqual(self.trustee['id'], new_trust['trustee_user_id'])
        role_ids = [self.role_browser['id'], self.role_member['id']]
        self.assertTrue(timeutils.parse_strtime(new_trust['expires_at'],
                                                fmt=TIME_FORMAT))
        self.assertIn('%s/v3/OS-TRUST/' % HOST_URL,
                      new_trust['links']['self'])
        self.assertIn('%s/v3/OS-TRUST/' % HOST_URL,
                      new_trust['roles_links']['self'])

        for role in new_trust['roles']:
            self.assertIn(role['id'], role_ids)
Beispiel #11
0
    def test_create_trust(self):
        expires_at = timeutils.strtime(timeutils.utcnow() +
                                       datetime.timedelta(minutes=10),
                                       fmt=TIME_FORMAT)
        new_trust = self.create_trust(self.sample_data,
                                      self.trustor['name'],
                                      expires_at=expires_at)
        self.assertEqual(self.trustor['id'], new_trust['trustor_user_id'])
        self.assertEqual(self.trustee['id'], new_trust['trustee_user_id'])
        role_ids = [self.role_browser['id'], self.role_member['id']]
        self.assertTrue(
            timeutils.parse_strtime(new_trust['expires_at'], fmt=TIME_FORMAT))
        self.assertIn('%s/v3/OS-TRUST/' % HOST_URL, new_trust['links']['self'])
        self.assertIn('%s/v3/OS-TRUST/' % HOST_URL,
                      new_trust['roles_links']['self'])

        for role in new_trust['roles']:
            self.assertIn(role['id'], role_ids)
Beispiel #12
0
    def setUp(self):
        super(AuthWithTrust, self).setUp()
        self.opt_in_group("trust", enabled=True)

        trust.Manager()
        self.trust_controller = trust.controllers.TrustV3()
        self.auth_v3_controller = auth.controllers.Auth()
        self.trustor = self.user_foo
        self.trustee = self.user_two
        self.assigned_roles = [self.role_member["id"], self.role_browser["id"]]
        for assigned_role in self.assigned_roles:
            self.assignment_api.add_role_to_user_and_project(self.trustor["id"], self.tenant_bar["id"], assigned_role)

        self.sample_data = {
            "trustor_user_id": self.trustor["id"],
            "trustee_user_id": self.trustee["id"],
            "project_id": self.tenant_bar["id"],
            "impersonation": True,
            "roles": [{"id": self.role_browser["id"]}, {"name": self.role_member["name"]}],
        }
        expires_at = timeutils.strtime(timeutils.utcnow() + datetime.timedelta(minutes=10), fmt=TIME_FORMAT)
        self.create_trust(expires_at=expires_at)
Beispiel #13
0
 def format_token(cls, token_ref, roles_ref=None, catalog_ref=None):
     user_ref = token_ref["user"]
     metadata_ref = token_ref["metadata"]
     if roles_ref is None:
         roles_ref = []
     expires = token_ref.get("expires", token.default_expire_time())
     if expires is not None:
         if not isinstance(expires, six.text_type):
             expires = timeutils.isotime(expires)
     o = {
         "access": {
             "token": {"id": token_ref["id"], "expires": expires, "issued_at": timeutils.strtime()},
             "user": {
                 "id": user_ref["id"],
                 "name": user_ref["name"],
                 "username": user_ref["name"],
                 "roles": roles_ref,
                 "roles_links": metadata_ref.get("roles_links", []),
             },
         }
     }
     if "bind" in token_ref:
         o["access"]["token"]["bind"] = token_ref["bind"]
     if "tenant" in token_ref and token_ref["tenant"]:
         token_ref["tenant"]["enabled"] = True
         o["access"]["token"]["tenant"] = token_ref["tenant"]
     if catalog_ref is not None:
         o["access"]["serviceCatalog"] = V2TokenDataHelper.format_catalog(catalog_ref)
     if metadata_ref:
         if "is_admin" in metadata_ref:
             o["access"]["metadata"] = {"is_admin": metadata_ref["is_admin"]}
         else:
             o["access"]["metadata"] = {"is_admin": 0}
     if "roles" in metadata_ref:
         o["access"]["metadata"]["roles"] = metadata_ref["roles"]
     if CONF.trust.enabled and "trust_id" in metadata_ref:
         o["access"]["trust"] = {"trustee_user_id": metadata_ref["trustee_user_id"], "id": metadata_ref["trust_id"]}
     return o
Beispiel #14
0
 def _format_token(self, token_ref, roles_ref, catalog_ref=None):
     user_ref = token_ref['user']
     metadata_ref = token_ref['metadata']
     expires = token_ref['expires']
     if expires is not None:
         if not isinstance(expires, unicode):
             expires = timeutils.isotime(expires)
     o = {
         'access': {
             'token': {
                 'id': token_ref['id'],
                 'expires': expires,
                 'issued_at': timeutils.strtime()
             },
             'user': {
                 'id': user_ref['id'],
                 'name': user_ref['name'],
                 'username': user_ref['name'],
                 'roles': roles_ref,
                 'roles_links': metadata_ref.get('roles_links', [])
             }
         }
     }
     if 'tenant' in token_ref and token_ref['tenant']:
         token_ref['tenant']['enabled'] = True
         o['access']['token']['tenant'] = token_ref['tenant']
     if catalog_ref is not None:
         o['access']['serviceCatalog'] = self._format_catalog(catalog_ref)
     if metadata_ref:
         if 'is_admin' in metadata_ref:
             o['access']['metadata'] = {
                 'is_admin': metadata_ref['is_admin']
             }
         else:
             o['access']['metadata'] = {'is_admin': 0}
     if 'roles' in metadata_ref:
         o['access']['metadata']['roles'] = metadata_ref['roles']
     return o
Beispiel #15
0
    def new_trust_ref(
        self,
        trustor_user_id,
        trustee_user_id,
        project_id=None,
        impersonation=None,
        expires=None,
        role_ids=None,
        role_names=None,
    ):
        ref = self.new_ref()

        ref["trustor_user_id"] = trustor_user_id
        ref["trustee_user_id"] = trustee_user_id
        ref["impersonation"] = impersonation or False
        ref["project_id"] = project_id

        if isinstance(expires, basestring):
            ref["expires_at"] = expires
        elif isinstance(expires, dict):
            ref["expires_at"] = timeutils.strtime(timeutils.utcnow() + datetime.timedelta(**expires), fmt=TIME_FORMAT)
        elif expires is None:
            pass
        else:
            raise NotImplementedError('Unexpected value for "expires"')

        role_ids = role_ids or []
        role_names = role_names or []
        if role_ids or role_names:
            ref["roles"] = []
            for role_id in role_ids:
                ref["roles"].append({"id": role_id})
            for role_name in role_names:
                ref["roles"].append({"name": role_name})

        return ref
Beispiel #16
0
def to_primitive(value, convert_instances=False, level=0):
    """Convert a complex object into primitives.

    Handy for JSON serialization. We can optionally handle instances,
    but since this is a recursive function, we could have cyclical
    data structures.

    To handle cyclical data structures we could track the actual objects
    visited in a set, but not all objects are hashable. Instead we just
    track the depth of the object inspections and don't go too deep.

    Therefore, convert_instances=True is lossy ... be aware.

    """
    nasty = [inspect.ismodule, inspect.isclass, inspect.ismethod,
             inspect.isfunction, inspect.isgeneratorfunction,
             inspect.isgenerator, inspect.istraceback, inspect.isframe,
             inspect.iscode, inspect.isbuiltin, inspect.isroutine,
             inspect.isabstract]
    for test in nasty:
        if test(value):
            return unicode(value)

    # value of itertools.count doesn't get caught by inspects
    # above and results in infinite loop when list(value) is called.
    if type(value) == itertools.count:
        return unicode(value)

    # FIXME(vish): Workaround for LP bug 852095. Without this workaround,
    #              tests that raise an exception in a mocked method that
    #              has a @wrap_exception with a notifier will fail. If
    #              we up the dependency to 0.5.4 (when it is released) we
    #              can remove this workaround.
    if getattr(value, '__module__', None) == 'mox':
        return 'mock'

    if level > 3:
        return '?'

    # The try block may not be necessary after the class check above,
    # but just in case ...
    try:
        # It's not clear why xmlrpclib created their own DateTime type, but
        # for our purposes, make it a datetime type which is explicitly
        # handled
        if isinstance(value, xmlrpclib.DateTime):
            value = datetime.datetime(*tuple(value.timetuple())[:6])

        if isinstance(value, (list, tuple)):
            o = []
            for v in value:
                o.append(to_primitive(v, convert_instances=convert_instances,
                                      level=level))
            return o
        elif isinstance(value, dict):
            o = {}
            for k, v in value.iteritems():
                o[k] = to_primitive(v, convert_instances=convert_instances,
                                    level=level)
            return o
        elif isinstance(value, datetime.datetime):
            return timeutils.strtime(value)
        elif hasattr(value, 'iteritems'):
            return to_primitive(dict(value.iteritems()),
                                convert_instances=convert_instances,
                                level=level + 1)
        elif hasattr(value, '__iter__'):
            return to_primitive(list(value),
                                convert_instances=convert_instances,
                                level=level)
        elif convert_instances and hasattr(value, '__dict__'):
            # Likely an instance of something. Watch for cycles.
            # Ignore class member vars.
            return to_primitive(value.__dict__,
                                convert_instances=convert_instances,
                                level=level + 1)
        else:
            return value
    except TypeError, e:
        # Class objects are tricky since they may define something like
        # __iter__ defined but it isn't callable as list().
        return unicode(value)
Beispiel #17
0
def to_primitive(value, convert_instances=False, convert_datetime=True,
                 level=0, max_depth=3):
    """Convert a complex object into primitives.

    Handy for JSON serialization. We can optionally handle instances,
    but since this is a recursive function, we could have cyclical
    data structures.

    To handle cyclical data structures we could track the actual objects
    visited in a set, but not all objects are hashable. Instead we just
    track the depth of the object inspections and don't go too deep.

    Therefore, convert_instances=True is lossy ... be aware.

    """
    # handle obvious types first - order of basic types determined by running
    # full tests on nova project, resulting in the following counts:
    # 572754 <type 'NoneType'>
    # 460353 <type 'int'>
    # 379632 <type 'unicode'>
    # 274610 <type 'str'>
    # 199918 <type 'dict'>
    # 114200 <type 'datetime.datetime'>
    #  51817 <type 'bool'>
    #  26164 <type 'list'>
    #   6491 <type 'float'>
    #    283 <type 'tuple'>
    #     19 <type 'long'>
    if isinstance(value, _simple_types):
        return value

    if isinstance(value, datetime.datetime):
        if convert_datetime:
            return timeutils.strtime(value)
        else:
            return value

    # value of itertools.count doesn't get caught by nasty_type_tests
    # and results in infinite loop when list(value) is called.
    if type(value) == itertools.count:
        return six.text_type(value)

    # FIXME(vish): Workaround for LP bug 852095. Without this workaround,
    #              tests that raise an exception in a mocked method that
    #              has a @wrap_exception with a notifier will fail. If
    #              we up the dependency to 0.5.4 (when it is released) we
    #              can remove this workaround.
    if getattr(value, '__module__', None) == 'mox':
        return 'mock'

    if level > max_depth:
        return '?'

    # The try block may not be necessary after the class check above,
    # but just in case ...
    try:
        recursive = functools.partial(to_primitive,
                                      convert_instances=convert_instances,
                                      convert_datetime=convert_datetime,
                                      level=level,
                                      max_depth=max_depth)
        if isinstance(value, dict):
            return dict((k, recursive(v)) for k, v in value.iteritems())
        elif isinstance(value, (list, tuple)):
            return [recursive(lv) for lv in value]

        # It's not clear why xmlrpclib created their own DateTime type, but
        # for our purposes, make it a datetime type which is explicitly
        # handled
        if isinstance(value, xmlrpclib.DateTime):
            value = datetime.datetime(*tuple(value.timetuple())[:6])

        if convert_datetime and isinstance(value, datetime.datetime):
            return timeutils.strtime(value)
        elif hasattr(value, 'iteritems'):
            return recursive(dict(value.iteritems()), level=level + 1)
        elif hasattr(value, '__iter__'):
            return recursive(list(value))
        elif convert_instances and hasattr(value, '__dict__'):
            # Likely an instance of something. Watch for cycles.
            # Ignore class member vars.
            return recursive(value.__dict__, level=level + 1)
        elif isinstance(value, netaddr.IPAddress):
            return six.text_type(value)
        else:
            if any(test(value) for test in _nasty_type_tests):
                return six.text_type(value)
            return value
    except TypeError:
        # Class objects are tricky since they may define something like
        # __iter__ defined but it isn't callable as list().
        return six.text_type(value)
Beispiel #18
0
def to_primitive(value, convert_instances=False, convert_datetime=True,
                 level=0, max_depth=3):
    """Convert a complex object into primitives.

    Handy for JSON serialization. We can optionally handle instances,
    but since this is a recursive function, we could have cyclical
    data structures.

    To handle cyclical data structures we could track the actual objects
    visited in a set, but not all objects are hashable. Instead we just
    track the depth of the object inspections and don't go too deep.

    Therefore, convert_instances=True is lossy ... be aware.

    """
    # handle obvious types first - order of basic types determined by running
    # full tests on nova project, resulting in the following counts:
    # 572754 <type 'NoneType'>
    # 460353 <type 'int'>
    # 379632 <type 'unicode'>
    # 274610 <type 'str'>
    # 199918 <type 'dict'>
    # 114200 <type 'datetime.datetime'>
    #  51817 <type 'bool'>
    #  26164 <type 'list'>
    #   6491 <type 'float'>
    #    283 <type 'tuple'>
    #     19 <type 'long'>
    if isinstance(value, _simple_types):
        return value

    if isinstance(value, datetime.datetime):
        if convert_datetime:
            return timeutils.strtime(value)
        else:
            return value

    # value of itertools.count doesn't get caught by nasty_type_tests
    # and results in infinite loop when list(value) is called.
    if type(value) == itertools.count:
        return six.text_type(value)

    # FIXME(vish): Workaround for LP bug 852095. Without this workaround,
    #              tests that raise an exception in a mocked method that
    #              has a @wrap_exception with a notifier will fail. If
    #              we up the dependency to 0.5.4 (when it is released) we
    #              can remove this workaround.
    if getattr(value, '__module__', None) == 'mox':
        return 'mock'

    if level > max_depth:
        return '?'

    # The try block may not be necessary after the class check above,
    # but just in case ...
    try:
        recursive = functools.partial(to_primitive,
                                      convert_instances=convert_instances,
                                      convert_datetime=convert_datetime,
                                      level=level,
                                      max_depth=max_depth)
        if isinstance(value, dict):
            return dict((k, recursive(v)) for k, v in value.iteritems())
        elif isinstance(value, (list, tuple)):
            return [recursive(lv) for lv in value]

        # It's not clear why xmlrpclib created their own DateTime type, but
        # for our purposes, make it a datetime type which is explicitly
        # handled
        if xmlrpclib and isinstance(value, xmlrpclib.DateTime):
            value = datetime.datetime(*tuple(value.timetuple())[:6])

        if convert_datetime and isinstance(value, datetime.datetime):
            return timeutils.strtime(value)
        elif isinstance(value, gettextutils.Message):
            return value.data
        elif hasattr(value, 'iteritems'):
            return recursive(dict(value.iteritems()), level=level + 1)
        elif hasattr(value, '__iter__'):
            return recursive(list(value))
        elif convert_instances and hasattr(value, '__dict__'):
            # Likely an instance of something. Watch for cycles.
            # Ignore class member vars.
            return recursive(value.__dict__, level=level + 1)
        elif netaddr and isinstance(value, netaddr.IPAddress):
            return six.text_type(value)
        else:
            if any(test(value) for test in _nasty_type_tests):
                return six.text_type(value)
            return value
    except TypeError:
        # Class objects are tricky since they may define something like
        # __iter__ defined but it isn't callable as list().
        return six.text_type(value)