usr/lib/byobu/ec2_cost,

usr/lib/byobu/include/ec2instancespricing.py,
  usr/lib/byobu/include/Makefile.am, usr/lib/byobu/include/shutil,
  usr/lib/byobu/Makefile.am, usr/share/byobu/status/status,
  usr/share/man/man1/byobu.1:
  - deprecate unmaintained ec2/rcs pricing functionality
  - this never really worked well, and these prices are constantly changing
This commit is contained in:
Dustin Kirkland 2018-08-12 08:56:19 -05:00
commit 0df1e1f347
8 changed files with 14 additions and 700 deletions

8
debian/changelog vendored
View file

@ -10,7 +10,13 @@ byobu (5.127) unreleased; urgency=medium
* usr/lib/byobu/include/shutil, usr/lib/byobu/Makefile.am,
usr/lib/byobu/rcs_cost, usr/share/byobu/status/status,
usr/share/man/man1/byobu.1:
- deprecate some unmaintained functionality
usr/lib/byobu/ec2_cost,
usr/lib/byobu/include/ec2instancespricing.py,
usr/lib/byobu/include/Makefile.am, usr/lib/byobu/include/shutil,
usr/lib/byobu/Makefile.am, usr/share/byobu/status/status,
usr/share/man/man1/byobu.1:
- deprecate unmaintained ec2/rcs pricing functionality
- this never really worked well, and these prices are constantly changing
-- Dustin Kirkland <kirkland@ubuntu.com> Sun, 27 May 2018 18:07:11 -0500

View file

@ -1,3 +1,3 @@
libdirdir = $(prefix)/lib/@PACKAGE@
libdir_SCRIPTS = apport arch battery cpu_count cpu_freq cpu_temp color custom date disk disk_io distro entropy ec2_cost fan_speed hostname ip_address load_average logo mail memory menu network processes raid reboot_required release services session swap time time_binary time_utc trash updates_available uptime users whoami wifi_quality
libdir_SCRIPTS = apport arch battery cpu_count cpu_freq cpu_temp color custom date disk disk_io distro entropy fan_speed hostname ip_address load_average logo mail memory menu network processes raid reboot_required release services session swap time time_binary time_utc trash updates_available uptime users whoami wifi_quality

View file

@ -1,107 +0,0 @@
#!/bin/sh -e
#
# ec2_cost: approximate EC2 cost (USD) of the current instance
#
# Copyright (C) 2008 Canonical Ltd.
# Copyright (C) 2011-2014 Dustin Kirkland
#
# Authors: Dustin Kirkland <kirkland@byobu.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Data Transfer Cost Basis
# Incoming $0.01/GB
# Outgoing $0.12/GB
# (This gets more complex if you use >10TB/mo)
RX_RATE="0.01"
TX_RATE="0.12"
__ec2_cost_detail() {
DETAIL=1
__ec2_cost
}
__ec2_cost() {
local zone type file_to_stat cpu mem rate hours tx_gb rx_gb network_cost uptime_cost total_cost interface cache="$BYOBU_RUN_DIR/cache.$BYOBU_BACKEND/ec2_cost"
if [ -s "$cache.rate" ]; then
read rate < "$cache.rate"
elif metadata_available; then
# Try to use metadata service
[ -s "$cache.zone" ] || timeout 0.2 wget -q -O- http://169.254.169.254/latest/meta-data/placement/availability-zone </dev/null >"$cache.zone" 2>/dev/null &
sleep 0.02
[ -s "$cache.zone" ] && read zone < "$cache.zone"
zone=${zone%%[a-z]}
[ -s "$cache.type" ] || timeout 0.2 wget -q -O- http://169.254.169.254/latest/meta-data/instance-type </dev/null >"$cache.type" 2>/dev/null &
sleep 0.02
[ -s "$cache.type" ] && read type < "$cache.type"
$BYOBU_PREFIX/lib/byobu/include/ec2instancespricing.py --type ondemand --filter-region $zone --filter-type $type --filter-os-type linux --format csv | tail -n1 > "$cache.rate"
read rate < "$cache.rate"
fi
if [ -z "$rate" ]; then
# Unknown rate, exit immediately
# Rate estimation is now deprecated
return
fi
rate=${rate##*,}
file_to_stat="/etc/hostname"
hours=$(((`date +%s` - `stat --printf %Y $file_to_stat`) / 60 / 60 + 1))
# Auto detect network interface
[ -r "/proc/net/route" ] || return
interface=$(tail -n1 /proc/net/route | awk '{print $1}')
local iface rbytes rpackets rerrs rdrop rfifo rframe rcompressed rmulticast tbytes tpackets terrs tdrop tfifo tcolls tcarrier tcompressed
while read iface rbytes rpackets rerrs rdrop rfifo rframe rcompressed rmulticast tbytes tpackets terrs tdrop tfifo tcolls tcarrier tcompressed; do
case "$iface" in
${interface}:)
tx_gb=${tbytes}
rx_gb=${rbytes}
break;
;;
${interface}:*)
# Interface and rbytes got munged together
tx_gb=${rmulticast##*:}
rx_gb=${iface##*:}
break;
;;
esac
if [ "$iface" = "${interface}:" ]; then
tx_gb=${tbytes}
rx_gb=${rbytes}
break
fi
done < /proc/net/dev
tx_gb=$(printf "%s" ${tx_gb} | awk '{ printf "%f", $1 / 1024 / 1024 / 1024 }')
rx_gb=$(printf "%s" ${rx_gb} | awk '{ printf "%f", $1 / 1024 / 1024 / 1024 }')
network_cost=`printf "%s %s %s %s" "$tx_gb" "$TX_RATE" "$rx_gb" "$RX_RATE" | awk '{printf "%f %f", $1*$2, $3*$4}' | awk '{printf "%f", $1 + $2}'`
# Calculate uptime cost
uptime_cost=`printf "%s" "$hours" | awk "{printf \"%f\", "$rate" * $hours}"`
total_cost=`printf "%s %s" "$network_cost" "$uptime_cost" | awk '{printf "%.2f", $1 + $2}'`
if [ "$DETAIL" = "1" ]; then
echo "================================================"
echo "Estimated cost in Amazon's EC2 since last reboot"
echo "================================================"
echo " Network sent: $tx_gb GB @ \$$RX_RATE/GB"
echo " Network recv: $rx_gb GB @ \$$TX_RATE/GB"
echo " Network cost: \$$network_cost"
echo "------------------------------------------------"
echo " Uptime: $hours hr @ \$$rate/hr"
echo " Uptime cost: \$$uptime_cost"
echo "------------------------------------------------"
echo "Total cost: ~\$$total_cost"
echo "================================================"
return
fi
[ -n "$total_cost" ] || return
color K G; printf "A\$"; color -; color b K G; printf "%s" "$total_cost"; color --
}
# vi: syntax=sh ts=4 noexpandtab

View file

@ -1,2 +1,2 @@
inclibdirdir = $(prefix)/lib/@PACKAGE@/include
inclibdir_SCRIPTS = common colors config.py constants cycle-status dirs icons mondrian notify_osd shutil ec2instancespricing.py select-session.py tmux-detach-all-but-current-client tmux-send-command-to-all-panes tmux-send-command-to-all-windows toggle-utf8
inclibdir_SCRIPTS = common colors config.py constants cycle-status dirs icons mondrian notify_osd shutil select-session.py tmux-detach-all-but-current-client tmux-send-command-to-all-panes tmux-send-command-to-all-windows toggle-utf8

View file

@ -1,582 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2012 Eran Sandler (eran@sandler.co.il), http://eran.sandler.co.il, http://forecastcloudy.net
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import object
import urllib.request, urllib.error, urllib.parse
import argparse
import datetime
try:
import simplejson as json
except ImportError:
import json
EC2_REGIONS = [
"us-east-1",
"us-west-1",
"us-west-2",
"eu-west-1",
"ap-southeast-1",
"ap-southeast-2",
"ap-northeast-1",
"sa-east-1"
]
EC2_INSTANCE_TYPES = [
"t1.micro",
"m1.small",
"m1.medium",
"m1.large",
"m1.xlarge",
"m2.xlarge",
"m2.2xlarge",
"m2.4xlarge",
"c1.medium",
"c1.xlarge",
"cc1.4xlarge",
"cc2.8xlarge",
"cg1.4xlarge",
"cr1.8xlarge",
"m3.xlarge",
"m3.2xlarge",
"hi1.4xlarge",
"hs1.8xlarge",
"g2.2xlarge"
]
EC2_OS_TYPES = [
"linux", # api platform name = "linux"
"mswin", # api platform name = "windows"
"rhel", # api platform name = ""
"sles", # api platform name = ""
"mswinSQL", # api platform name = "windows"
"mswinSQLWeb", # api platform name = "windows"
]
JSON_NAME_TO_EC2_REGIONS_API = {
"us-east" : "us-east-1",
"us-east-1" : "us-east-1",
"us-west" : "us-west-1",
"us-west-1" : "us-west-1",
"us-west-2" : "us-west-2",
"eu-ireland" : "eu-west-1",
"eu-west-1" : "eu-west-1",
"apac-sin" : "ap-southeast-1",
"ap-southeast-1" : "ap-southeast-1",
"ap-southeast-2" : "ap-southeast-2",
"apac-syd" : "ap-southeast-2",
"apac-tokyo" : "ap-northeast-1",
"ap-northeast-1" : "ap-northeast-1",
"sa-east-1" : "sa-east-1"
}
EC2_REGIONS_API_TO_JSON_NAME = {
"us-east-1" : "us-east",
"us-west-1" : "us-west",
"us-west-2" : "us-west-2",
"eu-west-1" : "eu-ireland",
"ap-southeast-1" : "apac-sin",
"ap-southeast-2" : "apac-syd",
"ap-northeast-1" : "apac-tokyo",
"sa-east-1" : "sa-east-1"
}
INSTANCES_ON_DEMAND_LINUX_URL = "http://aws.amazon.com/ec2/pricing/json/linux-od.json"
INSTANCES_ON_DEMAND_RHEL_URL = "http://aws.amazon.com/ec2/pricing/json/rhel-od.json"
INSTANCES_ON_DEMAND_SLES_URL = "http://aws.amazon.com/ec2/pricing/json/sles-od.json"
INSTANCES_ON_DEMAND_WINDOWS_URL = "http://aws.amazon.com/ec2/pricing/json/mswin-od.json"
INSTANCES_ON_DEMAND_WINSQL_URL = "http://aws.amazon.com/ec2/pricing/json/mswinSQL-od.json"
INSTANCES_ON_DEMAND_WINSQLWEB_URL = "http://aws.amazon.com/ec2/pricing/json/mswinSQLWeb-od.json"
INSTANCES_RESERVED_LIGHT_UTILIZATION_LINUX_URL = "http://aws.amazon.com/ec2/pricing/json/linux-ri-light.json"
INSTANCES_RESERVED_LIGHT_UTILIZATION_RHEL_URL = "http://aws.amazon.com/ec2/pricing/json/rhel-ri-light.json"
INSTANCES_RESERVED_LIGHT_UTILIZATION_SLES_URL = "http://aws.amazon.com/ec2/pricing/json/sles-ri-light.json"
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINDOWS_URL = "http://aws.amazon.com/ec2/pricing/json/mswin-ri-light.json"
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINSQL_URL = "http://aws.amazon.com/ec2/pricing/json/mswinSQL-ri-light.json"
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINSQLWEB_URL = "http://aws.amazon.com/ec2/pricing/json/mswinSQLWeb-ri-light.json"
INSTANCES_RESERVED_MEDIUM_UTILIZATION_LINUX_URL = "http://aws.amazon.com/ec2/pricing/json/linux-ri-medium.json"
INSTANCES_RESERVED_MEDIUM_UTILIZATION_RHEL_URL = "http://aws.amazon.com/ec2/pricing/json/rhel-ri-medium.json"
INSTANCES_RESERVED_MEDIUM_UTILIZATION_SLES_URL = "http://aws.amazon.com/ec2/pricing/json/sles-ri-medium.json"
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINDOWS_URL = "http://aws.amazon.com/ec2/pricing/json/mswin-ri-medium.json"
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINSQL_URL = "http://aws.amazon.com/ec2/pricing/json/mswinSQL-ri-medium.json"
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINSQLWEB_URL = "http://aws.amazon.com/ec2/pricing/json/mswinSQLWeb-ri-medium.json"
INSTANCES_RESERVED_HEAVY_UTILIZATION_LINUX_URL = "http://aws.amazon.com/ec2/pricing/json/linux-ri-heavy.json"
INSTANCES_RESERVED_HEAVY_UTILIZATION_RHEL_URL = "http://aws.amazon.com/ec2/pricing/json/rhel-ri-heavy.json"
INSTANCES_RESERVED_HEAVY_UTILIZATION_SLES_URL = "http://aws.amazon.com/ec2/pricing/json/sles-ri-heavy.json"
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINDOWS_URL = "http://aws.amazon.com/ec2/pricing/json/mswin-ri-heavy.json"
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINSQL_URL = "http://aws.amazon.com/ec2/pricing/json/mswinSQL-ri-heavy.json"
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINSQLWEB_URL = "http://aws.amazon.com/ec2/pricing/json/mswinSQLWeb-ri-heavy.json"
INSTANCES_ONDEMAND_OS_TYPE_BY_URL = {
INSTANCES_ON_DEMAND_LINUX_URL : "linux",
INSTANCES_ON_DEMAND_RHEL_URL : "rhel",
INSTANCES_ON_DEMAND_SLES_URL : "sles",
INSTANCES_ON_DEMAND_WINDOWS_URL : "mswin",
INSTANCES_ON_DEMAND_WINSQL_URL : "mswinSQL",
INSTANCES_ON_DEMAND_WINSQLWEB_URL : "mswinSQLWeb",
}
INSTANCES_RESERVED_OS_TYPE_BY_URL = {
INSTANCES_RESERVED_LIGHT_UTILIZATION_LINUX_URL : "linux",
INSTANCES_RESERVED_LIGHT_UTILIZATION_RHEL_URL : "rhel",
INSTANCES_RESERVED_LIGHT_UTILIZATION_SLES_URL : "sles",
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINDOWS_URL : "mswin",
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINSQL_URL : "mswinSQL",
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINSQLWEB_URL : "mswinSQLWeb",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_LINUX_URL : "linux",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_RHEL_URL : "rhel",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_SLES_URL : "sles",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINDOWS_URL : "mswin",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINSQL_URL : "mswinSQL",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINSQLWEB_URL : "mswinSQLWeb",
INSTANCES_RESERVED_HEAVY_UTILIZATION_LINUX_URL : "linux",
INSTANCES_RESERVED_HEAVY_UTILIZATION_RHEL_URL : "rhel",
INSTANCES_RESERVED_HEAVY_UTILIZATION_SLES_URL : "sles",
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINDOWS_URL : "mswin",
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINSQL_URL : "mswinSQL",
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINSQLWEB_URL : "mswinSQLWeb",
}
INSTANCES_RESERVED_UTILIZATION_TYPE_BY_URL = {
INSTANCES_RESERVED_LIGHT_UTILIZATION_LINUX_URL : "light",
INSTANCES_RESERVED_LIGHT_UTILIZATION_RHEL_URL : "light",
INSTANCES_RESERVED_LIGHT_UTILIZATION_SLES_URL : "light",
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINDOWS_URL : "light",
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINSQL_URL : "light",
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINSQLWEB_URL : "light",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_LINUX_URL : "medium",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_RHEL_URL : "medium",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_SLES_URL : "medium",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINDOWS_URL : "medium",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINSQL_URL : "medium",
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINSQLWEB_URL : "medium",
INSTANCES_RESERVED_HEAVY_UTILIZATION_LINUX_URL : "heavy",
INSTANCES_RESERVED_HEAVY_UTILIZATION_RHEL_URL : "heavy",
INSTANCES_RESERVED_HEAVY_UTILIZATION_SLES_URL : "heavy",
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINDOWS_URL : "heavy",
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINSQL_URL : "heavy",
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINSQLWEB_URL : "heavy",
}
DEFAULT_CURRENCY = "USD"
INSTANCE_TYPE_MAPPING = {
"stdODI" : "m1",
"uODI" : "t1",
"hiMemODI" : "m2",
"hiCPUODI" : "c1",
"clusterComputeI" : "cc1",
"clusterGPUI" : "cg1",
"hiIoODI" : "hi1",
"secgenstdODI" : "m3",
"hiStoreODI": "hs1",
"clusterHiMemODI": "cr1",
# Reserved Instance Types
"stdResI" : "m1",
"uResI" : "t1",
"hiMemResI" : "m2",
"hiCPUResI" : "c1",
"clusterCompResI" : "cc1",
"clusterGPUResI" : "cg1",
"hiIoResI" : "hi1",
"secgenstdResI" : "m3",
"hiStoreResI": "hs1",
"clusterHiMemResI": "cr1"
}
INSTANCE_SIZE_MAPPING = {
"u" : "micro",
"sm" : "small",
"med" : "medium",
"lg" : "large",
"xl" : "xlarge",
"xxl" : "2xlarge",
"xxxxl" : "4xlarge",
"xxxxxxxxl" : "8xlarge"
}
class ResultsCacheBase(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(ResultsCacheBase, cls).__new__(cls, *args, **kwargs)
return cls._instance
def get(self, key):
pass
def set(self, key, value):
pass
class SimpleResultsCache(ResultsCacheBase):
_cache = {}
def get(self, key):
if key in self._cache:
return self._cache[key]
return None
def set(self, key, value):
self._cache[key] = value
class TimeBasedResultsCache(ResultsCacheBase):
_cache = {}
_cache_expiration = {}
# If you wish to chance this expiration use the following (a bit ugly) code:
#
# TimeBasedResultsCache()._default_expiration_in_seconds = 86400 # 1 day
#
# Since all cache classes inherit from ResultsCacheBase and are singletons that should set it correctly.
#
_default_expiration_in_seconds = 3600 # 1 hour
def get(self, key):
if key not in self._cache or key not in self._cache_expiration:
return None
# If key has expired return None
if self._cache_expiration[key] < datetime.datetime.utcnow():
if key in self._cache: del self._cache[key]
if key in self._cache_expiration: del self._cache_expiration[key]
return None
return self._cache[key]
def set(self, key, value):
self._cache[key] = value
self._cache_expiration[key] = datetime.datetime.utcnow() + datetime.timedelta(seconds=self._default_expiration_in_seconds)
def _load_data(url, use_cache=False, cache_class=SimpleResultsCache):
cache_object = None
if use_cache:
cache_object = cache_class()
result = cache_object.get(url)
if result is not None:
return result
f = urllib.request.urlopen(url)
result = json.loads(f.read())
if use_cache:
cache_object.set(url, result)
return result
def get_ec2_reserved_instances_prices(filter_region=None, filter_instance_type=None, filter_os_type=None, use_cache=False, cache_class=SimpleResultsCache):
""" Get EC2 reserved instances prices. Results can be filtered by region """
get_specific_region = (filter_region is not None)
if get_specific_region:
filter_region = EC2_REGIONS_API_TO_JSON_NAME[filter_region]
get_specific_instance_type = (filter_instance_type is not None)
get_specific_os_type = (filter_os_type is not None)
currency = DEFAULT_CURRENCY
urls = [
INSTANCES_RESERVED_LIGHT_UTILIZATION_LINUX_URL,
INSTANCES_RESERVED_LIGHT_UTILIZATION_RHEL_URL,
INSTANCES_RESERVED_LIGHT_UTILIZATION_SLES_URL,
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINDOWS_URL,
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINSQL_URL,
INSTANCES_RESERVED_LIGHT_UTILIZATION_WINSQLWEB_URL,
INSTANCES_RESERVED_MEDIUM_UTILIZATION_LINUX_URL,
INSTANCES_RESERVED_MEDIUM_UTILIZATION_RHEL_URL,
INSTANCES_RESERVED_MEDIUM_UTILIZATION_SLES_URL,
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINDOWS_URL,
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINSQL_URL,
INSTANCES_RESERVED_MEDIUM_UTILIZATION_WINSQLWEB_URL,
INSTANCES_RESERVED_HEAVY_UTILIZATION_LINUX_URL,
INSTANCES_RESERVED_HEAVY_UTILIZATION_RHEL_URL,
INSTANCES_RESERVED_HEAVY_UTILIZATION_SLES_URL,
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINDOWS_URL,
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINSQL_URL,
INSTANCES_RESERVED_HEAVY_UTILIZATION_WINSQLWEB_URL,
]
result_regions = []
result_regions_index = {}
result = {
"config" : {
"currency" : currency,
},
"regions" : result_regions
}
for u in urls:
os_type = INSTANCES_RESERVED_OS_TYPE_BY_URL[u]
if get_specific_os_type and os_type != filter_os_type:
continue
utilization_type = INSTANCES_RESERVED_UTILIZATION_TYPE_BY_URL[u]
data = _load_data(u, use_cache=use_cache, cache_class=cache_class)
if "config" in data and data["config"] and "regions" in data["config"] and data["config"]["regions"]:
for r in data["config"]["regions"]:
if "region" in r and r["region"]:
if get_specific_region and filter_region != r["region"]:
continue
region_name = JSON_NAME_TO_EC2_REGIONS_API[r["region"]]
if region_name in result_regions_index:
instance_types = result_regions_index[region_name]["instanceTypes"]
else:
instance_types = []
result_regions.append({
"region" : region_name,
"instanceTypes" : instance_types
})
result_regions_index[region_name] = result_regions[-1]
if "instanceTypes" in r:
for it in r["instanceTypes"]:
instance_type = it["type"]
if "sizes" in it:
for s in it["sizes"]:
instance_size = s["size"]
prices = {
"1year" : {
"hourly" : None,
"upfront" : None
},
"3year" : {
"hourly" : None,
"upfront" : None
}
}
_type = instance_size
if _type == "cc1.8xlarge":
# Fix conflict where cc1 and cc2 share the same type
_type = "cc2.8xlarge"
if get_specific_instance_type and _type != filter_instance_type:
continue
if get_specific_os_type and os_type != filter_os_type:
continue
instance_types.append({
"type" : _type,
"os" : os_type,
"utilization" : utilization_type,
"prices" : prices
})
for price_data in s["valueColumns"]:
price = None
try:
price = float(price_data["prices"][currency])
except ValueError:
price = None
if price_data["name"] == "yrTerm1":
prices["1year"]["upfront"] = price
elif price_data["name"] == "yrTerm1Hourly":
prices["1year"]["hourly"] = price
elif price_data["name"] == "yrTerm3":
prices["3year"]["upfront"] = price
elif price_data["name"] == "yrTerm3Hourly":
prices["3year"]["hourly"] = price
return result
def get_ec2_ondemand_instances_prices(filter_region=None, filter_instance_type=None, filter_os_type=None, use_cache=False, cache_class=SimpleResultsCache):
""" Get EC2 on-demand instances prices. Results can be filtered by region """
get_specific_region = (filter_region is not None)
if get_specific_region:
filter_region = EC2_REGIONS_API_TO_JSON_NAME[filter_region]
get_specific_instance_type = (filter_instance_type is not None)
get_specific_os_type = (filter_os_type is not None)
currency = DEFAULT_CURRENCY
urls = [
INSTANCES_ON_DEMAND_LINUX_URL,
INSTANCES_ON_DEMAND_RHEL_URL,
INSTANCES_ON_DEMAND_SLES_URL,
INSTANCES_ON_DEMAND_WINDOWS_URL,
INSTANCES_ON_DEMAND_WINSQL_URL,
INSTANCES_ON_DEMAND_WINSQLWEB_URL
]
result_regions = []
result = {
"config" : {
"currency" : currency,
"unit" : "perhr"
},
"regions" : result_regions
}
for u in urls:
if get_specific_os_type and INSTANCES_ONDEMAND_OS_TYPE_BY_URL[u] != filter_os_type:
continue
data = _load_data(u, use_cache=use_cache, cache_class=cache_class)
if "config" in data and data["config"] and "regions" in data["config"] and data["config"]["regions"]:
for r in data["config"]["regions"]:
if "region" in r and r["region"]:
if get_specific_region and filter_region != r["region"]:
continue
region_name = JSON_NAME_TO_EC2_REGIONS_API[r["region"]]
instance_types = []
if "instanceTypes" in r:
for it in r["instanceTypes"]:
instance_type = it["type"]
if "sizes" in it:
for s in it["sizes"]:
instance_size = s["size"]
for price_data in s["valueColumns"]:
price = None
try:
price = float(price_data["prices"][currency])
except ValueError:
price = None
_type = instance_size
if _type == "cc1.8xlarge":
# Fix conflict where cc1 and cc2 share the same type
_type = "cc2.8xlarge"
if get_specific_instance_type and _type != filter_instance_type:
continue
if get_specific_os_type and price_data["name"] != filter_os_type:
continue
instance_types.append({
"type" : _type,
"os" : price_data["name"],
"price" : price
})
result_regions.append({
"region" : region_name,
"instanceTypes" : instance_types
})
return result
if __name__ == "__main__":
def none_as_string(v):
if not v:
return ""
else:
return v
try:
import argparse
except ImportError:
print("ERROR: You are running Python < 2.7. Please use pip to install argparse: pip install argparse")
parser = argparse.ArgumentParser(add_help=True, description="Print out the current prices of EC2 instances")
parser.add_argument("--type", "-t", help="Show ondemand or reserved instances", choices=["ondemand", "reserved"], required=True)
parser.add_argument("--filter-region", "-fr", help="Filter results to a specific region", choices=EC2_REGIONS, default=None)
parser.add_argument("--filter-type", "-ft", help="Filter results to a specific instance type", choices=EC2_INSTANCE_TYPES, default=None)
parser.add_argument("--filter-os-type", "-fo", help="Filter results to a specific os type", choices=EC2_OS_TYPES, default=None)
parser.add_argument("--format", "-f", choices=["json", "table", "csv"], help="Output format", default="table")
args = parser.parse_args()
if args.format == "table":
try:
from prettytable import PrettyTable
except ImportError:
print("ERROR: Please install 'prettytable' using pip: pip install prettytable")
data = None
if args.type == "ondemand":
data = get_ec2_ondemand_instances_prices(args.filter_region, args.filter_type, args.filter_os_type)
elif args.type == "reserved":
data = get_ec2_reserved_instances_prices(args.filter_region, args.filter_type, args.filter_os_type)
if args.format == "json":
print(json.dumps(data))
elif args.format == "table":
x = PrettyTable()
if args.type == "ondemand":
try:
x.set_field_names(["region", "type", "os", "price"])
except AttributeError:
x.field_names = ["region", "type", "os", "price"]
try:
x.aligns[-1] = "l"
except AttributeError:
x.align["price"] = "l"
for r in data["regions"]:
region_name = r["region"]
for it in r["instanceTypes"]:
x.add_row([region_name, it["type"], it["os"], none_as_string(it["price"])])
elif args.type == "reserved":
try:
x.set_field_names(["region", "type", "os", "utilization", "term", "price", "upfront"])
except AttributeError:
x.field_names = ["region", "type", "os", "utilization", "term", "price", "upfront"]
try:
x.aligns[-1] = "l"
x.aligns[-2] = "l"
except AttributeError:
x.align["price"] = "l"
x.align["upfront"] = "l"
for r in data["regions"]:
region_name = r["region"]
for it in r["instanceTypes"]:
for term in it["prices"]:
x.add_row([region_name, it["type"], it["os"], it["utilization"], term, none_as_string(it["prices"][term]["hourly"]), none_as_string(it["prices"][term]["upfront"])])
print(x)
elif args.format == "csv":
if args.type == "ondemand":
print("region,type,os,price")
for r in data["regions"]:
region_name = r["region"]
for it in r["instanceTypes"]:
print("%s,%s,%s,%s" % (region_name, it["type"], it["os"], none_as_string(it["price"])))
elif args.type == "reserved":
print("region,type,os,utilization,term,price,upfront")
for r in data["regions"]:
region_name = r["region"]
for it in r["instanceTypes"]:
for term in it["prices"]:
print("%s,%s,%s,%s,%s,%s,%s" % (region_name, it["type"], it["os"], it["utilization"], term, none_as_string(it["prices"][term]["hourly"]), none_as_string(it["prices"][term]["upfront"])))

View file

@ -247,7 +247,6 @@ status_freq() {
disk) _RET=13 ;;
disk_io) _RET=3 ;;
distro) _RET=9999991 ;;
ec2_cost) _RET=601 ;;
entropy) _RET=5 ;;
fan_speed) _RET=23 ;;
hostname) _RET=607 ;;

View file

@ -26,12 +26,12 @@
screen_upper_left="color"
screen_upper_right="color whoami hostname ip_address menu"
screen_lower_left="color logo distro release #arch session"
screen_lower_right="color network #disk_io custom #entropy raid reboot_required updates_available #apport #services #mail users uptime #ec2_cost #fan_speed #cpu_temp battery wifi_quality #processes load_average cpu_count cpu_freq memory #swap disk #time_utc date time"
screen_lower_right="color network #disk_io custom #entropy raid reboot_required updates_available #apport #services #mail users uptime #fan_speed #cpu_temp battery wifi_quality #processes load_average cpu_count cpu_freq memory #swap disk #time_utc date time"
# Tmux has one status line, with 2 halves for status
tmux_left="logo #distro release #arch session"
# You can have as many tmux right lines below here, and cycle through them using Shift-F5
tmux_right="#network #disk_io #custom #entropy raid reboot_required updates_available #apport #services #mail #users uptime #ec2_cost #fan_speed #cpu_temp #battery #wifi_quality #processes load_average cpu_count cpu_freq memory #swap disk #whoami #hostname #ip_address #time_utc date time"
#tmux_right="network #disk_io #custom entropy raid reboot_required updates_available #apport #services #mail users uptime #ec2_cost fan_speed cpu_temp battery wifi_quality #processes load_average cpu_count cpu_freq memory #swap #disk whoami hostname ip_address #time_utc date time"
#tmux_right="network #disk_io custom #entropy raid reboot_required updates_available #apport #services #mail users uptime #ec2_cost #fan_speed #cpu_temp battery wifi_quality #processes load_average cpu_count cpu_freq memory #swap #disk #whoami #hostname ip_address #time_utc date time"
#tmux_right="#network disk_io #custom entropy #raid #reboot_required #updates_available #apport #services #mail #users #uptime #ec2_cost fan_speed cpu_temp #battery #wifi_quality #processes #load_average #cpu_count #cpu_freq #memory #swap whoami hostname ip_address #time_utc disk date time"
tmux_right="#network #disk_io #custom #entropy raid reboot_required updates_available #apport #services #mail #users uptime #fan_speed #cpu_temp #battery #wifi_quality #processes load_average cpu_count cpu_freq memory #swap disk #whoami #hostname #ip_address #time_utc date time"
#tmux_right="network #disk_io #custom entropy raid reboot_required updates_available #apport #services #mail users uptime fan_speed cpu_temp battery wifi_quality #processes load_average cpu_count cpu_freq memory #swap #disk whoami hostname ip_address #time_utc date time"
#tmux_right="network #disk_io custom #entropy raid reboot_required updates_available #apport #services #mail users uptime #fan_speed #cpu_temp battery wifi_quality #processes load_average cpu_count cpu_freq memory #swap #disk #whoami #hostname ip_address #time_utc date time"
#tmux_right="#network disk_io #custom entropy #raid #reboot_required #updates_available #apport #services #mail #users #uptime fan_speed cpu_temp #battery #wifi_quality #processes #load_average #cpu_count #cpu_freq #memory #swap whoami hostname ip_address #time_utc disk date time"

View file

@ -51,8 +51,6 @@ The background colors of the \fBbyobu\fP status lines can be adjusted by editing
\fBdistro\fP \- OS/distribution name of the release running on the current system as reported by \fBlsb_release(1)\fP or \fI/etc/issue\fP; displayed in the lower bar in bold black text toward the left on a grey background; you may override the detected release with DISTRO=Whatever in \fI$BYOBU_CONFIG_DIR/statusrc\fP
\fBec2_cost\fP \- an estimation of the cost of the current boot of the system in terms of the Amazon EC2 billing model; displayed in the lower bar toward the right in green text on a black background; the monetary units are US Dollars '$'; this plugin only works when an AWS-compatible metadata server is available at \fIhttp://169.254.169.254\fP
\fBentropy\fP \- a count of the system's current entropy in bytes; displayed in the lower bar toward the right in yellow text on a dark grey background; there is a leading 'e' to indicate 'entropy'
\fBraid\fP \- note very prominently if there is a RAID failure detected, in red blinking text on a white background; the term 'RAID' notes that there is something wrong with the RAID, and if there is a rebuild/resync in progress, the percent complete is also shown