diff --git a/.gitignore b/.gitignore index 6fe3a61..94f88c4 100644 --- a/.gitignore +++ b/.gitignore @@ -109,8 +109,19 @@ ansible/*.retry ansible/roles/*\.*/ # Galaxy collections ansible/collections/**/ +# Image cache +ansible/openstack-config-image-cache +# Venvs +ansible/openstack-config-venv # Editors *~ .*.swp .*sw? + +# Ignore working dirs +ansible/openstack-config-image-cache +ansible/openstack-config-venv + +# Ignore tmp output from template generation playbook +generated-magnum-snippets/ \ No newline at end of file diff --git a/README.rst b/README.rst index a459010..13f69ba 100644 --- a/README.rst +++ b/README.rst @@ -17,17 +17,12 @@ packages. For example: $ virtualenv venv $ source venv/bin/activate - $ pip install -U pip + $ python -m pip install --upgrade pip $ pip install -r requirements.txt Install Ansible role and collection dependencies from Ansible Galaxy: .. code-block:: - - $ ansible-galaxy role install \ - -p ansible/roles \ - -r requirements.yml - $ ansible-galaxy collection install \ -p ansible/collections \ -r requirements.yml @@ -81,3 +76,33 @@ configuration parameter: .. code-block:: $ tools/openstack-config -- --vault-password-file config-secret.vault + + +Magnum Cluster Templates +======================== + +To generate a new set of Magnum cluster templates and corresponding Glance image +definitions which utilise the latest stable upstream release tag, set the following +variables in `etc/openstack-config.yml` + +.. code-block:: yaml + + magnum_default_master_flavor_name: # Chosen flavor on target cloud + magnum_default_worker_flavor_name: # Chosen flavor on target cloud + magnum_external_net_name: # External network + magnum_loadbalancer_provider: # Octavia provider (e.g. 'ovn') + +then run the provided playbook with + +.. code-block:: bash + + $ tools/openstack-config -p ansible/generate-magnum-capi-templates.yml + +This will create a ``generated-magnum-snippets`` directory in the repo root with +a timestamped sub-directory containing an ``images.yml`` file and a ``templates.yml`` +file. The contents of these two files can then be added to any existing images and +cluster templates in ``etc/openstack-config.yml``. When deploying the updated config, +be sure to run the ``openstack-images.yml`` playbook *before* running the +``openstack-container-clusters.yml`` playbook, otherwise the Magnum API will return +an error referencing an invalid cluster type with image ``None``. This is handled +automatically if running the full ``openstack.yml`` playbook. diff --git a/ansible/generate-magnum-capi-templates.yml b/ansible/generate-magnum-capi-templates.yml new file mode 100644 index 0000000..ccbb574 --- /dev/null +++ b/ansible/generate-magnum-capi-templates.yml @@ -0,0 +1,60 @@ +--- +- name: Generate cluster templates + hosts: localhost + vars: + root_dir: ../ + tasks: + + - name: Check that required variables are defined + assert: + that: + - magnum_default_master_flavor_name is defined + - magnum_default_worker_flavor_name is defined + - magnum_external_net_name is defined + - magnum_loadbalancer_provider is defined + + - name: Fetch capi-helm-charts release information + ansible.builtin.uri: + url: https://api.github.com/repos/stackhpc/capi-helm-charts/releases/latest + register: capi_helm_chart_release_data + + - name: Fetch dependencies.json for capi-helm-charts release + ansible.builtin.uri: + url: https://raw.githubusercontent.com/stackhpc/capi-helm-charts/{{ capi_helm_chart_release_data.json.tag_name }}/dependencies.json + register: dependencies_response + + - name: Ensure wget packages is installed + become: true + package: + name: wget + state: present + + - name: Fetch manifest.json for capi-helm-charts images + # ansible.builtin.uri: + # url: https://raw.githubusercontent.com/stackhpc/azimuth-images/{{ dependencies_response.json['azimuth-images'] }}/manifest.json + # Above URL returns 404 even though similar URL for capi-helm-charts repo works fine + # Not sure why but fall back to wget + JSON parsing for now. + shell: "wget -O - https://github.com/stackhpc/azimuth-images/releases/download/{{ dependencies_response.json['azimuth-images'] }}/manifest.json" + register: manifest_response + changed_when: false + + - name: Parse JSON response + set_fact: + new_template_data: "{{ manifest_response.stdout | from_json | dict2items | selectattr('key', 'match', 'kubernetes*') | list }}" + + - name: Ensure output dir exists + ansible.builtin.file: + path: "{{ [root_dir, 'generated-magnum-snippets', now(utc=true,fmt='%Y-%m-%d-T%H-%M-%S')] | path_join }}" + state: directory + mode: '0755' + register: output_dir + + - name: Write new image config to file + template: + src: "magnum-capi-images.j2" + dest: "{{ output_dir.path }}/images.yml" + + - name: Write new cluster template config to file + template: + src: "magnum-capi-templates.j2" + dest: "{{ output_dir.path }}/templates.yml" diff --git a/ansible/group_vars/all/openstack b/ansible/group_vars/all/openstack index 690572b..462f3eb 100644 --- a/ansible/group_vars/all/openstack +++ b/ansible/group_vars/all/openstack @@ -2,6 +2,10 @@ ############################################################################### # Configuration of OpenStack user environment for OpenStack. +# List of OpenStack domains. Format is as required by the stackhpc.os-projects +# role. +openstack_domains: [] + # List of OpenStack projects. Format is as required by the stackhpc.os-projects # role. openstack_projects: [] @@ -21,6 +25,10 @@ openstack_routers: [] # stackhpc.os-networks role. openstack_security_groups: [] +# List of RBAC definitions in the openstack projct. Format is as required by the +# stackhpc.os-networks role. +openstack_networks_rbac: [] + ############################################################################### # Configuration of nova flavors for OpenStack. diff --git a/ansible/openstack-container-clusters.yml b/ansible/openstack-container-clusters.yml index 0194742..5df9a4c 100644 --- a/ansible/openstack-container-clusters.yml +++ b/ansible/openstack-container-clusters.yml @@ -4,7 +4,7 @@ tags: - container-clusters-templates roles: - - role: stackhpc.os-container-clusters + - role: stackhpc.openstack.os_container_clusters os_container_clusters_venv: "{{ openstack_venv }}" os_container_clusters_auth_type: "{{ openstack_auth_type }}" os_container_clusters_auth: "{{ openstack_auth }}" diff --git a/ansible/openstack-flavors.yml b/ansible/openstack-flavors.yml index 16a06b3..69b94f2 100644 --- a/ansible/openstack-flavors.yml +++ b/ansible/openstack-flavors.yml @@ -4,7 +4,7 @@ tags: - flavors roles: - - role: stackhpc.os-flavors + - role: stackhpc.openstack.os_flavors os_flavors_venv: "{{ openstack_venv }}" os_flavors_auth_type: "{{ openstack_auth_type }}" os_flavors_auth: "{{ openstack_auth }}" diff --git a/ansible/openstack-host-aggregates.yml b/ansible/openstack-host-aggregates.yml index 3826904..f37449e 100644 --- a/ansible/openstack-host-aggregates.yml +++ b/ansible/openstack-host-aggregates.yml @@ -4,7 +4,7 @@ tags: - host_aggregates roles: - - role: stackhpc.os_host_aggregates + - role: stackhpc.openstack.os_host_aggregates os_host_aggregates_venv: "{{ openstack_venv }}" os_host_aggregates_auth_type: "{{ openstack_auth_type }}" os_host_aggregates_auth: "{{ openstack_auth }}" diff --git a/ansible/openstack-images.yml b/ansible/openstack-images.yml index 3c89df6..8fafc3c 100644 --- a/ansible/openstack-images.yml +++ b/ansible/openstack-images.yml @@ -4,7 +4,7 @@ tags: - images roles: - - role: stackhpc.os-images + - role: stackhpc.openstack.os_images os_images_venv: "{{ openstack_venv }}" os_images_cache: "{{ ansible_env.PWD }}/openstack-config-image-cache" os_images_auth_type: "{{ openstack_auth_type }}" diff --git a/ansible/openstack-networks.yml b/ansible/openstack-networks.yml index 525712d..5f175d0 100644 --- a/ansible/openstack-networks.yml +++ b/ansible/openstack-networks.yml @@ -4,7 +4,7 @@ tags: - networks roles: - - role: stackhpc.os-networks + - role: stackhpc.openstack.os_networks os_networks_venv: "{{ openstack_venv }}" os_networks_auth_type: "{{ openstack_auth_type }}" os_networks_auth: "{{ openstack_auth }}" @@ -12,3 +12,4 @@ os_networks: "{{ openstack_networks }}" os_networks_routers: "{{ openstack_routers }}" os_networks_security_groups: "{{ openstack_security_groups }}" + os_networks_rbac: "{{ openstack_networks_rbac }}" diff --git a/ansible/openstack-project.yml b/ansible/openstack-project.yml index f18334b..2de1fb9 100644 --- a/ansible/openstack-project.yml +++ b/ansible/openstack-project.yml @@ -4,9 +4,10 @@ tags: - project roles: - - role: stackhpc.os-projects + - role: stackhpc.openstack.os_projects os_projects_venv: "{{ openstack_venv }}" os_projects_auth_type: "{{ openstack_auth_type }}" os_projects_admin_auth: "{{ openstack_auth }}" os_projects_cacert: "{{ openstack_cacert }}" os_projects: "{{ openstack_projects }}" + os_projects_domains: "{{ openstack_domains }}" diff --git a/ansible/roles/.keep b/ansible/roles/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/ansible/secrets/nvidia-client-token.tok b/ansible/secrets/nvidia-client-token.tok new file mode 100644 index 0000000..cfda18b --- /dev/null +++ b/ansible/secrets/nvidia-client-token.tok @@ -0,0 +1,140 @@ +$ANSIBLE_VAULT;1.1;AES256 +37366431656638653236363833623031663536646163326536386265303135323237353665653638 +3634653939306336373662656461663832653866373563320a373336393064366363386263333764 +61313162303263383936373437653334306565373232613132343335356533656361386166326335 +3235636135376136360a356636626338613230316233336538616236303538313237653934613132 +65623064386539663866663432376430383565376231393939646435636264326463653033313038 +62333365396436303737626638333833353264343965376538346632623966363131646639646561 +32333161313464316533613230636131613336303863303131326631636163623631326166323438 +66636232376461303231343930303535303532663361663034336562366537353863666137363631 +63633133373639376338633234613766326433366361636637393638613362326434623337333939 +66316564316639383534643465623837633039333763613864336165363566323733343064663930 +38353965323763303934393465303731306332613935646636633233393531323033353031653063 +64643663653665343937363439373835383033373365633637306162356464663066323830633636 +38306265386562396137336431633331396137643338313061313061393061306238346634323138 +64306437343865386261373561656661333062323963326334663764613836346266393535386463 +61383031356665363233313637343533366539633734336365643834646438653265383862666336 +63353163623635386233356462636232316563303136383764616633336432316633376266326365 +61393564333532323836383564373537383435396464366536393130666236356536393634333436 +35643765396663373035306166376530663530366233373331646533333038376435653964636236 +63353531356663383234636238383239643462646366363439373036396238353132333537623237 +63346538333637373131613332383237663933643034653437323337636338653434646131386136 +65646538326466653733646666343266343737393138323038653161393163623433363632633633 +38633632323033396539366363316239636233656565653334336266383531393231386239643233 +63623939306366333131373739633434373733363864386438653938306562376131626665663433 +34623365313838353762393361386136303932653631363661336533343263636333393465636330 +33396239636232393535356233623735656665643530643963306236326235323631363362383033 +37383661343535303561363066396236353463613437643966393762346466373562343163653661 +61663437353932666239656263363739643135666138356634393335326336333739343733326133 +35373332663438626264306432643037323763386261396363343065343866393731623136346432 +61356331353662306633643563313964386637643938336234346636323834623562373431623831 +65336561653161663665303537656336323339336262303833383838376537623030343633626130 +39643838326634313934623139663064383634633338386261343931343464393733636630633033 +30383937666364663333396366346335313565373337636362306262343861323061366433303232 +65303030353934313931393466633432363761623837656332356333336561623039633938623066 +64343238373134313735636561613866313761376463333731336361613865663261656535346461 +61613534663566313236646364616231656664343138383236326265636235616136323130373864 +32613134663431613034383435326431306136656638653164633439313865346464383663663265 +38373230366361363866383330633836353535393039616231636662663437353962613863646634 +63356637366164313131333231393466383133363863306164613030393566366534613063653636 +38393562616330383136333932376330366562366238356266323063313030386432333966353236 +34663934343231643630396331306231616561363833383034353062656537353363376463383162 +34636538643233383137663733303638613961323735363636646630373337383636643837343534 +37643035356436656430333038663938646662363837346238303735353539333661346239386239 +30336565323166663564373034613430323931633562363337316533383066616532313163393439 +32656162343362633038356330366233353133303135613266663935653338346139333135613964 +33666438636166303265303937623738663439386630373735626433653738613334346261353131 +36323864633665306133643332396231366332666461356331306237373163613236643664366364 +33653433636262326232323136343636383362373638323530323466306161363338343364653735 +64393436313238616331333438396539386666663532396233396462363266323265383537343532 +35663838313065356630336361663761366532663934633564333436376537346637393238616535 +34333564646230353336633037373038393262646361396332353161376563333631663563643261 +62323633386431643766623361613866656232316232386132326538383635636538613639326635 +65316665313433303031313939623831333930363464323737373832386632363139346664653033 +36373638386435326236623866326636623531306364353737393634386662353136343033636664 +37616265343664396534656633626634313761373435366666636238653030626564616165303864 +36353964373562383832626230653139643934613938353432613335623966383364623233666532 +36366363336533353561363630376162643635653863623064643634303061313863376463626162 +32326138613432373132376366313163656339636261343133393233363033613335316262643963 +66646533346230383936383963636532636666663265343230316263626666366365353965346239 +65373964366432353233313232663765343765393963373163333331386364316166666537353431 +65663339633139393532613430663437363865376637633835663464316231303939373331323839 +38336435613433353339336162633335353134393966323931353634663865613539383764343032 +38303036633639383733633963643138396463643932656538376534396562626432363138636533 +61366362656236393536643139333964336265326539323334306462633965363966616432663337 +33643730363532313439396536326338313539313732623334353332313963363631366663663164 +32363033336565356363633661636538356437663538346237356636616331613266653534326363 +64653862613763313830373532633437653737396265636464353161323939373530616239393632 +35646631633263333537393931393232383433396236313065306437653731313066316631333735 +64623132303638353334336463646138306362656139633731356636643737333737303738376635 +32646639366165353866633466353337666236383434623133653736303633663934346132303736 +39343966653665356231646439613334656237623663393065373366363362356336356538323966 +66623966356461393231623732356534646564643763626161303430626561633339633639353831 +30303332383565646237333965653339643539313062323364353335343738663333333061663535 +31393835333234353736393039313530336332303363653763386438376663646535363065373632 +33666363376137623561646231653137363366333332626164653534613766323338393932613533 +64333937633839626235366465623262313063393132653933656539353637623766336531323939 +61323966613564386330636261383961383330623834316331613064656332356134393536656461 +38316633666263626133386437613865633436356432663261336335323834363433303462656633 +31613034303733613663363333313937353931356262343937303136616666616637303165346566 +65333766326663356664323731356264393737353430633066346132353665343361616235393939 +35356434383662626664313132636539376562393238323462306532326639386566616236623665 +30653734303333346661363132376664366264643830376635303838643738366230363731333664 +61333362326134386464373030633634373138363461376133333764313532323364663838336664 +38353161306233633731343863636139396138653761623931346533653937316531316230646162 +62663430663339366463343032343366376436313936363133383237646534336361613534363237 +36626236376536626361666137356263366236613935363231363366306563326366613663313338 +62653861653264643136306565303064373166626163646466303733363837353434613463396430 +37633031383261363435646233663435336165643238663263646165623961666463323333373138 +32613032343637363330646432323265306139396637323531396330623030306437393435323533 +66653638343636353734373233633065333562366361303137326334666532303636333431356264 +37636435363462323838336330363934643330393336373864643531666236326536353265343564 +61323831623562393437333264383664383461333965316536326365353761663632643238643935 +65313933393664386566363161633364633562383134396131643236663834613661323136386533 +64306561656532666162346232303262353135633434383834393835636333306266633630313835 +64626335396661616335303465336631383366366463353638373131386636636436363438636636 +35613834373932376665323066633561333739383736313431346665353335663462316463376137 +64313837363533626538396332383266373665393633373835626234356339326564343962626435 +62623730303839366637623534323833636334616534653132663839383762646361613563646366 +62343034653037303030306132376664653536373865393831653733396436653465336137396566 +32373565653533333336363662373939626633663965623866623730636665656432376330616562 +63333338346263393761343935623037393735316363333233366637386263633238366464633361 +31306265393365306630656239323462346562646432336566336364306130313334613861363331 +31363631366436333034663739353038643333633732336563633536306131326136646237376630 +66343032653631366363636534663363613863366563353136383830313037616232366335333461 +30323730323635633736663264343736353639616234356566393664643561366436363636616461 +62333830346530616636373034363338346330653735323065393236343432366263353939383132 +65386266363537346139623836613563633935643030376263336634646333336564633563323639 +35643130303466636136623037303036633465343537626131323432653937643766333666363238 +65383338346431383236613364666331363937303836396639306261336232633433373731313163 +32316361613239623137316464373033323661376336336233306130666635643839336232373637 +36363464643830663834363933613061623764353933626166633436666639336239613736383861 +65326436323232643362303932616137373634663034663665356166356634666564636133663038 +34373639653365333031353732303633653262306133303766666561363330653763366438343161 +35316361303666383337316638383134646461663931326265323663636237333563633961383664 +62663337643433643232393532303365353032306535356437643531653235633534626230363762 +63376536623630356333316464306539666132323661383962656461353162326533323764343434 +61633861613364373532383839333632323831393866643162623333316530633335623733633038 +39353032316434336263336331366431333036626334303566313561303236653337623764366439 +34373734643331633830316230356664616239633232326565626235363034643338653531323336 +65643134613635383863366463326438356262393637656235316332353137366436363066386165 +32643636613163356133373065396134373732643737323135303238613334626339393436666438 +61616164633561666466333665346262653965343830366465363333353366316630656661343261 +36393633353630306632616162343762323566376338303464636365653661653061393561303063 +33373739626139376634373765613236366632386532393364643231643838313261633864323836 +39323536666231613766306133393334396261623937353536326533373730313438643137636461 +38383531383066396436373162336466326535393334616438313731383161346439373631336266 +65376632373838656165393262363834303937396635323463656361623937666239663432383538 +39353666626230626135373466613733383130383063326434316539373231343934653266646362 +30376235386130393538396465306537343539396337653731623739373434663864666562666634 +66636532626133303034656661376237363130653631313064656231323637663232646637376564 +32633564316462386138626430323438386532623337386662356363613135373663313830373330 +61313061653266633636313934616631646334316266303735316364323366333631313035666666 +38346663396132383865376564633064653163636361666636333138343731306131333263366331 +38653866626565303936363966316230643032663161623466643231653833396435623461303539 +34373133333461383963656332633666636536303038346138663236353461346665356563616365 +61663436303863373037636334333936323365306133316236616463323031613337343437356231 +65333832633165306539643932653231303537363738663330383962383334343638363034633536 +37383162333166643231366434646364333763626336646335643962333534613730666266393233 +31646637336637643733333764653735396265313237326436646338356232613135613338616561 +636634393539646639373534393432363562 diff --git a/ansible/templates/magnum-capi-images.j2 b/ansible/templates/magnum-capi-images.j2 new file mode 100644 index 0000000..2e5e7e2 --- /dev/null +++ b/ansible/templates/magnum-capi-images.j2 @@ -0,0 +1,24 @@ +# Images required for corresponding Magnum cluster template +# To make use of the generated config snippets, copy them to +# etc/openstack-config and add the images to the openstack_images +# list. + +# List snippet to add to existing openstack_images: +{% for item in new_template_data %} +# -{% raw %} "{{ {% endraw %}{{ item.value.name | replace('-', '_') | replace('.', '_') }}{% raw %} }}"{% endraw %} + +{% endfor %} + +{% for item in new_template_data %} +# Image for {{ item.key }} +{{ item.value.name | replace('-', '_') | replace('.', '_') }}: + name: "{{ item.value.name }}" + type: qcow2 + image_url: "{{ item.value.url }}" + visibility: "community" + properties: + os_distro: "ubuntu" + os_version: "20.04" + kube_version: "{{ item.value.kubernetes_version }}" + +{% endfor %} diff --git a/ansible/templates/magnum-capi-templates.j2 b/ansible/templates/magnum-capi-templates.j2 new file mode 100644 index 0000000..f1d2cc7 --- /dev/null +++ b/ansible/templates/magnum-capi-templates.j2 @@ -0,0 +1,30 @@ +# Magnum cluster templates generated using latest upstream release tags +# To make use of the generated config snippets, copy them to the +# openstack_container_clusters_templates list. + +# List snippet to add to existing openstack_container_clusters_templates: +{% for item in new_template_data %} +# -{% raw %} "{{ {% endraw %}{{ item.key | replace('-', '_') }}_{{ item.value.kubernetes_version | replace('.', '_') }}{% raw %} }}"{% endraw %} + +{% endfor %} + +{% for item in new_template_data %} +{{ item.key | replace('-', '_') }}_{{ item.value.kubernetes_version | replace('.', '_') }}: + labels: + monitoring_enabled: "True" + kube_dashboard_enabled: "True" + capi_helm_chart_version: "{{ capi_helm_chart_release_data.json.tag_name }}" + octavia_provider: {{ magnum_loadbalancer_provider }} + external_network_id: {{ magnum_external_net_name }} + master_flavor: {{ magnum_default_master_flavor_name }} + flavor: {{ magnum_default_worker_flavor_name }} + image: "{{ item.value.name }}" + name: "{{ item.key }}" + coe: "kubernetes" + network_driver: "{{ magnum_default_network_driver | default('calico') }}" + master_lb_enabled: "{{ magnum_master_lb_enabled | default('True') }}" + floating_ip_enabled: "{{ magnum_cluster_floating_ip_enabled | default('True') }}" + dns_nameserver: "{{ (magnum_cluster_default_dns_nameservers | default(['1.1.1.1', '8.8.8.8', '8.8.4.4'])) | join(',') }}" + public: "{{ magnum_cluster_templates_public | default('True') }}" + +{% endfor %} \ No newline at end of file diff --git a/containerfiles/rocky-8.8 b/containerfiles/rocky-8.8 new file mode 100644 index 0000000..bd2439c --- /dev/null +++ b/containerfiles/rocky-8.8 @@ -0,0 +1,33 @@ +# syntax=docker/dockerfile:1.4.3 + +FROM docker.io/library/rockylinux:8.8 + +ARG rocky_version=8.8 + +# /etc/machine-id needs to be populated for /bin/kernel-install to +# correctly copy kernels into /boot. We will clear this out in the +# final image. +RUN systemd-machine-id-setup + +# Pin to an older version of Rocky Linux by setting a DNF package variable +# RUN echo "8.8" > /etc/dnf/vars/releasever && dnf update -y --refresh + +# Install/remove packages from https://git.rockylinux.org/rocky/kickstarts/-/blob/r8/Rocky-8-GenericCloud.ks +RUN dnf install -y @core --allowerasing +RUN dnf install -y chrony dnf yum cloud-init cloud-utils-growpart NetworkManager \ + findutils util-linux sudo python3 \ + dracut-config-generic dracut-norescue firewalld gdisk grub2 \ + kernel nfs-utils rsync tar dnf-utils yum-utils \ + python3-jsonschema qemu-guest-agent dhcp-client \ + rocky-release rng-tools +RUN dnf erase -y aic94xx-firmware alsa-firmware alsa-lib alsa-tools-firmware \ + ivtv-firmware iwl100-firmware iwl1000-firmware iwl105-firmware \ + iwl135-firmware iwl2000-firmware iwl2030-firmware iwl3160-firmware \ + iwl3945-firmware iwl4965-firmware iwl5000-firmware iwl5150-firmware \ + iwl6000-firmware iwl6000g2a-firmware iwl6000g2b-firmware iwl6050-firmware \ + iwl7260-firmware libertas-sd8686-firmware libertas-sd8787-firmware \ + libertas-usb8388-firmware biosdevname iprutils plymouth + +RUN systemctl unmask console-getty.service dev-hugepages.mount \ + getty.target sys-fs-fuse-connections.mount systemd-logind.service \ + systemd-remount-fs.service diff --git a/containerfiles/rocky-8.8-ofed-23.04 b/containerfiles/rocky-8.8-ofed-23.04 new file mode 100644 index 0000000..2077f7b --- /dev/null +++ b/containerfiles/rocky-8.8-ofed-23.04 @@ -0,0 +1,53 @@ +# syntax=docker/dockerfile:1.4.3 + +FROM docker.io/library/rockylinux:8.8 + +# /etc/machine-id needs to be populated for /bin/kernel-install to +# correctly copy kernels into /boot. We will clear this out in the +# final image. +RUN systemd-machine-id-setup + +# Pin to an older version of Rocky Linux by setting a DNF package variable +# RUN echo "8.8" > /etc/dnf/vars/releasever && dnf update -y --refresh + +# Install/remove packages from https://git.rockylinux.org/rocky/kickstarts/-/blob/r8/Rocky-8-GenericCloud.ks +RUN dnf install -y @core --allowerasing +RUN dnf install -y chrony dnf yum cloud-init cloud-utils-growpart NetworkManager \ + findutils util-linux sudo python3 \ + dracut-config-generic dracut-norescue firewalld gdisk grub2 \ + kernel nfs-utils rsync tar dnf-utils yum-utils \ + python3-jsonschema qemu-guest-agent dhcp-client \ + rocky-release rng-tools +RUN dnf erase -y aic94xx-firmware alsa-firmware alsa-lib alsa-tools-firmware \ + ivtv-firmware iwl100-firmware iwl1000-firmware iwl105-firmware \ + iwl135-firmware iwl2000-firmware iwl2030-firmware iwl3160-firmware \ + iwl3945-firmware iwl4965-firmware iwl5000-firmware iwl5150-firmware \ + iwl6000-firmware iwl6000g2a-firmware iwl6000g2b-firmware iwl6050-firmware \ + iwl7260-firmware libertas-sd8686-firmware libertas-sd8787-firmware \ + libertas-usb8388-firmware biosdevname iprutils plymouth + +RUN systemctl unmask console-getty.service dev-hugepages.mount \ + getty.target sys-fs-fuse-connections.mount systemd-logind.service \ + systemd-remount-fs.service + +# Apply OFED installation +# FIXME: the hardcoded kernel version should be dynamically deduced +RUN dnf config-manager --set-enabled powertools && dnf install -y perl cmake kernel-devel \ + python36-devel perl-generators python36 rpm-build elfutils-libelf-devel zlib-devel \ + gcc-c++ gdb-headless glib2-devel patch lsof libmnl-devel openssl-devel pciutils-devel \ + pkgconf-pkg-config libstdc++-devel libnl3-devel libtool python3-docutils numactl-devel \ + systemd-devel kernel-rpm-macros glibc-devel pciutils gcc valgrind-devel iptables-devel \ + bison libdb-devel elfutils-devel tcsh binutils-devel flex gcc-gfortran python3-Cython + +# Apply all package updates ahead of OFED installation to avoid dependency wrangling later +RUN dnf update -y + +RUN curl -L https://content.mellanox.com/ofed/MLNX_OFED-23.04-1.1.3.0/MLNX_OFED_SRC-23.04-1.1.3.0.tgz --output /tmp/MLNX_OFED_SRC-23.04-1.1.3.0.tgz \ + && cd /tmp \ + && tar -xzf MLNX_OFED_SRC-23.04-1.1.3.0.tgz \ + && /tmp/MLNX_OFED_SRC-23.04-1.1.3.0/install.pl --hpc --kernel $(cd /lib/modules && ls -t1 | head -n 1) -vvv \ + && rm -rf /tmp/MLNX_OFED_SRC-23.04-1.1.3.0* + +# This package causes us problems later on due to a higher epoch +# assigned to a lower version of OpenMPI 4 built by Rocky Linux +RUN dnf install -y python3-dnf-plugin-versionlock && yum versionlock openmpi diff --git a/containerfiles/rocky-9.1 b/containerfiles/rocky-9.1 new file mode 100644 index 0000000..d3e09e8 --- /dev/null +++ b/containerfiles/rocky-9.1 @@ -0,0 +1,32 @@ +# syntax=docker/dockerfile:1.4.3 + +FROM docker.io/library/rockylinux:9.1 + +ARG rocky_version=9.1 + +# /etc/machine-id needs to be populated for /bin/kernel-install to +# correctly copy kernels into /boot. We will clear this out in the +# final image. +#RUN systemd-machine-id-setup + +# Pin to an older version of Rocky Linux by setting a DNF package variable +RUN echo "9.1" > /etc/dnf/vars/releasever && echo "vault/rocky" > /etc/dnf/vars/contentdir && sed -e 's|^mirrorlist|#mirrorlist|' -e 's/^#baseurl=/baseurl=/' -i /etc/yum.repos.d/rocky*.repo && dnf update -y --refresh + +# Install/remove packages from https://git.rockylinux.org/rocky/kickstarts/-/blob/r8/Rocky-8-GenericCloud.ks +RUN dnf install -y @core --allowerasing +RUN dnf install -y chrony dnf yum cloud-init cloud-utils-growpart \ + dracut-config-generic firewalld gdisk grub2 \ + kernel nfs-utils rsync tar dnf-utils yum-utils \ + python3-jsonschema dhcp-client \ + rocky-release rng-tools initscripts +RUN dnf erase -y aic94xx-firmware alsa-firmware alsa-lib alsa-tools-firmware \ + ivtv-firmware iwl100-firmware iwl1000-firmware iwl105-firmware \ + iwl135-firmware iwl2000-firmware iwl2030-firmware iwl3160-firmware \ + iwl3945-firmware iwl4965-firmware iwl5000-firmware iwl5150-firmware \ + iwl6000-firmware iwl6000g2a-firmware iwl6000g2b-firmware iwl6050-firmware \ + iwl7260-firmware libertas-sd8686-firmware libertas-sd8787-firmware \ + libertas-usb8388-firmware biosdevname iprutils plymouth + +RUN systemctl unmask console-getty.service dev-hugepages.mount \ + getty.target sys-fs-fuse-connections.mount systemd-logind.service \ + systemd-remount-fs.service diff --git a/containerfiles/rocky-9.1-ofed-5.8 b/containerfiles/rocky-9.1-ofed-5.8 new file mode 100644 index 0000000..bb93d99 --- /dev/null +++ b/containerfiles/rocky-9.1-ofed-5.8 @@ -0,0 +1,47 @@ +# syntax=docker/dockerfile:1.4.3 + +FROM docker.io/library/rockylinux:9.1 + +# Pin to an older version of Rocky Linux by setting a DNF package variable +RUN echo "9.1" > /etc/dnf/vars/releasever && echo "vault/rocky" > /etc/dnf/vars/contentdir && sed -e 's|^mirrorlist|#mirrorlist|' -e 's/^#baseurl=/baseurl=/' -i /etc/yum.repos.d/rocky*.repo && dnf update -y --refresh + + +# /etc/machine-id needs to be populated for /bin/kernel-install to +# correctly copy kernels into /boot. We will clear this out in the +# final image. +RUN dnf install -y systemd +RUN /usr/bin/systemd-machine-id-setup + +# Install/remove packages from https://git.rockylinux.org/rocky/kickstarts/-/blob/r8/Rocky-8-GenericCloud.ks +RUN dnf install -y @core --allowerasing +RUN dnf install -y chrony dnf yum cloud-init cloud-utils-growpart \ + dracut-config-generic firewalld gdisk grub2 \ + kernel nfs-utils rsync tar dnf-utils yum-utils \ + python3-jsonschema dhcp-client \ + rocky-release rng-tools initscripts +RUN dnf erase -y aic94xx-firmware alsa-firmware alsa-lib alsa-tools-firmware \ + ivtv-firmware iwl100-firmware iwl1000-firmware iwl105-firmware \ + iwl135-firmware iwl2000-firmware iwl2030-firmware iwl3160-firmware \ + iwl3945-firmware iwl4965-firmware iwl5000-firmware iwl5150-firmware \ + iwl6000-firmware iwl6000g2a-firmware iwl6000g2b-firmware iwl6050-firmware \ + iwl7260-firmware libertas-sd8686-firmware libertas-sd8787-firmware \ + libertas-usb8388-firmware biosdevname iprutils plymouth + +RUN systemctl unmask console-getty.service dev-hugepages.mount \ + getty.target sys-fs-fuse-connections.mount systemd-logind.service \ + systemd-remount-fs.service + +# Apply OFED installation +RUN dnf config-manager --set-enabled appstream crb && dnf install -y perl cmake kernel-devel \ + python3-devel perl-generators python3 rpm-build elfutils-libelf-devel zlib-devel \ + gcc-c++ gdb-headless glib2-devel patch lsof libmnl openssl-devel pciutils-devel \ + pkgconf-pkg-config libstdc++-devel libnl3-devel libtool numactl-devel \ + systemd-devel kernel-rpm-macros glibc-devel pciutils gcc valgrind-devel iptables-devel \ + bison libdb-devel elfutils-devel tcsh binutils-devel flex gcc-gfortran \ + python3-Cython python3-docutils libmnl-devel + +RUN curl -L https://content.mellanox.com/ofed/MLNX_OFED-5.8-1.1.2.1/MLNX_OFED_SRC-5.8-1.1.2.1.tgz --output /tmp/MLNX_OFED_SRC-5.8-1.1.2.1.tgz \ + && cd /tmp \ + && tar -xzf MLNX_OFED_SRC-5.8-1.1.2.1.tgz \ + && /tmp/MLNX_OFED_SRC-5.8-1.1.2.1/install.pl --hpc --kernel $(cd /lib/modules && ls -t1 | head -n 1) \ + && rm -rf /tmp/MLNX_OFED_SRC-5.8-1.1.2.1* diff --git a/containerfiles/rocky-9.2 b/containerfiles/rocky-9.2 new file mode 100644 index 0000000..f1f33a1 --- /dev/null +++ b/containerfiles/rocky-9.2 @@ -0,0 +1,32 @@ +# syntax=docker/dockerfile:1.4.3 + +FROM docker.io/library/rockylinux:9.2 + +ARG rocky_version=9.2 + +# /etc/machine-id needs to be populated for /bin/kernel-install to +# correctly copy kernels into /boot. We will clear this out in the +# final image. +#RUN systemd-machine-id-setup + +# Pin to an older version of Rocky Linux by setting a DNF package variable +# RUN echo "9.2" > /etc/dnf/vars/releasever && dnf update -y --refresh + +# Install/remove packages from https://git.rockylinux.org/rocky/kickstarts/-/blob/r8/Rocky-8-GenericCloud.ks +RUN dnf install -y @core --allowerasing +RUN dnf install -y chrony dnf yum cloud-init cloud-utils-growpart \ + dracut-config-generic firewalld gdisk grub2 \ + kernel nfs-utils rsync tar dnf-utils yum-utils \ + python3-jsonschema dhcp-client \ + rocky-release rng-tools initscripts +RUN dnf erase -y aic94xx-firmware alsa-firmware alsa-lib alsa-tools-firmware \ + ivtv-firmware iwl100-firmware iwl1000-firmware iwl105-firmware \ + iwl135-firmware iwl2000-firmware iwl2030-firmware iwl3160-firmware \ + iwl3945-firmware iwl4965-firmware iwl5000-firmware iwl5150-firmware \ + iwl6000-firmware iwl6000g2a-firmware iwl6000g2b-firmware iwl6050-firmware \ + iwl7260-firmware libertas-sd8686-firmware libertas-sd8787-firmware \ + libertas-usb8388-firmware biosdevname iprutils plymouth + +RUN systemctl unmask console-getty.service dev-hugepages.mount \ + getty.target sys-fs-fuse-connections.mount systemd-logind.service \ + systemd-remount-fs.service diff --git a/etc/openstack-config/openstack-config.yml b/etc/openstack-config/openstack-config.yml index fd88313..28abb23 100644 --- a/etc/openstack-config/openstack-config.yml +++ b/etc/openstack-config/openstack-config.yml @@ -2,31 +2,513 @@ ############################################################################### # Configuration of OpenStack projects and users user environment. +# List of OpenStack domains. Format is as required by the stackhpc.os-projects +# role. +#openstack_domains: + # List of OpenStack projects. Format is as required by the stackhpc.os-projects # role. -#openstack_projects: +openstack_projects: + - "{{ openstack_project_stackhpc }}" + - "{{ project_cloud_services }}" + - "{{ openstack_project_azimuth }}" + +# Definition of the openstack demo project. Format is as required by the +# stackhpc.os-projects role. +openstack_project_stackhpc: + name: "stackhpc" + description: "StackHPC demo project" + project_domain: "default" + user_domain: "default" + users: "{{ openstack_stackhpc_users }}" + quotas: "{{ openstack_project_quotas }}" + +# StackHPC project users and roles +openstack_stackhpc_users: + - name: "stackhpc-dmehmood" + description: "Dawud Mehmood (StackHPC)" + email: "dawud@stackhpc.com" + password: "placeholder" + roles: "{{ openstack_user_roles }}" + - name: "stackhpc-mcrees" + description: "Matt Crees (StackHPC)" + email: "mattc@stackhpc.com" + password: "placeholder" + roles: "{{ openstack_user_roles }}" + - name: "stackhpc-stelfer" + description: "Stig Telfer (StackHPC)" + email: "stig@stackhpc.com" + password: "placeholder" + roles: "{{ openstack_user_roles }}" + - name: "stackhpc-sdavidson" + description: "Scott Davidson (StackHPC)" + email: "scott@stackhpc.com" + password: "placeholder" + roles: "{{ openstack_user_roles }}" + - name: "stackhpc-slee" + description: "Seunghun Lee (StackHPC)" + email: "seunghun@stackhpc.com" + password: "placeholder" + roles: "{{ openstack_user_roles }}" + +project_cloud_services: + name: "cloud-services" + description: "Internal Cloud services" + project_domain: default + user_domain: default + users: [] + quotas: "{{ openstack_project_quotas }}" + +# List of roles to apply to regular users in the openstack demo project. +openstack_user_roles: + - member + - heat_stack_owner + # This allows a user read and write access to octavia APIs. + # https://docs.openstack.org/octavia/latest/configuration/policy.html + - load-balancer_member + # This allows a user read access to Barbican secrets. + # https://docs.openstack.org/barbican/latest/admin/access_control.html + - observer + +openstack_project_azimuth: + name: "azimuth" + description: "A project for hosting Azimuth management resources" + project_domain: "default" + user_domain: "default" + users: "{{ openstack_stackhpc_users }}" + quotas: "{{ openstack_project_quotas }}" + +# Dict of quotas to set for projects with basic resource quotas +openstack_project_quotas: + backup_gigabytes: -1 + backups: -1 + cores: 250 + floatingip: 10 + gigabytes: 10000 + injected_file_size: -1 + injected_files: -1 + instances: 20 + key_pairs: 10 + per_volume_gigabytes: 500 + ram: 1000000 + security_group: 10 + security_group_rule: 100 + snapshots: -1 + volumes: 50 + +# Dict of quotas to set for projects with unlimited resource quotas +openstack_unlimited_quotas: + backup_gigabytes: -1 + backups: -1 + cores: -1 + floatingip: -1 + gigabytes: -1 + injected_file_size: -1 + injected_files: -1 + instances: -1 + key_pairs: -1 + per_volume_gigabytes: -1 + ram: -1 + security_group: -1 + security_group_rule: -1 + snapshots: -1 + volumes: -1 ############################################################################### # Configuration of networks, subnets and routers. # List of networks in the openstack system. Format is as required by the # stackhpc.os-networks role. -#openstack_networks: +openstack_networks: + - "{{ openstack_network_external_internet }}" + - "{{ openstack_network_external_ceph }}" + - "{{ openstack_network_stackhpc }}" + - "{{ openstack_network_stackhpc_vlan }}" + +openstack_networks_rbac: + - "{{ openstack_rbac_external_ceph }}" + +# +# External/Internet network +# Actually still a private subnet range but intended for outward-facing +# networking. +# +openstack_network_external_internet_name: "external" + +openstack_network_external_internet: + name: "{{ openstack_network_external_internet_name }}" + project: "admin" + provider_network_type: "vlan" + provider_physical_network: "physnet1" + provider_segmentation_id: 2803 + shared: false + external: true + # Subnet configuration. + subnets: + - "{{ openstack_subnet_external_internet }}" + +openstack_subnet_external_internet: + name: "{{ openstack_network_external_internet_name }}" + project: "admin" + cidr: "10.129.30.0/23" + gateway_ip: "10.129.31.254" + allocation_pool_start: "10.129.30.20" + allocation_pool_end: "10.129.31.240" + +# +# External/Ceph network +# +openstack_network_external_ceph_name: "external-ceph" + +# The External/Ceph network is owned by the admin project and shared +# via RBAC with projects that require direct access to Ceph storage +# (eg, for Manila CephFS native access). The network access control +# is set as "access as shared" for those tenant networks. +openstack_network_external_ceph: + name: "{{ openstack_network_external_ceph_name }}" + project: "admin" + provider_network_type: "vlan" + provider_physical_network: "physnet2" + provider_segmentation_id: 8 + shared: false + external: false + mtu: 9150 + # Subnet configuration. + subnets: + - "{{ openstack_subnet_external_ceph }}" + +# There is no route out from this network for VMs +# Reserve some space at the bottom of the network for Ceph IPs +openstack_subnet_external_ceph: + name: "{{ openstack_network_external_ceph_name }}" + project: "admin" + cidr: "10.0.0.0/20" + allocation_pool_start: "10.0.0.2" + allocation_pool_end: "10.0.15.250" + host_routes: + - destination: "10.129.27.0/25" + nexthop: "10.0.15.254" + +# The External/Ceph network is shared as an additional tenant +# VLAN for approved projects requiring high-speed direct access +# to the Ceph cluster. Those projects don't get to attach routers +# or make other changes to the external-ceph network, but can attach +# VM network ports to the shared network. VMs from different +# projects are on the same network but isolated from one another +# by security groups. +# Those projects are listed here. +openstack_rbac_external_ceph: + network: "{{ openstack_network_external_ceph_name }}" + access: "access_as_shared" + projects: + - "{{ openstack_project_stackhpc.name }}" # List of routers in the openstack project. Format is as required by the # stackhpc.os-networks role. -#openstack_routers: +openstack_routers: + - "{{ openstack_router_stackhpc }}" # List of security groups in the openstack project. # Format is as required by the stackhpc.os-networks role. -#openstack_security_groups: +openstack_security_groups: + - "{{ openstack_secgroup_stackhpc }}" + - "{{ secgroup_nvidia_dls }}" + +# Default security group rule settings for a project +openstack_secgroup_rules_default: + # Allow ICMP (for ping, etc.). + - ethertype: IPv4 + protocol: icmp + # Allow SSH. + - ethertype: IPv4 + protocol: tcp + port_range_min: 22 + port_range_max: 22 + +secgroup_rules_nvidia_dls: + # Allow ICMP (for ping, etc.). + - ethertype: IPv4 + protocol: icmp + # Allow SSH. + - ethertype: IPv4 + protocol: tcp + port_range_min: 22 + port_range_max: 22 + # https://docs.nvidia.com/license-system/latest/nvidia-license-system-user-guide/index.html + - ethertype: IPv4 + protocol: tcp + port_range_min: 443 + port_range_max: 443 + - ethertype: IPv4 + protocol: tcp + port_range_min: 80 + port_range_max: 80 + - ethertype: IPv4 + protocol: tcp + port_range_min: 7070 + port_range_max: 7070 + +secgroup_nvidia_dls: + name: nvidia-dls + project: "{{ project_cloud_services.name }}" + rules: "{{ secgroup_rules_nvidia_dls }}" + +################################################################################ +# Networks for stackhpc +# +openstack_network_stackhpc: + name: "{{ openstack_project_stackhpc.name }}" + project: "{{ openstack_project_stackhpc.name }}" + shared: false + external: false + # Subnet configuration. + subnets: + - "{{ openstack_subnet_stackhpc }}" + +openstack_subnet_stackhpc: + name: "{{ openstack_project_stackhpc.name }}" + project: "{{ openstack_project_stackhpc.name }}" + cidr: "192.168.0.0/24" + gateway_ip: "192.168.0.1" + allocation_pool_start: "192.168.0.10" + allocation_pool_end: "192.168.0.250" + +openstack_network_stackhpc_vlan: + name: "{{ openstack_project_stackhpc.name }}-vlan" + project: "{{ openstack_project_stackhpc.name }}" + shared: false + external: false + provider_network_type: "vlan" + provider_physical_network: "physnet2" + # This may be required for RDMA traffic + port_security_enabled: false + mtu: 9000 + # Subnet configuration. + subnets: + - "{{ openstack_subnet_stackhpc_vlan }}" + +openstack_subnet_stackhpc_vlan: + name: "{{ openstack_project_stackhpc.name }}-vlan" + project: "{{ openstack_project_stackhpc.name }}" + cidr: "192.168.1.0/24" + gateway_ip: "192.168.1.1" + allocation_pool_start: "192.168.1.10" + allocation_pool_end: "192.168.1.250" + +openstack_router_stackhpc: + name: "{{ openstack_project_stackhpc.name }}" + project: "{{ openstack_project_stackhpc.name }}" + interfaces: + - "{{ openstack_network_stackhpc.name }}" + - "{{ openstack_network_stackhpc_vlan.name }}" + network: "{{ openstack_network_external_internet.name }}" + +openstack_secgroup_stackhpc: + name: default + project: "{{ openstack_project_stackhpc.name }}" + rules: "{{ openstack_secgroup_rules_default }}" + + +# List of RBAC definitions in the openstack projct. Format is as required by the +# stackhpc.os-networks role. +#openstack_networks_rbac: ############################################################################### # Configuration of nova flavors. # List of nova flavors in the openstack project. Format is as required by the # stackhpc.os-flavors role. -#openstack_flavors: +openstack_flavors: +# - "{{ openstack_flavor_godzilla }}" + - "{{ vgpu_a100d_2g_20gb }}" + - "{{ vgpu_a100d_1g_10gb }}" + - "{{ vgpu_a100d_40c }}" + - "{{ hpc_v1_8cpu }}" + - "{{ hpc_v1_16cpu }}" + - "{{ hpc_v1_32cpu }}" + - "{{ hpc_v1_48cpu }}" + - "{{ hpc_v1_64cpu }}" + - "{{ hpc_v1_80cpu }}" + - "{{ hpc_v1_96cpu }}" + +# openstack_flavor_godzilla: +# name: "godzilla" +# ram: 393216 +# disk: 50 +# vcpus: 96 +# is_public: true +# extra_specs: +# hw:cpu_policy: "dedicated" +# hw:cpu_thread_policy: "prefer" +# hw:cpu_threads: 2 +# hw:mem_page_size: "1GB" +# hw:cpu_sockets: 2 +# hw:numa_nodes: 8 +# hw:pci_numa_affinity_policy: preferred +# hw_rng:allowed: "True" + +# HPC v1: +# Core-pinned VCPUs +# 4GB RAM per VCPU +# Spread across NUMA regions (but in thread sibling pairs) +# +hpc_v1_8cpu: + name: "hpc.v1.8cpu" + ram: 32768 + disk: 30 + vcpus: 8 + is_public: false + extra_specs: + hw:cpu_policy: "dedicated" + hw:cpu_thread_policy: "prefer" + hw:cpu_threads: 2 + hw:mem_page_size: "1GB" + hw:cpu_sockets: 2 + hw:numa_nodes: 8 + hw:pci_numa_affinity_policy: preferred + hw_rng:allowed: "True" + +hpc_v1_16cpu: + name: "hpc.v1.16cpu" + ram: 65536 + disk: 30 + vcpus: 16 + is_public: false + extra_specs: + hw:cpu_policy: "dedicated" + hw:cpu_thread_policy: "prefer" + hw:cpu_threads: 2 + hw:mem_page_size: "1GB" + hw:cpu_sockets: 2 + hw:numa_nodes: 8 + hw:pci_numa_affinity_policy: preferred + hw_rng:allowed: "True" + +hpc_v1_32cpu: + name: "hpc.v1.32cpu" + ram: 131072 + disk: 30 + vcpus: 32 + is_public: false + extra_specs: + hw:cpu_policy: "dedicated" + hw:cpu_thread_policy: "prefer" + hw:cpu_threads: 2 + hw:mem_page_size: "1GB" + hw:cpu_sockets: 2 + hw:numa_nodes: 8 + hw:pci_numa_affinity_policy: preferred + hw_rng:allowed: "True" + +hpc_v1_48cpu: + name: "hpc.v1.48cpu" + ram: 196608 + disk: 30 + vcpus: 48 + is_public: false + extra_specs: + hw:cpu_policy: "dedicated" + hw:cpu_thread_policy: "prefer" + hw:cpu_threads: 2 + hw:mem_page_size: "1GB" + hw:cpu_sockets: 2 + hw:numa_nodes: 8 + hw:pci_numa_affinity_policy: preferred + hw_rng:allowed: "True" + +hpc_v1_64cpu: + name: "hpc.v1.64cpu" + ram: 262144 + disk: 30 + vcpus: 64 + is_public: false + extra_specs: + hw:cpu_policy: "dedicated" + hw:cpu_thread_policy: "prefer" + hw:cpu_threads: 2 + hw:mem_page_size: "1GB" + hw:cpu_sockets: 2 + hw:numa_nodes: 8 + hw:pci_numa_affinity_policy: preferred + hw_rng:allowed: "True" + +hpc_v1_80cpu: + name: "hpc.v1.80cpu" + ram: 327680 + disk: 30 + vcpus: 80 + is_public: false + extra_specs: + hw:cpu_policy: "dedicated" + hw:cpu_thread_policy: "prefer" + hw:cpu_threads: 2 + hw:mem_page_size: "1GB" + hw:cpu_sockets: 2 + hw:numa_nodes: 8 + hw:pci_numa_affinity_policy: preferred + hw_rng:allowed: "True" + +hpc_v1_96cpu: + name: "hpc.v1.96cpu" + ram: 393216 + disk: 30 + vcpus: 96 + is_public: false + extra_specs: + hw:cpu_policy: "dedicated" + hw:cpu_thread_policy: "prefer" + hw:cpu_threads: 2 + hw:mem_page_size: "1GB" + hw:cpu_sockets: 2 + hw:numa_nodes: 8 + hw:pci_numa_affinity_policy: preferred + hw_rng:allowed: "True" + +vgpu_a100d_2g_20gb: + name: "vgpu.a100d.2g.20gb" + ram: 32768 + disk: 30 + vcpus: 8 + is_public: true + extra_specs: + hw:cpu_policy: "dedicated" + hw:cpu_thread_policy: "prefer" + hw:mem_page_size: "1GB" + hw:cpu_sockets: 2 + hw:numa_nodes: 4 + hw_rng:allowed: "True" + resources:CUSTOM_NVIDIA_700: "1" + +vgpu_a100d_1g_10gb: + name: "vgpu.a100d.1g.10gb" + ram: 16384 + disk: 30 + vcpus: 4 + is_public: true + extra_specs: + hw:cpu_policy: "dedicated" + hw:cpu_thread_policy: "prefer" + hw:mem_page_size: "1GB" + hw:cpu_sockets: 2 + hw:numa_nodes: 2 + hw_rng:allowed: "True" + resources:CUSTOM_NVIDIA_699: "1" + +vgpu_a100d_40c: + name: "vgpu.a100d.40c" + ram: 65536 + disk: 30 + vcpus: 16 + is_public: true + extra_specs: + hw:cpu_policy: "dedicated" + hw:cpu_thread_policy: "prefer" + hw:mem_page_size: "1GB" + hw:cpu_sockets: 2 + hw:numa_nodes: 8 + hw_rng:allowed: "True" + resources:CUSTOM_NVIDIA_697: "1" + ############################################################################### # Configuration of nova host aggregates. @@ -39,7 +521,328 @@ # Configuration of Glance software images. # List of Glance images. Format is as required by the stackhpc.os-images role. -#openstack_images: +# List of additional host packages. +os_images_package_dependencies_extra: + # debootstrap is required to build ubuntu-minimal images. + - debootstrap + +# Drop cloud-init and stable-interface-names from default elements. +os_images_common: enable-serial-console + +# Set this to true to force rebuilding images. +os_images_force_rebuild: false + +# List of Glance images. Format is as required by the stackhpc.os-images role. +openstack_images: + - "{{ openstack_image_rocky88 }}" + - "{{ openstack_image_rocky88_ofed2304 }}" + - "{{ openstack_image_rocky88_ofed2304_dev }}" + - "{{ openstack_image_rocky92 }}" + - "{{ openstack_image_ubuntu_jammy }}" + - "{{ image_rocky9_nvidia }}" + +# Rocky Linux 8.8 built using a custom containerfile +openstack_image_rocky88: + name: "Rocky-8.8" + type: "raw" + elements: + - "rocky-container" + - "cloud-init" + - "cloud-init-growpart" + - "epel" + - "selinux-permissive" + - "dhcp-all-interfaces" + - "vm" + - "grub2" + - "openssh-server" + - "block-device-efi" + - "dracut-regenerate" + is_public: True + packages: + - "gdisk" + - "efibootmgr" + - "efivar" + - "bash-completion" + - "git" + - "linux-firmware" + - "logrotate" + - "lshw" + - "man-db" + - "net-tools" + - "nmon" + - "pciutils" + - "tmux" + - "vim-enhanced" + - "NetworkManager-initscripts-updown" + - "dracut" + - "dracut-network" + env: + DIB_CONTAINERFILE_NETWORK_DRIVER: host + DIB_CONTAINERFILE_RUNTIME: docker + DIB_CONTAINERFILE_DOCKERFILE: "{{ playbook_dir }}/../containerfiles/rocky-8.8" + DIB_CLOUD_INIT_GROWPART_DEVICES: + - / + YUM: dnf + DIB_RELEASE: "8.8" + DIB_DRACUT_ENABLED_MODULES: + - name: lvm + packages: + - lvm2 + - name: kernel-modules + - name: kernel-network-modules + properties: + os_type: "linux" + os_distro: "rocky" + os_version: "8.8" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + +# Rocky 8.8 built with Mellanox OFED 23.04 +openstack_image_rocky88_ofed2304: + name: "Rocky-8.8-OFED-23.04" + type: "raw" + elements: + - "rocky-container" + - "cloud-init" + - "cloud-init-growpart" + - "epel" + - "selinux-permissive" + - "dhcp-all-interfaces" + - "vm" + - "grub2" + - "openssh-server" + - "block-device-efi" + - "dracut-regenerate" + is_public: False + packages: + - "gdisk" + - "efibootmgr" + - "efivar" + - "bash-completion" + - "git" + - "linux-firmware" + - "logrotate" + - "lshw" + - "man-db" + - "net-tools" + - "nmon" + - "pciutils" + - "tmux" + - "vim-enhanced" + - "NetworkManager-initscripts-updown" + - "dracut" + - "dracut-network" + env: + DIB_CONTAINERFILE_NETWORK_DRIVER: host + DIB_CONTAINERFILE_RUNTIME: docker + DIB_CONTAINERFILE_DOCKERFILE: "{{ playbook_dir }}/../containerfiles/rocky-8.8-ofed-23.04" + DIB_CLOUD_INIT_GROWPART_DEVICES: + - / + YUM: dnf + DIB_RELEASE: "8.8" + DIB_DRACUT_ENABLED_MODULES: + - name: lvm + packages: + - lvm2 + - name: kernel-modules + - name: kernel-network-modules + properties: + os_type: "linux" + os_distro: "rocky" + os_version: "8.8" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + +# Rocky 8.8 built with Mellanox OFED 23.04 + devuser +openstack_image_rocky88_ofed2304_dev: + name: "Rocky-8.8-OFED-23.04-dev" + type: "raw" + elements: + - "rocky-container" + - "cloud-init" + - "cloud-init-growpart" + - "epel" + - "selinux-permissive" + - "dhcp-all-interfaces" + - "vm" + - "grub2" + - "openssh-server" + - "block-device-efi" + - "dracut-regenerate" + - "devuser" + is_public: False + packages: + - "gdisk" + - "efibootmgr" + - "efivar" + - "bash-completion" + - "git" + - "linux-firmware" + - "logrotate" + - "lshw" + - "man-db" + - "net-tools" + - "nmon" + - "pciutils" + - "tmux" + - "vim-enhanced" + - "NetworkManager-initscripts-updown" + - "dracut" + - "dracut-network" + env: + DIB_DEV_USER_USERNAME: "devuser" + DIB_DEV_USER_PASSWORD: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 36346461356139626536656561353063623964356566303264383031653034633566386161333738 + 3831343166353132363332623232376463306138323038330a663231663833393132653965316534 + 36393032656138303632336231383437313532653335393038626132646635353664396233393037 + 3537396337623037370a393739396535316539663061623363376330636466333635646233306664 + 64623262396365373437356235346630613732666537623464663862653463333362 + DIB_DEV_USER_PWDLESS_SUDO: "yes" + DIB_CONTAINERFILE_NETWORK_DRIVER: host + DIB_CONTAINERFILE_RUNTIME: docker + DIB_CONTAINERFILE_DOCKERFILE: "{{ playbook_dir }}/../containerfiles/rocky-8.8-ofed-23.04" + DIB_CLOUD_INIT_GROWPART_DEVICES: + - / + YUM: dnf + DIB_RELEASE: "8.8" + DIB_DRACUT_ENABLED_MODULES: + - name: lvm + packages: + - lvm2 + - name: kernel-modules + - name: kernel-network-modules + properties: + os_type: "linux" + os_distro: "rocky" + os_version: "8.8" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + +# Rocky Linux 9.2 built from custom containerfile +openstack_image_rocky92: + name: "Rocky-9.2" + type: "raw" + elements: + - "rocky-container" + - "cloud-init" + - "cloud-init-growpart" + - "selinux-permissive" + - "vm" + - "grub2" + - "openssh-server" + is_public: True + packages: + - "git" + - "tmux" + - "vim-enhanced" + env: + DIB_CONTAINERFILE_NETWORK_DRIVER: host + DIB_CONTAINERFILE_RUNTIME: docker + DIB_CONTAINERFILE_DOCKERFILE: "{{ playbook_dir }}/../containerfiles/rocky-9.2" + YUM: dnf + DIB_CLOUD_INIT_GROWPART_DEVICES: + - "/" + DIB_RELEASE: "9.2" + properties: + os_type: "linux" + os_distro: "rocky" + os_version: "9.2" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + +# Ubuntu Jammy 22.04 +openstack_image_ubuntu_jammy: + name: "Ubuntu-22.04" + type: "raw" + is_public: True + elements: + - "cloud-init" + - "grub2" + - "openssh-server" + - "ubuntu-minimal" + - "vm" + - "dhcp-all-interfaces" + packages: + - "bash-completion" + - "git" + - "less" + - "logrotate" + - "lshw" + - "man-db" + - "net-tools" + - "nmon" + - "pciutils" + - "tmux" + - "iputils-ping" + - "netbase" + - "apt-utils" + - "curl" + - "debootstrap" + - "vim" + properties: + os_type: "linux" + os_distro: "ubuntu" + os_version: "jammy" + hw_rng_model: "virtio" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + env: + DIB_RELEASE: "jammy" + +image_rocky9_nvidia: + name: "Rocky9-NVIDIA" + type: raw + elements: + - "rocky-container" + - "rpm" + - "nvidia-vgpu" + - "cloud-init" + - "epel" + - "cloud-init-growpart" + - "selinux-permissive" + - "dhcp-all-interfaces" + - "vm" + - "extra-repos" + - "grub2" + - "stable-interface-names" + - "openssh-server" + is_public: True + packages: + - "dkms" + - "git" + - "tmux" + - "cuda-minimal-build-12-1" + - "cuda-demo-suite-12-1" + - "cuda-libraries-12-1" + - "cuda-toolkit" + - "vim-enhanced" + env: + DIB_CONTAINERFILE_NETWORK_DRIVER: host + DIB_CONTAINERFILE_RUNTIME: docker + DIB_RPMS: "http://10.129.28.41:80/pulp/content/nvidia/nvidia-linux-grid-525-525.125.06-1.x86_64.rpm" + YUM: dnf + DIB_EXTRA_REPOS: "https://developer.download.nvidia.com/compute/cuda/repos/rhel9/x86_64/cuda-rhel9.repo" + DIB_NVIDIA_VGPU_CLIENT_TOKEN: "{{ lookup('file' , 'secrets/nvidia-client-token.tok') }}" + DIB_CLOUD_INIT_GROWPART_DEVICES: + - "/" + DIB_RELEASE: "9" + properties: + os_type: "linux" + os_distro: "rocky" + os_version: "9" + +openstack_image_git_elements: + - repo: "https://github.com/stackhpc/stackhpc-image-elements" + local: "{{ playbook_dir }}/stackhpc-image-elements" + version: master + elements_path: elements + # List of Diskimage Builder (DIB) elements paths to include in image builds. #openstack_image_elements: @@ -55,6 +858,39 @@ # stackhpc.os-container-clusters role. #openstack_container_clusters_templates: +############################################################################### +# Configuration variables for generating new Magnum cluster template config. + +# These variables must be defined before using the generating new cluster +# templates - see repo README for more details. + +# Must have at least 2 CPUs, 4GB RAM and 20GB disk +# magnum_default_master_flavor_name: +# magnum_default_worker_flavor_name: + +# Network to create tenant cluster FIPs on +# magnum_external_net_name: + +# Provider for cluster loadbalancers (e.g. 'ovn') +# magnum_loadbalancer_provider: + +# Kubernetes CNI to use for cluster templates (defaults to 'calico') +# Must be one of the options supported by capi-helm-charts, see +# https://github.com/stackhpc/capi-helm-charts/tree/main/charts/cluster-addons#container-network-interface-cni-plugins +# magnum_default_network_driver: + +# Whether to create a master nodes loadbalancer for cluster templates (defaults to 'True') +# magnum_master_lb_enabled: + +# Whether to add a floating IP to the loadbalancer for cluster templates (defaults to 'True') +# magnum_cluster_floating_ip_enabled: + +# List of nameservers to use for cluster templates +# magnum_cluster_default_dns_nameservers: + +# Whether generated cluster templates should be public by default (defaults to 'True') +# magnum_cluster_templates_public: + ############################################################################### # Dummy variable to allow Ansible to accept this file. workaround_ansible_issue_8743: yes diff --git a/examples/images.yml b/examples/images.yml index 925406c..ba7ba0b 100644 --- a/examples/images.yml +++ b/examples/images.yml @@ -18,7 +18,11 @@ openstack_images: - "{{ openstack_image_centos_stream8 }}" - "{{ openstack_image_cirros_0_6_0 }}" - "{{ openstack_image_rocky8 }}" + - "{{ openstack_image_rocky88 }}" + - "{{ openstack_image_rocky91 }}" + - "{{ openstack_image_rocky92 }}" - "{{ openstack_image_ubuntu_focal }}" + - "{{ openstack_image_ubuntu_jammy }}" # CentOS Stream 8. openstack_image_centos_stream8: @@ -62,7 +66,7 @@ openstack_image_cirros_0_6_0: os_version: "0.6.0" hw_rng_model: "virtio" -# Rocky Linux 8. +# Rocky Linux 8, latest release. openstack_image_rocky8: name: "Rocky8" type: raw @@ -97,6 +101,129 @@ openstack_image_rocky8: os_version: "8" hw_rng_model: "virtio" +# Rocky Linux 8.8 built using a custom containerfile +openstack_image_rocky88: + name: "Rocky-8.8" + type: "raw" + elements: + - "rocky-container" + - "cloud-init" + - "cloud-init-growpart" + - "epel" + - "selinux-permissive" + - "dhcp-all-interfaces" + - "vm" + - "grub2" + - "openssh-server" + - "block-device-efi" + - "dracut-regenerate" + is_public: True + packages: + - "gdisk" + - "efibootmgr" + - "efivar" + - "bash-completion" + - "git" + - "linux-firmware" + - "logrotate" + - "lshw" + - "man-db" + - "net-tools" + - "nmon" + - "pciutils" + - "tmux" + - "vim-enhanced" + - "NetworkManager-initscripts-updown" + - "dracut" + - "dracut-network" + env: + DIB_CONTAINERFILE_NETWORK_DRIVER: host + DIB_CONTAINERFILE_RUNTIME: docker + DIB_CONTAINERFILE_DOCKERFILE: "{{ playbook_dir }}/../containerfiles/rocky-8.8" + DIB_CLOUD_INIT_GROWPART_DEVICES: + - / + YUM: dnf + DIB_RELEASE: "8.8" + DIB_DRACUT_ENABLED_MODULES: + - name: lvm + packages: + - lvm2 + - name: kernel-modules + - name: kernel-network-modules + properties: + os_type: "linux" + os_distro: "rocky" + os_version: "8.8" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + +# Rocky Linux 9.1 built from custom containerfile +openstack_image_rocky91: + name: "Rocky-9.1" + type: "raw" + elements: + - "rocky-container" + - "cloud-init" + - "cloud-init-growpart" + - "selinux-permissive" + - "vm" + - "grub2" + - "openssh-server" + is_public: True + packages: + - "git" + - "tmux" + - "vim-enhanced" + env: + DIB_CONTAINERFILE_NETWORK_DRIVER: host + DIB_CONTAINERFILE_RUNTIME: docker + DIB_CONTAINERFILE_DOCKERFILE: "{{ playbook_dir }}/../containerfiles/rocky-9.1" + YUM: dnf + DIB_CLOUD_INIT_GROWPART_DEVICES: + - "/" + DIB_RELEASE: "9.1" + properties: + os_type: "linux" + os_distro: "rocky" + os_version: "9.1" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + +# Rocky Linux 9.2 built from custom containerfile +openstack_image_rocky92: + name: "Rocky-9.2" + type: "raw" + elements: + - "rocky-container" + - "cloud-init" + - "cloud-init-growpart" + - "selinux-permissive" + - "vm" + - "grub2" + - "openssh-server" + is_public: True + packages: + - "git" + - "tmux" + - "vim-enhanced" + env: + DIB_CONTAINERFILE_NETWORK_DRIVER: host + DIB_CONTAINERFILE_RUNTIME: docker + DIB_CONTAINERFILE_DOCKERFILE: "{{ playbook_dir }}/../containerfiles/rocky-9.2" + YUM: dnf + DIB_CLOUD_INIT_GROWPART_DEVICES: + - "/" + DIB_RELEASE: "9.2" + properties: + os_type: "linux" + os_distro: "rocky" + os_version: "9.2" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + # Ubuntu Focal 20.04. openstack_image_ubuntu_focal: name: "Ubuntu-20.04" @@ -124,3 +251,139 @@ openstack_image_ubuntu_focal: env: DIB_RELEASE: "focal" DIB_CLOUD_INIT_DATASOURCES: "ConfigDrive" + +# Ubuntu Jammy 22.04 +openstack_image_ubuntu_jammy: + name: "Ubuntu-22.04" + type: "raw" + is_public: True + elements: + - "cloud-init" + - "grub2" + - "openssh-server" + - "ubuntu-minimal" + - "vm" + packages: + - "bash-completion" + - "git" + - "less" + - "logrotate" + - "lshw" + - "man-db" + - "net-tools" + - "nmon" + - "pciutils" + - "tmux" + - "iputils-ping" + - "netbase" + - "apt-utils" + - "curl" + - "debootstrap" + - "vim" + properties: + os_type: "linux" + os_distro: "ubuntu" + os_version: "jammy" + hw_rng_model: "virtio" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + env: + DIB_RELEASE: "jammy" + +################################################################################ +# Rocky Linux plus Open Fabrics (OFED) + +# Rocky 8.8 built with Mellanox OFED 23.04 +openstack_image_rocky88_ofed2304: + name: "Rocky-8.8-OFED-23.04" + type: "raw" + elements: + - "rocky-container" + - "cloud-init" + - "cloud-init-growpart" + - "epel" + - "selinux-permissive" + - "dhcp-all-interfaces" + - "vm" + - "grub2" + - "openssh-server" + - "block-device-efi" + - "dracut-regenerate" + is_public: False + packages: + - "gdisk" + - "efibootmgr" + - "efivar" + - "bash-completion" + - "git" + - "linux-firmware" + - "logrotate" + - "lshw" + - "man-db" + - "net-tools" + - "nmon" + - "pciutils" + - "tmux" + - "vim-enhanced" + - "NetworkManager-initscripts-updown" + - "dracut" + - "dracut-network" + env: + DIB_CONTAINERFILE_NETWORK_DRIVER: host + DIB_CONTAINERFILE_RUNTIME: docker + DIB_CONTAINERFILE_DOCKERFILE: "{{ playbook_dir }}/../containerfiles/rocky-8.8-ofed-23.04" + DIB_CLOUD_INIT_GROWPART_DEVICES: + - / + YUM: dnf + DIB_RELEASE: "8.8" + DIB_DRACUT_ENABLED_MODULES: + - name: lvm + packages: + - lvm2 + - name: kernel-modules + - name: kernel-network-modules + properties: + os_type: "linux" + os_distro: "rocky" + os_version: "8.8" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + +# Rocky Linux 9.1 plus OFED 5.8 drivers +openstack_image_rocky91_ofed58: + name: "Rocky-9.1-OFED-5.8" + type: "raw" + elements: + - "rocky-container" + - "cloud-init" + - "cloud-init-growpart" + - "selinux-permissive" + - "vm" + - "openssh-server" + - "dracut-regenerate" + is_public: False + packages: + - "git" + - "tmux" + - "vim-enhanced" + - "lshw" + - "pciutils" + - "infiniband-diags" + env: + DIB_CONTAINERFILE_DOCKERFILE: "{{ playbook_dir }}/../containerfiles/rocky-9.1-ofed-5.8" + DIB_CONTAINERFILE_NETWORK_DRIVER: host + DIB_CONTAINERFILE_RUNTIME: docker + YUM: dnf + DIB_CLOUD_INIT_GROWPART_DEVICES: + - "/" + DIB_RELEASE: "9.1" + properties: + os_type: "linux" + os_distro: "rocky" + os_version: "9.1" + hw_vif_multiqueue_enabled: true + hw_scsi_model: "virtio-scsi" + hw_disk_bus: "scsi" + diff --git a/examples/projects-octavia.yml b/examples/projects-octavia.yml new file mode 100644 index 0000000..f116b18 --- /dev/null +++ b/examples/projects-octavia.yml @@ -0,0 +1,29 @@ +--- +############################################################################### +# Configuration of OpenStack user environment for OpenStack. + +# List of OpenStack projects. Format is as required by the stackhpc.os-projects +# role. +openstack_projects: + - "{{ openstack_service_project }}" + +# Definition of the openstack service project. Format is as required by the +# stackhpc.os-projects role. Quotas are set to unlimited to avoid Octavia load +# balancer creation failing on quota limits. +openstack_service_project: + name: service + project_domain: default + user_domain: default + quotas: "{{ openstack_octavia_unlimited_quotas }}" + +# Dict of quotas to set for service project when Octavia is used. +openstack_octavia_unlimited_quotas: + cores: -1 + fixed_ips: -1 + floatingip: -1 + injected_file_size: -1 + injected_files: -1 + instances: -1 + ram: -1 + security_group: -1 + security_group_rule: -1 diff --git a/examples/projects.yml b/examples/projects.yml index ab5250d..911cbe4 100644 --- a/examples/projects.yml +++ b/examples/projects.yml @@ -57,7 +57,6 @@ openstack_unlimited_quotas: backup_gigabytes: -1 backups: -1 cores: -1 - fixed_ips: -1 floatingip: -1 gigabytes: -1 injected_file_size: -1 diff --git a/requirements.txt b/requirements.txt index bcefbee..0c0c0b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ -# Use Ansible 5 for consistent Rocky 9 behaviour when available, otherwise use Ansible 4 +# Use Ansible 5 for consistent Rocky 9 behaviour when available, otherwise use +# Ansible 4 ansible>=4,<5; python_version<"3.7" -ansible>=5,<6; python_version>="3.7" \ No newline at end of file +ansible>=5,<6; python_version>="3.7" diff --git a/requirements.yml b/requirements.yml index fda082e..bf5cf5a 100644 --- a/requirements.yml +++ b/requirements.yml @@ -1,12 +1,7 @@ --- -roles: - - name: stackhpc.os-flavors - - name: stackhpc.os-images - - name: stackhpc.os-networks - - name: stackhpc.os-projects - - name: stackhpc.os_host_aggregates - - name: stackhpc.os-container-clusters - collections: - name: openstack.cloud - version: '<2' + version: 2.1.0 + - name: stackhpc.openstack + version: 0.1.0 +