Sebastian Rieger
8 months ago
6 changed files with 923 additions and 0 deletions
-
47CloudComp-openrc
-
144demo1_getting_started.py
-
268demo2_instance_with_init_script.py
-
317demo3_microservice.py
-
126destroy_all_demo_instances.py
-
21root-ca.crt
@ -0,0 +1,47 @@ |
|||
#!/usr/bin/env bash |
|||
# To use an OpenStack cloud you need to authenticate against the Identity |
|||
# service named keystone, which returns a **Token** and **Service Catalog**. |
|||
# The catalog contains the endpoints for all services the user/tenant has |
|||
# access to - such as Compute, Image Service, Identity, Object Storage, Block |
|||
# Storage, and Networking (code-named nova, glance, keystone, swift, |
|||
# cinder, and neutron). |
|||
|
|||
# unset all OPENSTACK ENV VARS |
|||
unset $(env | grep OS_ | cut -d "=" -f 1) |
|||
|
|||
export OS_CACERT=./root-ca.crt |
|||
export GROUP_NUMBER=0 |
|||
|
|||
# |
|||
# *NOTE*: Using the 3 *Identity API* does not necessarily mean any other |
|||
# OpenStack API is version 3. For example, your cloud provider may implement |
|||
# Image API v1.1, Block Storage API v2, and Compute API v2.0. OS_AUTH_URL is |
|||
# only for the Identity API served through keystone. |
|||
export OS_AUTH_URL=https://10.32.4.182:5000/v3 |
|||
# With the addition of Keystone we have standardized on the term **project** |
|||
# as the entity that owns the resources. |
|||
#export OS_PROJECT_ID=bba62cf6bf0b447491829d207e1b05f9 |
|||
export OS_PROJECT_NAME="CloudComp$GROUP_NUMBER" |
|||
unset OS_DOMAIN_NAME |
|||
export OS_USER_DOMAIN_NAME="Default" |
|||
if [ -z "$OS_USER_DOMAIN_NAME" ]; then unset OS_USER_DOMAIN_NAME; fi |
|||
export OS_PROJECT_DOMAIN_ID="default" |
|||
if [ -z "$OS_PROJECT_DOMAIN_ID" ]; then unset OS_PROJECT_DOMAIN_ID; fi |
|||
# unset v2.0 items in case set |
|||
unset OS_TENANT_ID |
|||
unset OS_TENANT_NAME |
|||
# In addition to the owning entity (tenant), OpenStack stores the entity |
|||
# performing the action as the **user**. |
|||
export OS_USERNAME="CloudComp$GROUP_NUMBER" |
|||
# With Keystone you pass the keystone password. |
|||
#echo "Please enter your OpenStack Password for project $OS_PROJECT_NAME as user $OS_USERNAME: " |
|||
#read -sr OS_PASSWORD_INPUT |
|||
#export OS_PASSWORD=$OS_PASSWORD_INPUT |
|||
export OS_PASSWORD="demo" |
|||
# If your configuration has multiple regions, we set that information here. |
|||
# OS_REGION_NAME is optional and only valid in certain environments. |
|||
export OS_REGION_NAME="RegionOne" |
|||
# Don't leave a blank variable, unset it if it was empty |
|||
if [ -z "$OS_REGION_NAME" ]; then unset OS_REGION_NAME; fi |
|||
export OS_INTERFACE=public |
|||
export OS_IDENTITY_API_VERSION=3 |
@ -0,0 +1,144 @@ |
|||
"""Example for Cloud Computing Course Master AI / GSD""" |
|||
|
|||
# This script demonstrates how to use libcloud to start an instance in an OpenStack environment. |
|||
# The script will start an instance, list all instances, and then destroy the instance again. |
|||
# |
|||
# The script uses the libcloud library to interact with the OpenStack API. |
|||
# Need to install libcloud first: pip install apache-libcloud |
|||
# |
|||
# libCloud: https://libcloud.apache.org/ |
|||
# libCloud API documentation: https://libcloud.readthedocs.io/en/latest/ |
|||
# OpenStack API documentation: https://developer.openstack.org/ |
|||
# this code was initially based on the former tutorial: |
|||
# https://developer.openstack.org/firstapp-libcloud/ |
|||
|
|||
# Only needed for the password prompt: |
|||
# import getpass |
|||
|
|||
from libcloud.compute.providers import get_driver |
|||
from libcloud.compute.types import Provider |
|||
|
|||
# For our new Charmed OpenStack private cloud, we need to specify the path to the |
|||
# root CA certificate |
|||
import libcloud.security |
|||
libcloud.security.CA_CERTS_PATH = ['./root-ca.crt'] |
|||
# Disable SSL certificate verification (not recommended for production) |
|||
# libcloud.security.VERIFY_SSL_CERT = False |
|||
|
|||
# Please use 1-29 for 0 in the following variable to specify your group number. |
|||
# (will be used for the username, project etc., as coordinated in the lab sessions) |
|||
|
|||
GROUP_NUMBER = 0 |
|||
|
|||
|
|||
############################################################################################### |
|||
# |
|||
# no changes necessary below this line in this example |
|||
# |
|||
############################################################################################### |
|||
|
|||
# web service endpoint of the private cloud infrastructure |
|||
# auth_url = 'https://private-cloud.informatik.hs-fulda.de:5000' |
|||
AUTH_URL = 'https://10.32.4.182:5000' |
|||
# auth_url = 'https://private-cloud2.informatik.hs-fulda.de:5000' |
|||
# your username in OpenStack |
|||
AUTH_USERNAME = 'CloudComp' + str(GROUP_NUMBER) |
|||
# your project in OpenStack |
|||
PROJECT_NAME = 'CloudComp' + str(GROUP_NUMBER) |
|||
# A network in the project the started instance will be attached to |
|||
PROJECT_NETWORK = 'CloudComp' + str(GROUP_NUMBER) + '-net' |
|||
|
|||
# The image to look for and use for the started instance |
|||
# ubuntu_image_name = "Ubuntu 18.04 - Bionic Beaver - 64-bit - Cloud Based Image" |
|||
UBUNTU_IMAGE_NAME = "auto-sync/ubuntu-jammy-22.04-amd64-server-20240319-disk1.img" |
|||
|
|||
# default region |
|||
REGION_NAME = 'RegionOne' |
|||
# domain to use, "default" for local accounts, formerly "hsfulda" for LDAP accounts etc. |
|||
# domain_name = "default" |
|||
|
|||
|
|||
def main(): # noqa: C901 pylint: disable=too-many-branches,too-many-statements,too-many-locals,missing-function-docstring |
|||
# get the password from user |
|||
# auth_password = getpass.getpass("Enter your OpenStack password:") |
|||
auth_password = "demo" |
|||
|
|||
# instantiate a connection to the OpenStack private cloud |
|||
# make sure to include ex_force_auth_version='3.x_password', as needed in our environment |
|||
provider = get_driver(Provider.OPENSTACK) |
|||
|
|||
print(f"Opening connection to {AUTH_URL} as {AUTH_USERNAME}...") |
|||
|
|||
conn = provider(AUTH_USERNAME, |
|||
auth_password, |
|||
ex_force_auth_url=AUTH_URL, |
|||
ex_force_auth_version='3.x_password', |
|||
ex_tenant_name=PROJECT_NAME, |
|||
ex_force_service_region=REGION_NAME) |
|||
# ex_domain_name=domain_name) |
|||
|
|||
print("Getting images and selecting desired one...") |
|||
print("=========================================================================") |
|||
|
|||
# get a list of images offered in the cloud context (e.g. Ubuntu 20.04, cirros, ...) |
|||
images = conn.list_images() |
|||
image = '' |
|||
for img in images: |
|||
if img.name == UBUNTU_IMAGE_NAME: |
|||
image = img |
|||
print(img) |
|||
|
|||
print("Getting flavors...") |
|||
print("=========================================================================") |
|||
|
|||
# get a list of flavors offered in the cloud context (e.g. m1.small, m1.medium, ...) |
|||
flavors = conn.list_sizes() |
|||
for flavor in flavors: |
|||
print(flavor) |
|||
|
|||
print("Selecting desired flavor...") |
|||
print("=========================================================================") |
|||
|
|||
# get the flavor with id 2 |
|||
flavor_id = '2' |
|||
flavor = conn.ex_get_size(flavor_id) |
|||
print(flavor) |
|||
|
|||
print("Selecting desired network...") |
|||
print("=========================================================================") |
|||
|
|||
# get a list of networks in the cloud context |
|||
networks = conn.ex_list_networks() |
|||
network = '' |
|||
for net in networks: |
|||
if net.name == PROJECT_NETWORK: |
|||
network = net |
|||
|
|||
print("Create instance 'testing'...") |
|||
print("=========================================================================") |
|||
|
|||
# create a new instance with the name "testing" |
|||
# make sure to provide networks (networks={network}) the instance should be attached to |
|||
instance_name = 'testing' |
|||
testing_instance = conn.create_node(name=instance_name, image=image, size=flavor, |
|||
networks={network}) |
|||
print(testing_instance) |
|||
|
|||
print("Showing all running instances...") |
|||
print("=========================================================================") |
|||
|
|||
# show all instances (running nodes) in the cloud context |
|||
instances = conn.list_nodes() |
|||
for instance in instances: |
|||
print(instance) |
|||
|
|||
print("Destroying instance...") |
|||
print("=========================================================================") |
|||
|
|||
# destroy the instance we have just created |
|||
conn.destroy_node(testing_instance) |
|||
|
|||
|
|||
# method that is called when the script is started from the command line |
|||
if __name__ == '__main__': |
|||
main() |
@ -0,0 +1,268 @@ |
|||
"""Example for Cloud Computing Course Master AI / GSD""" |
|||
|
|||
# This script demonstrates how to use libcloud to start an instance in an OpenStack environment. |
|||
# The script will create and install a new SSH key pair, create a security group, start an instance |
|||
# and deploy a demo app (faafo) using cloud-init and assign a floating IP to the instance. |
|||
# |
|||
# cloud-init is a multi-distribution package that handles early initialization of a cloud instance. |
|||
# It is supported by many major cloud providers, including OpenStack. |
|||
# cloud-init documentation: https://cloudinit.readthedocs.io/en/latest/ |
|||
|
|||
# Needed if the password should be prompted for: |
|||
# import getpass |
|||
import os |
|||
import sys |
|||
|
|||
from libcloud.compute.providers import get_driver |
|||
from libcloud.compute.types import Provider |
|||
|
|||
# For our new Charmed OpenStack private cloud, we need to specify the path to the root |
|||
# CA certificate |
|||
import libcloud.security |
|||
libcloud.security.CA_CERTS_PATH = ['./root-ca.crt'] |
|||
# Disable SSL certificate verification (not recommended for production) |
|||
# libcloud.security.VERIFY_SSL_CERT = False |
|||
|
|||
# Please use 1-29 as environment variable GROUP_NUMBER to specify your group number. |
|||
# (will be used for the username, project etc., as coordinated in the lab sessions) |
|||
|
|||
group_number = os.environ.get('GROUP_NUMBER') |
|||
if group_number is None: |
|||
sys.exit('Please set the GROUP_NUMBER environment variable to your group number,\n' |
|||
'e.g., on Windows:\n' |
|||
' "$env:GROUP_NUMBER=0" or "set GROUP_NUMBER=0"\n' |
|||
'or on Linux/MacOS:\n' |
|||
' "export GROUP_NUMBER=0" or "set GROUP_NUMBER=0"') |
|||
|
|||
|
|||
# web service endpoint of the private cloud infrastructure |
|||
# auth_url = 'https://private-cloud.informatik.hs-fulda.de:5000' |
|||
AUTH_URL = 'https://10.32.4.182:5000' |
|||
# auth_url = 'https://private-cloud2.informatik.hs-fulda.de:5000' |
|||
# your username in OpenStack |
|||
AUTH_USERNAME = 'CloudComp' + str(group_number) |
|||
print(f'Using username: {AUTH_USERNAME}\n') |
|||
# your project in OpenStack |
|||
PROJECT_NAME = 'CloudComp' + str(group_number) |
|||
# A network in the project the started instance will be attached to |
|||
PROJECT_NETWORK = 'CloudComp' + str(group_number) + '-net' |
|||
|
|||
# The image to look for and use for the started instance |
|||
# ubuntu_image_name = "Ubuntu 18.04 - Bionic Beaver - 64-bit - Cloud Based Image" |
|||
UBUNTU_IMAGE_NAME = "auto-sync/ubuntu-jammy-22.04-amd64-server-20240319-disk1.img" |
|||
|
|||
# The public key to be used for SSH connection, please make sure, that you have the |
|||
# corresponding private key |
|||
# |
|||
# id_rsa.pub should look like this (standard sshd pubkey format): |
|||
# ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAw+J...F3w2mleybgT1w== user@HOSTNAME |
|||
|
|||
KEYPAIR_NAME = 'srieger-pub' |
|||
PUB_KEY_FILE = '~/.ssh/id_rsa.pub' |
|||
|
|||
FLAVOR_NAME = 'm1.small' |
|||
|
|||
|
|||
# default region |
|||
REGION_NAME = 'RegionOne' |
|||
# domain to use, "default" for local accounts, formerly "hsfulda" for LDAP accounts etc. |
|||
# domain_name = "default" |
|||
|
|||
|
|||
def main(): # noqa: C901 pylint: disable=too-many-branches,too-many-statements,too-many-locals,missing-function-docstring |
|||
########################################################################### |
|||
# |
|||
# get credentials |
|||
# |
|||
########################################################################### |
|||
|
|||
# if "OS_PASSWORD" in os.environ: |
|||
# auth_password = os.environ["OS_PASSWORD"] |
|||
# else: |
|||
# auth_password = getpass.getpass("Enter your OpenStack password:") |
|||
auth_password = "demo" |
|||
|
|||
########################################################################### |
|||
# |
|||
# create connection |
|||
# |
|||
########################################################################### |
|||
|
|||
provider = get_driver(Provider.OPENSTACK) |
|||
conn = provider(AUTH_USERNAME, |
|||
auth_password, |
|||
ex_force_auth_url=AUTH_URL, |
|||
ex_force_auth_version='3.x_password', |
|||
ex_tenant_name=PROJECT_NAME, |
|||
ex_force_service_region=REGION_NAME) |
|||
# ex_domain_name=domain_name) |
|||
|
|||
########################################################################### |
|||
# |
|||
# get image, flavor, network for instance creation |
|||
# |
|||
########################################################################### |
|||
images = conn.list_images() |
|||
image = '' |
|||
for img in images: |
|||
if img.name == UBUNTU_IMAGE_NAME: |
|||
image = img |
|||
|
|||
flavors = conn.list_sizes() |
|||
flavor = '' |
|||
for flav in flavors: |
|||
if flav.name == FLAVOR_NAME: |
|||
flavor = conn.ex_get_size(flav.id) |
|||
|
|||
networks = conn.ex_list_networks() |
|||
network = '' |
|||
for net in networks: |
|||
if net.name == PROJECT_NETWORK: |
|||
network = net |
|||
|
|||
########################################################################### |
|||
# |
|||
# create keypair dependency |
|||
# |
|||
########################################################################### |
|||
|
|||
print('Checking for existing SSH key pair...') |
|||
keypair_exists = False |
|||
for keypair in conn.list_key_pairs(): |
|||
if keypair.name == KEYPAIR_NAME: |
|||
keypair_exists = True |
|||
|
|||
if keypair_exists: |
|||
print('Keypair ' + KEYPAIR_NAME + ' already exists. Skipping import.') |
|||
else: |
|||
print('adding keypair...') |
|||
conn.import_key_pair_from_file(KEYPAIR_NAME, PUB_KEY_FILE) |
|||
|
|||
for keypair in conn.list_key_pairs(): |
|||
print(keypair) |
|||
|
|||
########################################################################### |
|||
# |
|||
# create security group dependency |
|||
# |
|||
########################################################################### |
|||
|
|||
print('Checking for existing security group...') |
|||
security_group_name = 'all-in-one' |
|||
security_group_exists = False |
|||
all_in_one_security_group = '' |
|||
for security_group in conn.ex_list_security_groups(): |
|||
if security_group.name == security_group_name: |
|||
all_in_one_security_group = security_group |
|||
security_group_exists = True |
|||
|
|||
if security_group_exists: |
|||
print('Security Group ' + all_in_one_security_group.name + ' already exists. ' |
|||
'Skipping creation.') |
|||
else: |
|||
all_in_one_security_group = conn.ex_create_security_group(security_group_name, |
|||
'network access for ' |
|||
'all-in-one application.') |
|||
conn.ex_create_security_group_rule(all_in_one_security_group, 'TCP', 80, 80) |
|||
conn.ex_create_security_group_rule(all_in_one_security_group, 'TCP', 22, 22) |
|||
|
|||
for security_group in conn.ex_list_security_groups(): |
|||
print(security_group) |
|||
|
|||
########################################################################### |
|||
# |
|||
# create all-in-one instance |
|||
# |
|||
########################################################################### |
|||
|
|||
hsfd_faafo_cloud_init_script = 'https://gogs.informatik.hs-fulda.de/srieger/cloud-computing-msc-ai-examples/raw/master/faafo/contrib/install.sh' # noqa: E501 pylint: disable=line-too-long |
|||
# testing / faafo dev branch: |
|||
# hsfd_faafo_cloud_init_script = 'https://gogs.informatik.hs-fulda.de/srieger/cloud-computing-msc-ai-examples/raw/branch/dev_faafo/faafo/contrib/install.sh' # noqa: E501 pylint: disable=line-too-long |
|||
|
|||
userdata = '#!/usr/bin/env bash\n' \ |
|||
f'curl -L -s {hsfd_faafo_cloud_init_script} | bash -s -- ' \ |
|||
'-i faafo -i messaging -r api -r worker -r demo\n' |
|||
print('\nUsing cloud-init userdata:\n"' + userdata + '"\n') |
|||
|
|||
print('Checking for existing instance...') |
|||
instance_name = 'all-in-one' |
|||
instance_exists = False |
|||
testing_instance = '' |
|||
for instance in conn.list_nodes(): |
|||
if instance.name == instance_name: |
|||
testing_instance = instance |
|||
instance_exists = True |
|||
|
|||
if instance_exists: |
|||
print('Instance ' + testing_instance.name + ' already exists. Skipping creation.') |
|||
exit() |
|||
else: |
|||
print('Starting new all-in-one instance and wait until it is running...') |
|||
testing_instance = conn.create_node(name=instance_name, |
|||
image=image, |
|||
size=flavor, |
|||
networks=[network], |
|||
ex_keyname=KEYPAIR_NAME, |
|||
ex_userdata=userdata, |
|||
ex_security_groups=[all_in_one_security_group]) |
|||
conn.wait_until_running(nodes=[testing_instance], timeout=120, ssh_interface='private_ips') |
|||
|
|||
########################################################################### |
|||
# |
|||
# assign all-in-one instance floating ip |
|||
# |
|||
########################################################################### |
|||
|
|||
private_ip = None |
|||
if len(testing_instance.private_ips): |
|||
private_ip = testing_instance.private_ips[0] |
|||
print(f'Private IP found: {private_ip}') |
|||
|
|||
public_ip = None |
|||
if len(testing_instance.public_ips): |
|||
public_ip = testing_instance.public_ips[0] |
|||
print(f'Public IP found: {public_ip}') |
|||
|
|||
print('Checking for unused Floating IP...') |
|||
unused_floating_ip = None |
|||
for floating_ip in conn.ex_list_floating_ips(): |
|||
if not floating_ip.node_id: |
|||
unused_floating_ip = floating_ip |
|||
break |
|||
|
|||
if not unused_floating_ip and len(conn.ex_list_floating_ip_pools()): |
|||
pool = conn.ex_list_floating_ip_pools()[0] |
|||
print(f'Allocating new Floating IP from pool: {pool}') |
|||
unused_floating_ip = pool.create_floating_ip() |
|||
|
|||
if public_ip: |
|||
print('Instance ' + testing_instance.name + ' already has a public ip. Skipping attachment.') |
|||
elif unused_floating_ip: |
|||
conn.ex_attach_floating_ip_to_node(testing_instance, unused_floating_ip) |
|||
|
|||
actual_ip_address = None |
|||
if public_ip: |
|||
actual_ip_address = public_ip |
|||
elif unused_floating_ip: |
|||
actual_ip_address = unused_floating_ip.ip_address |
|||
elif private_ip: |
|||
actual_ip_address = private_ip |
|||
|
|||
print('\n\n#### Deployment finished\n\n') |
|||
print('After some minutes, as soon as cloud-init installed required packages and the\n' |
|||
'faafo app, (First App Application For OpenStack) fractals demo will be available\n' |
|||
f'at http://{actual_ip_address}\n') |
|||
|
|||
print('You can use ssh to login to the instance using your private key. Default user name for official Ubuntu\n' |
|||
f'Cloud Images is: ubuntu, so you can use, e.g.: "ssh -i ~/.ssh/id_rsa ubuntu@{actual_ip_address}" if your\n' |
|||
'private key is in the default location.\n\n' |
|||
'After login, you can list available fractals using "faafo list". \n' |
|||
'To request the generation of new fractals, you can use "faafo create".\n\n' |
|||
'You can also see other options to use the faafo example cloud service using "faafo -h".\n\n' |
|||
'If you cannot start faafo command and/or do not see the webpage, you can check the Instance Console Log of\n' |
|||
'the instance, e.g., in OpenStack web interface or look at "tail -f /var/log/cloud-init*.log" for the\n' |
|||
'cloud-init log files.\n') |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
main() |
@ -0,0 +1,317 @@ |
|||
"""Example for Cloud Computing Course Master AI / GSD""" |
|||
|
|||
# This script demonstrates how to use libcloud to start an instance in an OpenStack environment. |
|||
# The script will create start multiple instances splitting up the faafo monolithic application into |
|||
# a (minimalistic but already scalable) microservice architecture. |
|||
# Also introduces the concept of different security groups and corresponding frontend/backend |
|||
# separation. |
|||
|
|||
# Needed if the password should be prompted for: |
|||
# import getpass |
|||
import os |
|||
import sys |
|||
|
|||
from libcloud.compute.providers import get_driver |
|||
from libcloud.compute.types import Provider |
|||
|
|||
# For our new Charmed OpenStack private cloud, we need to specify the path to the root |
|||
# CA certificate |
|||
import libcloud.security |
|||
libcloud.security.CA_CERTS_PATH = ['./root-ca.crt'] |
|||
# Disable SSL certificate verification (not recommended for production) |
|||
# libcloud.security.VERIFY_SSL_CERT = False |
|||
|
|||
# Please use 1-29 as environment variable GROUP_NUMBER to specify your group number. |
|||
# (will be used for the username, project etc., as coordinated in the lab sessions) |
|||
|
|||
group_number = os.environ.get('GROUP_NUMBER') |
|||
if group_number is None: |
|||
sys.exit('Please set the GROUP_NUMBER environment variable to your group number,\n' |
|||
'e.g., on Windows:\n' |
|||
' "$env:GROUP_NUMBER=0" or "set GROUP_NUMBER=0"\n' |
|||
'or on Linux/MacOS:\n' |
|||
' "export GROUP_NUMBER=0" or "set GROUP_NUMBER=0"') |
|||
|
|||
|
|||
# web service endpoint of the private cloud infrastructure |
|||
# auth_url = 'https://private-cloud.informatik.hs-fulda.de:5000' |
|||
AUTH_URL = 'https://10.32.4.182:5000' |
|||
# auth_url = 'https://private-cloud2.informatik.hs-fulda.de:5000' |
|||
# your username in OpenStack |
|||
AUTH_USERNAME = 'CloudComp' + str(group_number) |
|||
print(f'Using username: {AUTH_USERNAME}\n') |
|||
# your project in OpenStack |
|||
PROJECT_NAME = 'CloudComp' + str(group_number) |
|||
# A network in the project the started instance will be attached to |
|||
PROJECT_NETWORK = 'CloudComp' + str(group_number) + '-net' |
|||
|
|||
# The image to look for and use for the started instance |
|||
# ubuntu_image_name = "Ubuntu 18.04 - Bionic Beaver - 64-bit - Cloud Based Image" |
|||
UBUNTU_IMAGE_NAME = "auto-sync/ubuntu-jammy-22.04-amd64-server-20240319-disk1.img" |
|||
|
|||
# The public key to be used for SSH connection, please make sure, that you have the |
|||
# corresponding private key |
|||
# |
|||
# id_rsa.pub should look like this (standard sshd pubkey format): |
|||
# ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAw+J...F3w2mleybgT1w== user@HOSTNAME |
|||
|
|||
KEYPAIR_NAME = 'srieger-pub' |
|||
PUB_KEY_FILE = '~/.ssh/id_rsa.pub' |
|||
|
|||
FLAVOR_NAME = 'm1.small' |
|||
|
|||
|
|||
# default region |
|||
REGION_NAME = 'RegionOne' |
|||
# domain to use, "default" for local accounts, formerly "hsfulda" for LDAP accounts etc. |
|||
# domain_name = "default" |
|||
|
|||
|
|||
def main(): # noqa: C901 pylint: disable=too-many-branches,too-many-statements,too-many-locals,missing-function-docstring |
|||
########################################################################### |
|||
# |
|||
# get credentials |
|||
# |
|||
########################################################################### |
|||
|
|||
# if "OS_PASSWORD" in os.environ: |
|||
# auth_password = os.environ["OS_PASSWORD"] |
|||
# else: |
|||
# auth_password = getpass.getpass("Enter your OpenStack password:") |
|||
auth_password = "demo" |
|||
|
|||
########################################################################### |
|||
# |
|||
# create connection |
|||
# |
|||
########################################################################### |
|||
|
|||
provider = get_driver(Provider.OPENSTACK) |
|||
conn = provider(AUTH_USERNAME, |
|||
auth_password, |
|||
ex_force_auth_url=AUTH_URL, |
|||
ex_force_auth_version='3.x_password', |
|||
ex_tenant_name=PROJECT_NAME, |
|||
ex_force_service_region=REGION_NAME) |
|||
# ex_domain_name=domain_name) |
|||
|
|||
########################################################################### |
|||
# |
|||
# get image, flavor, network for instance creation |
|||
# |
|||
########################################################################### |
|||
|
|||
images = conn.list_images() |
|||
image = '' |
|||
for img in images: |
|||
if img.name == UBUNTU_IMAGE_NAME: |
|||
image = img |
|||
|
|||
flavors = conn.list_sizes() |
|||
flavor = '' |
|||
for flav in flavors: |
|||
if flav.name == FLAVOR_NAME: |
|||
flavor = conn.ex_get_size(flav.id) |
|||
|
|||
networks = conn.ex_list_networks() |
|||
network = '' |
|||
for net in networks: |
|||
if net.name == PROJECT_NETWORK: |
|||
network = net |
|||
|
|||
########################################################################### |
|||
# |
|||
# create keypair dependency |
|||
# |
|||
########################################################################### |
|||
|
|||
print('Checking for existing SSH key pair...') |
|||
keypair_exists = False |
|||
for keypair in conn.list_key_pairs(): |
|||
if keypair.name == KEYPAIR_NAME: |
|||
keypair_exists = True |
|||
|
|||
if keypair_exists: |
|||
print('Keypair ' + KEYPAIR_NAME + ' already exists. Skipping import.') |
|||
else: |
|||
print('adding keypair...') |
|||
conn.import_key_pair_from_file(KEYPAIR_NAME, PUB_KEY_FILE) |
|||
|
|||
for keypair in conn.list_key_pairs(): |
|||
print(keypair) |
|||
|
|||
########################################################################### |
|||
# |
|||
# create security group dependency |
|||
# |
|||
########################################################################### |
|||
|
|||
print('Checking for existing worker security group...') |
|||
security_group_name = 'worker' |
|||
security_group_exists = False |
|||
worker_security_group = '' |
|||
for security_group in conn.ex_list_security_groups(): |
|||
if security_group.name == security_group_name: |
|||
worker_security_group = security_group |
|||
security_group_exists = True |
|||
|
|||
if security_group_exists: |
|||
print('Worker Security Group ' + worker_security_group.name + ' already exists. ' |
|||
'Skipping creation.') |
|||
else: |
|||
worker_security_group = conn.ex_create_security_group('worker', 'for services ' |
|||
'that run on a worker node') |
|||
conn.ex_create_security_group_rule(worker_security_group, 'TCP', 22, 22) |
|||
|
|||
print('Checking for existing controller security group...') |
|||
security_group_name = 'control' |
|||
security_group_exists = False |
|||
controller_security_group = '' |
|||
for security_group in conn.ex_list_security_groups(): |
|||
if security_group.name == security_group_name: |
|||
controller_security_group = security_group |
|||
security_group_exists = True |
|||
|
|||
if security_group_exists: |
|||
print('Controller Security Group ' + controller_security_group.name + ' already exists. ' |
|||
'Skipping creation.') |
|||
else: |
|||
controller_security_group = conn.ex_create_security_group('control', 'for services that ' |
|||
'run on a control node') |
|||
conn.ex_create_security_group_rule(controller_security_group, 'TCP', 22, 22) |
|||
conn.ex_create_security_group_rule(controller_security_group, 'TCP', 80, 80) |
|||
conn.ex_create_security_group_rule(controller_security_group, 'TCP', 5672, 5672, |
|||
source_security_group=worker_security_group) |
|||
|
|||
for security_group in conn.ex_list_security_groups(): |
|||
print(security_group) |
|||
|
|||
########################################################################### |
|||
# |
|||
# create app-controller |
|||
# |
|||
########################################################################### |
|||
|
|||
# https://git.openstack.org/cgit/openstack/faafo/plain/contrib/install.sh |
|||
# is currently broken, hence the "rabbitctl" lines were added in the example |
|||
# below, see also https://bugs.launchpad.net/faafo/+bug/1679710 |
|||
# |
|||
# Thanks to Stefan Friedmann for finding this fix ;) |
|||
# TODO: still needed for new version of faafo and Ubuntu 22.04? |
|||
|
|||
userdata = '#!/usr/bin/env bash\n' \ |
|||
'curl -L -s https://gogs.informatik.hs-fulda.de/srieger/cloud-computing-msc-ai-' \ |
|||
'examples/raw/master/faafo/contrib/install.sh | bash -s -- ' \ |
|||
'-i messaging -i faafo -r api\n' \ |
|||
'rabbitmqctl add_user faafo guest\n' \ |
|||
'rabbitmqctl set_user_tags faafo administrator\n' \ |
|||
'rabbitmqctl set_permissions -p / faafo ".*" ".*" ".*"\n' |
|||
print('\nUsing cloud-init userdata:\n"' + userdata + '"\n') |
|||
|
|||
print('Starting new app-controller instance and wait until it is running...') |
|||
instance_controller_1 = conn.create_node(name='app-controller', |
|||
image=image, |
|||
size=flavor, |
|||
networks=[network], |
|||
ex_keyname=KEYPAIR_NAME, |
|||
ex_userdata=userdata, |
|||
ex_security_groups=[controller_security_group]) |
|||
|
|||
conn.wait_until_running(nodes=[instance_controller_1], timeout=120, ssh_interface='private_ips') |
|||
|
|||
########################################################################### |
|||
# |
|||
# assign app-controller floating ip |
|||
# |
|||
########################################################################### |
|||
|
|||
print('Checking for unused Floating IP...') |
|||
unused_floating_ip = None |
|||
for floating_ip in conn.ex_list_floating_ips(): |
|||
if not floating_ip.node_id: |
|||
unused_floating_ip = floating_ip |
|||
break |
|||
|
|||
if not unused_floating_ip: |
|||
pool = conn.ex_list_floating_ip_pools()[0] |
|||
print(f'Allocating new Floating IP from pool: {pool}') |
|||
unused_floating_ip = pool.create_floating_ip() |
|||
|
|||
conn.ex_attach_floating_ip_to_node(instance_controller_1, unused_floating_ip) |
|||
print(f'Controller Application will be deployed to http://{unused_floating_ip.ip_address}') |
|||
actual_ip_address = unused_floating_ip.ip_address |
|||
|
|||
########################################################################### |
|||
# |
|||
# getting id and ip address of app-controller instance |
|||
# |
|||
########################################################################### |
|||
|
|||
# instance should not have a public ip? floating ips are assigned later |
|||
instance_controller_1 = conn.ex_get_node_details(instance_controller_1.id) |
|||
ip_controller = '' |
|||
if instance_controller_1.public_ips: |
|||
ip_controller = instance_controller_1.public_ips[0] |
|||
else: |
|||
ip_controller = instance_controller_1.private_ips[0] |
|||
|
|||
########################################################################### |
|||
# |
|||
# create app-worker-1 |
|||
# |
|||
########################################################################### |
|||
|
|||
userdata = '#!/usr/bin/env bash\n' \ |
|||
'curl -L -s https://gogs.informatik.hs-fulda.de/srieger/cloud-computing-msc-ai-' \ |
|||
'examples/raw/master/faafo/contrib/install.sh | bash -s -- ' \ |
|||
f'-i faafo -r worker -e "http://{ip_controller}" -m "amqp://faafo:guest@' \ |
|||
f'{ip_controller}:5672/\n' |
|||
print('\nUsing cloud-init userdata:\n"' + userdata + '"\n') |
|||
|
|||
print('Starting new app-worker-1 instance and wait until it is running...') |
|||
instance_worker_1 = conn.create_node(name='app-worker-1', |
|||
image=image, |
|||
size=flavor, |
|||
networks=[network], |
|||
ex_keyname=KEYPAIR_NAME, |
|||
ex_userdata=userdata, |
|||
ex_security_groups=[worker_security_group]) |
|||
|
|||
conn.wait_until_running(nodes=[instance_worker_1], timeout=120, ssh_interface='private_ips') |
|||
|
|||
########################################################################### |
|||
# |
|||
# assign app-worker floating ip |
|||
# |
|||
########################################################################### |
|||
|
|||
print('Checking for unused Floating IP...') |
|||
unused_floating_ip = None |
|||
for floating_ip in conn.ex_list_floating_ips(): |
|||
if not floating_ip.node_id: |
|||
unused_floating_ip = floating_ip |
|||
break |
|||
|
|||
if not unused_floating_ip: |
|||
pool = conn.ex_list_floating_ip_pools()[0] |
|||
print(f'Allocating new Floating IP from pool: {pool}') |
|||
unused_floating_ip = pool.create_floating_ip() |
|||
|
|||
conn.ex_attach_floating_ip_to_node(instance_worker_1, unused_floating_ip) |
|||
print(f'The worker will be available for SSH at {unused_floating_ip.ip_address}') |
|||
|
|||
print('\n\n#### Deployment finished\n\n') |
|||
print('After some minutes, as soon as cloud-init installed required packages and the\n' |
|||
'faafo app, (First App Application For OpenStack) fractals demo will be available\n' |
|||
f'at http://{actual_ip_address}\n') |
|||
|
|||
print('You can use ssh to login to the controller using your private key.\n' |
|||
f'E.g., "ssh -i ~/.ssh/id_rsa ubuntu@{actual_ip_address}". After login,\n' |
|||
'you can list available fractals using "faafo list". To request the generation of\n' |
|||
'new fractals, you can use "faafo create". \n' |
|||
'You can also see other options to use the faafo example cloud service using ' |
|||
'"faafo -h".') |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
main() |
@ -0,0 +1,126 @@ |
|||
"""Example for Cloud Computing Course Master AI / GSD""" |
|||
|
|||
|
|||
# This script demonstrates how to use libcloud to cleanup all instances used in the demos |
|||
# for our OpenStack private cloud environment. |
|||
|
|||
# import getpass |
|||
import os |
|||
import sys |
|||
|
|||
import time |
|||
from libcloud.compute.providers import get_driver |
|||
from libcloud.compute.types import Provider |
|||
|
|||
# For our new Charmed OpenStack private cloud, we need to specify the path to the |
|||
# root CA certificate |
|||
import libcloud.security |
|||
libcloud.security.CA_CERTS_PATH = ['./root-ca.crt'] |
|||
# Disable SSL certificate verification (not recommended for production) |
|||
# libcloud.security.VERIFY_SSL_CERT = False |
|||
|
|||
# Please use 1-29 for X in the following variable to specify your group number. |
|||
# (will be used for the username, project etc., as coordinated in the lab sessions) |
|||
|
|||
group_number = os.environ.get('GROUP_NUMBER') |
|||
if group_number is None: |
|||
sys.exit('Please set the GROUP_NUMBER environment variable to your group number,\n' |
|||
'e.g., on Windows:\n' |
|||
' "$env:GROUP_NUMBER=0" or "set GROUP_NUMBER=0"\n' |
|||
'or on Linux/MacOS:\n' |
|||
' "export GROUP_NUMBER=0" or "set GROUP_NUMBER=0"') |
|||
|
|||
|
|||
############################################################################################### |
|||
# |
|||
# no changes necessary below this line in this example |
|||
# |
|||
############################################################################################### |
|||
|
|||
# web service endpoint of the private cloud infrastructure |
|||
# auth_url = 'https://private-cloud.informatik.hs-fulda.de:5000' |
|||
AUTH_URL = 'https://10.32.4.182:5000' |
|||
# auth_url = 'https://private-cloud2.informatik.hs-fulda.de:5000' |
|||
# your username in OpenStack |
|||
AUTH_USERNAME = 'CloudComp' + str(group_number) |
|||
# your project in OpenStack |
|||
PROJECT_NAME = 'CloudComp' + str(group_number) |
|||
# A network in the project the started instance will be attached to |
|||
PROJET_NETWORK = 'CloudComp' + str(group_number) + '-net' |
|||
|
|||
# The image to look for and use for the started instance |
|||
# ubuntu_image_name = "Ubuntu 18.04 - Bionic Beaver - 64-bit - Cloud Based Image" |
|||
UBUNTU_IMAGE_NAME = "auto-sync/ubuntu-jammy-22.04-amd64-server-20240319-disk1.img" |
|||
|
|||
# default region |
|||
REGION_NAME = 'RegionOne' |
|||
# domain to use, "default" for local accounts, formerly "hsfulda" for LDAP accounts etc. |
|||
# domain_name = "default" |
|||
|
|||
|
|||
def main(): # noqa: C901 pylint: disable=too-many-branches,too-many-statements,too-many-locals,missing-function-docstring |
|||
########################################################################### |
|||
# |
|||
# get credentials |
|||
# |
|||
########################################################################### |
|||
|
|||
# if "OS_PASSWORD" in os.environ: |
|||
# auth_password = os.environ["OS_PASSWORD"] |
|||
# else: |
|||
# auth_password = getpass.getpass("Enter your OpenStack password:") |
|||
auth_password = "demo" |
|||
|
|||
########################################################################### |
|||
# |
|||
# create connection |
|||
# |
|||
########################################################################### |
|||
|
|||
# libcloud.security.VERIFY_SSL_CERT = False |
|||
|
|||
provider = get_driver(Provider.OPENSTACK) |
|||
conn = provider(AUTH_USERNAME, |
|||
auth_password, |
|||
ex_force_auth_url=AUTH_URL, |
|||
ex_force_auth_version='3.x_password', |
|||
ex_tenant_name=PROJECT_NAME, |
|||
ex_force_service_region=REGION_NAME) |
|||
# ex_domain_name=domain_name) |
|||
|
|||
########################################################################### |
|||
# |
|||
# clean up resources from previous demos |
|||
# |
|||
########################################################################### |
|||
|
|||
# destroy running demo instances |
|||
for instance in conn.list_nodes(): |
|||
if instance.name in ['all-in-one', 'app-worker-1', 'app-worker-2', 'app-worker-3', |
|||
'app-controller', |
|||
'app-services', 'app-api-1', 'app-api-2']: |
|||
print(f'Destroying Instance: {instance.name}') |
|||
conn.destroy_node(instance) |
|||
|
|||
# wait until all nodes are destroyed to be able to remove depended security groups |
|||
nodes_still_running = True |
|||
while nodes_still_running: |
|||
nodes_still_running = False |
|||
time.sleep(3) |
|||
instances = conn.list_nodes() |
|||
for instance in instances: |
|||
# if we see any demo instances still running continue to wait for them to stop |
|||
if instance.name in ['all-in-one', 'app-worker-1', 'app-worker-2', 'app-worker-3', |
|||
'app-controller', 'app-services', 'app-api-1', 'app-api-2']: |
|||
nodes_still_running = True |
|||
print('There are still instances running, waiting for them to be destroyed...') |
|||
|
|||
# delete security groups |
|||
for group in conn.ex_list_security_groups(): |
|||
if group.name in ['control', 'worker', 'api', 'services']: |
|||
print(f'Deleting security group: {group.name}') |
|||
conn.ex_delete_security_group(group) |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
main() |
@ -0,0 +1,21 @@ |
|||
-----BEGIN CERTIFICATE----- |
|||
MIIDazCCAlOgAwIBAgIUEQjSqiZ86fhawQU09G8hn3i9dIwwDQYJKoZIhvcNAQEL |
|||
BQAwPTE7MDkGA1UEAxMyVmF1bHQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkg |
|||
KGNoYXJtLXBraS1sb2NhbCkwHhcNMjQwMzI1MTMxNDU0WhcNMzQwMzIzMTIxNTIz |
|||
WjA9MTswOQYDVQQDEzJWYXVsdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAo |
|||
Y2hhcm0tcGtpLWxvY2FsKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB |
|||
ALcax5l2zU1ELCtF/k6yq3HUv7gFq6f/sl8rX0VRhzZyEy4hcMgRSZDAM14viTVZ |
|||
8d7+ptY3+GwuLSpEY2UUlX5kJSDb4pUNRXDhxzRatbByG8pr5FQE8pX9W7y4C0TU |
|||
3PQA4uIjAsPFKayFxXjJjOQN0HX3K6MCQz/BTV81U3fmdFrKma3x/PXyUYndjQH6 |
|||
zlIiQSdYh7FMTbS2FlpvwWbT9zKOpp+2M0odI8Y8fjCSUdSdKDFhVu02zQTq6/h0 |
|||
Q1/sNHz2IP9F83sNW+ro0bvv5CJ2iCyAk/RiFoB+RoSO6HncOtYHxa/guwTy4eHh |
|||
VQVJXkEI2PutCw6S3lWqLEcCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud |
|||
EwEB/wQFMAMBAf8wHQYDVR0OBBYEFDKQHfpVHJgge6RRC5uDwMByLbV3MB8GA1Ud |
|||
IwQYMBaAFDKQHfpVHJgge6RRC5uDwMByLbV3MA0GCSqGSIb3DQEBCwUAA4IBAQCa |
|||
ajIRi/+7Yy7l46yFURLyELMWayRpdx2KCxIuAiSkTlNSVOPCmwZvgnYLPVffXWpt |
|||
IXJGQk//9+5q18LiZat5MbvUU3ffLc/ZCxIeQiWNuYKziLYNFHmpfMvxNxzAJ6Pi |
|||
2fj5ZP/cA4Vie3M1iHfdSXmYPvyw76i9/sA2+F7Wy8fzK53S1OaMaeADNGljHTaW |
|||
ovRxreLKJZybqe/YWlcEiP4dC4VMHLl+H5RmZ5ojrRiy1c3uUssNnIJU+ilkY8TP |
|||
0VV17+wQBaJbbp4jh8acwvOJbN8Y1EHQWhxkEf3PfjJRv+b1NI/Iai27DfYto7Dm |
|||
rZvaFnAMCcyFXyJv3WdJ |
|||
-----END CERTIFICATE----- |
Write
Preview
Loading…
Cancel
Save
Reference in new issue