Updated docs. Updated tests to add further coverage.
This commit is contained in:
parent
e13c9fd0cd
commit
555bfbd3ff
63
INVOICES.md
63
INVOICES.md
@ -81,3 +81,66 @@ add the line:
|
||||
|
||||
similar to *paste*-style configuration items.
|
||||
|
||||
|
||||
## Rates
|
||||
|
||||
Rate information is currently consumed from CSV files, dictated by the
|
||||
configuration file in the [invoice_object] section.
|
||||
|
||||
This rates information applies solely (at present) to the CSV output module
|
||||
for Artifice.
|
||||
|
||||
### Rate and Names Mapping files
|
||||
|
||||
#### Name mapping file
|
||||
|
||||
First, names must be mapped from the internal Ceilometer naming to a
|
||||
user-friendly format.
|
||||
This allows for a much simpler user interface, allowing for people to easily
|
||||
determine what services they are taking advantage of on the Catalyst cloud
|
||||
without needing to interpret internal names.
|
||||
|
||||
The naming file format is a |-delimited CSV file, consisting of:
|
||||
|
||||
ceilometer name | user-facing name
|
||||
|
||||
An example file would be:
|
||||
|
||||
m1.nano | VM instance, size nano
|
||||
network.incoming.bytes | Incoming Network Usage
|
||||
network.outgoing.bytes | Outgoing Network Usage
|
||||
storage.objects.size | Object Storage Usage
|
||||
volume.size | Disk Volume, Size
|
||||
|
||||
Excess whitespace will be trimmed.
|
||||
|
||||
#### Rates Mapping File
|
||||
|
||||
The other half of the Rates system is the Rates mapping file.
|
||||
|
||||
This mapping describes, for a given region, the price multiplier per
|
||||
unit per time that should be applied.
|
||||
|
||||
The default time range is a 10 minute time slice.
|
||||
|
||||
The rates mapping file is in the structure of:
|
||||
|
||||
region | VM instance, size nano | duration | 100
|
||||
region | Incoming Network Usage | bytes | 120
|
||||
region | Outgoing Network Usage | bytes | 240
|
||||
region | Object Storage Usage | bytes per hour | 300
|
||||
region | Disk Volume, Size | bytes per hour | 320
|
||||
|
||||
The first column is the name of the region this rate should be used for.
|
||||
This is **NOT CURRENTLY IMPLEMENTED.**
|
||||
|
||||
The second column is the name of the item being rated.
|
||||
This is always the prettified name from the Names mapping file.
|
||||
|
||||
The third column is what is being measured, per time slice.
|
||||
|
||||
The fourth column is an integer or decimal value denoting the cost per time
|
||||
slice.
|
||||
|
||||
The time slice width will be set in the config file. This is not currently
|
||||
implemented.
|
@ -156,6 +156,8 @@ class NamesFileMixin(object):
|
||||
# internal name | external name
|
||||
self.__names[ row[0].strip() ] = row[1].strip()
|
||||
|
||||
if not self.__names:
|
||||
raise IndexError("Malformed names CSV")
|
||||
fh.close()
|
||||
except KeyError:
|
||||
# couldn't actually find the useful info for rateS?
|
||||
|
@ -88,7 +88,7 @@ class VM(BaseModelConstruct):
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._raw["metadata"]["instance_type"]
|
||||
return self._raw["metadata"]["nistance_type"]
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
|
@ -116,8 +116,8 @@ class TestInvoice(test_interface.TestInterface):
|
||||
for uvm, cvm in zip(self.usage.vms, rows):
|
||||
print cvm
|
||||
self.assertEqual(
|
||||
uvm.amount.volume() * r.rate(r.pretty_name(uvm.type)),
|
||||
Decimal( cvm[-1] )
|
||||
uvm.amount.volume(), #* r.rate(r.pretty_name(uvm.type)),
|
||||
Decimal( cvm[-2] )
|
||||
)
|
||||
|
||||
|
||||
@ -142,12 +142,48 @@ class TestInvoice(test_interface.TestInterface):
|
||||
|
||||
def test_bad_names_file(self):
|
||||
"""test raising an exception with a malformed names file"""
|
||||
pass
|
||||
test_interface.config["invoice_object"]["rates"]["name"] = \
|
||||
bad_names_file
|
||||
self.assertRaises(IndexError, self.test_creates_csv )
|
||||
|
||||
def test_csv_rates_match(self):
|
||||
"""test rates in output CSV match computed rates"""
|
||||
pass
|
||||
|
||||
def test_names_match(self):
|
||||
"""test names in output CSV match pretty names"""
|
||||
pass
|
||||
i = self.test_creates_csv()
|
||||
fh = open(i.filename)
|
||||
|
||||
r = csv.reader(fh)
|
||||
rows = [row for row in r] # slurp
|
||||
fh.close()
|
||||
|
||||
# We need to grab the costing info here
|
||||
|
||||
# fh = open(test_interface.config["invoice_object"]["rates"]["file"])
|
||||
# rates = {}
|
||||
# reader = csv.reader(fh, delimiter = "|")
|
||||
# This is not ideal.
|
||||
class Reader(invoice.RatesFileMixin, invoice.NamesFileMixin):
|
||||
def __init__(self):
|
||||
self.config = {
|
||||
"rates": {
|
||||
"file": test_interface.config["invoice_object"]["rates"]["file"],
|
||||
"name": test_interface.config["invoice_object"]["rates"]["name"]
|
||||
}
|
||||
}
|
||||
# for row in reader:
|
||||
# # The default layout is expected to be:
|
||||
# # location | rate name | rate measurement | rate value
|
||||
# rates[row[1].strip()] = {
|
||||
# "cost": row[3].strip(),
|
||||
# "region": row[0].strip(),
|
||||
# "measures": row[2].strip()
|
||||
# }
|
||||
# fh.close()
|
||||
r = Reader()
|
||||
|
||||
for uvm, cvm in zip(self.usage.vms, rows):
|
||||
print cvm
|
||||
self.assertEqual(
|
||||
uvm.amount.volume() * r.rate(r.pretty_name(uvm.type)),
|
||||
Decimal( cvm[-1] )
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user