|
|
84ba10 |
diff --git a/python-rhsm.spec b/python-rhsm.spec
|
|
|
84ba10 |
index 0318cc1..d2e00c1 100644
|
|
|
84ba10 |
--- a/python-rhsm.spec
|
|
|
84ba10 |
+++ b/python-rhsm.spec
|
|
|
84ba10 |
@@ -13,7 +13,7 @@
|
|
|
84ba10 |
|
|
|
84ba10 |
Name: python-rhsm
|
|
|
84ba10 |
Version: 1.15.4
|
|
|
84ba10 |
-Release: 2%{?dist}
|
|
|
84ba10 |
+Release: 3%{?dist}
|
|
|
84ba10 |
|
|
|
84ba10 |
Summary: A Python library to communicate with a Red Hat Unified Entitlement Platform
|
|
|
84ba10 |
Group: Development/Libraries
|
|
|
84ba10 |
@@ -74,6 +74,11 @@ rm -rf %{buildroot}
|
|
|
84ba10 |
%attr(644,root,root) %{_sysconfdir}/rhsm/ca/*.pem
|
|
|
84ba10 |
|
|
|
84ba10 |
%changelog
|
|
|
84ba10 |
+* Wed Aug 12 2015 Chris Rog <crog@redhat.com> 1.15.4-3
|
|
|
84ba10 |
+- Add user-agent to rhsm requests. (alikins@redhat.com)
|
|
|
84ba10 |
+- 1247890: KeyErrors are now caught when checking manager capabilities
|
|
|
84ba10 |
+ (csnyder@redhat.com)
|
|
|
84ba10 |
+
|
|
|
84ba10 |
* Thu Jul 23 2015 Chris Rog <crog@redhat.com> 1.15.4-2
|
|
|
84ba10 |
- Fedora 20 has been retired. (awood@redhat.com)
|
|
|
84ba10 |
|
|
|
84ba10 |
diff --git a/rel-eng/packages/python-rhsm b/rel-eng/packages/python-rhsm
|
|
|
84ba10 |
index ace4dde..c370a05 100644
|
|
|
84ba10 |
--- a/rel-eng/packages/python-rhsm
|
|
|
84ba10 |
+++ b/rel-eng/packages/python-rhsm
|
|
|
84ba10 |
@@ -1 +1 @@
|
|
|
84ba10 |
-1.15.4-2 ./
|
|
|
84ba10 |
+1.15.4-3 ./
|
|
|
84ba10 |
diff --git a/rel-eng/tito.props b/rel-eng/tito.props
|
|
|
84ba10 |
index fd057f6..6c86a16 100644
|
|
|
84ba10 |
--- a/rel-eng/tito.props
|
|
|
84ba10 |
+++ b/rel-eng/tito.props
|
|
|
84ba10 |
@@ -1,4 +1,4 @@
|
|
|
84ba10 |
-[buildconfig]
|
|
|
84ba10 |
-builder = tito.builder.Builder
|
|
|
84ba10 |
-tagger = tito.tagger.VersionTagger
|
|
|
84ba10 |
+[globalconfig]
|
|
|
84ba10 |
+default_builder = tito.distributionbuilder.DistributionBuilder
|
|
|
84ba10 |
+default_tagger = tito.tagger.ReleaseTagger
|
|
|
84ba10 |
|
|
|
84ba10 |
diff --git a/src/rhsm/connection.py b/src/rhsm/connection.py
|
|
|
84ba10 |
index 465405d..f5cbbdf 100644
|
|
|
84ba10 |
--- a/src/rhsm/connection.py
|
|
|
84ba10 |
+++ b/src/rhsm/connection.py
|
|
|
84ba10 |
@@ -43,7 +43,7 @@ except ImportError:
|
|
|
84ba10 |
subman_version = "unknown"
|
|
|
84ba10 |
|
|
|
84ba10 |
from rhsm import ourjson as json
|
|
|
84ba10 |
-from rhsm.utils import get_env_proxy_info
|
|
|
84ba10 |
+from rhsm import utils
|
|
|
84ba10 |
|
|
|
84ba10 |
global_socket_timeout = 60
|
|
|
84ba10 |
timeout_altered = None
|
|
|
84ba10 |
@@ -115,6 +115,7 @@ def drift_check(utc_time_string, hours=1):
|
|
|
84ba10 |
return drift
|
|
|
84ba10 |
|
|
|
84ba10 |
|
|
|
84ba10 |
+
|
|
|
84ba10 |
class ConnectionException(Exception):
|
|
|
84ba10 |
pass
|
|
|
84ba10 |
|
|
|
84ba10 |
@@ -264,7 +265,6 @@ class ContentConnection(object):
|
|
|
84ba10 |
self.username = username
|
|
|
84ba10 |
self.password = password
|
|
|
84ba10 |
self.ssl_verify_depth = ssl_verify_depth
|
|
|
84ba10 |
-
|
|
|
84ba10 |
self.timeout_altered = False
|
|
|
84ba10 |
|
|
|
84ba10 |
# get the proxy information from the environment variable
|
|
|
84ba10 |
@@ -275,13 +275,17 @@ class ContentConnection(object):
|
|
|
84ba10 |
'proxy_port': '',
|
|
|
84ba10 |
'proxy_password': ''}
|
|
|
84ba10 |
else:
|
|
|
84ba10 |
- info = get_env_proxy_info()
|
|
|
84ba10 |
+ info = utils.get_env_proxy_info()
|
|
|
84ba10 |
|
|
|
84ba10 |
self.proxy_hostname = proxy_hostname or config.get('server', 'proxy_hostname') or info['proxy_hostname']
|
|
|
84ba10 |
self.proxy_port = proxy_port or config.get('server', 'proxy_port') or info['proxy_port']
|
|
|
84ba10 |
self.proxy_user = proxy_user or config.get('server', 'proxy_user') or info['proxy_username']
|
|
|
84ba10 |
self.proxy_password = proxy_password or config.get('server', 'proxy_password') or info['proxy_password']
|
|
|
84ba10 |
|
|
|
84ba10 |
+ @property
|
|
|
84ba10 |
+ def user_agent(self):
|
|
|
84ba10 |
+ return "RHSM-content/1.0 (cmd=%s)" % utils.cmd_name(sys.argv)
|
|
|
84ba10 |
+
|
|
|
84ba10 |
def _request(self, request_type, handler, body=None):
|
|
|
84ba10 |
# See note in Restlib._request
|
|
|
84ba10 |
context = SSL.Context("sslv23")
|
|
|
84ba10 |
@@ -304,7 +308,11 @@ class ContentConnection(object):
|
|
|
84ba10 |
|
|
|
84ba10 |
set_default_socket_timeout_if_python_2_3()
|
|
|
84ba10 |
|
|
|
84ba10 |
- conn.request("GET", handler, body="", headers={"Host": "%s:%s" % (self.host, self.ssl_port), "Content-Length": "0"})
|
|
|
84ba10 |
+ conn.request("GET", handler,
|
|
|
84ba10 |
+ body="",
|
|
|
84ba10 |
+ headers={"Host": "%s:%s" % (self.host, self.ssl_port),
|
|
|
84ba10 |
+ "Content-Length": "0",
|
|
|
84ba10 |
+ "User-Agent": self.user_agent})
|
|
|
84ba10 |
response = conn.getresponse()
|
|
|
84ba10 |
result = {
|
|
|
84ba10 |
"content": response.read(),
|
|
|
84ba10 |
@@ -383,6 +391,9 @@ class Restlib(object):
|
|
|
84ba10 |
self.apihandler = apihandler
|
|
|
84ba10 |
lc = _get_locale()
|
|
|
84ba10 |
|
|
|
84ba10 |
+ # Default, updated by UepConnection
|
|
|
84ba10 |
+ self.user_agent = "python-rhsm-user-agent"
|
|
|
84ba10 |
+
|
|
|
84ba10 |
self.headers = {"Content-type": "application/json",
|
|
|
84ba10 |
"Accept": "application/json",
|
|
|
84ba10 |
"x-python-rhsm-version": python_rhsm_version,
|
|
|
84ba10 |
@@ -492,6 +503,7 @@ class Restlib(object):
|
|
|
84ba10 |
else:
|
|
|
84ba10 |
conn = httpslib.HTTPSConnection(self.host, self.ssl_port, ssl_context=context)
|
|
|
84ba10 |
|
|
|
84ba10 |
+
|
|
|
84ba10 |
if info is not None:
|
|
|
84ba10 |
body = json.dumps(info, default=json.encode)
|
|
|
84ba10 |
else:
|
|
|
84ba10 |
@@ -499,6 +511,9 @@ class Restlib(object):
|
|
|
84ba10 |
|
|
|
84ba10 |
log.debug("Making request: %s %s" % (request_type, handler))
|
|
|
84ba10 |
|
|
|
84ba10 |
+ if self.user_agent:
|
|
|
84ba10 |
+ self.headers['User-Agent'] = self.user_agent
|
|
|
84ba10 |
+
|
|
|
84ba10 |
headers = self.headers
|
|
|
84ba10 |
if body is None:
|
|
|
84ba10 |
headers = dict(self.headers.items() +
|
|
|
84ba10 |
@@ -665,7 +680,7 @@ class UEPConnection:
|
|
|
84ba10 |
'proxy_port': '',
|
|
|
84ba10 |
'proxy_password': ''}
|
|
|
84ba10 |
else:
|
|
|
84ba10 |
- info = get_env_proxy_info()
|
|
|
84ba10 |
+ info = utils.get_env_proxy_info()
|
|
|
84ba10 |
|
|
|
84ba10 |
self.proxy_hostname = proxy_hostname or config.get('server', 'proxy_hostname') or info['proxy_hostname']
|
|
|
84ba10 |
self.proxy_port = proxy_port or config.get('server', 'proxy_port') or info['proxy_port']
|
|
|
84ba10 |
@@ -731,6 +746,8 @@ class UEPConnection:
|
|
|
84ba10 |
ssl_verify_depth=self.ssl_verify_depth)
|
|
|
84ba10 |
auth_description = "auth=none"
|
|
|
84ba10 |
|
|
|
84ba10 |
+ self.conn.user_agent = "RHSM/1.0 (cmd=%s)" % utils.cmd_name(sys.argv)
|
|
|
84ba10 |
+
|
|
|
84ba10 |
self.resources = None
|
|
|
84ba10 |
self.capabilities = None
|
|
|
84ba10 |
connection_description = ""
|
|
|
84ba10 |
@@ -771,21 +788,27 @@ class UEPConnection:
|
|
|
84ba10 |
def _load_manager_capabilities(self):
|
|
|
84ba10 |
"""
|
|
|
84ba10 |
Loads manager capabilities by doing a GET on the status
|
|
|
84ba10 |
- resource located at '/status/'
|
|
|
84ba10 |
- """
|
|
|
84ba10 |
- self.capabilities = {}
|
|
|
84ba10 |
- self.capabilities = self.conn.request_get("/status/")
|
|
|
84ba10 |
- self.capabilities = self.capabilities['managerCapabilities']
|
|
|
84ba10 |
- log.debug("Server has the following capabilities: %s",
|
|
|
84ba10 |
- self.capabilities)
|
|
|
84ba10 |
+ resource located at '/status'
|
|
|
84ba10 |
+ """
|
|
|
84ba10 |
+ status = self.getStatus()
|
|
|
84ba10 |
+ capabilities = status.get('managerCapabilities')
|
|
|
84ba10 |
+ if capabilities is None:
|
|
|
84ba10 |
+ log.debug("The status retrieved did not \
|
|
|
84ba10 |
+ include key 'managerCapabilities'.\nStatus:'%s'" % status)
|
|
|
84ba10 |
+ capabilities = []
|
|
|
84ba10 |
+ elif isinstance(capabilities, list) and not capabilities:
|
|
|
84ba10 |
+ log.debug("The managerCapabilities list \
|
|
|
84ba10 |
+ was empty\nStatus:'%s'" % status)
|
|
|
84ba10 |
+ else:
|
|
|
84ba10 |
+ log.debug("Server has the following capabilities: %s", capabilities)
|
|
|
84ba10 |
+ return capabilities
|
|
|
84ba10 |
|
|
|
84ba10 |
def has_capability(self, capability):
|
|
|
84ba10 |
"""
|
|
|
84ba10 |
Check if the server we're connected to has a particular capability.
|
|
|
84ba10 |
"""
|
|
|
84ba10 |
if self.capabilities is None:
|
|
|
84ba10 |
- self._load_manager_capabilities()
|
|
|
84ba10 |
-
|
|
|
84ba10 |
+ self.capabilities = self._load_manager_capabilities()
|
|
|
84ba10 |
return capability in self.capabilities
|
|
|
84ba10 |
|
|
|
84ba10 |
def shutDown(self):
|
|
|
84ba10 |
diff --git a/src/rhsm/utils.py b/src/rhsm/utils.py
|
|
|
84ba10 |
index dd41161..f1a7f4e 100644
|
|
|
84ba10 |
--- a/src/rhsm/utils.py
|
|
|
84ba10 |
+++ b/src/rhsm/utils.py
|
|
|
84ba10 |
@@ -17,6 +17,7 @@ import gettext
|
|
|
84ba10 |
import os
|
|
|
84ba10 |
import re
|
|
|
84ba10 |
from urlparse import urlparse
|
|
|
84ba10 |
+
|
|
|
84ba10 |
from rhsm.config import DEFAULT_PROXY_PORT
|
|
|
84ba10 |
|
|
|
84ba10 |
_ = lambda x: gettext.ldgettext("rhsm", x)
|
|
|
84ba10 |
@@ -232,3 +233,24 @@ def get_env_proxy_info():
|
|
|
84ba10 |
else:
|
|
|
84ba10 |
the_proxy['proxy_port'] = int(info[3])
|
|
|
84ba10 |
return the_proxy
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+def cmd_name(argv):
|
|
|
84ba10 |
+ """Attempt to get a meaningful command name from argv.
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ This handles cases where argv[0] isn't helpful (for
|
|
|
84ba10 |
+ example, '/usr/bin/python' or '__main__.py'.
|
|
|
84ba10 |
+ """
|
|
|
84ba10 |
+ argv0 = os.path.basename(argv[0])
|
|
|
84ba10 |
+ argvdir = os.path.dirname(argv[0])
|
|
|
84ba10 |
+ head, tail = os.path.split(argvdir)
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ cmd_name_string = argv0
|
|
|
84ba10 |
+ # initial-setup is launched as 'python -m initial_setup', so
|
|
|
84ba10 |
+ # sys.argv looks like
|
|
|
84ba10 |
+ # ['/usr/lib/python2.7/site-packages/initial_setup/__main__.py'],
|
|
|
84ba10 |
+ # so we look for initial_setup in the exe path.
|
|
|
84ba10 |
+ if tail == "initial_setup":
|
|
|
84ba10 |
+ cmd_name_string = "initial-setup"
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ return cmd_name_string
|
|
|
84ba10 |
diff --git a/test/unit/connection-tests.py b/test/unit/connection-tests.py
|
|
|
84ba10 |
index 6e449ad..8a0091d 100644
|
|
|
84ba10 |
--- a/test/unit/connection-tests.py
|
|
|
84ba10 |
+++ b/test/unit/connection-tests.py
|
|
|
84ba10 |
@@ -37,6 +37,26 @@ class ConnectionTests(unittest.TestCase):
|
|
|
84ba10 |
self.cp = UEPConnection(username="dummy", password="dummy",
|
|
|
84ba10 |
handler="/Test/", insecure=True)
|
|
|
84ba10 |
|
|
|
84ba10 |
+ def test_load_manager_capabilities(self):
|
|
|
84ba10 |
+ expected_capabilities = ['hypervisors_async', 'cores']
|
|
|
84ba10 |
+ proper_status = {'version':'1',
|
|
|
84ba10 |
+ 'result':True,
|
|
|
84ba10 |
+ 'managerCapabilities':expected_capabilities}
|
|
|
84ba10 |
+ improper_status = dict.copy(proper_status)
|
|
|
84ba10 |
+ # Remove the managerCapabilities key from the dict
|
|
|
84ba10 |
+ del improper_status['managerCapabilities']
|
|
|
84ba10 |
+ self.cp.conn = Mock()
|
|
|
84ba10 |
+ # The first call will return the proper_status, the second, the improper
|
|
|
84ba10 |
+ # status
|
|
|
84ba10 |
+ original_getStatus = self.cp.getStatus
|
|
|
84ba10 |
+ self.cp.getStatus = Mock(side_effect=[proper_status,
|
|
|
84ba10 |
+ improper_status])
|
|
|
84ba10 |
+ actual_capabilities = self.cp._load_manager_capabilities()
|
|
|
84ba10 |
+ self.assertEquals(sorted(actual_capabilities),
|
|
|
84ba10 |
+ sorted(expected_capabilities))
|
|
|
84ba10 |
+ self.assertEquals([], self.cp._load_manager_capabilities())
|
|
|
84ba10 |
+ self.cp.getStatus = original_getStatus
|
|
|
84ba10 |
+
|
|
|
84ba10 |
def test_get_environment_by_name_requires_owner(self):
|
|
|
84ba10 |
self.assertRaises(Exception, self.cp.getEnvironment, None, {"name": "env name"})
|
|
|
84ba10 |
|
|
|
84ba10 |
diff --git a/test/unit/util-tests.py b/test/unit/util-tests.py
|
|
|
84ba10 |
index c650d74..4d4a65b 100644
|
|
|
84ba10 |
--- a/test/unit/util-tests.py
|
|
|
84ba10 |
+++ b/test/unit/util-tests.py
|
|
|
84ba10 |
@@ -6,7 +6,7 @@ from rhsm.utils import remove_scheme, get_env_proxy_info, \
|
|
|
84ba10 |
ServerUrlParseErrorEmpty, ServerUrlParseErrorNone, \
|
|
|
84ba10 |
ServerUrlParseErrorPort, ServerUrlParseErrorScheme, \
|
|
|
84ba10 |
ServerUrlParseErrorJustScheme, has_bad_scheme, has_good_scheme, \
|
|
|
84ba10 |
- parse_url
|
|
|
84ba10 |
+ parse_url, cmd_name
|
|
|
84ba10 |
from rhsm.config import DEFAULT_PORT, DEFAULT_PREFIX, DEFAULT_HOSTNAME, \
|
|
|
84ba10 |
DEFAULT_CDN_HOSTNAME, DEFAULT_CDN_PORT, DEFAULT_CDN_PREFIX
|
|
|
84ba10 |
|
|
|
84ba10 |
@@ -379,3 +379,45 @@ class TestProxyInfo(unittest.TestCase):
|
|
|
84ba10 |
self.assertEquals(None, proxy_info["proxy_password"])
|
|
|
84ba10 |
self.assertEquals("host", proxy_info["proxy_hostname"])
|
|
|
84ba10 |
self.assertEquals(int("1111"), proxy_info["proxy_port"])
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+class TestCmdName(unittest.TestCase):
|
|
|
84ba10 |
+ def test_usr_sbin(self):
|
|
|
84ba10 |
+ argv = ['/usr/sbin/subscription-manager', 'list']
|
|
|
84ba10 |
+ self.assertEquals("subscription-manager", cmd_name(argv))
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ def test_bin(self):
|
|
|
84ba10 |
+ argv = ['bin/subscription-manager', 'subscribe', '--auto']
|
|
|
84ba10 |
+ self.assertEquals("subscription-manager", cmd_name(argv))
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ def test_sbin(self):
|
|
|
84ba10 |
+ argv = ['/sbin/subscription-manager', 'list']
|
|
|
84ba10 |
+ self.assertEquals("subscription-manager", cmd_name(argv))
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ def test_subscription_manager_gui(self):
|
|
|
84ba10 |
+ argv = ['/sbin/subscription-manager-gui']
|
|
|
84ba10 |
+ self.assertEquals("subscription-manager-gui", cmd_name(argv))
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ def test_initial_setup(self):
|
|
|
84ba10 |
+ argv = ['/usr/lib/python2.7/site-packages/initial_setup/__main__.py']
|
|
|
84ba10 |
+ self.assertEquals("initial-setup", cmd_name(argv))
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ def test_yum(self):
|
|
|
84ba10 |
+ argv = ['/bin/yum', 'install', 'zsh']
|
|
|
84ba10 |
+ self.assertEquals("yum", cmd_name(argv))
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ def test_rhsmcertd_worker(self):
|
|
|
84ba10 |
+ argv = ['/usr/libexec/rhsmcertd-worker']
|
|
|
84ba10 |
+ self.assertEquals("rhsmcertd-worker", cmd_name(argv))
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ def test_rhsm_debug(self):
|
|
|
84ba10 |
+ argv = ['/bin/rhsm-debug']
|
|
|
84ba10 |
+ self.assertEquals("rhsm-debug", cmd_name(argv))
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ def test_virt_who(self):
|
|
|
84ba10 |
+ argv = ['/usr/share/virt-who/virtwho.py']
|
|
|
84ba10 |
+ self.assertEquals("virtwho.py", cmd_name(argv))
|
|
|
84ba10 |
+
|
|
|
84ba10 |
+ def test_rhsmd(self):
|
|
|
84ba10 |
+ argv = ['/usr/libexec/rhsmd', '-i', '-f', 'valid']
|
|
|
84ba10 |
+ self.assertEquals("rhsmd", cmd_name(argv))
|