diff --git a/.gitignore b/.gitignore index c8266e8..d428ddb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ token.txt +.env \ No newline at end of file diff --git a/lab4/4.1-hetzner/deploy.sh b/lab4/4.1-hetzner/deploy.sh new file mode 100644 index 0000000..0c11a46 --- /dev/null +++ b/lab4/4.1-hetzner/deploy.sh @@ -0,0 +1,5 @@ +#!/bin/bash +pip install hcloud + +python del_gitea.py +python lab4/4.1-hetzner/start-hetzner.py \ No newline at end of file diff --git a/lab4/4.1-hetzner/start-hetzner.py b/lab4/4.1-hetzner/start-hetzner.py new file mode 100644 index 0000000..69bffb1 --- /dev/null +++ b/lab4/4.1-hetzner/start-hetzner.py @@ -0,0 +1,116 @@ +from hcloud import Client + +from hcloud.images.domain import Image +from hcloud.server_types.domain import ServerType + +from hcloud.networks.domain import NetworkSubnet + +from hcloud.locations.domain import Location + +from hcloud.load_balancer_types.domain import LoadBalancerType + +from hcloud.load_balancers.domain import LoadBalancerHealthCheck, LoadBalancerService, LoadBalancerHealtCheckHttp, LoadBalancerTarget + +api_token = "" + +with open("token.txt", "r") as file: + api_token = file.read().strip() + +client = Client(token=api_token) + +PREFIX = "s444417" + +YOUR_LOCAL_SSH_PUBKEY = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQChkJi01w/rrQ7HICEJYDN/4ldPxorU4umbc8Sw1MRIU2Mz/rds/pd2f+B/PYTjvvtOdZml4SyC4Y8kFoBo4AmRUTxn2yk3g/d1eiDtRzhY1c22+mua6V1dee72EhWAWHaAAa9caChMWV3oP2TljgUEF/Hd7ctMkMxo0Hlh6EVHec1HR6lMIWspYRWjIKPLzknW7WePNgAB5MBDz6+WzokwnULbglUnJ5uy+WrFgWl9tfN7MoNyG1aZkLiWuXvF1HUddAS+gmhs2MEEWeGi3kNewBKQfviAxdCgEKirPra+4ffgLUej7exDzcacxU8AjcK5DLlk3LJr34YTpeV+LMN6M3FB/XVu4vAv9IAyHCOJRer8Vb7gM+ehukgr6HCPrFyCgO3GBh9TvQaBeUajtqjJQ2YHw7D2SFWEfZ6XSx2YSW0NQpfturEHlFLLzN7ohpzSzupe/8yHXlhASSntducXrsXNm1Sz2PdqjDSkoMRZjCzNIxhUS67SZDncOxqsmjE= s444417@MIK" + +vnet_name = f"{PREFIX}-pzc-test-vnet" +vnet = client.networks.get_by_name(vnet_name) or None +if not vnet: + vnet = client.networks.create( + name=vnet_name, + ip_range="10.10.10.0/24", + subnets=[ + NetworkSubnet(ip_range="10.10.10.0/24", network_zone="eu-central", type="cloud") + ] + ) + +print(f"Utworzono sieć wirtualną {vnet.data_model.name} ({vnet.data_model.ip_range})") + +ssh_name = f"{PREFIX}-pzc-ssh-key" +ssh_key = client.ssh_keys.get_by_name(ssh_name) or None +if not ssh_key: + ssh_key = client.ssh_keys.create(name=ssh_name, public_key=YOUR_LOCAL_SSH_PUBKEY) + +print(f"Klucz {ssh_key.data_model.name} został dodany: {ssh_key.data_model.public_key}") + +cloud_init_wp1=r'''#cloud-config +runcmd: + - git clone https://git.wmi.amu.edu.pl/s444417/dpzc + - chmod +x /dpzc/lab4/4.1-hetzner/webservice + - systemctl start /dpzc/lab4/4.1-hetzner/webservice +''' + +servers = [] +for i in range(2): + name=f"{PREFIX}-service-{i+1}" + server = client.servers.create( + name=name, + server_type=ServerType("cx11"), + image=Image(name="ubuntu-20.04"), + ssh_keys=[ssh_key], + networks=[vnet], + location=Location("hel1"), + user_data=cloud_init_wp1 + ) + server.action.wait_until_finished() + print(f"Tworzenie serwera: {server.action.complete}") + + server = client.servers.get_by_name(name) + print(f"Serwer: {server.data_model.name}\n\tpubliczne IP: {server.data_model.public_net.ipv4.ip}\n\tprywatne IP: {server.data_model.private_net[0].ip}") + servers.append(server) + + +name = f"{PREFIX}-load-balancer-${i}" + +targets = [] +for s in servers: + targets.append(LoadBalancerTarget( + type="server", + server=s, + use_private_ip=True +)) + +load_balancer = client.load_balancers.create( + name=name, + load_balancer_type=LoadBalancerType(name="lb11"), + location=Location("hel1"), + services=[ + LoadBalancerService( + protocol="http", + listen_port=8080, + destination_port=8080, + proxyprotocol=False, + health_check=LoadBalancerHealthCheck( + protocol="http", + port="8080", + interval=15, + timeout=10, + retries=3, + http=LoadBalancerHealtCheckHttp( + path="/factors/10", + status_codes=["2??", "3??"], + tls=False + ) + ) + ) + ], + targets=targets, + public_interface=True, + network=vnet +) + + +load_balancer.action.wait_until_finished() +print(f"Tworzenie load balancera {name}: {load_balancer.action.complete}") + +load_balancer = client.load_balancers.get_by_name(name) +print(f"Load balancer: {load_balancer.data_model.name}\n\tpubliczne IP: {load_balancer.data_model.public_net.ipv4.ip}") diff --git a/lab4/4.1-hetzner/webservice b/lab4/4.1-hetzner/webservice new file mode 100644 index 0000000..afd2204 Binary files /dev/null and b/lab4/4.1-hetzner/webservice differ diff --git a/lab4/__pycache__/boto3_helper.cpython-310.pyc b/lab4/__pycache__/boto3_helper.cpython-310.pyc new file mode 100644 index 0000000..37c2575 Binary files /dev/null and b/lab4/__pycache__/boto3_helper.cpython-310.pyc differ diff --git a/lab4/__pycache__/boto3_helper.cpython-39.pyc b/lab4/__pycache__/boto3_helper.cpython-39.pyc new file mode 100644 index 0000000..353beb7 Binary files /dev/null and b/lab4/__pycache__/boto3_helper.cpython-39.pyc differ diff --git a/lab4/aws_wordpress_autoscale.py b/lab4/aws_wordpress_autoscale.py new file mode 100644 index 0000000..1a85ddc --- /dev/null +++ b/lab4/aws_wordpress_autoscale.py @@ -0,0 +1,384 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from boto3_helper import * + +# Check if the user has the Access & Secret key configured +import boto3 +from boto3 import Session + +session = init_aws_session() +# credentials = session.get_credentials() +# current_credentials = credentials.get_frozen_credentials() +# +# # Break & Exit if any of the key is not present +# if current_credentials.access_key is None: +# print("Access Key missing, use `aws configure` to setup") +# exit() +# +# if current_credentials.secret_key is None: +# print("Secret Key missing, use `aws configure` to setup") +# exit() +# +# VPC design for multi az deployments +globalVars = {} +globalVars['REGION_NAME'] = "ap-south-1" +globalVars['AZ1'] = "ap-south-1a" +globalVars['AZ2'] = "ap-south-1b" +globalVars['CIDRange'] = "10.240.0.0/23" +globalVars['az1_pvtsubnet_CIDRange'] = "10.240.0.0/25" +globalVars['az1_pubsubnet_CIDRange'] = "10.240.0.128/26" +globalVars['az1_sparesubnet_CIDRange'] = "10.240.0.192/26" +globalVars['az2_pvtsubnet_CIDRange'] = "10.240.1.0/25" +globalVars['az2_pubsubnet_CIDRange'] = "10.240.1.128/26" +globalVars['az2_sparesubnet_CIDRange'] = "10.240.1.192/26" +globalVars['Project'] = { 'Key': 'Name', 'Value': 'AutoScaling-Demo'} +globalVars['tags'] = [{'Key': 'Owner', 'Value': 'Miztiik'}, + {'Key': 'Environment', 'Value': 'Test'}, + {'Key': 'Department', 'Value': 'Valaxy-Training'}] +# EC2 Parameters +globalVars['EC2-RH-AMI-ID'] = "ami-cdbdd7a2" +globalVars['EC2-Amazon-AMI-ID'] = "ami-3c89f653" +globalVars['EC2-InstanceType'] = "t2.micro" +globalVars['EC2-KeyName'] = globalVars['Project']['Value']+'-Key' + +# AutoScaling Parameters +globalVars['ASG-LaunchConfigName'] = "ASG-Demo-LaunchConfig" +globalVars['ASG-AutoScalingGroupName'] = "ASG-Demo-AutoScalingGrp" + +# RDS Parameters +globalVars['RDS-DBIdentifier'] = "ProdDb01" +globalVars['RDS-Engine'] = "mysql" +globalVars['RDS-DBName'] = "WordPressDB" +globalVars['RDS-DBMasterUserName'] = "WpDdMasterUsr" +globalVars['RDS-DBMasterUserPass'] = "WpDdMasterUsrPass" +globalVars['RDS-DBInstanceClass'] = "db.t2.micro" +globalVars['RDS-DBSubnetGroup'] = "RDS-WP-DB-Subnet-Group" + +# Creating a VPC, Subnet, and Gateway +ec2 = boto3.resource('ec2', region_name=globalVars['REGION_NAME']) +ec2Client = boto3.client('ec2', region_name=globalVars['REGION_NAME']) +vpc = ec2.create_vpc(CidrBlock=globalVars['CIDRange']) +asgClient = boto3.client('autoscaling', region_name=globalVars['REGION_NAME']) +rds = boto3.client('rds', region_name=globalVars['REGION_NAME']) + +# AZ1 Subnets +az1_pvtsubnet = vpc.create_subnet(CidrBlock=globalVars['az1_pvtsubnet_CIDRange'], AvailabilityZone=globalVars['AZ1']) +az1_pubsubnet = vpc.create_subnet(CidrBlock=globalVars['az1_pubsubnet_CIDRange'], AvailabilityZone=globalVars['AZ1']) +az1_sparesubnet = vpc.create_subnet(CidrBlock=globalVars['az1_sparesubnet_CIDRange'], AvailabilityZone=globalVars['AZ1']) +# AZ2 Subnet +az2_pvtsubnet = vpc.create_subnet(CidrBlock=globalVars['az2_pvtsubnet_CIDRange'], AvailabilityZone=globalVars['AZ2']) +az2_pubsubnet = vpc.create_subnet(CidrBlock=globalVars['az2_pubsubnet_CIDRange'], AvailabilityZone=globalVars['AZ2']) +az2_sparesubnet = vpc.create_subnet(CidrBlock=globalVars['az2_sparesubnet_CIDRange'], AvailabilityZone=globalVars['AZ2']) + +# Enable DNS Hostnames in the VPC +vpc.modify_attribute(EnableDnsSupport={'Value': True}) +vpc.modify_attribute(EnableDnsHostnames={'Value': True}) + +# Create the Internet Gatway & Attach to the VPC +intGateway = ec2.create_internet_gateway() +intGateway.attach_to_vpc(VpcId=vpc.id) + +# Create another route table for Public & Private traffic +routeTable = ec2.create_route_table(VpcId=vpc.id) +rtbAssn=[] +rtbAssn.append(routeTable.associate_with_subnet(SubnetId=az1_pubsubnet.id)) +rtbAssn.append(routeTable.associate_with_subnet(SubnetId=az1_pvtsubnet.id)) +rtbAssn.append(routeTable.associate_with_subnet(SubnetId=az2_pubsubnet.id)) +rtbAssn.append(routeTable.associate_with_subnet(SubnetId=az2_pvtsubnet.id)) + +# Create a route for internet traffic to flow out +intRoute = ec2Client.create_route(RouteTableId=routeTable.id, DestinationCidrBlock='0.0.0.0/0', GatewayId=intGateway.id) + +# Tag the resources +vpc.create_tags (Tags=globalVars['tags']) +az1_pvtsubnet.create_tags (Tags=globalVars['tags']) +az1_pubsubnet.create_tags (Tags=globalVars['tags']) +az1_sparesubnet.create_tags(Tags=globalVars['tags']) +az2_pvtsubnet.create_tags (Tags=globalVars['tags']) +az2_pubsubnet.create_tags (Tags=globalVars['tags']) +az2_sparesubnet.create_tags(Tags=globalVars['tags']) +intGateway.create_tags (Tags=globalVars['tags']) +routeTable.create_tags (Tags=globalVars['tags']) + +vpc.create_tags (Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-vpc'}]) +az1_pvtsubnet.create_tags (Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-az1-private-subnet'}]) +az1_pubsubnet.create_tags (Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-az1-public-subnet'}]) +az1_sparesubnet.create_tags(Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-az1-spare-subnet'}]) +az2_pvtsubnet.create_tags (Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-az2-private-subnet'}]) +az2_pubsubnet.create_tags (Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-az2-public-subnet'}]) +az2_sparesubnet.create_tags(Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-az2-spare-subnet'}]) +intGateway.create_tags (Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-igw'}]) +routeTable.create_tags (Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-rtb'}]) + +# Let create the Public & Private Security Groups +elbSecGrp = ec2.create_security_group(DryRun=False, + GroupName='elbSecGrp', + Description='ElasticLoadBalancer_Security_Group', + VpcId=vpc.id + ) + +pubSecGrp = ec2.create_security_group(DryRun=False, + GroupName='pubSecGrp', + Description='Public_Security_Group', + VpcId=vpc.id + ) + +pvtSecGrp = ec2.create_security_group(DryRun=False, + GroupName='pvtSecGrp', + Description='Private_Security_Group', + VpcId=vpc.id + ) + +elbSecGrp.create_tags(Tags=globalVars['tags']) +pubSecGrp.create_tags(Tags=globalVars['tags']) +pvtSecGrp.create_tags(Tags=globalVars['tags']) + +elbSecGrp.create_tags(Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-elb-security-group'}]) +pubSecGrp.create_tags(Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-public-security-group'}]) +pvtSecGrp.create_tags(Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-private-security-group'}]) + +# Add a rule that allows inbound SSH, HTTP, HTTPS traffic ( from any source ) +ec2Client.authorize_security_group_ingress(GroupId=elbSecGrp.id, + IpProtocol='tcp', + FromPort=80, + ToPort=80, + CidrIp='0.0.0.0/0' + ) + +# Allow Public Security Group to receive traffic from ELB Security group +ec2Client.authorize_security_group_ingress(GroupId=pubSecGrp.id, + IpPermissions=[{'IpProtocol': 'tcp', + 'FromPort': 80, + 'ToPort': 80, + 'UserIdGroupPairs': [{'GroupId': elbSecGrp.id}] + }] + ) +# Allow Private Security Group to receive traffic from Application Security group +ec2Client.authorize_security_group_ingress(GroupId=pvtSecGrp.id, + IpPermissions=[{'IpProtocol': 'tcp', + 'FromPort': 3306, + 'ToPort': 3306, + 'UserIdGroupPairs': [{'GroupId': pubSecGrp.id}] + }] + ) + +ec2Client.authorize_security_group_ingress(GroupId=pubSecGrp.id, + IpProtocol='tcp', + FromPort=80, + ToPort=80, + CidrIp='0.0.0.0/0' + ) +ec2Client.authorize_security_group_ingress(GroupId=pubSecGrp.id, + IpProtocol='tcp', + FromPort=443, + ToPort=443, + CidrIp='0.0.0.0/0' + ) +ec2Client.authorize_security_group_ingress(GroupId=pubSecGrp.id, + IpProtocol='tcp', + FromPort=22, + ToPort=22, + CidrIp='0.0.0.0/0' + ) + +# Lets create the key-pair that we will use +## Check if key is already present +customEC2Keys = ec2Client.describe_key_pairs()['KeyPairs'] +if not next((key for key in customEC2Keys if key["KeyName"] == globalVars['EC2-KeyName']), False): + ec2_key_pair = ec2.create_key_pair(KeyName=globalVars['EC2-KeyName']) + print("New Private Key created,Save the below key-material\n\n") + print(ec2_key_pair.key_material) + +# Using the userdata field, we will download, install & configure our basic word press website. +# The user defined code to install Wordpress, WebServer & Configure them +userDataCode = """ +#!/bin/bash +set -e -x +# Setting up the HTTP server +yum install -y httpd php php-mysql mysql-server +service httpd start +service mysqld start +chkconfig httpd on +groupadd www +usermod -a -G www ec2-user +# Download wordpress site & move to http +cd /var/www/ +curl -O https://wordpress.org/latest.tar.gz && tar -zxf latest.tar.gz +rm -rf /var/www/html +mv wordpress /var/www/html +# Set the permissions +chown -R root:www /var/www +chmod 2775 /var/www +find /var/www -type d -exec chmod 2775 {} + +find /var/www -type f -exec chmod 0664 {} + +# SE Linux permissive +# needed to make wp connect to DB over newtork +# setsebool -P httpd_can_network_connect=1 +# setsebool httpd_can_network_connect_db on +service httpd restart +# Remove below file after testing +echo "" > /var/www/html/phptestinfo.php +""" + +# Create the Public Word Press Instance +##### **DeviceIndex**:The network interface's position in the attachment order. For example, the first attached network interface has a DeviceIndex of 0 +instanceLst = ec2.create_instances(ImageId=globalVars['EC2-Amazon-AMI-ID'], + MinCount=1, + MaxCount=1, + KeyName=globalVars['EC2-KeyName'], + UserData=userDataCode, + InstanceType=globalVars['EC2-InstanceType'], + NetworkInterfaces=[ + { + 'SubnetId': az1_pubsubnet.id, + 'Groups': [pubSecGrp.id], + 'DeviceIndex': 0, + 'DeleteOnTermination': True, + 'AssociatePublicIpAddress': True, + } + ] + ) + + +# Create the Launch Configuration +# InstanceId = 'string' +asgLaunchConfig = asgClient.create_launch_configuration( + LaunchConfigurationName=globalVars['ASG-LaunchConfigName'], + ImageId=globalVars['EC2-Amazon-AMI-ID'], + KeyName=globalVars['EC2-KeyName'], + SecurityGroups=[pubSecGrp.id], + UserData=userDataCode, + InstanceType=globalVars['EC2-InstanceType'], + InstanceMonitoring={'Enabled': False }, + EbsOptimized=False, + AssociatePublicIpAddress=False +) + +# create Auto-Scaling Group +ASGSubnets = az1_pubsubnet.id + "," +az2_pubsubnet.id +asGroup=asgClient.create_auto_scaling_group( + AutoScalingGroupName=globalVars['ASG-AutoScalingGroupName'], + LaunchConfigurationName=globalVars['ASG-LaunchConfigName'], + MinSize=1, + MaxSize=3, + DesiredCapacity=2, + DefaultCooldown=120, + HealthCheckType='EC2', + HealthCheckGracePeriod=60, + Tags=globalVars['tags'], + VPCZoneIdentifier=ASGSubnets + ) + +asgClient.create_or_update_tags( + Tags=[ + { + 'ResourceId': globalVars['ASG-AutoScalingGroupName'], + 'ResourceType': 'auto-scaling-group', + 'Key': 'Name', + 'Value': globalVars['Project']['Value'] + '-ASG-Group', + 'PropagateAtLaunch': True + }, + ] +) + +## First lets create the RDS Subnet Groups +rdsDBSubnetGrp = rds.create_db_subnet_group(DBSubnetGroupName=globalVars['RDS-DBSubnetGroup'], + DBSubnetGroupDescription=globalVars['RDS-DBSubnetGroup'], + SubnetIds=[az1_pvtsubnet.id, az2_pvtsubnet.id], + Tags=[{'Key': 'Name', + 'Value': globalVars['Project']['Value'] + '-DB-Subnet-Group'}] + ) + +rdsInstance = rds.create_db_instance(DBInstanceIdentifier=globalVars['RDS-DBIdentifier'], + AllocatedStorage=5, + DBName=globalVars['RDS-DBName'], + Engine=globalVars['RDS-Engine'], + Port=3306, + # General purpose SSD + StorageType='gp2', + StorageEncrypted=False, + AutoMinorVersionUpgrade=False, + # Set this to true later? + MultiAZ=False, + MasterUsername=globalVars['RDS-DBMasterUserName'], + MasterUserPassword=globalVars['RDS-DBMasterUserPass'], + DBInstanceClass=globalVars['RDS-DBInstanceClass'], + VpcSecurityGroupIds=[pvtSecGrp.id], + DBSubnetGroupName=globalVars['RDS-DBSubnetGroup'], + CopyTagsToSnapshot=True, + Tags=[{'Key': 'Name', 'Value': globalVars['Project']['Value'] + '-RDS-Instance'}]) + +# Lets wait until the RDS is created successfully +## Polls RDS.Client.describe_db_instances() every 30 seconds until a successful state is reached. An error is returned after 60 failed checks. + +waiter = rds.get_waiter('db_instance_available') +waiter.wait(DBInstanceIdentifier=globalVars['RDS-DBIdentifier']) + +resp = rds.describe_db_instances(DBInstanceIdentifier= globalVars['RDS-DBIdentifier']) +db_instances = resp['DBInstances'] +if len(db_instances) != 1: + raise Exception('Whoa!!! More than one DB instance returned; this should not have happened') +db_instance = db_instances[0] +status = db_instance['DBInstanceStatus'] +if status == 'available': + rdsEndpointDict = db_instance['Endpoint'] + globalVars['Endpoint'] = rdsEndpointDict['Address'] + # port = endpoint['Port'] + + +###### Print to Screen ######## +print("VPC ID : {0}".format(vpc.id)) +print("AZ1 Public Subnet ID : {0}".format(az1_pubsubnet.id)) +print("AZ1 Private Subnet ID : {0}".format(az1_pvtsubnet.id)) +print("AZ1 Spare Subnet ID : {0}".format(az1_sparesubnet.id)) +print("Internet Gateway ID : {0}".format(intGateway.id)) +print("Route Table ID : {0}".format(routeTable.id)) +print("Public Security Group ID : {0}".format(pubSecGrp.id)) +print("Private Security Group ID : {0}".format(pvtSecGrp.id)) +print("EC2 Key Pair : {0}".format(globalVars['EC2-KeyName'])) +print("EC2 PublicIP : {0}".format(globalVars['EC2-KeyName'])) +print("RDS Endpoint : {0}".format(globalVars['Endpoint'])) +###### Print to Screen ######## + + +""" +Function to clean up all the resources +""" +def cleanAll(resourcesDict=None): + # Delete the RDS Instance + waiter = rds.get_waiter('db_instance_deleted') + waiter.wait(DBInstanceIdentifier=globalVars['RDS-DBIdentifier']) + rds.delete_db_instance(DBInstanceIdentifier=globalVars['RDS-DBIdentifier'], SkipFinalSnapshot=True) + # Delete the instances + ids = [] + for i in instanceLst: + ids.append(i.id) + + ec2.instances.filter(InstanceIds=ids).terminate() + + # Wait for the instance to be terminated + waiter = ec2Client.get_waiter('instance_terminated') + waiter.wait(InstanceIds=[ids]) + ec2Client.delete_key_pair(KeyName=globalVars['EC2-KeyName']) + + # Delete Routes & Routing Table + for assn in rtbAssn: + ec2Client.disassociate_route_table(AssociationId=assn.id) + + routeTable.delete() + + # Delete Subnets + az1_pvtsubnet.delete() + az1_pubsubnet.delete() + az1_sparesubnet.delete() + + # Detach & Delete internet Gateway + ec2Client.detach_internet_gateway(InternetGatewayId=intGateway.id, VpcId=vpc.id) + intGateway.delete() + + # Delete Security Groups + pubSecGrp.delete() + pvtSecGrp.delete() + + vpc.delete() \ No newline at end of file diff --git a/lab4/boto3-load-balancers-add.py b/lab4/boto3-load-balancers-add.py new file mode 100644 index 0000000..859f2d4 --- /dev/null +++ b/lab4/boto3-load-balancers-add.py @@ -0,0 +1,42 @@ +import pprint +from boto3_helper import * + +# find a security group that allows port 80 and tcp +security_groups = ec2_get_security_group_list() +for security_group in security_groups: + security_group_ip_perms = security_group['IpPermissions'] + for security_group_ip_perm in security_group_ip_perms: + if security_group_ip_perm['IpProtocol'] == 'tcp' and security_group_ip_perm['FromPort'] == 80: + vpc_id = security_group['VpcId'] + security_group_id = security_group['GroupId'] + break + +# find subnet and VPC ID associated with security group +subnet_list = ec2_get_subnet_list() +subnet_id_list = [] +for subnet in subnet_list: + if subnet['VpcId'] == vpc_id: + subnet_id_list.append(subnet['SubnetId']) + +print (subnet_id_list, vpc_id, security_group_id) + +# Create a target group +target_group = elb_create_target_group('unbiased-coder-target-group', vpc_id) +target_group_arn = target_group['TargetGroups'][0]['TargetGroupArn'] + +session = init_aws_session() +elb = session.client('elbv2') + +response = elb.create_load_balancer( + Name='UnbiasedCoderLoadBalancer', + Subnets = subnet_id_list, + SecurityGroups=[ + security_group_id, + ], + + Scheme='internal', + + Type='application', + IpAddressType='ipv4', +) +pprint.pprint(response) \ No newline at end of file diff --git a/lab4/boto3-load-balancers-list.py b/lab4/boto3-load-balancers-list.py new file mode 100644 index 0000000..c9383dc --- /dev/null +++ b/lab4/boto3-load-balancers-list.py @@ -0,0 +1,7 @@ +import pprint +from boto3_helper import init_aws_session + +session = init_aws_session() +elb = session.client('elbv2') +response = elb.describe_load_balancers() +pprint.pprint(response['LoadBalancers']) \ No newline at end of file diff --git a/lab4/boto3_helper.py b/lab4/boto3_helper.py new file mode 100644 index 0000000..c3feb75 --- /dev/null +++ b/lab4/boto3_helper.py @@ -0,0 +1,40 @@ +import os +from urllib import response +import boto3 +import pprint +from dotenv import load_dotenv + +load_dotenv(dotenv_path="lab4/.env") + +def get_aws_keys(): + return os.getenv('aws_access_key_id'), os.getenv('aws_secret_access_key') + +def init_aws_session(): + aws_access_key_id, aws_secret_access_key = get_aws_keys() + return boto3.Session(aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, aws_session_token=os.getenv("aws_session_token"), region_name=os.getenv('AWS_REGION')) + +def ec2_get_vpc_list(): + session = init_aws_session() + ec2 = session.client('ec2') + response = ec2.describe_vpcs() + return response['Vpcs'] + +def elb_create_target_group(target_group_name, vpc_id): + session = init_aws_session() + elb = session.client('elbv2') + response = elb.create_target_group(Name=target_group_name, Protocol='HTTP', Port=80, VpcId=vpc_id) + return response + +def ec2_get_subnet_list(): + session = init_aws_session() + ec2 = session.client('ec2') + response = ec2.describe_subnets() + return response['Subnets'] + +def ec2_get_security_group_list(): + session = init_aws_session() + ec2 = session.client('ec2') + response = ec2.describe_security_groups() + return response['SecurityGroups'] + +# src: https://unbiased-coder.com/boto3-load-balancer-guide/ \ No newline at end of file diff --git a/lab4/create-load-balancer.py b/lab4/create-load-balancer.py new file mode 100644 index 0000000..7f75845 --- /dev/null +++ b/lab4/create-load-balancer.py @@ -0,0 +1,9 @@ +import os +import boto.ec2.elb +from dotenv import load_dotenv + +load_dotenv(dotenv_path="lab4/.env") +region_name=os.getenv('AWS_REGION') +elb = boto.ec2.elb.connect_to_region(region_name) + +print(elb) \ No newline at end of file diff --git a/lab4/prime.py b/lab4/prime.py new file mode 100644 index 0000000..3475842 --- /dev/null +++ b/lab4/prime.py @@ -0,0 +1,128 @@ +import requests +import random +import math +import time +import threading +import logging +logging.getLogger().setLevel(logging.INFO) + + +API_URL="http://localhost:8080" + + +UNIT = 5.0 # secs + +# Pre generated primes +first_primes_list = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, + 31, 37, 41, 43, 47, 53, 59, 61, 67, + 71, 73, 79, 83, 89, 97, 101, 103, + 107, 109, 113, 127, 131, 137, 139, + 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, 257, + 263, 269, 271, 277, 281, 283, 293, + 307, 311, 313, 317, 331, 337, 347, 349] + + +def nBitRandom(n): + return random.randrange(2**(n-1)+1, 2**n - 1) + +def getLowLevelPrime(n): + '''Generate a prime candidate divisible + by first primes''' + while True: + # Obtain a random number + pc = nBitRandom(n) + + # Test divisibility by pre-generated + # primes + for divisor in first_primes_list: + if pc % divisor == 0 and divisor**2 <= pc: + break + else: return pc + +def isMillerRabinPassed(mrc): + '''Run 20 iterations of Rabin Miller Primality test''' + maxDivisionsByTwo = 0 + ec = mrc-1 + while ec % 2 == 0: + ec >>= 1 + maxDivisionsByTwo += 1 + assert(2**maxDivisionsByTwo * ec == mrc-1) + + def trialComposite(round_tester): + if pow(round_tester, ec, mrc) == 1: + return False + for i in range(maxDivisionsByTwo): + if pow(round_tester, 2**i * ec, mrc) == mrc-1: + return False + return True + + # Set number of trials here + numberOfRabinTrials = 20 + for i in range(numberOfRabinTrials): + round_tester = random.randrange(2, mrc) + if trialComposite(round_tester): + return False + return True + +def random_large_prime(bits): + while True: + prime_candidate = getLowLevelPrime(bits) + if not isMillerRabinPassed(prime_candidate): + continue + else: + return prime_candidate + +def thread_function(i, fast, timeout): + start = time.time() + + c = 5 # bits: 20: 200ms; 21: 350ms; 22: 700ms 23: 1.5s; 25: 6s; 26: 10s; 27: 24s + bits = 19 if fast else 23 + last_report = time.time() + processing_time = 0.0 + reqs = 0 + while True: + iter_start = time.time() + if iter_start - start > timeout: + logging.info("Thread: %d\treqs: %d\tmean time: %.3fs\t%s"%(i, reqs, processing_time/reqs if reqs>0 else 0.0, "fast\t" if fast else "")) + results[i][iter_start] = processing_time/reqs if reqs>0 else 0.0 + return + if iter_start - last_report > UNIT/2: + if len(results[i])%2 == 0: + logging.info("Thread: %d\treqs: %d\tmean time: %.3fs\t%s"%(i, reqs, processing_time/reqs if reqs>0 else 0.0, "fast\t" if fast else "")) + results[i][iter_start] = processing_time/reqs if reqs>0 else 0.0 + processing_time = 0.0 + reqs = 0 + last_report=iter_start + + factors = [random_large_prime(bits) for i in range(c)] + factors.sort() + n=math.prod(factors) + + r = requests.get(API_URL+'/factors/%d'%(n)) + if r.status_code != 200: + logging.error("wrong status code from webservice") + else: + result = r.json() + if result != factors: + logging.error("Wrong factors") + + processing_time+=time.time() - iter_start + reqs+=1 + time.sleep(0.5) + +START = time.time() +slow_threads = 4 + +results = [ {} for i in range(slow_threads+1)] + +t0 = threading.Thread(target=thread_function, args=(0, True, (5 + slow_threads*3) * UNIT)) +t0.start() +time.sleep(2 * UNIT) +for i in range(slow_threads): + t = threading.Thread(target=thread_function, args=(i+1, False, (slow_threads-i) * 3 * UNIT)) + t.start() + time.sleep(2 * UNIT) + +t0.join() \ No newline at end of file