option to bypass managment endpoint and timings support
--timings = show timings for each call made to nova (including auth) --bypass_url = api node endpoint to use instead of one from service catalog For example: nova --timings --bypass_url=http://10.24.31.37:8774/v1.1/nova-staging boot --image f304d266-0a49-4877-b34c-63aea8360297 --flavor 3 delete_me_2 Change-Id: Ib2a258b7e969ad56ce4ee2bd64c61310278cb856
This commit is contained in:
parent
d94edf1469
commit
a2a62a5f71
@ -10,6 +10,7 @@ OpenStack Client interface. Handles the REST calls and responses.
|
||||
import httplib2
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
import urlparse
|
||||
|
||||
try:
|
||||
@ -38,7 +39,8 @@ class HTTPClient(httplib2.Http):
|
||||
timeout=None, proxy_tenant_id=None,
|
||||
proxy_token=None, region_name=None,
|
||||
endpoint_type='publicURL', service_type=None,
|
||||
service_name=None, volume_service_name=None):
|
||||
service_name=None, volume_service_name=None,
|
||||
timings=False):
|
||||
super(HTTPClient, self).__init__(timeout=timeout)
|
||||
self.user = user
|
||||
self.password = password
|
||||
@ -50,6 +52,9 @@ class HTTPClient(httplib2.Http):
|
||||
self.service_type = service_type
|
||||
self.service_name = service_name
|
||||
self.volume_service_name = volume_service_name
|
||||
self.timings = timings
|
||||
|
||||
self.times = [] # [("item", starttime, endtime), ...]
|
||||
|
||||
self.management_url = None
|
||||
self.auth_token = None
|
||||
@ -60,6 +65,12 @@ class HTTPClient(httplib2.Http):
|
||||
self.force_exception_to_status_code = True
|
||||
self.disable_ssl_certificate_validation = insecure
|
||||
|
||||
def set_management_url(self, url):
|
||||
self.management_url = url
|
||||
|
||||
def get_timings(self):
|
||||
return self.times
|
||||
|
||||
def http_log(self, args, kwargs, resp, body):
|
||||
if not _logger.isEnabledFor(logging.DEBUG):
|
||||
return
|
||||
@ -105,6 +116,13 @@ class HTTPClient(httplib2.Http):
|
||||
|
||||
return resp, body
|
||||
|
||||
def _time_request(self, url, method, **kwargs):
|
||||
start_time = time.time()
|
||||
resp, body = self.request(url, method, **kwargs)
|
||||
self.times.append(("%s %s" % (method, url),
|
||||
start_time, time.time()))
|
||||
return resp, body
|
||||
|
||||
def _cs_request(self, url, method, **kwargs):
|
||||
if not self.management_url:
|
||||
self.authenticate()
|
||||
@ -117,14 +135,14 @@ class HTTPClient(httplib2.Http):
|
||||
if self.projectid:
|
||||
kwargs['headers']['X-Auth-Project-Id'] = self.projectid
|
||||
|
||||
resp, body = self.request(self.management_url + url, method,
|
||||
resp, body = self._time_request(self.management_url + url, method,
|
||||
**kwargs)
|
||||
return resp, body
|
||||
except exceptions.Unauthorized, ex:
|
||||
try:
|
||||
self.authenticate()
|
||||
resp, body = self.request(self.management_url + url, method,
|
||||
**kwargs)
|
||||
resp, body = self._time_request(self.management_url + url,
|
||||
method, **kwargs)
|
||||
return resp, body
|
||||
except exceptions.Unauthorized:
|
||||
raise ex
|
||||
@ -195,7 +213,7 @@ class HTTPClient(httplib2.Http):
|
||||
url = '/'.join([url, 'tokens', '%s?belongsTo=%s'
|
||||
% (self.proxy_token, self.proxy_tenant_id)])
|
||||
_logger.debug("Using Endpoint URL: %s" % url)
|
||||
resp, body = self.request(url, "GET",
|
||||
resp, body = self._time_request(url, "GET",
|
||||
headers={'X-Auth_Token': self.auth_token})
|
||||
return self._extract_service_catalog(url, resp, body,
|
||||
extract_token=False)
|
||||
@ -256,7 +274,7 @@ class HTTPClient(httplib2.Http):
|
||||
if self.projectid:
|
||||
headers['X-Auth-Project-Id'] = self.projectid
|
||||
|
||||
resp, body = self.request(url, 'GET', headers=headers)
|
||||
resp, body = self._time_request(url, 'GET', headers=headers)
|
||||
if resp.status in (200, 204): # in some cases we get No Content
|
||||
try:
|
||||
mgmt_header = 'x-server-management-url'
|
||||
@ -300,7 +318,7 @@ class HTTPClient(httplib2.Http):
|
||||
self.follow_all_redirects = True
|
||||
|
||||
try:
|
||||
resp, body = self.request(token_url, "POST", body=body)
|
||||
resp, body = self._time_request(token_url, "POST", body=body)
|
||||
finally:
|
||||
self.follow_all_redirects = tmp_follow_all_redirects
|
||||
|
||||
|
@ -86,6 +86,11 @@ class OpenStackComputeShell(object):
|
||||
action='store_true',
|
||||
help="Print debugging output")
|
||||
|
||||
parser.add_argument('--timings',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help="Print call timing info")
|
||||
|
||||
parser.add_argument('--os_username',
|
||||
default=utils.env('OS_USERNAME', 'NOVA_USERNAME'),
|
||||
help='Defaults to env[OS_USERNAME].')
|
||||
@ -159,6 +164,9 @@ class OpenStackComputeShell(object):
|
||||
default=utils.env('NOVA_URL'),
|
||||
help='Deprecated')
|
||||
|
||||
parser.add_argument('--bypass_url', dest='bypass_url',
|
||||
help="Use this API endpoint instead of the Service Catalog")
|
||||
|
||||
return parser
|
||||
|
||||
def get_subcommand_parser(self, version):
|
||||
@ -298,14 +306,16 @@ class OpenStackComputeShell(object):
|
||||
(os_username, os_password, os_tenant_name, os_auth_url,
|
||||
os_region_name, endpoint_type, insecure,
|
||||
service_type, service_name, volume_service_name,
|
||||
username, apikey, projectid, url, region_name) = (
|
||||
username, apikey, projectid, url, region_name,
|
||||
bypass_url) = (
|
||||
args.os_username, args.os_password,
|
||||
args.os_tenant_name, args.os_auth_url,
|
||||
args.os_region_name, args.endpoint_type,
|
||||
args.insecure, args.service_type, args.service_name,
|
||||
args.volume_service_name, args.username,
|
||||
args.apikey, args.projectid,
|
||||
args.url, args.region_name)
|
||||
args.url, args.region_name,
|
||||
args.bypass_url)
|
||||
|
||||
if not endpoint_type:
|
||||
endpoint_type = DEFAULT_NOVA_ENDPOINT_TYPE
|
||||
@ -366,11 +376,14 @@ class OpenStackComputeShell(object):
|
||||
region_name=os_region_name, endpoint_type=endpoint_type,
|
||||
extensions=self.extensions, service_type=service_type,
|
||||
service_name=service_name,
|
||||
volume_service_name=volume_service_name)
|
||||
volume_service_name=volume_service_name,
|
||||
timings=args.timings)
|
||||
|
||||
try:
|
||||
if not utils.isunauthenticated(args.func):
|
||||
self.cs.authenticate()
|
||||
if bypass_url:
|
||||
self.cs.set_management_url(bypass_url)
|
||||
except exc.Unauthorized:
|
||||
raise exc.CommandError("Invalid OpenStack Nova credentials.")
|
||||
except exc.AuthorizationFailure:
|
||||
@ -378,6 +391,21 @@ class OpenStackComputeShell(object):
|
||||
|
||||
args.func(self.cs, args)
|
||||
|
||||
if args.timings:
|
||||
self._dump_timings(self.cs.get_timings())
|
||||
|
||||
def _dump_timings(self, timings):
|
||||
class Tyme(object):
|
||||
def __init__(self, url, seconds):
|
||||
self.url = url
|
||||
self.seconds = seconds
|
||||
results = [Tyme(url, end - start) for url, start, end in timings]
|
||||
total = 0.0
|
||||
for tyme in results:
|
||||
total += tyme.seconds
|
||||
results.append(Tyme("Total", total))
|
||||
utils.print_list(results, ["url", "seconds"], sortby_index=None)
|
||||
|
||||
def _run_extension_hooks(self, hook_type, *args, **kwargs):
|
||||
"""Run hooks for all registered extensions."""
|
||||
for extension in self.extensions:
|
||||
|
@ -123,7 +123,11 @@ def pretty_choice_list(l):
|
||||
return ', '.join("'%s'" % i for i in l)
|
||||
|
||||
|
||||
def print_list(objs, fields, formatters={}):
|
||||
def print_list(objs, fields, formatters={}, sortby_index=0):
|
||||
if sortby_index == None:
|
||||
sortby = None
|
||||
else:
|
||||
sortby = fields[sortby_index]
|
||||
mixed_case_fields = ['serverId']
|
||||
pt = prettytable.PrettyTable([f for f in fields], caching=False)
|
||||
pt.align = 'l'
|
||||
@ -142,7 +146,7 @@ def print_list(objs, fields, formatters={}):
|
||||
row.append(data)
|
||||
pt.add_row(row)
|
||||
|
||||
print pt.get_string(sortby=fields[0])
|
||||
print pt.get_string(sortby=sortby)
|
||||
|
||||
|
||||
def print_dict(d, property="Property"):
|
||||
|
@ -45,7 +45,7 @@ class Client(object):
|
||||
proxy_token=None, region_name=None,
|
||||
endpoint_type='publicURL', extensions=None,
|
||||
service_type='compute', service_name=None,
|
||||
volume_service_name=None):
|
||||
volume_service_name=None, timings=False):
|
||||
# FIXME(comstud): Rename the api_key argument above when we
|
||||
# know it's not being used as keyword argument
|
||||
password = api_key
|
||||
@ -95,7 +95,14 @@ class Client(object):
|
||||
endpoint_type=endpoint_type,
|
||||
service_type=service_type,
|
||||
service_name=service_name,
|
||||
volume_service_name=volume_service_name)
|
||||
volume_service_name=volume_service_name,
|
||||
timings=timings)
|
||||
|
||||
def set_management_url(self, url):
|
||||
self.client.management_url = url
|
||||
|
||||
def get_timings(self):
|
||||
return self.client.get_timings()
|
||||
|
||||
def authenticate(self):
|
||||
"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user