class Script(wtypes.Base): """Type describing a script. """ script_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the script.""" name = wtypes.wsattr(wtypes.text, mandatory=True) """Name of the script.""" data = wtypes.wsattr(wtypes.text, mandatory=False) """Data of the script.""" checksum = wtypes.wsattr(wtypes.text, mandatory=False, readonly=True) """Checksum of the script data.""" @classmethod def sample(cls): sample = cls(script_id='bc05108d-f515-4984-8077-de319cbf35aa', name='policy1', data='return 0', checksum='cf83e1357eefb8bdf1542850d66d8007d620e4050b5715d' 'c83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec' '2f63b931bd47417a81a538327af927da3e') return sample
class Threshold(wtypes.Base): """Type describing a Threshold. A threshold is used to apply rating rules based on a level, if the parent is a field then the level is checked against a metadata. If it's a service then it's the quantity of the resource that is checked. """ threshold_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the threshold.""" level = wtypes.wsattr(decimal.Decimal, mandatory=True, default=decimal.Decimal('0')) """Level of the threshold.""" map_type = wtypes.wsattr(mapping_models.MAP_TYPE, default='flat', name='type') """Type of the threshold.""" cost = wtypes.wsattr(decimal.Decimal, mandatory=True) """Value of the threshold.""" service_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the service.""" field_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the field.""" group_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the hashmap group.""" tenant_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False, default=None) """UUID of the hashmap tenant.""" @classmethod def sample(cls): sample = cls(threshold_id='39dbd39d-f663-4444-a795-fb19d81af136', field_id='ac55b000-a05b-4832-b2ff-265a034886ab', level=decimal.Decimal('1024'), map_type='flat', cost=decimal.Decimal('4.2'), tenant_id='7977999e-2e25-11e6-a8b2-df30b233ffcb') return sample
class Mapping(wtypes.Base): """Type describing a Mapping. A mapping is used to apply rating rules based on a value, if the parent is a field then it's check the value of a metadata. If it's a service then it directly apply the rate to the volume. """ mapping_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the mapping.""" value = wtypes.wsattr(wtypes.text, mandatory=False, default='') """Key of the mapping.""" map_type = wtypes.wsattr(MAP_TYPE, default='flat', name='type') """Type of the mapping.""" cost = wtypes.wsattr(decimal.Decimal, mandatory=True) """Value of the mapping.""" service_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the service.""" field_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the field.""" group_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the hashmap group.""" tenant_id = wtypes.wsattr(wtypes.text, mandatory=False, default=None) """ID of the hashmap tenant.""" @classmethod def sample(cls): sample = cls(mapping_id='39dbd39d-f663-4444-a795-fb19d81af136', field_id='ac55b000-a05b-4832-b2ff-265a034886ab', value='m1.micro', map_type='flat', cost=decimal.Decimal('4.2'), tenant_id='7977999e-2e25-11e6-a8b2-df30b233ffcb') return sample
class Field(wtypes.Base): """Type describing a field. A field is mapping a value of the 'desc' dict of the CloudKitty data. It's used to map the name of a metadata. """ field_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the field.""" name = wtypes.wsattr(wtypes.text, mandatory=True) """Name of the field.""" service_id = wtypes.wsattr(ck_types.UuidType(), mandatory=True) """UUID of the parent service.""" @classmethod def sample(cls): sample = cls(field_id='ac55b000-a05b-4832-b2ff-265a034886ab', name='image_id', service_id='a733d0e1-1ec9-4800-8df8-671e4affd017') return sample
class Service(wtypes.Base): """Type describing a service. A service is directly mapped to the usage key, the collected service. """ service_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the service.""" name = wtypes.wsattr(wtypes.text, mandatory=True) """Name of the service.""" @classmethod def sample(cls): sample = cls(service_id='a733d0e1-1ec9-4800-8df8-671e4affd017', name='compute') return sample
class Group(wtypes.Base): """Type describing a group. A group is used to divide calculations. It can be used to create a group for the instance rating (flavor) and one if we have premium images (image_id). So you can take into account multiple parameters during the rating. """ group_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the group.""" name = wtypes.wsattr(wtypes.text, mandatory=True) """Name of the group.""" @classmethod def sample(cls): sample = cls(group_id='afe898cb-86d8-4557-ad67-f4f01891bbee', name='instance_rating') return sample
class Script(wtypes.Base): """Type describing a script. """ script_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) """UUID of the script.""" name = wtypes.wsattr(wtypes.text, mandatory=True) """Name of the script.""" data = wtypes.wsattr(wtypes.text, mandatory=False) """Data of the script.""" checksum = wtypes.wsattr(wtypes.text, mandatory=False, readonly=True) """Checksum of the script data.""" @classmethod def sample(cls): sample = cls(script_id='bc05108d-f515-4984-8077-de319cbf35aa', name='policy1', data='return 0', checksum='da39a3ee5e6b4b0d3255bfef95601890afd80709') return sample
class HashMapMappingsController(rating.RatingRestControllerBase): """Controller responsible of mappings management. """ _custom_actions = {'group': ['GET']} @wsme_pecan.wsexpose(group_models.Group, ck_types.UuidType()) def group(self, mapping_id): """Get the group attached to the mapping. :param mapping_id: UUID of the mapping to filter on. """ hashmap = db_api.get_instance() try: group_db = hashmap.get_group_from_mapping(uuid=mapping_id) return group_models.Group(**group_db.export_model()) except db_api.MappingHasNoGroup as e: pecan.abort(404, six.text_type(e)) @wsme_pecan.wsexpose(mapping_models.MappingCollection, ck_types.UuidType(), ck_types.UuidType(), ck_types.UuidType(), bool, ck_types.UuidType(), bool, status_code=200) def get_all(self, service_id=None, field_id=None, group_id=None, no_group=False, tenant_id=None, filter_tenant=False): """Get the mapping list :param service_id: Service UUID to filter on. :param field_id: Field UUID to filter on. :param group_id: Group UUID to filter on. :param no_group: Filter on orphaned mappings. :param tenant_id: Tenant UUID to filter on. :param filter_tenant: Explicitly filter on tenant (default is to not filter on tenant). Useful if you want to filter on tenant being None. :return: List of every mappings. """ hashmap = db_api.get_instance() mapping_list = [] search_opts = dict() if filter_tenant: search_opts['tenant_uuid'] = tenant_id mappings_uuid_list = hashmap.list_mappings(service_uuid=service_id, field_uuid=field_id, group_uuid=group_id, no_group=no_group, **search_opts) for mapping_uuid in mappings_uuid_list: mapping_db = hashmap.get_mapping(uuid=mapping_uuid) mapping_list.append( mapping_models.Mapping(**mapping_db.export_model())) res = mapping_models.MappingCollection(mappings=mapping_list) return res @wsme_pecan.wsexpose(mapping_models.Mapping, ck_types.UuidType()) def get_one(self, mapping_id): """Return a mapping. :param mapping_id: UUID of the mapping to filter on. """ hashmap = db_api.get_instance() try: mapping_db = hashmap.get_mapping(uuid=mapping_id) return mapping_models.Mapping(**mapping_db.export_model()) except db_api.NoSuchMapping as e: pecan.abort(404, six.text_type(e)) @wsme_pecan.wsexpose(mapping_models.Mapping, body=mapping_models.Mapping, status_code=201) def post(self, mapping_data): """Create a mapping. :param mapping_data: Informations about the mapping to create. """ hashmap = db_api.get_instance() try: mapping_db = hashmap.create_mapping( value=mapping_data.value, map_type=mapping_data.map_type, cost=mapping_data.cost, field_id=mapping_data.field_id, group_id=mapping_data.group_id, service_id=mapping_data.service_id, tenant_id=mapping_data.tenant_id) pecan.response.location = pecan.request.path_url if pecan.response.location[-1] != '/': pecan.response.location += '/' pecan.response.location += mapping_db.mapping_id return mapping_models.Mapping(**mapping_db.export_model()) except db_api.MappingAlreadyExists as e: pecan.abort(409, six.text_type(e)) except db_api.ClientHashMapError as e: pecan.abort(400, six.text_type(e)) @wsme_pecan.wsexpose(None, ck_types.UuidType(), body=mapping_models.Mapping, status_code=302) def put(self, mapping_id, mapping): """Update a mapping. :param mapping_id: UUID of the mapping to update. :param mapping: Mapping data to insert. """ hashmap = db_api.get_instance() try: hashmap.update_mapping(mapping_id, mapping_id=mapping.mapping_id, value=mapping.value, cost=mapping.cost, map_type=mapping.map_type, group_id=mapping.group_id, tenant_id=mapping.tenant_id) pecan.response.headers['Location'] = pecan.request.path except db_api.MappingAlreadyExists as e: pecan.abort(409, six.text_type(e)) except db_api.NoSuchMapping as e: pecan.abort(404, six.text_type(e)) except db_api.ClientHashMapError as e: pecan.abort(400, six.text_type(e)) @wsme_pecan.wsexpose(None, ck_types.UuidType(), status_code=204) def delete(self, mapping_id): """Delete a mapping. :param mapping_id: UUID of the mapping to delete. """ hashmap = db_api.get_instance() try: hashmap.delete_mapping(uuid=mapping_id) except db_api.NoSuchMapping as e: pecan.abort(404, six.text_type(e))
class HashMapThresholdsController(rating.RatingRestControllerBase): """Controller responsible of thresholds management. """ _custom_actions = {'group': ['GET']} @wsme_pecan.wsexpose(group_models.Group, ck_types.UuidType()) def group(self, threshold_id): """Get the group attached to the threshold. :param threshold_id: UUID of the threshold to filter on. """ hashmap = db_api.get_instance() try: group_db = hashmap.get_group_from_threshold(uuid=threshold_id) return group_models.Group(**group_db.export_model()) except db_api.ThresholdHasNoGroup as e: pecan.abort(404, six.text_type(e)) @wsme_pecan.wsexpose(threshold_models.ThresholdCollection, ck_types.UuidType(), ck_types.UuidType(), ck_types.UuidType(), bool, status_code=200) def get_all(self, service_id=None, field_id=None, group_id=None, no_group=False): """Get the threshold list :param service_id: Service UUID to filter on. :param field_id: Field UUID to filter on. :param group_id: Group UUID to filter on. :param no_group: Filter on orphaned thresholds. :return: List of every thresholds. """ hashmap = db_api.get_instance() threshold_list = [] thresholds_uuid_list = hashmap.list_thresholds(service_uuid=service_id, field_uuid=field_id, group_uuid=group_id) for threshold_uuid in thresholds_uuid_list: threshold_db = hashmap.get_threshold(uuid=threshold_uuid) threshold_list.append( threshold_models.Threshold(**threshold_db.export_model())) res = threshold_models.ThresholdCollection(thresholds=threshold_list) return res @wsme_pecan.wsexpose(threshold_models.Threshold, ck_types.UuidType()) def get_one(self, threshold_id): """Return a threshold. :param threshold_id: UUID of the threshold to filter on. """ hashmap = db_api.get_instance() try: threshold_db = hashmap.get_threshold(uuid=threshold_id) return threshold_models.Threshold(**threshold_db.export_model()) except db_api.NoSuchThreshold as e: pecan.abort(404, six.text_type(e)) @wsme_pecan.wsexpose(threshold_models.Threshold, body=threshold_models.Threshold, status_code=201) def post(self, threshold_data): """Create a threshold. :param threshold_data: Informations about the threshold to create. """ hashmap = db_api.get_instance() try: threshold_db = hashmap.create_threshold( level=threshold_data.level, map_type=threshold_data.map_type, cost=threshold_data.cost, field_id=threshold_data.field_id, group_id=threshold_data.group_id, service_id=threshold_data.service_id) pecan.response.location = pecan.request.path_url if pecan.response.location[-1] != '/': pecan.response.location += '/' pecan.response.location += threshold_db.threshold_id return threshold_models.Threshold(**threshold_db.export_model()) except db_api.ThresholdAlreadyExists as e: pecan.abort(409, six.text_type(e)) except db_api.ClientHashMapError as e: pecan.abort(400, six.text_type(e)) @wsme_pecan.wsexpose(None, ck_types.UuidType(), body=threshold_models.Threshold, status_code=302) def put(self, threshold_id, threshold): """Update a threshold. :param threshold_id: UUID of the threshold to update. :param threshold: Threshold data to insert. """ hashmap = db_api.get_instance() try: hashmap.update_threshold(threshold_id, threshold_id=threshold.threshold_id, level=threshold.level, cost=threshold.cost, map_type=threshold.map_type, group_id=threshold.group_id) pecan.response.headers['Location'] = pecan.request.path except db_api.NoSuchThreshold as e: pecan.abort(404, six.text_type(e)) except db_api.ClientHashMapError as e: pecan.abort(400, six.text_type(e)) @wsme_pecan.wsexpose(None, ck_types.UuidType(), status_code=204) def delete(self, threshold_id): """Delete a threshold. :param threshold_id: UUID of the threshold to delete. """ hashmap = db_api.get_instance() try: hashmap.delete_threshold(uuid=threshold_id) except db_api.NoSuchThreshold as e: pecan.abort(404, six.text_type(e))
class HashMapServicesController(rating.RatingRestControllerBase): """Controller responsible of services management. """ fields = field_api.HashMapFieldsController() mappings = mapping_api.HashMapMappingsController() @wsme_pecan.wsexpose(service_models.ServiceCollection) def get_all(self): """Get the service list :return: List of every services. """ hashmap = db_api.get_instance() service_list = [] services_uuid_list = hashmap.list_services() for service_uuid in services_uuid_list: service_db = hashmap.get_service(uuid=service_uuid) service_list.append(service_models.Service( **service_db.export_model())) res = service_models.ServiceCollection(services=service_list) return res @wsme_pecan.wsexpose(service_models.Service, ck_types.UuidType()) def get_one(self, service_id): """Return a service. :param service_id: UUID of the service to filter on. """ hashmap = db_api.get_instance() try: service_db = hashmap.get_service(uuid=service_id) return service_models.Service(**service_db.export_model()) except db_api.NoSuchService as e: pecan.abort(404, e.args[0]) @wsme_pecan.wsexpose(service_models.Service, body=service_models.Service, status_code=201) def post(self, service_data): """Create hashmap service. :param service_data: Informations about the service to create. """ hashmap = db_api.get_instance() try: service_db = hashmap.create_service(service_data.name) pecan.response.location = pecan.request.path_url if pecan.response.location[-1] != '/': pecan.response.location += '/' pecan.response.location += service_db.service_id return service_models.Service( **service_db.export_model()) except db_api.ServiceAlreadyExists as e: pecan.abort(409, e.args[0]) @wsme_pecan.wsexpose(None, ck_types.UuidType(), status_code=204) def delete(self, service_id): """Delete the service and all the sub keys recursively. :param service_id: UUID of the service to delete. """ hashmap = db_api.get_instance() try: hashmap.delete_service(uuid=service_id) except db_api.NoSuchService as e: pecan.abort(404, e.args[0])
class HashMapGroupsController(rating.RatingRestControllerBase): """Controller responsible of groups management. """ _custom_actions = {'mappings': ['GET'], 'thresholds': ['GET']} @wsme_pecan.wsexpose(mapping_models.MappingCollection, ck_types.UuidType()) def mappings(self, group_id): """Get the mappings attached to the group. :param group_id: UUID of the group to filter on. """ hashmap = db_api.get_instance() mapping_list = [] mappings_uuid_list = hashmap.list_mappings(group_uuid=group_id) for mapping_uuid in mappings_uuid_list: mapping_db = hashmap.get_mapping(uuid=mapping_uuid) mapping_list.append( mapping_models.Mapping(**mapping_db.export_model())) res = mapping_models.MappingCollection(mappings=mapping_list) return res @wsme_pecan.wsexpose(threshold_models.ThresholdCollection, ck_types.UuidType()) def thresholds(self, group_id): """Get the thresholds attached to the group. :param group_id: UUID of the group to filter on. """ hashmap = db_api.get_instance() threshold_list = [] thresholds_uuid_list = hashmap.list_thresholds(group_uuid=group_id) for threshold_uuid in thresholds_uuid_list: threshold_db = hashmap.get_threshold(uuid=threshold_uuid) threshold_list.append( threshold_models.Threshold(**threshold_db.export_model())) res = threshold_models.ThresholdCollection(thresholds=threshold_list) return res @wsme_pecan.wsexpose(group_models.GroupCollection) def get_all(self): """Get the group list :return: List of every group. """ hashmap = db_api.get_instance() group_list = [] groups_uuid_list = hashmap.list_groups() for group_uuid in groups_uuid_list: group_db = hashmap.get_group(uuid=group_uuid) group_list.append(group_models.Group(**group_db.export_model())) res = group_models.GroupCollection(groups=group_list) return res @wsme_pecan.wsexpose(group_models.Group, ck_types.UuidType()) def get_one(self, group_id): """Return a group. :param group_id: UUID of the group to filter on. """ hashmap = db_api.get_instance() try: group_db = hashmap.get_group(uuid=group_id) return group_models.Group(**group_db.export_model()) except db_api.NoSuchGroup as e: pecan.abort(404, six.text_type(e)) @wsme_pecan.wsexpose(group_models.Group, body=group_models.Group, status_code=201) def post(self, group_data): """Create a group. :param group_data: Informations about the group to create. """ hashmap = db_api.get_instance() try: group_db = hashmap.create_group(group_data.name) pecan.response.location = pecan.request.path_url if pecan.response.location[-1] != '/': pecan.response.location += '/' pecan.response.location += group_db.group_id return group_models.Group(**group_db.export_model()) except db_api.GroupAlreadyExists as e: pecan.abort(409, six.text_type(e)) @wsme_pecan.wsexpose(None, ck_types.UuidType(), bool, status_code=204) def delete(self, group_id, recursive=False): """Delete a group. :param group_id: UUID of the group to delete. :param recursive: Delete mappings recursively. """ hashmap = db_api.get_instance() try: hashmap.delete_group(uuid=group_id, recurse=recursive) except db_api.NoSuchGroup as e: pecan.abort(404, six.text_type(e))
class HashMapFieldsController(rating.RatingRestControllerBase): """Controller responsible of fields management. """ @wsme_pecan.wsexpose(field_models.FieldCollection, ck_types.UuidType(), status_code=200) def get_all(self, service_id): """Get the field list. :param service_id: Service's UUID to filter on. :return: List of every fields. """ hashmap = db_api.get_instance() field_list = [] fields_uuid_list = hashmap.list_fields(service_id) for field_uuid in fields_uuid_list: field_db = hashmap.get_field(field_uuid) field_list.append(field_models.Field( **field_db.export_model())) res = field_models.FieldCollection(fields=field_list) return res @wsme_pecan.wsexpose(field_models.Field, ck_types.UuidType(), status_code=200) def get_one(self, field_id): """Return a field. :param field_id: UUID of the field to filter on. """ hashmap = db_api.get_instance() try: field_db = hashmap.get_field(uuid=field_id) return field_models.Field(**field_db.export_model()) except db_api.NoSuchField as e: pecan.abort(404, six.text_type(e)) @wsme_pecan.wsexpose(field_models.Field, body=field_models.Field, status_code=201) def post(self, field_data): """Create a field. :param field_data: Informations about the field to create. """ hashmap = db_api.get_instance() try: field_db = hashmap.create_field( field_data.service_id, field_data.name) pecan.response.location = pecan.request.path_url if pecan.response.location[-1] != '/': pecan.response.location += '/' pecan.response.location += field_db.field_id return field_models.Field( **field_db.export_model()) except db_api.FieldAlreadyExists as e: pecan.abort(409, six.text_type(e)) except db_api.ClientHashMapError as e: pecan.abort(400, six.text_type(e)) @wsme_pecan.wsexpose(None, ck_types.UuidType(), status_code=204) def delete(self, field_id): """Delete the field and all the sub keys recursively. :param field_id: UUID of the field to delete. """ hashmap = db_api.get_instance() try: hashmap.delete_field(uuid=field_id) except db_api.NoSuchField as e: pecan.abort(404, six.text_type(e))
class PyScriptsScriptsController(rating.RatingRestControllerBase): """Controller responsible of scripts management. """ def normalize_data(self, data): """Translate data to binary format if needed. :param data: Data to convert to binary type. """ if data == wtypes.Unset: return '' if not isinstance(data, six.binary_type): data = data.encode('utf-8') return data @wsme_pecan.wsexpose(script_models.ScriptCollection, bool) def get_all(self, no_data=False): """Get the script list :param no_data: Set to True to remove script data from output. :return: List of every scripts. """ pyscripts = db_api.get_instance() script_list = [] script_uuid_list = pyscripts.list_scripts() for script_uuid in script_uuid_list: script_db = pyscripts.get_script(uuid=script_uuid) script = script_db.export_model() if no_data: del script['data'] script_list.append(script_models.Script(**script)) res = script_models.ScriptCollection(scripts=script_list) return res @wsme_pecan.wsexpose(script_models.Script, ck_types.UuidType()) def get_one(self, script_id): """Return a script. :param script_id: UUID of the script to filter on. """ pyscripts = db_api.get_instance() try: script_db = pyscripts.get_script(uuid=script_id) return script_models.Script(**script_db.export_model()) except db_api.NoSuchScript as e: pecan.abort(400, six.text_type(e)) @wsme_pecan.wsexpose(script_models.Script, body=script_models.Script, status_code=201) def post(self, script_data): """Create pyscripts script. :param script_data: Informations about the script to create. """ pyscripts = db_api.get_instance() try: data = self.normalize_data(script_data.data) script_db = pyscripts.create_script(script_data.name, data) pecan.response.location = pecan.request.path_url if pecan.response.location[-1] != '/': pecan.response.location += '/' pecan.response.location += script_db.script_id return script_models.Script(**script_db.export_model()) except db_api.ScriptAlreadyExists as e: pecan.abort(409, six.text_type(e)) @wsme_pecan.wsexpose(script_models.Script, ck_types.UuidType(), body=script_models.Script, status_code=201) def put(self, script_id, script_data): """Update pyscripts script. :param script_id: UUID of the script to update. :param script_data: Script data to update. """ pyscripts = db_api.get_instance() try: data = self.normalize_data(script_data.data) script_db = pyscripts.update_script(script_id, name=script_data.name, data=data) pecan.response.location = pecan.request.path_url if pecan.response.location[-1] != '/': pecan.response.location += '/' pecan.response.location += script_db.script_id return script_models.Script(**script_db.export_model()) except db_api.NoSuchScript as e: pecan.abort(400, six.text_type(e)) @wsme_pecan.wsexpose(None, ck_types.UuidType(), status_code=204) def delete(self, script_id): """Delete the script. :param script_id: UUID of the script to delete. """ pyscripts = db_api.get_instance() try: pyscripts.delete_script(uuid=script_id) except db_api.NoSuchScript as e: pecan.abort(400, six.text_type(e))