diff --git a/actions/actions.py b/actions/actions.py
index 88d5f52ece657287f65234fb4e7b22aed107ca1c..3234e67057c20dfb2ffd1d8e0e93008b832c32b0 100755
--- a/actions/actions.py
+++ b/actions/actions.py
@@ -22,6 +22,7 @@ from charmhelpers.core.hookenv import (
     action_set,
 )
 from ceilometer_utils import (
+    assess_status,
     ceilometer_upgrade_helper,
     pause_unit_helper,
     register_configs,
@@ -59,6 +60,7 @@ def ceilometer_upgrade(args):
         if e.trace:
             action_set({'traceback': e.trace})
         raise Exception(str(e.message))
+    assess_status(register_configs())
 
 
 # A dictionary of all the defined actions to callables (which take
diff --git a/charmhelpers/contrib/openstack/utils.py b/charmhelpers/contrib/openstack/utils.py
index 4e432a25bd2e00ab4bf5fa9ba6d05457fce99c7b..1d1f8641e4dcf0ba85d55ca93534d5753bf0d8bd 100644
--- a/charmhelpers/contrib/openstack/utils.py
+++ b/charmhelpers/contrib/openstack/utils.py
@@ -83,7 +83,8 @@ from charmhelpers.fetch import (
     add_source as fetch_add_source,
     SourceConfigError,
     GPGKeyError,
-    get_upstream_version
+    get_upstream_version,
+    filter_missing_packages
 )
 
 from charmhelpers.fetch.snap import (
@@ -309,6 +310,15 @@ def error_out(msg):
     sys.exit(1)
 
 
+def get_installed_semantic_versioned_packages():
+    '''Get a list of installed packages which have OpenStack semantic versioning
+
+    :returns List of installed packages
+    :rtype: [pkg1, pkg2, ...]
+    '''
+    return filter_missing_packages(PACKAGE_CODENAMES.keys())
+
+
 def get_os_codename_install_source(src):
     '''Derive OpenStack release codename from a given installation source.'''
     ubuntu_rel = lsb_release()['DISTRIB_CODENAME']
@@ -972,7 +982,9 @@ def _ows_check_charm_func(state, message, charm_func_with_configs):
     """
     if charm_func_with_configs:
         charm_state, charm_message = charm_func_with_configs()
-        if charm_state != 'active' and charm_state != 'unknown':
+        if (charm_state != 'active' and
+                charm_state != 'unknown' and
+                charm_state is not None):
             state = workload_state_compare(state, charm_state)
             if message:
                 charm_message = charm_message.replace("Incomplete relations: ",
diff --git a/lib/ceilometer_utils.py b/lib/ceilometer_utils.py
index 838ffe87de7ebf825f5738afb81cb0ea29e38843..940cad2a3efe91fd4eb02953aa33a1af0392236b 100644
--- a/lib/ceilometer_utils.py
+++ b/lib/ceilometer_utils.py
@@ -19,6 +19,8 @@ import traceback
 
 from collections import OrderedDict
 
+from charmhelpers.core.unitdata import kv
+
 from charmhelpers.contrib.openstack import (
     templating,
     context,
@@ -75,6 +77,7 @@ POLLING_CONF = "%s/polling.yaml" % CEILOMETER_CONF_DIR
 CEILOMETER_API_SYSTEMD_CONF = (
     '/etc/systemd/system/ceilometer-api.service.d/override.conf'
 )
+CEILOMETER_UPGRADED = "ceilometer-upgrade-run"
 HTTPS_APACHE_CONF = "/etc/apache2/sites-available/openstack_https_frontend"
 HTTPS_APACHE_24_CONF = "/etc/apache2/sites-available/" \
     "openstack_https_frontend.conf"
@@ -545,6 +548,7 @@ def assess_status_func(configs):
     """
     return make_assess_status_func(
         configs, resolve_required_interfaces(),
+        charm_func=check_ceilometer_upgraded,
         services=services(), ports=determine_ports())
 
 
@@ -655,6 +659,10 @@ def ceilometer_upgrade_helper(CONFIGS):
                            'unexpected error: {}'.format(e.message),
                            outcome='ceilometer-upgrade failed, see traceback.',
                            trace=traceback.format_exc())
+    kvstore = kv()
+    if not kvstore.get(CEILOMETER_UPGRADED, False):
+        kvstore.set(key=CEILOMETER_UPGRADED, value=True)
+        kvstore.flush()
 
 
 def ceilometer_upgrade(action=False):
@@ -669,3 +677,25 @@ def ceilometer_upgrade(action=False):
         log("Running ceilomter-upgrade: {}".format(" ".join(cmd)), DEBUG)
         subprocess.check_call(cmd)
         log("ceilometer-upgrade succeeded", DEBUG)
+
+
+def check_ceilometer_upgraded(configs):
+    """Assess status check if ceilometer-upgrade action has run
+
+    When related to gnocchi check that the ceilometer-upgrade action has been
+    run. Set blocked when action run is still required. Set None None when no
+    action is required.
+
+    :param configs: The charms main OSConfigRenderer object.
+    :return: str, str tuple or None, None
+    """
+
+    if relation_ids("metric-service"):
+        kvstore = kv()
+        if not kvstore.get(CEILOMETER_UPGRADED, False):
+            log("Action ceilometer-upgrade not yet run, setting status "
+                "blocked")
+            return "blocked", ("Run the ceilometer-upgrade action to "
+                               "initialize ceilometer and gnocchi")
+    # Avoid changing status check
+    return None, None
diff --git a/tests/basic_deployment.py b/tests/basic_deployment.py
index 164d5aa8abbd367a70608526e63fb51d41311aa7..a2da927dd709a36c5fc68f7c53bfd2b4c956be5a 100644
--- a/tests/basic_deployment.py
+++ b/tests/basic_deployment.py
@@ -45,8 +45,12 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
         self._deploy()
 
         u.log.info('Waiting on extended status checks...')
-        exclude_services = ['mongodb', 'memcached']
-        self._auto_wait_for_status(exclude_services=exclude_services)
+        self.exclude_services = ['mongodb', 'memcached']
+        if self._get_openstack_release() >= self.xenial_pike:
+            # Ceilometer will come up blocked until the ceilometer-upgrade
+            # action is run
+            self.exclude_services.append("ceilometer")
+        self._auto_wait_for_status(exclude_services=self.exclude_services)
 
         self.d.sentry.wait()
         self._initialize_tests()
@@ -163,6 +167,7 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
         self.nova_sentry = self.d.sentry['nova-compute'][0]
         if self._get_openstack_release() >= self.xenial_pike:
             self.gnocchi_sentry = self.d.sentry['gnocchi'][0]
+            self.run_ceilometer_upgrade_action()
         else:
             self.mongodb_sentry = self.d.sentry['mongodb'][0]
         u.log.debug('openstack release val: {}'.format(
@@ -681,8 +686,13 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
         assert u.status_get(unit)[0] == "active"
         u.log.debug('OK')
 
-    def test_920_ceilometer_upgrade(self):
-        """Run ceilometer-upgrade"""
+    def run_ceilometer_upgrade_action(self):
+        """Run ceilometer-upgrade
+
+        This action will be run early to initialize ceilometer
+        when gnocchi is related.
+        Ceilometer will be in a blocked state until this runs.
+        """
         if self._get_openstack_release() < self.xenial_pike:
             u.log.debug('Not checking ceilometer-upgrade')
             return
@@ -691,4 +701,7 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
 
         action_id = unit.run_action("ceilometer-upgrade")
         assert u.wait_on_action(action_id), "ceilometer-upgrade action failed"
+        # Wait for acivte Unit is ready on ceilometer
+        self.exclude_services.remove('ceilometer')
+        self._auto_wait_for_status(exclude_services=self.exclude_services)
         u.log.debug('OK')
diff --git a/unit_tests/test_ceilometer_utils.py b/unit_tests/test_ceilometer_utils.py
index 26b6d49bf1bd31b31b8d51b06aa0ae9b1334f7a8..1c531a70246ec481fab4232f932c3fa5d1e0824e 100644
--- a/unit_tests/test_ceilometer_utils.py
+++ b/unit_tests/test_ceilometer_utils.py
@@ -270,6 +270,7 @@ class CeilometerUtilsTest(CharmTestCase):
                 utils.VERSION_PACKAGE
             )
 
+    @patch.object(utils, 'check_ceilometer_upgraded')
     @patch.object(utils, 'resolve_required_interfaces')
     @patch.object(utils, 'services')
     @patch.object(utils, 'determine_ports')
@@ -278,13 +279,16 @@ class CeilometerUtilsTest(CharmTestCase):
                                 make_assess_status_func,
                                 determine_ports,
                                 services,
-                                resolve_required_interfaces):
+                                resolve_required_interfaces,
+                                check_ceilometer_upgraded):
+        check_ceilometer_upgraded.return_value = None, None
         services.return_value = 's1'
         determine_ports.return_value = 'p1'
         resolve_required_interfaces.return_value = {'a': ['b']}
         utils.assess_status_func('test-config')
         make_assess_status_func.assert_called_once_with(
-            'test-config', {'a': ['b']}, services='s1', ports='p1')
+            'test-config', {'a': ['b']}, charm_func=check_ceilometer_upgraded,
+            services='s1', ports='p1')
 
     def test_pause_unit_helper(self):
         with patch.object(utils, '_pause_resume_helper') as prh:
@@ -433,3 +437,29 @@ class CeilometerUtilsTest(CharmTestCase):
         with self.assertRaises(utils.FailedAction):
             utils.ceilometer_upgrade_helper(self.CONFIGS)
         mock_ceilometer_upgrade.assert_called_once_with(action=True)
+
+    @patch.object(utils, 'kv')
+    def test_check_ceilometer_upgraded(self, mock_kv):
+        self.CONFIGS = MagicMock()
+        _kv = MagicMock()
+        mock_kv.return_value = _kv
+
+        # Not related
+        self.relation_ids.return_value = []
+        self.assertEqual(
+            (None, None),
+            utils.check_ceilometer_upgraded(self.CONFIGS))
+
+        # Related not ready
+        self.relation_ids.return_value = ['metric:1']
+        _kv.get.return_value = False
+        self.assertEqual(
+            ("blocked", "Run the ceilometer-upgrade action to initialize "
+                        "ceilometer and gnocchi"),
+            utils.check_ceilometer_upgraded(self.CONFIGS))
+
+        # Related ready
+        _kv.get.return_value = True
+        self.assertEqual(
+            (None, None),
+            utils.check_ceilometer_upgraded(self.CONFIGS))