{"id":41363471,"url":"https://github.com/platform9/pcd-maas","last_synced_at":"2026-01-23T08:10:23.083Z","repository":{"id":293488212,"uuid":"984203799","full_name":"platform9/pcd-maas","owner":"platform9","description":"MaaS automation for PCD!","archived":false,"fork":false,"pushed_at":"2025-11-27T15:56:00.000Z","size":16866,"stargazers_count":1,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-11-30T08:42:51.356Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/platform9.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-15T14:54:50.000Z","updated_at":"2025-07-29T07:10:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"925e2cb7-004e-4d2a-b4c0-3f955eda8f29","html_url":"https://github.com/platform9/pcd-maas","commit_stats":null,"previous_names":["platform9/pcd-maas"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/platform9/pcd-maas","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/platform9%2Fpcd-maas","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/platform9%2Fpcd-maas/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/platform9%2Fpcd-maas/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/platform9%2Fpcd-maas/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/platform9","download_url":"https://codeload.github.com/platform9/pcd-maas/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/platform9%2Fpcd-maas/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28684014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T05:48:07.525Z","status":"ssl_error","status_checked_at":"2026-01-23T05:48:07.129Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-23T08:10:21.988Z","updated_at":"2026-01-23T08:10:23.075Z","avatar_url":"https://github.com/platform9.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Continuous Integration for this project is done using GitHub Actions.\n\nMore info is [here](./CI.md)\n\n# Adding and deploying a machine to MAAS server, then PCD joining with an automated script \n \n\n### This automation process is split into two sections: \n\n- Automate the process of enrolling baremetals into MaaS \n- Onboarding is done by triggering Ansible playbooks. \n\n \n\n \n\n### How to use?\n\nDownload the script and prerequisite files into the same directory.\n\nScript directory structure:\n```bash\n .\n ├── cloud-init_tempalte.yaml\n ├── machines_tempalte.csv\n ├── vars_template.j2\n ├── main_script.py\n ├── lv_config_template.json \n ├── modules\n │   ├── maasHelper.py  ---\u003e add and deploy machines to MAAS\n │   ├── onboard.py     ---\u003e onboard machines to PCD\n ├── pcd_ansible-pcd_develop\n │   ├── .....\n │   ├── setup-local.sh ---\u003e Set up the  environment for PCD onboarding\n```\n\n\n\n#### Prerequisites: \n    \n1. Maas cli login\n \n        maas login \u003cmaas_user\u003e http://\u003cmaas_ip\u003e:5240/MAAS/ $(sudo maas apikey --generate --username=\u003cmaas_user\u003e)\n\n2. Clouds.yaml created in /{home}/.config/openstack/clouds.yaml\n   ```bash\n        clouds:\n          titan:\n            auth:\n             auth_url: https://\u003cDU-name\u003e.app.staging-pcd.platform9.com/keystone/v3\n             project_name: service\n             username: abc@ACME.com\n             password: *********\n             user_domain_name: default\n             project_domain_name: default\n            region_name: titan\n            interface: public\n            identity_api_version: 3\n            compute_api_version: 2\n            volume_api_version: 3\n            image_api_version: 2\n            identity_interface: public\n            volume_interface: public\n   ```\n3. untar the prerequisites file \n   ```bash\n   tar -xzvf prerequisites.tar.gz\n   ```\n4. Set up the  environment for PCD onboarding by running the script setup-local.sh from inside pcd_ansible-pcd_develop directory.\n   ```bash\n   sudo bash setup-local.sh\n   ```\n       \n 5. You need to create/edit the following files according to your environment before running the script You can use the templates provided in the prerequisites folder:\n\n       1. machines_template.csv\n          ```bash\n          hostname,architecture,mac_addresses,power_type,power_user,power_pass,power_driver,power_address,cipher_suite_id,power_boot_type,privilege_level,k_g,ip,storage_ip,cloud_init\n          pf9-test001,amd64/generic,3c:fd:fe:b5:1a:8d,ipmi,admin,password,LAN_2_0,172.25.1.11,3,auto,ADMIN,,192.168.125.167,192.168.125.165,cloud_init.yaml\n          pf9-test002,amd64/generic,3c:fd:fe:b5:1a:8d,ipmi,admin,password,LAN_2_0,172.25.1.12,3,auto,ADMIN,,192.168.125.168,192.168.125.166,cloud_init2.yaml\n          ```\n          optional fields:\n            1. storage_ip\n            2. cloud_init :  In case you want to provide a different cloud-init template per server, you can add it in the CSV file instead of passing it as an argument via command line.\n\n       3. cloud-init-template.yaml\n          - The only requirement for this file is to have the IP and the storage_ip  as a placeholder to be filled in dynamically for each machine \n          ```bash\n          #cloud-config\n          write_files:\n            - path: /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg\n              permissions: \"0644\"\n              content: |\n                network: {config: disabled}\n          \n            - path: /etc/netplan/99-custom.yaml\n              permissions: \"0644\"\n              content: |\n                network:\n                  version: 2\n                  renderer: networkd\n                  ethernets:\n                    enp94s0f0:\n                      dhcp4: false\n                    enp24s0f1:\n                      dhcp4: false\n                  bonds:\n                    bond0:\n                      interfaces:\n                        - enp24s0f1\n                        - enp94s0f0\n                      parameters:\n                        mode: active-backup\n                        primary: enp24s0f1\n                        mii-monitor-interval: 100\n                      dhcp4: false\n                      addresses:\n                        - $ip/24    --\u003e placeholder for the IP\n                      routes:\n                        - to: default\n                          via: 192.168.125.254\n                      nameservers:\n                        addresses:\n                          - 8.8.8.8\n                  vlans:\n                    vlan.301:  \n                      id: 301  \n                      link: bond0 \n                      addresses:  \n                        - $storage_ip/18     --\u003e placeholder for the storage IP\n                      routes:  \n                        - to: default  \n                          via: 10.10.0.1  \n                      nameservers:  \n                        addresses:  \n                          - 8.8.8.8 \n                          - 1.1.1.1 \n          ```\n          \n       4. lv_config_template.json (in case the --storage_layout flag is set to yes)\n    \n          ```bash\n              {\n              \"vg_group\": \"rootvg\", # the name for the vg group\n              \"boot_efi_size\": \"1G\", \n              \"boot_size\": \"3G\",\n              \"volumes\": [\n                {\"name\": \"home\", \"size\": \"10G\" , \"fs_type\": \"xfs\" , \"mount_point\": \"/home\"},\n                {\"name\": \"opt\", \"size\": \"10G\" , \"fs_type\": \"xfs\" , \"mount_point\": \"/opt\"},\n                {\"name\": \"opt-pf9\", \"size\": \"10G\" , \"fs_type\": \"xfs\" , \"mount_point\": \"/opt/pf9\"},\n                {\"name\": \"swap\", \"size\": \"3G\" , \"fs_type\": \"\" , \"mount_point\": \"\"} ,\n                {\"name\": \"tmp\", \"size\": \"10G\" , \"fs_type\": \"xfs\" , \"mount_point\": \"/tmp\"},\n                {\"name\": \"usr-openv\", \"size\": \"30G\" , \"fs_type\": \"xfs\" , \"mount_point\": \"/usr/openv\"},\n                {\"name\": \"var\", \"size\": \"20G\" , \"fs_type\": \"xfs\" , \"mount_point\": \"/var\"},\n                {\"name\": \"var-log\", \"size\": \"20G\" , \"fs_type\": \"xfs\" , \"mount_point\": \"/var/log\"},\n                {\"name\": \"var-log-audit\", \"size\": \"20G\"  , \"fs_type\": \"xfs\" , \"mount_point\": \"/var/log/audit\"},\n                {\"name\": \"var-tmp\", \"size\": \"5G\" , \"fs_type\": \"xfs\" , \"mount_point\": \"/var/tmp\"},\n                {\"name\": \"root\", \"size\": \"20G\" , \"fs_type\": \"xfs\" , \"mount_point\": \"/\"}\n              ]\n            }\n          ```\n\n  7. Ensure the SSH key for the MAAS server user (used to connect to deployed machines during onboarding) is added in the MAAS UI.\n        \n#### Run the script:  \n\n```bash\n    python3 main_script.py \\\n    --maas_user admin \\\n    --csv_filename machines.csv \\\n    --cloud_init_template cloud-init.yaml \\\n    --portal exalt-pcd \\\n    --region jrs \\\n    --environment stage \\\n    --url https://exalt-pcd-jrs.app.qa-pcd.platform9.com/ \\\n    --max_workers 5 \\\n    --ssh_user ubuntu \\\n    --setup_env yes\n```\nWhat the options mean:\n  - ```--maas_user```: MAAS admin username.\n  - ```--csv_filename```: CSV file path.\n  - ```--cloud_init_template```:  Cloud-init template YAML path. If not provided, it will look for it in the CSV file.\n  - ```--max_workers```: Maximum number of concurrent threads for provisioning.\n  - ```--ssh_user```: SSH user for Ansible.\n  - ```--setup_env```: By default, it's no, but for the first run on the maas machine, it should be yes to set up the necessary directories\n\n    \nThere is an optional argument:\n  - ```--preserve_cloud_init```: By default, it's no, but when set to yes, it will keep all generated cloud-init files under\n    ```bash\n    /{script directory}/maas-cloud-init/cloud-init-{hostname}.yaml\n    ```\n  - ```--storage_layout```: By default, it's no, but if set to yes will allow the storage script to run and create custome storage layout\n  - ```--storage_layout_template```: Required if --storage_layout is set to yes.\n  - ```--onprem```:  If the setup is on-prem, set this to yes.\n  - ```--controller_ip```:  Required if --onprem is set to yes.\n  \nScript directory structure after running the script:\n```bash\n .\n ├── cloud-init_tempalte.yaml\n ├── maas-cloud-init\n │   └── cloud-init-{hostname}.yaml    ---\u003e generated cloud-init files for each machine\n ├── deploy_logs\n │   └── maas_deployment.log           ---\u003e generated logs for MAAS \n ├── machines_tempalte.csv\n ├── {your CSV file name}_updated.csv  ---\u003e updated csv with the status of the deployment\n ├── vars_template.j2\n ├── vars.yaml                         ---\u003e yaml file that will be used by the onboarding Ansible playbooks\n ├── lv_config_template.json\n ├── main_script.py\n ├── modules\n │   ├── maasHelper.py  \n │   ├── onboard.py     \n ├── pcd_ansible-pcd_develop\n │   ├── .....\n │   ├── logs\n │   │   └── pcd_installer_logs\n │   ├── setup-local.sh \n```\n \n#### Script Functionality: \n\n##### 1. It will add the machines to MAAS and commission them.\n\n##### 2. It will create the storage layout incase the flag was set to yes.\n\n##### 3. Deploy the machines once the state is ready \nWhen in ready state, it will generate a cloud-init file for each machine with the IP specified for each one from the CSV file,it will be generated in the tmp directory,and then deploy the OS.\n```bash\n/maas-cloud-init/cloud-init-{hostname}.yaml\n```\nThose files will be deleted once the deployment is done, unless the flag preserve_cloud_init is set to yes\n##### 4. After the deployment is done and successful, the onboarding process will begin. \nAfter deployment, a new CSV file will be generated that contains all the previous info along with the deployment status to ensure that undeployed or uncommissioned machines don't go through the onboarding phase.\n```bash\n{your CSV file name}_updated.csv\n```\n##### 5. Will start by generating a vars.yaml file, which contains all the necessary information about each host, using Jinja2 \n  - Loads a template (vars_template.j2) and fills it with the extracted data. \n  - Saves the rendered YAML to vars.yaml.\n    \nsample vars.yaml:\n```bash\nurl: https://exalt-pcd-jrs.app.qa-pcd.platform9.com/\ncloud: jrs\nenvironment: stage\nhosts:\n  192.168.125.165:\n    ansible_ssh_user: \"ubuntu\"\n    ansible_ssh_private_key_file: \"/home/exalt/.ssh/id_rsa\"\n    roles:\n      - \"node_onboard\"\n``` \n\n##### 6. Copying vars.yml to Ansible Playbook Directory \nIt will copy the vars file to user_resource_examples/templates/host_onboard_data.yaml.j2, where the Ansible playbooks will use this file  \n\n\n##### 7. Executing Ansible Playbooks for PCD Host Onboarding  \n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplatform9%2Fpcd-maas","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplatform9%2Fpcd-maas","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplatform9%2Fpcd-maas/lists"}