Hello community,

here is the log from the commit of package python-ceilometerclient for 
openSUSE:13.1 checked in at 2013-10-23 11:26:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:13.1/python-ceilometerclient (Old)
 and      /work/SRC/openSUSE:13.1/.python-ceilometerclient.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-ceilometerclient"

Changes:
--------
--- 
/work/SRC/openSUSE:13.1/python-ceilometerclient/python-ceilometerclient.changes 
    2013-10-02 13:32:39.000000000 +0200
+++ 
/work/SRC/openSUSE:13.1/.python-ceilometerclient.new/python-ceilometerclient.changes
        2013-10-23 11:26:54.000000000 +0200
@@ -1,0 +2,11 @@
+Mon Oct  7 10:18:31 UTC 2013 - [email protected]
+
+- Update to version 1.0.6:
+  + Allow to update an alarm partially
+  + Fix shell.do_alarm_get_state to get as opposed to set
+  + Use standard CLI object-verb ordering for alarm-{g|s}set-state
+  + Updated from global requirements
+  + Added support to --os-cacert
+  + Add support for new alarm-history command
+
+-------------------------------------------------------------------

Old:
----
  python-ceilometerclient-master.tar.gz

New:
----
  python-ceilometerclient-1.0.6.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-ceilometerclient.spec ++++++
--- /var/tmp/diff_new_pack.68QDnN/_old  2013-10-23 11:26:54.000000000 +0200
+++ /var/tmp/diff_new_pack.68QDnN/_new  2013-10-23 11:26:54.000000000 +0200
@@ -20,13 +20,13 @@
 %define component ceilometerclient
 
 Name:           python-%{component}
-Version:        1.0.5.2
+Version:        1.0.6
 Release:        0
 Url:            https://github.com/openstack/python-ceilometerclient
 Summary:        OpenStack Metering (Ceilometer) API Client
 License:        Apache-2.0
 Group:          Development/Languages/Python
-Source:         python-ceilometerclient-master.tar.gz
+Source:         python-ceilometerclient-1.0.6.tar.gz
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildRequires:  openstack-suse-macros
 BuildRequires:  python-base
@@ -71,7 +71,7 @@
 This package contains testsuite files for %{name}.
 
 %prep
-%setup -q -n python-ceilometerclient-1.0.5.2.gb961738
+%setup -q -n python-ceilometerclient-1.0.6
 %openstack_cleanup_prep
 echo %{version} > ceilometerclient/versioninfo
 

++++++ _service ++++++
--- /var/tmp/diff_new_pack.68QDnN/_old  2013-10-23 11:26:54.000000000 +0200
+++ /var/tmp/diff_new_pack.68QDnN/_new  2013-10-23 11:26:54.000000000 +0200
@@ -1,8 +1,7 @@
 <services>
   <service name="git_tarballs" mode="disabled">
-    <param 
name="url">http://tarballs.openstack.org/python-ceilometerclient/python-ceilometerclient-master.tar.gz</param>
+    <param 
name="url">http://tarballs.openstack.org/python-ceilometerclient/python-ceilometerclient-1.0.6.tar.gz</param>
     <param name="email">[email protected]</param>
-    <param name="version-regexp">.*-([^-]+)\.g[a-zA-Z0-9]{7}</param>
     <param name="plain-version">True</param>
   </service>
 </services>

++++++ python-ceilometerclient-master.tar.gz -> 
python-ceilometerclient-1.0.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-ceilometerclient-1.0.5.2.gb961738/AUTHORS 
new/python-ceilometerclient-1.0.6/AUTHORS
--- old/python-ceilometerclient-1.0.5.2.gb961738/AUTHORS        2013-09-30 
18:22:39.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/AUTHORS   2013-10-04 09:58:49.000000000 
+0200
@@ -16,5 +16,7 @@
 Lianhao Lu <[email protected]>
 Mehdi Abaakouk <[email protected]>
 Monty Taylor <[email protected]>
+OpenStack Jenkins <[email protected]>
+Stefano Zilli <[email protected]>
 ZhiQiang Fan <[email protected]>
 yolanda.robla <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-ceilometerclient-1.0.5.2.gb961738/ChangeLog 
new/python-ceilometerclient-1.0.6/ChangeLog
--- old/python-ceilometerclient-1.0.5.2.gb961738/ChangeLog      2013-09-30 
18:22:39.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/ChangeLog 2013-10-04 09:58:49.000000000 
+0200
@@ -1,3 +1,103 @@
+commit c3283ec1e861f29a53c59c1a09f2a1bc21a713e4
+Author: Eoghan Glynn <[email protected]>
+Date:   Wed Oct 2 16:18:06 2013 +0000
+
+    Add support for new alarm-history command
+    
+    Expose the new alarm history API via the CLI.
+    
+    Change-Id: I5757d309dd7143dfab83985fb51ee6d320478e3b
+
+commit 50ecc8f63b9f2f9a482f2211ad0499f2be7c6f5a
+Merge: 146de67 544e621
+Author: Jenkins <[email protected]>
+Date:   Thu Oct 3 00:34:12 2013 +0000
+
+    Merge "Added support to --os-cacert"
+
+commit 146de671496a72ccdc20a3da4beec901a890f9b3
+Merge: db2c858 a99a8c6
+Author: OpenStack Jenkins <[email protected]>
+Date:   Thu Oct 3 00:34:10 2013 +0000
+
+    Merge "Updated from global requirements"
+
+commit db2c858585aea4426aad9cf6c870b338e1a921ea
+Merge: 0a6a6b4 fc201b3
+Author: Jenkins <[email protected]>
+Date:   Thu Oct 3 00:34:09 2013 +0000
+
+    Merge "Use standard CLI object-verb ordering for alarm-{g|s}set-state"
+
+commit 0a6a6b4d099f627e71ca22dd9d376da2f54d4f90
+Merge: 66ef360 7c8a676
+Author: Jenkins <[email protected]>
+Date:   Thu Oct 3 00:34:08 2013 +0000
+
+    Merge "Fix shell.do_alarm_get_state to get as opposed to set"
+
+commit fc201b3805dda16fad66d7c0d0e47b1e32612874
+Author: Eoghan Glynn <[email protected]>
+Date:   Wed Oct 2 09:59:47 2013 +0000
+
+    Use standard CLI object-verb ordering for alarm-{g|s}set-state
+    
+    The openstack CLIs all use an object-followed-by-verb ordering
+    convention when construct command names.
+    
+    Follow a similar convention for commands to get and set alarm
+    state.
+    
+    Change-Id: I34e0f450019556c80476df782d4c86dca08bdc9d
+
+commit 7c8a676b43e9f82276041afbae15d739dc2c1ab4
+Author: Eoghan Glynn <[email protected]>
+Date:   Wed Oct 2 09:30:27 2013 +0000
+
+    Fix shell.do_alarm_get_state to get as opposed to set
+    
+    Otherwise the CLI fails when attempting to set a state arg that
+    doesn't exist.
+    
+    (Simple copy'n'paste error in the original code).
+    
+    Change-Id: Iab117177805449ddec9d03656a95a0cbbbbd58bb
+
+commit a99a8c628faa33768961952b59b8175c1a108780
+Author: OpenStack Jenkins <[email protected]>
+Date:   Tue Oct 1 16:14:33 2013 +0000
+
+    Updated from global requirements
+    
+    Change-Id: I71d6d8aad148b240f8ab1325d3c3ff2996ebf642
+
+commit 66ef360c1480899bcdf6ad7af8f2d581b532c5e6
+Author: Mehdi Abaakouk <[email protected]>
+Date:   Thu Sep 26 09:50:37 2013 +0200
+
+    Allow to update an alarm partially
+    
+    The patch allow to only modify a part of an alarm instead of force to
+    set the full alarm description.
+    
+    This permit to an application that have been written code around alarm
+    with ceilometerclient 1.0.4 and ceilometer pre havana-3. To update alarm
+    without any change with this and ceilometer >= havana-3 (ie: heat).
+    
+    Fixes bug #1231303
+    
+    Change-Id: I20250131d05d20bfadbca450dfe6b8237f4b7183
+
+commit 544e6217e58a9eaee67e98f27cb9385ee412ba79
+Author: Stefano Zilli <[email protected]>
+Date:   Fri Sep 13 09:08:19 2013 +0200
+
+    Added support to --os-cacert
+    
+    Closes-Bug: #1224343
+    
+    Change-Id: Ib0549d4496c47900c81cc970b99bcff25cad0040
+
 commit b961738765976e77711d909eec1ecc402fa8a484
 Author: Cyril Roelandt <[email protected]>
 Date:   Wed Sep 25 12:49:58 2013 +0000
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-ceilometerclient-1.0.5.2.gb961738/PKG-INFO 
new/python-ceilometerclient-1.0.6/PKG-INFO
--- old/python-ceilometerclient-1.0.5.2.gb961738/PKG-INFO       2013-09-30 
18:22:40.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/PKG-INFO  2013-10-04 09:58:49.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: python-ceilometerclient
-Version: 1.0.5.2.gb961738
+Version: 1.0.6
 Summary: OpenStack Metering API Client Library
 Home-page: http://www.openstack.org/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/client.py 
new/python-ceilometerclient-1.0.6/ceilometerclient/client.py
--- old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/client.py     
2013-09-30 18:21:46.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/ceilometerclient/client.py        
2013-10-04 09:58:25.000000000 +0200
@@ -21,6 +21,7 @@
             * username: name of user
             * password: user's password
             * auth_url: endpoint to authenticate against
+            * cacert: path of CA TLS certificate
             * insecure: allow insecure SSL (no cert verification)
             * tenant_{name|id}: name or ID of tenant
     """
@@ -30,6 +31,7 @@
                            tenant_name=kwargs.get('tenant_name'),
                            auth_url=kwargs.get('auth_url'),
                            region_name=kwargs.get('region_name'),
+                           cacert=kwargs.get('cacert'),
                            insecure=kwargs.get('insecure'))
 
 
@@ -52,6 +54,7 @@
             * os_username: name of user
             * os_password: user's password
             * os_auth_url: endpoint to authenticate against
+            * os_cacert: path of CA TLS certificate
             * insecure: allow insecure SSL (no cert verification)
             * os_tenant_{name|id}: name or ID of tenant
     """
@@ -72,6 +75,7 @@
             'region_name': kwargs.get('os_region_name'),
             'service_type': kwargs.get('os_service_type'),
             'endpoint_type': kwargs.get('os_endpoint_type'),
+            'cacert': kwargs.get('os_cacert'),
             'insecure': kwargs.get('insecure'),
         }
         _ksclient = _get_ksclient(**ks_kwargs)
@@ -86,7 +90,7 @@
         'token': token,
         'insecure': kwargs.get('insecure'),
         'timeout': kwargs.get('timeout'),
-        'ca_file': kwargs.get('ca_file'),
+        'cacert': kwargs.get('cacert'),
         'cert_file': kwargs.get('cert_file'),
         'key_file': kwargs.get('key_file'),
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/common/http.py 
new/python-ceilometerclient-1.0.6/ceilometerclient/common/http.py
--- 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/common/http.py    
    2013-09-30 18:21:46.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/ceilometerclient/common/http.py   
2013-10-04 09:58:25.000000000 +0200
@@ -63,7 +63,7 @@
 
         if parts.scheme == 'https':
             _class = VerifiedHTTPSConnection
-            _kwargs['ca_file'] = kwargs.get('ca_file', None)
+            _kwargs['ca_cert'] = kwargs.get('cacert', None)
             _kwargs['cert_file'] = kwargs.get('cert_file', None)
             _kwargs['key_file'] = kwargs.get('key_file', None)
             _kwargs['insecure'] = kwargs.get('insecure', False)
@@ -93,7 +93,7 @@
         conn_params_fmt = [
             ('key_file', '--key %s'),
             ('cert_file', '--cert %s'),
-            ('ca_file', '--cacert %s'),
+            ('cacert', '--cacert %s'),
         ]
         for (key, fmt) in conn_params_fmt:
             value = self.connection_params[2].get(key)
@@ -215,21 +215,21 @@
     """
 
     def __init__(self, host, port, key_file=None, cert_file=None,
-                 ca_file=None, timeout=None, insecure=False):
+                 cacert=None, timeout=None, insecure=False):
         httplib.HTTPSConnection.__init__(self, host, port, key_file=key_file,
                                          cert_file=cert_file)
         self.key_file = key_file
         self.cert_file = cert_file
-        if ca_file is not None:
-            self.ca_file = ca_file
+        if cacert is not None:
+            self.cacert = cacert
         else:
-            self.ca_file = self.get_system_ca_file()
+            self.cacert = self.get_system_ca_file()
         self.timeout = timeout
         self.insecure = insecure
 
     def connect(self):
         """Connect to a host on a given (SSL) port.
-        If ca_file is pointing somewhere, use it to check Server Certificate.
+        If cacert is pointing somewhere, use it to check Server Certificate.
 
         Redefined/copied and extended from httplib.py:1105 (Python 2.6.x).
         This is needed to pass cert_reqs=ssl.CERT_REQUIRED as parameter to
@@ -245,7 +245,7 @@
         if self.insecure is True:
             kwargs = {'cert_reqs': ssl.CERT_NONE}
         else:
-            kwargs = {'cert_reqs': ssl.CERT_REQUIRED, 'ca_certs': self.ca_file}
+            kwargs = {'cert_reqs': ssl.CERT_REQUIRED, 'ca_certs': self.cacert}
 
         if self.cert_file:
             kwargs['certfile'] = self.cert_file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/common/utils.py 
new/python-ceilometerclient-1.0.6/ceilometerclient/common/utils.py
--- 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/common/utils.py   
    2013-09-30 18:21:46.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/ceilometerclient/common/utils.py  
2013-10-04 09:58:25.000000000 +0200
@@ -160,6 +160,15 @@
     return kwargs
 
 
+def merge_nested_dict(dest, source, depth=0):
+    for (key, value) in source.iteritems():
+        if isinstance(value, dict) and depth:
+            merge_nested_dict(dest[key], value,
+                              depth=(depth - 1))
+        else:
+            dest[key] = value
+
+
 def exit(msg=''):
     if msg:
         print >> sys.stderr, msg
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/shell.py 
new/python-ceilometerclient-1.0.6/ceilometerclient/shell.py
--- old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/shell.py      
2013-09-30 18:21:46.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/ceilometerclient/shell.py 2013-10-04 
09:58:25.000000000 +0200
@@ -76,11 +76,17 @@
                             ' This option is not necessary if your key is '
                             'prepended to your cert file.')
 
-        parser.add_argument('--ca-file',
-                            help='Path of CA SSL certificate(s) used to verify'
-                            ' the remote server certificate. Without this '
+        parser.add_argument('--os-cacert',
+                            metavar='<ca-certificate-file>',
+                            dest='os_cacert',
+                            default=utils.env('OS_CACERT'),
+                            help='Path of CA TLS certificate(s) used to verify'
+                            'the remote server\'s certificate. Without this '
                             'option ceilometer looks for the default system '
                             'CA certificates.')
+        parser.add_argument('--ca-file',
+                            dest='os_cacert',
+                            help='DEPRECATED! Use --os-cacert.')
 
         parser.add_argument('--timeout',
                             default=600,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/tests/test_utils.py
 new/python-ceilometerclient-1.0.6/ceilometerclient/tests/test_utils.py
--- 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/tests/test_utils.py
   2013-09-30 18:21:46.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/ceilometerclient/tests/test_utils.py      
2013-10-04 09:58:25.000000000 +0200
@@ -93,3 +93,34 @@
             pass
         _, args = not_required_default.__dict__['arguments'][0]
         self.assertEqual(args['help'], "not_required_default. Defaults to 42.")
+
+    def test_merge_nested_dict(self):
+        dest = {'key': 'value',
+                'nested': {'key2': 'value2',
+                           'key3': 'value3',
+                           'nested2': {'key': 'value',
+                                       'some': 'thing'}}}
+        source = {'key': 'modified',
+                  'nested': {'key3': 'modified3',
+                             'nested2': {'key5': 'value5'}}}
+        utils.merge_nested_dict(dest, source, depth=1)
+
+        self.assertEqual(dest, {'key': 'modified',
+                                'nested': {'key2': 'value2',
+                                           'key3': 'modified3',
+                                           'nested2': {'key5': 'value5'}}})
+
+    def test_merge_nested_dict_no_depth(self):
+        dest = {'key': 'value',
+                'nested': {'key2': 'value2',
+                           'key3': 'value3',
+                           'nested2': {'key': 'value',
+                                       'some': 'thing'}}}
+        source = {'key': 'modified',
+                  'nested': {'key3': 'modified3',
+                             'nested2': {'key5': 'value5'}}}
+        utils.merge_nested_dict(dest, source)
+
+        self.assertEqual(dest, {'key': 'modified',
+                                'nested': {'key3': 'modified3',
+                                           'nested2': {'key5': 'value5'}}})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/tests/v2/test_alarms.py
 new/python-ceilometerclient-1.0.6/ceilometerclient/tests/v2/test_alarms.py
--- 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/tests/v2/test_alarms.py
       2013-09-30 18:21:46.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/ceilometerclient/tests/v2/test_alarms.py  
2013-10-04 09:58:25.000000000 +0200
@@ -20,7 +20,7 @@
 import testtools
 
 from ceilometerclient.tests import utils
-import ceilometerclient.v2.alarms
+from ceilometerclient.v2 import alarms
 
 AN_ALARM = {u'alarm_actions': [u'http://site:8000/alarm'],
             u'ok_actions': [u'http://site:8000/ok'],
@@ -61,6 +61,7 @@
 UPDATED_ALARM = copy.deepcopy(AN_ALARM)
 UPDATED_ALARM.update(DELTA_ALARM)
 UPDATED_ALARM['threshold_rule'].update(DELTA_ALARM_RULE)
+DELTA_ALARM['threshold_rule'] = DELTA_ALARM_RULE
 UPDATE_ALARM = copy.deepcopy(UPDATED_ALARM)
 del UPDATE_ALARM['user_id']
 del UPDATE_ALARM['project_id']
@@ -107,6 +108,47 @@
 del UPDATE_LEGACY_ALARM['timestamp']
 del UPDATE_LEGACY_ALARM['state_timestamp']
 
+FULL_DETAIL = ('{"alarm_actions": [], '
+               '"user_id": "8185aa72421a4fd396d4122cba50e1b5", '
+               '"name": "scombo", '
+               '"timestamp": "2013-10-03T08:58:33.647912", '
+               '"enabled": true, '
+               '"state_timestamp": "2013-10-03T08:58:33.647912", '
+               '"rule": {"operator": "or", "alarm_ids": '
+               '["062cc907-3a9f-4867-ab3b-fa83212b39f7"]}, '
+               '"alarm_id": "alarm-id, '
+               '"state": "insufficient data", '
+               '"insufficient_data_actions": [], '
+               '"repeat_actions": false, '
+               '"ok_actions": [], '
+               '"project_id": "57d04f24d0824b78b1ea9bcecedbda8f", '
+               '"type": "combination", '
+               '"description": "Combined state of alarms '
+               '062cc907-3a9f-4867-ab3b-fa83212b39f7"}')
+ALARM_HISTORY = [{'on_behalf_of': '57d04f24d0824b78b1ea9bcecedbda8f',
+                  'user_id': '8185aa72421a4fd396d4122cba50e1b5',
+                  'event_id': 'c74a8611-6553-4764-a860-c15a6aabb5d0',
+                  'timestamp': '2013-10-03T08:59:28.326000',
+                  'detail': '{"state": "alarm"}',
+                  'alarm_id': 'alarm-id',
+                  'project_id': '57d04f24d0824b78b1ea9bcecedbda8f',
+                  'type': 'state transition'},
+                 {'on_behalf_of': '57d04f24d0824b78b1ea9bcecedbda8f',
+                  'user_id': '8185aa72421a4fd396d4122cba50e1b5',
+                  'event_id': 'c74a8611-6553-4764-a860-c15a6aabb5d0',
+                  'timestamp': '2013-10-03T08:59:28.326000',
+                  'detail': '{"description": "combination of one"}',
+                  'alarm_id': 'alarm-id',
+                  'project_id': '57d04f24d0824b78b1ea9bcecedbda8f',
+                  'type': 'rule change'},
+                 {'on_behalf_of': '57d04f24d0824b78b1ea9bcecedbda8f',
+                  'user_id': '8185aa72421a4fd396d4122cba50e1b5',
+                  'event_id': '4fd7df9e-190d-4471-8884-dc5a33d5d4bb',
+                  'timestamp': '2013-10-03T08:58:33.647000',
+                  'detail': FULL_DETAIL,
+                  'alarm_id': 'alarm-id',
+                  'project_id': '57d04f24d0824b78b1ea9bcecedbda8f',
+                  'type': 'creation'}]
 
 fixtures = {
     '/v2/alarms':
@@ -158,6 +200,20 @@
             None,
         ),
     },
+    '/v2/alarms/alarm-id/history':
+    {
+        'GET': (
+            {},
+            ALARM_HISTORY,
+        ),
+    },
+    '/v2/alarms/alarm-id/history?q.op=&q.value=NOW&q.field=timestamp':
+    {
+        'GET': (
+            {},
+            ALARM_HISTORY,
+        ),
+    },
 }
 
 
@@ -166,7 +222,7 @@
     def setUp(self):
         super(AlarmManagerTest, self).setUp()
         self.api = utils.FakeAPI(fixtures)
-        self.mgr = ceilometerclient.v2.alarms.AlarmManager(self.api)
+        self.mgr = alarms.AlarmManager(self.api)
 
     def test_list_all(self):
         alarms = list(self.mgr.list())
@@ -215,7 +271,20 @@
     def test_update(self):
         alarm = self.mgr.update(alarm_id='alarm-id', **UPDATE_ALARM)
         expect = [
-            ('PUT', '/v2/alarms/alarm-id', {}, UPDATE_ALARM),
+            ('GET', '/v2/alarms/alarm-id', {}, None),
+            ('PUT', '/v2/alarms/alarm-id', {}, UPDATED_ALARM),
+        ]
+        self.assertEqual(self.api.calls, expect)
+        self.assertTrue(alarm)
+        self.assertEqual(alarm.alarm_id, 'alarm-id')
+        for (key, value) in UPDATED_ALARM.iteritems():
+            self.assertEqual(getattr(alarm, key), value)
+
+    def test_update_delta(self):
+        alarm = self.mgr.update(alarm_id='alarm-id', **DELTA_ALARM)
+        expect = [
+            ('GET', '/v2/alarms/alarm-id', {}, None),
+            ('PUT', '/v2/alarms/alarm-id', {}, UPDATED_ALARM),
         ]
         self.assertEqual(self.api.calls, expect)
         self.assertTrue(alarm)
@@ -247,13 +316,33 @@
         self.assertEqual(self.api.calls, expect)
         self.assertTrue(deleted is None)
 
+    def _do_test_get_history(self, q, url):
+        history = self.mgr.get_history(q=q, alarm_id='alarm-id')
+        expect = [('GET', url, {}, None)]
+        self.assertEqual(self.api.calls, expect)
+        for i in xrange(len(history)):
+            change = history[i]
+            self.assertTrue(isinstance(change, alarms.AlarmChange))
+            for k, v in ALARM_HISTORY[i].iteritems():
+                self.assertEqual(getattr(change, k), v)
+
+    def test_get_all_history(self):
+        url = '/v2/alarms/alarm-id/history'
+        self._do_test_get_history(None, url)
+
+    def test_get_constrained_history(self):
+        q = [dict(field='timestamp', value='NOW')]
+        url = ('/v2/alarms/alarm-id/history'
+               '?q.op=&q.value=NOW&q.field=timestamp')
+        self._do_test_get_history(q, url)
+
 
 class AlarmLegacyManagerTest(testtools.TestCase):
 
     def setUp(self):
         super(AlarmLegacyManagerTest, self).setUp()
         self.api = utils.FakeAPI(fixtures)
-        self.mgr = ceilometerclient.v2.alarms.AlarmManager(self.api)
+        self.mgr = alarms.AlarmManager(self.api)
 
     def test_create(self):
         alarm = self.mgr.create(**CREATE_LEGACY_ALARM)
@@ -276,9 +365,10 @@
         self.assertTrue(alarm)
 
     def test_update(self):
-        alarm = self.mgr.update(alarm_id='alarm-id', **UPDATE_LEGACY_ALARM)
+        alarm = self.mgr.update(alarm_id='alarm-id', **DELTA_LEGACY_ALARM)
         expect = [
-            ('PUT', '/v2/alarms/alarm-id', {}, UPDATE_ALARM),
+            ('GET', '/v2/alarms/alarm-id', {}, None),
+            ('PUT', '/v2/alarms/alarm-id', {}, UPDATED_ALARM),
         ]
         self.assertEqual(self.api.calls, expect)
         self.assertTrue(alarm)
@@ -293,7 +383,8 @@
         del updated['meter_name']
         alarm = self.mgr.update(alarm_id='alarm-id', **updated)
         expect = [
-            ('PUT', '/v2/alarms/alarm-id', {}, UPDATE_ALARM),
+            ('GET', '/v2/alarms/alarm-id', {}, None),
+            ('PUT', '/v2/alarms/alarm-id', {}, UPDATED_ALARM),
         ]
         self.assertEqual(self.api.calls, expect)
         self.assertTrue(alarm)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/tests/v2/test_shell.py
 new/python-ceilometerclient-1.0.6/ceilometerclient/tests/v2/test_shell.py
--- 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/tests/v2/test_shell.py
        1970-01-01 01:00:00.000000000 +0100
+++ new/python-ceilometerclient-1.0.6/ceilometerclient/tests/v2/test_shell.py   
2013-10-04 09:58:25.000000000 +0200
@@ -0,0 +1,137 @@
+#   Licensed under the Apache License, Version 2.0 (the "License"); you may
+#   not use this file except in compliance with the License. You may obtain
+#   a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#   License for the specific language governing permissions and limitations
+#   under the License.
+
+import cStringIO
+import mock
+import re
+import sys
+
+from testtools import matchers
+
+from ceilometerclient.tests import utils
+from ceilometerclient.v2 import alarms
+from ceilometerclient.v2 import shell as ceilometer_shell
+
+
+class ShellAlarmStateCommandsTest(utils.BaseTestCase):
+
+    ALARM_ID = 'foobar'
+
+    def setUp(self):
+        super(ShellAlarmStateCommandsTest, self).setUp()
+        self.cc = mock.Mock()
+        self.cc.alarms = mock.Mock()
+        self.args = mock.Mock()
+        self.args.alarm_id = self.ALARM_ID
+
+    def test_alarm_state_get(self):
+        ceilometer_shell.do_alarm_state_get(self.cc, self.args)
+        self.cc.alarms.get_state.assert_called_once_with(self.ALARM_ID)
+        self.assertFalse(self.cc.alarms.set_state.called)
+
+    def test_alarm_state_set(self):
+        self.args.state = 'ok'
+        ceilometer_shell.do_alarm_state_set(self.cc, self.args)
+        self.cc.alarms.set_state.assert_called_once_with(self.ALARM_ID, 'ok')
+        self.assertFalse(self.cc.alarms.get_state.called)
+
+
+class ShellAlarmHistoryCommandTest(utils.BaseTestCase):
+
+    ALARM_ID = '768ff714-8cfb-4db9-9753-d484cb33a1cc'
+    FULL_DETAIL = ('{"alarm_actions": [], '
+                   '"user_id": "8185aa72421a4fd396d4122cba50e1b5", '
+                   '"name": "scombo", '
+                   '"timestamp": "2013-10-03T08:58:33.647912", '
+                   '"enabled": true, '
+                   '"state_timestamp": "2013-10-03T08:58:33.647912", '
+                   '"rule": {"operator": "or", "alarm_ids": '
+                   '["062cc907-3a9f-4867-ab3b-fa83212b39f7"]}, '
+                   '"alarm_id": "768ff714-8cfb-4db9-9753-d484cb33a1cc", '
+                   '"state": "insufficient data", '
+                   '"insufficient_data_actions": [], '
+                   '"repeat_actions": false, '
+                   '"ok_actions": [], '
+                   '"project_id": "57d04f24d0824b78b1ea9bcecedbda8f", '
+                   '"type": "combination", '
+                   '"description": "Combined state of alarms '
+                   '062cc907-3a9f-4867-ab3b-fa83212b39f7"}')
+    ALARM_HISTORY = [{'on_behalf_of': '57d04f24d0824b78b1ea9bcecedbda8f',
+                      'user_id': '8185aa72421a4fd396d4122cba50e1b5',
+                      'event_id': 'c74a8611-6553-4764-a860-c15a6aabb5d0',
+                      'timestamp': '2013-10-03T08:59:28.326000',
+                      'detail': '{"state": "alarm"}',
+                      'alarm_id': '768ff714-8cfb-4db9-9753-d484cb33a1cc',
+                      'project_id': '57d04f24d0824b78b1ea9bcecedbda8f',
+                      'type': 'state transition'},
+                     {'on_behalf_of': '57d04f24d0824b78b1ea9bcecedbda8f',
+                      'user_id': '8185aa72421a4fd396d4122cba50e1b5',
+                      'event_id': 'c74a8611-6553-4764-a860-c15a6aabb5d0',
+                      'timestamp': '2013-10-03T08:59:28.326000',
+                      'detail': '{"description": "combination of one"}',
+                      'alarm_id': '768ff714-8cfb-4db9-9753-d484cb33a1cc',
+                      'project_id': '57d04f24d0824b78b1ea9bcecedbda8f',
+                      'type': 'rule change'},
+                     {'on_behalf_of': '57d04f24d0824b78b1ea9bcecedbda8f',
+                      'user_id': '8185aa72421a4fd396d4122cba50e1b5',
+                      'event_id': '4fd7df9e-190d-4471-8884-dc5a33d5d4bb',
+                      'timestamp': '2013-10-03T08:58:33.647000',
+                      'detail': FULL_DETAIL,
+                      'alarm_id': '768ff714-8cfb-4db9-9753-d484cb33a1cc',
+                      'project_id': '57d04f24d0824b78b1ea9bcecedbda8f',
+                      'type': 'creation'}]
+    TIMESTAMP_RE = (' +\| (\d{4})-(\d{2})-(\d{2})T'
+                    '(\d{2})\:(\d{2})\:(\d{2})\.(\d{6}) \| +')
+
+    def setUp(self):
+        super(ShellAlarmHistoryCommandTest, self).setUp()
+        self.cc = mock.Mock()
+        self.cc.alarms = mock.Mock()
+        self.args = mock.Mock()
+        self.args.alarm_id = self.ALARM_ID
+
+    def _do_test_alarm_history(self, raw_query=None, parsed_query=None):
+        self.args.query = raw_query
+        orig = sys.stdout
+        sys.stdout = cStringIO.StringIO()
+        history = [alarms.AlarmChange(mock.Mock(), change)
+                   for change in self.ALARM_HISTORY]
+        self.cc.alarms.get_history.return_value = history
+
+        try:
+            ceilometer_shell.do_alarm_history(self.cc, self.args)
+            self.cc.alarms.get_history.assert_called_once_with(
+                q=parsed_query,
+                alarm_id=self.ALARM_ID
+            )
+            out = sys.stdout.getvalue()
+            required = [
+                '.*creation%sname: scombo.*' % self.TIMESTAMP_RE,
+                '.*rule change%sdescription: combination of one.*' %
+                self.TIMESTAMP_RE,
+                '.*state transition%sstate: alarm.*' % self.TIMESTAMP_RE,
+            ]
+            for r in required:
+                self.assertThat(out, matchers.MatchesRegex(r, re.DOTALL))
+        finally:
+            sys.stdout.close()
+            sys.stdout = orig
+
+    def test_alarm_all_history(self):
+        self._do_test_alarm_history()
+
+    def test_alarm_constrained_history(self):
+        parsed_query = [dict(field='timestamp',
+                             value='2013-10-03T08:59:28',
+                             op='gt')]
+        self._do_test_alarm_history(raw_query='timestamp>2013-10-03T08:59:28',
+                                    parsed_query=parsed_query)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/v2/alarms.py 
new/python-ceilometerclient-1.0.6/ceilometerclient/v2/alarms.py
--- old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/v2/alarms.py  
2013-09-30 18:21:46.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/ceilometerclient/v2/alarms.py     
2013-10-04 09:58:25.000000000 +0200
@@ -19,6 +19,7 @@
 import warnings
 
 from ceilometerclient.common import base
+from ceilometerclient.common import utils
 from ceilometerclient.v2 import options
 
 
@@ -34,7 +35,7 @@
     'repeat_actions',
     'threshold_rule',
     'combination_rule',
-    ]
+]
 CREATION_ATTRIBUTES = UPDATABLE_ATTRIBUTES + ['project_id', 'user_id']
 
 
@@ -50,6 +51,14 @@
         return super(Alarm, self).__getattr__(k)
 
 
+class AlarmChange(base.Resource):
+    def __repr__(self):
+        return "<AlarmChange %s>" % self._info
+
+    def __getattr__(self, k):
+        return super(AlarmChange, self).__getattr__(k)
+
+
 class AlarmManager(base.Manager):
     resource_class = Alarm
 
@@ -67,12 +76,12 @@
             return None
 
     @classmethod
-    def _compat_legacy_alarm_kwargs(cls, kwargs):
-        cls._compat_counter_rename_kwargs(kwargs)
-        cls._compat_alarm_before_rule_type_kwargs(kwargs)
+    def _compat_legacy_alarm_kwargs(cls, kwargs, create=False):
+        cls._compat_counter_rename_kwargs(kwargs, create)
+        cls._compat_alarm_before_rule_type_kwargs(kwargs, create)
 
     @staticmethod
-    def _compat_counter_rename_kwargs(kwargs):
+    def _compat_counter_rename_kwargs(kwargs, create=False):
         # NOTE(jd) Compatibility with Havana-2 API
         if 'counter_name' in kwargs:
             warnings.warn("counter_name has been renamed to meter_name",
@@ -80,40 +89,40 @@
             kwargs['meter_name'] = kwargs['counter_name']
 
     @staticmethod
-    def _compat_alarm_before_rule_type_kwargs(kwargs):
+    def _compat_alarm_before_rule_type_kwargs(kwargs, create=False):
         # NOTE(sileht) Compatibility with Havana-3 API
-        if kwargs.get('type'):
-            return
-        warnings.warn("alarm without type set is deprecated",
-                      DeprecationWarning)
+        if create and 'type' not in kwargs:
+            warnings.warn("alarm without type set is deprecated",
+                          DeprecationWarning)
+            kwargs['type'] = 'threshold'
 
-        kwargs['type'] = 'threshold'
-        kwargs['threshold_rule'] = {}
         for field in ['period', 'evaluation_periods', 'threshold',
                       'statistic', 'comparison_operator', 'meter_name']:
             if field in kwargs:
-                kwargs['threshold_rule'][field] = kwargs[field]
+                kwargs.setdefault('threshold_rule', {})[field] = kwargs[field]
                 del kwargs[field]
 
-        query = []
         if 'matching_metadata' in kwargs:
+            query = []
             for key in kwargs['matching_metadata']:
                 query.append({'field': key,
                               'op': 'eq',
                               'value': kwargs['matching_metadata'][key]})
             del kwargs['matching_metadata']
-        kwargs['threshold_rule']['query'] = query
+            kwargs['threshold_rule']['query'] = query
 
     def create(self, **kwargs):
-        self._compat_legacy_alarm_kwargs(kwargs)
+        self._compat_legacy_alarm_kwargs(kwargs, create=True)
         new = dict((key, value) for (key, value) in kwargs.items()
                    if key in CREATION_ATTRIBUTES)
         return self._create(self._path(), new)
 
     def update(self, alarm_id, **kwargs):
         self._compat_legacy_alarm_kwargs(kwargs)
-        updated = dict((key, value) for (key, value) in kwargs.items()
-                       if key in UPDATABLE_ATTRIBUTES)
+        updated = self.get(alarm_id).to_dict()
+        kwargs = dict((k, v) for k, v in kwargs.items()
+                      if k in updated and k in UPDATABLE_ATTRIBUTES)
+        utils.merge_nested_dict(updated, kwargs, depth=1)
         return self._update(self._path(alarm_id), updated)
 
     def delete(self, alarm_id):
@@ -129,3 +138,8 @@
         resp, body = self.api.json_request('GET',
                                            "%s/state" % self._path(alarm_id))
         return body
+
+    def get_history(self, alarm_id, q=None):
+        path = '%s/history' % self._path(alarm_id)
+        url = options.build_url(path, q)
+        return self._list(url, obj_class=AlarmChange)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/v2/shell.py 
new/python-ceilometerclient-1.0.6/ceilometerclient/v2/shell.py
--- old/python-ceilometerclient-1.0.5.2.gb961738/ceilometerclient/v2/shell.py   
2013-09-30 18:21:46.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/ceilometerclient/v2/shell.py      
2013-10-04 09:58:25.000000000 +0200
@@ -127,26 +127,63 @@
                      sortby=0)
 
 
-def alarm_rule_formatter(alarm):
-    if alarm.type == 'threshold':
+def _display_rule(type, rule):
+    if type == 'threshold':
         return ('%(meter_name)s %(comparison_operator)s '
                 '%(threshold)s during %(evaluation_periods)s x %(period)ss' %
                 {
-                    'meter_name': alarm.rule['meter_name'],
-                    'threshold': alarm.rule['threshold'],
-                    'evaluation_periods': alarm.rule['evaluation_periods'],
-                    'period': alarm.rule['period'],
+                    'meter_name': rule['meter_name'],
+                    'threshold': rule['threshold'],
+                    'evaluation_periods': rule['evaluation_periods'],
+                    'period': rule['period'],
                     'comparison_operator': OPERATORS_STRING.get(
-                        alarm.rule['comparison_operator'])
+                        rule['comparison_operator'])
                 })
-    elif alarm.type == 'combination':
+    elif type == 'combination':
         return ('combinated states (%(operator)s) of %(alarms)s' % {
-            'operator': alarm.rule['operator'].upper(),
-            'alarms': ", ".join(alarm.rule['alarm_ids'])})
+            'operator': rule['operator'].upper(),
+            'alarms': ", ".join(rule['alarm_ids'])})
     else:
         # just dump all
         return "\n".join(["%s: %s" % (f, v)
-                          for f, v in alarm.rule.iteritems()])
+                          for f, v in rule.iteritems()])
+
+
+def alarm_rule_formatter(alarm):
+    return _display_rule(alarm.type, alarm.rule)
+
+
+def _infer_type(detail):
+    if 'type' in detail:
+        return detail['type']
+    elif 'meter_name' in detail['rule']:
+        return 'threshold'
+    elif 'alarms' in detail['rule']:
+        return 'combination'
+    else:
+        return 'unknown'
+
+
+def alarm_change_detail_formatter(change):
+    detail = json.loads(change.detail)
+    fields = []
+    if change.type == 'state transition':
+        fields.append('state: %s' % detail['state'])
+    elif change.type == 'creation' or change.type == 'deletion':
+        for k in ['name', 'description', 'type', 'rule']:
+            if k == 'rule':
+                fields.append('rule: %s' % _display_rule(detail['type'],
+                                                         detail[k]))
+            else:
+                fields.append('%s: %s' % (k, detail[k]))
+    elif change.type == 'rule change':
+        for k, v in detail.iteritems():
+            if k == 'rule':
+                fields.append('rule: %s' % _display_rule(_infer_type(detail),
+                                                         v))
+            else:
+                fields.append('%s: %s' % (k, v))
+    return '\n'.join(fields)
 
 
 @utils.arg('-q', '--query', metavar='<QUERY>',
@@ -196,45 +233,49 @@
         _display_alarm(alarm)
 
 
-def common_alarm_arguments(func):
-    @utils.arg('--name', metavar='<NAME>', required=True,
-               help='Name of the alarm (must be unique per tenant)')
-    @utils.arg('--project-id', metavar='<PROJECT_ID>',
-               help='Tenant to associate with alarm '
-               '(only settable by admin users)')
-    @utils.arg('--user-id', metavar='<USER_ID>',
-               help='User to associate with alarm '
-               '(only settable by admin users)')
-    @utils.arg('--description', metavar='<DESCRIPTION>',
-               help='Free text description of the alarm')
-    @utils.arg('--state', metavar='<STATE>',
-               help='State of the alarm, one of: ' + str(ALARM_STATES))
-    @utils.arg('--enabled', type=utils.string_to_bool, metavar='{True|False}',
-               help='True if alarm evaluation/actioning is enabled')
-    @utils.arg('--alarm-action', dest='alarm_actions',
-               metavar='<Webhook URL>', action='append', default=None,
-               help=('URL to invoke when state transitions to alarm. '
-                     'May be used multiple times.'))
-    @utils.arg('--ok-action', dest='ok_actions',
-               metavar='<Webhook URL>', action='append', default=None,
-               help=('URL to invoke when state transitions to OK. '
-                     'May be used multiple times.'))
-    @utils.arg('--insufficient-data-action', dest='insufficient_data_actions',
-               metavar='<Webhook URL>', action='append', default=None,
-               help=('URL to invoke when state transitions to unkown. '
-                     'May be used multiple times.'))
-    @utils.arg('--repeat-actions', dest='repeat_actions',
-               metavar='{True|False}', type=utils.string_to_bool,
-               default=False,
-               help=('True if actions should be repeatedly notified '
-                     'while alarm remains in target state'))
-    @functools.wraps(func)
-    def _wrapper(*args, **kwargs):
-        return func(*args, **kwargs)
+def common_alarm_arguments(create=False):
+    def _wrapper(func):
+        @utils.arg('--name', metavar='<NAME>', required=create,
+                   help='Name of the alarm (must be unique per tenant)')
+        @utils.arg('--project-id', metavar='<PROJECT_ID>',
+                   help='Tenant to associate with alarm '
+                   '(only settable by admin users)')
+        @utils.arg('--user-id', metavar='<USER_ID>',
+                   help='User to associate with alarm '
+                   '(only settable by admin users)')
+        @utils.arg('--description', metavar='<DESCRIPTION>',
+                   help='Free text description of the alarm')
+        @utils.arg('--state', metavar='<STATE>',
+                   help='State of the alarm, one of: ' + str(ALARM_STATES))
+        @utils.arg('--enabled', type=utils.string_to_bool,
+                   metavar='{True|False}',
+                   help='True if alarm evaluation/actioning is enabled')
+        @utils.arg('--alarm-action', dest='alarm_actions',
+                   metavar='<Webhook URL>', action='append', default=None,
+                   help=('URL to invoke when state transitions to alarm. '
+                         'May be used multiple times.'))
+        @utils.arg('--ok-action', dest='ok_actions',
+                   metavar='<Webhook URL>', action='append', default=None,
+                   help=('URL to invoke when state transitions to OK. '
+                         'May be used multiple times.'))
+        @utils.arg('--insufficient-data-action',
+                   dest='insufficient_data_actions',
+                   metavar='<Webhook URL>', action='append', default=None,
+                   help=('URL to invoke when state transitions to unkown. '
+                         'May be used multiple times.'))
+        @utils.arg('--repeat-actions', dest='repeat_actions',
+                   metavar='{True|False}', type=utils.string_to_bool,
+                   default=False,
+                   help=('True if actions should be repeatedly notified '
+                         'while alarm remains in target state'))
+        @functools.wraps(func)
+        def _wrapped(*args, **kwargs):
+            return func(*args, **kwargs)
+        return _wrapped
     return _wrapper
 
 
-@common_alarm_arguments
+@common_alarm_arguments(create=True)
 @utils.arg('--period', type=int, metavar='<PERIOD>',
            help='Length of each period (seconds) to evaluate over')
 @utils.arg('--evaluation-periods', type=int, metavar='<COUNT>',
@@ -259,7 +300,7 @@
     _display_alarm(alarm)
 
 
-@common_alarm_arguments
+@common_alarm_arguments(create=True)
 @utils.arg('--meter-name', metavar='<METRIC>', required=True,
            dest='threshold_rule/meter_name',
            help='Metric to evaluate against')
@@ -294,7 +335,7 @@
     _display_alarm(alarm)
 
 
-@common_alarm_arguments
+@common_alarm_arguments(create=True)
 @utils.arg('--alarm_ids', action='append', metavar='<ALARM IDS>',
            required=True, dest='combination_rule/alarm_ids',
            help='List of alarm id')
@@ -313,18 +354,18 @@
 
 @utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
            help='ID of the alarm to update.')
-@common_alarm_arguments
+@common_alarm_arguments()
 @utils.arg('--period', type=int, metavar='<PERIOD>',
            help='Length of each period (seconds) to evaluate over')
 @utils.arg('--evaluation-periods', type=int, metavar='<COUNT>',
            help='Number of periods to evaluate over')
[email protected]('--meter-name', metavar='<METRIC>', required=True,
[email protected]('--meter-name', metavar='<METRIC>',
            help='Metric to evaluate against')
 @utils.arg('--statistic', metavar='<STATISTIC>',
            help='Statistic to evaluate, one of: ' + str(STATISTICS))
 @utils.arg('--comparison-operator', metavar='<OPERATOR>',
            help='Operator to compare with, one of: ' + str(ALARM_OPERATORS))
[email protected]('--threshold', type=float, metavar='<THRESHOLD>', required=True,
[email protected]('--threshold', type=float, metavar='<THRESHOLD>',
            help='Threshold to evaluate against')
 @utils.arg('--matching-metadata', dest='matching_metadata',
            metavar='<Matching Metadata>', action='append', default=None,
@@ -344,9 +385,9 @@
 
 @utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
            help='ID of the alarm to update.')
-@common_alarm_arguments
+@common_alarm_arguments()
 @utils.arg('--meter-name', metavar='<METRIC>',
-           dest='threshold_rule/meter_name', required=True,
+           dest='threshold_rule/meter_name',
            help='Metric to evaluate against')
 @utils.arg('--period', type=int, metavar='<PERIOD>',
            dest='threshold_rule/period',
@@ -360,7 +401,7 @@
 @utils.arg('--comparison-operator', metavar='<OPERATOR>',
            dest='threshold_rule/comparison_operator',
            help='Operator to compare with, one of: ' + str(ALARM_OPERATORS))
[email protected]('--threshold', type=float, metavar='<THRESHOLD>', required=True,
[email protected]('--threshold', type=float, metavar='<THRESHOLD>',
            dest='threshold_rule/threshold',
            help='Threshold to evaluate against')
 @utils.arg('-q', '--query', metavar='<QUERY>',
@@ -385,9 +426,9 @@
 
 @utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
            help='ID of the alarm to update.')
-@common_alarm_arguments
+@common_alarm_arguments()
 @utils.arg('--alarm_ids', action='append', metavar='<ALARM IDS>',
-           dest='combination_rule/alarm_ids', required=True,
+           dest='combination_rule/alarm_ids',
            help='List of alarm id')
 @utils.arg('---operator', metavar='<OPERATOR>',
            dest='combination_rule/operator',
@@ -420,28 +461,45 @@
            help='ID of the alarm state to set.')
 @utils.arg('--state', metavar='<STATE>', required=True,
            help='State of the alarm, one of: ' + str(ALARM_STATES))
-def do_alarm_set_state(cc, args={}):
+def do_alarm_state_set(cc, args={}):
     '''Set the state of an alarm.'''
     try:
-        cc.alarms.set_state(args.alarm_id, args.state)
+        state = cc.alarms.set_state(args.alarm_id, args.state)
     except exc.HTTPNotFound:
         raise exc.CommandError('Alarm not found: %s' % args.alarm_id)
-    state = cc.alarms.get_state(args.alarm_id)
     utils.print_dict({'state': state}, wrap=72)
 
 
 @utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
            help='ID of the alarm state to show.')
-def do_alarm_get_state(cc, args={}):
+def do_alarm_state_get(cc, args={}):
     '''Get the state of an alarm.'''
     try:
-        cc.alarms.set_state(args.alarm_id, args.state)
+        state = cc.alarms.get_state(args.alarm_id)
     except exc.HTTPNotFound:
         raise exc.CommandError('Alarm not found: %s' % args.alarm_id)
-    state = cc.alarms.get_state(args.alarm_id)
     utils.print_dict({'state': state}, wrap=72)
 
 
[email protected]('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
+           help='ID of the alarm for which history is shown.')
[email protected]('-q', '--query', metavar='<QUERY>',
+           help='key[op]value; list.')
+def do_alarm_history(cc, args={}):
+    '''Display the change history of an alarm.'''
+    kwargs = dict(alarm_id=args.alarm_id,
+                  q=options.cli_to_array(args.query))
+    try:
+        history = cc.alarms.get_history(**kwargs)
+    except exc.HTTPNotFound:
+        raise exc.CommandError('Alarm not found: %s' % args.alarm_id)
+    field_labels = ['Type', 'Timestamp', 'Detail']
+    fields = ['type', 'timestamp', 'detail']
+    utils.print_list(history, fields, field_labels,
+                     formatters={'detail': alarm_change_detail_formatter},
+                     sortby=1)
+
+
 @utils.arg('-q', '--query', metavar='<QUERY>',
            help='key[op]value; list.')
 def do_resource_list(cc, args={}):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/python_ceilometerclient.egg-info/PKG-INFO
 new/python-ceilometerclient-1.0.6/python_ceilometerclient.egg-info/PKG-INFO
--- 
old/python-ceilometerclient-1.0.5.2.gb961738/python_ceilometerclient.egg-info/PKG-INFO
      2013-09-30 18:22:39.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/python_ceilometerclient.egg-info/PKG-INFO 
2013-10-04 09:58:49.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: python-ceilometerclient
-Version: 1.0.5.2.gb961738
+Version: 1.0.6
 Summary: OpenStack Metering API Client Library
 Home-page: http://www.openstack.org/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/python_ceilometerclient.egg-info/SOURCES.txt
 new/python-ceilometerclient-1.0.6/python_ceilometerclient.egg-info/SOURCES.txt
--- 
old/python-ceilometerclient-1.0.5.2.gb961738/python_ceilometerclient.egg-info/SOURCES.txt
   2013-09-30 18:22:40.000000000 +0200
+++ 
new/python-ceilometerclient-1.0.6/python_ceilometerclient.egg-info/SOURCES.txt  
    2013-10-04 09:58:49.000000000 +0200
@@ -39,6 +39,7 @@
 ceilometerclient/tests/v2/test_options.py
 ceilometerclient/tests/v2/test_resources.py
 ceilometerclient/tests/v2/test_samples.py
+ceilometerclient/tests/v2/test_shell.py
 ceilometerclient/tests/v2/test_statistics.py
 ceilometerclient/v1/__init__.py
 ceilometerclient/v1/client.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-ceilometerclient-1.0.5.2.gb961738/setup.py 
new/python-ceilometerclient-1.0.6/setup.py
--- old/python-ceilometerclient-1.0.5.2.gb961738/setup.py       2013-09-30 
18:21:46.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/setup.py  2013-10-04 09:58:25.000000000 
+0200
@@ -18,5 +18,5 @@
 import setuptools
 
 setuptools.setup(
-    setup_requires=['pbr>=0.5.21,<1.0'],
+    setup_requires=['pbr'],
     pbr=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-ceilometerclient-1.0.5.2.gb961738/test-requirements.txt 
new/python-ceilometerclient-1.0.6/test-requirements.txt
--- old/python-ceilometerclient-1.0.5.2.gb961738/test-requirements.txt  
2013-09-30 18:21:46.000000000 +0200
+++ new/python-ceilometerclient-1.0.6/test-requirements.txt     2013-10-04 
09:58:25.000000000 +0200
@@ -6,6 +6,7 @@
 coverage>=3.6
 discover
 fixtures>=0.3.14
+mock>=1.0
 mox>=0.5.3
 python-subunit
 sphinx>=1.1.2

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to