<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.bwcloud-os.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sia</id>
	<title>bwCloud-OS - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.bwcloud-os.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sia"/>
	<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php/Special:Contributions/Sia"/>
	<updated>2026-05-31T00:29:33Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Cloud_Migration_Guide&amp;diff=2267</id>
		<title>Cloud Migration Guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Cloud_Migration_Guide&amp;diff=2267"/>
		<updated>2026-05-28T09:52:34Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;mw-message-box mw-message-box-warning&amp;quot;&lt;br /&gt;
| style=&amp;quot;vertical-align:middle;&amp;quot; | &#039;&#039;&#039;⚠️ Please Note:&#039;&#039;&#039; This guide is still work in progress. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-message-box mw-message-box-warning&amp;quot;&lt;br /&gt;
| style=&amp;quot;vertical-align:middle;&amp;quot; | &#039;&#039;&#039;⚠️ IMPORTANT SHUTDOWN NOTICE:&#039;&#039;&#039; &lt;br /&gt;
The Gen2 infrastructure will be permanently shut down in &#039;&#039;&#039;September 2026&#039;&#039;&#039; (refer to the [https://bwcloud-os.de/ &#039;&#039;&#039;bwCloud-OS website&#039;&#039;&#039;] for the exact date). All projects and data that have not been migrated to Gen3 by this date will be irrevocably deleted. To use Gen3, you must clarify and apply for your entitlements (which are subject to costs) in a timely manner.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;There is no automatic migration path: Gen2 and Gen3 are completely separate environments.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Migration requires a new entitlement.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Security Groups and IP addresses will change and must be reconfigured manually.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;&#039;Recommended approach:&#039;&#039;&#039; Start a new, fresh instance (VM) in Gen3 and copy your old data over the network (e.g., via rsync).&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= General Information =&lt;br /&gt;
&lt;br /&gt;
This guide explains how to migrate your resources from the old bwCloud-OS Gen2 environment to bwCloud-OS Gen3. Because the two environments are completely separated, there is no automatic migration path. You will need to manually export your resources from the old cloud, download them locally, and upload them to the new cloud. Please note that network settings and Security Groups cannot be copied and must be reconfigured manually in the new environment.&lt;br /&gt;
&lt;br /&gt;
== Important Prerequisites: Entitlements and Quotas ==&lt;br /&gt;
The new bwCloud-OS Gen3 will become a paid infrastructure platform. Therefore, it is necessary for each participating university or institution to actively assign the corresponding entitlements to its users. You cannot simply transfer your old projects directly without this authorization.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Missing Entitlement?&#039;&#039;&#039; If you have not yet been assigned an entitlement, please get in touch directly with your local institution or university&#039;s IT support. &lt;br /&gt;
* &#039;&#039;&#039;Quota Allocation:&#039;&#039;&#039; Please note that the allocation of resource quotas is entirely managed and regulated through your respective institution.&lt;br /&gt;
&lt;br /&gt;
Details can be found [https://wiki.bwcloud-os.de/index.php/Guide:_Entitlement_%26_Eligibility here].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-message-box mw-message-box-notice&amp;quot;&lt;br /&gt;
| style=&amp;quot;vertical-align:middle;&amp;quot; | &#039;&#039;&#039;ℹ️ Note on Group Projects:&#039;&#039;&#039; Currently, there is no established process for complex group projects and their corresponding quota allocation. If you require resources for such a project, we kindly ask for a little more patience until the procedures are fully defined.&lt;br /&gt;
|}&lt;br /&gt;
== Dashboard Login ==&lt;br /&gt;
* [https://portal.bw-cloud.org/ Old bwCloud-OS Gen2]&lt;br /&gt;
* [https://portal.ul.bwcos.de/auth/login/?next=/%20https://portal.ul.bwcos.de/ New bwCloud-OS Gen3]&lt;br /&gt;
== Networks ==&lt;br /&gt;
The new infrastructure includes not only new networks but also new network-related features such as load balancers. You can find an overview [[Networks_Gen3|here]].&lt;br /&gt;
&lt;br /&gt;
Network-specific differences between regions and details about the individual networks can be found in the following guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
➡️ [[Guide:_Network_Configuration_by_Region|Guide: Network Configuration by Region]]&lt;br /&gt;
&lt;br /&gt;
= Transferring Data and VMs= &lt;br /&gt;
&lt;br /&gt;
There are basically two ways to transfer your data to the new bwCloud-OS (Gen3): The rsync method over the network and the snapshot method. &lt;br /&gt;
&lt;br /&gt;
== Transferring Volumes ==&lt;br /&gt;
&lt;br /&gt;
While it is technically possible to migrate a Cinder volume by converting it to an image and uploading it to the new cloud, we do not recommend this approach. The process is extremely slow, and depending on the backend configuration, the upload may silently fail entirely.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Our recommendation: create a fresh volume and copy your data over the network.&#039;&#039;&#039;&lt;br /&gt;
* In the new environment, create a new empty volume of the appropriate size and attach it to a new VM.&lt;br /&gt;
* Format and mount the volume on the new VM. Detailed instructions can be found [[Guide:_Volumes_and_Images#Create_and_Attach_a_Volume|here]]. &lt;br /&gt;
* Make sure your old VM (with the old volume mounted) is reachable from the new VM via SSH (either by exchanging SSH keys or setting a password in the VM). &lt;br /&gt;
* Sync your data directly over the network using &#039;&#039;&#039;rsync&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -avz --progress /path/to/old/data/ root@&amp;lt;NEW_VM_IP&amp;gt;:/path/to/new/destination/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transferring VMs ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
* Access to both bwCloud-OS environments and &lt;br /&gt;
* Application Credentials, as described [[Programmatic_Access_and_Automation#Application_Credentials|here]] and&lt;br /&gt;
* OpenStack Client installed, as described [[Programmatic_Access_and_Automation#OpenStack_Client|here]].&lt;br /&gt;
&lt;br /&gt;
=== Procedure ===&lt;br /&gt;
&lt;br /&gt;
When transferring a VM, you create a snapshot of its current state, download it, and use it as a base image in the new environment.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 1: Create a Snapshot&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First, source your old bwCloud-OS Gen2 credentials and find the ID of the instance (VM) you want to migrate: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
source old-creds.sh &lt;br /&gt;
openstack server list &lt;br /&gt;
openstack server image create --name &amp;lt;snapshot_name&amp;gt; &amp;lt;instance_id&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 2: Download the Snapshot&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Image ID should have been prompted in the previous step. However, it is also possible to find the ID of your created snapshot and download it to your local computer later:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image list&lt;br /&gt;
openstack image save --file myimage.img &amp;lt;snapshot_id&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 3: Upload to the New Environment (bwCloud-OS Gen3)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Source your new cloud credentials and upload the image file. &#039;&#039;&#039;Important&#039;&#039;&#039;: Always set the visibility to Private so other users cannot use your image as a base for their services.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
source new-creds.sh&lt;br /&gt;
openstack image create --file myimage.img --private myimage&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternative: You can also upload the downloaded .img file using the new Horizon GUI by navigating to &#039;&#039;&#039;Compute -&amp;gt; Images&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 4: Start the Instance&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can now start a new instance using this uploaded image. Remember to reconfigure your &#039;&#039;&#039;Security Groups&#039;&#039;&#039; and note that you will receive a &#039;&#039;&#039;new IP address&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To start a new instance: &lt;br /&gt;
* Log in to the bwCloud-OS Gen3 Dashboard. &lt;br /&gt;
* Navigate to Project --&amp;gt; Compute --&amp;gt; Images. The uploaded snapshot should be listed there.&lt;br /&gt;
* Click on &amp;quot;Start&amp;quot;, choose an instance name, and select the network and SSH key (or create a new one).&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Cloud_Migration_Guide&amp;diff=2266</id>
		<title>Cloud Migration Guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Cloud_Migration_Guide&amp;diff=2266"/>
		<updated>2026-05-28T09:51:00Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;mw-message-box mw-message-box-warning&amp;quot;&lt;br /&gt;
| style=&amp;quot;vertical-align:middle;&amp;quot; | &#039;&#039;&#039;⚠️ Please Note:&#039;&#039;&#039; This guide is still work in progress. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-message-box mw-message-box-warning&amp;quot;&lt;br /&gt;
| style=&amp;quot;vertical-align:middle;&amp;quot; | &#039;&#039;&#039;⚠️ IMPORTANT SHUTDOWN NOTICE:&#039;&#039;&#039; &lt;br /&gt;
The Gen2 infrastructure will be permanently shut down in &#039;&#039;&#039;September 2026&#039;&#039;&#039; (refer to the [https://bwcloud-os.de/ &#039;&#039;&#039;bwCloud-OS website&#039;&#039;&#039;] for the exact date). All projects and data that have not been migrated by this date will be irrevocably deleted. To use Gen3, you must clarify and apply for your entitlements (which are subject to costs) in a timely manner.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;There is no automatic migration path: Gen2 and Gen3 are completely separate environments.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Migration requires a new entitlement.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Security Groups and IP addresses will change and must be reconfigured manually.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;&#039;Recommended approach:&#039;&#039;&#039; Start a new, fresh instance (VM) in Gen3 and copy your old data over the network (e.g., via rsync).&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= General Information =&lt;br /&gt;
&lt;br /&gt;
This guide explains how to migrate your resources from the old bwCloud-OS Gen2 environment to bwCloud-OS Gen3. Because the two environments are completely separated, there is no automatic migration path. You will need to manually export your resources from the old cloud, download them locally, and upload them to the new cloud. Please note that network settings and Security Groups cannot be copied and must be reconfigured manually in the new environment.&lt;br /&gt;
&lt;br /&gt;
== Important Prerequisites: Entitlements and Quotas ==&lt;br /&gt;
The new bwCloud-OS Gen3 will become a paid infrastructure platform. Therefore, it is necessary for each participating university or institution to actively assign the corresponding entitlements to its users. You cannot simply transfer your old projects directly without this authorization.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Missing Entitlement?&#039;&#039;&#039; If you have not yet been assigned an entitlement, please get in touch directly with your local institution or university&#039;s IT support. &lt;br /&gt;
* &#039;&#039;&#039;Quota Allocation:&#039;&#039;&#039; Please note that the allocation of resource quotas is entirely managed and regulated through your respective institution.&lt;br /&gt;
&lt;br /&gt;
Details can be found [https://wiki.bwcloud-os.de/index.php/Guide:_Entitlement_%26_Eligibility here].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-message-box mw-message-box-notice&amp;quot;&lt;br /&gt;
| style=&amp;quot;vertical-align:middle;&amp;quot; | &#039;&#039;&#039;ℹ️ Note on Group Projects:&#039;&#039;&#039; Currently, there is no established process for complex group projects and their corresponding quota allocation. If you require resources for such a project, we kindly ask for a little more patience until the procedures are fully defined.&lt;br /&gt;
|}&lt;br /&gt;
== Dashboard Login ==&lt;br /&gt;
* [https://portal.bw-cloud.org/ Old bwCloud-OS Gen2]&lt;br /&gt;
* [https://portal.ul.bwcos.de/auth/login/?next=/%20https://portal.ul.bwcos.de/ New bwCloud-OS Gen3]&lt;br /&gt;
== Networks ==&lt;br /&gt;
The new infrastructure includes not only new networks but also new network-related features such as load balancers. You can find an overview [[Networks_Gen3|here]].&lt;br /&gt;
&lt;br /&gt;
Network-specific differences between regions and details about the individual networks can be found in the following guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
➡️ [[Guide:_Network_Configuration_by_Region|Guide: Network Configuration by Region]]&lt;br /&gt;
&lt;br /&gt;
= Transferring Data and VMs= &lt;br /&gt;
&lt;br /&gt;
There are basically two ways to transfer your data to the new bwCloud-OS (Gen3): The rsync method over the network and the snapshot method. &lt;br /&gt;
&lt;br /&gt;
== Transferring Volumes ==&lt;br /&gt;
&lt;br /&gt;
While it is technically possible to migrate a Cinder volume by converting it to an image and uploading it to the new cloud, we do not recommend this approach. The process is extremely slow, and depending on the backend configuration, the upload may silently fail entirely.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Our recommendation: create a fresh volume and copy your data over the network.&#039;&#039;&#039;&lt;br /&gt;
* In the new environment, create a new empty volume of the appropriate size and attach it to a new VM.&lt;br /&gt;
* Format and mount the volume on the new VM. Detailed instructions can be found [[Guide:_Volumes_and_Images#Create_and_Attach_a_Volume|here]]. &lt;br /&gt;
* Make sure your old VM (with the old volume mounted) is reachable from the new VM via SSH (either by exchanging SSH keys or setting a password in the VM). &lt;br /&gt;
* Sync your data directly over the network using &#039;&#039;&#039;rsync&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -avz --progress /path/to/old/data/ root@&amp;lt;NEW_VM_IP&amp;gt;:/path/to/new/destination/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transferring VMs ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
* Access to both bwCloud-OS environments and &lt;br /&gt;
* Application Credentials, as described [[Programmatic_Access_and_Automation#Application_Credentials|here]] and&lt;br /&gt;
* OpenStack Client installed, as described [[Programmatic_Access_and_Automation#OpenStack_Client|here]].&lt;br /&gt;
&lt;br /&gt;
=== Procedure ===&lt;br /&gt;
&lt;br /&gt;
When transferring a VM, you create a snapshot of its current state, download it, and use it as a base image in the new environment.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 1: Create a Snapshot&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First, source your old bwCloud-OS Gen2 credentials and find the ID of the instance (VM) you want to migrate: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
source old-creds.sh &lt;br /&gt;
openstack server list &lt;br /&gt;
openstack server image create --name &amp;lt;snapshot_name&amp;gt; &amp;lt;instance_id&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 2: Download the Snapshot&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Image ID should have been prompted in the previous step. However, it is also possible to find the ID of your created snapshot and download it to your local computer later:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image list&lt;br /&gt;
openstack image save --file myimage.img &amp;lt;snapshot_id&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 3: Upload to the New Environment (bwCloud-OS Gen3)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Source your new cloud credentials and upload the image file. &#039;&#039;&#039;Important&#039;&#039;&#039;: Always set the visibility to Private so other users cannot use your image as a base for their services.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
source new-creds.sh&lt;br /&gt;
openstack image create --file myimage.img --private myimage&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternative: You can also upload the downloaded .img file using the new Horizon GUI by navigating to &#039;&#039;&#039;Compute -&amp;gt; Images&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 4: Start the Instance&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can now start a new instance using this uploaded image. Remember to reconfigure your &#039;&#039;&#039;Security Groups&#039;&#039;&#039; and note that you will receive a &#039;&#039;&#039;new IP address&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To start a new instance: &lt;br /&gt;
* Log in to the bwCloud-OS Gen3 Dashboard. &lt;br /&gt;
* Navigate to Project --&amp;gt; Compute --&amp;gt; Images. The uploaded snapshot should be listed there.&lt;br /&gt;
* Click on &amp;quot;Start&amp;quot;, choose an instance name, and select the network and SSH key (or create a new one).&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_Network_Configuration_by_Region&amp;diff=2265</id>
		<title>Guide: Network Configuration by Region</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_Network_Configuration_by_Region&amp;diff=2265"/>
		<updated>2026-05-28T09:48:56Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
This guide provides details of the VM networks in each &#039;&#039;&#039;[[Registration#Regions|bwCloud-OS region]]&#039;&#039;&#039;. It describes which networks are available by default, which can be requested, and how IPv4 and IPv6 connectivity is provided. &lt;br /&gt;
&lt;br /&gt;
While core networking concepts are consistent across regions, available networks, IP address ranges, and access methods may differ. Please refer to the section for your specific region.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Freiburg ==&lt;br /&gt;
*Information for this region will be provided soon.*&lt;br /&gt;
&lt;br /&gt;
== Karlsruhe ==&lt;br /&gt;
The Karlsruhe region provides a &#039;&#039;&#039;default routed network&#039;&#039;&#039;, as well as additional networks that can be assigned to projects upon request.&lt;br /&gt;
&lt;br /&gt;
=== Default Network ===&lt;br /&gt;
&lt;br /&gt;
* All projects have access to the default network &amp;lt;code&amp;gt;default-network&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Instances connected to this network receive:&lt;br /&gt;
** A &#039;&#039;&#039;public IPv6 address&#039;&#039;&#039;&lt;br /&gt;
** A &#039;&#039;&#039;private IPv4 address&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
This is a &#039;&#039;&#039;routed network&#039;&#039;&#039; using an OpenStack router connected to an external provider network.&lt;br /&gt;
&lt;br /&gt;
* IPv6: Direct public connectivity&lt;br /&gt;
* IPv4 (egress): Provided via &#039;&#039;&#039;SNAT&#039;&#039;&#039; through the router&lt;br /&gt;
* IPv4 (ingress): Not available by default (see [[Guide: Network Configuration by Region#IPv4 Ingress via Floating IPs|&#039;&#039;&#039;IPv4 Ingress via Floating IPs&#039;&#039;&#039;]])&lt;br /&gt;
* This Network is shared between all projects&lt;br /&gt;
=== IPv4 Ingress via Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; are allocated from the external network &amp;lt;code&amp;gt;provider-network&amp;lt;/code&amp;gt;.&lt;br /&gt;
* They can be assigned to projects upon request via a &#039;&#039;&#039;[https://bw-support.scc.kit.edu/ support ticket]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Once assigned, a Floating IP can be associated with an instance to provide IPv4 ingress connectivity.&lt;br /&gt;
&lt;br /&gt;
=== Separated Networks ===&lt;br /&gt;
If you require a separated Broadcast Domain you can request one via a &#039;&#039;&#039;[https://bw-support.scc.kit.edu/ support ticket]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The network will:&lt;br /&gt;
&lt;br /&gt;
* receive a separate private IPv4 Subnet&lt;br /&gt;
* receive a separate public IPv6 Subnet&lt;br /&gt;
* have a separated Broadcast Domain only accessible by authorized projects&lt;br /&gt;
* always use up at least one public IPv4 used for the virtual Router&lt;br /&gt;
&lt;br /&gt;
=== Migration from Gen2 to Gen3 ===&lt;br /&gt;
&lt;br /&gt;
The Karlsruhe region is currently operating two environments in parallel:&lt;br /&gt;
&lt;br /&gt;
* Gen2 (legacy cloud)&lt;br /&gt;
* Gen3 (current bwCloud-OS environment)&lt;br /&gt;
&lt;br /&gt;
This setup allows users to migrate their instances and data from Gen2 to Gen3.&lt;br /&gt;
&lt;br /&gt;
* The coexistence period will last until September 2026. Refer to the [https://bwcloud-os.de/ bwCloud-OS website] for the exact date.&lt;br /&gt;
&lt;br /&gt;
After the transition period:&lt;br /&gt;
&lt;br /&gt;
* All IP addresses (Routers and Floating IPs) from &amp;lt;code&amp;gt;provider-network&amp;lt;/code&amp;gt; will be migrated to a new IPv4 Subnet. &lt;br /&gt;
* This migration will be performed by administrators; no user action is required.&lt;br /&gt;
* During the Migration all Floating IPs will be redistributed and some minor connection interruptions will happen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Mannheim ==&lt;br /&gt;
&lt;br /&gt;
The Mannheim region provides a &#039;&#039;&#039;default routed network&#039;&#039;&#039;, as well as &#039;&#039;&#039;additional networks&#039;&#039;&#039; that can be assigned to projects &#039;&#039;&#039;upon request&#039;&#039;&#039;. Both IPv6 and IPv4 connectivity options are available, depending on the selected network.&lt;br /&gt;
&lt;br /&gt;
=== Default Network ===&lt;br /&gt;
&lt;br /&gt;
* All projects have access to the default network &amp;lt;code&amp;gt;routed_default_net&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Instances connected to this network receive:&lt;br /&gt;
** A &#039;&#039;&#039;public IPv6 address&#039;&#039;&#039;&lt;br /&gt;
** A &#039;&#039;&#039;private IPv4 address&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
This is a &#039;&#039;&#039;routed network&#039;&#039;&#039; using an OpenStack router connected to an external provider network:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;IPv6&#039;&#039;&#039;: Direct public connectivity&lt;br /&gt;
* &#039;&#039;&#039;IPv4 (egress)&#039;&#039;&#039;: Provided via &#039;&#039;&#039;SNAT&#039;&#039;&#039; through the router&lt;br /&gt;
* IPv4 (ingress): Not available by default (see [[Guide: Network Configuration by Region#IPv4 Ingress via Floating IPs|&#039;&#039;&#039;IPv4 Ingress via Floating IPs&#039;&#039;&#039;]])&lt;br /&gt;
📌 &#039;&#039;&#039;Note:&#039;&#039;&#039; This network extends the legacy IPv6-only network in the Mannheim region, which did not provide IPv4 connectivity. &#039;&#039;Before requesting an IPv4 address via a support ticket, please ensure that the combined connectivity is not already sufficient for your use case.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== IPv4 Ingress via Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; are allocated from the external network &amp;lt;code&amp;gt;provider_default_net&amp;lt;/code&amp;gt;.&lt;br /&gt;
* They can be assigned to projects upon request via a &#039;&#039;&#039;[https://bw-support.scc.kit.edu/ support ticket]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Once assigned to a project, a Floating IP can be associated with an instance to provide &#039;&#039;&#039;IPv4 ingress connectivity&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Flat External Networks ===&lt;br /&gt;
&lt;br /&gt;
* There are also flat external networks available, such as &amp;lt;code&amp;gt;provider_interim_net&amp;lt;/code&amp;gt; .&lt;br /&gt;
* They can be assigned to projects via a &#039;&#039;&#039;[https://bw-support.scc.kit.edu/ support ticket]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Instances connected directly to this type of network receive:&lt;br /&gt;
&lt;br /&gt;
* A &#039;&#039;&#039;public IPv4 address&#039;&#039;&#039;&lt;br /&gt;
* A &#039;&#039;&#039;public IPv6 address&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This enables dual-stack public connectivity (IPv4 and IPv6) without the need for Floating IPs.&lt;br /&gt;
&lt;br /&gt;
=== Migration from Gen2 to Gen3 ===&lt;br /&gt;
&lt;br /&gt;
The Mannheim region is currently operating two environments in parallel:&lt;br /&gt;
&lt;br /&gt;
* Gen2 (legacy cloud)&lt;br /&gt;
* Gen3 (current bwCloud-OS environment)&lt;br /&gt;
&lt;br /&gt;
This setup allows users to migrate their instances and data from Gen2 to Gen3.&lt;br /&gt;
&lt;br /&gt;
* The coexistence period will last until September 2026. Refer to the [https://bwcloud-os.de/ bwCloud-OS website] for the exact date.&lt;br /&gt;
* During this period, &amp;lt;code&amp;gt;provider_interim_net&amp;lt;/code&amp;gt; is used as the flat external network.&lt;br /&gt;
&lt;br /&gt;
After the transition period:&lt;br /&gt;
&lt;br /&gt;
* All dual-stack IP addresses from &amp;lt;code&amp;gt;provider_interim_net&amp;lt;/code&amp;gt; will be migrated to &amp;lt;code&amp;gt;provider_default_net&amp;lt;/code&amp;gt;. This migration will be performed by administrators; no user action is required.&lt;br /&gt;
* Projects requiring a flat external network will be assigned &amp;lt;code&amp;gt;provider_default_net&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
📌 &#039;&#039;&#039;Note:&#039;&#039;&#039; We do not recommend allocating Floating IPs from the &amp;lt;code&amp;gt;provider_interim_net&amp;lt;/code&amp;gt;, because they will be lost after the transition period. Instead, request and associate them from &amp;lt;code&amp;gt;provider_default_net&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ulm ==&lt;br /&gt;
&lt;br /&gt;
=== Default Network ===&lt;br /&gt;
&lt;br /&gt;
* All projects have access to the default network &amp;lt;code&amp;gt;virt-shared&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Instances connected to this network receive:&lt;br /&gt;
** A &#039;&#039;&#039;public global IPv6 address&#039;&#039;&#039;&lt;br /&gt;
** A &#039;&#039;&#039;private NAT-ed IPv4 address&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a &#039;&#039;&#039;routed network&#039;&#039;&#039; using an OpenStack router connected to an external provider network:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;IPv6&#039;&#039;&#039;: Direct public connectivity&lt;br /&gt;
* &#039;&#039;&#039;IPv4 (egress)&#039;&#039;&#039;: Provided via &#039;&#039;&#039;SNAT&#039;&#039;&#039; through the router&lt;br /&gt;
* &#039;&#039;&#039;IPv4 (ingress)&#039;&#039;&#039;: Optional and possible via &#039;&#039;&#039;Floating IPs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== IPv4 Ingress via Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
* Optional &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; can allocated from the external network &amp;lt;code&amp;gt;public-link&amp;lt;/code&amp;gt; quota permitting.&lt;br /&gt;
* Once assigned to a project, a &#039;&#039;&#039;Floating IP&#039;&#039;&#039; can be associated with an instance to provide &#039;&#039;&#039;IPv4 ingress connectivity&#039;&#039;&#039; for that instance.&lt;br /&gt;
* Incoming requests to the &#039;&#039;&#039;Floating IP&#039;&#039;&#039; will be relayed by the router to the instance&#039;s private IPv4 and vice-versa (&#039;&#039;&#039;DNAT&#039;&#039;&#039; + &#039;&#039;&#039;SNAT&#039;&#039;&#039;).&lt;br /&gt;
* The instance internally only sees its private IPv4, but through the &#039;&#039;&#039;Floating IP&#039;&#039;&#039; external requests will arrive at its private IPv4.&lt;br /&gt;
&lt;br /&gt;
=== Flat External Networks ===&lt;br /&gt;
&lt;br /&gt;
* There are no flat networks available to users in region Ulm.&lt;br /&gt;
&lt;br /&gt;
=== Per Project Networks ===&lt;br /&gt;
&lt;br /&gt;
* If a project with multiple VMs wishes to use a separate network instead of relying on the &amp;lt;code&amp;gt;virt-shared&amp;lt;/code&amp;gt; network, it is possible to allocate a private network.&lt;br /&gt;
* Private networks have the same properties and limitations as the shared &amp;lt;code&amp;gt;virt-shared&amp;lt;/code&amp;gt; network, but receive a smaller private IPv4 range and are not shared with other projects.&lt;br /&gt;
* Private networks need to be connected the the internal side of a private router with the external side connected to &amp;lt;code&amp;gt;public-link&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A VM in a dual-stacked private network will receive a private, NAT-ed IPv4 and a public, global IPv6 address.&lt;br /&gt;
** A unique, private IPv4 /26 range can be allocated from the subnet pool &amp;lt;code&amp;gt;tenant-v4-16-26&amp;lt;/code&amp;gt;.&lt;br /&gt;
** A unique, public IPv6 /64 range can be allocated from the subnet pool &amp;lt;code&amp;gt;tenant-v6-48-64&amp;lt;/code&amp;gt;. &lt;br /&gt;
* Optional &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; from &amp;lt;code&amp;gt;public-link&amp;lt;/code&amp;gt; can be used for IPv4 ingress, just like with the default &amp;lt;code&amp;gt;virt-shared&amp;lt;/code&amp;gt; network.&lt;br /&gt;
* The only meaningful advantage of a per project network is that is not shared with VMs from other projects.&lt;br /&gt;
&lt;br /&gt;
=== Network Renumbering ===&lt;br /&gt;
&lt;br /&gt;
* The IPv4 range that Gen3 region Ulm starts with initially is only temporary and will be replaced with an IPv4 range that is currently still in-use in Gen2 region Ulm, once Gen2 shuts down.&lt;br /&gt;
** During that IPv4 renumbering all IPv4 &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; will be removed.&lt;br /&gt;
** Afterwards new IPv4 &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; can be allocated from &amp;lt;code&amp;gt;public-link&amp;lt;/code&amp;gt;.&lt;br /&gt;
** This affects &amp;lt;code&amp;gt;virt-shared&amp;lt;/code&amp;gt; and all per project networks.&lt;br /&gt;
** IPv6 ranges and addresses will remain unchanged.&lt;br /&gt;
** private IPv4 ranges and addresses will remain unchanged.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_Network_Configuration_by_Region&amp;diff=2264</id>
		<title>Guide: Network Configuration by Region</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_Network_Configuration_by_Region&amp;diff=2264"/>
		<updated>2026-05-28T09:43:31Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
This guide provides details of the VM networks in each &#039;&#039;&#039;[[Registration#Regions|bwCloud-OS region]]&#039;&#039;&#039;. It describes which networks are available by default, which can be requested, and how IPv4 and IPv6 connectivity is provided. &lt;br /&gt;
&lt;br /&gt;
While core networking concepts are consistent across regions, available networks, IP address ranges, and access methods may differ. Please refer to the section for your specific region.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Freiburg ==&lt;br /&gt;
*Information for this region will be provided soon.*&lt;br /&gt;
&lt;br /&gt;
== Karlsruhe ==&lt;br /&gt;
The Karlsruhe region provides a &#039;&#039;&#039;default routed network&#039;&#039;&#039;, as well as additional networks that can be assigned to projects upon request.&lt;br /&gt;
&lt;br /&gt;
=== Default Network ===&lt;br /&gt;
&lt;br /&gt;
* All projects have access to the default network &amp;lt;code&amp;gt;default-network&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Instances connected to this network receive:&lt;br /&gt;
** A &#039;&#039;&#039;public IPv6 address&#039;&#039;&#039;&lt;br /&gt;
** A &#039;&#039;&#039;private IPv4 address&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
This is a &#039;&#039;&#039;routed network&#039;&#039;&#039; using an OpenStack router connected to an external provider network.&lt;br /&gt;
&lt;br /&gt;
* IPv6: Direct public connectivity&lt;br /&gt;
* IPv4 (egress): Provided via &#039;&#039;&#039;SNAT&#039;&#039;&#039; through the router&lt;br /&gt;
* IPv4 (ingress): Not available by default (see [[Guide: Network Configuration by Region#IPv4 Ingress via Floating IPs|&#039;&#039;&#039;IPv4 Ingress via Floating IPs&#039;&#039;&#039;]])&lt;br /&gt;
* This Network is shared between all projects&lt;br /&gt;
=== IPv4 Ingress via Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; are allocated from the external network &amp;lt;code&amp;gt;provider-network&amp;lt;/code&amp;gt;.&lt;br /&gt;
* They can be assigned to projects upon request via a &#039;&#039;&#039;[https://bw-support.scc.kit.edu/ support ticket]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Once assigned, a Floating IP can be associated with an instance to provide IPv4 ingress connectivity.&lt;br /&gt;
&lt;br /&gt;
=== Separated Networks ===&lt;br /&gt;
If you require a separated Broadcast Domain you can request one via a &#039;&#039;&#039;[https://bw-support.scc.kit.edu/ support ticket]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The network will:&lt;br /&gt;
&lt;br /&gt;
* receive a separate private IPv4 Subnet&lt;br /&gt;
* receive a separate public IPv6 Subnet&lt;br /&gt;
* have a separated Broadcast Domain only accessible by authorized projects&lt;br /&gt;
* always use up at least one public IPv4 used for the virtual Router&lt;br /&gt;
&lt;br /&gt;
=== Migration from Gen2 to Gen3 ===&lt;br /&gt;
&lt;br /&gt;
The Karlsruhe region is currently operating two environments in parallel:&lt;br /&gt;
&lt;br /&gt;
* Gen2 (legacy cloud)&lt;br /&gt;
* Gen3 (current bwCloud-OS environment)&lt;br /&gt;
&lt;br /&gt;
This setup allows users to migrate their instances and data from Gen2 to Gen3.&lt;br /&gt;
&lt;br /&gt;
* The coexistence period will last until 15. September 2026.&lt;br /&gt;
&lt;br /&gt;
After the transition period:&lt;br /&gt;
&lt;br /&gt;
* All IP addresses (Routers and Floating IPs) from &amp;lt;code&amp;gt;provider-network&amp;lt;/code&amp;gt; will be migrated to a new IPv4 Subnet. &lt;br /&gt;
* This migration will be performed by administrators; no user action is required.&lt;br /&gt;
* During the Migration all Floating IPs will be redistributed and some minor connection interruptions will happen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Mannheim ==&lt;br /&gt;
&lt;br /&gt;
The Mannheim region provides a &#039;&#039;&#039;default routed network&#039;&#039;&#039;, as well as &#039;&#039;&#039;additional networks&#039;&#039;&#039; that can be assigned to projects &#039;&#039;&#039;upon request&#039;&#039;&#039;. Both IPv6 and IPv4 connectivity options are available, depending on the selected network.&lt;br /&gt;
&lt;br /&gt;
=== Default Network ===&lt;br /&gt;
&lt;br /&gt;
* All projects have access to the default network &amp;lt;code&amp;gt;routed_default_net&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Instances connected to this network receive:&lt;br /&gt;
** A &#039;&#039;&#039;public IPv6 address&#039;&#039;&#039;&lt;br /&gt;
** A &#039;&#039;&#039;private IPv4 address&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
This is a &#039;&#039;&#039;routed network&#039;&#039;&#039; using an OpenStack router connected to an external provider network:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;IPv6&#039;&#039;&#039;: Direct public connectivity&lt;br /&gt;
* &#039;&#039;&#039;IPv4 (egress)&#039;&#039;&#039;: Provided via &#039;&#039;&#039;SNAT&#039;&#039;&#039; through the router&lt;br /&gt;
* IPv4 (ingress): Not available by default (see [[Guide: Network Configuration by Region#IPv4 Ingress via Floating IPs|&#039;&#039;&#039;IPv4 Ingress via Floating IPs&#039;&#039;&#039;]])&lt;br /&gt;
📌 &#039;&#039;&#039;Note:&#039;&#039;&#039; This network extends the legacy IPv6-only network in the Mannheim region, which did not provide IPv4 connectivity. &#039;&#039;Before requesting an IPv4 address via a support ticket, please ensure that the combined connectivity is not already sufficient for your use case.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== IPv4 Ingress via Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; are allocated from the external network &amp;lt;code&amp;gt;provider_default_net&amp;lt;/code&amp;gt;.&lt;br /&gt;
* They can be assigned to projects upon request via a &#039;&#039;&#039;[https://bw-support.scc.kit.edu/ support ticket]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Once assigned to a project, a Floating IP can be associated with an instance to provide &#039;&#039;&#039;IPv4 ingress connectivity&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Flat External Networks ===&lt;br /&gt;
&lt;br /&gt;
* There are also flat external networks available, such as &amp;lt;code&amp;gt;provider_interim_net&amp;lt;/code&amp;gt; .&lt;br /&gt;
* They can be assigned to projects via a &#039;&#039;&#039;[https://bw-support.scc.kit.edu/ support ticket]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Instances connected directly to this type of network receive:&lt;br /&gt;
&lt;br /&gt;
* A &#039;&#039;&#039;public IPv4 address&#039;&#039;&#039;&lt;br /&gt;
* A &#039;&#039;&#039;public IPv6 address&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This enables dual-stack public connectivity (IPv4 and IPv6) without the need for Floating IPs.&lt;br /&gt;
&lt;br /&gt;
=== Migration from Gen2 to Gen3 ===&lt;br /&gt;
&lt;br /&gt;
The Mannheim region is currently operating two environments in parallel:&lt;br /&gt;
&lt;br /&gt;
* Gen2 (legacy cloud)&lt;br /&gt;
* Gen3 (current bwCloud-OS environment)&lt;br /&gt;
&lt;br /&gt;
This setup allows users to migrate their instances and data from Gen2 to Gen3.&lt;br /&gt;
&lt;br /&gt;
* The coexistence period will last until 31. August 2026.&lt;br /&gt;
* During this period, &amp;lt;code&amp;gt;provider_interim_net&amp;lt;/code&amp;gt; is used as the flat external network.&lt;br /&gt;
&lt;br /&gt;
After the transition period:&lt;br /&gt;
&lt;br /&gt;
* All dual-stack IP addresses from &amp;lt;code&amp;gt;provider_interim_net&amp;lt;/code&amp;gt; will be migrated to &amp;lt;code&amp;gt;provider_default_net&amp;lt;/code&amp;gt;. This migration will be performed by administrators; no user action is required.&lt;br /&gt;
* Projects requiring a flat external network will be assigned &amp;lt;code&amp;gt;provider_default_net&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
📌 &#039;&#039;&#039;Note:&#039;&#039;&#039; We do not recommend allocating Floating IPs from the &amp;lt;code&amp;gt;provider_interim_net&amp;lt;/code&amp;gt;, because they will be lost after the transition period. Instead, request and associate them from &amp;lt;code&amp;gt;provider_default_net&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ulm ==&lt;br /&gt;
&lt;br /&gt;
=== Default Network ===&lt;br /&gt;
&lt;br /&gt;
* All projects have access to the default network &amp;lt;code&amp;gt;virt-shared&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Instances connected to this network receive:&lt;br /&gt;
** A &#039;&#039;&#039;public global IPv6 address&#039;&#039;&#039;&lt;br /&gt;
** A &#039;&#039;&#039;private NAT-ed IPv4 address&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a &#039;&#039;&#039;routed network&#039;&#039;&#039; using an OpenStack router connected to an external provider network:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;IPv6&#039;&#039;&#039;: Direct public connectivity&lt;br /&gt;
* &#039;&#039;&#039;IPv4 (egress)&#039;&#039;&#039;: Provided via &#039;&#039;&#039;SNAT&#039;&#039;&#039; through the router&lt;br /&gt;
* &#039;&#039;&#039;IPv4 (ingress)&#039;&#039;&#039;: Optional and possible via &#039;&#039;&#039;Floating IPs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== IPv4 Ingress via Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
* Optional &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; can allocated from the external network &amp;lt;code&amp;gt;public-link&amp;lt;/code&amp;gt; quota permitting.&lt;br /&gt;
* Once assigned to a project, a &#039;&#039;&#039;Floating IP&#039;&#039;&#039; can be associated with an instance to provide &#039;&#039;&#039;IPv4 ingress connectivity&#039;&#039;&#039; for that instance.&lt;br /&gt;
* Incoming requests to the &#039;&#039;&#039;Floating IP&#039;&#039;&#039; will be relayed by the router to the instance&#039;s private IPv4 and vice-versa (&#039;&#039;&#039;DNAT&#039;&#039;&#039; + &#039;&#039;&#039;SNAT&#039;&#039;&#039;).&lt;br /&gt;
* The instance internally only sees its private IPv4, but through the &#039;&#039;&#039;Floating IP&#039;&#039;&#039; external requests will arrive at its private IPv4.&lt;br /&gt;
&lt;br /&gt;
=== Flat External Networks ===&lt;br /&gt;
&lt;br /&gt;
* There are no flat networks available to users in region Ulm.&lt;br /&gt;
&lt;br /&gt;
=== Per Project Networks ===&lt;br /&gt;
&lt;br /&gt;
* If a project with multiple VMs wishes to use a separate network instead of relying on the &amp;lt;code&amp;gt;virt-shared&amp;lt;/code&amp;gt; network, it is possible to allocate a private network.&lt;br /&gt;
* Private networks have the same properties and limitations as the shared &amp;lt;code&amp;gt;virt-shared&amp;lt;/code&amp;gt; network, but receive a smaller private IPv4 range and are not shared with other projects.&lt;br /&gt;
* Private networks need to be connected the the internal side of a private router with the external side connected to &amp;lt;code&amp;gt;public-link&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A VM in a dual-stacked private network will receive a private, NAT-ed IPv4 and a public, global IPv6 address.&lt;br /&gt;
** A unique, private IPv4 /26 range can be allocated from the subnet pool &amp;lt;code&amp;gt;tenant-v4-16-26&amp;lt;/code&amp;gt;.&lt;br /&gt;
** A unique, public IPv6 /64 range can be allocated from the subnet pool &amp;lt;code&amp;gt;tenant-v6-48-64&amp;lt;/code&amp;gt;. &lt;br /&gt;
* Optional &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; from &amp;lt;code&amp;gt;public-link&amp;lt;/code&amp;gt; can be used for IPv4 ingress, just like with the default &amp;lt;code&amp;gt;virt-shared&amp;lt;/code&amp;gt; network.&lt;br /&gt;
* The only meaningful advantage of a per project network is that is not shared with VMs from other projects.&lt;br /&gt;
&lt;br /&gt;
=== Network Renumbering ===&lt;br /&gt;
&lt;br /&gt;
* The IPv4 range that Gen3 region Ulm starts with initially is only temporary and will be replaced with an IPv4 range that is currently still in-use in Gen2 region Ulm, once Gen2 shuts down.&lt;br /&gt;
** During that IPv4 renumbering all IPv4 &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; will be removed.&lt;br /&gt;
** Afterwards new IPv4 &#039;&#039;&#039;Floating IPs&#039;&#039;&#039; can be allocated from &amp;lt;code&amp;gt;public-link&amp;lt;/code&amp;gt;.&lt;br /&gt;
** This affects &amp;lt;code&amp;gt;virt-shared&amp;lt;/code&amp;gt; and all per project networks.&lt;br /&gt;
** IPv6 ranges and addresses will remain unchanged.&lt;br /&gt;
** private IPv4 ranges and addresses will remain unchanged.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Cloud_Migration_Guide&amp;diff=2263</id>
		<title>Cloud Migration Guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Cloud_Migration_Guide&amp;diff=2263"/>
		<updated>2026-05-28T09:42:04Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;mw-message-box mw-message-box-warning&amp;quot;&lt;br /&gt;
| style=&amp;quot;vertical-align:middle;&amp;quot; | &#039;&#039;&#039;⚠️ Please Note:&#039;&#039;&#039; This guide is still work in progress. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-message-box mw-message-box-warning&amp;quot;&lt;br /&gt;
| style=&amp;quot;vertical-align:middle;&amp;quot; | &#039;&#039;&#039;⚠️ IMPORTANT SHUTDOWN NOTICE:&#039;&#039;&#039; &lt;br /&gt;
The Gen2 infrastructure will be permanently shut down on &#039;&#039;&#039;September 15, 2026&#039;&#039;&#039;. All projects and data that have not been migrated by this date will be irrevocably deleted. To use Gen3, you must clarify and apply for your entitlements (which are subject to costs) in a timely manner.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;There is no automatic migration path: Gen2 and Gen3 are completely separate environments.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Migration requires a new entitlement.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Security Groups and IP addresses will change and must be reconfigured manually.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;&#039;Recommended approach:&#039;&#039;&#039; Start a new, fresh instance (VM) in Gen3 and copy your old data over the network (e.g., via rsync).&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= General Information =&lt;br /&gt;
&lt;br /&gt;
This guide explains how to migrate your resources from the old bwCloud-OS Gen2 environment to bwCloud-OS Gen3. Because the two environments are completely separated, there is no automatic migration path. You will need to manually export your resources from the old cloud, download them locally, and upload them to the new cloud. Please note that network settings and Security Groups cannot be copied and must be reconfigured manually in the new environment.&lt;br /&gt;
&lt;br /&gt;
== Important Prerequisites: Entitlements and Quotas ==&lt;br /&gt;
The new bwCloud-OS Gen3 will become a paid infrastructure platform. Therefore, it is necessary for each participating university or institution to actively assign the corresponding entitlements to its users. You cannot simply transfer your old projects directly without this authorization.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Missing Entitlement?&#039;&#039;&#039; If you have not yet been assigned an entitlement, please get in touch directly with your local institution or university&#039;s IT support. &lt;br /&gt;
* &#039;&#039;&#039;Quota Allocation:&#039;&#039;&#039; Please note that the allocation of resource quotas is entirely managed and regulated through your respective institution.&lt;br /&gt;
&lt;br /&gt;
Details can be found [https://wiki.bwcloud-os.de/index.php/Guide:_Entitlement_%26_Eligibility here].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-message-box mw-message-box-notice&amp;quot;&lt;br /&gt;
| style=&amp;quot;vertical-align:middle;&amp;quot; | &#039;&#039;&#039;ℹ️ Note on Group Projects:&#039;&#039;&#039; Currently, there is no established process for complex group projects and their corresponding quota allocation. If you require resources for such a project, we kindly ask for a little more patience until the procedures are fully defined.&lt;br /&gt;
|}&lt;br /&gt;
== Dashboard Login ==&lt;br /&gt;
* [https://portal.bw-cloud.org/ Old bwCloud-OS Gen2]&lt;br /&gt;
* [https://portal.ul.bwcos.de/auth/login/?next=/%20https://portal.ul.bwcos.de/ New bwCloud-OS Gen3]&lt;br /&gt;
== Networks ==&lt;br /&gt;
The new infrastructure includes not only new networks but also new network-related features such as load balancers. You can find an overview [[Networks_Gen3|here]].&lt;br /&gt;
&lt;br /&gt;
Network-specific differences between regions and details about the individual networks can be found in the following guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
➡️ [[Guide:_Network_Configuration_by_Region|Guide: Network Configuration by Region]]&lt;br /&gt;
&lt;br /&gt;
= Transferring Data and VMs= &lt;br /&gt;
&lt;br /&gt;
There are basically two ways to transfer your data to the new bwCloud-OS (Gen3): The rsync method over the network and the snapshot method. &lt;br /&gt;
&lt;br /&gt;
== Transferring Volumes ==&lt;br /&gt;
&lt;br /&gt;
While it is technically possible to migrate a Cinder volume by converting it to an image and uploading it to the new cloud, we do not recommend this approach. The process is extremely slow, and depending on the backend configuration, the upload may silently fail entirely.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Our recommendation: create a fresh volume and copy your data over the network.&#039;&#039;&#039;&lt;br /&gt;
* In the new environment, create a new empty volume of the appropriate size and attach it to a new VM.&lt;br /&gt;
* Format and mount the volume on the new VM. Detailed instructions can be found [[Guide:_Volumes_and_Images#Create_and_Attach_a_Volume|here]]. &lt;br /&gt;
* Make sure your old VM (with the old volume mounted) is reachable from the new VM via SSH (either by exchanging SSH keys or setting a password in the VM). &lt;br /&gt;
* Sync your data directly over the network using &#039;&#039;&#039;rsync&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -avz --progress /path/to/old/data/ root@&amp;lt;NEW_VM_IP&amp;gt;:/path/to/new/destination/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transferring VMs ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
* Access to both bwCloud-OS environments and &lt;br /&gt;
* Application Credentials, as described [[Programmatic_Access_and_Automation#Application_Credentials|here]] and&lt;br /&gt;
* OpenStack Client installed, as described [[Programmatic_Access_and_Automation#OpenStack_Client|here]].&lt;br /&gt;
&lt;br /&gt;
=== Procedure ===&lt;br /&gt;
&lt;br /&gt;
When transferring a VM, you create a snapshot of its current state, download it, and use it as a base image in the new environment.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 1: Create a Snapshot&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First, source your old bwCloud-OS Gen2 credentials and find the ID of the instance (VM) you want to migrate: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
source old-creds.sh &lt;br /&gt;
openstack server list &lt;br /&gt;
openstack server image create --name &amp;lt;snapshot_name&amp;gt; &amp;lt;instance_id&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 2: Download the Snapshot&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Image ID should have been prompted in the previous step. However, it is also possible to find the ID of your created snapshot and download it to your local computer later:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image list&lt;br /&gt;
openstack image save --file myimage.img &amp;lt;snapshot_id&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 3: Upload to the New Environment (bwCloud-OS Gen3)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Source your new cloud credentials and upload the image file. &#039;&#039;&#039;Important&#039;&#039;&#039;: Always set the visibility to Private so other users cannot use your image as a base for their services.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
source new-creds.sh&lt;br /&gt;
openstack image create --file myimage.img --private myimage&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternative: You can also upload the downloaded .img file using the new Horizon GUI by navigating to &#039;&#039;&#039;Compute -&amp;gt; Images&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 4: Start the Instance&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can now start a new instance using this uploaded image. Remember to reconfigure your &#039;&#039;&#039;Security Groups&#039;&#039;&#039; and note that you will receive a &#039;&#039;&#039;new IP address&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To start a new instance: &lt;br /&gt;
* Log in to the bwCloud-OS Gen3 Dashboard. &lt;br /&gt;
* Navigate to Project --&amp;gt; Compute --&amp;gt; Images. The uploaded snapshot should be listed there.&lt;br /&gt;
* Click on &amp;quot;Start&amp;quot;, choose an instance name, and select the network and SSH key (or create a new one).&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_Load_Balancers&amp;diff=2262</id>
		<title>Guide: Load Balancers</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_Load_Balancers&amp;diff=2262"/>
		<updated>2026-05-24T13:06:34Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide walks through creating a private network, deploying two web server VMs on it, and exposing them via an OpenStack load balancer to a public network.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Network Setup =&lt;br /&gt;
&lt;br /&gt;
== Create a private network ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network create myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a subnet of the private network==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet create myNet_v4 --network myNet --subnet-range 192.168.100.0/24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a router and connect it to a public network ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router create myRouter&lt;br /&gt;
openstack router add subnet myRouter myNet_v4&lt;br /&gt;
openstack router set myRouter --external-gateway provider_net&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Creating Backend Instances for Load Balancing =&lt;br /&gt;
As an example, we create two identical web server instances that will serve as backend nodes for the load balancer. &lt;br /&gt;
&lt;br /&gt;
== Create two identical VMs ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server create \&lt;br /&gt;
  --image ubuntu-24.04 \&lt;br /&gt;
  --flavor p1.tiny \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --key-name myKey \&lt;br /&gt;
  --min 2 --max 2 \&lt;br /&gt;
  webserver&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Associate (temporary) floating IPs to make the VMs accessible ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
FIP1=$(openstack floating ip create provider_net -f value -c floating_ip_address)&lt;br /&gt;
FIP2=$(openstack floating ip create provider_net -f value -c floating_ip_address)&lt;br /&gt;
&lt;br /&gt;
openstack server add floating ip webserver-1 $FIP1&lt;br /&gt;
openstack server add floating ip webserver-2 $FIP2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install basic web servers on the VMs ==&lt;br /&gt;
SSH into each VM and run:&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt update &amp;amp;&amp;amp; \&lt;br /&gt;
sudo apt -y install apache2 &amp;amp;&amp;amp; \&lt;br /&gt;
sudo systemctl enable --now apache2 &amp;amp;&amp;amp; \&lt;br /&gt;
echo $(hostname) | sudo tee /var/www/html/index.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;Add security rules to both VMs to allow HTTP access on port 80 as described in the section on  [[Security#Example: Opening Port 443 for HTTPS Access|Security Rules.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Test the web servers:&amp;lt;pre&amp;gt;curl $FIP1&lt;br /&gt;
# Expected output: webserver-1&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Load Balancer Setup and Backend Integration =&lt;br /&gt;
&lt;br /&gt;
Install the client (preferably in a Python virtual environment):&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install python-octaviaclient&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Create the load balancer ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
openstack loadbalancer create \&lt;br /&gt;
  --name myLB \&lt;br /&gt;
  --vip-subnet-id myNet_v4 \&lt;br /&gt;
  --provider ovn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a listener on port 80 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack loadbalancer listener create \&lt;br /&gt;
    --name myListener \&lt;br /&gt;
    --protocol TCP \&lt;br /&gt;
    --protocol-port 80 \&lt;br /&gt;
    myLB&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a pool for the listener ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack loadbalancer pool create \&lt;br /&gt;
    --name myPool \&lt;br /&gt;
    --listener myListener \&lt;br /&gt;
    --protocol TCP \&lt;br /&gt;
    --lb-algorithm SOURCE_IP_PORT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add web servers to the pool ==&lt;br /&gt;
Get the subnet ID and VM IPs in it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SUBNET_ID=$(openstack subnet list --name myNet_v4 -f value -c ID)&lt;br /&gt;
WEB1_IP=$(openstack server show webserver-1 -f value -c addresses | grep -o &#039;192\.168\.100\.[0-9]\+&#039;)&lt;br /&gt;
WEB2_IP=$(openstack server show webserver-2 -f value -c addresses | grep -o &#039;192\.168\.100\.[0-9]\+&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add each VM to the pool:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack loadbalancer member create \&lt;br /&gt;
    --subnet-id $SUBNET_ID \&lt;br /&gt;
    --address $WEB1_IP \&lt;br /&gt;
    --protocol-port 80 \&lt;br /&gt;
    myPool&lt;br /&gt;
&lt;br /&gt;
openstack loadbalancer member create \&lt;br /&gt;
    --subnet-id $SUBNET_ID \&lt;br /&gt;
    --address $WEB2_IP \&lt;br /&gt;
    --protocol-port 80 \&lt;br /&gt;
    myPool&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Assign a floating IP to the load balancer ==&lt;br /&gt;
Create a floating IP and associate it with the VIP of the load balancer:&amp;lt;pre&amp;gt;&lt;br /&gt;
FIP=$(openstack floating ip create provider_net -f value -c floating_ip_address)&lt;br /&gt;
VIPPORT=$(openstack loadbalancer show myLB -f value -c vip_port_id)&lt;br /&gt;
openstack floating ip set --port $VIPPORT $FIP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Test the load balancer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl $FIP&lt;br /&gt;
# Expected output (may alternate between VMs): webserver-1 / webserver-2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_Load_Balancers&amp;diff=2261</id>
		<title>Guide: Load Balancers</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_Load_Balancers&amp;diff=2261"/>
		<updated>2026-05-24T13:04:18Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Load Balancer Setup and Backend Integration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide walks through creating a private network, deploying two web server VMs on it, and exposing them via an OpenStack load balancer to a public network.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Network Setup =&lt;br /&gt;
&lt;br /&gt;
== Create a private network ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network create myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a subnet of the private network==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet create myNet_v4 --network myNet --subnet-range 192.168.100.0/24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a router and connect it to a public network ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router create myRouter&lt;br /&gt;
openstack router add subnet myRouter myNet_v4&lt;br /&gt;
openstack router set myRouter --external-gateway provider_net&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Creating Backend Instances for Load Balancing =&lt;br /&gt;
As an example, we create two identical web server instances that will serve as backend nodes for the load balancer. &lt;br /&gt;
&lt;br /&gt;
== Create two identical VMs ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server create \&lt;br /&gt;
  --image ubuntu-24.04 \&lt;br /&gt;
  --flavor p1.tiny \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --key-name myKey \&lt;br /&gt;
  --min 2 --max 2 \&lt;br /&gt;
  webserver&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Associate (temporary) floating IPs to make the VMs accessible ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
FIP1=$(openstack floating ip create provider_net -f value -c floating_ip_address)&lt;br /&gt;
FIP2=$(openstack floating ip create provider_net -f value -c floating_ip_address)&lt;br /&gt;
&lt;br /&gt;
openstack server add floating ip webserver-1 $FIP1&lt;br /&gt;
openstack server add floating ip webserver-2 $FIP2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install basic web servers on the VMs ==&lt;br /&gt;
SSH into each VM and run:&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt update &amp;amp;&amp;amp; \&lt;br /&gt;
sudo apt -y install apache2 &amp;amp;&amp;amp; \&lt;br /&gt;
sudo systemctl enable --now apache2 &amp;amp;&amp;amp; \&lt;br /&gt;
echo $(hostname) | sudo tee /var/www/html/index.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;Add security rules to both VMs to allow HTTP access on port 80 as described in the section on  [[Security#Example: Opening Port 443 for HTTPS Access|Security Rules.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Test the web servers:&amp;lt;pre&amp;gt;curl $FIP1&lt;br /&gt;
# Expected output: webserver-1&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Load Balancer Setup and Backend Integration =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 pip3 install python-octaviaclient&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Create the load balancer ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack loadbalancer create \&lt;br /&gt;
  --name myLB \&lt;br /&gt;
  --vip-subnet-id myNet_v4 \&lt;br /&gt;
  --provider ovn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a listener on port 80 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack loadbalancer listener create \&lt;br /&gt;
    --name myListener \&lt;br /&gt;
    --protocol TCP \&lt;br /&gt;
    --protocol-port 80 \&lt;br /&gt;
    myLB&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a pool for the listener ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack loadbalancer pool create \&lt;br /&gt;
    --name myPool \&lt;br /&gt;
    --listener myListener \&lt;br /&gt;
    --protocol TCP \&lt;br /&gt;
    --lb-algorithm SOURCE_IP_PORT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add web servers to the pool ==&lt;br /&gt;
Get the subnet ID and VM IPs in it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SUBNET_ID=$(openstack subnet list --name myNet_v4 -f value -c ID)&lt;br /&gt;
WEB1_IP=$(openstack server show webserver-1 -f value -c addresses | grep -o &#039;192\.168\.100\.[0-9]\+&#039;)&lt;br /&gt;
WEB2_IP=$(openstack server show webserver-2 -f value -c addresses | grep -o &#039;192\.168\.100\.[0-9]\+&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add each VM to the pool:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack loadbalancer member create \&lt;br /&gt;
    --subnet-id $SUBNET_ID \&lt;br /&gt;
    --address $WEB1_IP \&lt;br /&gt;
    --protocol-port 80 \&lt;br /&gt;
    myPool&lt;br /&gt;
&lt;br /&gt;
openstack loadbalancer member create \&lt;br /&gt;
    --subnet-id $SUBNET_ID \&lt;br /&gt;
    --address $WEB2_IP \&lt;br /&gt;
    --protocol-port 80 \&lt;br /&gt;
    myPool&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Assign a floating IP to the load balancer ==&lt;br /&gt;
Create a floating IP and associate it with the VIP of the load balancer:&amp;lt;pre&amp;gt;&lt;br /&gt;
FIP=$(openstack floating ip create provider_net -f value -c floating_ip_address)&lt;br /&gt;
VIPPORT=$(openstack loadbalancer show myLB -f value -c vip_port_id)&lt;br /&gt;
openstack floating ip set --port $VIPPORT $FIP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Test the load balancer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl $FIP&lt;br /&gt;
# Expected output (may alternate between VMs): webserver-1 / webserver-2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Main_Page&amp;diff=2228</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Main_Page&amp;diff=2228"/>
		<updated>2026-05-01T08:52:31Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
= bwCloud-OS User Wiki =&lt;br /&gt;
Welcome to the &#039;&#039;&#039;bwCloud-OS User Wiki -&#039;&#039;&#039; the central guide to using the multi-region &#039;&#039;&#039;O&#039;&#039;&#039;pen&#039;&#039;&#039;S&#039;&#039;&#039;tack &#039;&#039;&#039;cloud&#039;&#039;&#039; shared across &#039;&#039;&#039;B&#039;&#039;&#039;aden-&#039;&#039;&#039;W&#039;&#039;&#039;ürttemberg, Germany. This cloud is jointly operated by the universities of Freiburg, Karlsruhe, Mannheim, and Ulm, and is available to users from all participating educational institutions.&lt;br /&gt;
&lt;br /&gt;
This wiki is primarily designed to answer &#039;&#039;&#039;frequently asked questions (FAQs)&#039;&#039;&#039; and provide &#039;&#039;&#039;practical guidance&#039;&#039;&#039; for common tasks when using the bwCloud-OS service. General information about the bwCloud-OS  and related projects is available on the [https://bwcloud-os.de/ &#039;&#039;&#039;bwCloud-OS website&#039;&#039;&#039;].&lt;br /&gt;
&lt;br /&gt;
If you need technical assistance beyond what is covered here, please open a support &#039;&#039;&#039;ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ &#039;&#039;&#039;bwSupportPortal&#039;&#039;&#039;].&lt;br /&gt;
&lt;br /&gt;
== Quickstart ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Quickstart&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; &lt;br /&gt;
&lt;br /&gt;
{{Box&lt;br /&gt;
|id=register1&lt;br /&gt;
|title=I. Register and/or Log in&lt;br /&gt;
|content=&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;Go to the bwCloud-OS [https://portal.bw-cloud.org/ Dashboard].&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;Select &#039;&#039;&#039;bwIDM via OpenID Connect&#039;&#039;&#039; and click &#039;&#039;&#039;Sign In&#039;&#039;&#039;.&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;Choose your home institution and log in with your university credentials.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If logging in for the first time, register for &amp;lt;strong&amp;gt;bwCloud SCOPE&amp;lt;/strong&amp;gt; by accepting the terms of use.&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;After login or registration, you will be redirected to the bwCloud-OS Dashboard.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
See the [[Registration|Registration page]] for more details.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Box&lt;br /&gt;
|id=register2&lt;br /&gt;
|title=II. Upload or Create an SSH Key&lt;br /&gt;
|content=&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;Log in to the [https://portal.bw-cloud.org/ Dashboard].&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;Go to &amp;lt;strong&amp;gt;Project → Compute → Key Pairs&amp;lt;/strong&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&lt;br /&gt;
    Choose one of the following options:&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;To import an existing key&amp;lt;/strong&amp;gt;: Click &amp;lt;strong&amp;gt;Import Public Key&amp;lt;/strong&amp;gt;, enter a name, select &amp;lt;strong&amp;gt;SSH Key&amp;lt;/strong&amp;gt; type, and upload your &#039;&#039;&#039;&#039;&#039;public&#039;&#039;&#039;&#039;&#039; SSH key. Then click &amp;lt;strong&amp;gt;Import&amp;lt;/strong&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;To create a new key pair&amp;lt;/strong&amp;gt;: Click &amp;lt;strong&amp;gt;Create Key Pair&amp;lt;/strong&amp;gt;, enter a name, select &amp;lt;strong&amp;gt;SSH Key&amp;lt;/strong&amp;gt; type, and click &amp;lt;strong&amp;gt;Create&amp;lt;/strong&amp;gt;. The &#039;&#039;&#039;&#039;&#039;private&#039;&#039;&#039;&#039;&#039; key will be downloaded automatically.&amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;Make sure the private key is securely stored and accessible on your local machine.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;For help generating an SSH key, see our [[Guide: SSH#Key-Pair-Creation|SSH Guide]].&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Box&lt;br /&gt;
|id=register3&lt;br /&gt;
|title=III. Launch a Virtual Machine&lt;br /&gt;
|content=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&lt;br /&gt;
    Go to &amp;lt;strong&amp;gt;Compute → Instances → Launch Instance&amp;lt;/strong&amp;gt; and fill out the tabs:&lt;br /&gt;
    &amp;lt;ol type=&amp;quot;a&amp;quot; style=&amp;quot;margin-left: 1.5em;&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Details&amp;lt;/strong&amp;gt;: Assign a name&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Source&amp;lt;/strong&amp;gt;: Choose an image (e.g., &#039;&#039;Debian 12&#039;&#039;)&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Flavor&amp;lt;/strong&amp;gt;: Select a resource package (e.g., &#039;&#039;m1.small&#039;&#039;)&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Networks&amp;lt;/strong&amp;gt;: Choose the appropriate  network&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Key Pair&amp;lt;/strong&amp;gt;: Select your SSH key&amp;lt;/li&amp;gt; &amp;lt;/ol&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;Click &amp;lt;strong&amp;gt;Launch&amp;lt;/strong&amp;gt; and wait for the instance to finish building and enter &amp;lt;strong&amp;gt;Running&amp;lt;/strong&amp;gt; state.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;For full details on managing instances, see  the [[Instances (VMs)|Instances page]]. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Box&lt;br /&gt;
|id=register4&lt;br /&gt;
|title=IV. Connect to Your VM&lt;br /&gt;
|content=&lt;br /&gt;
Connect to your VM via SSH from a terminal using the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f9f9f9; border: 1px solid #ccc; padding: 0.5em;&amp;quot;&amp;gt;&lt;br /&gt;
ssh -i /path/to/private-key &amp;amp;lt;user&amp;amp;gt;@&amp;amp;lt;address&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;user&amp;gt;&amp;lt;/code&amp;gt; is the default username, e.g. &amp;lt;code&amp;gt;ubuntu&amp;lt;/code&amp;gt; for Ubuntu images. For other images, see the [[Images|Image Overview]].&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;address&amp;gt;&amp;lt;/code&amp;gt; is the DNS name ([[Networks#FQDN|FQDN]]) or the public IP address of your running instance. Both can be found in the [https://portal.bw-cloud.org/ Dashboard], on the &amp;lt;strong&amp;gt;Instances&amp;lt;/strong&amp;gt; page. &lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;For (advanced) SSH connection methods, see our [[Guide: SSH|SSH Guide]].&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Topic Hub &#039;&#039;&#039;–&#039;&#039;&#039; Sections ==  &lt;br /&gt;
&amp;lt;span id=&amp;quot;Theme-Hub&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;🆔 [[Registration]]&#039;&#039;&#039; &#039;&#039;&#039;–&#039;&#039;&#039; Identity Management, Entitlements, Regions&lt;br /&gt;
* &#039;&#039;&#039;🖥️ [[Instances (VMs)]] –&#039;&#039;&#039; Launching Virtual Machines (VMs), Access to VMs (SSH), Flavors, Images&lt;br /&gt;
* &#039;&#039;&#039;🌐 [[Networks]]&#039;&#039;&#039; &#039;&#039;&#039;–&#039;&#039;&#039; IPs, FQDNs &amp;amp; DNS, Public and Private Networks&lt;br /&gt;
* &#039;&#039;&#039;[[Security|🛡️ Security]]&#039;&#039;&#039; &#039;&#039;&#039;–&#039;&#039;&#039; Open and Closed Ports, Security Groups, Security Incidents&lt;br /&gt;
* &#039;&#039;&#039;💾 [[Storage]]&#039;&#039;&#039; &#039;&#039;&#039;–&#039;&#039;&#039; Volumes, Snapshots, Backups&lt;br /&gt;
* &#039;&#039;&#039;👥&#039;&#039;&#039; &#039;&#039;&#039;[[Projects and Quota|Projects &amp;amp; Quota]]&#039;&#039;&#039; &#039;&#039;&#039;–&#039;&#039;&#039; Projects, Group Management, Quota Changes&lt;br /&gt;
* &#039;&#039;&#039;⚙️ [[Programmatic Access and Automation|Automation]]&#039;&#039;&#039; &#039;&#039;&#039;–&#039;&#039;&#039; Application Credentials, OpenStack CLI and SDK, Automation Tools&lt;br /&gt;
* &#039;&#039;&#039;📖 [[Glossary|Glossary]]&#039;&#039;&#039; &#039;&#039;&#039;–&#039;&#039;&#039; Key Terms Used in bwCloud-OS&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2224</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2224"/>
		<updated>2026-04-27T12:00:40Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;By default,  bwCloud-OS VMs are only accessible via &amp;lt;strong&amp;gt;SSH (port 22)&amp;lt;/strong&amp;gt; and  &amp;lt;strong&amp;gt;ICMP&amp;lt;/strong&amp;gt; (e.g., &#039;&#039;ping&#039;&#039;);  all other incoming traffic is blocked for security.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To allow access on additional ports (e.g. HTTPS/443), you can add rules via the &amp;lt;strong&amp;gt;Security Groups&amp;lt;/strong&amp;gt; in the [https://portal.bw-cloud.org/ Dashboard] — changes take effect immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Following our &amp;lt;strong&amp;gt;security checklist&amp;lt;/strong&amp;gt; below can help you harden your bwCloud-OS VM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;li&amp;gt;Some ports are &amp;lt;strong&amp;gt;centrally filtered&amp;lt;/strong&amp;gt; in specific bwCloud-OS regions and cannot be opened individually; refer to this [[Blocked_and_Allowed_Ports|overview]] for region-specific details.&amp;lt;/li&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you suspect a &amp;lt;strong&amp;gt;security incident&amp;lt;/strong&amp;gt;, stop the affected VMs and submit a [https://bw-support.scc.kit.edu/ support ticket] immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Access Control &amp;amp; Firewall Rules =&lt;br /&gt;
&lt;br /&gt;
== What network access is allowed by default in bwCloud-OS instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Default&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, &#039;&#039;&#039;bwCloud-OS instances&#039;&#039;&#039; are accessible via:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; – for remote login and configuration&lt;br /&gt;
* &#039;&#039;&#039;ICMP&#039;&#039;&#039; – to allow basic network diagnostics like &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This initial access is explicitly permitted by the &#039;&#039;&#039;automatically assigned security group&#039;&#039;&#039; (named &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;) in our configuration. This is not the default behavior in OpenStack — it is provided by bwCloud-OS to simplify first-time access for users.&lt;br /&gt;
&lt;br /&gt;
== How do I open additional ports for my instance? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Rules&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A newly created virtual machine in bwCloud-OS is only accessible from the outside via &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; and &#039;&#039;&#039;ICMP&#039;&#039;&#039;.  All other inbound traffic is &#039;&#039;&#039;blocked&#039;&#039;&#039; by default — meaning external traffic on other ports cannot reach the instance.&lt;br /&gt;
&lt;br /&gt;
To allow access on other ports (e.g. for web servers or applications), you need to &#039;&#039;&#039;add a rule&#039;&#039;&#039; to the relevant &#039;&#039;&#039;security group&#039;&#039;&#039;. &#039;&#039;Changes to security group rules apply immediately to all instances using that group&#039;&#039; — there&#039;s no need to reboot the instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening Port 443 for HTTPS Access ===&lt;br /&gt;
If you&#039;re running a web server that should be accessible via &#039;&#039;&#039;HTTPS&#039;&#039;&#039;, you typically need to open &#039;&#039;&#039;port 443&#039;&#039;&#039; in a security group assigned to your instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Steps in the [https://portal.bw-cloud.org/ Dashboard]:&#039;&#039;&#039;&lt;br /&gt;
# In the left menu, go to &#039;&#039;&#039;Network → Security Groups&#039;&#039;&#039;. A list of all defined security groups will appear.  &lt;br /&gt;
#* &#039;&#039;&#039;Recommended:&#039;&#039;&#039; Consider creating a dedicated security group (e.g. named &amp;lt;code&amp;gt;https-access&amp;lt;/code&amp;gt;), and assign it to your instance using &#039;&#039;&#039;Edit Security Groups&#039;&#039;&#039; in the instance menu before the next step.&lt;br /&gt;
# Find the relevant group and click &#039;&#039;&#039;Manage Rules&#039;&#039;&#039;. You’ll see all currently defined rules for that group.&lt;br /&gt;
# Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; to create a new one.&lt;br /&gt;
# In the dialog that appears, choose one of the following:&lt;br /&gt;
#* &#039;&#039;&#039;HTTPS&#039;&#039;&#039; from the &#039;&#039;&#039;Rule&#039;&#039;&#039; dropdown (automatically fills port 443), or&lt;br /&gt;
#* &#039;&#039;&#039;Custom TCP Rule&#039;&#039;&#039;, then manually enter &#039;&#039;&#039;443&#039;&#039;&#039; in the &#039;&#039;&#039;Port&#039;&#039;&#039; field.&lt;br /&gt;
# In the &#039;&#039;&#039;CIDR&#039;&#039;&#039; field, specify which IP addresses should be allowed to connect:&lt;br /&gt;
#* Use a specific IP range (e.g. &amp;lt;code&amp;gt;192.168.0.0/24&amp;lt;/code&amp;gt;) to &#039;&#039;&#039;limit access&#039;&#039;&#039;&lt;br /&gt;
#* ⚠️ Using &#039;&#039;&#039;&amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt;&#039;&#039;&#039; allows access from &#039;&#039;&#039;any IPv4 address&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;::/0&amp;lt;/code&amp;gt;&#039;&#039;&#039;  from &#039;&#039;&#039;any IPv6 address&#039;&#039;&#039;.&lt;br /&gt;
# Set the &#039;&#039;&#039;Direction&#039;&#039;&#039; of the rule:&lt;br /&gt;
#* &amp;lt;code&amp;gt;Ingress&amp;lt;/code&amp;gt; = incoming connections (usually what you want)&lt;br /&gt;
#* &amp;lt;code&amp;gt;Egress&amp;lt;/code&amp;gt; = outgoing connections&lt;br /&gt;
# Click &#039;&#039;&#039;Add&#039;&#039;&#039;. The rule will be created and added to the list immediately.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening a Port only for Access from Certain IP Ranges ===&lt;br /&gt;
&#039;&#039;&#039;➡️&#039;&#039;&#039;  [[Guide: Security Group|Security Groups Guide]]&lt;br /&gt;
&lt;br /&gt;
== Are some ports blocked in bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Blocked-Ports&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. Some ports are &#039;&#039;&#039;centrally&#039;&#039;&#039; &#039;&#039;&#039;blocked&#039;&#039;&#039; in &#039;&#039;&#039;certain&#039;&#039;&#039; &#039;&#039;&#039;bwCloud-OS regions&#039;&#039;&#039; due to specific network policies at the participating university data centers. Centrally blocked ports cannot be opened individually. &lt;br /&gt;
&lt;br /&gt;
For more details — including which ports are affected in each region — see the page [[Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
= SSL Certificates &amp;amp; Secure Services =&lt;br /&gt;
&lt;br /&gt;
== Can I get SSL/TLS certificates via bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SSL-Certificates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No, bwCloud-OS does &#039;&#039;&#039;not&#039;&#039;&#039; provide &#039;&#039;&#039;SSL/TLS certificates.&#039;&#039;&#039; However, you can obtain certificates directly from public providers like &#039;&#039;&#039;Let’s Encrypt&#039;&#039;&#039; using tools such as &#039;&#039;&#039;[https://certbot.eff.org/ Certbot]&#039;&#039;&#039;, which you can install and run on your instance.&lt;br /&gt;
&lt;br /&gt;
This allows you, for example, to enable &#039;&#039;&#039;HTTPS&#039;&#039;&#039; for services running on your VM. Don&#039;t forget to open the necessary ports (e.g., 443) using [[Security#Security-Rules|security group rules]].&lt;br /&gt;
&lt;br /&gt;
= General Security Recommendations =&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide a basic security checklist for virtual machines? ==&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
=== Secure SSH access ===&lt;br /&gt;
* Read and apply the recommendations in the [[Guide:_SSH|SSH guide]].&lt;br /&gt;
&lt;br /&gt;
=== Keep the system updated ===&lt;br /&gt;
Keeping your instance up to date is one of the most effective security measures: security updates fix known vulnerabilities that may otherwise be exploitable.&lt;br /&gt;
&lt;br /&gt;
There are two common approaches:&lt;br /&gt;
* &#039;&#039;&#039;Manual updates (one-time / on demand):&#039;&#039;&#039; You run updates yourself (e.g., after login, on a regular schedule).&lt;br /&gt;
* &#039;&#039;&#039;Automatic updates:&#039;&#039;&#039; The system installs security updates automatically in the background. On Ubuntu/Debian this is commonly done via &amp;lt;code&amp;gt;unattended-upgrades&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu/Debian) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Manual updates (one-time)&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt -y upgrade&lt;br /&gt;
&lt;br /&gt;
# Automatic security updates (background)&lt;br /&gt;
sudo apt -y install unattended-upgrades&lt;br /&gt;
sudo dpkg-reconfigure --priority=low unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Allow only the minimal required ports in bwCloud-OS Security Groups ===&lt;br /&gt;
Only open the ports you actually need. This reduces the attack surface and limits who can reach services on your VM.&lt;br /&gt;
&lt;br /&gt;
* Check your instance&#039;s security groups in the [https://portal.bw-cloud.org/ Dashboard] and allow only the minimal required inbound rules.&lt;br /&gt;
* Restrict access by IP range (CIDR) wherever possible (avoid &amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt; unless truly required).&lt;br /&gt;
* For step-by-step instructions and examples, see: [[Security#Security-Rules|How do I open additional ports for my instance?]]&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; some ports may be centrally filtered in certain regions; see [[Blocked_and_Allowed_Ports|Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
=== Optional host firewall  ===&lt;br /&gt;
Security groups are the primary inbound filter in bwCloud-OS. A host firewall can provide an additional layer (defense-in-depth), e.g., to enforce local policies on the VM.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu with UFW) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt -y install ufw&lt;br /&gt;
sudo ufw default deny incoming&lt;br /&gt;
sudo ufw default allow outgoing&lt;br /&gt;
&lt;br /&gt;
# Allow SSH (ideally restrict in the bwCloud-OS security group as well)&lt;br /&gt;
sudo ufw allow 22/tcp&lt;br /&gt;
&lt;br /&gt;
# Example: allow HTTPS if you opened 443 in the security group&lt;br /&gt;
sudo ufw allow 443/tcp&lt;br /&gt;
&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw status verbose&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
⚠️ If you block SSH on the host firewall while only having SSH access, you may lock yourself out. Always ensure SSH remains permitted (and test from your client).&lt;br /&gt;
&lt;br /&gt;
=== Document your configuration ===&lt;br /&gt;
To operate and troubleshoot securely, keep a record of your instance configuration:&lt;br /&gt;
&lt;br /&gt;
* Which security groups/rules are attached (ports, protocols, CIDRs)?&lt;br /&gt;
* Host firewall rules (if used), SSH hardening settings, update strategy.&lt;br /&gt;
* Installed services and exposed endpoints.&lt;br /&gt;
* Where secrets are stored/managed (avoid putting secrets in shell history or plain text files).&lt;br /&gt;
&lt;br /&gt;
=== Plan and test a backup strategy ===&lt;br /&gt;
Backups are part of security (availability and recovery).&lt;br /&gt;
&lt;br /&gt;
* Define what needs to be recoverable (system, application data, databases, configuration).&lt;br /&gt;
* Decide on backup frequency and retention (e.g., daily incremental + weekly full).&lt;br /&gt;
* Store backups separately from the instance (avoid a single point of failure).&lt;br /&gt;
* Regularly test restores (a backup that was never restored is an assumption, not a plan).&lt;br /&gt;
&lt;br /&gt;
=== Snapshots and images ===&lt;br /&gt;
Snapshots capture the state of a VM or volume at a point in time (e.g., before risky changes). They can help with rollback, but they do not automatically replace a backup strategy.&lt;br /&gt;
&lt;br /&gt;
* Learn more: [[Guide:_Volumes_and_Images|Guide: Volumes and Images]]&lt;br /&gt;
* Recommended practice:&lt;br /&gt;
** Take a snapshot before major changes (OS upgrades, large configuration changes).&lt;br /&gt;
** Remove outdated snapshots according to your retention plan.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Security Incidents =&lt;br /&gt;
&lt;br /&gt;
== What should I do if I suspect my VM has been compromised? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Incident&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your virtual machine is behaving unexpectedly (e.g., high CPU/network load, unknown logins, suspicious processes), it could indicate a possible compromise.&lt;br /&gt;
&lt;br /&gt;
If you suspect that your VM has been compromised, please take the following steps &#039;&#039;&#039;immediately&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard].&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;Stop the affected instance(s).&#039;&#039;&#039; &#039;&#039;Do not delete them!&#039;&#039; This preserves data for further analysis.&lt;br /&gt;
# &#039;&#039;&#039;Submit a support ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ bwSupportPortal] with the following details:&lt;br /&gt;
#*       Which instance(s) are potentially affected?&lt;br /&gt;
#* How is the suspicious behavior observed? (e.g. logs, performance, alerts)&lt;br /&gt;
#* What actions have you already taken?&lt;br /&gt;
&lt;br /&gt;
Our team will contact you as soon as possible to help investigate and resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Does the bwCloud-OS operations team inspect running instances (e.g. through penetration tests)? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Scans&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contents and configuration of user instances are not inspected&#039;&#039;&#039; — we do &#039;&#039;&#039;not&#039;&#039;&#039; perform penetration tests or port scans on the instances. We also &#039;&#039;&#039;never look inside&#039;&#039;&#039; user virtual machines.&lt;br /&gt;
&lt;br /&gt;
However, the overall bwCloud-OS operating environment is actively monitored. For example, network monitoring tracks current inbound and outbound traffic levels. If certain parameters deviate significantly from typical patterns, this may trigger further investigation —  including direct contact with the affected user.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2223</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2223"/>
		<updated>2026-04-27T11:54:52Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;By default,  bwCloud-OS VMs are only accessible via &amp;lt;strong&amp;gt;SSH (port 22)&amp;lt;/strong&amp;gt; and  &amp;lt;strong&amp;gt;ICMP&amp;lt;/strong&amp;gt; (e.g., &#039;&#039;ping&#039;&#039;);  all other incoming traffic is blocked for security.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To allow access on additional ports (e.g. HTTPS/443), you can add rules via the &amp;lt;strong&amp;gt;Security Groups&amp;lt;/strong&amp;gt; in the [https://portal.bw-cloud.org/ Dashboard] — changes take effect immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Some ports are &amp;lt;strong&amp;gt;centrally filtered&amp;lt;/strong&amp;gt; in specific bwCloud-OS regions and cannot be opened individually; refer to this [[Blocked_and_Allowed_Ports|overview]] for region-specific details.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you suspect a &amp;lt;strong&amp;gt;security incident&amp;lt;/strong&amp;gt;, stop the affected VMs and submit a [https://bw-support.scc.kit.edu/ support ticket] immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Access Control &amp;amp; Firewall Rules =&lt;br /&gt;
&lt;br /&gt;
== What network access is allowed by default in bwCloud-OS instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Default&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, &#039;&#039;&#039;bwCloud-OS instances&#039;&#039;&#039; are accessible via:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; – for remote login and configuration&lt;br /&gt;
* &#039;&#039;&#039;ICMP&#039;&#039;&#039; – to allow basic network diagnostics like &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This initial access is explicitly permitted by the &#039;&#039;&#039;automatically assigned security group&#039;&#039;&#039; (named &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;) in our configuration. This is not the default behavior in OpenStack — it is provided by bwCloud-OS to simplify first-time access for users.&lt;br /&gt;
&lt;br /&gt;
== How do I open additional ports for my instance? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Rules&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A newly created virtual machine in bwCloud-OS is only accessible from the outside via &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; and &#039;&#039;&#039;ICMP&#039;&#039;&#039;.  All other inbound traffic is &#039;&#039;&#039;blocked&#039;&#039;&#039; by default — meaning external traffic on other ports cannot reach the instance.&lt;br /&gt;
&lt;br /&gt;
To allow access on other ports (e.g. for web servers or applications), you need to &#039;&#039;&#039;add a rule&#039;&#039;&#039; to the relevant &#039;&#039;&#039;security group&#039;&#039;&#039;. &#039;&#039;Changes to security group rules apply immediately to all instances using that group&#039;&#039; — there&#039;s no need to reboot the instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening Port 443 for HTTPS Access ===&lt;br /&gt;
If you&#039;re running a web server that should be accessible via &#039;&#039;&#039;HTTPS&#039;&#039;&#039;, you typically need to open &#039;&#039;&#039;port 443&#039;&#039;&#039; in a security group assigned to your instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Steps in the [https://portal.bw-cloud.org/ Dashboard]:&#039;&#039;&#039;&lt;br /&gt;
# In the left menu, go to &#039;&#039;&#039;Network → Security Groups&#039;&#039;&#039;. A list of all defined security groups will appear.  &lt;br /&gt;
#* &#039;&#039;&#039;Recommended:&#039;&#039;&#039; Consider creating a dedicated security group (e.g. named &amp;lt;code&amp;gt;https-access&amp;lt;/code&amp;gt;), and assign it to your instance using &#039;&#039;&#039;Edit Security Groups&#039;&#039;&#039; in the instance menu before the next step.&lt;br /&gt;
# Find the relevant group and click &#039;&#039;&#039;Manage Rules&#039;&#039;&#039;. You’ll see all currently defined rules for that group.&lt;br /&gt;
# Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; to create a new one.&lt;br /&gt;
# In the dialog that appears, choose one of the following:&lt;br /&gt;
#* &#039;&#039;&#039;HTTPS&#039;&#039;&#039; from the &#039;&#039;&#039;Rule&#039;&#039;&#039; dropdown (automatically fills port 443), or&lt;br /&gt;
#* &#039;&#039;&#039;Custom TCP Rule&#039;&#039;&#039;, then manually enter &#039;&#039;&#039;443&#039;&#039;&#039; in the &#039;&#039;&#039;Port&#039;&#039;&#039; field.&lt;br /&gt;
# In the &#039;&#039;&#039;CIDR&#039;&#039;&#039; field, specify which IP addresses should be allowed to connect:&lt;br /&gt;
#* Use a specific IP range (e.g. &amp;lt;code&amp;gt;192.168.0.0/24&amp;lt;/code&amp;gt;) to &#039;&#039;&#039;limit access&#039;&#039;&#039;&lt;br /&gt;
#* ⚠️ Using &#039;&#039;&#039;&amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt;&#039;&#039;&#039; allows access from &#039;&#039;&#039;any IPv4 address&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;::/0&amp;lt;/code&amp;gt;&#039;&#039;&#039;  from &#039;&#039;&#039;any IPv6 address&#039;&#039;&#039;.&lt;br /&gt;
# Set the &#039;&#039;&#039;Direction&#039;&#039;&#039; of the rule:&lt;br /&gt;
#* &amp;lt;code&amp;gt;Ingress&amp;lt;/code&amp;gt; = incoming connections (usually what you want)&lt;br /&gt;
#* &amp;lt;code&amp;gt;Egress&amp;lt;/code&amp;gt; = outgoing connections&lt;br /&gt;
# Click &#039;&#039;&#039;Add&#039;&#039;&#039;. The rule will be created and added to the list immediately.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening a Port only for Access from Certain IP Ranges ===&lt;br /&gt;
&#039;&#039;&#039;➡️&#039;&#039;&#039;  [[Guide: Security Group|Security Groups Guide]]&lt;br /&gt;
&lt;br /&gt;
== Are some ports blocked in bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Blocked-Ports&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. Some ports are &#039;&#039;&#039;centrally&#039;&#039;&#039; &#039;&#039;&#039;blocked&#039;&#039;&#039; in &#039;&#039;&#039;certain&#039;&#039;&#039; &#039;&#039;&#039;bwCloud-OS regions&#039;&#039;&#039; due to specific network policies at the participating university data centers. Centrally blocked ports cannot be opened individually. &lt;br /&gt;
&lt;br /&gt;
For more details — including which ports are affected in each region — see the page [[Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
= SSL Certificates &amp;amp; Secure Services =&lt;br /&gt;
&lt;br /&gt;
== Can I get SSL/TLS certificates via bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SSL-Certificates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No, bwCloud-OS does &#039;&#039;&#039;not&#039;&#039;&#039; provide &#039;&#039;&#039;SSL/TLS certificates.&#039;&#039;&#039; However, you can obtain certificates directly from public providers like &#039;&#039;&#039;Let’s Encrypt&#039;&#039;&#039; using tools such as &#039;&#039;&#039;[https://certbot.eff.org/ Certbot]&#039;&#039;&#039;, which you can install and run on your instance.&lt;br /&gt;
&lt;br /&gt;
This allows you, for example, to enable &#039;&#039;&#039;HTTPS&#039;&#039;&#039; for services running on your VM. Don&#039;t forget to open the necessary ports (e.g., 443) using [[Security#Security-Rules|security group rules]].&lt;br /&gt;
&lt;br /&gt;
= General Security Recommendations =&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide a basic security checklist for virtual machines? ==&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
=== Secure SSH access ===&lt;br /&gt;
* Read and apply the recommendations in the [[Guide:_SSH|SSH guide]].&lt;br /&gt;
&lt;br /&gt;
=== Keep the system updated ===&lt;br /&gt;
Keeping your instance up to date is one of the most effective security measures: security updates fix known vulnerabilities that may otherwise be exploitable.&lt;br /&gt;
&lt;br /&gt;
There are two common approaches:&lt;br /&gt;
* &#039;&#039;&#039;Manual updates (one-time / on demand):&#039;&#039;&#039; You run updates yourself (e.g., after login, on a regular schedule).&lt;br /&gt;
* &#039;&#039;&#039;Automatic updates:&#039;&#039;&#039; The system installs security updates automatically in the background. On Ubuntu/Debian this is commonly done via &amp;lt;code&amp;gt;unattended-upgrades&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu/Debian) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Manual updates (one-time)&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt -y upgrade&lt;br /&gt;
&lt;br /&gt;
# Automatic security updates (background)&lt;br /&gt;
sudo apt -y install unattended-upgrades&lt;br /&gt;
sudo dpkg-reconfigure --priority=low unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Allow only the minimal required ports in bwCloud-OS Security Groups ===&lt;br /&gt;
Only open the ports you actually need. This reduces the attack surface and limits who can reach services on your VM.&lt;br /&gt;
&lt;br /&gt;
* Check your instance&#039;s security groups in the [https://portal.bw-cloud.org/ Dashboard] and allow only the minimal required inbound rules.&lt;br /&gt;
* Restrict access by IP range (CIDR) wherever possible (avoid &amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt; unless truly required).&lt;br /&gt;
* For step-by-step instructions and examples, see: [[Security#Security-Rules|How do I open additional ports for my instance?]]&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; some ports may be centrally filtered in certain regions; see [[Blocked_and_Allowed_Ports|Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
=== Optional host firewall  ===&lt;br /&gt;
Security groups are the primary inbound filter in bwCloud-OS. A host firewall can provide an additional layer (defense-in-depth), e.g., to enforce local policies on the VM.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu with UFW) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt -y install ufw&lt;br /&gt;
sudo ufw default deny incoming&lt;br /&gt;
sudo ufw default allow outgoing&lt;br /&gt;
&lt;br /&gt;
# Allow SSH (ideally restrict in the bwCloud-OS security group as well)&lt;br /&gt;
sudo ufw allow 22/tcp&lt;br /&gt;
&lt;br /&gt;
# Example: allow HTTPS if you opened 443 in the security group&lt;br /&gt;
sudo ufw allow 443/tcp&lt;br /&gt;
&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw status verbose&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
⚠️ If you block SSH on the host firewall while only having SSH access, you may lock yourself out. Always ensure SSH remains permitted (and test from your client).&lt;br /&gt;
&lt;br /&gt;
=== Document your configuration ===&lt;br /&gt;
To operate and troubleshoot securely, keep a record of your instance configuration:&lt;br /&gt;
&lt;br /&gt;
* Which security groups/rules are attached (ports, protocols, CIDRs)?&lt;br /&gt;
* Host firewall rules (if used), SSH hardening settings, update strategy.&lt;br /&gt;
* Installed services and exposed endpoints.&lt;br /&gt;
* Where secrets are stored/managed (avoid putting secrets in shell history or plain text files).&lt;br /&gt;
&lt;br /&gt;
=== Plan and test a backup strategy ===&lt;br /&gt;
Backups are part of security (availability and recovery).&lt;br /&gt;
&lt;br /&gt;
* Define what needs to be recoverable (system, application data, databases, configuration).&lt;br /&gt;
* Decide on backup frequency and retention (e.g., daily incremental + weekly full).&lt;br /&gt;
* Store backups separately from the instance (avoid a single point of failure).&lt;br /&gt;
* Regularly test restores (a backup that was never restored is an assumption, not a plan).&lt;br /&gt;
&lt;br /&gt;
=== Snapshots and images ===&lt;br /&gt;
Snapshots capture the state of a VM or volume at a point in time (e.g., before risky changes). They can help with rollback, but they do not automatically replace a backup strategy.&lt;br /&gt;
&lt;br /&gt;
* Learn more: [[Guide:_Volumes_and_Images|Guide: Volumes and Images]]&lt;br /&gt;
* Recommended practice:&lt;br /&gt;
** Take a snapshot before major changes (OS upgrades, large configuration changes).&lt;br /&gt;
** Remove outdated snapshots according to your retention plan.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Security Incidents =&lt;br /&gt;
&lt;br /&gt;
== What should I do if I suspect my VM has been compromised? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Incident&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your virtual machine is behaving unexpectedly (e.g., high CPU/network load, unknown logins, suspicious processes), it could indicate a possible compromise.&lt;br /&gt;
&lt;br /&gt;
If you suspect that your VM has been compromised, please take the following steps &#039;&#039;&#039;immediately&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard].&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;Stop the affected instance(s).&#039;&#039;&#039; &#039;&#039;Do not delete them!&#039;&#039; This preserves data for further analysis.&lt;br /&gt;
# &#039;&#039;&#039;Submit a support ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ bwSupportPortal] with the following details:&lt;br /&gt;
#*       Which instance(s) are potentially affected?&lt;br /&gt;
#* How is the suspicious behavior observed? (e.g. logs, performance, alerts)&lt;br /&gt;
#* What actions have you already taken?&lt;br /&gt;
&lt;br /&gt;
Our team will contact you as soon as possible to help investigate and resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Does the bwCloud-OS operations team inspect running instances (e.g. through penetration tests)? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Scans&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contents and configuration of user instances are not inspected&#039;&#039;&#039; — we do &#039;&#039;&#039;not&#039;&#039;&#039; perform penetration tests or port scans on the instances. We also &#039;&#039;&#039;never look inside&#039;&#039;&#039; user virtual machines.&lt;br /&gt;
&lt;br /&gt;
However, the overall bwCloud-OS operating environment is actively monitored. For example, network monitoring tracks current inbound and outbound traffic levels. If certain parameters deviate significantly from typical patterns, this may trigger further investigation —  including direct contact with the affected user.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2222</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2222"/>
		<updated>2026-04-27T11:53:18Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Security Checklist */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;By default,  bwCloud-OS VMs are only accessible via &amp;lt;strong&amp;gt;SSH (port 22)&amp;lt;/strong&amp;gt; and  &amp;lt;strong&amp;gt;ICMP&amp;lt;/strong&amp;gt; (e.g., &#039;&#039;ping&#039;&#039;);  all other incoming traffic is blocked for security.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To allow access on additional ports (e.g. HTTPS/443), you can add rules via the &amp;lt;strong&amp;gt;Security Groups&amp;lt;/strong&amp;gt; in the [https://portal.bw-cloud.org/ Dashboard] — changes take effect immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Some ports are &amp;lt;strong&amp;gt;centrally filtered&amp;lt;/strong&amp;gt; in specific bwCloud-OS regions and cannot be opened individually; refer to this [[Blocked_and_Allowed_Ports|overview]] for region-specific details.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you suspect a &amp;lt;strong&amp;gt;security incident&amp;lt;/strong&amp;gt;, stop the affected VMs and submit a [https://bw-support.scc.kit.edu/ support ticket] immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Access Control &amp;amp; Firewall Rules =&lt;br /&gt;
&lt;br /&gt;
== What network access is allowed by default in bwCloud-OS instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Default&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, &#039;&#039;&#039;bwCloud-OS instances&#039;&#039;&#039; are accessible via:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; – for remote login and configuration&lt;br /&gt;
* &#039;&#039;&#039;ICMP&#039;&#039;&#039; – to allow basic network diagnostics like &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This initial access is explicitly permitted by the &#039;&#039;&#039;automatically assigned security group&#039;&#039;&#039; (named &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;) in our configuration. This is not the default behavior in OpenStack — it is provided by bwCloud-OS to simplify first-time access for users.&lt;br /&gt;
&lt;br /&gt;
== How do I open additional ports for my instance? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Rules&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A newly created virtual machine in bwCloud-OS is only accessible from the outside via &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; and &#039;&#039;&#039;ICMP&#039;&#039;&#039;.  All other inbound traffic is &#039;&#039;&#039;blocked&#039;&#039;&#039; by default — meaning external traffic on other ports cannot reach the instance.&lt;br /&gt;
&lt;br /&gt;
To allow access on other ports (e.g. for web servers or applications), you need to &#039;&#039;&#039;add a rule&#039;&#039;&#039; to the relevant &#039;&#039;&#039;security group&#039;&#039;&#039;. &#039;&#039;Changes to security group rules apply immediately to all instances using that group&#039;&#039; — there&#039;s no need to reboot the instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening Port 443 for HTTPS Access ===&lt;br /&gt;
If you&#039;re running a web server that should be accessible via &#039;&#039;&#039;HTTPS&#039;&#039;&#039;, you typically need to open &#039;&#039;&#039;port 443&#039;&#039;&#039; in a security group assigned to your instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Steps in the [https://portal.bw-cloud.org/ Dashboard]:&#039;&#039;&#039;&lt;br /&gt;
# In the left menu, go to &#039;&#039;&#039;Network → Security Groups&#039;&#039;&#039;. A list of all defined security groups will appear.  &lt;br /&gt;
#* &#039;&#039;&#039;Recommended:&#039;&#039;&#039; Consider creating a dedicated security group (e.g. named &amp;lt;code&amp;gt;https-access&amp;lt;/code&amp;gt;), and assign it to your instance using &#039;&#039;&#039;Edit Security Groups&#039;&#039;&#039; in the instance menu before the next step.&lt;br /&gt;
# Find the relevant group and click &#039;&#039;&#039;Manage Rules&#039;&#039;&#039;. You’ll see all currently defined rules for that group.&lt;br /&gt;
# Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; to create a new one.&lt;br /&gt;
# In the dialog that appears, choose one of the following:&lt;br /&gt;
#* &#039;&#039;&#039;HTTPS&#039;&#039;&#039; from the &#039;&#039;&#039;Rule&#039;&#039;&#039; dropdown (automatically fills port 443), or&lt;br /&gt;
#* &#039;&#039;&#039;Custom TCP Rule&#039;&#039;&#039;, then manually enter &#039;&#039;&#039;443&#039;&#039;&#039; in the &#039;&#039;&#039;Port&#039;&#039;&#039; field.&lt;br /&gt;
# In the &#039;&#039;&#039;CIDR&#039;&#039;&#039; field, specify which IP addresses should be allowed to connect:&lt;br /&gt;
#* Use a specific IP range (e.g. &amp;lt;code&amp;gt;192.168.0.0/24&amp;lt;/code&amp;gt;) to &#039;&#039;&#039;limit access&#039;&#039;&#039;&lt;br /&gt;
#* ⚠️ Using &#039;&#039;&#039;&amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt;&#039;&#039;&#039; allows access from &#039;&#039;&#039;any IPv4 address&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;::/0&amp;lt;/code&amp;gt;&#039;&#039;&#039;  from &#039;&#039;&#039;any IPv6 address&#039;&#039;&#039;.&lt;br /&gt;
# Set the &#039;&#039;&#039;Direction&#039;&#039;&#039; of the rule:&lt;br /&gt;
#* &amp;lt;code&amp;gt;Ingress&amp;lt;/code&amp;gt; = incoming connections (usually what you want)&lt;br /&gt;
#* &amp;lt;code&amp;gt;Egress&amp;lt;/code&amp;gt; = outgoing connections&lt;br /&gt;
# Click &#039;&#039;&#039;Add&#039;&#039;&#039;. The rule will be created and added to the list immediately.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening a Port only for Access from Certain IP Ranges ===&lt;br /&gt;
&#039;&#039;&#039;➡️&#039;&#039;&#039;  [[Guide: Security Group|Security Groups Guide]]&lt;br /&gt;
&lt;br /&gt;
== Are some ports blocked in bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Blocked-Ports&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. Some ports are &#039;&#039;&#039;centrally&#039;&#039;&#039; &#039;&#039;&#039;blocked&#039;&#039;&#039; in &#039;&#039;&#039;certain&#039;&#039;&#039; &#039;&#039;&#039;bwCloud-OS regions&#039;&#039;&#039; due to specific network policies at the participating university data centers. Centrally blocked ports cannot be opened individually. &lt;br /&gt;
&lt;br /&gt;
For more details — including which ports are affected in each region — see the page [[Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
= General Security Recommendations =&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide a basic security checklist for virtual machines? ==&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
=== Secure SSH access ===&lt;br /&gt;
* Read and apply the recommendations in the [[Guide:_SSH|SSH guide]].&lt;br /&gt;
&lt;br /&gt;
=== Keep the system updated ===&lt;br /&gt;
Keeping your instance up to date is one of the most effective security measures: security updates fix known vulnerabilities that may otherwise be exploitable.&lt;br /&gt;
&lt;br /&gt;
There are two common approaches:&lt;br /&gt;
* &#039;&#039;&#039;Manual updates (one-time / on demand):&#039;&#039;&#039; You run updates yourself (e.g., after login, on a regular schedule).&lt;br /&gt;
* &#039;&#039;&#039;Automatic updates:&#039;&#039;&#039; The system installs security updates automatically in the background. On Ubuntu/Debian this is commonly done via &amp;lt;code&amp;gt;unattended-upgrades&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu/Debian) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Manual updates (one-time)&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt -y upgrade&lt;br /&gt;
&lt;br /&gt;
# Automatic security updates (background)&lt;br /&gt;
sudo apt -y install unattended-upgrades&lt;br /&gt;
sudo dpkg-reconfigure --priority=low unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Allow only the minimal required ports in bwCloud-OS Security Groups ===&lt;br /&gt;
Only open the ports you actually need. This reduces the attack surface and limits who can reach services on your VM.&lt;br /&gt;
&lt;br /&gt;
* Check your instance&#039;s security groups in the [https://portal.bw-cloud.org/ Dashboard] and allow only the minimal required inbound rules.&lt;br /&gt;
* Restrict access by IP range (CIDR) wherever possible (avoid &amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt; unless truly required).&lt;br /&gt;
* For step-by-step instructions and examples, see: [[Security#Security-Rules|How do I open additional ports for my instance?]]&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; some ports may be centrally filtered in certain regions; see [[Blocked_and_Allowed_Ports|Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
=== Optional host firewall  ===&lt;br /&gt;
Security groups are the primary inbound filter in bwCloud-OS. A host firewall can provide an additional layer (defense-in-depth), e.g., to enforce local policies on the VM.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu with UFW) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt -y install ufw&lt;br /&gt;
sudo ufw default deny incoming&lt;br /&gt;
sudo ufw default allow outgoing&lt;br /&gt;
&lt;br /&gt;
# Allow SSH (ideally restrict in the bwCloud-OS security group as well)&lt;br /&gt;
sudo ufw allow 22/tcp&lt;br /&gt;
&lt;br /&gt;
# Example: allow HTTPS if you opened 443 in the security group&lt;br /&gt;
sudo ufw allow 443/tcp&lt;br /&gt;
&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw status verbose&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
⚠️ If you block SSH on the host firewall while only having SSH access, you may lock yourself out. Always ensure SSH remains permitted (and test from your client).&lt;br /&gt;
&lt;br /&gt;
=== Document your configuration ===&lt;br /&gt;
To operate and troubleshoot securely, keep a record of your instance configuration:&lt;br /&gt;
&lt;br /&gt;
* Which security groups/rules are attached (ports, protocols, CIDRs)?&lt;br /&gt;
* Host firewall rules (if used), SSH hardening settings, update strategy.&lt;br /&gt;
* Installed services and exposed endpoints.&lt;br /&gt;
* Where secrets are stored/managed (avoid putting secrets in shell history or plain text files).&lt;br /&gt;
&lt;br /&gt;
=== Plan and test a backup strategy ===&lt;br /&gt;
Backups are part of security (availability and recovery).&lt;br /&gt;
&lt;br /&gt;
* Define what needs to be recoverable (system, application data, databases, configuration).&lt;br /&gt;
* Decide on backup frequency and retention (e.g., daily incremental + weekly full).&lt;br /&gt;
* Store backups separately from the instance (avoid a single point of failure).&lt;br /&gt;
* Regularly test restores (a backup that was never restored is an assumption, not a plan).&lt;br /&gt;
&lt;br /&gt;
=== Snapshots and images ===&lt;br /&gt;
Snapshots capture the state of a VM or volume at a point in time (e.g., before risky changes). They can help with rollback, but they do not automatically replace a backup strategy.&lt;br /&gt;
&lt;br /&gt;
* Learn more: [[Guide:_Volumes_and_Images|Guide: Volumes and Images]]&lt;br /&gt;
* Recommended practice:&lt;br /&gt;
** Take a snapshot before major changes (OS upgrades, large configuration changes).&lt;br /&gt;
** Remove outdated snapshots according to your retention plan.&lt;br /&gt;
&lt;br /&gt;
= SSL Certificates &amp;amp; Secure Services =&lt;br /&gt;
&lt;br /&gt;
== Can I get SSL/TLS certificates via bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SSL-Certificates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No, bwCloud-OS does &#039;&#039;&#039;not&#039;&#039;&#039; provide &#039;&#039;&#039;SSL/TLS certificates.&#039;&#039;&#039; However, you can obtain certificates directly from public providers like &#039;&#039;&#039;Let’s Encrypt&#039;&#039;&#039; using tools such as &#039;&#039;&#039;[https://certbot.eff.org/ Certbot]&#039;&#039;&#039;, which you can install and run on your instance.&lt;br /&gt;
&lt;br /&gt;
This allows you, for example, to enable &#039;&#039;&#039;HTTPS&#039;&#039;&#039; for services running on your VM. Don&#039;t forget to open the necessary ports (e.g., 443) using [[Security#Security-Rules|security group rules]].&lt;br /&gt;
&lt;br /&gt;
=Security Incidents =&lt;br /&gt;
&lt;br /&gt;
== What should I do if I suspect my VM has been compromised? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Incident&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your virtual machine is behaving unexpectedly (e.g., high CPU/network load, unknown logins, suspicious processes), it could indicate a possible compromise.&lt;br /&gt;
&lt;br /&gt;
If you suspect that your VM has been compromised, please take the following steps &#039;&#039;&#039;immediately&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard].&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;Stop the affected instance(s).&#039;&#039;&#039; &#039;&#039;Do not delete them!&#039;&#039; This preserves data for further analysis.&lt;br /&gt;
# &#039;&#039;&#039;Submit a support ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ bwSupportPortal] with the following details:&lt;br /&gt;
#*       Which instance(s) are potentially affected?&lt;br /&gt;
#* How is the suspicious behavior observed? (e.g. logs, performance, alerts)&lt;br /&gt;
#* What actions have you already taken?&lt;br /&gt;
&lt;br /&gt;
Our team will contact you as soon as possible to help investigate and resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Does the bwCloud-OS operations team inspect running instances (e.g. through penetration tests)? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Scans&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contents and configuration of user instances are not inspected&#039;&#039;&#039; — we do &#039;&#039;&#039;not&#039;&#039;&#039; perform penetration tests or port scans on the instances. We also &#039;&#039;&#039;never look inside&#039;&#039;&#039; user virtual machines.&lt;br /&gt;
&lt;br /&gt;
However, the overall bwCloud-OS operating environment is actively monitored. For example, network monitoring tracks current inbound and outbound traffic levels. If certain parameters deviate significantly from typical patterns, this may trigger further investigation —  including direct contact with the affected user.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2221</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2221"/>
		<updated>2026-04-27T11:49:05Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Optional: host firewall */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;By default,  bwCloud-OS VMs are only accessible via &amp;lt;strong&amp;gt;SSH (port 22)&amp;lt;/strong&amp;gt; and  &amp;lt;strong&amp;gt;ICMP&amp;lt;/strong&amp;gt; (e.g., &#039;&#039;ping&#039;&#039;);  all other incoming traffic is blocked for security.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To allow access on additional ports (e.g. HTTPS/443), you can add rules via the &amp;lt;strong&amp;gt;Security Groups&amp;lt;/strong&amp;gt; in the [https://portal.bw-cloud.org/ Dashboard] — changes take effect immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Some ports are &amp;lt;strong&amp;gt;centrally filtered&amp;lt;/strong&amp;gt; in specific bwCloud-OS regions and cannot be opened individually; refer to this [[Blocked_and_Allowed_Ports|overview]] for region-specific details.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you suspect a &amp;lt;strong&amp;gt;security incident&amp;lt;/strong&amp;gt;, stop the affected VMs and submit a [https://bw-support.scc.kit.edu/ support ticket] immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Access Control &amp;amp; Firewall Rules =&lt;br /&gt;
&lt;br /&gt;
== What network access is allowed by default in bwCloud-OS instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Default&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, &#039;&#039;&#039;bwCloud-OS instances&#039;&#039;&#039; are accessible via:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; – for remote login and configuration&lt;br /&gt;
* &#039;&#039;&#039;ICMP&#039;&#039;&#039; – to allow basic network diagnostics like &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This initial access is explicitly permitted by the &#039;&#039;&#039;automatically assigned security group&#039;&#039;&#039; (named &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;) in our configuration. This is not the default behavior in OpenStack — it is provided by bwCloud-OS to simplify first-time access for users.&lt;br /&gt;
&lt;br /&gt;
== How do I open additional ports for my instance? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Rules&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A newly created virtual machine in bwCloud-OS is only accessible from the outside via &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; and &#039;&#039;&#039;ICMP&#039;&#039;&#039;.  All other inbound traffic is &#039;&#039;&#039;blocked&#039;&#039;&#039; by default — meaning external traffic on other ports cannot reach the instance.&lt;br /&gt;
&lt;br /&gt;
To allow access on other ports (e.g. for web servers or applications), you need to &#039;&#039;&#039;add a rule&#039;&#039;&#039; to the relevant &#039;&#039;&#039;security group&#039;&#039;&#039;. &#039;&#039;Changes to security group rules apply immediately to all instances using that group&#039;&#039; — there&#039;s no need to reboot the instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening Port 443 for HTTPS Access ===&lt;br /&gt;
If you&#039;re running a web server that should be accessible via &#039;&#039;&#039;HTTPS&#039;&#039;&#039;, you typically need to open &#039;&#039;&#039;port 443&#039;&#039;&#039; in a security group assigned to your instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Steps in the [https://portal.bw-cloud.org/ Dashboard]:&#039;&#039;&#039;&lt;br /&gt;
# In the left menu, go to &#039;&#039;&#039;Network → Security Groups&#039;&#039;&#039;. A list of all defined security groups will appear.  &lt;br /&gt;
#* &#039;&#039;&#039;Recommended:&#039;&#039;&#039; Consider creating a dedicated security group (e.g. named &amp;lt;code&amp;gt;https-access&amp;lt;/code&amp;gt;), and assign it to your instance using &#039;&#039;&#039;Edit Security Groups&#039;&#039;&#039; in the instance menu before the next step.&lt;br /&gt;
# Find the relevant group and click &#039;&#039;&#039;Manage Rules&#039;&#039;&#039;. You’ll see all currently defined rules for that group.&lt;br /&gt;
# Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; to create a new one.&lt;br /&gt;
# In the dialog that appears, choose one of the following:&lt;br /&gt;
#* &#039;&#039;&#039;HTTPS&#039;&#039;&#039; from the &#039;&#039;&#039;Rule&#039;&#039;&#039; dropdown (automatically fills port 443), or&lt;br /&gt;
#* &#039;&#039;&#039;Custom TCP Rule&#039;&#039;&#039;, then manually enter &#039;&#039;&#039;443&#039;&#039;&#039; in the &#039;&#039;&#039;Port&#039;&#039;&#039; field.&lt;br /&gt;
# In the &#039;&#039;&#039;CIDR&#039;&#039;&#039; field, specify which IP addresses should be allowed to connect:&lt;br /&gt;
#* Use a specific IP range (e.g. &amp;lt;code&amp;gt;192.168.0.0/24&amp;lt;/code&amp;gt;) to &#039;&#039;&#039;limit access&#039;&#039;&#039;&lt;br /&gt;
#* ⚠️ Using &#039;&#039;&#039;&amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt;&#039;&#039;&#039; allows access from &#039;&#039;&#039;any IPv4 address&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;::/0&amp;lt;/code&amp;gt;&#039;&#039;&#039;  from &#039;&#039;&#039;any IPv6 address&#039;&#039;&#039;.&lt;br /&gt;
# Set the &#039;&#039;&#039;Direction&#039;&#039;&#039; of the rule:&lt;br /&gt;
#* &amp;lt;code&amp;gt;Ingress&amp;lt;/code&amp;gt; = incoming connections (usually what you want)&lt;br /&gt;
#* &amp;lt;code&amp;gt;Egress&amp;lt;/code&amp;gt; = outgoing connections&lt;br /&gt;
# Click &#039;&#039;&#039;Add&#039;&#039;&#039;. The rule will be created and added to the list immediately.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening a Port only for Access from Certain IP Ranges ===&lt;br /&gt;
&#039;&#039;&#039;➡️&#039;&#039;&#039;  [[Guide: Security Group|Security Groups Guide]]&lt;br /&gt;
&lt;br /&gt;
== Are some ports blocked in bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Blocked-Ports&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. Some ports are &#039;&#039;&#039;centrally&#039;&#039;&#039; &#039;&#039;&#039;blocked&#039;&#039;&#039; in &#039;&#039;&#039;certain&#039;&#039;&#039; &#039;&#039;&#039;bwCloud-OS regions&#039;&#039;&#039; due to specific network policies at the participating university data centers. Centrally blocked ports cannot be opened individually. &lt;br /&gt;
&lt;br /&gt;
For more details — including which ports are affected in each region — see the page [[Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
= Security Checklist =&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide a basic security checklist for virtual machines? ==&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
=== Secure SSH access ===&lt;br /&gt;
* Read and apply the recommendations in the [[Guide:_SSH|SSH guide]].&lt;br /&gt;
&lt;br /&gt;
=== Keep the system updated ===&lt;br /&gt;
Keeping your instance up to date is one of the most effective security measures: security updates fix known vulnerabilities that may otherwise be exploitable.&lt;br /&gt;
&lt;br /&gt;
There are two common approaches:&lt;br /&gt;
* &#039;&#039;&#039;Manual updates (one-time / on demand):&#039;&#039;&#039; You run updates yourself (e.g., after login, on a regular schedule).&lt;br /&gt;
* &#039;&#039;&#039;Automatic updates:&#039;&#039;&#039; The system installs security updates automatically in the background. On Ubuntu/Debian this is commonly done via &amp;lt;code&amp;gt;unattended-upgrades&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu/Debian) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Manual updates (one-time)&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt -y upgrade&lt;br /&gt;
&lt;br /&gt;
# Automatic security updates (background)&lt;br /&gt;
sudo apt -y install unattended-upgrades&lt;br /&gt;
sudo dpkg-reconfigure --priority=low unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Allow only the minimal required ports in bwCloud-OS Security Groups ===&lt;br /&gt;
Only open the ports you actually need. This reduces the attack surface and limits who can reach services on your VM.&lt;br /&gt;
&lt;br /&gt;
* Check your instance&#039;s security groups in the [https://portal.bw-cloud.org/ Dashboard] and allow only the minimal required inbound rules.&lt;br /&gt;
* Restrict access by IP range (CIDR) wherever possible (avoid &amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt; unless truly required).&lt;br /&gt;
* For step-by-step instructions and examples, see: [[Security#Security-Rules|How do I open additional ports for my instance?]]&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; some ports may be centrally filtered in certain regions; see [[Blocked_and_Allowed_Ports|Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
=== Optional host firewall  ===&lt;br /&gt;
Security groups are the primary inbound filter in bwCloud-OS. A host firewall can provide an additional layer (defense-in-depth), e.g., to enforce local policies on the VM.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu with UFW) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt -y install ufw&lt;br /&gt;
sudo ufw default deny incoming&lt;br /&gt;
sudo ufw default allow outgoing&lt;br /&gt;
&lt;br /&gt;
# Allow SSH (ideally restrict in the bwCloud-OS security group as well)&lt;br /&gt;
sudo ufw allow 22/tcp&lt;br /&gt;
&lt;br /&gt;
# Example: allow HTTPS if you opened 443 in the security group&lt;br /&gt;
sudo ufw allow 443/tcp&lt;br /&gt;
&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw status verbose&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
⚠️ If you block SSH on the host firewall while only having SSH access, you may lock yourself out. Always ensure SSH remains permitted (and test from your client).&lt;br /&gt;
&lt;br /&gt;
=== Document your configuration ===&lt;br /&gt;
To operate and troubleshoot securely, keep a record of your instance configuration:&lt;br /&gt;
&lt;br /&gt;
* Which security groups/rules are attached (ports, protocols, CIDRs)?&lt;br /&gt;
* Host firewall rules (if used), SSH hardening settings, update strategy.&lt;br /&gt;
* Installed services and exposed endpoints.&lt;br /&gt;
* Where secrets are stored/managed (avoid putting secrets in shell history or plain text files).&lt;br /&gt;
&lt;br /&gt;
=== Plan and test a backup strategy ===&lt;br /&gt;
Backups are part of security (availability and recovery).&lt;br /&gt;
&lt;br /&gt;
* Define what needs to be recoverable (system, application data, databases, configuration).&lt;br /&gt;
* Decide on backup frequency and retention (e.g., daily incremental + weekly full).&lt;br /&gt;
* Store backups separately from the instance (avoid a single point of failure).&lt;br /&gt;
* Regularly test restores (a backup that was never restored is an assumption, not a plan).&lt;br /&gt;
&lt;br /&gt;
=== Snapshots and images ===&lt;br /&gt;
Snapshots capture the state of a VM or volume at a point in time (e.g., before risky changes). They can help with rollback, but they do not automatically replace a backup strategy.&lt;br /&gt;
&lt;br /&gt;
* Learn more: [[Guide:_Volumes_and_Images|Guide: Volumes and Images]]&lt;br /&gt;
* Recommended practice:&lt;br /&gt;
** Take a snapshot before major changes (OS upgrades, large configuration changes).&lt;br /&gt;
** Remove outdated snapshots according to your retention plan.&lt;br /&gt;
&lt;br /&gt;
= SSL Certificates &amp;amp; Secure Services =&lt;br /&gt;
&lt;br /&gt;
== Can I get SSL/TLS certificates via bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SSL-Certificates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No, bwCloud-OS does &#039;&#039;&#039;not&#039;&#039;&#039; provide &#039;&#039;&#039;SSL/TLS certificates.&#039;&#039;&#039; However, you can obtain certificates directly from public providers like &#039;&#039;&#039;Let’s Encrypt&#039;&#039;&#039; using tools such as &#039;&#039;&#039;[https://certbot.eff.org/ Certbot]&#039;&#039;&#039;, which you can install and run on your instance.&lt;br /&gt;
&lt;br /&gt;
This allows you, for example, to enable &#039;&#039;&#039;HTTPS&#039;&#039;&#039; for services running on your VM. Don&#039;t forget to open the necessary ports (e.g., 443) using [[Security#Security-Rules|security group rules]].&lt;br /&gt;
&lt;br /&gt;
=Security Incidents =&lt;br /&gt;
&lt;br /&gt;
== What should I do if I suspect my VM has been compromised? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Incident&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your virtual machine is behaving unexpectedly (e.g., high CPU/network load, unknown logins, suspicious processes), it could indicate a possible compromise.&lt;br /&gt;
&lt;br /&gt;
If you suspect that your VM has been compromised, please take the following steps &#039;&#039;&#039;immediately&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard].&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;Stop the affected instance(s).&#039;&#039;&#039; &#039;&#039;Do not delete them!&#039;&#039; This preserves data for further analysis.&lt;br /&gt;
# &#039;&#039;&#039;Submit a support ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ bwSupportPortal] with the following details:&lt;br /&gt;
#*       Which instance(s) are potentially affected?&lt;br /&gt;
#* How is the suspicious behavior observed? (e.g. logs, performance, alerts)&lt;br /&gt;
#* What actions have you already taken?&lt;br /&gt;
&lt;br /&gt;
Our team will contact you as soon as possible to help investigate and resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Does the bwCloud-OS operations team inspect running instances (e.g. through penetration tests)? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Scans&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contents and configuration of user instances are not inspected&#039;&#039;&#039; — we do &#039;&#039;&#039;not&#039;&#039;&#039; perform penetration tests or port scans on the instances. We also &#039;&#039;&#039;never look inside&#039;&#039;&#039; user virtual machines.&lt;br /&gt;
&lt;br /&gt;
However, the overall bwCloud-OS operating environment is actively monitored. For example, network monitoring tracks current inbound and outbound traffic levels. If certain parameters deviate significantly from typical patterns, this may trigger further investigation —  including direct contact with the affected user.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2220</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2220"/>
		<updated>2026-04-27T11:46:00Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;By default,  bwCloud-OS VMs are only accessible via &amp;lt;strong&amp;gt;SSH (port 22)&amp;lt;/strong&amp;gt; and  &amp;lt;strong&amp;gt;ICMP&amp;lt;/strong&amp;gt; (e.g., &#039;&#039;ping&#039;&#039;);  all other incoming traffic is blocked for security.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To allow access on additional ports (e.g. HTTPS/443), you can add rules via the &amp;lt;strong&amp;gt;Security Groups&amp;lt;/strong&amp;gt; in the [https://portal.bw-cloud.org/ Dashboard] — changes take effect immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Some ports are &amp;lt;strong&amp;gt;centrally filtered&amp;lt;/strong&amp;gt; in specific bwCloud-OS regions and cannot be opened individually; refer to this [[Blocked_and_Allowed_Ports|overview]] for region-specific details.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you suspect a &amp;lt;strong&amp;gt;security incident&amp;lt;/strong&amp;gt;, stop the affected VMs and submit a [https://bw-support.scc.kit.edu/ support ticket] immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Access Control &amp;amp; Firewall Rules =&lt;br /&gt;
&lt;br /&gt;
== What network access is allowed by default in bwCloud-OS instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Default&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, &#039;&#039;&#039;bwCloud-OS instances&#039;&#039;&#039; are accessible via:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; – for remote login and configuration&lt;br /&gt;
* &#039;&#039;&#039;ICMP&#039;&#039;&#039; – to allow basic network diagnostics like &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This initial access is explicitly permitted by the &#039;&#039;&#039;automatically assigned security group&#039;&#039;&#039; (named &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;) in our configuration. This is not the default behavior in OpenStack — it is provided by bwCloud-OS to simplify first-time access for users.&lt;br /&gt;
&lt;br /&gt;
== How do I open additional ports for my instance? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Rules&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A newly created virtual machine in bwCloud-OS is only accessible from the outside via &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; and &#039;&#039;&#039;ICMP&#039;&#039;&#039;.  All other inbound traffic is &#039;&#039;&#039;blocked&#039;&#039;&#039; by default — meaning external traffic on other ports cannot reach the instance.&lt;br /&gt;
&lt;br /&gt;
To allow access on other ports (e.g. for web servers or applications), you need to &#039;&#039;&#039;add a rule&#039;&#039;&#039; to the relevant &#039;&#039;&#039;security group&#039;&#039;&#039;. &#039;&#039;Changes to security group rules apply immediately to all instances using that group&#039;&#039; — there&#039;s no need to reboot the instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening Port 443 for HTTPS Access ===&lt;br /&gt;
If you&#039;re running a web server that should be accessible via &#039;&#039;&#039;HTTPS&#039;&#039;&#039;, you typically need to open &#039;&#039;&#039;port 443&#039;&#039;&#039; in a security group assigned to your instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Steps in the [https://portal.bw-cloud.org/ Dashboard]:&#039;&#039;&#039;&lt;br /&gt;
# In the left menu, go to &#039;&#039;&#039;Network → Security Groups&#039;&#039;&#039;. A list of all defined security groups will appear.  &lt;br /&gt;
#* &#039;&#039;&#039;Recommended:&#039;&#039;&#039; Consider creating a dedicated security group (e.g. named &amp;lt;code&amp;gt;https-access&amp;lt;/code&amp;gt;), and assign it to your instance using &#039;&#039;&#039;Edit Security Groups&#039;&#039;&#039; in the instance menu before the next step.&lt;br /&gt;
# Find the relevant group and click &#039;&#039;&#039;Manage Rules&#039;&#039;&#039;. You’ll see all currently defined rules for that group.&lt;br /&gt;
# Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; to create a new one.&lt;br /&gt;
# In the dialog that appears, choose one of the following:&lt;br /&gt;
#* &#039;&#039;&#039;HTTPS&#039;&#039;&#039; from the &#039;&#039;&#039;Rule&#039;&#039;&#039; dropdown (automatically fills port 443), or&lt;br /&gt;
#* &#039;&#039;&#039;Custom TCP Rule&#039;&#039;&#039;, then manually enter &#039;&#039;&#039;443&#039;&#039;&#039; in the &#039;&#039;&#039;Port&#039;&#039;&#039; field.&lt;br /&gt;
# In the &#039;&#039;&#039;CIDR&#039;&#039;&#039; field, specify which IP addresses should be allowed to connect:&lt;br /&gt;
#* Use a specific IP range (e.g. &amp;lt;code&amp;gt;192.168.0.0/24&amp;lt;/code&amp;gt;) to &#039;&#039;&#039;limit access&#039;&#039;&#039;&lt;br /&gt;
#* ⚠️ Using &#039;&#039;&#039;&amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt;&#039;&#039;&#039; allows access from &#039;&#039;&#039;any IPv4 address&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;::/0&amp;lt;/code&amp;gt;&#039;&#039;&#039;  from &#039;&#039;&#039;any IPv6 address&#039;&#039;&#039;.&lt;br /&gt;
# Set the &#039;&#039;&#039;Direction&#039;&#039;&#039; of the rule:&lt;br /&gt;
#* &amp;lt;code&amp;gt;Ingress&amp;lt;/code&amp;gt; = incoming connections (usually what you want)&lt;br /&gt;
#* &amp;lt;code&amp;gt;Egress&amp;lt;/code&amp;gt; = outgoing connections&lt;br /&gt;
# Click &#039;&#039;&#039;Add&#039;&#039;&#039;. The rule will be created and added to the list immediately.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening a Port only for Access from Certain IP Ranges ===&lt;br /&gt;
&#039;&#039;&#039;➡️&#039;&#039;&#039;  [[Guide: Security Group|Security Groups Guide]]&lt;br /&gt;
&lt;br /&gt;
== Are some ports blocked in bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Blocked-Ports&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. Some ports are &#039;&#039;&#039;centrally&#039;&#039;&#039; &#039;&#039;&#039;blocked&#039;&#039;&#039; in &#039;&#039;&#039;certain&#039;&#039;&#039; &#039;&#039;&#039;bwCloud-OS regions&#039;&#039;&#039; due to specific network policies at the participating university data centers. Centrally blocked ports cannot be opened individually. &lt;br /&gt;
&lt;br /&gt;
For more details — including which ports are affected in each region — see the page [[Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
= Security Checklist =&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide a basic security checklist for virtual machines? ==&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
=== Secure SSH access ===&lt;br /&gt;
* Read and apply the recommendations in the [[Guide:_SSH|SSH guide]].&lt;br /&gt;
&lt;br /&gt;
=== Keep the system updated ===&lt;br /&gt;
Keeping your instance up to date is one of the most effective security measures: security updates fix known vulnerabilities that may otherwise be exploitable.&lt;br /&gt;
&lt;br /&gt;
There are two common approaches:&lt;br /&gt;
* &#039;&#039;&#039;Manual updates (one-time / on demand):&#039;&#039;&#039; You run updates yourself (e.g., after login, on a regular schedule).&lt;br /&gt;
* &#039;&#039;&#039;Automatic updates:&#039;&#039;&#039; The system installs security updates automatically in the background. On Ubuntu/Debian this is commonly done via &amp;lt;code&amp;gt;unattended-upgrades&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu/Debian) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Manual updates (one-time)&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt -y upgrade&lt;br /&gt;
&lt;br /&gt;
# Automatic security updates (background)&lt;br /&gt;
sudo apt -y install unattended-upgrades&lt;br /&gt;
sudo dpkg-reconfigure --priority=low unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Allow only the minimal required ports in bwCloud-OS Security Groups ===&lt;br /&gt;
Only open the ports you actually need. This reduces the attack surface and limits who can reach services on your VM.&lt;br /&gt;
&lt;br /&gt;
* Check your instance&#039;s security groups in the [https://portal.bw-cloud.org/ Dashboard] and allow only the minimal required inbound rules.&lt;br /&gt;
* Restrict access by IP range (CIDR) wherever possible (avoid &amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt; unless truly required).&lt;br /&gt;
* For step-by-step instructions and examples, see: [[Security#Security-Rules|How do I open additional ports for my instance?]]&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; some ports may be centrally filtered in certain regions; see [[Blocked_and_Allowed_Ports|Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
=== Optional: host firewall  ===&lt;br /&gt;
Security groups are the primary inbound filter in bwCloud-OS. A host firewall can provide an additional layer (defense-in-depth), e.g., to enforce local policies on the VM.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu with UFW) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt -y install ufw&lt;br /&gt;
sudo ufw default deny incoming&lt;br /&gt;
sudo ufw default allow outgoing&lt;br /&gt;
&lt;br /&gt;
# Allow SSH (ideally restrict in the bwCloud-OS security group as well)&lt;br /&gt;
sudo ufw allow 22/tcp&lt;br /&gt;
&lt;br /&gt;
# Example: allow HTTPS if you opened 443 in the security group&lt;br /&gt;
sudo ufw allow 443/tcp&lt;br /&gt;
&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw status verbose&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
⚠️ If you block SSH on the host firewall while only having SSH access, you may lock yourself out. Always ensure SSH remains permitted (and test from your client).&lt;br /&gt;
&lt;br /&gt;
=== Document your configuration ===&lt;br /&gt;
To operate and troubleshoot securely, keep a record of your instance configuration:&lt;br /&gt;
&lt;br /&gt;
* Which security groups/rules are attached (ports, protocols, CIDRs)?&lt;br /&gt;
* Host firewall rules (if used), SSH hardening settings, update strategy.&lt;br /&gt;
* Installed services and exposed endpoints.&lt;br /&gt;
* Where secrets are stored/managed (avoid putting secrets in shell history or plain text files).&lt;br /&gt;
&lt;br /&gt;
=== Plan and test a backup strategy ===&lt;br /&gt;
Backups are part of security (availability and recovery).&lt;br /&gt;
&lt;br /&gt;
* Define what needs to be recoverable (system, application data, databases, configuration).&lt;br /&gt;
* Decide on backup frequency and retention (e.g., daily incremental + weekly full).&lt;br /&gt;
* Store backups separately from the instance (avoid a single point of failure).&lt;br /&gt;
* Regularly test restores (a backup that was never restored is an assumption, not a plan).&lt;br /&gt;
&lt;br /&gt;
=== Snapshots and images ===&lt;br /&gt;
Snapshots capture the state of a VM or volume at a point in time (e.g., before risky changes). They can help with rollback, but they do not automatically replace a backup strategy.&lt;br /&gt;
&lt;br /&gt;
* Learn more: [[Guide:_Volumes_and_Images|Guide: Volumes and Images]]&lt;br /&gt;
* Recommended practice:&lt;br /&gt;
** Take a snapshot before major changes (OS upgrades, large configuration changes).&lt;br /&gt;
** Remove outdated snapshots according to your retention plan.&lt;br /&gt;
&lt;br /&gt;
= SSL Certificates &amp;amp; Secure Services =&lt;br /&gt;
&lt;br /&gt;
== Can I get SSL/TLS certificates via bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SSL-Certificates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No, bwCloud-OS does &#039;&#039;&#039;not&#039;&#039;&#039; provide &#039;&#039;&#039;SSL/TLS certificates.&#039;&#039;&#039; However, you can obtain certificates directly from public providers like &#039;&#039;&#039;Let’s Encrypt&#039;&#039;&#039; using tools such as &#039;&#039;&#039;[https://certbot.eff.org/ Certbot]&#039;&#039;&#039;, which you can install and run on your instance.&lt;br /&gt;
&lt;br /&gt;
This allows you, for example, to enable &#039;&#039;&#039;HTTPS&#039;&#039;&#039; for services running on your VM. Don&#039;t forget to open the necessary ports (e.g., 443) using [[Security#Security-Rules|security group rules]].&lt;br /&gt;
&lt;br /&gt;
=Security Incidents =&lt;br /&gt;
&lt;br /&gt;
== What should I do if I suspect my VM has been compromised? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Incident&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your virtual machine is behaving unexpectedly (e.g., high CPU/network load, unknown logins, suspicious processes), it could indicate a possible compromise.&lt;br /&gt;
&lt;br /&gt;
If you suspect that your VM has been compromised, please take the following steps &#039;&#039;&#039;immediately&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard].&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;Stop the affected instance(s).&#039;&#039;&#039; &#039;&#039;Do not delete them!&#039;&#039; This preserves data for further analysis.&lt;br /&gt;
# &#039;&#039;&#039;Submit a support ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ bwSupportPortal] with the following details:&lt;br /&gt;
#*       Which instance(s) are potentially affected?&lt;br /&gt;
#* How is the suspicious behavior observed? (e.g. logs, performance, alerts)&lt;br /&gt;
#* What actions have you already taken?&lt;br /&gt;
&lt;br /&gt;
Our team will contact you as soon as possible to help investigate and resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Does the bwCloud-OS operations team inspect running instances (e.g. through penetration tests)? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Scans&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contents and configuration of user instances are not inspected&#039;&#039;&#039; — we do &#039;&#039;&#039;not&#039;&#039;&#039; perform penetration tests or port scans on the instances. We also &#039;&#039;&#039;never look inside&#039;&#039;&#039; user virtual machines.&lt;br /&gt;
&lt;br /&gt;
However, the overall bwCloud-OS operating environment is actively monitored. For example, network monitoring tracks current inbound and outbound traffic levels. If certain parameters deviate significantly from typical patterns, this may trigger further investigation —  including direct contact with the affected user.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2219</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2219"/>
		<updated>2026-04-27T11:43:59Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Optional host firewall (e.g., UFW on Ubuntu) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;By default,  bwCloud-OS VMs are only accessible via &amp;lt;strong&amp;gt;SSH (port 22)&amp;lt;/strong&amp;gt; and  &amp;lt;strong&amp;gt;ICMP&amp;lt;/strong&amp;gt; (e.g., &#039;&#039;ping&#039;&#039;);  all other incoming traffic is blocked for security.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To allow access on additional ports (e.g. HTTPS/443), you can add rules via the &amp;lt;strong&amp;gt;Security Groups&amp;lt;/strong&amp;gt; in the [https://portal.bw-cloud.org/ Dashboard] — changes take effect immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Some ports are &amp;lt;strong&amp;gt;centrally filtered&amp;lt;/strong&amp;gt; in specific bwCloud-OS regions and cannot be opened individually; refer to this [[Blocked_and_Allowed_Ports|overview]] for region-specific details.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you suspect a &amp;lt;strong&amp;gt;security incident&amp;lt;/strong&amp;gt;, stop the affected VMs and submit a [https://bw-support.scc.kit.edu/ support ticket] immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Access Control &amp;amp; Firewall Rules =&lt;br /&gt;
&lt;br /&gt;
== What network access is allowed by default in bwCloud-OS instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Default&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, &#039;&#039;&#039;bwCloud-OS instances&#039;&#039;&#039; are accessible via:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; – for remote login and configuration&lt;br /&gt;
* &#039;&#039;&#039;ICMP&#039;&#039;&#039; – to allow basic network diagnostics like &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This initial access is explicitly permitted by the &#039;&#039;&#039;automatically assigned security group&#039;&#039;&#039; (named &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;) in our configuration. This is not the default behavior in OpenStack — it is provided by bwCloud-OS to simplify first-time access for users.&lt;br /&gt;
&lt;br /&gt;
== How do I open additional ports for my instance? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Rules&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A newly created virtual machine in bwCloud-OS is only accessible from the outside via &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; and &#039;&#039;&#039;ICMP&#039;&#039;&#039;.  All other inbound traffic is &#039;&#039;&#039;blocked&#039;&#039;&#039; by default — meaning external traffic on other ports cannot reach the instance.&lt;br /&gt;
&lt;br /&gt;
To allow access on other ports (e.g. for web servers or applications), you need to &#039;&#039;&#039;add a rule&#039;&#039;&#039; to the relevant &#039;&#039;&#039;security group&#039;&#039;&#039;. &#039;&#039;Changes to security group rules apply immediately to all instances using that group&#039;&#039; — there&#039;s no need to reboot the instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening Port 443 for HTTPS Access ===&lt;br /&gt;
If you&#039;re running a web server that should be accessible via &#039;&#039;&#039;HTTPS&#039;&#039;&#039;, you typically need to open &#039;&#039;&#039;port 443&#039;&#039;&#039; in a security group assigned to your instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Steps in the [https://portal.bw-cloud.org/ Dashboard]:&#039;&#039;&#039;&lt;br /&gt;
# In the left menu, go to &#039;&#039;&#039;Network → Security Groups&#039;&#039;&#039;. A list of all defined security groups will appear.  &lt;br /&gt;
#* &#039;&#039;&#039;Recommended:&#039;&#039;&#039; Consider creating a dedicated security group (e.g. named &amp;lt;code&amp;gt;https-access&amp;lt;/code&amp;gt;), and assign it to your instance using &#039;&#039;&#039;Edit Security Groups&#039;&#039;&#039; in the instance menu before the next step.&lt;br /&gt;
# Find the relevant group and click &#039;&#039;&#039;Manage Rules&#039;&#039;&#039;. You’ll see all currently defined rules for that group.&lt;br /&gt;
# Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; to create a new one.&lt;br /&gt;
# In the dialog that appears, choose one of the following:&lt;br /&gt;
#* &#039;&#039;&#039;HTTPS&#039;&#039;&#039; from the &#039;&#039;&#039;Rule&#039;&#039;&#039; dropdown (automatically fills port 443), or&lt;br /&gt;
#* &#039;&#039;&#039;Custom TCP Rule&#039;&#039;&#039;, then manually enter &#039;&#039;&#039;443&#039;&#039;&#039; in the &#039;&#039;&#039;Port&#039;&#039;&#039; field.&lt;br /&gt;
# In the &#039;&#039;&#039;CIDR&#039;&#039;&#039; field, specify which IP addresses should be allowed to connect:&lt;br /&gt;
#* Use a specific IP range (e.g. &amp;lt;code&amp;gt;192.168.0.0/24&amp;lt;/code&amp;gt;) to &#039;&#039;&#039;limit access&#039;&#039;&#039;&lt;br /&gt;
#* ⚠️ Using &#039;&#039;&#039;&amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt;&#039;&#039;&#039; allows access from &#039;&#039;&#039;any IPv4 address&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;::/0&amp;lt;/code&amp;gt;&#039;&#039;&#039;  from &#039;&#039;&#039;any IPv6 address&#039;&#039;&#039;.&lt;br /&gt;
# Set the &#039;&#039;&#039;Direction&#039;&#039;&#039; of the rule:&lt;br /&gt;
#* &amp;lt;code&amp;gt;Ingress&amp;lt;/code&amp;gt; = incoming connections (usually what you want)&lt;br /&gt;
#* &amp;lt;code&amp;gt;Egress&amp;lt;/code&amp;gt; = outgoing connections&lt;br /&gt;
# Click &#039;&#039;&#039;Add&#039;&#039;&#039;. The rule will be created and added to the list immediately.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening a Port only for Access from Certain IP Ranges ===&lt;br /&gt;
&#039;&#039;&#039;➡️&#039;&#039;&#039;  [[Guide: Security Group|Security Groups Guide]]&lt;br /&gt;
&lt;br /&gt;
== Are some ports blocked in bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Blocked-Ports&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. Some ports are &#039;&#039;&#039;centrally&#039;&#039;&#039; &#039;&#039;&#039;blocked&#039;&#039;&#039; in &#039;&#039;&#039;certain&#039;&#039;&#039; &#039;&#039;&#039;bwCloud-OS regions&#039;&#039;&#039; due to specific network policies at the participating university data centers. Centrally blocked ports cannot be opened individually. &lt;br /&gt;
&lt;br /&gt;
For more details — including which ports are affected in each region — see the page [[Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
= Security Checklist =&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide a basic security checklist for virtual machines? ==&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
=== Secure SSH access ===&lt;br /&gt;
* Read and apply the recommendations in the [[Guide:_SSH|SSH guide]].&lt;br /&gt;
&lt;br /&gt;
=== Keep the system updated ===&lt;br /&gt;
Keeping your instance up to date is one of the most effective security measures: security updates fix known vulnerabilities that may otherwise be exploitable.&lt;br /&gt;
&lt;br /&gt;
There are two common approaches:&lt;br /&gt;
* &#039;&#039;&#039;Manual updates (one-time / on demand):&#039;&#039;&#039; You run updates yourself (e.g., after login, on a regular schedule).&lt;br /&gt;
* &#039;&#039;&#039;Automatic updates:&#039;&#039;&#039; The system installs security updates automatically in the background. On Ubuntu/Debian this is commonly done via &amp;lt;code&amp;gt;unattended-upgrades&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu/Debian) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Manual updates (one-time)&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt -y upgrade&lt;br /&gt;
&lt;br /&gt;
# Automatic security updates (background)&lt;br /&gt;
sudo apt -y install unattended-upgrades&lt;br /&gt;
sudo dpkg-reconfigure --priority=low unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Allow only the minimal required ports in bwCloud-OS Security Groups ===&lt;br /&gt;
Only open the ports you actually need. This reduces the attack surface and limits who can reach services on your VM.&lt;br /&gt;
&lt;br /&gt;
* Check your instance&#039;s security groups in the [https://portal.bw-cloud.org/ Dashboard] and allow only the minimal required inbound rules.&lt;br /&gt;
* Restrict access by IP range (CIDR) wherever possible (avoid &amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt; unless truly required).&lt;br /&gt;
* For step-by-step instructions and examples, see: [[Security#Security-Rules|How do I open additional ports for my instance?]]&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; some ports may be centrally filtered in certain regions; see [[Blocked_and_Allowed_Ports|Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
=== Optional: host firewall  ===&lt;br /&gt;
Security groups are the primary inbound filter in bwCloud-OS. A host firewall can provide an additional layer (defense-in-depth), e.g., to enforce local policies on the VM.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu with UFW) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt -y install ufw&lt;br /&gt;
sudo ufw default deny incoming&lt;br /&gt;
sudo ufw default allow outgoing&lt;br /&gt;
&lt;br /&gt;
# Allow SSH (ideally restrict in the bwCloud-OS security group as well)&lt;br /&gt;
sudo ufw allow 22/tcp&lt;br /&gt;
&lt;br /&gt;
# Example: allow HTTPS if you opened 443 in the security group&lt;br /&gt;
sudo ufw allow 443/tcp&lt;br /&gt;
&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw status verbose&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Important:&#039;&#039; If you block SSH on the host firewall while only having SSH access, you may lock yourself out. Always ensure SSH remains permitted (and test from your client).&lt;br /&gt;
&lt;br /&gt;
=== Document your configuration ===&lt;br /&gt;
To operate and troubleshoot securely, keep a record of your instance configuration:&lt;br /&gt;
&lt;br /&gt;
* Which security groups/rules are attached (ports, protocols, CIDRs)?&lt;br /&gt;
* Host firewall rules (if used), SSH hardening settings, update strategy.&lt;br /&gt;
* Installed services and exposed endpoints.&lt;br /&gt;
* Where secrets are stored/managed (avoid putting secrets in shell history or plain text files).&lt;br /&gt;
&lt;br /&gt;
=== Plan and test a backup strategy ===&lt;br /&gt;
Backups are part of security (availability and recovery).&lt;br /&gt;
&lt;br /&gt;
* Define what needs to be recoverable (system, application data, databases, configuration).&lt;br /&gt;
* Decide on backup frequency and retention (e.g., daily incremental + weekly full).&lt;br /&gt;
* Store backups separately from the instance (avoid a single point of failure).&lt;br /&gt;
* Regularly test restores (a backup that was never restored is an assumption, not a plan).&lt;br /&gt;
&lt;br /&gt;
=== Snapshots and images ===&lt;br /&gt;
Snapshots capture the state of a VM or volume at a point in time (e.g., before risky changes). They can help with rollback, but they do not automatically replace a backup strategy.&lt;br /&gt;
&lt;br /&gt;
* Learn more: [[Guide:_Volumes_and_Images|Guide: Volumes and Images]]&lt;br /&gt;
* Recommended practice:&lt;br /&gt;
** Take a snapshot before major changes (OS upgrades, large configuration changes).&lt;br /&gt;
** Remove outdated snapshots according to your retention plan.&lt;br /&gt;
&lt;br /&gt;
= SSL Certificates &amp;amp; Secure Services =&lt;br /&gt;
&lt;br /&gt;
== Can I get SSL/TLS certificates via bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SSL-Certificates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No, bwCloud-OS does &#039;&#039;&#039;not&#039;&#039;&#039; provide &#039;&#039;&#039;SSL/TLS certificates.&#039;&#039;&#039; However, you can obtain certificates directly from public providers like &#039;&#039;&#039;Let’s Encrypt&#039;&#039;&#039; using tools such as &#039;&#039;&#039;[https://certbot.eff.org/ Certbot]&#039;&#039;&#039;, which you can install and run on your instance.&lt;br /&gt;
&lt;br /&gt;
This allows you, for example, to enable &#039;&#039;&#039;HTTPS&#039;&#039;&#039; for services running on your VM. Don&#039;t forget to open the necessary ports (e.g., 443) using [[Security#Security-Rules|security group rules]].&lt;br /&gt;
&lt;br /&gt;
=Security Incidents =&lt;br /&gt;
&lt;br /&gt;
== What should I do if I suspect my VM has been compromised? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Incident&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your virtual machine is behaving unexpectedly (e.g., high CPU/network load, unknown logins, suspicious processes), it could indicate a possible compromise.&lt;br /&gt;
&lt;br /&gt;
If you suspect that your VM has been compromised, please take the following steps &#039;&#039;&#039;immediately&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard].&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;Stop the affected instance(s).&#039;&#039;&#039; &#039;&#039;Do not delete them!&#039;&#039; This preserves data for further analysis.&lt;br /&gt;
# &#039;&#039;&#039;Submit a support ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ bwSupportPortal] with the following details:&lt;br /&gt;
#*       Which instance(s) are potentially affected?&lt;br /&gt;
#* How is the suspicious behavior observed? (e.g. logs, performance, alerts)&lt;br /&gt;
#* What actions have you already taken?&lt;br /&gt;
&lt;br /&gt;
Our team will contact you as soon as possible to help investigate and resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Does the bwCloud-OS operations team inspect running instances (e.g. through penetration tests)? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Scans&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contents and configuration of user instances are not inspected&#039;&#039;&#039; — we do &#039;&#039;&#039;not&#039;&#039;&#039; perform penetration tests or port scans on the instances. We also &#039;&#039;&#039;never look inside&#039;&#039;&#039; user virtual machines.&lt;br /&gt;
&lt;br /&gt;
However, the overall bwCloud-OS operating environment is actively monitored. For example, network monitoring tracks current inbound and outbound traffic levels. If certain parameters deviate significantly from typical patterns, this may trigger further investigation —  including direct contact with the affected user.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2218</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2218"/>
		<updated>2026-04-27T11:43:21Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Allow only the minimal required ports in bwCloud-OS Security Groups */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;By default,  bwCloud-OS VMs are only accessible via &amp;lt;strong&amp;gt;SSH (port 22)&amp;lt;/strong&amp;gt; and  &amp;lt;strong&amp;gt;ICMP&amp;lt;/strong&amp;gt; (e.g., &#039;&#039;ping&#039;&#039;);  all other incoming traffic is blocked for security.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To allow access on additional ports (e.g. HTTPS/443), you can add rules via the &amp;lt;strong&amp;gt;Security Groups&amp;lt;/strong&amp;gt; in the [https://portal.bw-cloud.org/ Dashboard] — changes take effect immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Some ports are &amp;lt;strong&amp;gt;centrally filtered&amp;lt;/strong&amp;gt; in specific bwCloud-OS regions and cannot be opened individually; refer to this [[Blocked_and_Allowed_Ports|overview]] for region-specific details.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you suspect a &amp;lt;strong&amp;gt;security incident&amp;lt;/strong&amp;gt;, stop the affected VMs and submit a [https://bw-support.scc.kit.edu/ support ticket] immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Access Control &amp;amp; Firewall Rules =&lt;br /&gt;
&lt;br /&gt;
== What network access is allowed by default in bwCloud-OS instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Default&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, &#039;&#039;&#039;bwCloud-OS instances&#039;&#039;&#039; are accessible via:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; – for remote login and configuration&lt;br /&gt;
* &#039;&#039;&#039;ICMP&#039;&#039;&#039; – to allow basic network diagnostics like &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This initial access is explicitly permitted by the &#039;&#039;&#039;automatically assigned security group&#039;&#039;&#039; (named &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;) in our configuration. This is not the default behavior in OpenStack — it is provided by bwCloud-OS to simplify first-time access for users.&lt;br /&gt;
&lt;br /&gt;
== How do I open additional ports for my instance? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Rules&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A newly created virtual machine in bwCloud-OS is only accessible from the outside via &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; and &#039;&#039;&#039;ICMP&#039;&#039;&#039;.  All other inbound traffic is &#039;&#039;&#039;blocked&#039;&#039;&#039; by default — meaning external traffic on other ports cannot reach the instance.&lt;br /&gt;
&lt;br /&gt;
To allow access on other ports (e.g. for web servers or applications), you need to &#039;&#039;&#039;add a rule&#039;&#039;&#039; to the relevant &#039;&#039;&#039;security group&#039;&#039;&#039;. &#039;&#039;Changes to security group rules apply immediately to all instances using that group&#039;&#039; — there&#039;s no need to reboot the instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening Port 443 for HTTPS Access ===&lt;br /&gt;
If you&#039;re running a web server that should be accessible via &#039;&#039;&#039;HTTPS&#039;&#039;&#039;, you typically need to open &#039;&#039;&#039;port 443&#039;&#039;&#039; in a security group assigned to your instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Steps in the [https://portal.bw-cloud.org/ Dashboard]:&#039;&#039;&#039;&lt;br /&gt;
# In the left menu, go to &#039;&#039;&#039;Network → Security Groups&#039;&#039;&#039;. A list of all defined security groups will appear.  &lt;br /&gt;
#* &#039;&#039;&#039;Recommended:&#039;&#039;&#039; Consider creating a dedicated security group (e.g. named &amp;lt;code&amp;gt;https-access&amp;lt;/code&amp;gt;), and assign it to your instance using &#039;&#039;&#039;Edit Security Groups&#039;&#039;&#039; in the instance menu before the next step.&lt;br /&gt;
# Find the relevant group and click &#039;&#039;&#039;Manage Rules&#039;&#039;&#039;. You’ll see all currently defined rules for that group.&lt;br /&gt;
# Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; to create a new one.&lt;br /&gt;
# In the dialog that appears, choose one of the following:&lt;br /&gt;
#* &#039;&#039;&#039;HTTPS&#039;&#039;&#039; from the &#039;&#039;&#039;Rule&#039;&#039;&#039; dropdown (automatically fills port 443), or&lt;br /&gt;
#* &#039;&#039;&#039;Custom TCP Rule&#039;&#039;&#039;, then manually enter &#039;&#039;&#039;443&#039;&#039;&#039; in the &#039;&#039;&#039;Port&#039;&#039;&#039; field.&lt;br /&gt;
# In the &#039;&#039;&#039;CIDR&#039;&#039;&#039; field, specify which IP addresses should be allowed to connect:&lt;br /&gt;
#* Use a specific IP range (e.g. &amp;lt;code&amp;gt;192.168.0.0/24&amp;lt;/code&amp;gt;) to &#039;&#039;&#039;limit access&#039;&#039;&#039;&lt;br /&gt;
#* ⚠️ Using &#039;&#039;&#039;&amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt;&#039;&#039;&#039; allows access from &#039;&#039;&#039;any IPv4 address&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;::/0&amp;lt;/code&amp;gt;&#039;&#039;&#039;  from &#039;&#039;&#039;any IPv6 address&#039;&#039;&#039;.&lt;br /&gt;
# Set the &#039;&#039;&#039;Direction&#039;&#039;&#039; of the rule:&lt;br /&gt;
#* &amp;lt;code&amp;gt;Ingress&amp;lt;/code&amp;gt; = incoming connections (usually what you want)&lt;br /&gt;
#* &amp;lt;code&amp;gt;Egress&amp;lt;/code&amp;gt; = outgoing connections&lt;br /&gt;
# Click &#039;&#039;&#039;Add&#039;&#039;&#039;. The rule will be created and added to the list immediately.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening a Port only for Access from Certain IP Ranges ===&lt;br /&gt;
&#039;&#039;&#039;➡️&#039;&#039;&#039;  [[Guide: Security Group|Security Groups Guide]]&lt;br /&gt;
&lt;br /&gt;
== Are some ports blocked in bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Blocked-Ports&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. Some ports are &#039;&#039;&#039;centrally&#039;&#039;&#039; &#039;&#039;&#039;blocked&#039;&#039;&#039; in &#039;&#039;&#039;certain&#039;&#039;&#039; &#039;&#039;&#039;bwCloud-OS regions&#039;&#039;&#039; due to specific network policies at the participating university data centers. Centrally blocked ports cannot be opened individually. &lt;br /&gt;
&lt;br /&gt;
For more details — including which ports are affected in each region — see the page [[Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
= Security Checklist =&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide a basic security checklist for virtual machines? ==&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
=== Secure SSH access ===&lt;br /&gt;
* Read and apply the recommendations in the [[Guide:_SSH|SSH guide]].&lt;br /&gt;
&lt;br /&gt;
=== Keep the system updated ===&lt;br /&gt;
Keeping your instance up to date is one of the most effective security measures: security updates fix known vulnerabilities that may otherwise be exploitable.&lt;br /&gt;
&lt;br /&gt;
There are two common approaches:&lt;br /&gt;
* &#039;&#039;&#039;Manual updates (one-time / on demand):&#039;&#039;&#039; You run updates yourself (e.g., after login, on a regular schedule).&lt;br /&gt;
* &#039;&#039;&#039;Automatic updates:&#039;&#039;&#039; The system installs security updates automatically in the background. On Ubuntu/Debian this is commonly done via &amp;lt;code&amp;gt;unattended-upgrades&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu/Debian) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Manual updates (one-time)&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt -y upgrade&lt;br /&gt;
&lt;br /&gt;
# Automatic security updates (background)&lt;br /&gt;
sudo apt -y install unattended-upgrades&lt;br /&gt;
sudo dpkg-reconfigure --priority=low unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Allow only the minimal required ports in bwCloud-OS Security Groups ===&lt;br /&gt;
Only open the ports you actually need. This reduces the attack surface and limits who can reach services on your VM.&lt;br /&gt;
&lt;br /&gt;
* Check your instance&#039;s security groups in the [https://portal.bw-cloud.org/ Dashboard] and allow only the minimal required inbound rules.&lt;br /&gt;
* Restrict access by IP range (CIDR) wherever possible (avoid &amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt; unless truly required).&lt;br /&gt;
* For step-by-step instructions and examples, see: [[Security#Security-Rules|How do I open additional ports for my instance?]]&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; some ports may be centrally filtered in certain regions; see [[Blocked_and_Allowed_Ports|Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
=== Optional host firewall (e.g., UFW on Ubuntu) ===&lt;br /&gt;
Security groups are the primary inbound filter in bwCloud-OS. A host firewall can provide an additional layer (defense-in-depth), e.g., to enforce local policies on the VM.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu with UFW) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt -y install ufw&lt;br /&gt;
sudo ufw default deny incoming&lt;br /&gt;
sudo ufw default allow outgoing&lt;br /&gt;
&lt;br /&gt;
# Allow SSH (ideally restrict in the bwCloud-OS security group as well)&lt;br /&gt;
sudo ufw allow 22/tcp&lt;br /&gt;
&lt;br /&gt;
# Example: allow HTTPS if you opened 443 in the security group&lt;br /&gt;
sudo ufw allow 443/tcp&lt;br /&gt;
&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw status verbose&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Important:&#039;&#039; If you block SSH on the host firewall while only having SSH access, you may lock yourself out. Always ensure SSH remains permitted (and test from your client).&lt;br /&gt;
&lt;br /&gt;
=== Document your configuration ===&lt;br /&gt;
To operate and troubleshoot securely, keep a record of your instance configuration:&lt;br /&gt;
&lt;br /&gt;
* Which security groups/rules are attached (ports, protocols, CIDRs)?&lt;br /&gt;
* Host firewall rules (if used), SSH hardening settings, update strategy.&lt;br /&gt;
* Installed services and exposed endpoints.&lt;br /&gt;
* Where secrets are stored/managed (avoid putting secrets in shell history or plain text files).&lt;br /&gt;
&lt;br /&gt;
=== Plan and test a backup strategy ===&lt;br /&gt;
Backups are part of security (availability and recovery).&lt;br /&gt;
&lt;br /&gt;
* Define what needs to be recoverable (system, application data, databases, configuration).&lt;br /&gt;
* Decide on backup frequency and retention (e.g., daily incremental + weekly full).&lt;br /&gt;
* Store backups separately from the instance (avoid a single point of failure).&lt;br /&gt;
* Regularly test restores (a backup that was never restored is an assumption, not a plan).&lt;br /&gt;
&lt;br /&gt;
=== Snapshots and images ===&lt;br /&gt;
Snapshots capture the state of a VM or volume at a point in time (e.g., before risky changes). They can help with rollback, but they do not automatically replace a backup strategy.&lt;br /&gt;
&lt;br /&gt;
* Learn more: [[Guide:_Volumes_and_Images|Guide: Volumes and Images]]&lt;br /&gt;
* Recommended practice:&lt;br /&gt;
** Take a snapshot before major changes (OS upgrades, large configuration changes).&lt;br /&gt;
** Remove outdated snapshots according to your retention plan.&lt;br /&gt;
&lt;br /&gt;
= SSL Certificates &amp;amp; Secure Services =&lt;br /&gt;
&lt;br /&gt;
== Can I get SSL/TLS certificates via bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SSL-Certificates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No, bwCloud-OS does &#039;&#039;&#039;not&#039;&#039;&#039; provide &#039;&#039;&#039;SSL/TLS certificates.&#039;&#039;&#039; However, you can obtain certificates directly from public providers like &#039;&#039;&#039;Let’s Encrypt&#039;&#039;&#039; using tools such as &#039;&#039;&#039;[https://certbot.eff.org/ Certbot]&#039;&#039;&#039;, which you can install and run on your instance.&lt;br /&gt;
&lt;br /&gt;
This allows you, for example, to enable &#039;&#039;&#039;HTTPS&#039;&#039;&#039; for services running on your VM. Don&#039;t forget to open the necessary ports (e.g., 443) using [[Security#Security-Rules|security group rules]].&lt;br /&gt;
&lt;br /&gt;
=Security Incidents =&lt;br /&gt;
&lt;br /&gt;
== What should I do if I suspect my VM has been compromised? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Incident&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your virtual machine is behaving unexpectedly (e.g., high CPU/network load, unknown logins, suspicious processes), it could indicate a possible compromise.&lt;br /&gt;
&lt;br /&gt;
If you suspect that your VM has been compromised, please take the following steps &#039;&#039;&#039;immediately&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard].&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;Stop the affected instance(s).&#039;&#039;&#039; &#039;&#039;Do not delete them!&#039;&#039; This preserves data for further analysis.&lt;br /&gt;
# &#039;&#039;&#039;Submit a support ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ bwSupportPortal] with the following details:&lt;br /&gt;
#*       Which instance(s) are potentially affected?&lt;br /&gt;
#* How is the suspicious behavior observed? (e.g. logs, performance, alerts)&lt;br /&gt;
#* What actions have you already taken?&lt;br /&gt;
&lt;br /&gt;
Our team will contact you as soon as possible to help investigate and resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Does the bwCloud-OS operations team inspect running instances (e.g. through penetration tests)? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Scans&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contents and configuration of user instances are not inspected&#039;&#039;&#039; — we do &#039;&#039;&#039;not&#039;&#039;&#039; perform penetration tests or port scans on the instances. We also &#039;&#039;&#039;never look inside&#039;&#039;&#039; user virtual machines.&lt;br /&gt;
&lt;br /&gt;
However, the overall bwCloud-OS operating environment is actively monitored. For example, network monitoring tracks current inbound and outbound traffic levels. If certain parameters deviate significantly from typical patterns, this may trigger further investigation —  including direct contact with the affected user.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2217</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2217"/>
		<updated>2026-04-27T11:40:59Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Does bwCloud-OS provide a basic security checklist for virtual machines? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;By default,  bwCloud-OS VMs are only accessible via &amp;lt;strong&amp;gt;SSH (port 22)&amp;lt;/strong&amp;gt; and  &amp;lt;strong&amp;gt;ICMP&amp;lt;/strong&amp;gt; (e.g., &#039;&#039;ping&#039;&#039;);  all other incoming traffic is blocked for security.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To allow access on additional ports (e.g. HTTPS/443), you can add rules via the &amp;lt;strong&amp;gt;Security Groups&amp;lt;/strong&amp;gt; in the [https://portal.bw-cloud.org/ Dashboard] — changes take effect immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Some ports are &amp;lt;strong&amp;gt;centrally filtered&amp;lt;/strong&amp;gt; in specific bwCloud-OS regions and cannot be opened individually; refer to this [[Blocked_and_Allowed_Ports|overview]] for region-specific details.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you suspect a &amp;lt;strong&amp;gt;security incident&amp;lt;/strong&amp;gt;, stop the affected VMs and submit a [https://bw-support.scc.kit.edu/ support ticket] immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Access Control &amp;amp; Firewall Rules =&lt;br /&gt;
&lt;br /&gt;
== What network access is allowed by default in bwCloud-OS instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Default&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, &#039;&#039;&#039;bwCloud-OS instances&#039;&#039;&#039; are accessible via:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; – for remote login and configuration&lt;br /&gt;
* &#039;&#039;&#039;ICMP&#039;&#039;&#039; – to allow basic network diagnostics like &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This initial access is explicitly permitted by the &#039;&#039;&#039;automatically assigned security group&#039;&#039;&#039; (named &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;) in our configuration. This is not the default behavior in OpenStack — it is provided by bwCloud-OS to simplify first-time access for users.&lt;br /&gt;
&lt;br /&gt;
== How do I open additional ports for my instance? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Rules&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A newly created virtual machine in bwCloud-OS is only accessible from the outside via &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; and &#039;&#039;&#039;ICMP&#039;&#039;&#039;.  All other inbound traffic is &#039;&#039;&#039;blocked&#039;&#039;&#039; by default — meaning external traffic on other ports cannot reach the instance.&lt;br /&gt;
&lt;br /&gt;
To allow access on other ports (e.g. for web servers or applications), you need to &#039;&#039;&#039;add a rule&#039;&#039;&#039; to the relevant &#039;&#039;&#039;security group&#039;&#039;&#039;. &#039;&#039;Changes to security group rules apply immediately to all instances using that group&#039;&#039; — there&#039;s no need to reboot the instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening Port 443 for HTTPS Access ===&lt;br /&gt;
If you&#039;re running a web server that should be accessible via &#039;&#039;&#039;HTTPS&#039;&#039;&#039;, you typically need to open &#039;&#039;&#039;port 443&#039;&#039;&#039; in a security group assigned to your instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Steps in the [https://portal.bw-cloud.org/ Dashboard]:&#039;&#039;&#039;&lt;br /&gt;
# In the left menu, go to &#039;&#039;&#039;Network → Security Groups&#039;&#039;&#039;. A list of all defined security groups will appear.  &lt;br /&gt;
#* &#039;&#039;&#039;Recommended:&#039;&#039;&#039; Consider creating a dedicated security group (e.g. named &amp;lt;code&amp;gt;https-access&amp;lt;/code&amp;gt;), and assign it to your instance using &#039;&#039;&#039;Edit Security Groups&#039;&#039;&#039; in the instance menu before the next step.&lt;br /&gt;
# Find the relevant group and click &#039;&#039;&#039;Manage Rules&#039;&#039;&#039;. You’ll see all currently defined rules for that group.&lt;br /&gt;
# Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; to create a new one.&lt;br /&gt;
# In the dialog that appears, choose one of the following:&lt;br /&gt;
#* &#039;&#039;&#039;HTTPS&#039;&#039;&#039; from the &#039;&#039;&#039;Rule&#039;&#039;&#039; dropdown (automatically fills port 443), or&lt;br /&gt;
#* &#039;&#039;&#039;Custom TCP Rule&#039;&#039;&#039;, then manually enter &#039;&#039;&#039;443&#039;&#039;&#039; in the &#039;&#039;&#039;Port&#039;&#039;&#039; field.&lt;br /&gt;
# In the &#039;&#039;&#039;CIDR&#039;&#039;&#039; field, specify which IP addresses should be allowed to connect:&lt;br /&gt;
#* Use a specific IP range (e.g. &amp;lt;code&amp;gt;192.168.0.0/24&amp;lt;/code&amp;gt;) to &#039;&#039;&#039;limit access&#039;&#039;&#039;&lt;br /&gt;
#* ⚠️ Using &#039;&#039;&#039;&amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt;&#039;&#039;&#039; allows access from &#039;&#039;&#039;any IPv4 address&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;::/0&amp;lt;/code&amp;gt;&#039;&#039;&#039;  from &#039;&#039;&#039;any IPv6 address&#039;&#039;&#039;.&lt;br /&gt;
# Set the &#039;&#039;&#039;Direction&#039;&#039;&#039; of the rule:&lt;br /&gt;
#* &amp;lt;code&amp;gt;Ingress&amp;lt;/code&amp;gt; = incoming connections (usually what you want)&lt;br /&gt;
#* &amp;lt;code&amp;gt;Egress&amp;lt;/code&amp;gt; = outgoing connections&lt;br /&gt;
# Click &#039;&#039;&#039;Add&#039;&#039;&#039;. The rule will be created and added to the list immediately.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening a Port only for Access from Certain IP Ranges ===&lt;br /&gt;
&#039;&#039;&#039;➡️&#039;&#039;&#039;  [[Guide: Security Group|Security Groups Guide]]&lt;br /&gt;
&lt;br /&gt;
== Are some ports blocked in bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Blocked-Ports&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. Some ports are &#039;&#039;&#039;centrally&#039;&#039;&#039; &#039;&#039;&#039;blocked&#039;&#039;&#039; in &#039;&#039;&#039;certain&#039;&#039;&#039; &#039;&#039;&#039;bwCloud-OS regions&#039;&#039;&#039; due to specific network policies at the participating university data centers. Centrally blocked ports cannot be opened individually. &lt;br /&gt;
&lt;br /&gt;
For more details — including which ports are affected in each region — see the page [[Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
= Security Checklist =&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide a basic security checklist for virtual machines? ==&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
=== Secure SSH access ===&lt;br /&gt;
* Read and apply the recommendations in the [[Guide:_SSH|SSH guide]].&lt;br /&gt;
&lt;br /&gt;
=== Keep the system updated ===&lt;br /&gt;
Keeping your instance up to date is one of the most effective security measures: security updates fix known vulnerabilities that may otherwise be exploitable.&lt;br /&gt;
&lt;br /&gt;
There are two common approaches:&lt;br /&gt;
* &#039;&#039;&#039;Manual updates (one-time / on demand):&#039;&#039;&#039; You run updates yourself (e.g., after login, on a regular schedule).&lt;br /&gt;
* &#039;&#039;&#039;Automatic updates:&#039;&#039;&#039; The system installs security updates automatically in the background. On Ubuntu/Debian this is commonly done via &amp;lt;code&amp;gt;unattended-upgrades&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu/Debian) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Manual updates (one-time)&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt -y upgrade&lt;br /&gt;
&lt;br /&gt;
# Automatic security updates (background)&lt;br /&gt;
sudo apt -y install unattended-upgrades&lt;br /&gt;
sudo dpkg-reconfigure --priority=low unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Allow only the minimal required ports in bwCloud-OS Security Groups ===&lt;br /&gt;
Only open the ports you actually need. This reduces the attack surface and limits who can reach services on your VM.&lt;br /&gt;
&lt;br /&gt;
* Check your instance&#039;s security groups in the [https://portal.bw-cloud.org/ Dashboard] and allow only the minimal required inbound rules.&lt;br /&gt;
* Restrict access by IP range (CIDR) wherever possible (avoid &amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt; unless truly required).&lt;br /&gt;
* For step-by-step instructions and examples, see: [[Security#Security-Rules|How do I open additional ports for my instance?]]&lt;br /&gt;
* Note: some ports may be centrally filtered in certain regions; see [[Blocked_and_Allowed_Ports|Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
=== Optional host firewall (e.g., UFW on Ubuntu) ===&lt;br /&gt;
Security groups are the primary inbound filter in bwCloud-OS. A host firewall can provide an additional layer (defense-in-depth), e.g., to enforce local policies on the VM.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu with UFW) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt -y install ufw&lt;br /&gt;
sudo ufw default deny incoming&lt;br /&gt;
sudo ufw default allow outgoing&lt;br /&gt;
&lt;br /&gt;
# Allow SSH (ideally restrict in the bwCloud-OS security group as well)&lt;br /&gt;
sudo ufw allow 22/tcp&lt;br /&gt;
&lt;br /&gt;
# Example: allow HTTPS if you opened 443 in the security group&lt;br /&gt;
sudo ufw allow 443/tcp&lt;br /&gt;
&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw status verbose&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Important:&#039;&#039; If you block SSH on the host firewall while only having SSH access, you may lock yourself out. Always ensure SSH remains permitted (and test from your client).&lt;br /&gt;
&lt;br /&gt;
=== Document your configuration ===&lt;br /&gt;
To operate and troubleshoot securely, keep a record of your instance configuration:&lt;br /&gt;
&lt;br /&gt;
* Which security groups/rules are attached (ports, protocols, CIDRs)?&lt;br /&gt;
* Host firewall rules (if used), SSH hardening settings, update strategy.&lt;br /&gt;
* Installed services and exposed endpoints.&lt;br /&gt;
* Where secrets are stored/managed (avoid putting secrets in shell history or plain text files).&lt;br /&gt;
&lt;br /&gt;
=== Plan and test a backup strategy ===&lt;br /&gt;
Backups are part of security (availability and recovery).&lt;br /&gt;
&lt;br /&gt;
* Define what needs to be recoverable (system, application data, databases, configuration).&lt;br /&gt;
* Decide on backup frequency and retention (e.g., daily incremental + weekly full).&lt;br /&gt;
* Store backups separately from the instance (avoid a single point of failure).&lt;br /&gt;
* Regularly test restores (a backup that was never restored is an assumption, not a plan).&lt;br /&gt;
&lt;br /&gt;
=== Snapshots and images ===&lt;br /&gt;
Snapshots capture the state of a VM or volume at a point in time (e.g., before risky changes). They can help with rollback, but they do not automatically replace a backup strategy.&lt;br /&gt;
&lt;br /&gt;
* Learn more: [[Guide:_Volumes_and_Images|Guide: Volumes and Images]]&lt;br /&gt;
* Recommended practice:&lt;br /&gt;
** Take a snapshot before major changes (OS upgrades, large configuration changes).&lt;br /&gt;
** Remove outdated snapshots according to your retention plan.&lt;br /&gt;
&lt;br /&gt;
= SSL Certificates &amp;amp; Secure Services =&lt;br /&gt;
&lt;br /&gt;
== Can I get SSL/TLS certificates via bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SSL-Certificates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No, bwCloud-OS does &#039;&#039;&#039;not&#039;&#039;&#039; provide &#039;&#039;&#039;SSL/TLS certificates.&#039;&#039;&#039; However, you can obtain certificates directly from public providers like &#039;&#039;&#039;Let’s Encrypt&#039;&#039;&#039; using tools such as &#039;&#039;&#039;[https://certbot.eff.org/ Certbot]&#039;&#039;&#039;, which you can install and run on your instance.&lt;br /&gt;
&lt;br /&gt;
This allows you, for example, to enable &#039;&#039;&#039;HTTPS&#039;&#039;&#039; for services running on your VM. Don&#039;t forget to open the necessary ports (e.g., 443) using [[Security#Security-Rules|security group rules]].&lt;br /&gt;
&lt;br /&gt;
=Security Incidents =&lt;br /&gt;
&lt;br /&gt;
== What should I do if I suspect my VM has been compromised? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Incident&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your virtual machine is behaving unexpectedly (e.g., high CPU/network load, unknown logins, suspicious processes), it could indicate a possible compromise.&lt;br /&gt;
&lt;br /&gt;
If you suspect that your VM has been compromised, please take the following steps &#039;&#039;&#039;immediately&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard].&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;Stop the affected instance(s).&#039;&#039;&#039; &#039;&#039;Do not delete them!&#039;&#039; This preserves data for further analysis.&lt;br /&gt;
# &#039;&#039;&#039;Submit a support ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ bwSupportPortal] with the following details:&lt;br /&gt;
#*       Which instance(s) are potentially affected?&lt;br /&gt;
#* How is the suspicious behavior observed? (e.g. logs, performance, alerts)&lt;br /&gt;
#* What actions have you already taken?&lt;br /&gt;
&lt;br /&gt;
Our team will contact you as soon as possible to help investigate and resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Does the bwCloud-OS operations team inspect running instances (e.g. through penetration tests)? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Scans&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contents and configuration of user instances are not inspected&#039;&#039;&#039; — we do &#039;&#039;&#039;not&#039;&#039;&#039; perform penetration tests or port scans on the instances. We also &#039;&#039;&#039;never look inside&#039;&#039;&#039; user virtual machines.&lt;br /&gt;
&lt;br /&gt;
However, the overall bwCloud-OS operating environment is actively monitored. For example, network monitoring tracks current inbound and outbound traffic levels. If certain parameters deviate significantly from typical patterns, this may trigger further investigation —  including direct contact with the affected user.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2216</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2216"/>
		<updated>2026-04-27T11:40:19Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;By default,  bwCloud-OS VMs are only accessible via &amp;lt;strong&amp;gt;SSH (port 22)&amp;lt;/strong&amp;gt; and  &amp;lt;strong&amp;gt;ICMP&amp;lt;/strong&amp;gt; (e.g., &#039;&#039;ping&#039;&#039;);  all other incoming traffic is blocked for security.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To allow access on additional ports (e.g. HTTPS/443), you can add rules via the &amp;lt;strong&amp;gt;Security Groups&amp;lt;/strong&amp;gt; in the [https://portal.bw-cloud.org/ Dashboard] — changes take effect immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Some ports are &amp;lt;strong&amp;gt;centrally filtered&amp;lt;/strong&amp;gt; in specific bwCloud-OS regions and cannot be opened individually; refer to this [[Blocked_and_Allowed_Ports|overview]] for region-specific details.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you suspect a &amp;lt;strong&amp;gt;security incident&amp;lt;/strong&amp;gt;, stop the affected VMs and submit a [https://bw-support.scc.kit.edu/ support ticket] immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Access Control &amp;amp; Firewall Rules =&lt;br /&gt;
&lt;br /&gt;
== What network access is allowed by default in bwCloud-OS instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Default&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, &#039;&#039;&#039;bwCloud-OS instances&#039;&#039;&#039; are accessible via:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; – for remote login and configuration&lt;br /&gt;
* &#039;&#039;&#039;ICMP&#039;&#039;&#039; – to allow basic network diagnostics like &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This initial access is explicitly permitted by the &#039;&#039;&#039;automatically assigned security group&#039;&#039;&#039; (named &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;) in our configuration. This is not the default behavior in OpenStack — it is provided by bwCloud-OS to simplify first-time access for users.&lt;br /&gt;
&lt;br /&gt;
== How do I open additional ports for my instance? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Rules&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A newly created virtual machine in bwCloud-OS is only accessible from the outside via &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; and &#039;&#039;&#039;ICMP&#039;&#039;&#039;.  All other inbound traffic is &#039;&#039;&#039;blocked&#039;&#039;&#039; by default — meaning external traffic on other ports cannot reach the instance.&lt;br /&gt;
&lt;br /&gt;
To allow access on other ports (e.g. for web servers or applications), you need to &#039;&#039;&#039;add a rule&#039;&#039;&#039; to the relevant &#039;&#039;&#039;security group&#039;&#039;&#039;. &#039;&#039;Changes to security group rules apply immediately to all instances using that group&#039;&#039; — there&#039;s no need to reboot the instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening Port 443 for HTTPS Access ===&lt;br /&gt;
If you&#039;re running a web server that should be accessible via &#039;&#039;&#039;HTTPS&#039;&#039;&#039;, you typically need to open &#039;&#039;&#039;port 443&#039;&#039;&#039; in a security group assigned to your instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Steps in the [https://portal.bw-cloud.org/ Dashboard]:&#039;&#039;&#039;&lt;br /&gt;
# In the left menu, go to &#039;&#039;&#039;Network → Security Groups&#039;&#039;&#039;. A list of all defined security groups will appear.  &lt;br /&gt;
#* &#039;&#039;&#039;Recommended:&#039;&#039;&#039; Consider creating a dedicated security group (e.g. named &amp;lt;code&amp;gt;https-access&amp;lt;/code&amp;gt;), and assign it to your instance using &#039;&#039;&#039;Edit Security Groups&#039;&#039;&#039; in the instance menu before the next step.&lt;br /&gt;
# Find the relevant group and click &#039;&#039;&#039;Manage Rules&#039;&#039;&#039;. You’ll see all currently defined rules for that group.&lt;br /&gt;
# Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; to create a new one.&lt;br /&gt;
# In the dialog that appears, choose one of the following:&lt;br /&gt;
#* &#039;&#039;&#039;HTTPS&#039;&#039;&#039; from the &#039;&#039;&#039;Rule&#039;&#039;&#039; dropdown (automatically fills port 443), or&lt;br /&gt;
#* &#039;&#039;&#039;Custom TCP Rule&#039;&#039;&#039;, then manually enter &#039;&#039;&#039;443&#039;&#039;&#039; in the &#039;&#039;&#039;Port&#039;&#039;&#039; field.&lt;br /&gt;
# In the &#039;&#039;&#039;CIDR&#039;&#039;&#039; field, specify which IP addresses should be allowed to connect:&lt;br /&gt;
#* Use a specific IP range (e.g. &amp;lt;code&amp;gt;192.168.0.0/24&amp;lt;/code&amp;gt;) to &#039;&#039;&#039;limit access&#039;&#039;&#039;&lt;br /&gt;
#* ⚠️ Using &#039;&#039;&#039;&amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt;&#039;&#039;&#039; allows access from &#039;&#039;&#039;any IPv4 address&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;::/0&amp;lt;/code&amp;gt;&#039;&#039;&#039;  from &#039;&#039;&#039;any IPv6 address&#039;&#039;&#039;.&lt;br /&gt;
# Set the &#039;&#039;&#039;Direction&#039;&#039;&#039; of the rule:&lt;br /&gt;
#* &amp;lt;code&amp;gt;Ingress&amp;lt;/code&amp;gt; = incoming connections (usually what you want)&lt;br /&gt;
#* &amp;lt;code&amp;gt;Egress&amp;lt;/code&amp;gt; = outgoing connections&lt;br /&gt;
# Click &#039;&#039;&#039;Add&#039;&#039;&#039;. The rule will be created and added to the list immediately.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening a Port only for Access from Certain IP Ranges ===&lt;br /&gt;
&#039;&#039;&#039;➡️&#039;&#039;&#039;  [[Guide: Security Group|Security Groups Guide]]&lt;br /&gt;
&lt;br /&gt;
== Are some ports blocked in bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Blocked-Ports&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. Some ports are &#039;&#039;&#039;centrally&#039;&#039;&#039; &#039;&#039;&#039;blocked&#039;&#039;&#039; in &#039;&#039;&#039;certain&#039;&#039;&#039; &#039;&#039;&#039;bwCloud-OS regions&#039;&#039;&#039; due to specific network policies at the participating university data centers. Centrally blocked ports cannot be opened individually. &lt;br /&gt;
&lt;br /&gt;
For more details — including which ports are affected in each region — see the page [[Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
= Security Checklist =&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide a basic security checklist for virtual machines? ==&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
=== Secure SSH access ===&lt;br /&gt;
* Read and apply the recommendations in the [[Guide:_SSH|SSH guide]].&lt;br /&gt;
&lt;br /&gt;
=== Keep the system updated ===&lt;br /&gt;
Keeping your instance up to date is one of the most effective security measures: security updates fix known vulnerabilities that may otherwise be exploitable.&lt;br /&gt;
&lt;br /&gt;
There are two common approaches:&lt;br /&gt;
* &#039;&#039;&#039;Manual updates (one-time / on demand):&#039;&#039;&#039; You run updates yourself (e.g., after login, on a regular schedule).&lt;br /&gt;
* &#039;&#039;&#039;Automatic updates:&#039;&#039;&#039; The system installs security updates automatically in the background. On Ubuntu/Debian this is commonly done via &amp;lt;code&amp;gt;unattended-upgrades&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu/Debian) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Manual updates (one-time)&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt -y upgrade&lt;br /&gt;
&lt;br /&gt;
# Automatic security updates (background)&lt;br /&gt;
sudo apt -y install unattended-upgrades&lt;br /&gt;
sudo dpkg-reconfigure --priority=low unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Allow only the minimal required ports in bwCloud-OS Security Groups ===&lt;br /&gt;
Only open the ports you actually need. This reduces the attack surface and limits who can reach services on your VM.&lt;br /&gt;
&lt;br /&gt;
* Check your instance&#039;s security groups in the [https://portal.bw-cloud.org/ Dashboard] and allow only the minimal required inbound rules.&lt;br /&gt;
* Restrict access by IP range (CIDR) wherever possible (avoid &amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt; unless truly required).&lt;br /&gt;
* For step-by-step instructions and examples, see: [[Security#Security-Rules|How do I open additional ports for my instance?]]&lt;br /&gt;
* Note: some ports may be centrally filtered in certain regions; see [[Blocked_and_Allowed_Ports|Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
=== Optional host firewall (e.g., UFW on Ubuntu) ===&lt;br /&gt;
Security groups are the primary inbound filter in bwCloud-OS. A host firewall can provide an additional layer (defense-in-depth), e.g., to enforce local policies on the VM.&lt;br /&gt;
&lt;br /&gt;
==== Example (Ubuntu with UFW) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt -y install ufw&lt;br /&gt;
sudo ufw default deny incoming&lt;br /&gt;
sudo ufw default allow outgoing&lt;br /&gt;
&lt;br /&gt;
# Allow SSH (ideally restrict in the bwCloud-OS security group as well)&lt;br /&gt;
sudo ufw allow 22/tcp&lt;br /&gt;
&lt;br /&gt;
# Example: allow HTTPS if you opened 443 in the security group&lt;br /&gt;
sudo ufw allow 443/tcp&lt;br /&gt;
&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw status verbose&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Important:&#039;&#039; If you block SSH on the host firewall while only having SSH access, you may lock yourself out. Always ensure SSH remains permitted (and test from your client).&lt;br /&gt;
&lt;br /&gt;
=== Document your configuration ===&lt;br /&gt;
To operate and troubleshoot securely, keep a record of your instance configuration:&lt;br /&gt;
&lt;br /&gt;
* Which security groups/rules are attached (ports, protocols, CIDRs)?&lt;br /&gt;
* Host firewall rules (if used), SSH hardening settings, update strategy.&lt;br /&gt;
* Installed services and exposed endpoints.&lt;br /&gt;
* Where secrets are stored/managed (avoid putting secrets in shell history or plain text files).&lt;br /&gt;
&lt;br /&gt;
=== Plan and test a backup strategy ===&lt;br /&gt;
Backups are part of security (availability and recovery).&lt;br /&gt;
&lt;br /&gt;
* Define what needs to be recoverable (system, application data, databases, configuration).&lt;br /&gt;
* Decide on backup frequency and retention (e.g., daily incremental + weekly full).&lt;br /&gt;
* Store backups separately from the instance (avoid a single point of failure).&lt;br /&gt;
* Regularly test restores (a backup that was never restored is an assumption, not a plan).&lt;br /&gt;
&lt;br /&gt;
=== Snapshots and images ===&lt;br /&gt;
Snapshots capture the state of a VM or volume at a point in time (e.g., before risky changes). They can help with rollback, but they do not automatically replace a backup strategy.&lt;br /&gt;
&lt;br /&gt;
* Learn more: [[Guide:_Volumes_and_Images|Guide: Volumes and Images]]&lt;br /&gt;
* Recommended practice:&lt;br /&gt;
** Take a snapshot before major changes (OS upgrades, large configuration changes).&lt;br /&gt;
** Remove outdated snapshots according to your retention plan.&lt;br /&gt;
&lt;br /&gt;
= SSL Certificates &amp;amp; Secure Services =&lt;br /&gt;
&lt;br /&gt;
== Can I get SSL/TLS certificates via bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SSL-Certificates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No, bwCloud-OS does &#039;&#039;&#039;not&#039;&#039;&#039; provide &#039;&#039;&#039;SSL/TLS certificates.&#039;&#039;&#039; However, you can obtain certificates directly from public providers like &#039;&#039;&#039;Let’s Encrypt&#039;&#039;&#039; using tools such as &#039;&#039;&#039;[https://certbot.eff.org/ Certbot]&#039;&#039;&#039;, which you can install and run on your instance.&lt;br /&gt;
&lt;br /&gt;
This allows you, for example, to enable &#039;&#039;&#039;HTTPS&#039;&#039;&#039; for services running on your VM. Don&#039;t forget to open the necessary ports (e.g., 443) using [[Security#Security-Rules|security group rules]].&lt;br /&gt;
&lt;br /&gt;
=Security Incidents =&lt;br /&gt;
&lt;br /&gt;
== What should I do if I suspect my VM has been compromised? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Incident&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your virtual machine is behaving unexpectedly (e.g., high CPU/network load, unknown logins, suspicious processes), it could indicate a possible compromise.&lt;br /&gt;
&lt;br /&gt;
If you suspect that your VM has been compromised, please take the following steps &#039;&#039;&#039;immediately&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard].&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;Stop the affected instance(s).&#039;&#039;&#039; &#039;&#039;Do not delete them!&#039;&#039; This preserves data for further analysis.&lt;br /&gt;
# &#039;&#039;&#039;Submit a support ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ bwSupportPortal] with the following details:&lt;br /&gt;
#*       Which instance(s) are potentially affected?&lt;br /&gt;
#* How is the suspicious behavior observed? (e.g. logs, performance, alerts)&lt;br /&gt;
#* What actions have you already taken?&lt;br /&gt;
&lt;br /&gt;
Our team will contact you as soon as possible to help investigate and resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Does the bwCloud-OS operations team inspect running instances (e.g. through penetration tests)? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Scans&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contents and configuration of user instances are not inspected&#039;&#039;&#039; — we do &#039;&#039;&#039;not&#039;&#039;&#039; perform penetration tests or port scans on the instances. We also &#039;&#039;&#039;never look inside&#039;&#039;&#039; user virtual machines.&lt;br /&gt;
&lt;br /&gt;
However, the overall bwCloud-OS operating environment is actively monitored. For example, network monitoring tracks current inbound and outbound traffic levels. If certain parameters deviate significantly from typical patterns, this may trigger further investigation —  including direct contact with the affected user.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2215</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Security&amp;diff=2215"/>
		<updated>2026-04-27T11:37:16Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Security Checklist */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;By default,  bwCloud-OS VMs are only accessible via &amp;lt;strong&amp;gt;SSH (port 22)&amp;lt;/strong&amp;gt; and  &amp;lt;strong&amp;gt;ICMP&amp;lt;/strong&amp;gt; (e.g., &#039;&#039;ping&#039;&#039;);  all other incoming traffic is blocked for security.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To allow access on additional ports (e.g. HTTPS/443), you can add rules via the &amp;lt;strong&amp;gt;Security Groups&amp;lt;/strong&amp;gt; in the [https://portal.bw-cloud.org/ Dashboard] — changes take effect immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Some ports are &amp;lt;strong&amp;gt;centrally filtered&amp;lt;/strong&amp;gt; in specific bwCloud-OS regions and cannot be opened individually; refer to this [[Blocked_and_Allowed_Ports|overview]] for region-specific details.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you suspect a &amp;lt;strong&amp;gt;security incident&amp;lt;/strong&amp;gt;, stop the affected VMs and submit a [https://bw-support.scc.kit.edu/ support ticket] immediately.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Access Control &amp;amp; Firewall Rules =&lt;br /&gt;
&lt;br /&gt;
== What network access is allowed by default in bwCloud-OS instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Default&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, &#039;&#039;&#039;bwCloud-OS instances&#039;&#039;&#039; are accessible via:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; – for remote login and configuration&lt;br /&gt;
* &#039;&#039;&#039;ICMP&#039;&#039;&#039; – to allow basic network diagnostics like &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This initial access is explicitly permitted by the &#039;&#039;&#039;automatically assigned security group&#039;&#039;&#039; (named &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;) in our configuration. This is not the default behavior in OpenStack — it is provided by bwCloud-OS to simplify first-time access for users.&lt;br /&gt;
&lt;br /&gt;
== How do I open additional ports for my instance? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Rules&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A newly created virtual machine in bwCloud-OS is only accessible from the outside via &#039;&#039;&#039;SSH (port 22)&#039;&#039;&#039; and &#039;&#039;&#039;ICMP&#039;&#039;&#039;.  All other inbound traffic is &#039;&#039;&#039;blocked&#039;&#039;&#039; by default — meaning external traffic on other ports cannot reach the instance.&lt;br /&gt;
&lt;br /&gt;
To allow access on other ports (e.g. for web servers or applications), you need to &#039;&#039;&#039;add a rule&#039;&#039;&#039; to the relevant &#039;&#039;&#039;security group&#039;&#039;&#039;. &#039;&#039;Changes to security group rules apply immediately to all instances using that group&#039;&#039; — there&#039;s no need to reboot the instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening Port 443 for HTTPS Access ===&lt;br /&gt;
If you&#039;re running a web server that should be accessible via &#039;&#039;&#039;HTTPS&#039;&#039;&#039;, you typically need to open &#039;&#039;&#039;port 443&#039;&#039;&#039; in a security group assigned to your instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Steps in the [https://portal.bw-cloud.org/ Dashboard]:&#039;&#039;&#039;&lt;br /&gt;
# In the left menu, go to &#039;&#039;&#039;Network → Security Groups&#039;&#039;&#039;. A list of all defined security groups will appear.  &lt;br /&gt;
#* &#039;&#039;&#039;Recommended:&#039;&#039;&#039; Consider creating a dedicated security group (e.g. named &amp;lt;code&amp;gt;https-access&amp;lt;/code&amp;gt;), and assign it to your instance using &#039;&#039;&#039;Edit Security Groups&#039;&#039;&#039; in the instance menu before the next step.&lt;br /&gt;
# Find the relevant group and click &#039;&#039;&#039;Manage Rules&#039;&#039;&#039;. You’ll see all currently defined rules for that group.&lt;br /&gt;
# Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; to create a new one.&lt;br /&gt;
# In the dialog that appears, choose one of the following:&lt;br /&gt;
#* &#039;&#039;&#039;HTTPS&#039;&#039;&#039; from the &#039;&#039;&#039;Rule&#039;&#039;&#039; dropdown (automatically fills port 443), or&lt;br /&gt;
#* &#039;&#039;&#039;Custom TCP Rule&#039;&#039;&#039;, then manually enter &#039;&#039;&#039;443&#039;&#039;&#039; in the &#039;&#039;&#039;Port&#039;&#039;&#039; field.&lt;br /&gt;
# In the &#039;&#039;&#039;CIDR&#039;&#039;&#039; field, specify which IP addresses should be allowed to connect:&lt;br /&gt;
#* Use a specific IP range (e.g. &amp;lt;code&amp;gt;192.168.0.0/24&amp;lt;/code&amp;gt;) to &#039;&#039;&#039;limit access&#039;&#039;&#039;&lt;br /&gt;
#* ⚠️ Using &#039;&#039;&#039;&amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt;&#039;&#039;&#039; allows access from &#039;&#039;&#039;any IPv4 address&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;::/0&amp;lt;/code&amp;gt;&#039;&#039;&#039;  from &#039;&#039;&#039;any IPv6 address&#039;&#039;&#039;.&lt;br /&gt;
# Set the &#039;&#039;&#039;Direction&#039;&#039;&#039; of the rule:&lt;br /&gt;
#* &amp;lt;code&amp;gt;Ingress&amp;lt;/code&amp;gt; = incoming connections (usually what you want)&lt;br /&gt;
#* &amp;lt;code&amp;gt;Egress&amp;lt;/code&amp;gt; = outgoing connections&lt;br /&gt;
# Click &#039;&#039;&#039;Add&#039;&#039;&#039;. The rule will be created and added to the list immediately.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Example: Opening a Port only for Access from Certain IP Ranges ===&lt;br /&gt;
&#039;&#039;&#039;➡️&#039;&#039;&#039;  [[Guide: Security Group|Security Groups Guide]]&lt;br /&gt;
&lt;br /&gt;
== Are some ports blocked in bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Blocked-Ports&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. Some ports are &#039;&#039;&#039;centrally&#039;&#039;&#039; &#039;&#039;&#039;blocked&#039;&#039;&#039; in &#039;&#039;&#039;certain&#039;&#039;&#039; &#039;&#039;&#039;bwCloud-OS regions&#039;&#039;&#039; due to specific network policies at the participating university data centers. Centrally blocked ports cannot be opened individually. &lt;br /&gt;
&lt;br /&gt;
For more details — including which ports are affected in each region — see the page [[Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
= Security Checklist =&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide a basic security checklist for virtual machines? ==&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following checklist helps you harden your bwCloud-OS instance after creation.&lt;br /&gt;
&lt;br /&gt;
== Secure SSH access ==&lt;br /&gt;
* Read and apply the recommendations in the [[Guide:_SSH|SSH guide]].&lt;br /&gt;
&lt;br /&gt;
== Keep the system updated ==&lt;br /&gt;
Keeping your instance up to date is one of the most effective security measures: security updates fix known vulnerabilities that may otherwise be exploitable.&lt;br /&gt;
&lt;br /&gt;
There are two common approaches:&lt;br /&gt;
* &#039;&#039;&#039;Manual updates (one-time / on demand):&#039;&#039;&#039; You run updates yourself (e.g., after login, on a regular schedule).&lt;br /&gt;
* &#039;&#039;&#039;Automatic updates:&#039;&#039;&#039; The system installs security updates automatically in the background. On Ubuntu/Debian this is commonly done via &amp;lt;code&amp;gt;unattended-upgrades&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Example (Ubuntu/Debian) ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Manual updates (one-time)&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt -y upgrade&lt;br /&gt;
&lt;br /&gt;
# Automatic security updates (background)&lt;br /&gt;
sudo apt -y install unattended-upgrades&lt;br /&gt;
sudo dpkg-reconfigure --priority=low unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Allow only the minimal required ports in bwCloud-OS Security Groups ==&lt;br /&gt;
Only open the ports you actually need. This reduces the attack surface and limits who can reach services on your VM.&lt;br /&gt;
&lt;br /&gt;
* Check your instance&#039;s security groups in the [https://portal.bw-cloud.org/ Dashboard] and allow only the minimal required inbound rules.&lt;br /&gt;
* Restrict access by IP range (CIDR) wherever possible (avoid &amp;lt;code&amp;gt;0.0.0.0/0&amp;lt;/code&amp;gt; unless truly required).&lt;br /&gt;
* For step-by-step instructions and examples, see: [[Security#Security-Rules|How do I open additional ports for my instance?]]&lt;br /&gt;
* Note: some ports may be centrally filtered in certain regions; see [[Blocked_and_Allowed_Ports|Blocked and Allowed Ports]].&lt;br /&gt;
&lt;br /&gt;
== Optional host firewall (e.g., UFW on Ubuntu) ==&lt;br /&gt;
Security groups are the primary inbound filter in bwCloud-OS. A host firewall can provide an additional layer (defense-in-depth), e.g., to enforce local policies on the VM.&lt;br /&gt;
&lt;br /&gt;
=== Example (Ubuntu with UFW) ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt -y install ufw&lt;br /&gt;
sudo ufw default deny incoming&lt;br /&gt;
sudo ufw default allow outgoing&lt;br /&gt;
&lt;br /&gt;
# Allow SSH (ideally restrict in the bwCloud-OS security group as well)&lt;br /&gt;
sudo ufw allow 22/tcp&lt;br /&gt;
&lt;br /&gt;
# Example: allow HTTPS if you opened 443 in the security group&lt;br /&gt;
sudo ufw allow 443/tcp&lt;br /&gt;
&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw status verbose&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Important:&#039;&#039; If you block SSH on the host firewall while only having SSH access, you may lock yourself out. Always ensure SSH remains permitted (and test from your client).&lt;br /&gt;
&lt;br /&gt;
== Document your configuration ==&lt;br /&gt;
To operate and troubleshoot securely, keep a record of your instance configuration:&lt;br /&gt;
&lt;br /&gt;
* Which security groups/rules are attached (ports, protocols, CIDRs)?&lt;br /&gt;
* Host firewall rules (if used), SSH hardening settings, update strategy.&lt;br /&gt;
* Installed services and exposed endpoints.&lt;br /&gt;
* Where secrets are stored/managed (avoid putting secrets in shell history or plain text files).&lt;br /&gt;
&lt;br /&gt;
== Plan and test a backup strategy ==&lt;br /&gt;
Backups are part of security (availability and recovery).&lt;br /&gt;
&lt;br /&gt;
* Define what needs to be recoverable (system, application data, databases, configuration).&lt;br /&gt;
* Decide on backup frequency and retention (e.g., daily incremental + weekly full).&lt;br /&gt;
* Store backups separately from the instance (avoid a single point of failure).&lt;br /&gt;
* Regularly test restores (a backup that was never restored is an assumption, not a plan).&lt;br /&gt;
&lt;br /&gt;
== Snapshots and images ==&lt;br /&gt;
Snapshots capture the state of a VM or volume at a point in time (e.g., before risky changes). They can help with rollback, but they do not automatically replace a backup strategy.&lt;br /&gt;
&lt;br /&gt;
* Learn more: [[Guide:_Volumes_and_Images|Guide: Volumes and Images]]&lt;br /&gt;
* Recommended practice:&lt;br /&gt;
** Take a snapshot before major changes (OS upgrades, large configuration changes).&lt;br /&gt;
** Remove outdated snapshots according to your retention plan.&lt;br /&gt;
&lt;br /&gt;
= SSL Certificates &amp;amp; Secure Services =&lt;br /&gt;
&lt;br /&gt;
== Can I get SSL/TLS certificates via bwCloud-OS? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SSL-Certificates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No, bwCloud-OS does &#039;&#039;&#039;not&#039;&#039;&#039; provide &#039;&#039;&#039;SSL/TLS certificates.&#039;&#039;&#039; However, you can obtain certificates directly from public providers like &#039;&#039;&#039;Let’s Encrypt&#039;&#039;&#039; using tools such as &#039;&#039;&#039;[https://certbot.eff.org/ Certbot]&#039;&#039;&#039;, which you can install and run on your instance.&lt;br /&gt;
&lt;br /&gt;
This allows you, for example, to enable &#039;&#039;&#039;HTTPS&#039;&#039;&#039; for services running on your VM. Don&#039;t forget to open the necessary ports (e.g., 443) using [[Security#Security-Rules|security group rules]].&lt;br /&gt;
&lt;br /&gt;
=Security Incidents =&lt;br /&gt;
&lt;br /&gt;
== What should I do if I suspect my VM has been compromised? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Incident&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your virtual machine is behaving unexpectedly (e.g., high CPU/network load, unknown logins, suspicious processes), it could indicate a possible compromise.&lt;br /&gt;
&lt;br /&gt;
If you suspect that your VM has been compromised, please take the following steps &#039;&#039;&#039;immediately&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard].&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;Stop the affected instance(s).&#039;&#039;&#039; &#039;&#039;Do not delete them!&#039;&#039; This preserves data for further analysis.&lt;br /&gt;
# &#039;&#039;&#039;Submit a support ticket&#039;&#039;&#039; via the [https://bw-support.scc.kit.edu/ bwSupportPortal] with the following details:&lt;br /&gt;
#*       Which instance(s) are potentially affected?&lt;br /&gt;
#* How is the suspicious behavior observed? (e.g. logs, performance, alerts)&lt;br /&gt;
#* What actions have you already taken?&lt;br /&gt;
&lt;br /&gt;
Our team will contact you as soon as possible to help investigate and resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Does the bwCloud-OS operations team inspect running instances (e.g. through penetration tests)? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Security-Scans&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contents and configuration of user instances are not inspected&#039;&#039;&#039; — we do &#039;&#039;&#039;not&#039;&#039;&#039; perform penetration tests or port scans on the instances. We also &#039;&#039;&#039;never look inside&#039;&#039;&#039; user virtual machines.&lt;br /&gt;
&lt;br /&gt;
However, the overall bwCloud-OS operating environment is actively monitored. For example, network monitoring tracks current inbound and outbound traffic levels. If certain parameters deviate significantly from typical patterns, this may trigger further investigation —  including direct contact with the affected user.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2214</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2214"/>
		<updated>2026-04-27T10:13:25Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing &amp;lt;code&amp;gt;Enter&amp;lt;/code&amp;gt; &#039;&#039;&#039;twice&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Images ==&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
subnet = conn.network.create_subnet(&lt;br /&gt;
    name=&amp;quot;mySubnet&amp;quot;,&lt;br /&gt;
    network_id=network.id,&lt;br /&gt;
    ip_version=4,&lt;br /&gt;
    cidr=&amp;quot;192.168.1.0/24&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
router = conn.network.create_router(name=&amp;quot;myRouter&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.add_interface_to_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
external_net = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
conn.network.update_router(&lt;br /&gt;
    router,&lt;br /&gt;
    external_gateway_info={&amp;quot;network_id&amp;quot;: external_net.id}&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.remove_interface_from_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_router(router.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_subnet(subnet.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Programmatic_Access_and_Automation&amp;diff=2213</id>
		<title>Programmatic Access and Automation</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Programmatic_Access_and_Automation&amp;diff=2213"/>
		<updated>2026-04-27T10:06:47Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* How can I connect to the bwCloud-OS using the OpenStack Python SDK? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span id=&amp;quot;In-a-Nutshell&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;&#039;Application Credentials&#039;&#039;&#039; enable secure, token-based access to bwCloud-OS — ideal for CLI usage and automation. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You can use these credentials with the &#039;&#039;&#039;OpenStack CLI&#039;&#039;&#039;  to manage cloud resources from the command line.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You can also use the credentials with the &#039;&#039;&#039;OpenStack Python SDK&#039;&#039;&#039; to manage cloud resources programmatically from within Python scripts or applications.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;&#039;Automation tools&#039;&#039;&#039; like &#039;&#039;&#039;Ansible&#039;&#039;&#039; or &#039;&#039;&#039;Terraform&#039;&#039;&#039; can be used for efficient deployment and configuration of instances.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Application Credentials =&lt;br /&gt;
&lt;br /&gt;
== How can I create an application credential? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Application-Credential&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Application Credentials&#039;&#039;&#039; (also called &#039;&#039;&#039;tokens&#039;&#039;&#039;) allow access to your OpenStack project in an automated or script-based way — without requiring a password. To create one, you must have the necessary &#039;&#039;&#039;member privileges&#039;&#039;&#039; in the target project.&lt;br /&gt;
&lt;br /&gt;
=== Steps to Create an Application Credential ===&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard]&#039;&#039;&#039; and select the correct &#039;&#039;&#039;region&#039;&#039;&#039;.&lt;br /&gt;
# Go to &#039;&#039;&#039;Identity → Application Credentials&#039;&#039;&#039; and click &#039;&#039;&#039;Create Application Credential&#039;&#039;&#039;.&lt;br /&gt;
# In the form that opens, fill out:&lt;br /&gt;
#* &#039;&#039;&#039;Name&#039;&#039;&#039; – a descriptive name for the credential.&lt;br /&gt;
#* &#039;&#039;&#039;Secret&#039;&#039;&#039; – choose a secure secret (password-like).&lt;br /&gt;
#* &#039;&#039;&#039;Expiration&#039;&#039;&#039; – set an (optional) expiration date.&lt;br /&gt;
# At the bottom of the form, click &#039;&#039;&#039;Create Application Credential&#039;&#039;&#039;.&lt;br /&gt;
# Download the &#039;&#039;&#039;&#039;&#039;OpenRC&#039;&#039;&#039;&#039;&#039; file and save it, for example as &amp;lt;code&amp;gt;my_token.sh&amp;lt;/code&amp;gt;. Alternatively, you can download the file &amp;lt;code&amp;gt;&#039;&#039;&#039;&#039;&#039;clouds.yaml&#039;&#039;&#039;&#039;&#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&#039;&#039;Make sure to protect your secret&#039;&#039;  &#039;&#039;— store it securely and do not share it.&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;📌 &#039;&#039;&#039;Note:&#039;&#039;&#039; The login-based method (via the top-right menu in the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard]&#039;&#039;&#039;) requires a password, which is not enabled by default in bwCloud-OS.&lt;br /&gt;
&lt;br /&gt;
=== Using the &#039;&#039;OpenRC&#039;&#039; file (Recommended for CLI Usage) ===&lt;br /&gt;
Source your credential file &#039;&#039;my_token.sh:&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;source my_token.sh&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following command (see [[Programmatic Access and Automation#OpenStack-CLI|OpenStack CLI]]) will display the active cloud configuration, including the application credentials:&lt;br /&gt;
&amp;lt;pre&amp;gt;openstack configuration show&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
To test the configuration, run the following command. You should see your credential ID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;curl \&lt;br /&gt;
-s \&lt;br /&gt;
-H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
-d &#039;{ &amp;quot;auth&amp;quot;: { &amp;quot;identity&amp;quot;: { &amp;quot;methods&amp;quot;: [&amp;quot;application_credential&amp;quot;], &amp;quot;application_credential&amp;quot;: { &amp;quot;id&amp;quot;: &amp;quot;&#039;${OS_APPLICATION_CREDENTIAL_ID}&#039;&amp;quot;, &amp;quot;secret&amp;quot;: &amp;quot;&#039;${OS_APPLICATION_CREDENTIAL_SECRET}&#039;&amp;quot; }}}}&#039; \&lt;br /&gt;
&amp;quot;${OS_AUTH_URL}/auth/tokens&amp;quot; \&lt;br /&gt;
| jq .token.application_credential&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;jq&amp;lt;/code&amp;gt; are not installed, you can install them using your system’s package manager (&amp;lt;code&amp;gt;apt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;dnf&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;brew&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
==== Optional: Ask for the Secret at Runtime ====&lt;br /&gt;
For added security, you can modify your &amp;lt;code&amp;gt;my_token.sh&amp;lt;/code&amp;gt; file so that the secret is not stored in plain text within the file. Replace the line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; export OS_APPLICATION_CREDENTIAL_SECRET=******************** &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
with:&amp;lt;pre&amp;gt;echo &amp;quot;Passphrase: &amp;quot;&lt;br /&gt;
read -sr os_credential_secret_input&lt;br /&gt;
export OS_APPLICATION_CREDENTIAL_SECRET=&amp;quot;$os_credential_secret_input&amp;quot;&amp;lt;/pre&amp;gt;This way, you will be prompted for the secret each time you use the credential file.&lt;br /&gt;
&lt;br /&gt;
=== Using the &#039;&#039;clouds.yaml&#039;&#039; file (Recommended for Automation) ===&lt;br /&gt;
A &amp;lt;code&amp;gt;&#039;&#039;&#039;&#039;&#039;clouds.yaml&#039;&#039;&#039;&#039;&#039;&amp;lt;/code&amp;gt; file provides a convenient way to configure access to OpenStack without exporting many environment variables.&lt;br /&gt;
==== Example &#039;&#039;clouds.yaml&#039;&#039; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clouds:&lt;br /&gt;
  openstack:&lt;br /&gt;
    auth:&lt;br /&gt;
      auth_url: https://your-auth-url:5000&lt;br /&gt;
      application_credential_id: &amp;quot;YOUR_ID&amp;quot;&lt;br /&gt;
      application_credential_secret: &amp;quot;YOUR_SECRET&amp;quot;&lt;br /&gt;
    region_name: &amp;quot;RegionOne&amp;quot;&lt;br /&gt;
    interface: &amp;quot;public&amp;quot;&lt;br /&gt;
    identity_api_version: 3&lt;br /&gt;
    auth_type: &amp;quot;v3applicationcredential&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Loading and Testing the Configuration ====&lt;br /&gt;
If this is your only cloud, you can place the file at one of the default locations:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;~/.config/openstack/clouds.yaml&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;/etc/openstack/clouds.yaml&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenStack CLI tools will automatically detect the file there.&lt;br /&gt;
&lt;br /&gt;
If your file is stored in a custom location, you can specify it explicitly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export OS_CLIENT_CONFIG_FILE=/path/to/clouds.yaml&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In multi-cloud setups, you can define multiple entries and select one by specifying the cloud name, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export OS_CLOUD=openstack&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once the above configuration is set, the following command (see [[Programmatic Access and Automation#OpenStack-CLI|OpenStack CLI]]) will display the active cloud configuration, including the application credentials:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack configuration show&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= OpenStack CLI =&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-CLI&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How can I connect to the bwCloud-OS using the OpenStack CLI? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-CLI&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To manage your resources from the command line, you can use the &#039;&#039;&#039;OpenStack Client&#039;&#039;&#039; (&amp;lt;code&amp;gt;openstack&amp;lt;/code&amp;gt; command-line tool, implemented in Python).&lt;br /&gt;
&lt;br /&gt;
Installation of the client depends on your operating system, e.g. for Ubuntu (for other installation methods, see the guide [[Guide: OpenStack CLI – Basic Usage|OpenStack CLI]]):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstackclient &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Authentication Methods ===&lt;br /&gt;
See the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
==== Method 2: Using Username and Password (Login-based – not default in bwCloud-OS) ====&lt;br /&gt;
This method only works if password-based authentication is enabled for your account.&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard]&#039;&#039;&#039;.&lt;br /&gt;
# In the top-right corner, click &#039;&#039;&#039;&amp;quot;OpenStack RC File&amp;quot;&#039;&#039;&#039;.&lt;br /&gt;
# &#039;&#039;&#039;Download and save&#039;&#039;&#039; the file, for example as &amp;lt;code&amp;gt;my_creds.sh&amp;lt;/code&amp;gt;.&lt;br /&gt;
--&amp;gt;=== Testing the Connection ===&lt;br /&gt;
&lt;br /&gt;
Run the following commands in a terminal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
source ./my_token.sh&lt;br /&gt;
openstack token issue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will issue a new authentication token, confirming that your configuration works correctly.&lt;br /&gt;
&lt;br /&gt;
== How can I perform basic operations with the OpenStack CLI? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;CLI-COMMANDS&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For common tasks such as managing instances, volumes, and networks, see:&lt;br /&gt;
[[Guide: OpenStack CLI – Basic Usage]].&lt;br /&gt;
&lt;br /&gt;
= OpenStack Python SDK =&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-SDK&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How can I connect to the bwCloud-OS using the OpenStack Python SDK? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-SDK&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To manage your resources from within Python scripts, you can use the &#039;&#039;&#039;OpenStack Python SDK&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Installation depends on your operating system, e.g. for Ubuntu (for other installation methods, see the guide [[Guide: OpenStack Python SDK – Basic Usage|OpenStack Python SDK]]):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Authentication Methods ===&lt;br /&gt;
See the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
For this purpose, we recommend  using the &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
=== Testing the Connection ===&lt;br /&gt;
&lt;br /&gt;
Start a Python shell and run:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
conn.authorize()&lt;br /&gt;
token = conn.session.get_token()&lt;br /&gt;
print(&amp;quot;Token:&amp;quot;, token)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will issue a new authentication token, confirming that your configuration works correctly.&lt;br /&gt;
&lt;br /&gt;
== How can I perform basic operations with the OpenStack SDK? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SDK-ROUTINES&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For common tasks such as managing instances, volumes, and networks, see:&lt;br /&gt;
[[Guide: OpenStack Python SDK – Basic Usage]].&lt;br /&gt;
&lt;br /&gt;
= Auto-Deployment =&lt;br /&gt;
The following tools are commonly used for (semi-)automated provisioning of resources.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Usage&lt;br /&gt;
|-&lt;br /&gt;
| [https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs Terraform] || This tool can be used to create an instance or a defined infrastructure.&lt;br /&gt;
|-&lt;br /&gt;
| [https://docs.ansible.com/ansible/latest/index.html Ansible] || Create roles or tasks for all customizations that you make in an instance.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide templates for automated deployment of OpenStack instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Ansible-Template&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. You can use this [https://github.com/bwCloud/ansible-template Ansible template] to get started more easily.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Programmatic_Access_and_Automation&amp;diff=2212</id>
		<title>Programmatic Access and Automation</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Programmatic_Access_and_Automation&amp;diff=2212"/>
		<updated>2026-04-27T10:06:12Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span id=&amp;quot;In-a-Nutshell&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;&#039;Application Credentials&#039;&#039;&#039; enable secure, token-based access to bwCloud-OS — ideal for CLI usage and automation. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You can use these credentials with the &#039;&#039;&#039;OpenStack CLI&#039;&#039;&#039;  to manage cloud resources from the command line.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You can also use the credentials with the &#039;&#039;&#039;OpenStack Python SDK&#039;&#039;&#039; to manage cloud resources programmatically from within Python scripts or applications.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;&#039;Automation tools&#039;&#039;&#039; like &#039;&#039;&#039;Ansible&#039;&#039;&#039; or &#039;&#039;&#039;Terraform&#039;&#039;&#039; can be used for efficient deployment and configuration of instances.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Application Credentials =&lt;br /&gt;
&lt;br /&gt;
== How can I create an application credential? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Application-Credential&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Application Credentials&#039;&#039;&#039; (also called &#039;&#039;&#039;tokens&#039;&#039;&#039;) allow access to your OpenStack project in an automated or script-based way — without requiring a password. To create one, you must have the necessary &#039;&#039;&#039;member privileges&#039;&#039;&#039; in the target project.&lt;br /&gt;
&lt;br /&gt;
=== Steps to Create an Application Credential ===&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard]&#039;&#039;&#039; and select the correct &#039;&#039;&#039;region&#039;&#039;&#039;.&lt;br /&gt;
# Go to &#039;&#039;&#039;Identity → Application Credentials&#039;&#039;&#039; and click &#039;&#039;&#039;Create Application Credential&#039;&#039;&#039;.&lt;br /&gt;
# In the form that opens, fill out:&lt;br /&gt;
#* &#039;&#039;&#039;Name&#039;&#039;&#039; – a descriptive name for the credential.&lt;br /&gt;
#* &#039;&#039;&#039;Secret&#039;&#039;&#039; – choose a secure secret (password-like).&lt;br /&gt;
#* &#039;&#039;&#039;Expiration&#039;&#039;&#039; – set an (optional) expiration date.&lt;br /&gt;
# At the bottom of the form, click &#039;&#039;&#039;Create Application Credential&#039;&#039;&#039;.&lt;br /&gt;
# Download the &#039;&#039;&#039;&#039;&#039;OpenRC&#039;&#039;&#039;&#039;&#039; file and save it, for example as &amp;lt;code&amp;gt;my_token.sh&amp;lt;/code&amp;gt;. Alternatively, you can download the file &amp;lt;code&amp;gt;&#039;&#039;&#039;&#039;&#039;clouds.yaml&#039;&#039;&#039;&#039;&#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&#039;&#039;Make sure to protect your secret&#039;&#039;  &#039;&#039;— store it securely and do not share it.&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;📌 &#039;&#039;&#039;Note:&#039;&#039;&#039; The login-based method (via the top-right menu in the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard]&#039;&#039;&#039;) requires a password, which is not enabled by default in bwCloud-OS.&lt;br /&gt;
&lt;br /&gt;
=== Using the &#039;&#039;OpenRC&#039;&#039; file (Recommended for CLI Usage) ===&lt;br /&gt;
Source your credential file &#039;&#039;my_token.sh:&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;source my_token.sh&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following command (see [[Programmatic Access and Automation#OpenStack-CLI|OpenStack CLI]]) will display the active cloud configuration, including the application credentials:&lt;br /&gt;
&amp;lt;pre&amp;gt;openstack configuration show&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
To test the configuration, run the following command. You should see your credential ID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;curl \&lt;br /&gt;
-s \&lt;br /&gt;
-H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
-d &#039;{ &amp;quot;auth&amp;quot;: { &amp;quot;identity&amp;quot;: { &amp;quot;methods&amp;quot;: [&amp;quot;application_credential&amp;quot;], &amp;quot;application_credential&amp;quot;: { &amp;quot;id&amp;quot;: &amp;quot;&#039;${OS_APPLICATION_CREDENTIAL_ID}&#039;&amp;quot;, &amp;quot;secret&amp;quot;: &amp;quot;&#039;${OS_APPLICATION_CREDENTIAL_SECRET}&#039;&amp;quot; }}}}&#039; \&lt;br /&gt;
&amp;quot;${OS_AUTH_URL}/auth/tokens&amp;quot; \&lt;br /&gt;
| jq .token.application_credential&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;jq&amp;lt;/code&amp;gt; are not installed, you can install them using your system’s package manager (&amp;lt;code&amp;gt;apt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;dnf&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;brew&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
==== Optional: Ask for the Secret at Runtime ====&lt;br /&gt;
For added security, you can modify your &amp;lt;code&amp;gt;my_token.sh&amp;lt;/code&amp;gt; file so that the secret is not stored in plain text within the file. Replace the line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; export OS_APPLICATION_CREDENTIAL_SECRET=******************** &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
with:&amp;lt;pre&amp;gt;echo &amp;quot;Passphrase: &amp;quot;&lt;br /&gt;
read -sr os_credential_secret_input&lt;br /&gt;
export OS_APPLICATION_CREDENTIAL_SECRET=&amp;quot;$os_credential_secret_input&amp;quot;&amp;lt;/pre&amp;gt;This way, you will be prompted for the secret each time you use the credential file.&lt;br /&gt;
&lt;br /&gt;
=== Using the &#039;&#039;clouds.yaml&#039;&#039; file (Recommended for Automation) ===&lt;br /&gt;
A &amp;lt;code&amp;gt;&#039;&#039;&#039;&#039;&#039;clouds.yaml&#039;&#039;&#039;&#039;&#039;&amp;lt;/code&amp;gt; file provides a convenient way to configure access to OpenStack without exporting many environment variables.&lt;br /&gt;
==== Example &#039;&#039;clouds.yaml&#039;&#039; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clouds:&lt;br /&gt;
  openstack:&lt;br /&gt;
    auth:&lt;br /&gt;
      auth_url: https://your-auth-url:5000&lt;br /&gt;
      application_credential_id: &amp;quot;YOUR_ID&amp;quot;&lt;br /&gt;
      application_credential_secret: &amp;quot;YOUR_SECRET&amp;quot;&lt;br /&gt;
    region_name: &amp;quot;RegionOne&amp;quot;&lt;br /&gt;
    interface: &amp;quot;public&amp;quot;&lt;br /&gt;
    identity_api_version: 3&lt;br /&gt;
    auth_type: &amp;quot;v3applicationcredential&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Loading and Testing the Configuration ====&lt;br /&gt;
If this is your only cloud, you can place the file at one of the default locations:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;~/.config/openstack/clouds.yaml&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;/etc/openstack/clouds.yaml&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenStack CLI tools will automatically detect the file there.&lt;br /&gt;
&lt;br /&gt;
If your file is stored in a custom location, you can specify it explicitly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export OS_CLIENT_CONFIG_FILE=/path/to/clouds.yaml&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In multi-cloud setups, you can define multiple entries and select one by specifying the cloud name, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export OS_CLOUD=openstack&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once the above configuration is set, the following command (see [[Programmatic Access and Automation#OpenStack-CLI|OpenStack CLI]]) will display the active cloud configuration, including the application credentials:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack configuration show&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= OpenStack CLI =&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-CLI&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How can I connect to the bwCloud-OS using the OpenStack CLI? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-CLI&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To manage your resources from the command line, you can use the &#039;&#039;&#039;OpenStack Client&#039;&#039;&#039; (&amp;lt;code&amp;gt;openstack&amp;lt;/code&amp;gt; command-line tool, implemented in Python).&lt;br /&gt;
&lt;br /&gt;
Installation of the client depends on your operating system, e.g. for Ubuntu (for other installation methods, see the guide [[Guide: OpenStack CLI – Basic Usage|OpenStack CLI]]):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstackclient &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Authentication Methods ===&lt;br /&gt;
See the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
==== Method 2: Using Username and Password (Login-based – not default in bwCloud-OS) ====&lt;br /&gt;
This method only works if password-based authentication is enabled for your account.&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard]&#039;&#039;&#039;.&lt;br /&gt;
# In the top-right corner, click &#039;&#039;&#039;&amp;quot;OpenStack RC File&amp;quot;&#039;&#039;&#039;.&lt;br /&gt;
# &#039;&#039;&#039;Download and save&#039;&#039;&#039; the file, for example as &amp;lt;code&amp;gt;my_creds.sh&amp;lt;/code&amp;gt;.&lt;br /&gt;
--&amp;gt;=== Testing the Connection ===&lt;br /&gt;
&lt;br /&gt;
Run the following commands in a terminal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
source ./my_token.sh&lt;br /&gt;
openstack token issue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will issue a new authentication token, confirming that your configuration works correctly.&lt;br /&gt;
&lt;br /&gt;
== How can I perform basic operations with the OpenStack CLI? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;CLI-COMMANDS&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For common tasks such as managing instances, volumes, and networks, see:&lt;br /&gt;
[[Guide: OpenStack CLI – Basic Usage]].&lt;br /&gt;
&lt;br /&gt;
= OpenStack Python SDK =&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-SDK&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How can I connect to the bwCloud-OS using the OpenStack Python SDK? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-SDK&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To manage your resources from within Python scripts, you can use the &#039;&#039;&#039;OpenStack Python SDK&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Installation depends on your operating system, e.g. for Ubuntu (for other installation methods, see the guide: [[Guide: OpenStack Python SDK – Basic Usage|OpenStack Python SDK]]):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Authentication Methods ===&lt;br /&gt;
See the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
For this purpose, we recommend  using the &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
=== Testing the Connection ===&lt;br /&gt;
&lt;br /&gt;
Start a Python shell and run:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
conn.authorize()&lt;br /&gt;
token = conn.session.get_token()&lt;br /&gt;
print(&amp;quot;Token:&amp;quot;, token)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will issue a new authentication token, confirming that your configuration works correctly.&lt;br /&gt;
&lt;br /&gt;
== How can I perform basic operations with the OpenStack SDK? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SDK-ROUTINES&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For common tasks such as managing instances, volumes, and networks, see:&lt;br /&gt;
[[Guide: OpenStack Python SDK – Basic Usage]].&lt;br /&gt;
&lt;br /&gt;
= Auto-Deployment =&lt;br /&gt;
The following tools are commonly used for (semi-)automated provisioning of resources.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Usage&lt;br /&gt;
|-&lt;br /&gt;
| [https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs Terraform] || This tool can be used to create an instance or a defined infrastructure.&lt;br /&gt;
|-&lt;br /&gt;
| [https://docs.ansible.com/ansible/latest/index.html Ansible] || Create roles or tasks for all customizations that you make in an instance.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide templates for automated deployment of OpenStack instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Ansible-Template&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. You can use this [https://github.com/bwCloud/ansible-template Ansible template] to get started more easily.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Programmatic_Access_and_Automation&amp;diff=2211</id>
		<title>Programmatic Access and Automation</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Programmatic_Access_and_Automation&amp;diff=2211"/>
		<updated>2026-04-27T10:05:00Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span id=&amp;quot;In-a-Nutshell&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
{{InANutshell|&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;&#039;Application Credentials&#039;&#039;&#039; enable secure, token-based access to bwCloud-OS — ideal for CLI usage and automation. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You can use these credentials with the &#039;&#039;&#039;OpenStack CLI&#039;&#039;&#039;  to manage cloud resources from the command line.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You can also use the credentials with the &#039;&#039;&#039;OpenStack Python SDK&#039;&#039;&#039; to manage cloud resources programmatically from within Python scripts or applications.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&#039;&#039;&#039;Automation tools&#039;&#039;&#039; like &#039;&#039;&#039;Ansible&#039;&#039;&#039; or &#039;&#039;&#039;Terraform&#039;&#039;&#039; can be used for efficient deployment and configuration of instances.&amp;lt;/li&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Application Credentials =&lt;br /&gt;
&lt;br /&gt;
== How can I create an application credential? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Application-Credential&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Application Credentials&#039;&#039;&#039; (also called &#039;&#039;&#039;tokens&#039;&#039;&#039;) allow access to your OpenStack project in an automated or script-based way — without requiring a password. To create one, you must have the necessary &#039;&#039;&#039;member privileges&#039;&#039;&#039; in the target project.&lt;br /&gt;
&lt;br /&gt;
=== Steps to Create an Application Credential ===&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard]&#039;&#039;&#039; and select the correct &#039;&#039;&#039;region&#039;&#039;&#039;.&lt;br /&gt;
# Go to &#039;&#039;&#039;Identity → Application Credentials&#039;&#039;&#039; and click &#039;&#039;&#039;Create Application Credential&#039;&#039;&#039;.&lt;br /&gt;
# In the form that opens, fill out:&lt;br /&gt;
#* &#039;&#039;&#039;Name&#039;&#039;&#039; – a descriptive name for the credential.&lt;br /&gt;
#* &#039;&#039;&#039;Secret&#039;&#039;&#039; – choose a secure secret (password-like).&lt;br /&gt;
#* &#039;&#039;&#039;Expiration&#039;&#039;&#039; – set an (optional) expiration date.&lt;br /&gt;
# At the bottom of the form, click &#039;&#039;&#039;Create Application Credential&#039;&#039;&#039;.&lt;br /&gt;
# Download the &#039;&#039;&#039;&#039;&#039;OpenRC&#039;&#039;&#039;&#039;&#039; file and save it, for example as &amp;lt;code&amp;gt;my_token.sh&amp;lt;/code&amp;gt;. Alternatively, you can download the file &amp;lt;code&amp;gt;&#039;&#039;&#039;&#039;&#039;clouds.yaml&#039;&#039;&#039;&#039;&#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&#039;&#039;Make sure to protect your secret&#039;&#039;  &#039;&#039;— store it securely and do not share it.&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;📌 &#039;&#039;&#039;Note:&#039;&#039;&#039; The login-based method (via the top-right menu in the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard]&#039;&#039;&#039;) requires a password, which is not enabled by default in bwCloud-OS.&lt;br /&gt;
&lt;br /&gt;
=== Using the &#039;&#039;OpenRC&#039;&#039; file (Recommended for CLI Usage) ===&lt;br /&gt;
Source your credential file &#039;&#039;my_token.sh:&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;source my_token.sh&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following command (see [[Programmatic Access and Automation#OpenStack-CLI|OpenStack CLI]]) will display the active cloud configuration, including the application credentials:&lt;br /&gt;
&amp;lt;pre&amp;gt;openstack configuration show&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
To test the configuration, run the following command. You should see your credential ID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;curl \&lt;br /&gt;
-s \&lt;br /&gt;
-H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
-d &#039;{ &amp;quot;auth&amp;quot;: { &amp;quot;identity&amp;quot;: { &amp;quot;methods&amp;quot;: [&amp;quot;application_credential&amp;quot;], &amp;quot;application_credential&amp;quot;: { &amp;quot;id&amp;quot;: &amp;quot;&#039;${OS_APPLICATION_CREDENTIAL_ID}&#039;&amp;quot;, &amp;quot;secret&amp;quot;: &amp;quot;&#039;${OS_APPLICATION_CREDENTIAL_SECRET}&#039;&amp;quot; }}}}&#039; \&lt;br /&gt;
&amp;quot;${OS_AUTH_URL}/auth/tokens&amp;quot; \&lt;br /&gt;
| jq .token.application_credential&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;jq&amp;lt;/code&amp;gt; are not installed, you can install them using your system’s package manager (&amp;lt;code&amp;gt;apt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;dnf&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;brew&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
==== Optional: Ask for the Secret at Runtime ====&lt;br /&gt;
For added security, you can modify your &amp;lt;code&amp;gt;my_token.sh&amp;lt;/code&amp;gt; file so that the secret is not stored in plain text within the file. Replace the line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; export OS_APPLICATION_CREDENTIAL_SECRET=******************** &amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
with:&amp;lt;pre&amp;gt;echo &amp;quot;Passphrase: &amp;quot;&lt;br /&gt;
read -sr os_credential_secret_input&lt;br /&gt;
export OS_APPLICATION_CREDENTIAL_SECRET=&amp;quot;$os_credential_secret_input&amp;quot;&amp;lt;/pre&amp;gt;This way, you will be prompted for the secret each time you use the credential file.&lt;br /&gt;
&lt;br /&gt;
=== Using the &#039;&#039;clouds.yaml&#039;&#039; file (Recommended for Automation) ===&lt;br /&gt;
A &amp;lt;code&amp;gt;&#039;&#039;&#039;&#039;&#039;clouds.yaml&#039;&#039;&#039;&#039;&#039;&amp;lt;/code&amp;gt; file provides a convenient way to configure access to OpenStack without exporting many environment variables.&lt;br /&gt;
==== Example &#039;&#039;clouds.yaml&#039;&#039; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clouds:&lt;br /&gt;
  openstack:&lt;br /&gt;
    auth:&lt;br /&gt;
      auth_url: https://your-auth-url:5000&lt;br /&gt;
      application_credential_id: &amp;quot;YOUR_ID&amp;quot;&lt;br /&gt;
      application_credential_secret: &amp;quot;YOUR_SECRET&amp;quot;&lt;br /&gt;
    region_name: &amp;quot;RegionOne&amp;quot;&lt;br /&gt;
    interface: &amp;quot;public&amp;quot;&lt;br /&gt;
    identity_api_version: 3&lt;br /&gt;
    auth_type: &amp;quot;v3applicationcredential&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Loading and Testing the Configuration ====&lt;br /&gt;
If this is your only cloud, you can place the file at one of the default locations:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;~/.config/openstack/clouds.yaml&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;/etc/openstack/clouds.yaml&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenStack CLI tools will automatically detect the file there.&lt;br /&gt;
&lt;br /&gt;
If your file is stored in a custom location, you can specify it explicitly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export OS_CLIENT_CONFIG_FILE=/path/to/clouds.yaml&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In multi-cloud setups, you can define multiple entries and select one by specifying the cloud name, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export OS_CLOUD=openstack&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once the above configuration is set, the following command (see [[Programmatic Access and Automation#OpenStack-CLI|OpenStack CLI]]) will display the active cloud configuration, including the application credentials:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack configuration show&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= OpenStack CLI =&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-CLI&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How can I connect to the bwCloud-OS using the OpenStack CLI? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-CLI&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To manage your resources from the command line, you can use the &#039;&#039;&#039;OpenStack Client&#039;&#039;&#039; (&amp;lt;code&amp;gt;openstack&amp;lt;/code&amp;gt; command-line tool, implemented in Python).&lt;br /&gt;
&lt;br /&gt;
Installation of the client depends on your operating system, e.g. for Ubuntu (for other installation methods, see the guide [[Guide: OpenStack CLI – Basic Usage|OpenStack CLI]]):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstackclient &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Authentication Methods ===&lt;br /&gt;
See the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
==== Method 2: Using Username and Password (Login-based – not default in bwCloud-OS) ====&lt;br /&gt;
This method only works if password-based authentication is enabled for your account.&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Log in&#039;&#039;&#039; to the &#039;&#039;&#039;[https://portal.bw-cloud.org/ Dashboard]&#039;&#039;&#039;.&lt;br /&gt;
# In the top-right corner, click &#039;&#039;&#039;&amp;quot;OpenStack RC File&amp;quot;&#039;&#039;&#039;.&lt;br /&gt;
# &#039;&#039;&#039;Download and save&#039;&#039;&#039; the file, for example as &amp;lt;code&amp;gt;my_creds.sh&amp;lt;/code&amp;gt;.&lt;br /&gt;
--&amp;gt;=== Testing the Connection ===&lt;br /&gt;
&lt;br /&gt;
Run the following commands in a terminal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
source ./my_token.sh&lt;br /&gt;
openstack token issue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will issue a new authentication token, confirming that your configuration works correctly.&lt;br /&gt;
&lt;br /&gt;
== How can I perform basic operations with the OpenStack CLI? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;CLI-COMMANDS&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For common tasks such as managing instances, volumes, and networks, see:&lt;br /&gt;
[[Guide: OpenStack CLI – Basic Usage]].&lt;br /&gt;
&lt;br /&gt;
= OpenStack Python SDK =&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-SDK&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How can I connect to the bwCloud-OS using the OpenStack Python SDK? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;OpenStack-SDK&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To manage your resources from within Python scripts, you can use the &#039;&#039;&#039;OpenStack Python SDK&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Installation depends on your operating system, e.g. for Ubuntu (for other installation methods, see: [[Guide: OpenStack Python SDK – Basic Usage]]):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Authentication Methods ===&lt;br /&gt;
See the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
For this purpose, we recommend  using the &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
=== Testing the Connection ===&lt;br /&gt;
&lt;br /&gt;
Start a Python shell and run:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
conn.authorize()&lt;br /&gt;
token = conn.session.get_token()&lt;br /&gt;
print(&amp;quot;Token:&amp;quot;, token)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will issue a new authentication token, confirming that your configuration works correctly.&lt;br /&gt;
&lt;br /&gt;
== How can I perform basic operations with the OpenStack SDK? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;SDK-ROUTINES&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For common tasks such as managing instances, volumes, and networks, see:&lt;br /&gt;
[[Guide: OpenStack Python SDK – Basic Usage]].&lt;br /&gt;
&lt;br /&gt;
= Auto-Deployment =&lt;br /&gt;
The following tools are commonly used for (semi-)automated provisioning of resources.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Usage&lt;br /&gt;
|-&lt;br /&gt;
| [https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs Terraform] || This tool can be used to create an instance or a defined infrastructure.&lt;br /&gt;
|-&lt;br /&gt;
| [https://docs.ansible.com/ansible/latest/index.html Ansible] || Create roles or tasks for all customizations that you make in an instance.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Does bwCloud-OS provide templates for automated deployment of OpenStack instances? ==&lt;br /&gt;
&amp;lt;span id=&amp;quot;Ansible-Template&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes. You can use this [https://github.com/bwCloud/ansible-template Ansible template] to get started more easily.&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_CLI_%E2%80%93_Basic_Usage&amp;diff=2210</id>
		<title>Guide: OpenStack CLI – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_CLI_%E2%80%93_Basic_Usage&amp;diff=2210"/>
		<updated>2026-04-26T15:57:07Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack CLI. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack client, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstackclient &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstackclient_venv&lt;br /&gt;
source openstackclient_venv/bin/activate&lt;br /&gt;
pip install python-openstackclient&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== General Information about Cloud, Project, and User ==&lt;br /&gt;
&lt;br /&gt;
Before working with resources, you can inspect your current configuration and context:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack configuration show&lt;br /&gt;
openstack project list&lt;br /&gt;
openstack token issue&lt;br /&gt;
openstack region list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Images ==&lt;br /&gt;
&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image create ubuntu-24.04 \&lt;br /&gt;
  --file=/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img \&lt;br /&gt;
  --disk-format=qcow2 \&lt;br /&gt;
  --container-format=bare&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image show &amp;amp;lt;IMAGE_ID&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image delete &amp;amp;lt;IMAGE_ID&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair create myKey &amp;gt; myKey.pem&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair delete myKey&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server create \&lt;br /&gt;
  --image ubuntu-24.04 \&lt;br /&gt;
  --flavor p1.tiny \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --key-name myKey \&lt;br /&gt;
  myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server show myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server delete myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume create --size 10 myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume delete myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add volume myVM myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove volume myVM myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network create myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network delete myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet create mySubnet \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --subnet-range 192.168.1.0/24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router create myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router add subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router set myRouter --external-gateway provider_default_net&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router remove subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router delete myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet delete mySubnet&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openstack floating ip create provider_default_net&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack floating ip list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add floating ip myVM &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove floating ip myVM &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack floating ip delete &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group create mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group rule create \&lt;br /&gt;
  --ingress \&lt;br /&gt;
  --proto tcp \&lt;br /&gt;
  --dst-port 80 \&lt;br /&gt;
  --ethertype IPv4 \&lt;br /&gt;
  mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add security group myVM mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove security group myVM mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group delete mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2209</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2209"/>
		<updated>2026-04-26T15:54:59Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Basic Connection */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter &#039;&#039;&#039;twice&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Images ==&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
subnet = conn.network.create_subnet(&lt;br /&gt;
    name=&amp;quot;mySubnet&amp;quot;,&lt;br /&gt;
    network_id=network.id,&lt;br /&gt;
    ip_version=4,&lt;br /&gt;
    cidr=&amp;quot;192.168.1.0/24&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
router = conn.network.create_router(name=&amp;quot;myRouter&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.add_interface_to_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
external_net = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
conn.network.update_router(&lt;br /&gt;
    router,&lt;br /&gt;
    external_gateway_info={&amp;quot;network_id&amp;quot;: external_net.id}&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.remove_interface_from_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_router(router.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_subnet(subnet.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2208</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2208"/>
		<updated>2026-04-26T15:54:43Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter &#039;&#039;&#039;twice&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Images ==&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
subnet = conn.network.create_subnet(&lt;br /&gt;
    name=&amp;quot;mySubnet&amp;quot;,&lt;br /&gt;
    network_id=network.id,&lt;br /&gt;
    ip_version=4,&lt;br /&gt;
    cidr=&amp;quot;192.168.1.0/24&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
router = conn.network.create_router(name=&amp;quot;myRouter&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.add_interface_to_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
external_net = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
conn.network.update_router(&lt;br /&gt;
    router,&lt;br /&gt;
    external_gateway_info={&amp;quot;network_id&amp;quot;: external_net.id}&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.remove_interface_from_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_router(router.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_subnet(subnet.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2207</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2207"/>
		<updated>2026-04-26T14:58:34Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter &#039;&#039;&#039;twice&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
subnet = conn.network.create_subnet(&lt;br /&gt;
    name=&amp;quot;mySubnet&amp;quot;,&lt;br /&gt;
    network_id=network.id,&lt;br /&gt;
    ip_version=4,&lt;br /&gt;
    cidr=&amp;quot;192.168.1.0/24&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
router = conn.network.create_router(name=&amp;quot;myRouter&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.add_interface_to_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
external_net = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
conn.network.update_router(&lt;br /&gt;
    router,&lt;br /&gt;
    external_gateway_info={&amp;quot;network_id&amp;quot;: external_net.id}&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.remove_interface_from_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_router(router.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_subnet(subnet.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2206</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2206"/>
		<updated>2026-04-26T14:57:12Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Authentication */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
subnet = conn.network.create_subnet(&lt;br /&gt;
    name=&amp;quot;mySubnet&amp;quot;,&lt;br /&gt;
    network_id=network.id,&lt;br /&gt;
    ip_version=4,&lt;br /&gt;
    cidr=&amp;quot;192.168.1.0/24&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
router = conn.network.create_router(name=&amp;quot;myRouter&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.add_interface_to_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
external_net = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
conn.network.update_router(&lt;br /&gt;
    router,&lt;br /&gt;
    external_gateway_info={&amp;quot;network_id&amp;quot;: external_net.id}&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.remove_interface_from_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_router(router.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_subnet(subnet.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2205</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2205"/>
		<updated>2026-04-26T14:53:29Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
subnet = conn.network.create_subnet(&lt;br /&gt;
    name=&amp;quot;mySubnet&amp;quot;,&lt;br /&gt;
    network_id=network.id,&lt;br /&gt;
    ip_version=4,&lt;br /&gt;
    cidr=&amp;quot;192.168.1.0/24&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
router = conn.network.create_router(name=&amp;quot;myRouter&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.add_interface_to_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
external_net = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
conn.network.update_router(&lt;br /&gt;
    router,&lt;br /&gt;
    external_gateway_info={&amp;quot;network_id&amp;quot;: external_net.id}&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.remove_interface_from_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_router(router.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_subnet(subnet.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2204</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2204"/>
		<updated>2026-04-26T14:53:07Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Networking */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
subnet = conn.network.create_subnet(&lt;br /&gt;
    name=&amp;quot;mySubnet&amp;quot;,&lt;br /&gt;
    network_id=network.id,&lt;br /&gt;
    ip_version=4,&lt;br /&gt;
    cidr=&amp;quot;192.168.1.0/24&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
router = conn.network.create_router(name=&amp;quot;myRouter&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.add_interface_to_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
external_net = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
conn.network.update_router(&lt;br /&gt;
    router,&lt;br /&gt;
    external_gateway_info={&amp;quot;network_id&amp;quot;: external_net.id}&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.remove_interface_from_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_router(router.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_subnet(subnet.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2203</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2203"/>
		<updated>2026-04-26T14:48:16Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Subnets, Routers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
subnet = conn.network.create_subnet(&lt;br /&gt;
    name=&amp;quot;mySubnet&amp;quot;,&lt;br /&gt;
    network_id=network.id,&lt;br /&gt;
    ip_version=4,&lt;br /&gt;
    cidr=&amp;quot;192.168.1.0/24&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
router = conn.network.create_router(name=&amp;quot;myRouter&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.add_interface_to_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
external_net = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
conn.network.update_router(&lt;br /&gt;
    router,&lt;br /&gt;
    external_gateway_info={&amp;quot;network_id&amp;quot;: external_net.id}&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.remove_interface_from_router(&lt;br /&gt;
    router,&lt;br /&gt;
    subnet_id=subnet.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_router(router.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_subnet(subnet.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2202</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2202"/>
		<updated>2026-04-26T14:47:42Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet create mySubnet \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --subnet-range 192.168.1.0/24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router create myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router add subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router set myRouter --external-gateway provider_default_net&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router remove subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router delete myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet delete mySubnet&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_CLI_%E2%80%93_Basic_Usage&amp;diff=2201</id>
		<title>Guide: OpenStack CLI – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_CLI_%E2%80%93_Basic_Usage&amp;diff=2201"/>
		<updated>2026-04-26T14:44:41Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Images */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack CLI. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack client, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstackclient &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstackclient_venv&lt;br /&gt;
source openstackclient_venv/bin/activate&lt;br /&gt;
pip install python-openstackclient&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== General Information about Cloud, Project, and User ==&lt;br /&gt;
&lt;br /&gt;
Before working with resources, you can inspect your current configuration and context:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack configuration show&lt;br /&gt;
openstack project list&lt;br /&gt;
openstack token issue&lt;br /&gt;
openstack region list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image create ubuntu-24.04 \&lt;br /&gt;
  --file=/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img \&lt;br /&gt;
  --disk-format=qcow2 \&lt;br /&gt;
  --container-format=bare&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image show &amp;amp;lt;IMAGE_ID&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image delete &amp;amp;lt;IMAGE_ID&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair create myKey &amp;gt; myKey.pem&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair delete myKey&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server create \&lt;br /&gt;
  --image ubuntu-24.04 \&lt;br /&gt;
  --flavor p1.tiny \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --key-name myKey \&lt;br /&gt;
  myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server show myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server delete myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume create --size 10 myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume delete myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add volume myVM myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove volume myVM myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network create myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network delete myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet create mySubnet \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --subnet-range 192.168.1.0/24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router create myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router add subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router set myRouter --external-gateway provider_default_net&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router remove subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router delete myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet delete mySubnet&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openstack floating ip create provider_default_net&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack floating ip list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add floating ip myVM &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove floating ip myVM &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack floating ip delete &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group create mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group rule create \&lt;br /&gt;
  --ingress \&lt;br /&gt;
  --proto tcp \&lt;br /&gt;
  --dst-port 80 \&lt;br /&gt;
  --ethertype IPv4 \&lt;br /&gt;
  mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add security group myVM mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove security group myVM mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group delete mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2200</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2200"/>
		<updated>2026-04-26T14:44:11Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Images */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2199</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2199"/>
		<updated>2026-04-26T14:41:33Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Security Groups */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_CLI_%E2%80%93_Basic_Usage&amp;diff=2198</id>
		<title>Guide: OpenStack CLI – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_CLI_%E2%80%93_Basic_Usage&amp;diff=2198"/>
		<updated>2026-04-26T14:40:18Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Security Groups */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack CLI. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack client, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstackclient &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstackclient_venv&lt;br /&gt;
source openstackclient_venv/bin/activate&lt;br /&gt;
pip install python-openstackclient&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== General Information about Cloud, Project, and User ==&lt;br /&gt;
&lt;br /&gt;
Before working with resources, you can inspect your current configuration and context:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack configuration show&lt;br /&gt;
openstack project list&lt;br /&gt;
openstack token issue&lt;br /&gt;
openstack region list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image create ubuntu-24.04 \&lt;br /&gt;
  --file=/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img \&lt;br /&gt;
  --disk-format=qcow2 \&lt;br /&gt;
  --container-format=bare&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image show &amp;amp;lt;IMAGE_ID&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image delete &amp;amp;lt;IMAGE_ID_OR_NAME&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair create myKey &amp;gt; myKey.pem&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair delete myKey&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server create \&lt;br /&gt;
  --image ubuntu-24.04 \&lt;br /&gt;
  --flavor p1.tiny \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --key-name myKey \&lt;br /&gt;
  myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server show myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server delete myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume create --size 10 myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume delete myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add volume myVM myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove volume myVM myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network create myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network delete myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet create mySubnet \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --subnet-range 192.168.1.0/24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router create myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router add subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router set myRouter --external-gateway provider_default_net&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router remove subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router delete myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet delete mySubnet&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openstack floating ip create provider_default_net&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack floating ip list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add floating ip myVM &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove floating ip myVM &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack floating ip delete &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group create mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group rule create \&lt;br /&gt;
  --ingress \&lt;br /&gt;
  --proto tcp \&lt;br /&gt;
  --dst-port 80 \&lt;br /&gt;
  --ethertype IPv4 \&lt;br /&gt;
  mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add security group myVM mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove security group myVM mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group delete mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2197</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2197"/>
		<updated>2026-04-26T14:36:52Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2196</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2196"/>
		<updated>2026-04-26T14:35:50Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Floating IPs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 conn.network.update_ip(fip, port_id=None)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2195</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2195"/>
		<updated>2026-04-26T14:30:13Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Floating IPs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
port = list(conn.network.ports(device_id=server.id))[0]&lt;br /&gt;
conn.network.update_ip(fip, port_id=port.id)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2194</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2194"/>
		<updated>2026-04-26T14:20:32Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Floating IPs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for fip in conn.network.ips():&lt;br /&gt;
    print(fip.floating_ip_address, fip.status, fip.port_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_floating_ip_to_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2193</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2193"/>
		<updated>2026-04-26T14:18:03Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Floating IPs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_floating_ip_to_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2192</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2192"/>
		<updated>2026-04-26T14:12:37Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Instances */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
if server is None:&lt;br /&gt;
    raise ValueError(&amp;quot;Server &#039;myVM&#039; not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
server = conn.compute.get_server(server.id)&lt;br /&gt;
print(server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_floating_ip_to_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2191</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2191"/>
		<updated>2026-04-26T13:59:03Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Compute */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
image_path = &amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;&lt;br /&gt;
if not os.path.isfile(image_path):&lt;br /&gt;
    raise FileNotFoundError(f&amp;quot;Image file not found: {image_path}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with open(image_path, &amp;quot;rb&amp;quot;) as img:&lt;br /&gt;
    image = conn.image.upload_image(&lt;br /&gt;
        name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
        data=img,&lt;br /&gt;
        disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
        container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Image ID:&amp;quot;, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_floating_ip_to_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2190</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2190"/>
		<updated>2026-04-26T13:45:31Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.upload_image(&lt;br /&gt;
    name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
    filename=&amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;,&lt;br /&gt;
    disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
    container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
print(image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_floating_ip_to_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2189</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2189"/>
		<updated>2026-04-26T13:43:43Z</updated>

		<summary type="html">&lt;p&gt;Sia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Note| In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.upload_image(&lt;br /&gt;
    name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
    filename=&amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;,&lt;br /&gt;
    disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
    container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
print(image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_floating_ip_to_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_CLI_%E2%80%93_Basic_Usage&amp;diff=2188</id>
		<title>Guide: OpenStack CLI – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_CLI_%E2%80%93_Basic_Usage&amp;diff=2188"/>
		<updated>2026-04-26T13:38:18Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Security Groups */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack CLI. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack client, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstackclient &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstackclient_venv&lt;br /&gt;
source openstackclient_venv/bin/activate&lt;br /&gt;
pip install python-openstackclient&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== General Information about Cloud, Project, and User ==&lt;br /&gt;
&lt;br /&gt;
Before working with resources, you can inspect your current configuration and context:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack configuration show&lt;br /&gt;
openstack project list&lt;br /&gt;
openstack token issue&lt;br /&gt;
openstack region list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image create ubuntu-24.04 \&lt;br /&gt;
  --file=/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img \&lt;br /&gt;
  --disk-format=qcow2 \&lt;br /&gt;
  --container-format=bare&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image show &amp;amp;lt;IMAGE_ID&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image delete &amp;amp;lt;IMAGE_ID_OR_NAME&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair create myKey &amp;gt; myKey.pem&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair delete myKey&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server create \&lt;br /&gt;
  --image ubuntu-24.04 \&lt;br /&gt;
  --flavor p1.tiny \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --key-name myKey \&lt;br /&gt;
  myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server show myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server delete myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume create --size 10 myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume delete myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add volume myVM myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove volume myVM myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network create myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network delete myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet create mySubnet \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --subnet-range 192.168.1.0/24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router create myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router add subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router set myRouter --external-gateway provider_default_net&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router remove subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router delete myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet delete mySubnet&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openstack floating ip create provider_default_net&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack floating ip list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add floating ip myVM &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove floating ip myVM &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack floating ip delete &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group create mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group rule create \&lt;br /&gt;
  --ingress \&lt;br /&gt;
  --proto tcp \&lt;br /&gt;
  --dst-port 80 \&lt;br /&gt;
  --ethertype IPv4 \&lt;br /&gt;
  mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add security group myVM mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove security group from instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove security group myVM mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group delete mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2187</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2187"/>
		<updated>2026-04-26T13:38:16Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Security Groups */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.upload_image(&lt;br /&gt;
    name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
    filename=&amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;,&lt;br /&gt;
    disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
    container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
print(image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_floating_ip_to_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_CLI_%E2%80%93_Basic_Usage&amp;diff=2186</id>
		<title>Guide: OpenStack CLI – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_CLI_%E2%80%93_Basic_Usage&amp;diff=2186"/>
		<updated>2026-04-26T13:33:45Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Floating IPs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack CLI. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack client, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstackclient &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstackclient_venv&lt;br /&gt;
source openstackclient_venv/bin/activate&lt;br /&gt;
pip install python-openstackclient&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== General Information about Cloud, Project, and User ==&lt;br /&gt;
&lt;br /&gt;
Before working with resources, you can inspect your current configuration and context:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack configuration show&lt;br /&gt;
openstack project list&lt;br /&gt;
openstack token issue&lt;br /&gt;
openstack region list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image create ubuntu-24.04 \&lt;br /&gt;
  --file=/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img \&lt;br /&gt;
  --disk-format=qcow2 \&lt;br /&gt;
  --container-format=bare&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image show &amp;amp;lt;IMAGE_ID&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack image delete &amp;amp;lt;IMAGE_ID_OR_NAME&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair create myKey &amp;gt; myKey.pem&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack keypair delete myKey&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server create \&lt;br /&gt;
  --image ubuntu-24.04 \&lt;br /&gt;
  --flavor p1.tiny \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --key-name myKey \&lt;br /&gt;
  myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show details of an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server show myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server delete myVM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume create --size 10 myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack volume delete myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add volume myVM myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove volume myVM myVolume&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network create myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network (after detaching all ports from its subnets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack network delete myNet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subnets, Routers ===&lt;br /&gt;
Create a subnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet create mySubnet \&lt;br /&gt;
  --network myNet \&lt;br /&gt;
  --subnet-range 192.168.1.0/24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router create myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Attach a subnet to a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router add subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set external gateway of a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router set myRouter --external-gateway provider_default_net&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a subnet from a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router remove subnet myRouter mySubnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a router:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack router delete myRouter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a subnet (after detaching all ports from the subnet):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack subnet delete mySubnet&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP (requires access to the provider network):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openstack floating ip create provider_default_net&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List floating IPs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack floating ip list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add floating ip myVM &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove floating ip myVM &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack floating ip delete &amp;amp;lt;FLOATING_IP&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group create mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule to a security group (e.g., HTTP access via port 80):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group rule create \&lt;br /&gt;
  --proto tcp \&lt;br /&gt;
  --dst-port 80 \&lt;br /&gt;
  --ingress \&lt;br /&gt;
  mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server add security group myVM mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove security group from instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack server remove security group myVM mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
openstack security group delete mySecGroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2185</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2185"/>
		<updated>2026-04-26T13:33:21Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Floating IPs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.upload_image(&lt;br /&gt;
    name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
    filename=&amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;,&lt;br /&gt;
    disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
    container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
print(image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_floating_ip_to_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Release (delete) a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2184</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2184"/>
		<updated>2026-04-26T13:32:50Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Volume Management for Instances */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.upload_image(&lt;br /&gt;
    name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
    filename=&amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;,&lt;br /&gt;
    disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
    container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
print(image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_floating_ip_to_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
	<entry>
		<id>https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2183</id>
		<title>Guide: OpenStack Python SDK – Basic Usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.bwcloud-os.de/index.php?title=Guide:_OpenStack_Python_SDK_%E2%80%93_Basic_Usage&amp;diff=2183"/>
		<updated>2026-04-26T13:31:11Z</updated>

		<summary type="html">&lt;p&gt;Sia: /* Security Groups */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.&lt;br /&gt;
&lt;br /&gt;
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
Install the OpenStack SDK, e.g. for Ubuntu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install python3-openstacksdk &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can install it via &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; (preferably inside a virtual environment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python3 -m venv openstacksdk_venv&lt;br /&gt;
source openstacksdk_venv/bin/activate&lt;br /&gt;
pip install openstacksdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
You can either:&lt;br /&gt;
&lt;br /&gt;
* source an OpenRC file, or&lt;br /&gt;
* use a &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; file&lt;br /&gt;
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]].&lt;br /&gt;
&lt;br /&gt;
In the following, we use the  &amp;lt;code&amp;gt;clouds.yaml&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
== Basic Connection ==&lt;br /&gt;
Create a connection in Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import openstack&lt;br /&gt;
conn = openstack.connect(cloud=&amp;quot;openstack&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compute ==&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
List available images:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for image in conn.image.images():&lt;br /&gt;
    print(image.name, image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload a new image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.upload_image(&lt;br /&gt;
    name=&amp;quot;ubuntu-24.04&amp;quot;,&lt;br /&gt;
    filename=&amp;quot;/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img&amp;quot;,&lt;br /&gt;
    disk_format=&amp;quot;qcow2&amp;quot;,&lt;br /&gt;
    container_format=&amp;quot;bare&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
print(image.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show image details:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.image.get_image(&amp;quot;&amp;lt;IMAGE_ID&amp;gt;&amp;quot;)&lt;br /&gt;
print(image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.image.delete_image(&amp;quot;&amp;lt;IMAGE_ID_OR_NAME&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Key Pairs (SSH Access) ===&lt;br /&gt;
Create a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
keypair = conn.compute.create_keypair(name=&amp;quot;myKey&amp;quot;)&lt;br /&gt;
with open(&amp;quot;myKey.pem&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(keypair.private_key)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set correct permissions (outside Python shell):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chmod 600 myKey.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List key pairs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for kp in conn.compute.keypairs():&lt;br /&gt;
    print(kp.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a key pair:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.delete_keypair(&amp;quot;myKey&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instances ===&lt;br /&gt;
List instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for server in conn.compute.servers():&lt;br /&gt;
    print(server.name, server.status)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an instance (ensure that the specified image, flavor, network, and key pair exist):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = conn.compute.find_image(&amp;quot;ubuntu-24.04&amp;quot;)&lt;br /&gt;
flavor = conn.compute.find_flavor(&amp;quot;p1.tiny&amp;quot;)&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
server = conn.compute.create_server(&lt;br /&gt;
    name=&amp;quot;myVM&amp;quot;,&lt;br /&gt;
    image_id=image.id,&lt;br /&gt;
    flavor_id=flavor.id,&lt;br /&gt;
    networks=[{&amp;quot;uuid&amp;quot;: network.id}],&lt;br /&gt;
    key_name=&amp;quot;myKey&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
server = conn.compute.wait_for_server(server)&lt;br /&gt;
print(&amp;quot;Created:&amp;quot;, server.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.delete_server(server.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage ==&lt;br /&gt;
&lt;br /&gt;
=== Volumes ===&lt;br /&gt;
&lt;br /&gt;
List volumes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for vol in conn.block_storage.volumes():&lt;br /&gt;
    print(vol.name, vol.size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a volume (size in GB):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.create_volume(&lt;br /&gt;
    name=&amp;quot;myVolume&amp;quot;,&lt;br /&gt;
    size=10&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.block_storage.delete_volume(volume.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Volume Management for Instances ===&lt;br /&gt;
&lt;br /&gt;
Attach a volume to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
volume = conn.block_storage.find_volume(&amp;quot;myVolume&amp;quot;)&lt;br /&gt;
conn.compute.create_volume_attachment(&lt;br /&gt;
    server,&lt;br /&gt;
    volumeId=volume.id&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detach a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attachments = conn.compute.volume_attachments(server)&lt;br /&gt;
for att in attachments:&lt;br /&gt;
    if att.volume_id == volume.id:&lt;br /&gt;
        conn.compute.delete_volume_attachment(att.id, server)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
&lt;br /&gt;
=== Networks ===&lt;br /&gt;
List networks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for net in conn.network.networks():&lt;br /&gt;
    print(net.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.create_network(name=&amp;quot;myNet&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a network:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;myNet&amp;quot;)&lt;br /&gt;
conn.network.delete_network(network.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating IPs ===&lt;br /&gt;
&lt;br /&gt;
Create a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network = conn.network.find_network(&amp;quot;provider_default_net&amp;quot;)&lt;br /&gt;
fip = conn.network.create_ip(floating_network_id=network.id)&lt;br /&gt;
print(fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Associate a floating IP with an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_floating_ip_to_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disassociate a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_floating_ip_from_server(server, fip.floating_ip_address)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a floating IP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_ip(fip.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Security Groups ===&lt;br /&gt;
&lt;br /&gt;
List security groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sg in conn.network.security_groups():&lt;br /&gt;
    print(sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sg = conn.network.create_security_group(name=&amp;quot;mySecGroup&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a rule (HTTP):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.create_security_group_rule(&lt;br /&gt;
    security_group_id=sg.id,&lt;br /&gt;
    protocol=&amp;quot;tcp&amp;quot;,&lt;br /&gt;
    port_range_min=80,&lt;br /&gt;
    port_range_max=80,&lt;br /&gt;
    direction=&amp;quot;ingress&amp;quot;,&lt;br /&gt;
    ethertype=&amp;quot;IPv4&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assign security group to an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server = conn.compute.find_server(&amp;quot;myVM&amp;quot;)&lt;br /&gt;
conn.compute.add_security_group_to_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove a security group from an instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.compute.remove_security_group_from_server(server, sg.name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete a security group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
conn.network.delete_security_group(sg.id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sia</name></author>
	</entry>
</feed>