def test_timestamp_to_seconds(self): """ :func:`helper.timestamp_to_seconds` returns a seconds since EPOCH matching the corresponding timestamp given in ISO8601 format """ local_matches = [(0, "1970-01-01"), (0, "1970-01-01T00"), (0, "1970-01-01T00:00"), (1800, "1970-01-01T00-00:30")] for seconds, timestamp in self.matches + local_matches: self.assertEqual(seconds, helper.timestamp_to_seconds(timestamp))
def request_list( self, http_get_request, include_details, absolutize_url, name=u"", limit=None, marker=None, changes_since=None ): """ Request the list JSON for all servers. :param str changes_since: ISO8601 formatted datetime. Based on http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ChangesSince.html Note: only supports filtering by name right now, but will need to support more going forward. Pagination behavior verified against Rackspace Nova as of 2015-04-29. """ to_be_listed = self.servers if changes_since is not None: since = timestamp_to_seconds(changes_since) to_be_listed = filter(lambda s: s.update_time >= since, to_be_listed) # marker can be passed without limit, in which case the whole server # list, after the server that matches the marker, is returned if marker is not None: last_seen = [i for i, server in enumerate(to_be_listed) if server.server_id == marker] if not last_seen: # Error response and body verified against Rackspace Nova as # of 2015-04-29 return dumps(bad_request("marker [{0}] not found".format(marker), http_get_request)) else: last_seen = last_seen[0] to_be_listed = to_be_listed[last_seen + 1 :] # A valid marker is an ID in the entire server list. It does not # have to be for a server that matches the given name. to_be_listed = [server for server in to_be_listed if name in server.server_name] if changes_since is None: to_be_listed = filter(lambda s: s.status != u"DELETED", to_be_listed) if limit is not None: try: limit = int(limit) except ValueError: return dumps(bad_request("limit param must be an integer", http_get_request)) if limit < 0: return dumps(bad_request("limit param must be positive", http_get_request)) to_be_listed = to_be_listed[:limit] result = { "servers": [ server.brief_json(absolutize_url) if not include_details else server.detail_json(absolutize_url) for server in to_be_listed ] } # A server links blob is included only if limit is passed. If # only the marker was provided, no server links blob is included. # Note that if limit=0, an empty server list is returned and no # server link blob is returned. if limit and len(to_be_listed) >= limit: query_params = {"limit": limit} query_params["marker"] = to_be_listed[-1].server_id if name: query_params["name"] = name path = "v2/{0}/servers{1}?{2}".format( self.tenant_id, "/detail" if include_details else "", urlencode(query_params) ) result["servers_links"] = [{"href": absolutize_url(path), "rel": "next"}] return dumps(result)
def request_list(self, http_get_request, include_details, absolutize_url, name=u"", limit=None, marker=None, changes_since=None): """ Request the list JSON for all servers. :param str changes_since: ISO8601 formatted datetime. Based on http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ChangesSince.html Note: only supports filtering by name right now, but will need to support more going forward. Pagination behavior verified against Rackspace Nova as of 2015-04-29. """ to_be_listed = self.servers if changes_since is not None: since = timestamp_to_seconds(changes_since) to_be_listed = filter(lambda s: s.update_time >= since, to_be_listed) # marker can be passed without limit, in which case the whole server # list, after the server that matches the marker, is returned if marker is not None: last_seen = [i for i, server in enumerate(to_be_listed) if server.server_id == marker] if not last_seen: # Error response and body verified against Rackspace Nova as # of 2015-04-29 return dumps(bad_request( "marker [{0}] not found".format(marker), http_get_request)) else: last_seen = last_seen[0] to_be_listed = to_be_listed[last_seen + 1:] # A valid marker is an ID in the entire server list. It does not # have to be for a server that matches the given name. to_be_listed = [server for server in to_be_listed if name in server.server_name] if changes_since is None: to_be_listed = filter(lambda s: s.status != u"DELETED", to_be_listed) if limit is not None: try: limit = int(limit) except ValueError: return dumps(bad_request("limit param must be an integer", http_get_request)) if limit < 0: return dumps(bad_request("limit param must be positive", http_get_request)) to_be_listed = to_be_listed[:limit] result = { "servers": [ server.brief_json(absolutize_url) if not include_details else server.detail_json(absolutize_url) for server in to_be_listed ] } # A server links blob is included only if limit is passed. If # only the marker was provided, no server links blob is included. # Note that if limit=0, an empty server list is returned and no # server link blob is returned. if limit and len(to_be_listed) >= limit: query_params = {'limit': limit} query_params['marker'] = to_be_listed[-1].server_id if name: query_params['name'] = name path = "v2/{0}/servers{1}?{2}".format( self.tenant_id, "/detail" if include_details else "", urlencode(query_params)) result["servers_links"] = [{ "href": absolutize_url(path), "rel": "next" }] return dumps(result)