in notebooks/parallelcluster/pcluster_athena.py [0:0]
def create_before(self):
ec2_client = boto3.client('ec2')
# the slurm REST token is generated from the headnode and stored in Secrets Manager. This token is used in makeing REST API calls to the Slurm REST endpoint running on the headnode
# specify the following names
# ssh key for access the pcluster. this key is not needed in this excercise, but useful if you need to ssh into the headnode of the pcluster
keypair_saved_path = './'+self.ssh_key_name+'.pem'
# we will not need to use the ssh_key in this excercise. However, you can only download the key once during creation. we will save it in case
try:
workshop.create_keypair(self.region, self.session, self.ssh_key_name, keypair_saved_path)
except ClientError as e:
if e.response['Error']['Code'] == "InvalidKeyPair.Duplicate":
print("KeyPair with the name {} alread exists. Skip".format(self.ssh_key_name))
# ## VPC
#
# You can use the existing default VPC or create a new VPC with 2 subnets.
#
# We will only be using one of the subnets for the ParallelCluster, but both are used for the RDS database.
if self.use_existing_vpc:
vpc_filter = [{'Name':'isDefault', 'Values':['true']}]
default_vpc = ec2_client.describe_vpcs(Filters=vpc_filter)
self.vpc_id = default_vpc['Vpcs'][0]['VpcId']
subnet_filter = [{'Name':'vpc-id', 'Values':[self.vpc_id]}]
subnets = ec2_client.describe_subnets(Filters=subnet_filter)
# only pick 1a, 1b az - others might have issue with resources
for sn in subnets['Subnets']:
if '-1a' in sn['AvailabilityZone'] :
subnet_id = sn['SubnetId']
if '-1b' in sn['AvailabilityZone'] :
subnet_id2 = sn['SubnetId']
else:
vpc, subnet1, subnet2 = workshop.create_and_configure_vpc()
self.vpc_id = vpc.id
subnet_id = subnet1.id
subnet_id2 = subnet2.id
# Create the project bucket.
# we will use this bucket for the scripts, input and output files
bucket_prefix = self.pcluster_name.lower()+'-'+self.my_account_id
# use the bucket prefix as name, don't use uuid suffix
self.my_bucket_name = workshop.create_bucket(self.region, self.session, bucket_prefix, False)
print(self.my_bucket_name)
# ## RDS Database (MySQL) - used with ParallelCluster for accounting
#
# We will create a simple MySQL RDS database instance to use as a data store for Slurmdbd for accounting. The username and password are stored as a secret in the Secrets Manager.
# The secret is later used to configure Slurmdbd.
#
# The RDS instance will be created asynchronuously. While the secret is created immediated, the hostname will be available only after the creation is completed. We will have to update the hostname in the secreat afterwards.
#
# We will update the security group to allow traffic to port 3306 from the cluster in the same vpc
#
# create a simple mysql rds instance , the username and password will be stored in secrets maanger as a secret
workshop.create_simple_mysql_rds(self.region, self.session, self.db_name, [subnet_id,subnet_id2] ,self.rds_secret_name)
rds_client = self.session.client('rds', self.region)
rds_waiter = rds_client.get_waiter('db_instance_available')
try:
print("Waiting for RDS instance creation to complete ... ")
rds_waiter.wait(DBInstanceIdentifier=self.db_name)
except botocore.exceptions.WaiterError as e:
print(e)
#since the rds creation is asynch, need to wait till the creation is done to get the hostname, then update the secret with the hostname
vpc_sgs = workshop.get_sgs_and_update_secret(self.region, self.session, self.db_name, self.rds_secret_name)
print(vpc_sgs)
# Step 3. get the vpc local CIDR range
ec2 = boto3.resource('ec2')
vpc = ec2.Vpc(self.vpc_id)
cidr = vpc.cidr_block
# update the RDS security group to allow inbound traffic to port 3306
workshop.update_security_group(vpc_sgs[0]['VpcSecurityGroupId'], cidr, 3306)
print(os.popen("pcluster version").read())
# ### ParallelCluster config file
# Start with the the configuration template file
#
# #### Setup parameters for PCluster
#
# We will be using a relational database on AWS (RDS) for Slurm accounting (slurmdbd). Please refer to this blog for how to set it up https://aws.amazon.com/blogs/compute/enabling-job-accounting-for-hpc-with-aws-parallelcluster-and-amazon-rds/
#
# Once you set up the MySQL RDS, create a secret in SecretManager with the type "Credentials for RDS", so we don't need to expose the database username/password in plain text in this notebook.
# the response is a json {"username": "xxxx", "password": "xxxx", "engine": "mysql", "host": "xxxx", "port": "xxxx", "dbInstanceIdentifier", "xxxx"}
rds_secret = json.loads(self.get_slurm_dbd_rds_secret())
post_install_script_prefix = self.post_install_script
post_install_script_location = "s3://{}/{}".format(self.my_bucket_name, post_install_script_prefix)
post_install_script_args = "'" + rds_secret['host']+' '+str(rds_secret['port']) +' ' + rds_secret['username'] + ' ' + rds_secret['password'] + ' ' + self.pcluster_name + ' ' + self.region + ' ' + self.dbd_host + ' ' + self.federation_name + "'"
# ### Post installation script
# This script is used to recompile and configure slurm with slurmrestd. We also added the automation of compiling Athena++ in the script.
#
# Let's take a look at the scrupt:
s3_client = self.session.client('s3')
try:
resp = s3_client.upload_file(post_install_script_prefix, self.my_bucket_name, post_install_script_prefix)
except ClientError as e:
print(e)
# Replace the placeholder with value in config.ini
print("Prepare the config file")
ph = {'${REGION}': self.region,
'${VPC_ID}': self.vpc_id,
'${SUBNET_ID}': subnet_id,
'${KEY_NAME}': self.ssh_key_name,
'${POST_INSTALL_SCRIPT_LOCATION}': post_install_script_location,
'${POST_INSTALL_SCRIPT_ARGS_1}': "'"+rds_secret['host']+"'",
'${POST_INSTALL_SCRIPT_ARGS_2}': "'"+str(rds_secret['port'])+"'",
'${POST_INSTALL_SCRIPT_ARGS_3}': "'"+rds_secret['username']+"'",
'${POST_INSTALL_SCRIPT_ARGS_4}': "'"+rds_secret['password']+"'",
'${POST_INSTALL_SCRIPT_ARGS_5}': "'"+self.pcluster_name+"'",
'${POST_INSTALL_SCRIPT_ARGS_6}': "'"+self.region+"'",
'${POST_INSTALL_SCRIPT_ARGS_7}': "'"+self.dbd_host+"'",
'${POST_INSTALL_SCRIPT_ARGS_8}': "'"+self.federation_name+"'",
'${BUCKET_NAME}': self.my_bucket_name
}
self.template_to_file("config/"+self.config_name+".ini", "build/"+self.config_name, ph)