diff --git a/README.md b/README.md index 82cbd4d..ead18e7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ + + + +DUE: 17 October + # virt-openstack-assignment OpenStack SDK assignment for ID720 paper @@ -19,7 +24,7 @@ be taken for each argument are - names: \-web, \-app, \-db - security-group: assignment2 (You do not need to create this) Assign the floating IP to the web server. - If any of the resources above already exisit when the script is run, then they + If any of the resources above already exist when the script is run, then they should not be recreated. *run*: Start the three servers created above. If any of them do not exist, diff --git a/assignment.py b/assignment.py deleted file mode 100644 index 28758e7..0000000 --- a/assignment.py +++ /dev/null @@ -1,50 +0,0 @@ -import argparse -import openstack - -def create(): - ''' Create a set of Openstack resources ''' - pass - -def run(): - ''' Start a set of Openstack virtual machines - if they are not already running. - ''' - pass - -def stop(): - ''' Stop a set of Openstack virtual machines - if they are running. - ''' - pass - -def destroy(): - ''' Tear down the set of Openstack resources - produced by the create action - ''' - pass - -def status(): - ''' Print a status report on the OpenStack - virtual machines created by the create action. - ''' - pass - - -### You should not modify anything below this line ### -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('operation', - help='One of "create", "run", "stop", "destroy", or "status"') - args = parser.parse_args() - operation = args.operation - - operations = { - 'create' : create, - 'run' : run, - 'stop' : stop, - 'destroy' : destroy, - 'status' : status - } - - action = operations.get(operation, lambda: print('{}: no such operation'.format(operation))) - action() diff --git a/assignment2/assignment.py b/assignment2/assignment.py new file mode 100644 index 0000000..85b26ec --- /dev/null +++ b/assignment2/assignment.py @@ -0,0 +1,296 @@ +# Adapted from examples on the openstack github https://github.com/openstack/openstacksdk/tree/master/examples/compute + +# + +from configparser import SectionProxy +from unicodedata import name +import constant +import argparse +import openstack + +conn = openstack.connect(cloud_name='openstack', region_name='nz-por-1') + +# checking for existing networks +def getNetwork(): + network = conn.network.find_network(constant.NETWORK) + return network + +def getSubnet(): + subnet = conn.network.find_subnet(constant.SUBNET) + return subnet + +def getRouter(): + router = conn.network.find_router(constant.ROUTERNAME) + return router + +def get_floating_ip(): + ''' Get a floating IP address from the pool + ''' + floating_ip = conn.network.create_ip(floating_network_id=conn.network.find_network("public-net").id) + return floating_ip + +def create_network(): + print("Checking network status...") + + # define network variables + network = getNetwork() + subnet = getSubnet() + router = getRouter() + + # check for network and create if non existing + if (network is None): + network = conn.network.create_network( + name=constant.NETWORK + ) + print("Created network with name " + constant.NETWORK) + + # check for subnet and create if non existing + if (subnet is None): + subnet = conn.network.create_subnet( + name=constant.SUBNET, + network_id=network.id, + ip_version='4', + cidr=constant.CIDR, + gateway_ip=constant.GATEWAY_IP + ) + print("Created subnet with name " + constant.SUBNET) + + # Check for router and create if non existing + if (router is None): + try: + router = conn.network.create_router( + name="westcl4-net", + external_gateway_info={"network_id": conn.network.find_network("public-net").id}) + print("Created router with attributes: ") + except: + print("Router creation failed") + router = conn.network.add_interface_to_router( + router, + subnet_id=subnet.id) + print(router) + else: + print("Router already exists") + + print(floating_ip) + # Check for floating IP and create if non existing + if (floating_ip is None): + floating_ip = conn.network.create_ip( + floating_network_id=conn.network.find_network("public-net").id) + print("Created floating IP with attributes: ") + print(floating_ip) + +def get_current_servers(): + servers = { + f'westcl4-web': conn.compute.find_server(f'westcl4-web', ignore_missing=True), + f'westcl4-app': conn.compute.find_server(f'westcl4-app', ignore_missing=True), + f'westcl4-db': conn.compute.find_server(f'westcl4-db', ignore_missing=True) + } + return servers + +# checking for existing compute +def get_app(): + app = conn.compute.get_server('westcl4-app') + return app + +def get_web(): + web = conn.compute.get_server(constant.WEB_NAME) + return web + +def get_db(): + db = conn.compute.get_server(constant.DB_NAME) + return db + + +def create_compute(): + print("Checking compute status...") + print("Note: Each server instance will take a few minutes to create.") + # define compute variables + app = get_app() + web = get_web() + db = get_db() + + public = conn.network.find_network(constant.PUBLIC_NET).id + + + # check for app server and create if non existing + if (app is None): + def create_app(): + print("Creating app server with attributes: ") + app = conn.compute.create_server( + name=constant.APP_NAME, + image_id=conn.compute.find_image(constant.IMAGE).id, + flavor_id=conn.compute.find_flavor(constant.FLAVOUR).id, + networks=[ + {"uuid": conn.network.find_network(constant.NETWORK).id}], + ) + app = conn.compute.wait_for_server(app) + conn.compute.add_security_group_to_server(app, constant.SECURITY_GROUP) + print(app) + create_app() + + # check for web server and create if non existing + if (web is None): + def create_web(): + print("Creating web server with attributes: ") + web = conn.compute.create_server( + name=constant.WEB_NAME, + image_id=conn.compute.find_image(constant.IMAGE).id, + flavor_id=conn.compute.find_flavor(constant.FLAVOUR).id, + networks=[ + {"uuid": conn.network.find_network(constant.NETWORK).id}] + ) + web = conn.compute.wait_for_server(web) + conn.compute.add_security_group_to_server(app, constant.SECURITY_GROUP) + ip = conn.network.create_ip(floating_network_id=public) + conn.compute.add_floating_ip_to_server(app, ip.floating_ip_address) + print(web) + create_web() + + # check for db server and create if non existing + if (db is None): + def create_db(): + print("Creating db server with attributes: ") + db = conn.compute.create_server( + name=constant.DB_NAME, + image_id=conn.compute.find_image(constant.IMAGE).id, + flavor_id=conn.compute.find_flavor(constant.FLAVOUR).id, + networks=[ + {"uuid": conn.network.find_network(constant.NETWORK).id}] + ) + db = conn.compute.wait_for_server(db) + conn.compute.add_security_group_to_server(app, constant.SECURITY_GROUP) + print(db) + create_db() + return + + +def run_compute(): + ''' Start the compute resources created by the create action ''' + print("Starting compute resources...") + + #create array and populate with servers + servers = get_current_servers() + for server_name, server in servers.items(): + if(server is not None): + res = conn.compute.get_server(server.id) + if(res.status == "SHUTOFF"): + print("Starting server: {} ".format(server_name)) + conn.compute.start_server(server.id) + else: + print("Server already running: {} ".format(server_name)) + else: + print("Server unavailable: {} ".format(server_name)) + +def stop_compute(): + ''' Stop the compute resources created by the create action ''' + print("Stopping compute resources...") + + servers = get_current_servers() + for server_name, server in servers.items(): + if(server is not None): + res = conn.compute.get_server(server.id) + if(res.status == "ACTIVE"): + print("Stopping server: {} ".format(server_name)) + conn.compute.stop_server(server.id) + else: + print("Server already stopped: {} ".format(server_name)) + else: + print("Server unavailable: {} ".format(server_name)) + +def get_status(): + #get server status and print to terminal + servers = get_current_servers() + for server_name, server in servers.items(): + if(server is not None): + res = conn.compute.get_server(server.id) + print("Server: {} Status: {} ".format(server_name, res.status)) + else: + print("Server unavailable: {} ".format(server_name)) + pass + +def tear_down(): + #delete servers and networks + print("Deleting compute resources...") + servers = get_current_servers() + for server_name, server in servers.items(): + if(server is not None): + print("Deleting server: {} ".format(server_name)) + conn.compute.delete_server(server.id) + else: + print("Server unavailable: {} ".format(server_name)) + + print("Deleting network resources...") + # define network variables + network = getNetwork() + subnet = getSubnet() + router = getRouter() + ports = None + + # delete router + if (router is not None): + print("Deleting router...") + conn.network.remove_interface_from_router(router, subnet.id, ports.id) + conn.network.delete_router(router.id) + else: + print("Router unavailable.") + + +def create(): + ''' Create a set of Openstack resources ''' + print("Creating resources...") + create_network() + create_compute() + pass + + +def run(): + ''' Start a set of Openstack virtual machines + if they are not already running. + ''' + run_compute() + pass + + +def stop(): + ''' Stop a set of Openstack virtual machines + if they are running. + ''' + stop_compute() + pass + + +def destroy(): + ''' Tear down the set of Openstack resources + produced by the create action + ''' + tear_down() + pass + + +def status(): + ''' Print a status report on the OpenStack + virtual machines created by the create action. + ''' + get_status() + pass + + +### You should not modify anything below this line ### +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('operation', + help='One of "create", "run", "stop", "destroy", or "status"') + args = parser.parse_args() + operation = args.operation + + operations = { + 'create': create, + 'run': run, + 'stop': stop, + 'destroy': destroy, + 'status': status + } + + action = operations.get(operation, lambda: print( + '{}: no such operation'.format(operation))) + action() diff --git a/assignment2/bin/activate b/assignment2/bin/activate new file mode 100644 index 0000000..02d308f --- /dev/null +++ b/assignment2/bin/activate @@ -0,0 +1,84 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + + +if [ "${BASH_SOURCE-}" = "$0" ]; then + echo "You must source this script: \$ source $0" >&2 + exit 33 +fi + +deactivate () { + unset -f pydoc >/dev/null 2>&1 + + # reset old environment variables + # ! [ -z ${VAR+_} ] returns true if VAR is declared at all + if ! [ -z "${_OLD_VIRTUAL_PATH:+_}" ] ; then + PATH="$_OLD_VIRTUAL_PATH" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then + PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null + fi + + if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then + PS1="$_OLD_VIRTUAL_PS1" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "${1-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV='/home/conor/virt_assignment/virt-openstack-assignment/assignment2' +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +if ! [ -z "${PYTHONHOME+_}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1-}" + if [ "x" != x ] ; then + PS1="${PS1-}" + else + PS1="(`basename \"$VIRTUAL_ENV\"`) ${PS1-}" + fi + export PS1 +fi + +# Make sure to unalias pydoc if it's already there +alias pydoc 2>/dev/null >/dev/null && unalias pydoc || true + +pydoc () { + python -m pydoc "$@" +} + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null +fi diff --git a/assignment2/bin/activate.csh b/assignment2/bin/activate.csh new file mode 100644 index 0000000..e9a0d6d --- /dev/null +++ b/assignment2/bin/activate.csh @@ -0,0 +1,55 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi . + +set newline='\ +' + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH:q" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT:q" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV '/home/conor/virt_assignment/virt-openstack-assignment/assignment2' + +set _OLD_VIRTUAL_PATH="$PATH:q" +setenv PATH "$VIRTUAL_ENV:q/bin:$PATH:q" + + + +if ('' != "") then + set env_name = '' +else + set env_name = '('"$VIRTUAL_ENV:t:q"') ' +endif + +if ( $?VIRTUAL_ENV_DISABLE_PROMPT ) then + if ( $VIRTUAL_ENV_DISABLE_PROMPT == "" ) then + set do_prompt = "1" + else + set do_prompt = "0" + endif +else + set do_prompt = "1" +endif + +if ( $do_prompt == "1" ) then + # Could be in a non-interactive environment, + # in which case, $prompt is undefined and we wouldn't + # care about the prompt anyway. + if ( $?prompt ) then + set _OLD_VIRTUAL_PROMPT="$prompt:q" + if ( "$prompt:q" =~ *"$newline:q"* ) then + : + else + set prompt = "$env_name:q$prompt:q" + endif + endif +endif + +unset env_name +unset do_prompt + +alias pydoc python -m pydoc + +rehash diff --git a/assignment2/bin/activate.fish b/assignment2/bin/activate.fish new file mode 100644 index 0000000..25e3447 --- /dev/null +++ b/assignment2/bin/activate.fish @@ -0,0 +1,100 @@ +# This file must be used using `source bin/activate.fish` *within a running fish ( http://fishshell.com ) session*. +# Do not run it directly. + +function _bashify_path -d "Converts a fish path to something bash can recognize" + set fishy_path $argv + set bashy_path $fishy_path[1] + for path_part in $fishy_path[2..-1] + set bashy_path "$bashy_path:$path_part" + end + echo $bashy_path +end + +function _fishify_path -d "Converts a bash path to something fish can recognize" + echo $argv | tr ':' '\n' +end + +function deactivate -d 'Exit virtualenv mode and return to the normal environment.' + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + # https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling + if test (echo $FISH_VERSION | head -c 1) -lt 3 + set -gx PATH (_fishify_path "$_OLD_VIRTUAL_PATH") + else + set -gx PATH "$_OLD_VIRTUAL_PATH" + end + set -e _OLD_VIRTUAL_PATH + end + + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME "$_OLD_VIRTUAL_PYTHONHOME" + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + and functions -q _old_fish_prompt + # Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`. + set -l fish_function_path + + # Erase virtualenv's `fish_prompt` and restore the original. + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + end + + set -e VIRTUAL_ENV + + if test "$argv[1]" != 'nondestructive' + # Self-destruct! + functions -e pydoc + functions -e deactivate + functions -e _bashify_path + functions -e _fishify_path + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV '/home/conor/virt_assignment/virt-openstack-assignment/assignment2' + +# https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling +if test (echo $FISH_VERSION | head -c 1) -lt 3 + set -gx _OLD_VIRTUAL_PATH (_bashify_path $PATH) +else + set -gx _OLD_VIRTUAL_PATH "$PATH" +end +set -gx PATH "$VIRTUAL_ENV"'/bin' $PATH + +# Unset `$PYTHONHOME` if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +function pydoc + python -m pydoc $argv +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # Copy the current `fish_prompt` function as `_old_fish_prompt`. + functions -c fish_prompt _old_fish_prompt + + function fish_prompt + # Run the user's prompt first; it might depend on (pipe)status. + set -l prompt (_old_fish_prompt) + + # Prompt override provided? + # If not, just prepend the environment name. + if test -n '' + printf '%s%s' '' (set_color normal) + else + printf '%s(%s) ' (set_color normal) (basename "$VIRTUAL_ENV") + end + + string join -- \n $prompt # handle multi-line prompts + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" +end diff --git a/assignment2/bin/activate.ps1 b/assignment2/bin/activate.ps1 new file mode 100644 index 0000000..95504d3 --- /dev/null +++ b/assignment2/bin/activate.ps1 @@ -0,0 +1,60 @@ +$script:THIS_PATH = $myinvocation.mycommand.path +$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent + +function global:deactivate([switch] $NonDestructive) { + if (Test-Path variable:_OLD_VIRTUAL_PATH) { + $env:PATH = $variable:_OLD_VIRTUAL_PATH + Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global + } + + if (Test-Path function:_old_virtual_prompt) { + $function:prompt = $function:_old_virtual_prompt + Remove-Item function:\_old_virtual_prompt + } + + if ($env:VIRTUAL_ENV) { + Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue + } + + if (!$NonDestructive) { + # Self destruct! + Remove-Item function:deactivate + Remove-Item function:pydoc + } +} + +function global:pydoc { + python -m pydoc $args +} + +# unset irrelevant variables +deactivate -nondestructive + +$VIRTUAL_ENV = $BASE_DIR +$env:VIRTUAL_ENV = $VIRTUAL_ENV + +New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH + +$env:PATH = "$env:VIRTUAL_ENV/bin:" + $env:PATH +if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) { + function global:_old_virtual_prompt { + "" + } + $function:_old_virtual_prompt = $function:prompt + + if ("" -ne "") { + function global:prompt { + # Add the custom prefix to the existing prompt + $previous_prompt_value = & $function:_old_virtual_prompt + ("" + $previous_prompt_value) + } + } + else { + function global:prompt { + # Add a prefix to the current prompt, but don't discard it. + $previous_prompt_value = & $function:_old_virtual_prompt + $new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) " + ($new_prompt_value + $previous_prompt_value) + } + } +} diff --git a/assignment2/bin/activate.xsh b/assignment2/bin/activate.xsh new file mode 100644 index 0000000..9f2110c --- /dev/null +++ b/assignment2/bin/activate.xsh @@ -0,0 +1,46 @@ +"""Xonsh activate script for virtualenv""" +from xonsh.tools import get_sep as _get_sep + +def _deactivate(args): + if "pydoc" in aliases: + del aliases["pydoc"] + + if ${...}.get("_OLD_VIRTUAL_PATH", ""): + $PATH = $_OLD_VIRTUAL_PATH + del $_OLD_VIRTUAL_PATH + + if ${...}.get("_OLD_VIRTUAL_PYTHONHOME", ""): + $PYTHONHOME = $_OLD_VIRTUAL_PYTHONHOME + del $_OLD_VIRTUAL_PYTHONHOME + + if "VIRTUAL_ENV" in ${...}: + del $VIRTUAL_ENV + + if "VIRTUAL_ENV_PROMPT" in ${...}: + del $VIRTUAL_ENV_PROMPT + + if "nondestructive" not in args: + # Self destruct! + del aliases["deactivate"] + + +# unset irrelevant variables +_deactivate(["nondestructive"]) +aliases["deactivate"] = _deactivate + +$VIRTUAL_ENV = r"/home/conor/virt_assignment/virt-openstack-assignment/assignment2" + +$_OLD_VIRTUAL_PATH = $PATH +$PATH = $PATH[:] +$PATH.add($VIRTUAL_ENV + _get_sep() + "bin", front=True, replace=True) + +if ${...}.get("PYTHONHOME", ""): + # unset PYTHONHOME if set + $_OLD_VIRTUAL_PYTHONHOME = $PYTHONHOME + del $PYTHONHOME + +$VIRTUAL_ENV_PROMPT = "" +if not $VIRTUAL_ENV_PROMPT: + del $VIRTUAL_ENV_PROMPT + +aliases["pydoc"] = ["python", "-m", "pydoc"] diff --git a/assignment2/bin/activate_this.py b/assignment2/bin/activate_this.py new file mode 100644 index 0000000..4479986 --- /dev/null +++ b/assignment2/bin/activate_this.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +"""Activate virtualenv for current interpreter: + +Use exec(open(this_file).read(), {'__file__': this_file}). + +This can be used when you must use an existing Python interpreter, not the virtualenv bin/python. +""" +import os +import site +import sys + +try: + abs_file = os.path.abspath(__file__) +except NameError: + raise AssertionError("You must use exec(open(this_file).read(), {'__file__': this_file}))") + +bin_dir = os.path.dirname(abs_file) +base = bin_dir[: -len("bin") - 1] # strip away the bin part from the __file__, plus the path separator + +# prepend bin to PATH (this file is inside the bin directory) +os.environ["PATH"] = os.pathsep.join([bin_dir] + os.environ.get("PATH", "").split(os.pathsep)) +os.environ["VIRTUAL_ENV"] = base # virtual env is right above bin directory + +# add the virtual environments libraries to the host python import mechanism +prev_length = len(sys.path) +for lib in "../lib/python3.8/site-packages".split(os.pathsep): + path = os.path.realpath(os.path.join(bin_dir, lib)) + site.addsitedir(path.decode("utf-8") if "" else path) +sys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length] + +sys.real_prefix = sys.prefix +sys.prefix = base diff --git a/assignment2/bin/ceilometer b/assignment2/bin/ceilometer new file mode 100755 index 0000000..5173282 --- /dev/null +++ b/assignment2/bin/ceilometer @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from ceilometerclient.shell import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/cinder b/assignment2/bin/cinder new file mode 100755 index 0000000..140735f --- /dev/null +++ b/assignment2/bin/cinder @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from cinderclient.shell import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/convert-json b/assignment2/bin/convert-json new file mode 100755 index 0000000..ef30af1 --- /dev/null +++ b/assignment2/bin/convert-json @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from oslo_log.cmds.convert_json import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/easy_install b/assignment2/bin/easy_install new file mode 100755 index 0000000..6476457 --- /dev/null +++ b/assignment2/bin/easy_install @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from setuptools.command.easy_install import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/easy_install-3.8 b/assignment2/bin/easy_install-3.8 new file mode 100755 index 0000000..6476457 --- /dev/null +++ b/assignment2/bin/easy_install-3.8 @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from setuptools.command.easy_install import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/easy_install3 b/assignment2/bin/easy_install3 new file mode 100755 index 0000000..6476457 --- /dev/null +++ b/assignment2/bin/easy_install3 @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from setuptools.command.easy_install import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/heat b/assignment2/bin/heat new file mode 100755 index 0000000..218bdc4 --- /dev/null +++ b/assignment2/bin/heat @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from heatclient.shell import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/jp.py b/assignment2/bin/jp.py new file mode 100755 index 0000000..bdde9a9 --- /dev/null +++ b/assignment2/bin/jp.py @@ -0,0 +1,54 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python + +import sys +import json +import argparse +from pprint import pformat + +import jmespath +from jmespath import exceptions + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('expression') + parser.add_argument('-f', '--filename', + help=('The filename containing the input data. ' + 'If a filename is not given then data is ' + 'read from stdin.')) + parser.add_argument('--ast', action='store_true', + help=('Pretty print the AST, do not search the data.')) + args = parser.parse_args() + expression = args.expression + if args.ast: + # Only print the AST + expression = jmespath.compile(args.expression) + sys.stdout.write(pformat(expression.parsed)) + sys.stdout.write('\n') + return 0 + if args.filename: + with open(args.filename, 'r') as f: + data = json.load(f) + else: + data = sys.stdin.read() + data = json.loads(data) + try: + sys.stdout.write(json.dumps( + jmespath.search(expression, data), indent=4, ensure_ascii=False)) + sys.stdout.write('\n') + except exceptions.ArityError as e: + sys.stderr.write("invalid-arity: %s\n" % e) + return 1 + except exceptions.JMESPathTypeError as e: + sys.stderr.write("invalid-type: %s\n" % e) + return 1 + except exceptions.UnknownFunctionError as e: + sys.stderr.write("unknown-function: %s\n" % e) + return 1 + except exceptions.ParseError as e: + sys.stderr.write("syntax-error: %s\n" % e) + return 1 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/assignment2/bin/jsondiff b/assignment2/bin/jsondiff new file mode 100755 index 0000000..865b08b --- /dev/null +++ b/assignment2/bin/jsondiff @@ -0,0 +1,39 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- + +from __future__ import print_function + +import sys +import json +import jsonpatch +import argparse + + +parser = argparse.ArgumentParser(description='Diff two JSON files') +parser.add_argument('FILE1', type=argparse.FileType('r')) +parser.add_argument('FILE2', type=argparse.FileType('r')) +parser.add_argument('--indent', type=int, default=None, + help='Indent output by n spaces') +parser.add_argument('-v', '--version', action='version', + version='%(prog)s ' + jsonpatch.__version__) + + +def main(): + try: + diff_files() + except KeyboardInterrupt: + sys.exit(1) + + +def diff_files(): + """ Diffs two JSON files and prints a patch """ + args = parser.parse_args() + doc1 = json.load(args.FILE1) + doc2 = json.load(args.FILE2) + patch = jsonpatch.make_patch(doc1, doc2) + if patch.patch: + print(json.dumps(patch.patch, indent=args.indent)) + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/assignment2/bin/jsonpatch b/assignment2/bin/jsonpatch new file mode 100755 index 0000000..5f99ca8 --- /dev/null +++ b/assignment2/bin/jsonpatch @@ -0,0 +1,107 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- + +import sys +import os.path +import json +import jsonpatch +import tempfile +import argparse + + +parser = argparse.ArgumentParser( + description='Apply a JSON patch on a JSON file') +parser.add_argument('ORIGINAL', type=argparse.FileType('r'), + help='Original file') +parser.add_argument('PATCH', type=argparse.FileType('r'), + nargs='?', default=sys.stdin, + help='Patch file (read from stdin if omitted)') +parser.add_argument('--indent', type=int, default=None, + help='Indent output by n spaces') +parser.add_argument('-b', '--backup', action='store_true', + help='Back up ORIGINAL if modifying in-place') +parser.add_argument('-i', '--in-place', action='store_true', + help='Modify ORIGINAL in-place instead of to stdout') +parser.add_argument('-v', '--version', action='version', + version='%(prog)s ' + jsonpatch.__version__) +parser.add_argument('-u', '--preserve-unicode', action='store_true', + help='Output Unicode character as-is without using Code Point') + +def main(): + try: + patch_files() + except KeyboardInterrupt: + sys.exit(1) + + +def patch_files(): + """ Diffs two JSON files and prints a patch """ + args = parser.parse_args() + doc = json.load(args.ORIGINAL) + patch = json.load(args.PATCH) + result = jsonpatch.apply_patch(doc, patch) + + if args.in_place: + dirname = os.path.abspath(os.path.dirname(args.ORIGINAL.name)) + + try: + # Attempt to replace the file atomically. We do this by + # creating a temporary file in the same directory as the + # original file so we can atomically move the new file over + # the original later. (This is done in the same directory + # because atomic renames do not work across mount points.) + + fd, pathname = tempfile.mkstemp(dir=dirname) + fp = os.fdopen(fd, 'w') + atomic = True + + except OSError: + # We failed to create the temporary file for an atomic + # replace, so fall back to non-atomic mode by backing up + # the original (if desired) and writing a new file. + + if args.backup: + os.rename(args.ORIGINAL.name, args.ORIGINAL.name + '.orig') + fp = open(args.ORIGINAL.name, 'w') + atomic = False + + else: + # Since we're not replacing the original file in-place, write + # the modified JSON to stdout instead. + + fp = sys.stdout + + # By this point we have some sort of file object we can write the + # modified JSON to. + + json.dump(result, fp, indent=args.indent, ensure_ascii=not(args.preserve_unicode)) + fp.write('\n') + + if args.in_place: + # Close the new file. If we aren't replacing atomically, this + # is our last step, since everything else is already in place. + + fp.close() + + if atomic: + try: + # Complete the atomic replace by linking the original + # to a backup (if desired), fixing up the permissions + # on the temporary file, and moving it into place. + + if args.backup: + os.link(args.ORIGINAL.name, args.ORIGINAL.name + '.orig') + os.chmod(pathname, os.stat(args.ORIGINAL.name).st_mode) + os.rename(pathname, args.ORIGINAL.name) + + except OSError: + # In the event we could not actually do the atomic + # replace, unlink the original to move it out of the + # way and finally move the temporary file into place. + + os.unlink(args.ORIGINAL.name) + os.rename(pathname, args.ORIGINAL.name) + + +if __name__ == "__main__": + main() diff --git a/assignment2/bin/jsonpointer b/assignment2/bin/jsonpointer new file mode 100755 index 0000000..be04112 --- /dev/null +++ b/assignment2/bin/jsonpointer @@ -0,0 +1,69 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- + +from __future__ import print_function + +import sys +import os.path +import json +import jsonpointer +import argparse + + +parser = argparse.ArgumentParser( + description='Resolve a JSON pointer on JSON files') + +# Accept pointer as argument or as file +ptr_group = parser.add_mutually_exclusive_group(required=True) + +ptr_group.add_argument('-f', '--pointer-file', type=argparse.FileType('r'), + nargs='?', + help='File containing a JSON pointer expression') + +ptr_group.add_argument('POINTER', type=str, nargs='?', + help='A JSON pointer expression') + +parser.add_argument('FILE', type=argparse.FileType('r'), nargs='+', + help='Files for which the pointer should be resolved') +parser.add_argument('--indent', type=int, default=None, + help='Indent output by n spaces') +parser.add_argument('-v', '--version', action='version', + version='%(prog)s ' + jsonpointer.__version__) + + +def main(): + try: + resolve_files() + except KeyboardInterrupt: + sys.exit(1) + + +def parse_pointer(args): + if args.POINTER: + ptr = args.POINTER + elif args.pointer_file: + ptr = args.pointer_file.read().strip() + else: + parser.print_usage() + sys.exit(1) + + return ptr + + +def resolve_files(): + """ Resolve a JSON pointer on JSON files """ + args = parser.parse_args() + + ptr = parse_pointer(args) + + for f in args.FILE: + doc = json.load(f) + try: + result = jsonpointer.resolve_pointer(doc, ptr) + print(json.dumps(result, indent=args.indent)) + except jsonpointer.JsonPointerException as e: + print('Could not resolve pointer: %s' % str(e), file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/assignment2/bin/netaddr b/assignment2/bin/netaddr new file mode 100755 index 0000000..5f857fb --- /dev/null +++ b/assignment2/bin/netaddr @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from netaddr.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/neutron b/assignment2/bin/neutron new file mode 100755 index 0000000..c3fa122 --- /dev/null +++ b/assignment2/bin/neutron @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from neutronclient.shell import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/normalizer b/assignment2/bin/normalizer new file mode 100755 index 0000000..22e4279 --- /dev/null +++ b/assignment2/bin/normalizer @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from charset_normalizer.cli.normalizer import cli_detect +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(cli_detect()) diff --git a/assignment2/bin/nova b/assignment2/bin/nova new file mode 100755 index 0000000..7f7999f --- /dev/null +++ b/assignment2/bin/nova @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from novaclient.shell import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/openstack b/assignment2/bin/openstack new file mode 100755 index 0000000..ff18329 --- /dev/null +++ b/assignment2/bin/openstack @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from openstackclient.shell import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/openstack-inventory b/assignment2/bin/openstack-inventory new file mode 100755 index 0000000..7cf1acf --- /dev/null +++ b/assignment2/bin/openstack-inventory @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from openstack.cloud.cmd.inventory import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/oslo-config-generator b/assignment2/bin/oslo-config-generator new file mode 100755 index 0000000..11f04bf --- /dev/null +++ b/assignment2/bin/oslo-config-generator @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from oslo_config.generator import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/oslo-config-validator b/assignment2/bin/oslo-config-validator new file mode 100755 index 0000000..1d93cfa --- /dev/null +++ b/assignment2/bin/oslo-config-validator @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from oslo_config.validator import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/pbr b/assignment2/bin/pbr new file mode 100755 index 0000000..926a7cb --- /dev/null +++ b/assignment2/bin/pbr @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from pbr.cmd.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/pip b/assignment2/bin/pip new file mode 100755 index 0000000..708e064 --- /dev/null +++ b/assignment2/bin/pip @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/pip-3.8 b/assignment2/bin/pip-3.8 new file mode 100755 index 0000000..708e064 --- /dev/null +++ b/assignment2/bin/pip-3.8 @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/pip3 b/assignment2/bin/pip3 new file mode 100755 index 0000000..708e064 --- /dev/null +++ b/assignment2/bin/pip3 @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/pip3.8 b/assignment2/bin/pip3.8 new file mode 100755 index 0000000..708e064 --- /dev/null +++ b/assignment2/bin/pip3.8 @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/pybabel b/assignment2/bin/pybabel new file mode 100755 index 0000000..5f465f6 --- /dev/null +++ b/assignment2/bin/pybabel @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from babel.messages.frontend import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/python b/assignment2/bin/python new file mode 120000 index 0000000..ae65fda --- /dev/null +++ b/assignment2/bin/python @@ -0,0 +1 @@ +/usr/bin/python3 \ No newline at end of file diff --git a/assignment2/bin/python3 b/assignment2/bin/python3 new file mode 120000 index 0000000..d8654aa --- /dev/null +++ b/assignment2/bin/python3 @@ -0,0 +1 @@ +python \ No newline at end of file diff --git a/assignment2/bin/python3.8 b/assignment2/bin/python3.8 new file mode 120000 index 0000000..d8654aa --- /dev/null +++ b/assignment2/bin/python3.8 @@ -0,0 +1 @@ +python \ No newline at end of file diff --git a/assignment2/bin/swift b/assignment2/bin/swift new file mode 100755 index 0000000..a1faf05 --- /dev/null +++ b/assignment2/bin/swift @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from swiftclient.shell import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/wheel b/assignment2/bin/wheel new file mode 100755 index 0000000..ce30962 --- /dev/null +++ b/assignment2/bin/wheel @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from wheel.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/wheel-3.8 b/assignment2/bin/wheel-3.8 new file mode 100755 index 0000000..ce30962 --- /dev/null +++ b/assignment2/bin/wheel-3.8 @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from wheel.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/bin/wheel3 b/assignment2/bin/wheel3 new file mode 100755 index 0000000..ce30962 --- /dev/null +++ b/assignment2/bin/wheel3 @@ -0,0 +1,8 @@ +#!/home/conor/virt_assignment/virt-openstack-assignment/assignment2/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from wheel.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/assignment2/clouds.yaml b/assignment2/clouds.yaml new file mode 100644 index 0000000..9eb21c5 --- /dev/null +++ b/assignment2/clouds.yaml @@ -0,0 +1,19 @@ +# This is a clouds.yaml file, which can be used by OpenStack tools as a source +# of configuration on how to connect to a cloud. If this is your only cloud, +# just put this file in ~/.config/openstack/clouds.yaml and tools like +# python-openstackclient will just work with no further config. (You will need +# to add your password to the auth section) +# If you have more than one cloud account, add the cloud entry to the clouds +# section of your existing file and you can refer to them by name with +# OS_CLOUD=catalystcloud or --os-cloud=catalystcloud +clouds: + catalystcloud: + auth: + auth_url: https://api.nz-por-1.catalystcloud.io:5000 + username: "WESTCL4@student.op.ac.nz" + project_id: 8e0cb4b58cee49289ea45cd97ea6ef49 + project_name: "tom-clark" + user_domain_name: "Default" + region_name: "nz-por-1" + interface: "public" + identity_api_version: 3 \ No newline at end of file diff --git a/assignment2/constant.py b/assignment2/constant.py new file mode 100644 index 0000000..01cfc9a --- /dev/null +++ b/assignment2/constant.py @@ -0,0 +1,28 @@ +# file containing constants for the assignment project. +import openstack + +# network constants +CONN = openstack.connect(cloud_name='openstack', region_name='nz-por-1') + +USER = "westcl4" +NETWORK = "westcl4_net" +SUBNET = "westcl4_subnet" +VPC = "westcl4_vpc" +NETWORK = "westcl4_net" +CIDR = "192.168.50.0/24" +GATEWAY_IP = "192.168.50.1" +ROUTERNAME = "westcl4-rtr" + + +# compute constants +IMAGE = "ubuntu-minimal-22.04-x86_64" +FLAVOUR = "c1.c1r1" +WEB_NAME = "westcl4-web" +APP_NAME = "westcl4-app" +DB_NAME = "westcl4-db" +SECURITY_GROUP = "default" +PUBLIC = "public-net" + +# run constants + +# stop constants \ No newline at end of file diff --git a/assignment2/pyvenv.cfg b/assignment2/pyvenv.cfg new file mode 100644 index 0000000..7ba78fa --- /dev/null +++ b/assignment2/pyvenv.cfg @@ -0,0 +1,8 @@ +home = /usr +implementation = CPython +version_info = 3.8.10.final.0 +virtualenv = 20.0.17 +include-system-site-packages = false +base-prefix = /usr +base-exec-prefix = /usr +base-executable = /usr/bin/python3 diff --git a/assignment2/share/man/man1/swift.1 b/assignment2/share/man/man1/swift.1 new file mode 100644 index 0000000..00e1440 --- /dev/null +++ b/assignment2/share/man/man1/swift.1 @@ -0,0 +1,214 @@ +.\" +.\" Author: Joao Marcelo Martins or +.\" Copyright (c) 2010-2011 OpenStack Foundation. +.\" +.\" Licensed under the Apache License, Version 2.0 (the "License"); +.\" you may not use this file except in compliance with the License. +.\" You may obtain a copy of the License at +.\" +.\" http://www.apache.org/licenses/LICENSE-2.0 +.\" +.\" Unless required by applicable law or agreed to in writing, software +.\" distributed under the License is distributed on an "AS IS" BASIS, +.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +.\" implied. +.\" See the License for the specific language governing permissions and +.\" limitations under the License. +.\" +.TH swift 1 "8/26/2011" "Linux" "OpenStack Swift" + +.SH NAME +.LP +.B swift +\- OpenStack Swift client tool + +.SH SYNOPSIS +.LP +.B swift +[options] [args] + +.SH DESCRIPTION +.PP +The \fBswift\fR tool is a command line utility for communicating with +an OpenStack Object Storage (Swift) environment. It allows one to perform +several types of operations. + +.SH COMMANDS +.PP + +\fBstat\fR [\fIcommand-options\fR] [\fIcontainer\fR] [\fIobject\fR] +.RS 4 +Displays information for the account, container, or object depending on the args given (if any). +In verbose mode, the Storage URL and the authentication token are displayed +as well. Option \-\-lh reports sizes in human readable format similar to ls \-lh. +.RE + +\fBlist\fR [\fIcommand-options\fR] [\fIcontainer\fR] +.RS 4 +Lists the containers for the account or the objects for a container. +The \-p or \-\-prefix is an option that will only list items beginning +with that prefix. The \-d or \-\-delimiter is option +(for container listings only) that will roll up items with the given +delimiter (see OpenStack Swift general documentation for what this means). + +The \-l or \-\-long and \-\-lh options provide more detail, similar to ls \-l and ls \-lh, the latter +providing sizes in human readable format (eg 3K, 12M, etc). These latter 2 switches +use more overhead to get those details, which is directly proportional to the number +of container or objects being listed. With the \-t or \-\-total option they only report totals. +.RE + +\fBupload\fR [\fIcommand-options\fR] container file_or_directory [\fIfile_or_directory\fR] [...] +.RS 4 +Uploads to the given container the files and directories specified by the +remaining args. The \-c or \-\-changed is an option that will only upload files +that have changed since the last upload. The \-\-object\-name is +an option that will upload file and name object to or upload dir +and use as object prefix. If the file name is "-", reads the +content from standard input. In this case, \-\-object\-name is required and no +other files may be given. The \-S or \-\-segment\-size and +\-\-leave\-segments and others are options as well (see swift upload \-\-help +for more). +.RE + +\fBpost\fR [\fIcommand-options\fR] [\fIcontainer\fR] [\fIobject\fR] +.RS 4 +Updates meta information for the account, container, or object depending +on the args given. If the container is not found, it will be created +automatically; but this is not true for accounts and objects. Containers +also allow the \-r (or \-\-read\-acl) and \-w (or \-\-write\-acl) options. The \-m +or \-\-meta option is allowed on all and used to define the user meta data +items to set in the form Name:Value. This option can be repeated. +For more details and options see swift post \-\-help. +\fBExample\fR: post \-m Color:Blue \-m Size:Large +.RE + +\fBcopy\fR [\fIcommand-options\fR] \fIcontainer\fR \fIobject\fR +.RS 4 +Copies an object to a new destination or adds user metadata to the object (current +user metadata will be preserved, in contrast with the post command) depending +on the args given. The \-\-destination option sets the destination in the form +/container/object. If not set, the object will be copied onto itself which is useful +for adding metadata. The \-M or \-\-fresh\-metadata option copies the object without +the existing user metadata. The \-m or \-\-meta option is always allowed and is used +to define the user metadata items to set in the form Name:Value (this option +can be repeated). +For more details and options see swift copy \-\-help. +.RE + +\fBdownload\fR [\fIcommand-options\fR] [\fIcontainer\fR] [\fIobject\fR] [\fIobject\fR] [...] +.RS 4 +Downloads everything in the account (with \-\-all), or everything in a +container, or a list of objects depending on the args given. For a single +object download, you may use the \-o [\-\-output] option to +redirect the output to a specific file or if "-" then just redirect to stdout or +with \-\-no-download actually not to write anything to disk. +The \-\-ignore-checksum is an option that turns off checksum validation. +You can specify optional headers with the repeatable cURL-like option +\-H [\-\-header]. For more details and options see swift download \-\-help. +The \-\-ignore\-mtime option ignores the x\-object\-meta\-mtime metadata entry +on the object (if present) and instead creates the downloaded files with +fresh atime and mtime values. +.RE + +\fBdelete\fR [\fIcommand-options\fR] [\fIcontainer\fR] [\fIobject\fR] [\fIobject\fR] [...] +.RS 4 +Deletes everything in the account (with \-\-all), or everything in a container, +or all objects in a container that start with a given string (given by \-\-prefix), +or a list of objects depending on the args given. Segments of manifest objects +will be deleted as well, unless you specify the \-\-leave\-segments option. +For more details and options see swift delete \-\-help. +.RE + +\fBcapabilities\fR [\fIcommand-options\fR] [\fIproxy-url\fR] +.RS 4 +Displays cluster capabilities. If the proxy-url option is not provided the +storage-url retrieved after authentication is used as proxy-url. + +By default, the output includes the list of the activated Swift middlewares as +well as relevant options for each one. Additionally the command displays +relevant options for the Swift core. + +The \-\-json option will print a json representation of the cluster +capabilities. This is typically more suitable for consumption by other +programs, such as jq. + +\fBExample\fR: capabilities https://swift.example.com + capabilities \-\-json +.RE + +\fBtempurl\fR [\fIcommand-option\fR] \fImethod\fR \fItime\fR \fIpath\fR \fIkey\fR +.RS 4 +Generates a temporary URL allowing unauthenticated access to the Swift object +at the given path, using the given HTTP method, for the given time, +using the given TempURL key. + +The time can be specified either as an integer +denoting the amount of seconds the temporary URL is valid, or as an ISO 8601 +timestamp in one of following formats: Complete date: YYYY\-MM\-DD (eg 1997\-07\-16), +complete date plus hours, minutes and seconds: YYYY\-MM\-DDThh:mm:ss +(eg 1997\-07\-16T19:20:30) or complete date plus hours, minutes and seconds with +UTC designator: YYYY\-MM\-DDThh:mm:ssZ (eg 1997\-07\-16T19:20:30Z). Be aware that +if you do not use the latter format, the timestamp is generated using your locale +timezone. If the first format is used, the time part used will equal to 00:00:00. + +With the \-\-prefix\-based option a +prefix-based URL is generated. + +The option \-\-iso8601 provides ISO 8601 UTC timestamps +instead of Unix timestamps inside the generated URL. + +If optional \-\-absolute argument is +provided and the time argument is specified in seconds, the seconds are +interpreted as a Unix timestamp at which the URL +should expire. + +\fBExample\fR: tempurl GET $(date \-d "Jan 1 2016" +%s) +/v1/AUTH_foo/bar_container/quux.md my_secret_tempurl_key \-\-absolute + +.RE + +\fBauth\fR +.RS 4 +Display auth related authentication variables in shell friendly format. +For examples see swift auth \-\-help. +.RE + +.SH OPTIONS +.PD 0 +.IP "--version Show program's version number and exit" +.IP "-h, --help Show this (or any subcommand if after command) help message and exit" +.IP "-s, --snet Use SERVICENET internal network" +.IP "-v, --verbose Print more info" +.IP "-q, --quiet Suppress status output" +.IP "-A AUTH, --auth=AUTH URL for obtaining an auth token " +.IP "-U USER, --user=USER User name for obtaining an auth token" +.IP "-V 1|2, --auth-version=VERSION Authentication protocol version" +.IP "-K KEY, --key=KEY Key for obtaining an auth token" +.IP "--os-storage-url=URL Use this instead of URL returned from auth" +.IP "--os-help Show all OpenStack authentication options" +.PD +.RS 4 +For more options see swift \-\-help and swift \-\-os\-help. +.RE + + +.SH EXAMPLE +.PP +swift \-A https://127.0.0.1:443/auth/v1.0 \-U swiftops:swiftops \-K swiftops stat + +.RS 2 +.PD 0 +.IP " Account: AUTH_43b42dae-dc0b-4a4b-ac55-97de614d6e6e" +.IP "Containers: 1" +.IP " Objects: 1" +.IP " Bytes: 1124" +.IP "Accept-Ranges: bytes" +.IP "X-Trans-Id: txb21186a9eef64ed295a1e95896a0fc72" +.PD +.RE + + +.SH DOCUMENTATION +.LP +More in depth documentation about OpenStack Swift as a whole can be found at +.BI https://docs.openstack.org/swift/latest/ diff --git a/assignment2/tom-clark-openrc.sh b/assignment2/tom-clark-openrc.sh new file mode 100644 index 0000000..bf9b055 --- /dev/null +++ b/assignment2/tom-clark-openrc.sh @@ -0,0 +1,250 @@ +#!/usr/bin/env bash +############### +# Configuration +############### +#------------------------------------------- +# Configuration variables for Catalyst Cloud +#------------------------------------------- +# Set the authentication API and version. +export OS_AUTH_URL=https://api.nz-por-1.catalystcloud.io:5000/v3 +export OS_IDENTITY_API_VERSION=3 +# Set the domain name for authentication. +export OS_USER_DOMAIN_NAME="Default" +export OS_PROJECT_DOMAIN_ID="default" +# Set the user name. +export OS_USERNAME="WESTCL4@student.op.ac.nz" +# Set the project name and id (the name is sufficient if unique, but it is a +# best practice to set the id in case two projects with the same name exist). +export OS_PROJECT_ID=8e0cb4b58cee49289ea45cd97ea6ef49 +export OS_PROJECT_NAME="tom-clark" +# Set the region name. +export OS_REGION_NAME="nz-por-1" +# Blank variables can result in unexpected errors. Unset variables that were +# left empty. +if [[ -z "${OS_USER_DOMAIN_NAME}" ]]; then unset OS_USER_DOMAIN_NAME; fi +if [[ -z "${OS_PROJECT_DOMAIN_ID}" ]]; then unset OS_PROJECT_DOMAIN_ID; fi +if [[ -z "${OS_REGION_NAME}" ]]; then unset OS_REGION_NAME; fi +# As a precaution, unset deprecated OpenStack auth v2.0 variables (in case they +# have been set by other scripts or applications running on the same host). +unset OS_TENANT_ID +unset OS_TENANT_NAME +# Set BASH_SOURCE for ZSH +SCRIPT_SOURCE="${BASH_SOURCE[0]}" +if [[ -z "${SCRIPT_SOURCE}" ]]; then + SCRIPT_SOURCE="${0}" +fi +########### +# Functions +########### +# Style text output as sucess message (green) +success () { + echo -e "\e[32m${1}\e[0m" +} +# Style text output as warning message (yellow) +warning () { + echo -e "\e[33m${1}\e[0m" +} +# Style text output as error message (red) +error () { + echo -e "\e[31m${1}\e[0m" +} +# Style text output as error message (majenta) +debug () { + echo -e "\e[35m${1}\e[0m" +} +################################################## +# Parses token HTTP Response and sets it in +# environment as OS_TOKEN +# Globals: +# OS_TOKEN +# Arguments: +# String containing raw HTTP Response Text +################################################## +parse_token_from_response () { + OS_TOKEN=$(echo "${1}" \ + | grep -i X-Subject-Token \ + | awk '{print $2}' \ + | tr '\r' ' ' \ + | sed 's/[[:space:]]*$//') +} +################################################## +# Get an openstack token using the first method +# available (openstack, wget, curl) +# Globals: +# OS_AUTH_TYPE +# OS_TOKEN +# OS_AUTH_TOKEN +# Returns: +# 0 if OS_TOKEN was set, non-zero on error. +################################################## +get_cloud_token () { + echo "Requesting a new access token..." + # Clear previous access token stored in memory, if any (because it may have + # expired). + unset OS_AUTH_TYPE + unset OS_TOKEN + unset OS_AUTH_TOKEN + url="${OS_AUTH_URL}/auth/tokens" + data=' + { "auth": { + "identity": { + "methods": ["password"], + "password": { + "user": { + "name": "'${OS_USERNAME}'", + "domain": { "name": "'${OS_USER_DOMAIN_NAME}'" }, + "password": "'${OS_PASSWORD}'" + } + } + }, + "scope": { + "project": { + "id": "'${OS_PROJECT_ID}'" + } + } + } + }' + # Use one of the methods available in order of priority (openstack, wget, + # curl). + if [[ -x "$(command -v openstack)" ]]; then + # Use openstack CLI + OS_TOKEN=$(openstack token issue -f value -c id) + elif [[ -x "$(command -v wget)" ]]; then + # Use wget + response=$(wget -S -q -O - --header="Content-Type: application/json" --post-data "${data}" "${url}" 2>&1) + parse_token_from_response "${response}" + elif [[ -x "$(command -v curl)" ]]; then + # Use curl + response=$(curl -i -H "Content-Type: application/json" -d "${data}" "${url}" 2>&1) + parse_token_from_response "${response}" + else + error "Unable to find 'openstack', 'wget' or 'curl' in \$PATH. Please ensure at least one of 'python-openstackclient', 'wget' or 'curl' are installed and included in \$PATH." + return 1 + fi +} +################################################## +# Parse CLI options +# Globals: +# USE_TOKEN +# Returns: +# 0 if options parsed, non-zero if invalid +# option or help +################################################## +parse_arguments () { + # Reset variables before entering the parse loop, because they may have a + # value set in the current shell session. + USE_TOKEN="true" + while (( $# )); do + case "${1}" in + -n|--no-token) + USE_TOKEN="false" + warning "Warning: The --no-token option cannot be used with accounts that have MFA enabled. Disable MFA if using this option." + shift + ;; + -h|--help) + help + return 1 + ;; + *) # preserve positional arguments + error "Error: Unsupported option: $1" >&2 + display_usage + return 1 + ;; + esac + done +} +################################################## +# Prompts user to enter one time password via +# stdin and if provided, appends OTP to +# OS_PASSWORD. +# Globals: +# OS_PASSWORD +################################################## +prompt_mfa_passcode () { + echo -n "Please enter your MFA verification code (leave blank if not enabled): " + read -r one_time_passcode + if [[ -n "${one_time_passcode}" ]]; then + export OS_PASSWORD="${OS_PASSWORD}${one_time_passcode}" + else + warning "MFA is recommended and can be enabled under the settings tab of the dashboard." + fi + unset one_time_passcode +} +################################################## +# Prompt user to enter account password via stdin +# and sets password in environment as OS_PASSWORD +# Globals: +# OS_PASSWORD +# OS_USERNAME +################################################## +prompt_password (){ + echo -n "Please enter the password for user ${OS_USERNAME}: " + read -sr OS_PASSWORD + export OS_PASSWORD + echo "" +} +################################################## +# Display usage and then help information +# Globals: +# BASH_SOURCE +# Outputs: +# Writes help text to stdout +################################################## +display_usage () { + script_name=$(basename "${SCRIPT_SOURCE}") + echo "Usage: source ${script_name} [-h] [--no-input]" +} +################################################## +# Display usage and then help information +# Globals: +# BASH_SOURCE +# Outputs: +# Writes help text to stdout +################################################## +help () { + display_usage + echo "" + echo "Optional arguments:" + echo " -h, --help Show this help mesage and exit." + echo " -n, --no-token Sets the \$OS_USERNAME and \$OS_PASSWORD" + echo " environment variables, but does not fetch" + echo " or store an auth token on \$OS_AUTH_TOKEN or" + echo " \$OS_TOKEN." +} +########## +# Main () +########## +parse_arguments "$@" +# Exit if parse arguments returns non 0 value. +if [[ $? -ne 0 ]]; then + return 1 +fi +#---------------------------------------------------- +# Prompt for username and password for authentication +#---------------------------------------------------- +prompt_password +# Only prompt for MFA if user is using token based auth +if [[ "${USE_TOKEN}" == "true" ]]; then + prompt_mfa_passcode + get_cloud_token + if [[ -n "${OS_TOKEN}" ]]; then + export OS_TOKEN + export OS_AUTH_TYPE="token" + export OS_AUTH_TOKEN="${OS_TOKEN}" + success "Access token obtained successfully and stored in \$OS_TOKEN." + else + error "Failed to authenticate. Credentials may be incorrect or auth API inaccessible." + fi + # Clear all variables that are no longer needed from memory. + unset OS_PROJECT_NAME + unset OS_PROJECT_DOMAIN_ID + unset OS_USER_DOMAIN_NAME + unset OS_USERNAME + unset OS_PASSWORD +else + unset OS_AUTH_TYPE + unset OS_TOKEN + unset OS_AUTH_TOKEN + success "Environment variables required for authentication are set." + echo "You can use the \"openstack token issue\" command to obtain an auth token." +fi \ No newline at end of file