+def _get_statuses(policy_type_id, policy_instance_id):
+ """
+ shared helper to get statuses for an instance
+ """
+ _instance_is_valid(policy_type_id, policy_instance_id)
+ prefixes_for_handler = "{0}{1}.{2}.".format(HANDLER_PREFIX, policy_type_id, policy_instance_id)
+ return list(SDL.find_and_get(A1NS, prefixes_for_handler).values())
+
+
+def _get_instance_list(policy_type_id):
+ """
+ shared helper to get instance list for a type
+ """
+ _type_is_valid(policy_type_id)
+ prefixes_for_type = "{0}{1}.".format(INSTANCE_PREFIX, policy_type_id)
+ instancekeys = SDL.find_and_get(A1NS, prefixes_for_type).keys()
+ return [k.split(prefixes_for_type)[1] for k in instancekeys]
+
+
+def _clear_handlers(policy_type_id, policy_instance_id):
+ """
+ delete all the handlers for a policy instance
+ """
+ all_handlers_pref = _generate_handler_prefix(policy_type_id, policy_instance_id)
+ keys = SDL.find_and_get(A1NS, all_handlers_pref)
+ for k in keys:
+ SDL.delete(A1NS, k)
+
+
+def _get_metadata(policy_type_id, policy_instance_id):
+ """
+ get instance metadata
+ """
+ _instance_is_valid(policy_type_id, policy_instance_id)
+ metadata_key = _generate_instance_metadata_key(policy_type_id, policy_instance_id)
+ return SDL.get(A1NS, metadata_key)
+
+
+def _delete_after(policy_type_id, policy_instance_id, ttl):
+ """
+ this is a blocking function, must call this in a thread to not block!
+ waits ttl seconds, then deletes the instance
+ """
+ _instance_is_valid(policy_type_id, policy_instance_id)
+
+ time.sleep(ttl)
+
+ # ready to delete
+ _clear_handlers(policy_type_id, policy_instance_id) # delete all the handlers
+ SDL.delete(A1NS, _generate_instance_key(policy_type_id, policy_instance_id)) # delete instance
+ SDL.delete(A1NS, _generate_instance_metadata_key(policy_type_id, policy_instance_id)) # delete instance metadata
+ mdc_logger.debug("type {0} instance {1} deleted".format(policy_type_id, policy_instance_id))
+
+
+# Types
+
+
+def get_type_list():
+ """
+ retrieve all type ids
+ """
+ typekeys = SDL.find_and_get(A1NS, TYPE_PREFIX).keys()
+ # policy types are ints but they get butchered to strings in the KV
+ return [int(k.split(TYPE_PREFIX)[1]) for k in typekeys]
+
+
+def store_policy_type(policy_type_id, body):
+ """
+ store a policy type if it doesn't already exist
+ """
+ key = _generate_type_key(policy_type_id)
+ if SDL.get(A1NS, key) is not None:
+ raise PolicyTypeAlreadyExists()
+ # overwrite ID in body to enforce consistency
+ body['policy_type_id'] = policy_type_id
+ SDL.set(A1NS, key, body)
+
+
+def delete_policy_type(policy_type_id):
+ """
+ delete a policy type; can only be done if there are no instances (business logic)
+ """
+ pil = get_instance_list(policy_type_id)
+ if pil == []: # empty, can delete
+ SDL.delete(A1NS, _generate_type_key(policy_type_id))
+ else:
+ raise CantDeleteNonEmptyType()
+
+
+def get_policy_type(policy_type_id):
+ """
+ retrieve a type
+ """
+ _type_is_valid(policy_type_id)
+ return SDL.get(A1NS, _generate_type_key(policy_type_id))
+
+
+# Instances
+
+