package com.clouck.converter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.convert.ConversionService; import org.springframework.stereotype.Component; import com.amazonaws.services.autoscaling.model.AutoScalingGroup; import com.amazonaws.services.autoscaling.model.LaunchConfiguration; import com.amazonaws.services.ec2.model.Address; import com.amazonaws.services.ec2.model.DhcpOptions; import com.amazonaws.services.ec2.model.GroupIdentifier; import com.amazonaws.services.ec2.model.Image; import com.amazonaws.services.ec2.model.Instance; import com.amazonaws.services.ec2.model.InternetGateway; import com.amazonaws.services.ec2.model.InternetGatewayAttachment; import com.amazonaws.services.ec2.model.KeyPairInfo; import com.amazonaws.services.ec2.model.NetworkAcl; import com.amazonaws.services.ec2.model.NetworkAclAssociation; import com.amazonaws.services.ec2.model.NetworkInterface; import com.amazonaws.services.ec2.model.NetworkInterfacePrivateIpAddress; import com.amazonaws.services.ec2.model.PlacementGroup; import com.amazonaws.services.ec2.model.RouteTable; import com.amazonaws.services.ec2.model.SecurityGroup; import com.amazonaws.services.ec2.model.Snapshot; import com.amazonaws.services.ec2.model.Subnet; import com.amazonaws.services.ec2.model.Volume; import com.amazonaws.services.ec2.model.Vpc; import com.amazonaws.services.identitymanagement.model.Group; import com.amazonaws.services.identitymanagement.model.Role; import com.amazonaws.services.identitymanagement.model.User; import com.clouck.application.Ec2Constants; import com.clouck.exception.CloudVersionIllegalStateException; import com.clouck.model.Event; import com.clouck.model.EventType; import com.clouck.model.Region; import com.clouck.model.ResourceType; import com.clouck.model.aws.AbstractResource; import com.clouck.model.aws.ec2.Ec2Ami; import com.clouck.model.aws.ec2.Ec2AutoScalingGroup; import com.clouck.model.aws.ec2.Ec2ElasticIP; import com.clouck.model.aws.ec2.Ec2Instance; import com.clouck.model.aws.ec2.Ec2KeyPair; import com.clouck.model.aws.ec2.Ec2LaunchConfiguration; import com.clouck.model.aws.ec2.Ec2NetworkInterface; import com.clouck.model.aws.ec2.Ec2PlacementGroup; import com.clouck.model.aws.ec2.Ec2SecurityGroup; import com.clouck.model.aws.ec2.Ec2Snapshot; import com.clouck.model.aws.ec2.Ec2Version; import com.clouck.model.aws.ec2.Ec2VersionMeta; import com.clouck.model.aws.ec2.Ec2Volume; import com.clouck.model.aws.ec2.VpcDhcpOptions; import com.clouck.model.aws.ec2.VpcInternetGateway; import com.clouck.model.aws.ec2.VpcNetworkAcl; import com.clouck.model.aws.ec2.VpcRouteTable; import com.clouck.model.aws.ec2.VpcSubnet; import com.clouck.model.aws.ec2.VpcVpc; import com.clouck.model.aws.iam.IamGroup; import com.clouck.model.aws.iam.IamRole; import com.clouck.model.aws.iam.IamUser; import com.clouck.rep.ChartDataRep; import com.clouck.rep.ChartDataSeriesRep; import com.clouck.rep.DataTableRep; import com.clouck.rep.Ec2ResourceRep; import com.clouck.rep.Ec2VersionMetaRep; import com.clouck.rep.EventRep; import com.clouck.rep.HighChartsDataRep; import com.clouck.rep.HighChartsRep; import com.clouck.rep.HighChartsSeriesRep; import com.clouck.service.AwsService; import com.clouck.wrapper.spring.MRWrapper; @Component public class RepConverter { private static final Logger log = LoggerFactory.getLogger(RepConverter.class); @Autowired private ConversionService conversionService; @Autowired private AwsService awsService; @Autowired private MRWrapper mrWrapper; public <T> T convert(Object source, Class<T> targetType) { return conversionService.convert(source, targetType); } public List<Ec2VersionMetaRep> toEc2VersionMetaReps(List<Ec2VersionMeta> ec2VersionMetas) { List<Ec2VersionMetaRep> result = new ArrayList<>(); for (Ec2VersionMeta meta : ec2VersionMetas) { result.add(toEc2VersionMetaRep(meta)); } return result; } public Ec2VersionMetaRep toEc2VersionMetaRep(Ec2VersionMeta ec2VersionMeta) { Ec2VersionMetaRep result = new Ec2VersionMetaRep(); result.setTimeDetected(new DateTime(ec2VersionMeta.getTimeDetected()).toLocalDateTime().toString(Ec2Constants.Date_Time_Format)); result.setMillis(ec2VersionMeta.getTimeDetected().getTime()); result.setRegion(ec2VersionMeta.getRegion()); List<EventRep> reps = new ArrayList<>(); for (Event event : ec2VersionMeta.getEvents()) { EventRep rep = new EventRep(); EventType et = event.getEventType(); String message = mrWrapper.getEventMessage(et, event); rep.setMessage(message); reps.add(rep); } result.setReps(reps); return result; } public List<Ec2ResourceRep> toEc2ResourceReps(List<Ec2VersionMeta> ec2VersionMetas, String uniqueId) { List<Ec2ResourceRep> result = new ArrayList<>(); for (Ec2VersionMeta ec2VersionMeta : ec2VersionMetas) { result.add(toEc2ResourceRep(ec2VersionMeta, uniqueId)); } return result; } public Ec2ResourceRep toEc2ResourceRep(Ec2VersionMeta ec2VersionMeta, String uniqueId) { Ec2ResourceRep result = new Ec2ResourceRep(); result.setTimeDetected(new DateTime(ec2VersionMeta.getTimeDetected()).toLocalDateTime().toString(Ec2Constants.Date_Time_Format)); result.setRegion(ec2VersionMeta.getRegion()); String resourceId = null; for (Event event : ec2VersionMeta.getEvents()) { if (event.getUniqueId() != null && event.getUniqueId().equals(uniqueId)) { EventRep rep = new EventRep(); resourceId = event.getNewResourceId(); EventType et = event.getEventType(); String message = mrWrapper.getEventMessage(et, event); rep.setMessage(message); result.getReps().add(rep); } } result.setResourceId(resourceId); return result; } // public List<EventRep> toEventReps(List<Event> events) { // List<EventRep> result = new ArrayList<>(); // for (Event event : events) { // result.add(toEventRep(event)); // } // return result; // } // public EventRep toEventRep(Event event) { // EventRep result = new EventRep(); // result.setUniqueId(event.getUniqueId()); // result.setResourceId(event.getResourceId()); // return result; // } // // public ResourceSizeRep toResourceSizeRep(int instanceSize, int securityGroupSize, int snapshotSize, int imageSize, int volumeSize) { // ResourceSizeRep res = new ResourceSizeRep(); // res.setInstance_size(instanceSize); // res.setSecurity_group_size(securityGroupSize); // res.setSnapshot_size(snapshotSize); // res.setVolume_size(volumeSize); // return res; // } public HighChartsRep toHigCharts(ResourceType resourceType, List<Ec2Version> ec2Versions) { HighChartsRep result = new HighChartsRep(); if (resourceType.isMultiRegion()) { Map<Region, HighChartsSeriesRep> region2Series = new HashMap<>(); for (Region region : Region.findAvailableRegions(resourceType)) { HighChartsSeriesRep rep = new HighChartsSeriesRep(); rep.setName(region.toString()); region2Series.put(region, rep); } for (int i = 0; i < ec2Versions.size(); i++) { Ec2Version ec2Version = ec2Versions.get(i); if (i != 0) { HighChartsSeriesRep seriesRep = region2Series.get(ec2Version.getRegion()); if (ec2Version.getResourceIds().size() != 0) { List<HighChartsDataRep> dataReps = seriesRep.getData(); dataReps.set(0, new HighChartsDataRep(ec2Version.getResourceIds().size(), ec2Version.getId(), ec2Version.getTimeDetected().getTime())); } } else { SimpleDateFormat sdf = new SimpleDateFormat("dd/MM kk:mm"); result.addCategory(sdf.format(ec2Version.getTimeDetected())); HighChartsSeriesRep seriesRep = region2Series.get(ec2Version.getRegion()); if (ec2Version.getResourceIds().size() == 0) { seriesRep.addData(new HighChartsDataRep(null, ec2Version.getId(), ec2Version.getTimeDetected().getTime())); } else { seriesRep.addData(new HighChartsDataRep(ec2Version.getResourceIds().size(), ec2Version.getId(), ec2Version.getTimeDetected().getTime())); } for (Region region : Region.findAvailableRegions(resourceType)) { if (!region.equals(ec2Version.getRegion())) { HighChartsSeriesRep otherSeriesRep = region2Series.get(region); List<HighChartsDataRep> dataReps = otherSeriesRep.getData(); if (dataReps.size() == 0) { otherSeriesRep.addData(new HighChartsDataRep(null, ec2Version.getId(), ec2Version.getTimeDetected().getTime())); } else { HighChartsDataRep dataRep = dataReps.get(dataReps.size() - 1); otherSeriesRep.addData(dataRep.clone(ec2Version.getTimeDetected().getTime())); } } } } } // remove items which are not in this page int size = result.getCategories().size(); if (size > Ec2Constants.High_Charts_Page_Size) { List<String> categories = result.getCategories(); result.setCategories(categories.subList(size - Ec2Constants.High_Charts_Page_Size, size)); for (HighChartsSeriesRep rep : region2Series.values()) { rep.setData(rep.getData().subList(size - Ec2Constants.High_Charts_Page_Size, size)); result.addSerie(rep); } } else { for (HighChartsSeriesRep rep : region2Series.values()) { result.addSerie(rep); } } } else { HighChartsSeriesRep rep = new HighChartsSeriesRep(); //TODO: XXX rep.setName("what is this?"); for (int i = 0; i < ec2Versions.size(); i++) { Ec2Version ec2Version = ec2Versions.get(i); SimpleDateFormat sdf = new SimpleDateFormat("dd/MM kk:mm"); result.addCategory(sdf.format(ec2Version.getTimeDetected())); if (ec2Version.getResourceIds().size() == 0) { rep.addData(new HighChartsDataRep(null, ec2Version.getId(), ec2Version.getTimeDetected().getTime())); } else { rep.addData(new HighChartsDataRep(ec2Version.getResourceIds().size(), ec2Version.getId(), ec2Version.getTimeDetected().getTime())); } } // remove items which are not in this page int size = result.getCategories().size(); if (size > Ec2Constants.High_Charts_Page_Size) { List<String> categories = result.getCategories(); result.setCategories(categories.subList(size - Ec2Constants.High_Charts_Page_Size, size)); rep.setData(rep.getData().subList(size - Ec2Constants.High_Charts_Page_Size, size)); result.addSerie(rep); } else { result.addSerie(rep); } } return result; } public DataTableRep toDataTableData(Collection<AbstractResource<?>> resources) { DataTableRep result = new DataTableRep(); for (AbstractResource<?> resource : resources) { result.addRow(createRow(resource)); } return result; } //TODO: I need to move this to a more proper json format intead of table format. private List<String> createRow(AbstractResource<?> resource) { List<String> result = new ArrayList<>(); ResourceType rt = ResourceType.find(resource); switch (rt) { case Ec2_Reservation: Ec2Instance ec2Instance = (Ec2Instance) resource; Instance instance = ec2Instance.getResource(); result.add(resource.getRegion().toString()); result.add(instance.getInstanceId()); result.add(instance.getState().getName()); result.add(instance.getPublicDnsName()); result.add(instance.getPrivateIpAddress()); break; case Ec2_Security_Group: Ec2SecurityGroup ec2SecurityGroup = (Ec2SecurityGroup) resource; SecurityGroup securityGroup = ec2SecurityGroup.getResource(); result.add(resource.getRegion().toString()); result.add(securityGroup.getGroupId()); result.add(securityGroup.getGroupName()); result.add(securityGroup.getDescription()); result.add(securityGroup.getVpcId()); break; case Ec2_Ami: Ec2Ami ec2Ami = (Ec2Ami) resource; Image image = ec2Ami.getResource(); result.add(resource.getRegion().toString()); result.add(image.getImageId()); result.add(image.getName()); result.add(image.getState().toString()); result.add(image.getArchitecture()); result.add(image.getPlatform()); result.add(image.getDescription()); result.add(image.getRootDeviceType()); result.add(image.getHypervisor()); break; case Ec2_Volume: Ec2Volume ec2Volume = (Ec2Volume) resource; Volume volume = ec2Volume.getResource(); result.add(resource.getRegion().toString()); result.add(volume.getVolumeId()); result.add(volume.getSize().toString() + " GiB"); result.add(volume.getAvailabilityZone()); result.add(volume.getState().toString()); result.add(volume.getCreateTime().toString()); result.add(volume.getVolumeType()); break; case Ec2_Snapshot: Ec2Snapshot ec2Snapshot = (Ec2Snapshot) resource; Snapshot snapshot = ec2Snapshot.getResource(); result.add(resource.getRegion().toString()); result.add(snapshot.getSnapshotId()); result.add(snapshot.getDescription()); result.add(snapshot.getStartTime().toString()); result.add(snapshot.getVolumeSize().toString() + " GiB"); break; case Ec2_Key_Pair: Ec2KeyPair ec2KeyPair = (Ec2KeyPair) resource; KeyPairInfo keyPair = ec2KeyPair.getResource(); result.add(resource.getRegion().toString()); result.add(keyPair.getKeyName()); result.add(keyPair.getKeyFingerprint()); break; case Ec2_Elastic_IP: Ec2ElasticIP ec2ElasticIP = (Ec2ElasticIP) resource; Address address = ec2ElasticIP.getResource(); result.add(resource.getRegion().toString()); result.add(address.getPublicIp()); result.add(address.getInstanceId()); result.add(address.getNetworkInterfaceId()); break; case Ec2_Placement_Group: Ec2PlacementGroup ec2PlacementGroup = (Ec2PlacementGroup) resource; PlacementGroup placementGroup = ec2PlacementGroup.getResource(); result.add(resource.getRegion().toString()); result.add(placementGroup.getGroupName()); result.add(placementGroup.getStrategy()); result.add(placementGroup.getState()); break; case Ec2_Network_Interface: Ec2NetworkInterface ec2NetworkInterface = (Ec2NetworkInterface) resource; NetworkInterface networkInterface = ec2NetworkInterface.getResource(); result.add(resource.getRegion().toString()); result.add(networkInterface.getNetworkInterfaceId()); result.add(networkInterface.getSubnetId()); result.add(networkInterface.getAvailabilityZone()); StringBuilder sb = new StringBuilder(); List<GroupIdentifier> groups = networkInterface.getGroups(); for (int i = 0; i < groups.size(); i++) { if (i != groups.size() - 1) { sb.append(groups.get(i).getGroupName() + ", "); } else { sb.append(groups.get(i).getGroupName()); } } result.add(sb.toString()); result.add(networkInterface.getDescription()); if (networkInterface.getAttachment() != null) { result.add(networkInterface.getAttachment().getInstanceId()); } else { result.add(""); } result.add(networkInterface.getStatus()); if (networkInterface.getAssociation() != null) { result.add(networkInterface.getAssociation().getPublicIp()); } else { result.add(""); } result.add(networkInterface.getPrivateIpAddress()); List<NetworkInterfacePrivateIpAddress> privateIpAddresses = networkInterface.getPrivateIpAddresses(); List<NetworkInterfacePrivateIpAddress> secondaryAddresses = new ArrayList<>(); for (NetworkInterfacePrivateIpAddress privateIpAddress : privateIpAddresses) { if (!privateIpAddress.getPrimary()) { secondaryAddresses.add(privateIpAddress); } } StringBuilder sb1 = new StringBuilder(); for (int i = 0; i < secondaryAddresses.size(); i++) { if (i != secondaryAddresses.size() - 1) { sb1.append(secondaryAddresses.get(i).getPrivateIpAddress() + ", "); } else { sb1.append(secondaryAddresses.get(i).getPrivateIpAddress()); } } result.add(sb1.toString()); break; case Ec2_Launch_Configuration: Ec2LaunchConfiguration ec2LaunchConf = (Ec2LaunchConfiguration) resource; LaunchConfiguration launchConf = ec2LaunchConf.getResource(); result.add(resource.getRegion().toString()); result.add(launchConf.getImageId()); break; case Ec2_Auto_Scaling_Group: Ec2AutoScalingGroup ec2AutoScalingGroup = (Ec2AutoScalingGroup) resource; AutoScalingGroup autoScalingGroup = ec2AutoScalingGroup.getResource(); result.add(resource.getRegion().toString()); result.add(autoScalingGroup.getAutoScalingGroupName()); break; case Vpc_Vpc: VpcVpc vpcVpc = (VpcVpc) resource; Vpc vpc = vpcVpc.getResource(); result.add(resource.getRegion().toString()); result.add(vpc.getVpcId()); result.add(vpc.getState()); result.add(vpc.getCidrBlock()); result.add(vpc.getDhcpOptionsId()); result.add(vpc.getInstanceTenancy()); //TODO: need to add main route table, default network acl. break; case Vpc_Subnet: VpcSubnet vpcSubnet = (VpcSubnet) resource; Subnet subnet = vpcSubnet.getResource(); result.add(resource.getRegion().toString()); result.add(subnet.getSubnetId()); result.add(subnet.getState()); result.add(subnet.getVpcId()); result.add(subnet.getCidrBlock()); result.add(subnet.getAvailableIpAddressCount().toString()); result.add(subnet.getAvailabilityZone()); //TODO: Add route table, network acl break; case Vpc_Route_Table: VpcRouteTable vpcRouteTable = (VpcRouteTable) resource; RouteTable routeTable = vpcRouteTable.getResource(); result.add(resource.getRegion().toString()); result.add(routeTable.getRouteTableId()); result.add(routeTable.getVpcId()); //TODO: need to add others break; case Vpc_Internet_Gateway: VpcInternetGateway vpcInternetGateway = (VpcInternetGateway) resource; InternetGateway internetGateway = vpcInternetGateway.getResource(); result.add(resource.getRegion().toString()); result.add(internetGateway.getInternetGatewayId()); List<InternetGatewayAttachment> attachments = internetGateway.getAttachments(); if (attachments.size() == 0) { result.add(""); result.add(""); } else if (attachments.size() == 1) { result.add(attachments.get(0).getState()); result.add(attachments.get(0).getVpcId()); } else { throw new CloudVersionIllegalStateException("internet gateway should at most have 1 attachment, but we've got " + attachments.size()); } break; case Vpc_DhcpOptions: VpcDhcpOptions vpcDhcpOptions = (VpcDhcpOptions) resource; DhcpOptions dhcpOptions = vpcDhcpOptions.getResource(); result.add(resource.getRegion().toString()); result.add(dhcpOptions.getDhcpOptionsId()); //TODO: ADD Options break; case Vpc_NetworkAcl: VpcNetworkAcl vpcNetworkAcl = (VpcNetworkAcl) resource; NetworkAcl networkAcl = vpcNetworkAcl.getResource(); result.add(resource.getRegion().toString()); result.add(networkAcl.getNetworkAclId()); List<NetworkAclAssociation> associations = networkAcl.getAssociations(); result.add(associations.size() + " Subnets"); result.add(networkAcl.getIsDefault() ? "Yes" : "No"); result.add(networkAcl.getVpcId()); break; case Iam_Group: IamGroup iamGroup = (IamGroup) resource; Group group = iamGroup.getResource(); result.add(group.getGroupName()); result.add(group.getCreateDate().toString()); break; case Iam_User: IamUser iamUser = (IamUser) resource; User user = iamUser.getResource(); result.add(user.getUserName()); result.add(user.getCreateDate().toString()); break; case Iam_Role: IamRole iamRole = (IamRole) resource; Role role = iamRole.getResource(); result.add(role.getRoleName()); result.add(role.getCreateDate().toString()); break; default: throw new CloudVersionIllegalStateException("unhandled resource type:" + rt); } result.add(resource.getTimeDetected().toString()); return result; } // private Long calculateTotal(Map<Region, Long> region2Num) { // Long total = 0L; // for (Region key : region2Num.keySet()) { // Long num = region2Num.get(key); // if (num != null) { // total += num; // } // } // return total; // } private List<Long> createPoint(Long millis, Long size) { List<Long> point = new ArrayList<>(); point.add(millis); point.add(size); return point; } public ChartDataRep toChartData(ResourceType resourceType, List<Ec2Version> ec2Versions) { ChartDataRep result = new ChartDataRep(); ChartDataSeriesRep srep = new ChartDataSeriesRep(); result.addSerie(srep); int size = 0; for (Ec2Version ec2Version : ec2Versions) { size = ec2Version.getResourceIds().size(); srep.addData(createPoint(ec2Version.getTimeDetected().getTime(), Long.valueOf(size))); } // for (int i = 0; i < ec2Versions.size(); i++) { // region2Num.put(ec2Versions.get(i).getRegion(), Long.valueOf(ec2Versions.get(i).getResourceIds().size())); // if (!ec2Versions.get(i).isFirstTimeScan() // || (ec2Versions.get(i).isFirstTimeScan() // && region2Num.keySet().size() == Region.findAvailableRegions(resourceType).size())) { // srep.addData(createPoint(ec2Versions.get(i), region2Num)); // } // } return result; } public DataTableRep toDataTableData(String accountId, String resourceType, Region region, List<Ec2VersionMeta> ec2VersionMetas, Integer sEcho, long totalNumEc2VersionMetas, long numOfFilteredEc2VersionMetas, String ctx) { DataTableRep result = new DataTableRep(); result.setiTotalRecords((int)totalNumEc2VersionMetas); result.setiTotalDisplayRecords((int)numOfFilteredEc2VersionMetas); result.setsEcho(sEcho); List<List<String>> aaData = new ArrayList<>(); for (Ec2VersionMeta meta : ec2VersionMetas) { List<String> row = new ArrayList<>(); row.add(meta.getRegion().name()); row.add(new DateTime(meta.getTimeDetected()).toString(Ec2Constants.Date_Time_Format)); StringBuilder sb = new StringBuilder(); List<Event> events = meta.getEvents(); for (int i = 0; i < events.size(); i++) { Event event = events.get(i); EventType et = event.getEventType(); String message = mrWrapper.getEventMessage(et, event); if (i != events.size() - 1) { sb.append(message + "<br>"); } else { sb.append(message); } } row.add(sb.toString()); sb = new StringBuilder(); sb.append("<a class=\"btn\" href=\""+ ctx + "/accounts/"); sb.append(accountId); sb.append("/ec2/"); sb.append(resourceType); sb.append("?at="); sb.append(meta.getTimeDetected().getTime()); if (!region.equals(Region.All)) { sb.append("®ion="); sb.append(region.getRegions().getName()); } sb.append("\">Browse</a>"); row.add(sb.toString()); aaData.add(row); } result.setAaData(aaData); return result; } public List<Object> toResources(List<AbstractResource<?>> ec2Resources) { List<Object> result = new ArrayList<>(); for (AbstractResource<?> resource : ec2Resources) { result.add(resource.getResource()); } return result; } }