use of com.netflix.ice.tag.Account in project ice by Netflix.
the class BillingFileProcessor method borrow.
private void borrow(int i, long time, Map<TagGroup, Double> usageMap, Map<TagGroup, Double> costMap, List<Account> fromAccounts, TagGroup tagGroup, Ec2InstanceReservationPrice.ReservationUtilization utilization, boolean forBonus) {
Double existing = usageMap.get(tagGroup);
if (existing != null && config.accountService.externalMappingExist(tagGroup.account, tagGroup.zone) && fromAccounts != null) {
for (Account from : fromAccounts) {
if (existing <= 0)
break;
TagGroup unusedTagGroup = new TagGroup(from, tagGroup.region, tagGroup.zone, tagGroup.product, Operation.getUnusedInstances(utilization), tagGroup.usageType, null);
Double unused = usageMap.get(unusedTagGroup);
if (unused != null && unused > 0) {
double hourlyCost = costMap.get(unusedTagGroup) / unused;
double reservedBorrowed = Math.min(existing, unused);
double reservedUnused = unused - reservedBorrowed;
existing -= reservedBorrowed;
TagGroup borrowedTagGroup = new TagGroup(tagGroup.account, tagGroup.region, tagGroup.zone, tagGroup.product, Operation.getBorrowedInstances(utilization), tagGroup.usageType, null);
TagGroup lentTagGroup = new TagGroup(from, tagGroup.region, tagGroup.zone, tagGroup.product, Operation.getLentInstances(utilization), tagGroup.usageType, null);
Double existingLent = usageMap.get(lentTagGroup);
double reservedLent = existingLent == null ? reservedBorrowed : reservedBorrowed + existingLent;
Double existingBorrowed = usageMap.get(borrowedTagGroup);
reservedBorrowed = existingBorrowed == null ? reservedBorrowed : reservedBorrowed + existingBorrowed;
usageMap.put(borrowedTagGroup, reservedBorrowed);
costMap.put(borrowedTagGroup, reservedBorrowed * hourlyCost);
usageMap.put(lentTagGroup, reservedLent);
costMap.put(lentTagGroup, reservedLent * hourlyCost);
usageMap.put(tagGroup, existing);
costMap.put(tagGroup, existing * hourlyCost);
usageMap.put(unusedTagGroup, reservedUnused);
costMap.put(unusedTagGroup, reservedUnused * hourlyCost);
}
}
}
// the rest is bonus
if (existing != null && existing > 0 && !forBonus) {
ReservationService.ReservationInfo reservation = config.reservationService.getReservation(time, tagGroup, utilization);
TagGroup bonusTagGroup = new TagGroup(tagGroup.account, tagGroup.region, tagGroup.zone, tagGroup.product, Operation.getBonusReservedInstances(utilization), tagGroup.usageType, null);
usageMap.put(bonusTagGroup, existing);
costMap.put(bonusTagGroup, existing * reservation.reservationHourlyCost);
usageMap.remove(tagGroup);
costMap.remove(tagGroup);
}
}
use of com.netflix.ice.tag.Account in project ice by Netflix.
the class BasicAccountService method getAccountById.
public Account getAccountById(String accountId) {
Account account = accountsById.get(accountId);
if (account == null) {
account = new Account(accountId, accountId);
accountsByName.put(account.name, account);
accountsById.put(account.id, account);
logger.info("created account " + accountId + ".");
}
return account;
}
use of com.netflix.ice.tag.Account in project ice by Netflix.
the class BasicAccountService method getAccountByName.
public Account getAccountByName(String accountName) {
Account account = accountsByName.get(accountName);
// data/tags are updated properly once the mapping is established in ice.properties
if (account == null) {
account = accountsById.get(accountName);
}
if (account == null) {
account = new Account(accountName, accountName);
accountsByName.put(account.name, account);
accountsById.put(account.id, account);
}
return account;
}
use of com.netflix.ice.tag.Account in project ice by Netflix.
the class BillingFileProcessor method processReservations.
private void processReservations(Ec2InstanceReservationPrice.ReservationUtilization utilization) {
if (config.reservationService.getTagGroups(utilization).size() == 0)
return;
ReadWriteData usageData = usageDataByProduct.get(null);
ReadWriteData costData = costDataByProduct.get(null);
Map<Account, List<Account>> reservationAccounts = config.accountService.getReservationAccounts();
Set<Account> reservationOwners = reservationAccounts.keySet();
Map<Account, List<Account>> reservationBorrowers = Maps.newHashMap();
for (Account account : reservationAccounts.keySet()) {
List<Account> list = reservationAccounts.get(account);
for (Account borrowingAccount : list) {
if (borrowingAccount.name.equals(account.name))
continue;
List<Account> from = reservationBorrowers.get(borrowingAccount);
if (from == null) {
from = Lists.newArrayList();
reservationBorrowers.put(borrowingAccount, from);
}
from.add(account);
}
}
// first mark owner accounts
Set<TagGroup> toMarkOwners = Sets.newTreeSet();
for (TagGroup tagGroup : config.reservationService.getTagGroups(utilization)) {
for (int i = 0; i < usageData.getNum(); i++) {
Map<TagGroup, Double> usageMap = usageData.getData(i);
Map<TagGroup, Double> costMap = costData.getData(i);
Double existing = usageMap.get(tagGroup);
double value = existing == null ? 0 : existing;
ReservationService.ReservationInfo reservation = config.reservationService.getReservation(startMilli + i * AwsUtils.hourMillis, tagGroup, utilization);
double reservedUsed = Math.min(value, reservation.capacity);
double reservedUnused = reservation.capacity - reservedUsed;
double bonusReserved = value > reservation.capacity ? value - reservation.capacity : 0;
if (reservedUsed > 0 || existing != null) {
usageMap.put(tagGroup, reservedUsed);
costMap.put(tagGroup, reservedUsed * reservation.reservationHourlyCost);
}
if (reservedUnused > 0) {
TagGroup unusedTagGroup = new TagGroup(tagGroup.account, tagGroup.region, tagGroup.zone, tagGroup.product, Operation.getUnusedInstances(utilization), tagGroup.usageType, null);
usageMap.put(unusedTagGroup, reservedUnused);
costMap.put(unusedTagGroup, reservedUnused * reservation.reservationHourlyCost);
}
if (bonusReserved > 0) {
TagGroup bonusTagGroup = new TagGroup(tagGroup.account, tagGroup.region, tagGroup.zone, tagGroup.product, Operation.getBonusReservedInstances(utilization), tagGroup.usageType, null);
usageMap.put(bonusTagGroup, bonusReserved);
costMap.put(bonusTagGroup, bonusReserved * reservation.reservationHourlyCost);
}
if (reservation.capacity > 0) {
TagGroup upfrontTagGroup = new TagGroup(tagGroup.account, tagGroup.region, tagGroup.zone, tagGroup.product, Operation.getUpfrontAmortized(utilization), tagGroup.usageType, null);
costMap.put(upfrontTagGroup, reservation.capacity * reservation.upfrontAmortized);
}
}
toMarkOwners.add(new TagGroup(tagGroup.account, tagGroup.region, tagGroup.zone, tagGroup.product, Operation.getReservedInstances(utilization), tagGroup.usageType, null));
}
// now mark borrowing accounts
Set<TagGroup> toMarkBorrowing = Sets.newTreeSet();
for (TagGroup tagGroup : usageData.getTagGroups()) {
if (tagGroup.resourceGroup == null && tagGroup.product == Product.ec2_instance && (tagGroup.operation == Operation.getReservedInstances(utilization) && !toMarkOwners.contains(tagGroup) || tagGroup.operation == Operation.getBonusReservedInstances(utilization))) {
toMarkBorrowing.add(tagGroup);
}
}
for (TagGroup tagGroup : toMarkBorrowing) {
for (int i = 0; i < usageData.getNum(); i++) {
Map<TagGroup, Double> usageMap = usageData.getData(i);
Map<TagGroup, Double> costMap = costData.getData(i);
borrow(i, startMilli + i * AwsUtils.hourMillis, usageMap, costMap, reservationBorrowers.get(tagGroup.account), tagGroup, utilization, reservationOwners.contains(tagGroup.account));
}
}
}
use of com.netflix.ice.tag.Account in project ice by Netflix.
the class ReservationCapacityPoller method poll.
@Override
protected void poll() throws Exception {
ProcessorConfig config = ProcessorConfig.getInstance();
// read from s3 if not exists
File file = new File(config.localDir, "reservation_capacity.txt");
if (!file.exists()) {
logger.info("downloading " + file + "...");
AwsUtils.downloadFileIfNotExist(config.workS3BucketName, config.workS3BucketPrefix, file);
logger.info("downloaded " + file);
}
// read from file
Map<String, ReservedInstances> reservations = Maps.newTreeMap();
if (file.exists()) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String line;
while ((line = reader.readLine()) != null) {
String[] tokens = line.split(",");
String accountId = tokens[0];
String region = tokens[1];
String reservationId = tokens[2];
String zone = tokens[3];
Long start = Long.parseLong(tokens[4]);
long duration = Long.parseLong(tokens[5]);
String instanceType = tokens[6];
String productDescription = tokens[7];
int instanceCount = Integer.parseInt(tokens[8]);
String offeringType = tokens[9];
String state = tokens[10];
Long end = tokens.length > 11 ? Long.parseLong(tokens[11]) : null;
float fixedPrice = tokens.length > 12 ? Float.parseFloat(tokens[12]) : 0;
float usagePrice = tokens.length > 13 ? Float.parseFloat(tokens[13]) : 0;
ReservedInstances reservation = new ReservedInstances().withAvailabilityZone(zone).withStart(new Date(start)).withDuration(duration).withInstanceType(instanceType).withProductDescription(productDescription).withInstanceCount(instanceCount).withOfferingType(offeringType).withState(state).withFixedPrice(fixedPrice).withUsagePrice(usagePrice);
if (end != null)
reservation.setEnd(new Date(end));
else
reservation.setEnd(new Date(start + duration * 1000));
reservations.put(accountId + "," + region + "," + reservationId, reservation);
}
} catch (Exception e) {
logger.error("error in reading " + file, e);
} finally {
if (reader != null)
try {
reader.close();
} catch (Exception e) {
}
}
}
logger.info("read " + reservations.size() + " reservations.");
for (Account account : config.accountService.getReservationAccounts().keySet()) {
try {
AmazonEC2Client ec2Client;
String assumeRole = config.accountService.getReservationAccessRoles().get(account);
if (assumeRole != null) {
String externalId = config.accountService.getReservationAccessExternalIds().get(account);
final Credentials credentials = AwsUtils.getAssumedCredentials(account.id, assumeRole, externalId);
ec2Client = new AmazonEC2Client(new AWSSessionCredentials() {
public String getAWSAccessKeyId() {
return credentials.getAccessKeyId();
}
public String getAWSSecretKey() {
return credentials.getSecretAccessKey();
}
public String getSessionToken() {
return credentials.getSessionToken();
}
});
} else
ec2Client = new AmazonEC2Client(AwsUtils.awsCredentialsProvider.getCredentials(), AwsUtils.clientConfig);
for (Region region : Region.getAllRegions()) {
ec2Client.setEndpoint("ec2." + region.name + ".amazonaws.com");
try {
DescribeReservedInstancesResult result = ec2Client.describeReservedInstances();
for (ReservedInstances reservation : result.getReservedInstances()) {
String key = account.id + "," + region.name + "," + reservation.getReservedInstancesId();
reservations.put(key, reservation);
if (reservation.getEnd() == null)
reservation.setEnd(new Date(reservation.getStart().getTime() + reservation.getDuration() * 1000L));
if (reservation.getFixedPrice() == null)
reservation.setFixedPrice(0f);
if (reservation.getUsagePrice() == null)
reservation.setUsagePrice(0f);
}
} catch (Exception e) {
logger.error("error in describeReservedInstances for " + region.name + " " + account.name, e);
}
}
ec2Client.shutdown();
} catch (Exception e) {
logger.error("Error in describeReservedInstances for " + account.name, e);
}
}
config.reservationService.updateEc2Reservations(reservations);
updatedConfig = true;
// archive to disk
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
for (String key : reservations.keySet()) {
ReservedInstances reservation = reservations.get(key);
String[] line = new String[] { key, reservation.getAvailabilityZone(), reservation.getStart().getTime() + "", reservation.getDuration().toString(), reservation.getInstanceType(), reservation.getProductDescription(), reservation.getInstanceCount().toString(), reservation.getOfferingType(), reservation.getState(), reservation.getEnd().getTime() + "", reservation.getFixedPrice() + "", reservation.getUsagePrice() + "" };
writer.write(StringUtils.join(line, ","));
writer.newLine();
}
} catch (Exception e) {
logger.error("", e);
} finally {
if (writer != null)
try {
writer.close();
} catch (Exception e) {
}
}
logger.info("archived " + reservations.size() + " reservations.");
// archive to s3
logger.info("uploading " + file + "...");
AwsUtils.upload(config.workS3BucketName, config.workS3BucketPrefix, config.localDir, file.getName());
logger.info("uploaded " + file);
}
Aggregations