diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e5be3de39f..8f74364d04 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,18 @@ Change Log All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `_. +==================== +2.80.1 - 2022-08-30 +==================== + +Added +----- +* Support for opting out of guest VM event collection, health metrics, diagnostics logs, and traces in the Database service +* Support for in-place upgrades for software-defined data centers in the VMWare Solution service +* Support for single-client access name protocol as a data source for private access channels in the Analytics Cloud service +* Support for network security groups, egress control on public datasources, and GitHub access in the Analytics Cloud service +* Support for performance-based autotuning of block and boot volumes in the Block Storage service + ==================== 2.80.0 - 2022-08-23 ==================== diff --git a/docs/api/analytics.rst b/docs/api/analytics.rst index 153535fb9e..797a5cc671 100644 --- a/docs/api/analytics.rst +++ b/docs/api/analytics.rst @@ -30,6 +30,7 @@ Analytics oci.analytics.models.PrivateAccessChannel oci.analytics.models.PrivateEndpointDetails oci.analytics.models.PrivateSourceDnsZone + oci.analytics.models.PrivateSourceScanHost oci.analytics.models.PublicEndpointDetails oci.analytics.models.ScaleAnalyticsInstanceDetails oci.analytics.models.SetKmsKeyDetails diff --git a/docs/api/analytics/models/oci.analytics.models.PrivateSourceScanHost.rst b/docs/api/analytics/models/oci.analytics.models.PrivateSourceScanHost.rst new file mode 100644 index 0000000000..4885ff75f4 --- /dev/null +++ b/docs/api/analytics/models/oci.analytics.models.PrivateSourceScanHost.rst @@ -0,0 +1,11 @@ +PrivateSourceScanHost +===================== + +.. currentmodule:: oci.analytics.models + +.. autoclass:: PrivateSourceScanHost + :show-inheritance: + :special-members: __init__ + :members: + :undoc-members: + :inherited-members: \ No newline at end of file diff --git a/docs/api/core.rst b/docs/api/core.rst index 0b0a148d03..807d1ecdca 100644 --- a/docs/api/core.rst +++ b/docs/api/core.rst @@ -63,6 +63,7 @@ Core Services oci.core.models.AttachServiceDeterminedVolumeDetails oci.core.models.AttachVnicDetails oci.core.models.AttachVolumeDetails + oci.core.models.AutotunePolicy oci.core.models.BgpSessionInfo oci.core.models.BlockVolumeReplica oci.core.models.BlockVolumeReplicaDetails @@ -229,6 +230,7 @@ Core Services oci.core.models.DeleteVirtualCircuitPublicPrefixDetails oci.core.models.DetachInstancePoolInstanceDetails oci.core.models.DetachLoadBalancerDetails + oci.core.models.DetachedVolumeAutotunePolicy oci.core.models.Device oci.core.models.DhcpDnsOption oci.core.models.DhcpOption @@ -292,10 +294,12 @@ Core Services oci.core.models.InstanceConfigurationAmdVmLaunchInstancePlatformConfig oci.core.models.InstanceConfigurationAttachVnicDetails oci.core.models.InstanceConfigurationAttachVolumeDetails + oci.core.models.InstanceConfigurationAutotunePolicy oci.core.models.InstanceConfigurationAvailabilityConfig oci.core.models.InstanceConfigurationBlockVolumeDetails oci.core.models.InstanceConfigurationCreateVnicDetails oci.core.models.InstanceConfigurationCreateVolumeDetails + oci.core.models.InstanceConfigurationDetachedVolumeAutotunePolicy oci.core.models.InstanceConfigurationInstanceDetails oci.core.models.InstanceConfigurationInstanceOptions oci.core.models.InstanceConfigurationInstanceSourceDetails @@ -311,6 +315,7 @@ Core Services oci.core.models.InstanceConfigurationLaunchInstanceShapeConfigDetails oci.core.models.InstanceConfigurationLaunchOptions oci.core.models.InstanceConfigurationParavirtualizedAttachVolumeDetails + oci.core.models.InstanceConfigurationPerformanceBasedAutotunePolicy oci.core.models.InstanceConfigurationSummary oci.core.models.InstanceConfigurationVolumeSourceDetails oci.core.models.InstanceConfigurationVolumeSourceFromVolumeBackupDetails @@ -367,6 +372,7 @@ Core Services oci.core.models.ParavirtualizedVolumeAttachment oci.core.models.PeerRegionForRemotePeering oci.core.models.PercentageOfCoresEnabledOptions + oci.core.models.PerformanceBasedAutotunePolicy oci.core.models.PhaseOneConfigDetails oci.core.models.PhaseTwoConfigDetails oci.core.models.PlatformConfig diff --git a/docs/api/core/models/oci.core.models.AutotunePolicy.rst b/docs/api/core/models/oci.core.models.AutotunePolicy.rst new file mode 100644 index 0000000000..a89a9312ce --- /dev/null +++ b/docs/api/core/models/oci.core.models.AutotunePolicy.rst @@ -0,0 +1,11 @@ +AutotunePolicy +============== + +.. currentmodule:: oci.core.models + +.. autoclass:: AutotunePolicy + :show-inheritance: + :special-members: __init__ + :members: + :undoc-members: + :inherited-members: \ No newline at end of file diff --git a/docs/api/core/models/oci.core.models.DetachedVolumeAutotunePolicy.rst b/docs/api/core/models/oci.core.models.DetachedVolumeAutotunePolicy.rst new file mode 100644 index 0000000000..88d0abd14b --- /dev/null +++ b/docs/api/core/models/oci.core.models.DetachedVolumeAutotunePolicy.rst @@ -0,0 +1,11 @@ +DetachedVolumeAutotunePolicy +============================ + +.. currentmodule:: oci.core.models + +.. autoclass:: DetachedVolumeAutotunePolicy + :show-inheritance: + :special-members: __init__ + :members: + :undoc-members: + :inherited-members: \ No newline at end of file diff --git a/docs/api/core/models/oci.core.models.InstanceConfigurationAutotunePolicy.rst b/docs/api/core/models/oci.core.models.InstanceConfigurationAutotunePolicy.rst new file mode 100644 index 0000000000..8c2359ffe6 --- /dev/null +++ b/docs/api/core/models/oci.core.models.InstanceConfigurationAutotunePolicy.rst @@ -0,0 +1,11 @@ +InstanceConfigurationAutotunePolicy +=================================== + +.. currentmodule:: oci.core.models + +.. autoclass:: InstanceConfigurationAutotunePolicy + :show-inheritance: + :special-members: __init__ + :members: + :undoc-members: + :inherited-members: \ No newline at end of file diff --git a/docs/api/core/models/oci.core.models.InstanceConfigurationDetachedVolumeAutotunePolicy.rst b/docs/api/core/models/oci.core.models.InstanceConfigurationDetachedVolumeAutotunePolicy.rst new file mode 100644 index 0000000000..e0c2a52f23 --- /dev/null +++ b/docs/api/core/models/oci.core.models.InstanceConfigurationDetachedVolumeAutotunePolicy.rst @@ -0,0 +1,11 @@ +InstanceConfigurationDetachedVolumeAutotunePolicy +================================================= + +.. currentmodule:: oci.core.models + +.. autoclass:: InstanceConfigurationDetachedVolumeAutotunePolicy + :show-inheritance: + :special-members: __init__ + :members: + :undoc-members: + :inherited-members: \ No newline at end of file diff --git a/docs/api/core/models/oci.core.models.InstanceConfigurationPerformanceBasedAutotunePolicy.rst b/docs/api/core/models/oci.core.models.InstanceConfigurationPerformanceBasedAutotunePolicy.rst new file mode 100644 index 0000000000..721202f4ed --- /dev/null +++ b/docs/api/core/models/oci.core.models.InstanceConfigurationPerformanceBasedAutotunePolicy.rst @@ -0,0 +1,11 @@ +InstanceConfigurationPerformanceBasedAutotunePolicy +=================================================== + +.. currentmodule:: oci.core.models + +.. autoclass:: InstanceConfigurationPerformanceBasedAutotunePolicy + :show-inheritance: + :special-members: __init__ + :members: + :undoc-members: + :inherited-members: \ No newline at end of file diff --git a/docs/api/core/models/oci.core.models.PerformanceBasedAutotunePolicy.rst b/docs/api/core/models/oci.core.models.PerformanceBasedAutotunePolicy.rst new file mode 100644 index 0000000000..975d59c771 --- /dev/null +++ b/docs/api/core/models/oci.core.models.PerformanceBasedAutotunePolicy.rst @@ -0,0 +1,11 @@ +PerformanceBasedAutotunePolicy +============================== + +.. currentmodule:: oci.core.models + +.. autoclass:: PerformanceBasedAutotunePolicy + :show-inheritance: + :special-members: __init__ + :members: + :undoc-members: + :inherited-members: \ No newline at end of file diff --git a/docs/api/ocvp.rst b/docs/api/ocvp.rst index 255c2cb056..f37a7ef0e8 100644 --- a/docs/api/ocvp.rst +++ b/docs/api/ocvp.rst @@ -41,6 +41,8 @@ Ocvp oci.ocvp.models.SupportedVmwareSoftwareVersionSummary oci.ocvp.models.UpdateEsxiHostDetails oci.ocvp.models.UpdateSddcDetails + oci.ocvp.models.VsphereLicense + oci.ocvp.models.VsphereUpgradeObject oci.ocvp.models.WorkRequest oci.ocvp.models.WorkRequestCollection oci.ocvp.models.WorkRequestError diff --git a/docs/api/ocvp/models/oci.ocvp.models.VsphereLicense.rst b/docs/api/ocvp/models/oci.ocvp.models.VsphereLicense.rst new file mode 100644 index 0000000000..9a8926aeb8 --- /dev/null +++ b/docs/api/ocvp/models/oci.ocvp.models.VsphereLicense.rst @@ -0,0 +1,11 @@ +VsphereLicense +============== + +.. currentmodule:: oci.ocvp.models + +.. autoclass:: VsphereLicense + :show-inheritance: + :special-members: __init__ + :members: + :undoc-members: + :inherited-members: \ No newline at end of file diff --git a/docs/api/ocvp/models/oci.ocvp.models.VsphereUpgradeObject.rst b/docs/api/ocvp/models/oci.ocvp.models.VsphereUpgradeObject.rst new file mode 100644 index 0000000000..ba81ab6a4f --- /dev/null +++ b/docs/api/ocvp/models/oci.ocvp.models.VsphereUpgradeObject.rst @@ -0,0 +1,11 @@ +VsphereUpgradeObject +==================== + +.. currentmodule:: oci.ocvp.models + +.. autoclass:: VsphereUpgradeObject + :show-inheritance: + :special-members: __init__ + :members: + :undoc-members: + :inherited-members: \ No newline at end of file diff --git a/examples/database_tools/adbs_create_connection_public_ip.py b/examples/database_tools/adbs_create_connection_public_ip.py index fd6b5460af..602bb05b86 100644 --- a/examples/database_tools/adbs_create_connection_public_ip.py +++ b/examples/database_tools/adbs_create_connection_public_ip.py @@ -2,322 +2,348 @@ # Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. # This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. - -# Creates a connection to an Autonomous Databases with Shared Exadata Infrastructure. With a Public IP. -# - Requires Database Tools Private Endpoint Reverse Connection: No -# - Requires a KeyStore: Yes, for mTLS +# ----------------------------------------------------------------------------- +# Example Use Case: Existing ADB-S with Public IP (no ACL) +# ----------------------------------------------------------------------------- +# This example creates a Database Tools connection to an Autonomous Database +# on shared Exadata infrastructure (ADB-S), accessible by public ip. Note, since +# this connection will be against a public ip address, a Database Tools private +# endpoint is not required, however, mTLS is required. +# +# Prerequisites: # -# 1- Create a new Autonomous Database -# 2- Create required secrets -# 3- Create a connection -# 4- Validate the connection +# - A compartment where Autonomous Database, vault, and connection will reside +# - An existing vault for storage of secrets, with at least one master key +# - A previously configured .oci/config file with a [DEFAULT] section +# - Set the following variables in the code below: +# + compartment_id : The compartment to use with the example +# + vault_id : The ocid for a vault (to store secrets) +# + db_password : The database password for the ADMIN user # -# If variable do_clean_up_at_end is set to True, connection, secrets and DB are removed upon completion. +# High-level Steps: # -# Prerequisites are: -# - A compartment_id where the vcn, autonomous database, vault and connection will reside. -# - vault_id: a Vault created in KMS with at least one master key. +# 1- Create a new Autonomous Database (ADB-S) +# 2- Create required secrets +# 3- Create a connection +# 4- Validate the connection +# ----------------------------------------------------------------------------- import oci from oci.config import from_file, validate_config -from utils.dbtools import get_dbtools_clients, get_database_clients, get_secrets_client, \ - get_kms_vault_client, get_vaults_clients, get_wallet_and_create_secrets, delete_secret +from utils.dbtools import get_dbtools_clients, get_database_clients, get_secrets_client, get_kms_vault_client +from utils.dbtools import get_vaults_clients, get_wallet_and_create_secrets, delete_secret -from datetime import datetime, timedelta import pkg_resources +from datetime import datetime, timedelta -# Specify Compartment to use for tests -compartment_id = "ocid1.compartment.oc1.changeme" -# Specify Vault id to use in the test. Must be in compartment_id and contain a master Key -vault_id = "ocid1.vault.oc1.phx.changeme" - -utc_now = datetime.utcnow() -dbname = "DB" + utc_now.strftime("%m%d%H%M") -db_password = "example-password" - -db_password_secret_name = "db" + "this-is-not-the-secret" + dbname -db_wallet_secret_name = "wallet" + "this-is-not-the-secret" + dbname - -# Display OCI Python SDK version -print("oci version:", pkg_resources.get_distribution("oci").version) - -# Set do_clean_up_at_end to false to keep the autonomous database, secrets and connection created +# Set do_clean_up_at_end = False to keep the secrets and connection created do_clean_up_at_end = True -# Variables that will be modified during the processing -autonomous_database_id = None -wallet_secret_id = None -password_secret_id = None -connection_id = None +# Specify compartment ocid to use. (can also use tenancy ocid if applicable) +compartment_id = "ocid1.tenancy......changeme" -# Load OCI Config -oci_config = from_file(file_location="~/.oci/config", profile_name="DEFAULT") +# Specify vault ocid to use. (For this example, vault must be in compartment_id and contain a master key) +vault_id = "ocid1.vault.....changeme" -# Validate OCI Config -validate_config(oci_config) - -# Prepare all clients that we will need -db_client, db_async_client = get_database_clients(oci_config) -vaults_client, vaults_async_client = get_vaults_clients(oci_config) -kms_vault_client = get_kms_vault_client(oci_config) -secrets_client = get_secrets_client(oci_config) -dbtools_client, dbtools_async_client = get_dbtools_clients(oci_config) +# Specify the password for the ADB-S database ADMIN user +db_password = "example-password" -# Prepare a dict that contains all the required clients -clients = {"db_client": db_client, "db_async_client": db_async_client, - "vaults_client": vaults_client, "vaults_async_client": vaults_async_client, - "kms_vault_client": kms_vault_client, - "secrets_client": secrets_client, - "dbtools_client": dbtools_client, "dbtools_async_client": dbtools_async_client} +print("Using oci version:", pkg_resources.get_distribution("oci").version) -def create_db(compartment_id, database_name, database_password, db_workload="OLTP"): - """ - Create an Autonomous Databases with Shared Exadata Infrastructure. With a Public IP. +class DBToolsExample: """ - global autonomous_database_id - - # If an autonomous db with same name already exists, return the OCID of the existing db - list_db_response = clients["db_client"].list_autonomous_databases( - compartment_id=compartment_id, - display_name=database_name - ) - assert list_db_response, "List db should return a response" - if list_db_response.data: - print(f"DB with name {database_name} already exists. Using: {list_db_response.data[0].id}") - autonomous_database_id = list_db_response.data[0].id - return - - # Provision a new Database - db_details = oci.database.models.CreateAutonomousDatabaseDetails( - admin_password=database_password, - compartment_id=compartment_id, - db_name=database_name, - display_name=database_name, - db_workload=db_workload, - whitelisted_ips=["0.0.0.0/0"], - cpu_core_count=1, - data_storage_size_in_tbs=1 - ) - - print(f"Creating Database with name {database_name}...") - create_db_response = clients["db_async_client"].create_autonomous_database_and_wait_for_state( - create_autonomous_database_details=db_details, - wait_for_states=["FAILED", "AVAILABLE", "CANCELED"] - ) - - assert create_db_response, "create_autonomous_database_and_wait_for_state should return a response" - assert create_db_response.data, "DB Response should contain data" - - # Get the OCID for the new Database - autonomous_database_id = create_db_response.data.id - print(f"Created Database with name {database_name} and OCID {autonomous_database_id}") - - -def do_connection_tests(): + A Database Tools example that demonstrates usage of the OCI Python SDK. """ - Do tests related to DBTools Connections - - Create Connection - - Get created connection - - Update Connection - - Validate Connection. This makes sure that we can use this connection to connect to the DB. - """ - global connection_id, wallet_secret_id, password_secret_id - print("===DBTools Service - Connections") - - # 1.get DB - autonomous_database_response = clients["db_client"].get_autonomous_database(autonomous_database_id) - assert autonomous_database_response, "No autonomous database found" - assert autonomous_database_response.data, "get_autonomous_database should return data" - autonomous_database = autonomous_database_response.data - - # 2. Prepare Wallet and secrets - wallet_secret_id, password_secret_id = get_wallet_and_create_secrets(oci_config=oci_config, - compartment_id=compartment_id, - clients=clients, - autonomous_database_id=autonomous_database_id, - vault_id=vault_id, - db_wallet_secret_name=db_wallet_secret_name, - db_password_secret_name=db_password_secret_name, - db_password=db_password) - - # 3. get Connection string with mTLS from DB - assert autonomous_database.connection_strings - assert autonomous_database.connection_strings.profiles - profiles = autonomous_database.connection_strings.profiles - - m_tls = oci.database.models.DatabaseConnectionStringProfile.TLS_AUTHENTICATION_MUTUAL - low = oci.database.models.DatabaseConnectionStringProfile.CONSUMER_GROUP_LOW - connection_string = next((p.value for p in profiles if - p.tls_authentication == m_tls and p.consumer_group == low), None) - - print(f"Using connection_string {connection_string}") - - # 4. create SSO keyStore using wallet_secret_id - key_store = oci.database_tools.models.DatabaseToolsKeyStoreDetails( - key_store_type=oci.database_tools.models.DatabaseToolsKeyStoreDetails.KEY_STORE_TYPE_SSO, - key_store_content=oci.database_tools.models.DatabaseToolsKeyStoreContentSecretIdDetails( - value_type=oci.database_tools.models.DatabaseToolsKeyStoreContentSecretIdDetails.VALUE_TYPE_SECRETID, - secret_id=wallet_secret_id) - ) - - # - # 5. Create connection using: - # - DB Compartment - # - Connection String - # - dbUser - # - dbPasswordSecretId - # - Time generated display name - # - Related Resource - # - keyStore - # - print("===Connection - Create") - user_name = "admin" - user_password = oci.database_tools.models.DatabaseToolsUserPasswordSecretIdDetails( - secret_id=password_secret_id) - - display_name = "conn_pysdk_" + utc_now.strftime("%Y-%m-%d_%H-%M-%S") - related_resource = oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails( - entity_type=oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails.ENTITY_TYPE_AUTONOMOUSDATABASE, - identifier=autonomous_database_id) - - conn_details_for_create = oci.database_tools.models.CreateDatabaseToolsConnectionOracleDatabaseDetails( - compartment_id=compartment_id, - connection_string=connection_string, - user_name=user_name, - user_password=user_password, - display_name=display_name, - related_resource=related_resource, - key_stores=[key_store] - ) - create_conn_response = clients["dbtools_async_client"].create_database_tools_connection_and_wait_for_state( - conn_details_for_create, wait_for_states=["FAILED", "SUCCEEDED", "CANCELED"]) - - assert create_conn_response, "create_database_tools_connection_and_wait_for_state should return a response" - assert create_conn_response.data, "Create db Response should contain data" - - status = create_conn_response.data.status - connection_id = create_conn_response.data.resources[0].identifier - print(f"Creating Connection. Status: {status}, name: {display_name}, connection id: {connection_id}.") - assert status == "SUCCEEDED", "Create Connection should succeed" - - # - # 6. Get connection that we just created BY Id - # - print("===Connection - Get by id:", connection_id) - connection = clients["dbtools_client"].get_database_tools_connection(connection_id) - print("Read created Connection:", connection.data) - assert connection.data is not None, "Created Connection data should exist" - assert connection.data.display_name == display_name, "Unexpected Connection display name" - assert connection.data.lifecycle_state == "ACTIVE", "Connection should be ACTIVE" - - # - # 7. Update connection that we just created BY Id - # - # Changing only the display name. - print("===Connection - Update by id:", connection_id) - connection_details_for_update = oci.database_tools.models.UpdateDatabaseToolsConnectionOracleDatabaseDetails( - display_name=display_name + "_updated") - result = clients["dbtools_async_client"].update_database_tools_connection_and_wait_for_state(connection_id, + def __init__(self, compartment, vault, password): + + # Load an OCI config with the DEFAULT profile + self.oci_config = from_file(file_location="~/.oci/config", profile_name="DEFAULT") + + self.compartment_id = compartment + self.vault_id = vault + self.db_password = password + + self.db_name = "DB" + datetime.utcnow().strftime("%m%d%H%M") + + validate_config(self.oci_config) + + # Prepare SDK clients used in this example + self.dbtools_client, self.dbtools_async_client = get_dbtools_clients(self.oci_config) + self.db_client, self.db_async_client = get_database_clients(self.oci_config) + self.vaults_client, self.vaults_async_client = get_vaults_clients(self.oci_config) + self.kms_vault_client = get_kms_vault_client(self.oci_config) + self.secrets_client = get_secrets_client(self.oci_config) + + # Dict that contains all the clients (used by utils.dbtools helpers) + self.clients = {"dbtools_client": self.dbtools_client, "dbtools_async_client": self.dbtools_async_client, + "db_client": self.db_client, "db_async_client": self.db_async_client, + "vaults_client": self.vaults_client, "vaults_async_client": self.vaults_async_client, + "kms_vault_client": self.kms_vault_client, + "secrets_client": self.secrets_client} + + self.autonomous_database_id = None # populated at runtime + self.wallet_secret_id = None # populated at runtime + self.password_secret_id = None # populated at runtime + self.connection_id = None # populated at runtime + self.connection_string = None # populated at runtime + + # When waiting for asynchronous calls, which status is considered "done" + self.terminal_states = ["FAILED", "SUCCEEDED", "CANCELED", "AVAILABLE"] + + def create_db(self, db_workload="OLTP"): + """ + Create an Autonomous Database with shared Exadata infrastructure and a public ip. + """ + print("=== DBTools Example - Create Autonomous Database Named:", self.db_name) + + response = self.db_client.list_autonomous_databases( + compartment_id=self.compartment_id, + display_name=self.db_name) + + assert response, "list_autonomous_databases should return a response" + + # If a database with same name already exists, abort the example to avoid + # accidentally deleting an existing Autonomous Database + assert len(response.data) == 0, f"a database with the name {self.db_name} should not already exist" + + db_details = oci.database.models.CreateAutonomousDatabaseDetails( + admin_password=self.db_password, + compartment_id=self.compartment_id, + db_name=self.db_name, + display_name=self.db_name, + db_workload=db_workload, + whitelisted_ips=["0.0.0.0/0"], + cpu_core_count=1, + data_storage_size_in_tbs=1) + + create_db_response = self.db_async_client.create_autonomous_database_and_wait_for_state( + create_autonomous_database_details=db_details, + wait_for_states=self.terminal_states) + + assert create_db_response, "create_autonomous_database_and_wait_for_state should return a response" + assert create_db_response.data.id, "create_db_response data should contain an id" + + self.autonomous_database_id = create_db_response.data.id + print(f"Created database. Name: {self.db_name}, ocid: {self.autonomous_database_id}") + + def save_secrets_to_vault(self): + """ + Database Tools connections don't store secrets directly. Instead, they hold a pointer to + secrets stored securely in a vault. + """ + print("=== DBTools Example - Save Secrets to Vault") + + db_wallet_secret_name = "dbtools-temp-secretw-" + datetime.utcnow().strftime("%m%d%H%M") + db_password_secret_name = "dbtools-temp-secretp-" + datetime.utcnow().strftime("%m%d%H%M") + + # The wallet zip file generated by the Autonomous Database contains the cwallet.sso file + # needed to establish an mTLS connection. Extract this and store it as a base64 encoded + # secret in the vault, along with a new secret for the database password. + + response = self.db_client.get_autonomous_database(self.autonomous_database_id) + assert response, "get_autonomous_database should return a response" + assert response.data, "response should contain data" + autonomous_database = response.data + + self.wallet_secret_id, self.password_secret_id = get_wallet_and_create_secrets(oci_config=self.oci_config, + compartment_id=self.compartment_id, + clients=self.clients, + autonomous_database_id=self.autonomous_database_id, + vault_id=self.vault_id, + db_wallet_secret_name=db_wallet_secret_name, + db_password_secret_name=db_password_secret_name, + db_password=self.db_password) + + # Get the connection string with mTLS from the database + assert autonomous_database.connection_strings, "autonomous_database should have connection strings" + assert autonomous_database.connection_strings.profiles, "connection_strings should have profiles" + + profiles = autonomous_database.connection_strings.profiles + m_tls = oci.database.models.DatabaseConnectionStringProfile.TLS_AUTHENTICATION_MUTUAL + low = oci.database.models.DatabaseConnectionStringProfile.CONSUMER_GROUP_LOW + self.connection_string = next((p.value for p in profiles if + p.tls_authentication == m_tls and p.consumer_group == low), None) + + print(f"Created secret. Name: {db_wallet_secret_name}, ocid: {self.wallet_secret_id}") + print(f"Created secret. Name: {db_password_secret_name}, ocid: {self.password_secret_id}") + + def create_connection(self): + """ + Given the configuration details provided above and the secrets stored in the vault, + create a Database Tools connection to the Autonomous Database. + """ + print("=== DBTools Example - Create Connection Using:", self.connection_string) + + # Setup SSO key store using wallet_secret_id (required for mTLS) + key_store = oci.database_tools.models.DatabaseToolsKeyStoreDetails( + key_store_type=oci.database_tools.models.DatabaseToolsKeyStoreDetails.KEY_STORE_TYPE_SSO, + key_store_content=oci.database_tools.models.DatabaseToolsKeyStoreContentSecretIdDetails( + value_type=oci.database_tools.models.DatabaseToolsKeyStoreContentSecretIdDetails.VALUE_TYPE_SECRETID, + secret_id=self.wallet_secret_id)) + + # ADMIN is automatically created when deploying a new Autonomous Database + user_name = "admin" + user_password = oci.database_tools.models.DatabaseToolsUserPasswordSecretIdDetails( + secret_id=self.password_secret_id) + + display_name = "conn_pysdk_" + datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S") + related_resource = oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails( + entity_type=oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails.ENTITY_TYPE_AUTONOMOUSDATABASE, + identifier=self.autonomous_database_id) + + conn_details_for_create = oci.database_tools.models.CreateDatabaseToolsConnectionOracleDatabaseDetails( + compartment_id=self.compartment_id, + connection_string=self.connection_string, + user_name=user_name, + user_password=user_password, + display_name=display_name, + related_resource=related_resource, + key_stores=[key_store]) + + response = self.dbtools_async_client.create_database_tools_connection_and_wait_for_state( + conn_details_for_create, wait_for_states=self.terminal_states) + + assert response, "create_database_tools_connection_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.resources, "response data should return resources" + + status = response.data.status + assert status == "SUCCEEDED", f"create connection should return status SUCCEEDED but was {status}" + + self.connection_id = response.data.resources[0].identifier + print(f"Created connection. Name: {display_name}, ocid: {self.connection_id}.") + + def get_connection(self): + """ + Given an existing Database Tools connection, this method shows how to get the connection by id. + """ + print("=== DBTools Connection - Get by id:", self.connection_id) + + response = self.dbtools_client.get_database_tools_connection(self.connection_id) + assert response.data, "response should contain data" + assert response.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE but was {response.data.lifecycle_state}" + + print("Read created connection:", response.data) + + def update_connection(self): + """ + Given an existing Database Tools connection, this method shows how to update the connection by id. + """ + print("=== DBTools Connection - Update by id:", self.connection_id) + + connection = self.dbtools_client.get_database_tools_connection(self.connection_id) + display_name = connection.data.display_name + + connection_details_for_update = oci.database_tools.models.UpdateDatabaseToolsConnectionOracleDatabaseDetails( + display_name=display_name + "_updated") + + response = self.dbtools_async_client.update_database_tools_connection_and_wait_for_state(self.connection_id, connection_details_for_update, - wait_for_states=[ - "FAILED", - "SUCCEEDED", - "CANCELED"]) - status = result.data.status - print( - f"Updating Connection. Status: {status}, name: {display_name}, connection id: {connection_id}.") - assert status == "SUCCEEDED", "Update Connection should succeed" - - # - # 8. Get connection that we just updated BY Id - # - print("===Connection - after update - Get by id:", connection_id) - connection = clients["dbtools_client"].get_database_tools_connection(connection_id) - assert connection.data is not None, "Updated Connection data should exist" - assert connection.data.display_name != display_name, "Unexpected Connection display name after update" - assert connection.data.lifecycle_state == "ACTIVE", "Connection should be ACTIVE after update" - - # - # 9. Validate Connection - # - print("===Connection - Validate by id:", connection_id) - validate_detail = oci.database_tools.models.ValidateDatabaseToolsConnectionOracleDatabaseDetails( - type="ORACLE_DATABASE") - result = clients["dbtools_client"].validate_database_tools_connection(connection_id, validate_detail) - assert result.data is not None, "validation should return a validation info" - print("Validation Result:", result.data) - assert result.data.code == "OK", "validation should pass" - - -def do_connection_cleanup(conn_id): - """ - Delete the connection that we used for our tests - """ - if connection_id: - print("===Connection - Delete by id:", conn_id) - result = clients["dbtools_async_client"].delete_database_tools_connection_and_wait_for_state(conn_id, - wait_for_states=[ - "FAILED", - "SUCCEEDED", - "CANCELED"]) - - if result and result.data: - status = result.data.status - print( - f"delete_database_tools_connection_and_wait_for_state. Status: {status}, connection id: {conn_id}.") - assert status == "SUCCEEDED", "Delete Connection should succeed" + wait_for_states=self.terminal_states) + status = response.data.status + assert status == "SUCCEEDED", f"update connection should return status SUCCEEDED but was {status}" + + # After update, get the connection again and confirm the change + connection = self.dbtools_client.get_database_tools_connection(self.connection_id) + assert connection.data, "updated connection data should exist" + assert connection.data.display_name != display_name, "unexpected connection display name after update" + assert connection.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE after update but was {connection.data.lifecycle_state}" + + print(f"Updated connection. Name: {connection.data.display_name}, ocid: {self.connection_id}.") + + def validate_connection(self): + """ + Given an existing Database Tools connection, this method shows how to validate a connection by id. + For a connection to be able to route traffic to a database, it must be valid. (code == OK) + """ + print("=== DBTools Connection - Validate by id:", self.connection_id) + + validate_detail = oci.database_tools.models.ValidateDatabaseToolsConnectionOracleDatabaseDetails() + response = self.dbtools_client.validate_database_tools_connection(self.connection_id, validate_detail) + assert response, "validate_database_tools_connection should return a response" + assert response.data, "response should contain data" + + print("Validation result:", response.data) + assert response.data.code == "OK", f"validation code should be OK but was {response.data.code}" + + def do_connection_cleanup(self): + """ + Delete the Database Tools connection created by the example. + """ + if self.connection_id is None: + print("do_connection_cleanup skipped") + return + + print("=== DBTools Connection - Delete by id:", self.connection_id) + response = self.dbtools_async_client.delete_database_tools_connection_and_wait_for_state(self.connection_id, + wait_for_states=self.terminal_states) + assert response, "delete_database_tools_connection_and_wait_for_state should return a response" + assert response.data, "response should contain data" + + status = response.data.status + assert status == "SUCCEEDED", f"delete connection should return status SUCCEEDED but was {status}" + + print(f"Deleted connection. Status: {status}, ocid: {self.connection_id}.") + + def do_secrets_cleanup(self, days=2): + """ + Schedule deletion of the secrets created by the example. + """ + secret_deletion_time = datetime.now() + timedelta(days=days) + if self.password_secret_id is not None: + print("=== DBTools Example - Schedule Secret Deletion:", self.password_secret_id) + delete_secret(clients=self.clients, secret_id=self.password_secret_id, deletion_time=secret_deletion_time) else: - print("Error. do_connection_tests_cleanup failed") - else: - print("Error. do_connection_tests_cleanup skipped") - - -def do_secrets_cleanup(secrets_ids, days=2): - """ - Delete the secrets that we used in our tests - """ - # Delete Secret in vault clean-up - secret_deletion_time = datetime.now() + timedelta(days=days) - for secret_id in secrets_ids: - if secret_id: - delete_secret(clients, - secret_id=secret_id, - deletion_time=secret_deletion_time) - + print("do_secrets_cleanup skipped (password)") -def do_db_delete(adb_id): - # Beware, this actually DELETES the specified DB - clients["db_client"].delete_autonomous_database(adb_id) - print(f"TERMINATED Autonomous Database: {adb_id}") + if self.wallet_secret_id is not None: + print("=== DBTools Example - Schedule Secret Deletion:", self.wallet_secret_id) + delete_secret(clients=self.clients, secret_id=self.wallet_secret_id, deletion_time=secret_deletion_time) + else: + print("do_secrets_cleanup skipped (wallet)") + + def do_database_cleanup(self): + # Beware, this actually DELETES the specified DB + if self.autonomous_database_id is not None: + print("=== DBTools Example - Terminate Database:", self.autonomous_database_id) + self.db_client.delete_autonomous_database(self.autonomous_database_id) + print("Database terminated.") + else: + print("do_database_cleanup skipped") # -# main logic +# Run DBToolsExample and print results # if __name__ == "__main__": # Output Colors OKGREEN = '\033[92m' FAIL = '\033[91m' ENDC = '\033[0m' + example = None try: - # Create Autonomous Database - create_db(compartment_id, dbname, db_password) + example = DBToolsExample(compartment_id, vault_id, db_password) + + example.create_db() + example.save_secrets_to_vault() + example.create_connection() + example.get_connection() + example.update_connection() + example.validate_connection() - # Create and test Connections - do_connection_tests() + print(f"{OKGREEN}Python SDK test completed OK{ENDC}") - print(f"{OKGREEN}Python SDK Test completed OK{ENDC}") except Exception as e: print(f"{FAIL}Exception during tests:{ENDC} {e}") + finally: - # Clean-up - if do_clean_up_at_end: + if do_clean_up_at_end and example is not None: print("Starting resource clean-up.") - do_connection_cleanup(connection_id) - do_secrets_cleanup([password_secret_id, wallet_secret_id]) - do_db_delete(autonomous_database_id) + example.do_connection_cleanup() + example.do_secrets_cleanup() + example.do_database_cleanup() print("Clean-up completed.") else: print("Skipping resource clean-up.") diff --git a/examples/database_tools/adbs_create_connection_with_pe.py b/examples/database_tools/adbs_create_connection_with_pe.py index 4fbc83c21d..b7ccbcfa05 100644 --- a/examples/database_tools/adbs_create_connection_with_pe.py +++ b/examples/database_tools/adbs_create_connection_with_pe.py @@ -2,337 +2,390 @@ # Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. # This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. - -# Creates a connection to an Autonomous Databases with Shared Exadata Infrastructure (ADB-S) with Private Endpoint (PE) -# - Requires Database Tools Private Endpoint Reverse Connection: Yes -# - Requires a KeyStore: Yes, for mTLS +# ----------------------------------------------------------------------------- +# Example Use Case: Existing ADB-S with Private Endpoint +# ----------------------------------------------------------------------------- +# This example creates a Database Tools connection to an Autonomous Database +# (ADB-S) accessible by private endpoint (PE). Note, since this connection will +# be for an ADB-S PE, a Database Tools PE is required to make a reverse connection. +# This example serves as an academic exercise of the SDK. It is a best practice +# to use separate subnets for the database and the Database Tools PE. +# +# Prerequisites: # -# 1- Create a Database Tools Private Endpoint for A Reverse Connection to the PE of the ADB-S -# 2- Create required secrets -# 3- Create a connection -# 4- Validate the connection +# - An existing ADB-S with PE and network security group (i.e. ingress on 1522) +# - Available capacity (limits apply) to create a new private endpoint +# - An existing vault for storage of secrets, with at least one master key +# - A previously configured .oci/config file with a [DEFAULT] section +# - Set the following variables in the code below: +# + compartment_id : The ocid for the target compartment +# + vault_id : The ocid for a vault (to store secrets) +# + autonomous_database_id : The ocid for an Autonomous Database +# + subnet_id : The ocid for a subnet where the ADB endpoint exists +# + db_username : The database user to connect with +# + db_password : The database password to connect with # -# Prerequisites are: -# - An ADB-S created following the instructions from: https://docs.oracle.com/en-us/iaas/Content/Database/Concepts/adbsprivateaccess.htm -# - A compartment Id where the vcn, autonomous database, vault, private endpoint and connection will reside -# - vault_id: a vault created in KMS with at least one master key. -# - subnet_id of the Database Tools Private Endpoint and the PE of the ADB-S. Best practice is use separate subnets. +# High-level Steps: +# +# 1- Create a Database Tools private endpoint +# 2- Create required secrets +# 3- Create a connection using the Database Tools private endpoint +# 4- Validate the connection +# ----------------------------------------------------------------------------- import oci from oci.config import from_file, validate_config -from utils.dbtools import get_dbtools_clients, get_database_clients, get_secrets_client, \ - get_kms_vault_client, get_vaults_clients, delete_secret, get_wallet_and_create_secrets +from utils.dbtools import get_dbtools_clients, get_database_clients, get_secrets_client, get_kms_vault_client +from utils.dbtools import get_vaults_clients, delete_secret, get_wallet_and_create_secrets -from datetime import datetime, timedelta import pkg_resources +from datetime import datetime, timedelta -# Specify ADB-S id -autonomous_database_id = "ocid1.autonomousdatabase.oc1.changeme" -# Specify Compartment and subnet to use for tests -compartment_id = "ocid1.compartment.oc1.changeme" -# Specify vault id to use in the test. Must in compartment_name -vault_id = "ocid1.vault.oc1.changeme" -# Specify subnet id -subnet_id = "ocid1.subnet.oc1.changeme" - -db_password = "example-password" - -utc_now = datetime.utcnow() -db_password_secret_name = "db" + "this-is-not-the-secret" + "dbname" -db_wallet_secret_name = "wallet" + "this-is-not-the-secret" + "dbname" - -# Display OCI Python SDK version -print("oci version:", pkg_resources.get_distribution("oci").version) - -# Set do_clean_up_at_end to false to keep the Database Tools Private Endpoint, secrets and connection created +# Set do_clean_up_at_end = False to keep the secrets, connection, and PE created do_clean_up_at_end = True -# Variables -wallet_secret_id = None -password_secret_id = None -private_endpoint_id = None -connection_id = None - -# Load OCI Config -oci_config = from_file(file_location="~/.oci/config", profile_name="DEFAULT") - -# Validate OCI Config -validate_config(oci_config) - -# Prepare all clients that we will need -db_client, db_async_client = get_database_clients(oci_config) -vaults_client, vaults_async_client = get_vaults_clients(oci_config) -kms_vault_client = get_kms_vault_client(oci_config) -secrets_client = get_secrets_client(oci_config) -dbtools_client, dbtools_async_client = get_dbtools_clients(oci_config) - -# Prepare a dict that contains all the required clients -clients = {"db_client": db_client, "db_async_client": db_async_client, - "vaults_client": vaults_client, "vaults_async_client": vaults_async_client, - "kms_vault_client": kms_vault_client, - "secrets_client": secrets_client, - "dbtools_client": dbtools_client, "dbtools_async_client": dbtools_async_client} - +# Specify compartment ocid to use. (can also use tenancy ocid if applicable) +compartment_id = "ocid1.tenancy......changeme" -def get_endpoint_services(): - """ - DBTools Endpoints Services - """ - print("===DBTools Service - Endpoint Services") +# Specify vault ocid to use. (For this example, vault must be in compartment_id and contain a master key) +vault_id = "ocid1.vault.....changeme" - endpoint_services_response = clients["dbtools_client"].list_database_tools_endpoint_services(compartment_id) +# Specify Autonomous Database ocid to use +autonomous_database_id = "ocid1.autonomousdatabase.....changeme" - assert endpoint_services_response, "list_database_tools_endpoint_services should return a response" - assert endpoint_services_response.data, "endpoint_services should return data" - assert endpoint_services_response.data.items, "endpoint_services should contain a list of endpoints" +# Specifiy the VCN subnet ocid where the ADB-S PE was created +subnet_id = "ocid1.subnet.....changeme" - # Use the first endpoint_service - endpoint_service = endpoint_services_response.data.items[0] - print(f"===Endpoints Services - Using {endpoint_service}.") - assert endpoint_service.lifecycle_state == "ACTIVE", "endpoint_service must be ACTIVE" +# Specify the database username and password +db_username = "changeme_user" +db_password = "example-password" - return endpoint_service.id +print("Using oci version:", pkg_resources.get_distribution("oci").version) -def create_private_endpoint(endpoint_service_id): - """ - Create a DBTools Private Endpoint +class DBToolsExample: """ - global private_endpoint_id - - print("===DBTools Service - Private Endpoints") - - # - # Create a Database Tools Private Endpoint - # - display_name = "pe_pysdk_" + utc_now.strftime("%Y-%m-%d_%H-%M-%S") - description = "test with Python SDK" - pe_details_for_create = oci.database_tools.models.CreateDatabaseToolsPrivateEndpointDetails( - compartment_id=compartment_id, - endpoint_service_id=endpoint_service_id, - subnet_id=subnet_id, - display_name=display_name, - description=description) - print("===Private Endpoint - Create") - create_pe_response = clients["dbtools_async_client"].create_database_tools_private_endpoint_and_wait_for_state( - pe_details_for_create, wait_for_states=["FAILED", "SUCCEEDED", "CANCELED"]) - - assert create_pe_response, "create_database_tools_private_endpoint_and_wait_for_state should return a response" - assert create_pe_response.data, "create_database_tools_private_endpoint_and_wait_for_state should return data" - - status = create_pe_response.data.status - private_endpoint_id = create_pe_response.data.resources[0].identifier - print(f"Database Tools Private Endpoint created. Status: {status}, name: {display_name}, pe id: {private_endpoint_id}.") - assert status == "SUCCEEDED", "Create Private Endpoint should succeed" - - # - # Get the Private Endpoint by Id - # - print("===Private endpoints - Get by id:", private_endpoint_id) - get_pe_response = clients["dbtools_client"].get_database_tools_private_endpoint(private_endpoint_id) - print("Read created Private Endpoint:", get_pe_response.data) - assert get_pe_response, "get_database_tools_private_endpoint should return a response" - assert get_pe_response.data, "get_database_tools_private_endpoint should return data" - assert get_pe_response.data.lifecycle_state == "ACTIVE", "Private Endpoint should be ACTIVE" - - -def create_connection(): + A Database Tools example that demonstrates usage of the OCI Python SDK. """ - Do tests related to DBTools Connections - - Create Connection - - Get created connection - - Validate Connection. This makes sure that we can use this connection to connect to the ADB-S. - """ - global connection_id, wallet_secret_id, password_secret_id - print("===DBTools Service - Connections") - - # 1.get ADB-S - autonomous_database_response = clients["db_client"].get_autonomous_database(autonomous_database_id) - assert autonomous_database_response, "No autonomous database found" - assert autonomous_database_response.data, "should contain data" - autonomous_database = autonomous_database_response.data - - # 2. Prepare Wallet and secrets - wallet_secret_id, password_secret_id = get_wallet_and_create_secrets(oci_config=oci_config, - compartment_id=compartment_id, - clients=clients, - autonomous_database_id=autonomous_database_id, - vault_id=vault_id, - db_wallet_secret_name=db_wallet_secret_name, - db_password_secret_name=db_password_secret_name, - db_password=db_password) - - # 3. get mTLS Connection string from DB - assert autonomous_database.connection_strings - assert autonomous_database.connection_strings.profiles - profiles = autonomous_database.connection_strings.profiles - - m_tls = oci.database.models.DatabaseConnectionStringProfile.TLS_AUTHENTICATION_MUTUAL - low = oci.database.models.DatabaseConnectionStringProfile.CONSUMER_GROUP_LOW - connection_string = next((p.value for p in profiles if - p.tls_authentication == m_tls and p.consumer_group == low), None) - - print(f"Using connection_string {connection_string}") - - # 4. create SSO keyStore using wallet_secret_id - key_store = oci.database_tools.models.DatabaseToolsKeyStoreDetails( - key_store_type=oci.database_tools.models.DatabaseToolsKeyStoreDetails.KEY_STORE_TYPE_SSO, - key_store_content=oci.database_tools.models.DatabaseToolsKeyStoreContentSecretIdDetails( - value_type=oci.database_tools.models.DatabaseToolsKeyStoreContentSecretIdDetails.VALUE_TYPE_SECRETID, - secret_id=wallet_secret_id) - ) - - # - # 5. Create connection using: - # - DB Compartment - # - Connection String - # - dbUser - # - dbPasswordSecretId - # - Time generated display name - # - Related Resource ... - # - keyStore - # - print("===Connection - Create") - user_name = "admin" - user_password = oci.database_tools.models.DatabaseToolsUserPasswordSecretIdDetails( - secret_id=password_secret_id) - - display_name = "conn_pysdk_" + utc_now.strftime("%Y-%m-%d_%H-%M-%S") - related_resource = oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails( - entity_type=oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails.ENTITY_TYPE_AUTONOMOUSDATABASE, - identifier=autonomous_database_id) - - conn_details_for_create = oci.database_tools.models.CreateDatabaseToolsConnectionOracleDatabaseDetails( - compartment_id=compartment_id, - connection_string=connection_string, - user_name=user_name, - user_password=user_password, - display_name=display_name, - private_endpoint_id=private_endpoint_id, - related_resource=related_resource, - key_stores=[key_store] - ) - create_conn_response = clients["dbtools_async_client"].create_database_tools_connection_and_wait_for_state( - conn_details_for_create, wait_for_states=["FAILED", "SUCCEEDED", "CANCELED"]) - - assert create_conn_response, "create_database_tools_connection_and_wait_for_state should return a response" - assert create_conn_response.data, "Create db Response should contain data" - - status = create_conn_response.data.status - connection_id = create_conn_response.data.resources[0].identifier - print(f"Creating Connection. Status: {status}, name: {display_name}, connection id: {connection_id}.") - assert status == "SUCCEEDED", "Create Connection should succeed" - - # - # 6. Get connection that we just created BY Id - # - print("===Connection - Get by id:", connection_id) - connection = clients["dbtools_client"].get_database_tools_connection(connection_id) - print("Read created Connection:", connection.data) - assert connection.data, "Created Connection data should exist" - assert connection.data.display_name == display_name, "Unexpected Connection display name" - assert connection.data.lifecycle_state == "ACTIVE", "Connection should be ACTIVE" - - # - # 7. Validate Connection - # - print("===Connection - Validate by id:", connection_id) - validate_detail = oci.database_tools.models.ValidateDatabaseToolsConnectionOracleDatabaseDetails( - type="ORACLE_DATABASE") - result = clients["dbtools_client"].validate_database_tools_connection(connection_id, validate_detail) - assert result.data, "Validation should return a validation info" - print("Validation Result:", result.data) - assert result.data.code == "OK", "Created connection should be valid" - - -def do_connection_cleanup(conn_id): - """ - Delete the connection that we used for our tests - """ - if conn_id: - print("===Connection - Delete by id:", conn_id) - result = clients["dbtools_async_client"].delete_database_tools_connection_and_wait_for_state(conn_id, - wait_for_states=[ - "FAILED", - "SUCCEEDED", - "CANCELED"]) - - if result and result.data: - status = result.data.status - print( - f"delete_database_tools_connection_and_wait_for_state. Status: {status}, connection id: {conn_id}.") - assert status == "SUCCEEDED", "Delete Connection should succeed" + def __init__(self, compartment, vault, db, subnet, username, password): + + # Load an OCI config with the DEFAULT profile + self.oci_config = from_file(file_location="~/.oci/config", profile_name="DEFAULT") + + self.compartment_id = compartment + self.vault_id = vault + self.autonomous_database_id = db + self.subnet_id = subnet + self.db_username = username + self.db_password = password + + validate_config(self.oci_config) + + # Prepare SDK clients used in this example + self.dbtools_client, self.dbtools_async_client = get_dbtools_clients(self.oci_config) + self.db_client, self.db_async_client = get_database_clients(self.oci_config) + self.vaults_client, self.vaults_async_client = get_vaults_clients(self.oci_config) + self.kms_vault_client = get_kms_vault_client(self.oci_config) + self.secrets_client = get_secrets_client(self.oci_config) + + # Dict that contains all the clients (used by utils.dbtools helpers) + self.clients = {"dbtools_client": self.dbtools_client, "dbtools_async_client": self.dbtools_async_client, + "db_client": self.db_client, "db_async_client": self.db_async_client, + "vaults_client": self.vaults_client, "vaults_async_client": self.vaults_async_client, + "kms_vault_client": self.kms_vault_client, + "secrets_client": self.secrets_client} + + self.wallet_secret_id = None # populated at runtime + self.password_secret_id = None # populated at runtime + self.private_endpoint_id = None # populated at runtime + self.connection_id = None # populated at runtime + self.connection_string = None # populated at runtime + + # When waiting for asynchronous calls, which status is considered "done" + self.terminal_states = ["FAILED", "SUCCEEDED", "CANCELED", "AVAILABLE"] + + def get_endpoint_service(self): + """ + Get the ocid of the Database Tools endpoints service (used to create private endpoints) + """ + response = self.dbtools_client.list_database_tools_endpoint_services(self.compartment_id) + + assert response, "list_database_tools_endpoint_services should return a response" + assert response.data, "endpoint_services should return data" + assert response.data.items, "endpoint_services should contain a list of endpoints" + + # Use the first endpoint_service + endpoint_service = response.data.items[0] + assert endpoint_service.lifecycle_state == "ACTIVE", f"endpoint_service should be ACTIVE but was {endpoint_service.lifecycle_state}" + + return endpoint_service.id + + def create_private_endpoint(self): + """ + Create a Database Tools private endpoint. + """ + print("=== DBTools Example - Create Private Endpoint") + + endpoint_service_id = self.get_endpoint_service() + assert endpoint_service_id, "endpoint_service_id is required" + + display_name = "pe_pysdk_" + datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S") + description = "Test private endpoint with Python SDK" + pe_details_for_create = oci.database_tools.models.CreateDatabaseToolsPrivateEndpointDetails( + compartment_id=self.compartment_id, + endpoint_service_id=endpoint_service_id, + subnet_id=self.subnet_id, + display_name=display_name, + description=description) + + response = self.dbtools_async_client.create_database_tools_private_endpoint_and_wait_for_state( + pe_details_for_create, wait_for_states=self.terminal_states) + + assert response, "create_database_tools_private_endpoint_and_wait_for_state should return a response" + assert response.data, "create_database_tools_private_endpoint_and_wait_for_state should return data" + + status = response.data.status + self.private_endpoint_id = response.data.resources[0].identifier + assert status == "SUCCEEDED", f"create private endpoint should return status SUCCEEDED but was {status}" + + print(f"Private endpoint created. Name: {display_name}, ocid: {self.private_endpoint_id}.") + + def get_private_endpoint(self): + """ + Given an existing Database Tools private endpoint, this method shows how to get a PE by id. + """ + print("=== DBTools Private Endpoint - Get by id:", self.private_endpoint_id) + + response = self.dbtools_client.get_database_tools_private_endpoint(self.private_endpoint_id) + assert response, "get_database_tools_private_endpoint should return a response" + assert response.data, "get_database_tools_private_endpoint should return data" + assert response.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE but was {response.data.lifecycle_state}" + + print("Read created private endpoint:", response.data) + + def save_secrets_to_vault(self): + """ + Database Tools connections don't store secrets directly. Instead, they hold a pointer to + secrets stored securely in a vault. + """ + print("=== DBTools Example - Save Secrets to Vault") + + db_wallet_secret_name = "dbtools-temp-secretw-" + datetime.utcnow().strftime("%m%d%H%M") + db_password_secret_name = "dbtools-temp-secretp-" + datetime.utcnow().strftime("%m%d%H%M") + + # The wallet zip file generated by the Autonomous Database contains the cwallet.sso file + # needed to establish an mTLS connection. Extract this and store it as a base64 encoded + # secret in the vault, along with a new secret for the database password. + + response = self.db_client.get_autonomous_database(self.autonomous_database_id) + assert response, "get_autonomous_database should return a response" + assert response.data, "response should contain data" + autonomous_database = response.data + + self.wallet_secret_id, self.password_secret_id = get_wallet_and_create_secrets(oci_config=self.oci_config, + compartment_id=self.compartment_id, + clients=self.clients, + autonomous_database_id=self.autonomous_database_id, + vault_id=self.vault_id, + db_wallet_secret_name=db_wallet_secret_name, + db_password_secret_name=db_password_secret_name, + db_password=self.db_password) + + # Get the connection string with mTLS from the database + assert autonomous_database.connection_strings, "autonomous_database should have connection strings" + assert autonomous_database.connection_strings.profiles, "connection_strings should have profiles" + + profiles = autonomous_database.connection_strings.profiles + m_tls = oci.database.models.DatabaseConnectionStringProfile.TLS_AUTHENTICATION_MUTUAL + low = oci.database.models.DatabaseConnectionStringProfile.CONSUMER_GROUP_LOW + self.connection_string = next((p.value for p in profiles if + p.tls_authentication == m_tls and p.consumer_group == low), None) + + print(f"Created secret. Name: {db_wallet_secret_name}, ocid: {self.wallet_secret_id}") + print(f"Created secret. Name: {db_password_secret_name}, ocid: {self.password_secret_id}") + + def create_connection(self): + """ + Given the configuration details provided above, the secrets stored in the vault, + and the PE, create a Database Tools connection to the database. + """ + print("=== DBTools Example - Create Connection Using:", self.connection_string) + + # Setup SSO key store using wallet_secret_id (required for mTLS) + key_store = oci.database_tools.models.DatabaseToolsKeyStoreDetails( + key_store_type=oci.database_tools.models.DatabaseToolsKeyStoreDetails.KEY_STORE_TYPE_SSO, + key_store_content=oci.database_tools.models.DatabaseToolsKeyStoreContentSecretIdDetails( + value_type=oci.database_tools.models.DatabaseToolsKeyStoreContentSecretIdDetails.VALUE_TYPE_SECRETID, + secret_id=self.wallet_secret_id)) + + user_name = self.db_username + user_password = oci.database_tools.models.DatabaseToolsUserPasswordSecretIdDetails( + secret_id=self.password_secret_id) + + display_name = "conn_pysdk_" + datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S") + related_resource = oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails( + entity_type=oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails.ENTITY_TYPE_AUTONOMOUSDATABASE, + identifier=self.autonomous_database_id) + + conn_details_for_create = oci.database_tools.models.CreateDatabaseToolsConnectionOracleDatabaseDetails( + compartment_id=self.compartment_id, + connection_string=self.connection_string, + user_name=user_name, + user_password=user_password, + display_name=display_name, + private_endpoint_id=self.private_endpoint_id, + related_resource=related_resource, + key_stores=[key_store]) + + response = self.dbtools_async_client.create_database_tools_connection_and_wait_for_state( + conn_details_for_create, wait_for_states=self.terminal_states) + + assert response, "create_database_tools_connection_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.resources, "response data should return resources" + + status = response.data.status + assert status == "SUCCEEDED", f"create connection should return status SUCCEEDED but was {status}" + + self.connection_id = response.data.resources[0].identifier + print(f"Created connection. Name: {display_name}, ocid: {self.connection_id}.") + + def get_connection(self): + """ + Given an existing Database Tools connection, this method shows how to get a connection by id. + """ + print("=== DBTools Connection - Get by id:", self.connection_id) + + response = self.dbtools_client.get_database_tools_connection(self.connection_id) + assert response.data, "response should contain data" + assert response.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE but was {response.data.lifecycle_state}" + + print("Read created connection:", response.data) + + def update_connection(self): + """ + Given an existing Database Tools connection, this method shows how to update the connection by id. + """ + print("=== DBTools Connection - Update by id:", self.connection_id) + + connection = self.dbtools_client.get_database_tools_connection(self.connection_id) + display_name = connection.data.display_name + + connection_details_for_update = oci.database_tools.models.UpdateDatabaseToolsConnectionOracleDatabaseDetails( + display_name=display_name + "_updated") + + response = self.dbtools_async_client.update_database_tools_connection_and_wait_for_state(self.connection_id, + connection_details_for_update, + wait_for_states=self.terminal_states) + status = response.data.status + assert status == "SUCCEEDED", f"update connection should return status SUCCEEDED but was {status}" + + # After update, get the connection again and confirm the change + connection = self.dbtools_client.get_database_tools_connection(self.connection_id) + assert connection.data, "updated connection data should exist" + assert connection.data.display_name != display_name, "unexpected connection display name after update" + assert connection.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE after update but was {connection.data.lifecycle_state}" + + print(f"Updated connection. Name: {connection.data.display_name}, ocid: {self.connection_id}.") + + def validate_connection(self): + """ + Given an existing Database Tools connection, this method shows how to validate a connection by id. + For a connection to be able to route traffic to a database, it must be valid. (code == OK) + """ + print("=== DBTools Connection - Validate by id:", self.connection_id) + + validate_detail = oci.database_tools.models.ValidateDatabaseToolsConnectionOracleDatabaseDetails() + response = self.dbtools_client.validate_database_tools_connection(self.connection_id, validate_detail) + assert response, "validate_database_tools_connection should return a response" + assert response.data, "response should contain data" + + print("Validation result:", response.data) + assert response.data.code == "OK", f"validation code should be OK but was {response.data.code}" + + def do_connection_cleanup(self): + """ + Delete the Database Tools connection created by the example. + """ + if self.connection_id is None: + print("do_connection_cleanup skipped") + return + + print("=== DBTools Connection - Delete by id:", self.connection_id) + response = self.dbtools_async_client.delete_database_tools_connection_and_wait_for_state(self.connection_id, + wait_for_states=self.terminal_states) + assert response, "delete_database_tools_connection_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.status == "SUCCEEDED", f"delete connection should return status SUCCEEDED but was {response.data.status}" + + print(f"Deleted connection. ocid: {self.connection_id}.") + + def do_private_endpoint_cleanup(self): + """ + Delete the Database Tools private endpoint created by the example. + """ + if self.private_endpoint_id is None: + print("do_private_endpoint_cleanup skipped") + return + + print("=== DBTools Private Endpoint - Delete by id:", self.private_endpoint_id) + response = self.dbtools_async_client.delete_database_tools_private_endpoint_and_wait_for_state(self.private_endpoint_id, + wait_for_states=self.terminal_states) + assert response, "delete_database_tools_private_endpoint_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.status == "SUCCEEDED", f"delete private endpoint should return status SUCCEEDED but was {response.data.status}" + + print(f"Deleted private endpoint. ocid: {self.private_endpoint_id}.") + + def do_secrets_cleanup(self, days=2): + """ + Schedule deletion of the secrets created by the example. + """ + secret_deletion_time = datetime.now() + timedelta(days=days) + if self.password_secret_id: + print("=== DBTools Example - Schedule Secret Deletion:", self.password_secret_id) + delete_secret(clients=self.clients, secret_id=self.password_secret_id, deletion_time=secret_deletion_time) else: - print("Error. do_connection_tests_cleanup failed") - else: - print("Error. do_connection_tests_cleanup skipped") - + print("do_secrets_cleanup skipped (password)") -def do_private_endpoint_cleanup(pe_id): - """ - Delete the Database Tools Private endpoint that we used for our tests - """ - if pe_id: - print("===Private Endpoint - Delete by id:", pe_id) - result = clients["dbtools_async_client"].delete_database_tools_private_endpoint_and_wait_for_state(pe_id, - wait_for_states=[ - "FAILED", - "SUCCEEDED", - "CANCELED"]) - - if result and result.data: - status = result.data.status - print( - f"delete_database_tools_private_endpoint_and_wait_for_state. Status: {status}, connection id: {pe_id}.") - assert status == "SUCCEEDED", "Delete Private Endpoint should succeed" + if self.wallet_secret_id: + print("=== DBTools Example - Schedule Secret Deletion:", self.wallet_secret_id) + delete_secret(clients=self.clients, secret_id=self.wallet_secret_id, deletion_time=secret_deletion_time) else: - print("Error. do_private_endpoint_cleanup failed") - else: - print("Error. do_private_endpoint_cleanup skipped") - - -def do_secrets_cleanup(secrets_ids, days=2): - """ - Delete the secrets that we used for our tests - """ - # Delete Secret in vault clean-up - secret_deletion_time = datetime.now() + timedelta(days=days) - for secret_id in secrets_ids: - if secret_id: - delete_secret(clients, - secret_id=secret_id, - deletion_time=secret_deletion_time) + print("do_secrets_cleanup skipped (wallet)") # -# main logic +# Run DBToolsExample and print results # if __name__ == "__main__": # Output Colors OKGREEN = '\033[92m' FAIL = '\033[91m' ENDC = '\033[0m' + example = None try: - # Endpoint Service - endpoint_service_id = get_endpoint_services() + example = DBToolsExample(compartment_id, vault_id, autonomous_database_id, subnet_id, db_username, db_password) - # Create a Database Tools Private Endpoint - create_private_endpoint(endpoint_service_id) + example.create_private_endpoint() + example.save_secrets_to_vault() + example.create_connection() + example.get_connection() + example.update_connection() + example.validate_connection() - # Create and Validate a Database Tools Connection - create_connection() + print(f"{OKGREEN}Python SDK test completed OK{ENDC}") - print(f"{OKGREEN}Python SDK Test completed OK{ENDC}") except Exception as e: print(f"{FAIL}Exception during tests:{ENDC} {e}") + finally: - # Clean-up - if do_clean_up_at_end: + if do_clean_up_at_end and example is not None: print("Starting resource clean-up.") - do_connection_cleanup(connection_id) - do_private_endpoint_cleanup(private_endpoint_id) - do_secrets_cleanup([password_secret_id, wallet_secret_id]) + example.do_connection_cleanup() + example.do_secrets_cleanup() + example.do_private_endpoint_cleanup() print("Clean-up completed.") else: print("Skipping resource clean-up.") diff --git a/examples/database_tools/db_system_create_connection_private_subnet.py b/examples/database_tools/db_system_create_connection_private_subnet.py index ebc2e96879..c35a96f604 100644 --- a/examples/database_tools/db_system_create_connection_private_subnet.py +++ b/examples/database_tools/db_system_create_connection_private_subnet.py @@ -2,355 +2,376 @@ # Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. # This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. - -# Creates a connection to a VM DB System with Private Endpoint (PE) in a Private Subnet -# - Requires Database Tools Private Endpoint Reverse Connection: Yes -# - Requires a KeyStore: No +# ----------------------------------------------------------------------------- +# Example Use Case: Existing Oracle VM DB System with Private IP +# ----------------------------------------------------------------------------- +# This example creates a Database Tools connection to an Oracle VM DB System +# accessible via private ip. Note, since this connection will be for a database +# in a private subnet, a Database Tools private endpoint (PE) is required to +# make a reverse connection. This example serves as an academic exercise of the +# SDK. It is a best practice to use separate subnets for the database and the +# Database Tools PE. +# +# Prerequisites: # -# 1- Create a Database Tools Private Endpoint for A Reverse Connection to the VM DB System -# 2- Create required secrets -# 3- Create a connection -# 4- Validate the connection +# - An existing VM DB System and network security group (i.e. ingress on 1521) +# See: https://docs.oracle.com/en-us/iaas/dbcs/doc/overview-creating-db-system.html +# - Available capacity (limits apply) to create a new private endpoint +# - An existing vault for storage of secrets, with at least one master key +# - A previously configured .oci/config file with a [DEFAULT] section +# - Set the following variables in the code below: +# + compartment_id : The ocid for the target compartment +# + vault_id : The ocid for a vault (to store secrets) +# + db_system_id : The ocid for an Oracle VM DB System +# + subnet_id : The ocid for a subnet where the DB exists +# + db_username : The database user to connect with +# + db_password : The database password to connect with # -# Prerequisites are: -# - An DB system created following the instructions from: https://docs.oracle.com/en-us/iaas/Content/Database/Tasks/creatingDBsystem.htm with NSG for port 1521 -# - A compartment Id where the vcn, DB System, vault, private endpoint and connection will reside -# - vault_id: a vault created in KMS with at least one master key. -# - subnet_id of the Database Tools Private Endpoint and the DB system. Best practice is to use a private subnet. +# High-level Steps: +# +# 1- Create a Database Tools private endpoint +# 2- Create required secret +# 3- Create a connection using the Database Tools private endpoint +# 4- Validate the connection +# ----------------------------------------------------------------------------- import oci from oci.config import from_file, validate_config -from utils.dbtools import get_dbtools_clients, get_database_clients, get_secrets_client, \ - get_kms_vault_client, get_vaults_clients, create_secret, delete_secret +from utils.dbtools import get_dbtools_clients, get_database_clients, get_secrets_client, get_kms_vault_client +from utils.dbtools import get_vaults_clients, create_secret, delete_secret -from datetime import datetime, timedelta import pkg_resources import base64 +from datetime import datetime, timedelta -# Specify Compartment and subnet to use for tests -compartment_id = "ocid1.compartment.oc1.changeme" -# Specify vault id to use in the test. Must in compartment_name -vault_id = "ocid1.vault.oc1.changeme" -# Specify subnet id -subnet_id = "ocid1.subnet.oc1.changeme" -# Specify VM DB System Id -db_system_id = "ocid1.dbsystem.oc1.changeme" -# Specify VM DB Password -db_password = "example-password" - -utc_now = datetime.utcnow() -db_password_secret_name = "db_password_SDK_" + utc_now.strftime("%m-%d%.%H%M") - -# Display OCI Python SDK version -print("oci version:", pkg_resources.get_distribution("oci").version) - -# Set do_clean_up_at_end to false to keep the Database Tools Private Endpoint, secrets and connection created +# Set do_clean_up_at_end = False to keep the secret and connection created do_clean_up_at_end = True -# Variables that will be modified during the processing -vault_key_id = None -password_secret_id = None -private_endpoint_id = None -connection_id = None - -# Load OCI Config -oci_config = from_file(file_location="~/.oci/config", profile_name="DEFAULT") - -# Validate OCI Config -validate_config(oci_config) - -# Prepare all clients that we will need -db_client, db_async_client = get_database_clients(oci_config) -vaults_client, vaults_async_client = get_vaults_clients(oci_config) -kms_vault_client = get_kms_vault_client(oci_config) -secrets_client = get_secrets_client(oci_config) -dbtools_client, dbtools_async_client = get_dbtools_clients(oci_config) +# Specify compartment ocid to use. (can also use tenancy ocid if applicable) +compartment_id = "ocid1.tenancy......changeme" -# Prepare a dict that contains all the required clients -clients = {"db_client": db_client, "db_async_client": db_async_client, - "vaults_client": vaults_client, "vaults_async_client": vaults_async_client, - "kms_vault_client": kms_vault_client, - "secrets_client": secrets_client, - "dbtools_client": dbtools_client, "dbtools_async_client": dbtools_async_client} - - -def get_endpoint_services(): - """ - DBTools Endpoints Services - """ - print("===DBTools Service - Endpoint Services") +# Specify vault ocid to use. (For this example, vault must be in compartment_id and contain a master key) +vault_id = "ocid1.vault.....changeme" - endpoint_services_response = clients["dbtools_client"].list_database_tools_endpoint_services(compartment_id) +# Specify Oracle VM DB System ocid to use +db_system_id = "ocid1.dbsystem.....changeme" - assert endpoint_services_response, "list_database_tools_endpoint_services should return a response" - assert endpoint_services_response.data, "endpoint_services should return data" - assert endpoint_services_response.data.items, "endpoint_services should contain a list of endpoints" +# Specifiy the VCN subnet ocid where the ADB-S PE was created +subnet_id = "ocid1.subnet.....changeme" - # Use the first endpoint_service - endpoint_service = endpoint_services_response.data.items[0] - print(f"===Endpoints Services - Using {endpoint_service}.") - assert endpoint_service.lifecycle_state == "ACTIVE", "endpoint_service must be ACTIVE" +# Specify the database username and password +db_username = "system" +db_password = "example-password" - return endpoint_service.id +print("Using oci version:", pkg_resources.get_distribution("oci").version) -def create_private_endpoint(endpoint_service_id): - """ - Create a DBTools Private Endpoint - """ - global private_endpoint_id - - print("===DBTools Service - Private Endpoints") - - # - # Create a Database Tools Private Endpoint - # - display_name = "pe_pysdk_" + utc_now.strftime("%Y-%m-%d_%H-%M-%S") - description = "test with Python SDK" - pe_details_for_create = oci.database_tools.models.CreateDatabaseToolsPrivateEndpointDetails( - compartment_id=compartment_id, - endpoint_service_id=endpoint_service_id, - subnet_id=subnet_id, - display_name=display_name, - description=description) - print("===Private Endpoint - Create") - create_pe_response = clients["dbtools_async_client"].create_database_tools_private_endpoint_and_wait_for_state( - pe_details_for_create, wait_for_states=["FAILED", "SUCCEEDED", "CANCELED"]) - - assert create_pe_response, "create_database_tools_private_endpoint_and_wait_for_state should return a response" - assert create_pe_response.data, "create_database_tools_private_endpoint_and_wait_for_state should return data" - - status = create_pe_response.data.status - private_endpoint_id = create_pe_response.data.resources[0].identifier - print(f"Database Tools Private Endpoint created. Status: {status}, name: {display_name}, pe id: {private_endpoint_id}.") - assert status == "SUCCEEDED", "Create Private Endpoint should succeed" - - # - # Get the Private Endpoint by Id - # - print("===Private endpoints - Get by id:", private_endpoint_id) - get_pe_response = clients["dbtools_client"].get_database_tools_private_endpoint(private_endpoint_id) - print("Read created Private Endpoint:", get_pe_response.data) - assert get_pe_response, "get_database_tools_private_endpoint should return a response" - assert get_pe_response.data, "get_database_tools_private_endpoint should return data" - assert get_pe_response.data.lifecycle_state == "ACTIVE", "Private Endpoint should be ACTIVE" - - -def create_connection(): - """ - Do tests related to DBTools Connections - - Create Connection - - Get created connection - - Validate Connection. This makes sure that we can use this connection to connect to the ADB-S. +class DBToolsExample: """ - global connection_id, password_secret_id, vault_key_id - print("===DBTools Service - Connections") - - # 1. Get Connection String for VM DB System - # - # - List dbHomes in compartment for our dbSystemId - # - Take the first - # - List database in compartment for the dbHome of our DB System - # - Take the 1 one that matches dbSystemId - # - List pdbs in database - # - Take the 1 one/ - # - connection string is in pdb_default of the connection strings. - - # List db_homes in compartment for our db_system_id - db_homes_response = clients["db_client"].list_db_homes( - compartment_id=compartment_id, - db_system_id=db_system_id - ) - assert db_homes_response, "list_db_homes should return a response" - assert db_homes_response.data, "list_db_homes should return data" - db_home = db_homes_response.data[0] - db_home_id = db_home.id - - # List databases in compartment for the dbHome of our DB System - databases_response = clients["db_client"].list_databases( - compartment_id=compartment_id, - db_home_id=db_home_id - ) - assert databases_response, "list_databases should return a response" - assert databases_response.data, "list_databases should return data" - database_summary = databases_response.data[0] - - assert database_summary.db_system_id == db_system_id, "This database should be for our VM DB System" - print("database:", database_summary) - - # List pdbs in database - pdbs_response = clients["db_client"].list_pluggable_databases( - database_id=database_summary.id - ) - assert pdbs_response, "list_pluggable_databases should return a response" - assert pdbs_response.data, "list_pluggable_databases should return data" - pdb = pdbs_response.data[0] - - assert pdb.connection_strings, "pdb should have connection_strings" - assert pdb.connection_strings.pdb_default, "pdb should have a default pdb connection_string" - connection_string = pdb.connection_strings.pdb_default - print(f"Using connection_string {connection_string}") - - # 4. Store the DB password in the vault as a secret under name X. If name X already exists, we will simply use it. - base64_db_password_str = base64.b64encode(db_password.encode()).decode() - password_secret_id, vault_key_id = create_secret(oci_config, - compartment_id=compartment_id, - clients=clients, - vault_id=vault_id, - vault_key_id=vault_key_id, - name=db_password_secret_name, - base64_password=base64_db_password_str) - - # - # 2. Create connection using: - # - DB Compartment - # - Connection String - # - dbUser - # - dbPasswordSecretId - # - Time generated display name - # - Related Resource - # - Advanced property since we want to connect with SYS as SYSDBA - # - print("===Connection - Create") - user_name = "system" - user_password = oci.database_tools.models.DatabaseToolsUserPasswordSecretIdDetails( - secret_id=password_secret_id) - - display_name = "conn_pysdk_" + utc_now.strftime("%Y-%m-%d_%H-%M-%S") - related_resource = oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails( - entity_type=oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails.ENTITY_TYPE_PLUGGABLEDATABASE, - identifier=db_system_id) - - conn_details_for_create = oci.database_tools.models.CreateDatabaseToolsConnectionOracleDatabaseDetails( - compartment_id=compartment_id, - connection_string=connection_string, - user_name=user_name, - user_password=user_password, - display_name=display_name, - private_endpoint_id=private_endpoint_id, - related_resource=related_resource - ) - create_conn_response = clients["dbtools_async_client"].create_database_tools_connection_and_wait_for_state( - conn_details_for_create, wait_for_states=["FAILED", "SUCCEEDED", "CANCELED"]) - - assert create_conn_response, "create_database_tools_connection_and_wait_for_state should return a response" - assert create_conn_response.data, "Create db Response should contain data" - - status = create_conn_response.data.status - connection_id = create_conn_response.data.resources[0].identifier - print(f"Creating Connection. Status: {status}, name: {display_name}, connection id: {connection_id}.") - assert status == "SUCCEEDED", "Create Connection should succeed" - - # - # 3. Get connection that we just created BY Id - # - print("===Connection - Get by id:", connection_id) - connection = clients["dbtools_client"].get_database_tools_connection(connection_id) - print("Read created Connection:", connection.data) - assert connection.data, "Created Connection data should exist" - assert connection.data.display_name == display_name, "Unexpected Connection display name" - assert connection.data.lifecycle_state == "ACTIVE", "Connection should be ACTIVE" - - # - # 4. Validate Connection - # - print("===Connection - Validate by id:", connection_id) - validate_detail = oci.database_tools.models.ValidateDatabaseToolsConnectionOracleDatabaseDetails( - type="ORACLE_DATABASE") - result = clients["dbtools_client"].validate_database_tools_connection(connection_id, validate_detail) - assert result.data, "Validation should return a validation info" - print("Validation Result:", result.data) - assert result.data.code == "OK", "Created connection should be valid" - - -def do_connection_cleanup(conn_id): + A Database Tools example that demonstrates usage of the OCI Python SDK. """ - Delete the connection that we used for our tests - """ - if conn_id: - print("===Connection - Delete by id:", conn_id) - result = clients["dbtools_async_client"].delete_database_tools_connection_and_wait_for_state(conn_id, - wait_for_states=[ - "FAILED", - "SUCCEEDED", - "CANCELED"]) - - if result and result.data: - status = result.data.status - print( - f"delete_database_tools_connection_and_wait_for_state. Status: {status}, connection id: {conn_id}.") - assert status == "SUCCEEDED", "Delete Connection should succeed" + def __init__(self, compartment, vault, db, subnet, username, password): + + # Load an OCI config with the DEFAULT profile + self.oci_config = from_file(file_location="~/.oci/config", profile_name="DEFAULT") + + self.compartment_id = compartment + self.vault_id = vault + self.db_system_id = db + self.subnet_id = subnet + self.db_username = username + self.db_password = password + + validate_config(self.oci_config) + + # Prepare SDK clients used in this example + self.dbtools_client, self.dbtools_async_client = get_dbtools_clients(self.oci_config) + self.db_client, self.db_async_client = get_database_clients(self.oci_config) + self.vaults_client, self.vaults_async_client = get_vaults_clients(self.oci_config) + self.kms_vault_client = get_kms_vault_client(self.oci_config) + self.secrets_client = get_secrets_client(self.oci_config) + + # Dict that contains all the clients (used by utils.dbtools helpers) + self.clients = {"dbtools_client": self.dbtools_client, "dbtools_async_client": self.dbtools_async_client, + "db_client": self.db_client, "db_async_client": self.db_async_client, + "vaults_client": self.vaults_client, "vaults_async_client": self.vaults_async_client, + "kms_vault_client": self.kms_vault_client, + "secrets_client": self.secrets_client} + + self.password_secret_id = None # populated at runtime + self.private_endpoint_id = None # populated at runtime + self.connection_id = None # populated at runtime + self.connection_string = None # populated at runtime + + # When waiting for asynchronous calls, which status is considered "done" + self.terminal_states = ["FAILED", "SUCCEEDED", "CANCELED", "AVAILABLE"] + + def get_endpoint_service(self): + """ + Get the ocid of the Database Tools endpoints service (used to create private endpoints) + """ + response = self.dbtools_client.list_database_tools_endpoint_services(self.compartment_id) + + assert response, "list_database_tools_endpoint_services should return a response" + assert response.data, "endpoint_services should return data" + assert response.data.items, "endpoint_services should contain a list of endpoints" + + # Use the first endpoint_service + endpoint_service = response.data.items[0] + assert endpoint_service.lifecycle_state == "ACTIVE", f"endpoint_service should be ACTIVE but was {endpoint_service.lifecycle_state}" + + return endpoint_service.id + + def create_private_endpoint(self): + """ + Create a Database Tools private endpoint. + """ + print("=== DBTools Example - Create Private Endpoint") + + endpoint_service_id = self.get_endpoint_service() + assert endpoint_service_id, "endpoint_service_id is required" + + display_name = "pe_pysdk_" + datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S") + description = "Test private endpoint with Python SDK" + pe_details_for_create = oci.database_tools.models.CreateDatabaseToolsPrivateEndpointDetails( + compartment_id=self.compartment_id, + endpoint_service_id=endpoint_service_id, + subnet_id=self.subnet_id, + display_name=display_name, + description=description) + + response = self.dbtools_async_client.create_database_tools_private_endpoint_and_wait_for_state( + pe_details_for_create, wait_for_states=self.terminal_states) + + assert response, "create_database_tools_private_endpoint_and_wait_for_state should return a response" + assert response.data, "create_database_tools_private_endpoint_and_wait_for_state should return data" + + status = response.data.status + self.private_endpoint_id = response.data.resources[0].identifier + assert status == "SUCCEEDED", f"create private endpoint should return status SUCCEEDED but was {status}" + + print(f"Private endpoint created. Name: {display_name}, ocid: {self.private_endpoint_id}.") + + def get_private_endpoint(self): + """ + Given an existing Database Tools private endpoint, this method shows how to get a PE by id. + """ + print("=== DBTools Private Endpoint - Get by id:", self.private_endpoint_id) + + response = self.dbtools_client.get_database_tools_private_endpoint(self.private_endpoint_id) + assert response, "get_database_tools_private_endpoint should return a response" + assert response.data, "get_database_tools_private_endpoint should return data" + assert response.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE but was {response.data.lifecycle_state}" + + print("Read created private endpoint:", response.data) + + def save_dbpassword_to_vault(self): + """ + Database Tools connections don't store secrets directly. Instead, they hold a pointer to + secrets stored securely in a vault. + """ + print("=== DBTools Example - Save DB Password to Vault") + + db_password_secret_name = "dbtools-temp-secretp-" + datetime.utcnow().strftime("%m%d%H%M") + base64_secret_content = base64.b64encode(self.db_password.encode()).decode() + + self.password_secret_id = create_secret(oci_config=self.oci_config, + compartment_id=self.compartment_id, + vault_id=self.vault_id, + name=db_password_secret_name, + base64_secret_content=base64_secret_content, + clients=self.clients)[0] + + print(f"Created secret. Name: {db_password_secret_name}, ocid: {self.password_secret_id}") + + def get_connection_string(self): + """ + Given a VM DB System, lookup the default connection string + """ + # - List dbHomes in the compartment for the dbSystemId + # - Take the first one + # - List the databases in compartment for the dbHome of the DB System + # - Take the first one that matches dbSystemId + # - List pdbs in the database + # - Take the first one + # - connection string is in pdb_default of the connection strings. + + # List db_homes in compartment for the db_system_id + db_homes_response = self.db_client.list_db_homes( + compartment_id=self.compartment_id, + db_system_id=self.db_system_id) + + assert db_homes_response, "list_db_homes should return a response" + assert db_homes_response.data, "list_db_homes should return data" + db_home = db_homes_response.data[0] + db_home_id = db_home.id + + # List databases in compartment for the dbHome of the DB System + databases_response = self.db_client.list_databases( + compartment_id=self.compartment_id, + db_home_id=db_home_id) + + assert databases_response, "list_databases should return a response" + assert databases_response.data, "list_databases should return data" + database_summary = databases_response.data[0] + + assert database_summary.db_system_id == self.db_system_id, f"expected {self.db_system_id} but found {database_summary.db_system_id}" + print("database:", database_summary) + + # List pdbs in database + pdbs_response = self.db_client.list_pluggable_databases( + database_id=database_summary.id) + + assert pdbs_response, "list_pluggable_databases should return a response" + assert pdbs_response.data, "list_pluggable_databases should return data" + pdb = pdbs_response.data[0] + + assert pdb.connection_strings, "pdb should have connection_strings" + assert pdb.connection_strings.pdb_default, "pdb should have a default pdb connection_string" + self.connection_string = pdb.connection_strings.pdb_default + + def create_connection(self): + """ + Given the configuration details provided above, the secrets stored in the vault, + and the PE, create a Database Tools connection to the database. + """ + print("=== DBTools Example - Create Connection Using:", self.connection_string) + + user_name = self.db_username + user_password = oci.database_tools.models.DatabaseToolsUserPasswordSecretIdDetails( + secret_id=self.password_secret_id) + + display_name = "conn_pysdk_" + datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S") + related_resource = oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails( + entity_type=oci.database_tools.models.CreateDatabaseToolsRelatedResourceDetails.ENTITY_TYPE_PLUGGABLEDATABASE, + identifier=self.db_system_id) + + conn_details_for_create = oci.database_tools.models.CreateDatabaseToolsConnectionOracleDatabaseDetails( + compartment_id=self.compartment_id, + connection_string=self.connection_string, + user_name=user_name, + user_password=user_password, + display_name=display_name, + private_endpoint_id=self.private_endpoint_id, + related_resource=related_resource) + + response = self.dbtools_async_client.create_database_tools_connection_and_wait_for_state( + conn_details_for_create, wait_for_states=self.terminal_states) + + assert response, "create_database_tools_connection_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.resources, "response data should return resources" + + status = response.data.status + assert status == "SUCCEEDED", f"create connection should return status SUCCEEDED but was {status}" + + self.connection_id = response.data.resources[0].identifier + print(f"Created connection. Name: {display_name}, ocid: {self.connection_id}.") + + def get_connection(self): + """ + Given an existing Database Tools connection, this method shows how to get a connection by id. + """ + print("=== DBTools Connection - Get by id:", self.connection_id) + + response = self.dbtools_client.get_database_tools_connection(self.connection_id) + assert response.data, "response should contain data" + assert response.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE but was {response.data.lifecycle_state}" + + print("Read created connection:", response.data) + + def validate_connection(self): + """ + Given an existing Database Tools connection, this method shows how to validate a connection by id. + For a connection to be able to route traffic to a database, it must be valid. (code == OK) + """ + print("=== DBTools Connection - Validate by id:", self.connection_id) + + validate_detail = oci.database_tools.models.ValidateDatabaseToolsConnectionOracleDatabaseDetails() + response = self.dbtools_client.validate_database_tools_connection(self.connection_id, validate_detail) + assert response, "validate_database_tools_connection should return a response" + assert response.data, "response should contain data" + + print("Validation result:", response.data) + assert response.data.code == "OK", f"validation code should be OK but was {response.data.code}" + + def do_connection_cleanup(self): + """ + Delete the Database Tools connection created by the example. + """ + if self.connection_id is None: + print("do_connection_cleanup skipped") + return + + print("=== DBTools Connection - Delete by id:", self.connection_id) + response = self.dbtools_async_client.delete_database_tools_connection_and_wait_for_state(self.connection_id, + wait_for_states=self.terminal_states) + assert response, "delete_database_tools_connection_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.status == "SUCCEEDED", f"delete connection should return status SUCCEEDED but was {response.data.status}" + + print(f"Deleted connection. ocid: {self.connection_id}.") + + def do_private_endpoint_cleanup(self): + """ + Delete the Database Tools private endpoint created by the example. + """ + if self.private_endpoint_id is None: + print("do_private_endpoint_cleanup skipped") + return + + print("=== DBTools Private Endpoint - Delete by id:", self.private_endpoint_id) + response = self.dbtools_async_client.delete_database_tools_private_endpoint_and_wait_for_state(self.private_endpoint_id, + wait_for_states=self.terminal_states) + assert response, "delete_database_tools_private_endpoint_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.status == "SUCCEEDED", f"delete private endpoint should return status SUCCEEDED but was {response.data.status}" + + print(f"Deleted private endpoint. ocid: {self.private_endpoint_id}.") + + def do_secrets_cleanup(self, days=2): + """ + Schedule deletion of the secrets created by the example. + """ + secret_deletion_time = datetime.now() + timedelta(days=days) + if self.password_secret_id: + print("=== DBTools Example - Schedule Secret Deletion:", self.password_secret_id) + delete_secret(clients=self.clients, secret_id=self.password_secret_id, deletion_time=secret_deletion_time) else: - print("Error. do_connection_tests_cleanup failed") - else: - print("Error. do_connection_tests_cleanup skipped") - - -def do_private_endpoint_cleanup(pe_id): - """ - Delete the Database Tools Private endpoint that we used for our tests - """ - if pe_id: - print("===Private Endpoint - Delete by id:", pe_id) - result = clients["dbtools_async_client"].delete_database_tools_private_endpoint_and_wait_for_state(pe_id, - wait_for_states=[ - "FAILED", - "SUCCEEDED", - "CANCELED"]) - - if result and result.data: - status = result.data.status - print( - f"delete_database_tools_private_endpoint_and_wait_for_state. Status: {status}, connection id: {private_endpoint_id}.") - assert status == "SUCCEEDED", "Delete Private Endpoint should succeed" - else: - print("Error. do_private_endpoint_cleanup failed") - else: - print("Error. do_private_endpoint_cleanup skipped") - - -def do_secrets_cleanup(secrets_ids, days=2): - """ - Delete the secrets that we used for our tests - """ - # Delete Secret in vault clean-up - secret_deletion_time = datetime.now() + timedelta(days=days) - for secret_id in secrets_ids: - if secret_id: - delete_secret(clients, - secret_id=secret_id, - deletion_time=secret_deletion_time) + print("do_secrets_cleanup skipped (password)") # -# main logic +# Run DBToolsExample and print results # if __name__ == "__main__": # Output Colors OKGREEN = '\033[92m' FAIL = '\033[91m' ENDC = '\033[0m' + example = None try: - # Endpoint Service - endpoint_service_id = get_endpoint_services() + example = DBToolsExample(compartment_id, vault_id, db_system_id, subnet_id, db_username, db_password) - # Create a Database Tools Private Endpoint - create_private_endpoint(endpoint_service_id) + example.create_private_endpoint() + example.save_dbpassword_to_vault() + example.get_connection_string() + example.create_connection() + example.get_connection() + example.validate_connection() - # Create and Validate a Database Tools Connection - create_connection() + print(f"{OKGREEN}Python SDK test completed OK{ENDC}") - print(f"{OKGREEN}Python SDK Test completed OK{ENDC}") except Exception as e: print(f"{FAIL}Exception during tests:{ENDC} {e}") + finally: - # Clean-up - if do_clean_up_at_end: + if do_clean_up_at_end and example is not None: print("Starting resource clean-up.") - do_connection_cleanup(connection_id) - do_private_endpoint_cleanup(private_endpoint_id) - do_secrets_cleanup([password_secret_id]) + example.do_connection_cleanup() + example.do_secrets_cleanup() + example.do_private_endpoint_cleanup() print("Clean-up completed.") else: print("Skipping resource clean-up.") diff --git a/examples/database_tools/images/MySQL.DB.System.with.PE.png b/examples/database_tools/images/MySQL.DB.System.with.PE.png new file mode 100644 index 0000000000..c1c52a923f Binary files /dev/null and b/examples/database_tools/images/MySQL.DB.System.with.PE.png differ diff --git a/examples/database_tools/images/MySQL.with.Public.IP.png b/examples/database_tools/images/MySQL.with.Public.IP.png new file mode 100644 index 0000000000..29fe8af5bd Binary files /dev/null and b/examples/database_tools/images/MySQL.with.Public.IP.png differ diff --git a/examples/database_tools/mysql_create_connection_public_ip.py b/examples/database_tools/mysql_create_connection_public_ip.py new file mode 100644 index 0000000000..8aba24fa9a --- /dev/null +++ b/examples/database_tools/mysql_create_connection_public_ip.py @@ -0,0 +1,261 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + +# ----------------------------------------------------------------------------- +# Example Use Case: Existing MySQL Database with Public IP (customer-managed) +# ----------------------------------------------------------------------------- +# This example creates a Database Tools connection to a MySQL database +# accessible by public ip. Note, since this connection will be against a +# public ip address, a Database Tools private endpoint is not required. +# Exposing a database directly to the Internet is NOT a recommended practice +# for security reasons. This example serves as an academic exercise of the SDK. +# +# Prerequisites: +# +# - An existing MySQL database on a compute node, for example +# - Firewall or security list entries allowing TCP traffic to MySQL +# - An existing Vault for storage of secrets, with at least one master key. +# - A previously configured .oci/config file with a [DEFAULT] section +# - Set the following variables in the code below: +# + compartment_id : The compartment to use with the example +# + vault_id : The ocid for a vault (to store secrets) +# + db_username : The MySQL database user to connect with +# + db_password : The MySQL database password to connect with +# + connection_string : The MySQL connection string +# +# High-level Steps: +# +# 1- Create required secret +# 2- Create a connection +# 3- Validate the connection +# ----------------------------------------------------------------------------- + +import oci +from oci.config import from_file, validate_config +from utils.dbtools import get_dbtools_clients, get_secrets_client, get_kms_vault_client, get_vaults_clients +from utils.dbtools import create_secret, delete_secret + +import pkg_resources +import base64 +from datetime import datetime, timedelta + +# Set do_clean_up_at_end = False to keep the secret and connection created +do_clean_up_at_end = True + +# Specify compartment ocid to use. (can also use tenancy ocid if applicable) +compartment_id = "ocid1.tenancy......changeme" + +# Specify vault ocid to use. (For this example, vault must be in compartment_id and contain a master key) +vault_id = "ocid1.vault.....changeme" + +# Specify the MySQL database connection string +connection_string = "mysql://host.changeme:port/" + +# Specify the database username and password +db_username = "example-username" +db_password = "example-password" + +print("Using oci version:", pkg_resources.get_distribution("oci").version) + + +class DBToolsExample: + """ + A Database Tools example that demonstrates usage of the OCI Python SDK. + """ + def __init__(self, compartment, vault, connection_string, username, password): + + # Load an OCI config with the DEFAULT profile + self.oci_config = from_file(file_location="~/.oci/config", profile_name="DEFAULT") + + self.compartment_id = compartment + self.vault_id = vault + self.connection_string = connection_string + self.db_username = username + self.db_password = password + + validate_config(self.oci_config) + + # Prepare SDK clients used in this example + self.dbtools_client, self.dbtools_async_client = get_dbtools_clients(self.oci_config) + self.vaults_client, self.vaults_async_client = get_vaults_clients(self.oci_config) + self.kms_vault_client = get_kms_vault_client(self.oci_config) + self.secrets_client = get_secrets_client(self.oci_config) + + # Dict that contains all the clients (used by utils.dbtools helpers) + self.clients = {"vaults_client": self.vaults_client, "vaults_async_client": self.vaults_async_client, + "kms_vault_client": self.kms_vault_client, + "secrets_client": self.secrets_client, + "dbtools_client": self.dbtools_client, "dbtools_async_client": self.dbtools_async_client} + + self.password_secret_id = None # populated at runtime + self.connection_id = None # populated at runtime + + # When waiting for asynchronous calls, which status is considered "done" + self.terminal_states = ["FAILED", "SUCCEEDED", "CANCELED"] + + def save_dbpassword_to_vault(self): + """ + Database Tools connections don't store secrets directly. Instead, they hold a pointer to + secrets stored securely in a vault. + """ + print("=== DBTools Example - Save DB Password to Vault") + + db_password_secret_name = "dbtools-temp-secretp-" + datetime.utcnow().strftime("%m%d%H%M") + base64_secret_content = base64.b64encode(self.db_password.encode()).decode() + + self.password_secret_id = create_secret(oci_config=self.oci_config, + compartment_id=self.compartment_id, + vault_id=self.vault_id, + name=db_password_secret_name, + base64_secret_content=base64_secret_content, + clients=self.clients)[0] + + print(f"Created secret. Name: {db_password_secret_name}, ocid: {self.password_secret_id}") + + def create_connection(self): + """ + Given the configuration details provided above and the secrets stored in the vault, + create a Database Tools connection to the MySQL database. + """ + print("=== DBTools Example - Create Connection Using:", self.connection_string) + + user_password = oci.database_tools.models.DatabaseToolsUserPasswordSecretIdDetails( + secret_id=self.password_secret_id) + + display_name = "conn_pysdk_" + datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S") + + conn_details_for_create = oci.database_tools.models.CreateDatabaseToolsConnectionMySqlDetails( + compartment_id=self.compartment_id, + connection_string=self.connection_string, + user_name=self.db_username, + user_password=user_password, + display_name=display_name) + + response = self.dbtools_async_client.create_database_tools_connection_and_wait_for_state( + conn_details_for_create, wait_for_states=self.terminal_states) + + assert response, "create_database_tools_connection_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.resources, "response data should return resources" + + status = response.data.status + assert status == "SUCCEEDED", f"create connection should return status SUCCEEDED but was {status}" + + self.connection_id = response.data.resources[0].identifier + print(f"Created connection. Name: {display_name}, ocid: {self.connection_id}.") + + def get_connection(self): + """ + Given an existing Database Tools connection, this method shows how to get the connection by id. + """ + print("=== DBTools Connection - Get by id:", self.connection_id) + + response = self.dbtools_client.get_database_tools_connection(self.connection_id) + assert response.data, "response should contain data" + assert response.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE but was {response.data.lifecycle_state}" + + print("Read created connection:", response.data) + + def update_connection(self): + """ + Given an existing Database Tools connection, this method shows how to update the connection by id. + """ + print("=== DBTools Connection - Update by id:", self.connection_id) + + connection = self.dbtools_client.get_database_tools_connection(self.connection_id) + display_name = connection.data.display_name + + connection_details_for_update = oci.database_tools.models.UpdateDatabaseToolsConnectionMySqlDetails( + display_name=display_name + "_updated") + + response = self.dbtools_async_client.update_database_tools_connection_and_wait_for_state(self.connection_id, + connection_details_for_update, + wait_for_states=self.terminal_states) + status = response.data.status + assert status == "SUCCEEDED", f"update connection should return status SUCCEEDED but was {status}" + + # After update, get the connection again and confirm the change + connection = self.dbtools_client.get_database_tools_connection(self.connection_id) + assert connection.data, "updated connection data should exist" + assert connection.data.display_name != display_name, "unexpected connection display name after update" + assert connection.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE after update but was {connection.data.lifecycle_state}" + + print(f"Updated connection. Name: {connection.data.display_name}, ocid: {self.connection_id}.") + + def validate_connection(self): + """ + Given an existing Database Tools connection, this method shows how to validate a connection by id. + For a connection to be able to route traffic to a database, it must be valid. (code == OK) + """ + print("=== DBTools Connection - Validate by id:", self.connection_id) + + validate_detail = oci.database_tools.models.ValidateDatabaseToolsConnectionMySqlDetails() + response = self.dbtools_client.validate_database_tools_connection(self.connection_id, validate_detail) + assert response, "validate_database_tools_connection should return a response" + assert response.data, "response should contain data" + + print("Validation result:", response.data) + assert response.data.code == "OK", f"validation code should be OK but was {response.data.code}" + + def do_connection_cleanup(self): + """ + Delete the Database Tools connection created by the example. + """ + if self.connection_id is None: + print("do_connection_cleanup skipped") + return + + print("=== DBTools Connection - Delete by id:", self.connection_id) + response = self.dbtools_async_client.delete_database_tools_connection_and_wait_for_state(self.connection_id, + wait_for_states=self.terminal_states) + assert response, "delete_database_tools_connection_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.status == "SUCCEEDED", f"delete connection should return status SUCCEEDED but was {response.data.status}" + + print(f"Deleted connection. ocid: {self.connection_id}.") + + def do_secrets_cleanup(self, days=2): + """ + Schedule deletion of the secrets created by the example. + """ + secret_deletion_time = datetime.now() + timedelta(days=days) + if self.password_secret_id: + print("=== DBTools Example - Schedule Secret Deletion:", self.password_secret_id) + delete_secret(clients=self.clients, secret_id=self.password_secret_id, deletion_time=secret_deletion_time) + else: + print("do_secrets_cleanup skipped (password)") + + +# +# Run DBToolsExample and print results +# +if __name__ == "__main__": + # Output Colors + OKGREEN = '\033[92m' + FAIL = '\033[91m' + ENDC = '\033[0m' + example = None + + try: + example = DBToolsExample(compartment_id, vault_id, connection_string, db_username, db_password) + + example.save_dbpassword_to_vault() + example.create_connection() + example.get_connection() + example.update_connection() + example.validate_connection() + + print(f"{OKGREEN}Python SDK test completed OK{ENDC}") + + except Exception as e: + print(f"{FAIL}Exception during tests:{ENDC} {e}") + + finally: + if do_clean_up_at_end and example is not None: + print("Starting resource clean-up.") + example.do_connection_cleanup() + example.do_secrets_cleanup() + print("Clean-up completed.") + else: + print("Skipping resource clean-up.") diff --git a/examples/database_tools/mysql_db_system_create_connection_with_pe.py b/examples/database_tools/mysql_db_system_create_connection_with_pe.py new file mode 100644 index 0000000000..d8d0b328ee --- /dev/null +++ b/examples/database_tools/mysql_db_system_create_connection_with_pe.py @@ -0,0 +1,359 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + +# ----------------------------------------------------------------------------- +# Example Use Case: MySQL DB System with Database Tools Private Endpoint +# ----------------------------------------------------------------------------- +# This example creates a Database Tools connection to a MySQL DB System +# accessible by private ip. Note, since this connection will be for a private +# ip address, a Database Tools private endpoint (PE) is required to make +# a reverse connection. This example serves as an academic exercise of the SDK. +# It is a best practice to use separate subnets for the database and the +# Database Tools PE. +# +# Prerequisites: +# +# - An existing MySQL DB System in a VCN and associated subnet +# - Available capacity (limits apply) to create a new private endpoint +# - An existing vault for storage of secrets, with at least one master key +# - A previously configured .oci/config file with a [DEFAULT] section +# - Set the following variables in the code below: +# + compartment_id : The ocid for the target compartment +# + vault_id : The ocid for a vault (to store secrets) +# + db_system_id : The ocid for a MySQL DB System +# + subnet_id : The ocid for a subnet where the DB System exists +# + db_username : The database user to connect with +# + db_password : The database password to connect with +# + connection_string : The MySQL connection string +# +# High-level Steps: +# +# 1- Create a Database Tools private endpoint +# 2- Create required secret +# 3- Create a connection using the Database Tools private endpoint +# 4- Validate the connection +# ----------------------------------------------------------------------------- + +import oci +from oci.config import from_file, validate_config +from utils.dbtools import get_dbtools_clients, get_secrets_client, get_kms_vault_client, get_vaults_clients +from utils.dbtools import create_secret, delete_secret + +import pkg_resources +import base64 +from datetime import datetime, timedelta + +# Set do_clean_up_at_end = False to keep the secret and connection created +do_clean_up_at_end = True + +# Specify compartment ocid to use. (can also use tenancy ocid if applicable) +compartment_id = "ocid1.tenancy......changeme" + +# Specify vault ocid to use. (For this example, vault must be in compartment_id and contain a master key) +vault_id = "ocid1.vault.....changeme" + +# Specify MySQL VM DB System ocid to use +db_system_id = "ocid1.mysqldbsystem......changeme" + +# Specify the MySQL DB System connection string +connection_string = "mysql://changeme-db-system-private-ip:3306/" + +# Specifiy the VCN subnet ocid where the ADB-S PE was created +subnet_id = "ocid1.subnet.....changeme" + +# Specify the database username and password +db_username = "example-username" +db_password = "example-password" + +print("Using oci version:", pkg_resources.get_distribution("oci").version) + + +class DBToolsExample: + """ + A Database Tools example that demonstrates usage of the OCI Python SDK. + """ + def __init__(self, compartment, vault, db, connection_string, subnet, username, password): + + # Load an OCI config with the DEFAULT profile + self.oci_config = from_file(file_location="~/.oci/config", profile_name="DEFAULT") + + self.compartment_id = compartment + self.vault_id = vault + self.db_system_id = db + self.subnet_id = subnet + self.connection_string = connection_string + self.db_username = username + self.db_password = password + + validate_config(self.oci_config) + + # Prepare SDK clients used in this example + self.dbtools_client, self.dbtools_async_client = get_dbtools_clients(self.oci_config) + self.vaults_client, self.vaults_async_client = get_vaults_clients(self.oci_config) + self.kms_vault_client = get_kms_vault_client(self.oci_config) + self.secrets_client = get_secrets_client(self.oci_config) + + # Dict that contains all the clients (used by utils.dbtools helpers) + self.clients = {"vaults_client": self.vaults_client, "vaults_async_client": self.vaults_async_client, + "kms_vault_client": self.kms_vault_client, + "secrets_client": self.secrets_client, + "dbtools_client": self.dbtools_client, "dbtools_async_client": self.dbtools_async_client} + + self.private_endpoint_id = None # populated at runtime + self.password_secret_id = None # populated at runtime + self.connection_id = None # populated at runtime + + # When waiting for asynchronous calls, which status is considered "done" + self.terminal_states = ["FAILED", "SUCCEEDED", "CANCELED"] + + def save_dbpassword_to_vault(self): + """ + DBTools connections don't store secrets directly. Instead, they hold a pointer to secret + stored securely in a tenancy within a Vault. + """ + print("=== DBTools Example - Save DB Password to Vault") + + db_password_secret_name = "dbtools-temp-secretp-" + datetime.utcnow().strftime("%m%d%H%M") + base64_secret_content = base64.b64encode(self.db_password.encode()).decode() + + self.password_secret_id = create_secret(oci_config=self.oci_config, + compartment_id=self.compartment_id, + vault_id=self.vault_id, + name=db_password_secret_name, + base64_secret_content=base64_secret_content, + clients=self.clients)[0] + + print(f"Created secret. Name: {db_password_secret_name}, ocid: {self.password_secret_id}") + + def get_endpoint_service(self): + """ + Get the ocid of the Database Tools endpoints service (used to create private endpoints) + """ + response = self.dbtools_client.list_database_tools_endpoint_services(self.compartment_id) + + assert response, "list_database_tools_endpoint_services should return a response" + assert response.data, "endpoint_services should return data" + assert response.data.items, "endpoint_services should contain a list of endpoints" + + # Use the first endpoint_service + endpoint_service = response.data.items[0] + assert endpoint_service.lifecycle_state == "ACTIVE", f"endpoint_service should be ACTIVE but was {endpoint_service.lifecycle_state}" + + return endpoint_service.id + + def create_private_endpoint(self): + """ + Create a Database Tools private endpoint. + """ + print("=== DBTools Example - Create Private Endpoint") + + endpoint_service_id = self.get_endpoint_service() + assert endpoint_service_id, "endpoint_service_id is required" + + display_name = "pe_pysdk_" + datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S") + description = "Test private endpoint with Python SDK" + pe_details_for_create = oci.database_tools.models.CreateDatabaseToolsPrivateEndpointDetails( + compartment_id=self.compartment_id, + endpoint_service_id=endpoint_service_id, + subnet_id=self.subnet_id, + display_name=display_name, + description=description) + + response = self.dbtools_async_client.create_database_tools_private_endpoint_and_wait_for_state( + pe_details_for_create, wait_for_states=self.terminal_states) + + assert response, "create_database_tools_private_endpoint_and_wait_for_state should return a response" + assert response.data, "create_database_tools_private_endpoint_and_wait_for_state should return data" + + status = response.data.status + self.private_endpoint_id = response.data.resources[0].identifier + assert status == "SUCCEEDED", f"create private endpoint should return status SUCCEEDED but was {status}" + + print(f"Private endpoint created. Name: {display_name}, ocid: {self.private_endpoint_id}.") + + def get_private_endpoint(self): + """ + Given an existing Database Tools private endpoint, this method shows how to get a PE by id. + """ + print("=== DBTools Private Endpoint - Get by id:", self.private_endpoint_id) + + response = self.dbtools_client.get_database_tools_private_endpoint(self.private_endpoint_id) + assert response, "get_database_tools_private_endpoint should return a response" + assert response.data, "get_database_tools_private_endpoint should return data" + assert response.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE but was {response.data.lifecycle_state}" + + print("Read created private endpoint:", response.data) + + def create_connection(self): + """ + Given the configuration details provided above, the secrets stored in the vault, + and the PE, create a Database Tools connection to the database. + """ + print("=== DBTools Example - Create Connection Using:", self.connection_string) + + related_resource = oci.database_tools.models.CreateDatabaseToolsRelatedResourceMySqlDetails( + entity_type=oci.database_tools.models.CreateDatabaseToolsRelatedResourceMySqlDetails.ENTITY_TYPE_MYSQLDBSYSTEM, + identifier=self.db_system_id) + + user_password = oci.database_tools.models.DatabaseToolsUserPasswordSecretIdDetails( + secret_id=self.password_secret_id) + + display_name = "conn_pysdk_" + datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S") + + conn_details_for_create = oci.database_tools.models.CreateDatabaseToolsConnectionMySqlDetails( + compartment_id=self.compartment_id, + connection_string=self.connection_string, + user_name=self.db_username, + user_password=user_password, + display_name=display_name, + private_endpoint_id=self.private_endpoint_id, + related_resource=related_resource) + + response = self.dbtools_async_client.create_database_tools_connection_and_wait_for_state( + conn_details_for_create, wait_for_states=self.terminal_states) + + assert response, "create_database_tools_connection_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.resources, "response data should return resources" + + status = response.data.status + assert status == "SUCCEEDED", f"create connection should return status SUCCEEDED but was {status}" + + self.connection_id = response.data.resources[0].identifier + print(f"Created connection. Name: {display_name}, ocid: {self.connection_id}.") + + def get_connection(self): + """ + Given an existing Database Tools connection, this method shows how to get a connection by id. + """ + print("=== DBTools Connection - Get by id:", self.connection_id) + + response = self.dbtools_client.get_database_tools_connection(self.connection_id) + assert response.data, "response should contain data" + assert response.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE but was {response.data.lifecycle_state}" + + print("Read created connection:", response.data) + + def update_connection(self): + """ + Given an existing Database Tools connection, this method shows how to update the connection by id. + """ + print("=== DBTools Connection - Update by id:", self.connection_id) + + connection = self.dbtools_client.get_database_tools_connection(self.connection_id) + display_name = connection.data.display_name + + connection_details_for_update = oci.database_tools.models.UpdateDatabaseToolsConnectionMySqlDetails( + display_name=display_name + "_updated") + + response = self.dbtools_async_client.update_database_tools_connection_and_wait_for_state(self.connection_id, + connection_details_for_update, + wait_for_states=self.terminal_states) + status = response.data.status + assert status == "SUCCEEDED", f"update connection should return status SUCCEEDED but was {status}" + + # After update, get the connection again and confirm the change + connection = self.dbtools_client.get_database_tools_connection(self.connection_id) + assert connection.data, "updated connection data should exist" + assert connection.data.display_name != display_name, "unexpected connection display name after update" + assert connection.data.lifecycle_state == "ACTIVE", f"lifecycle_state should be ACTIVE after update but was {connection.data.lifecycle_state}" + + print(f"Updated connection. Name: {connection.data.display_name}, ocid: {self.connection_id}.") + + def validate_connection(self): + """ + Given an existing Database Tools connection, this method shows how to validate a connection by id. + For a connection to be able to route traffic to a database, it must be valid. (code == OK) + """ + print("=== DBTools Connection - Validate by id:", self.connection_id) + + validate_detail = oci.database_tools.models.ValidateDatabaseToolsConnectionMySqlDetails() + response = self.dbtools_client.validate_database_tools_connection(self.connection_id, validate_detail) + assert response, "validate_database_tools_connection should return a response" + assert response.data, "response should contain data" + + print("Validation result:", response.data) + assert response.data.code == "OK", f"validation code should be OK but was {response.data.code}" + + def do_connection_cleanup(self): + """ + Delete the Database Tools connection created by the example. + """ + if self.connection_id is None: + print("do_connection_cleanup skipped") + return + + print("=== DBTools Connection - Delete by id:", self.connection_id) + response = self.dbtools_async_client.delete_database_tools_connection_and_wait_for_state(self.connection_id, + wait_for_states=self.terminal_states) + assert response, "delete_database_tools_connection_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.status == "SUCCEEDED", f"delete connection should return status SUCCEEDED but was {response.data.status}" + + print(f"Deleted connection. ocid: {self.connection_id}.") + + def do_private_endpoint_cleanup(self): + """ + Delete the Database Tools private endpoint created by the example. + """ + if self.private_endpoint_id is None: + print("do_private_endpoint_cleanup skipped") + return + + print("=== DBTools Private Endpoint - Delete by id:", self.private_endpoint_id) + response = self.dbtools_async_client.delete_database_tools_private_endpoint_and_wait_for_state(self.private_endpoint_id, + wait_for_states=self.terminal_states) + assert response, "delete_database_tools_private_endpoint_and_wait_for_state should return a response" + assert response.data, "response should contain data" + assert response.data.status == "SUCCEEDED", f"delete private endpoint should return status SUCCEEDED but was {response.data.status}" + + print(f"Deleted private endpoint. ocid: {self.private_endpoint_id}.") + + def do_secrets_cleanup(self, days=2): + """ + Schedule deletion of the secrets created by the example. + """ + secret_deletion_time = datetime.now() + timedelta(days=days) + if self.password_secret_id: + print("=== DBTools Example - Schedule Secret Deletion:", self.password_secret_id) + delete_secret(clients=self.clients, secret_id=self.password_secret_id, deletion_time=secret_deletion_time) + else: + print("do_secrets_cleanup skipped (password)") + + +# +# Run DBToolsExample and print results +# +if __name__ == "__main__": + # Output Colors + OKGREEN = '\033[92m' + FAIL = '\033[91m' + ENDC = '\033[0m' + example = None + + try: + example = DBToolsExample(compartment_id, vault_id, db_system_id, connection_string, subnet_id, db_username, db_password) + + example.create_private_endpoint() + example.get_private_endpoint() + example.save_dbpassword_to_vault() + example.create_connection() + example.get_connection() + example.update_connection() + example.validate_connection() + + print(f"{OKGREEN}Python SDK test completed OK{ENDC}") + + except Exception as e: + print(f"{FAIL}Exception during tests:{ENDC} {e}") + + finally: + if do_clean_up_at_end and example is not None: + print("Starting resource clean-up.") + example.do_connection_cleanup() + example.do_secrets_cleanup() + example.do_private_endpoint_cleanup() + print("Clean-up completed.") + else: + print("Skipping resource clean-up.") diff --git a/examples/database_tools/readme.md b/examples/database_tools/readme.md index 805b2242ca..d4bb9b06b3 100644 --- a/examples/database_tools/readme.md +++ b/examples/database_tools/readme.md @@ -1,18 +1,20 @@ # Database Tools Examples ## Introduction -We show 3 Use Cases for the Database Tools Service +We show 5 use cases for the Database Tools service ## Use Cases -- ADB-S with Public IP -- ADB-S with Private Endpoint -- Bare Metal, VM and Exadata with Private IP +- ADB-S with public ip +- ADB-S with private endpoint +- Bare Metal, VM and Exadata with private ip +- MySQL with public ip +- MySQL DB System with private endpoint ## ADB-S with Public IP ![](images/ADB-S.with.Public.IP.png) ### Example See: **adbs_create_connection_public_ip.py** where we: -1. Create a new Autonomous Database +1. Create a new Autonomous Database (ADB-S) 2. Create required secrets 3. Create a connection 4. Validate the connection @@ -21,16 +23,33 @@ See: **adbs_create_connection_public_ip.py** where we: ![](images/ADB-S.with.Private.Endpoint.png) ### Example See: **adbs_create_connection_with_pe.py** where we: -1. Create a Database Tools Private Endpoint for a Reverse Connection to the Private Endpoint of an ADB-S +1. Create a Database Tools private endpoint 2. Create required secrets -3. Create a connection +3. Create a connection using the Database Tools private endpoint 4. Validate the connection ## Bare Metal, DB System and Exadata with Private IP ![](images/Bare.Metal.VM.Exadata.with.Private.IP.png) ### Example See: **db_system_create_connection_private_subnet.py** where we: -1. Create a Database Tools Private Endpoint for a Reverse Connection to a VM DB System -2. Create required secrets -3. Create a connection -4. Validate the connection \ No newline at end of file +1. Create a Database Tools private endpoint +2. Create required secret +3. Create a connection using the Database Tools private endpoint +4. Validate the connection + +## MySQL with Public IP +![](images/MySQL.with.Public.IP.png) +### Example +See: **mysql_create_connection_public_ip.py** where we: +1. Create required secret +2. Create a connection +3. Validate the connection + +## MySQL DB System with Private Edpoint +![](images/MySQL.DB.System.with.PE.png) +### Example +See: **mysql_db_system_create_connection_with_pe.py** where we: +1. Create a Database Tools private endpoint +2. Create required secret +3. Create a connection using the Database Tools private endpoint +4. Validate the connection diff --git a/examples/database_tools/utils/dbtools.py b/examples/database_tools/utils/dbtools.py index daaec69e77..40ad0d9a0d 100644 --- a/examples/database_tools/utils/dbtools.py +++ b/examples/database_tools/utils/dbtools.py @@ -77,7 +77,7 @@ def extract_vault_first_master_key(oci_config, compartment_id, clients, vault_id return vault_key_id -def create_secret(oci_config, compartment_id: str, clients, vault_id: str, name: str, base64_password: str, vault_key_id: str = None): +def create_secret(oci_config, compartment_id: str, clients, vault_id: str, name: str, base64_secret_content: str, vault_key_id: str = None): """ Create a secret using the specified name. The content is in base64Secret. If a secret with that name already exists, we simply return its OCID. @@ -105,7 +105,7 @@ def create_secret(oci_config, compartment_id: str, clients, vault_id: str, name: compartment_id=compartment_id, secret_name=name, secret_content=oci.vault.models.Base64SecretContentDetails( - content=base64_password + content=base64_secret_content ) ) @@ -158,7 +158,7 @@ def get_wallet_and_create_secrets(oci_config, compartment_id, clients, autonomou # 2. Extract Wallet from DB # Create a wallet details object db_wallet = oci.database.models.GenerateAutonomousDatabaseWalletDetails( - password="example-password" + password="Change-Example-Passw0rd!" ) print("Extracting Wallet...") @@ -186,7 +186,7 @@ def get_wallet_and_create_secrets(oci_config, compartment_id, clients, autonomou clients=clients, vault_id=vault_id, name=db_wallet_secret_name, - base64_password=base64_sso_str) + base64_secret_content=base64_sso_str) # 4. Store the DB password in the vault as a secret under name X. If name X already exists, we will simply use it. base64_db_password_str = base64.b64encode(db_password.encode()).decode() @@ -196,6 +196,6 @@ def get_wallet_and_create_secrets(oci_config, compartment_id, clients, autonomou vault_id=vault_id, vault_key_id=vault_key_id, name=db_password_secret_name, - base64_password=base64_db_password_str) + base64_secret_content=base64_db_password_str) return wallet_secret_id, password_secret_id diff --git a/examples/list_resources_in_tenancy/README.md b/examples/list_resources_in_tenancy/README.md index 509584884b..7771ed8d5c 100644 --- a/examples/list_resources_in_tenancy/README.md +++ b/examples/list_resources_in_tenancy/README.md @@ -8,13 +8,10 @@ Several utilities to help with producing reports from OCI ## Executing using Cloud Shell: ``` - 1. install oci sdk package - pip3 install --user oci - - 2. clone the oci sdk repo + 1. clone the oci sdk repo git clone https://github.com/oracle/oci-python-sdk - 3. Execute + 2. Execute cd $HOME/oci-python-sdk/examples/list_resources_in_tenancy python3 list_all_ipsec_tunnels_in_tenancy.py -dt python3 list_all_virtual_circuits_in_tenancy.py -dt @@ -22,8 +19,9 @@ Several utilities to help with producing reports from OCI python3 list_dbsystem_with_maintenance_in_tenancy.py -dt python3 list_bv_backups_in_tenancy.py -dt python3 list_limits_per_compartments.py -dt + python3 list_databases_shapes_in_tenancy.py -dt -csv output.csv - 4. Help with --help + 3. Help with --help ``` ## list_all_ipsec_tunnels_in_tenancy.py @@ -114,13 +112,14 @@ optional arguments: -t CONFIG_PROFILE Config Profile inside the config file -p PROXY Set Proxy (i.e. www-proxy-server.com:80) -rg FILTER_REGION filter by region (i.e. us-ashburn-1) - -cp FILTER_COMP filter by compartment (i.e. production) + -cp FILTER_COMP filter by compartment (i.e. production or root) -sr FILTER_SERVICE filter by service (i.e. compute) -sc FILTER_SCOPE filter by scope (i.e. AD,REGION,GLOBAL) -ip Use Instance Principals for Authentication -dt Use Delegation Token for Authentication -js print in JSON format -csv CSV Output to CSV files, Input as file header + -all show all limits without filter those with zero ``` @@ -170,4 +169,30 @@ optional arguments: -rg FILTER_REGION filter by Region -js print in JSON format -csv CSV Output to CSV files, Input as file header +``` + +## list_databases_shapes_in_tenancy.py +Produce list of databases in tenancy with shape information + +``` +usage: list_databases_shapes_in_tenancy.py [-h] [-c CONFIG_FILE] + [-t CONFIG_PROFILE] [-p PROXY] + [-ip] [-is] [-dt] + [-rg FILTER_REGION] + [-cp FILTER_COMPN] + [-cr FILTER_COMPR] [-js] [-csv CSV] + +optional arguments: + -h, --help show this help message and exit + -c CONFIG_FILE OCI CLI Config file + -t CONFIG_PROFILE Config file section to use (tenancy profile) + -p PROXY Set Proxy (i.e. www-proxy-server.com:80) + -ip Use Instance Principals for Authentication + -is Use Security Token for Authentication + -dt Use Delegation Token for Authentication + -rg FILTER_REGION filter by region (i.e. us-ashburn-1) + -cp FILTER_COMPN filter by compartment Name or Id + -cr FILTER_COMPR filter by compartment Path + -js print in JSON format + -csv CSV Output to CSV file, Input as file name ``` \ No newline at end of file diff --git a/examples/list_resources_in_tenancy/how_to_run_in_cloud_shell.rst b/examples/list_resources_in_tenancy/how_to_run_in_cloud_shell.rst index 4db98938a9..268561457b 100644 --- a/examples/list_resources_in_tenancy/how_to_run_in_cloud_shell.rst +++ b/examples/list_resources_in_tenancy/how_to_run_in_cloud_shell.rst @@ -4,13 +4,10 @@ Executing using Cloud Shell: .. code-block:: - 1. install oci sdk package - pip3 install --user oci - - 2. clone the oci sdk repo + 1. clone the oci sdk repo git clone https://github.com/oracle/oci-python-sdk - 3. Execute + 2. Execute cd $HOME/oci-python-sdk/examples/list_resources_in_tenancy python3 list_all_ipsec_tunnels_in_tenancy.py -dt python3 list_all_virtual_circuits_in_tenancy.py -dt @@ -20,7 +17,8 @@ Executing using Cloud Shell: python3 list_limits_per_compartments.py -dt python3 list_policies_in_tenancy.py -dt python3 list_all_capacity_reservations_in_tenancy.py -dt + python3 list_databases_shapes_in_tenancy.py -dt -csv output.csv - 4. Help with --help + 3. Help with --help diff --git a/examples/list_resources_in_tenancy/list_databases_shapes_in_tenancy.py b/examples/list_resources_in_tenancy/list_databases_shapes_in_tenancy.py new file mode 100644 index 0000000000..75f0cf1a0a --- /dev/null +++ b/examples/list_resources_in_tenancy/list_databases_shapes_in_tenancy.py @@ -0,0 +1,775 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + +########################################################################## +# list_databases_shapes_in_tenancy.py +# +# @author: Adi Zohar +# +# Supports Python 3 +# +# DISCLAIMER – This is not an official Oracle application, It does not supported by Oracle Support, It should NOT be used for utilization calculation purposes +########################################################################## +# Info: +# List all databases shapes in tenancy, it includes, dbsystems, exacs , exacc and autonomous +# +# Connectivity: +# Option 1 - User Authentication +# $HOME/.oci/config, please follow - https://docs.cloud.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm +# OCI user part of ListDBSystemGroup group with below Policy rules: +# Allow group ListDBSystemGroup to inspect compartments in tenancy +# Allow group ListDBSystemGroup to inspect tenancies in tenancy +# Allow group ListDBSystemGroup to read database-family in tenancy +# +# Option 2 - Instance Principle +# Compute instance part of DynListDBSystemGroup dynamic group with policy rules: +# Allow dynamic group DynListDBSystemGroup to inspect compartments in tenancy +# Allow dynamic group DynListDBSystemGroup to inspect tenancies in tenancy +# Allow dynamic group DynListDBSystemGroup to read database-family in tenancy +# +########################################################################## +# Application Command line parameters +# +# -c config - OCI CLI Config +# -t config - Config file section to use (tenancy profile) +# -p proxy - Set Proxy (i.e. www-proxy-server.com:80) +# -ip - Use Instance Principals for Authentication +# -is - Use session token for Authentication +# -dt - Use Instance Principals with delegation token for cloud shell +# -rg region - Filter Region +# -cp compart - Filter by Compartment +# -cr compart - Filter by Comcpartment Path +# -js output as JSON +# -csv FILE output to CSV and Screen +# +########################################################################## + +from __future__ import print_function +import sys +import argparse +import datetime +import oci +import json +import os +import csv +import time +import platform + +version = "2022.08.23" + + +########################################################################## +# Print header centered +########################################################################## +def print_header(name, category=0): + options = {0: 120, 1: 100, 2: 90, 3: 85} + chars = int(options[category]) + print("") + print('#' * chars) + print("#" + name.center(chars - 2, " ") + "#") + print('#' * chars) + + +########################################################################## +# check service error to warn instead of error +########################################################################## +def check_service_error(code): + return ('max retries exceeded' in str(code).lower() or + 'auth' in str(code).lower() or + 'notfound' in str(code).lower() or + code == 'Forbidden' or + code == 'TooManyRequests' or + code == 'IncorrectState' or + code == 'LimitExceeded' + ) + + +########################################################################## +# Create signer for Authentication +# Input - config_profile and is_instance_principals and is_delegation_token +# Output - config and signer objects +########################################################################## +def create_signer(config_file, config_profile, is_instance_principals, is_delegation_token, is_security_token): + + # if instance principals authentications + if is_instance_principals: + try: + signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner() + config = {'region': signer.region, 'tenancy': signer.tenancy_id} + return config, signer + + except Exception: + print_header("Error obtaining instance principals certificate, aborting") + raise SystemExit + + if is_security_token: + try: + # create signer from config and security token + config = oci.config.from_file( + (config_file if config_file else oci.config.DEFAULT_LOCATION), + (config_profile if config_profile else oci.config.DEFAULT_PROFILE) + ) + security_token_file = config.get("security_token_file") + token = None + with open(security_token_file, 'r') as f: + token = f.read() + private_key = oci.signer.load_private_key_from_file(config['key_file']) + signer = oci.auth.signers.SecurityTokenSigner(token, private_key) + return config, signer + + except Exception: + print_header("Error obtaining instance principals certificate, aborting") + raise SystemExit + + # ----------------------------- + # Delegation Token + # ----------------------------- + elif is_delegation_token: + + try: + # check if env variables OCI_CONFIG_FILE, OCI_CONFIG_PROFILE exist and use them + env_config_file = os.environ.get('OCI_CONFIG_FILE') + env_config_section = os.environ.get('OCI_CONFIG_PROFILE') + + # check if file exist + if env_config_file is None or env_config_section is None: + print("*** OCI_CONFIG_FILE and OCI_CONFIG_PROFILE env variables not found, abort. ***") + print("") + raise SystemExit + + # check if file exist + if not os.path.isfile(env_config_file): + print("*** Config File " + env_config_file + " does not exist, Abort. ***") + print("") + raise SystemExit + + config = oci.config.from_file(env_config_file, env_config_section) + delegation_token_location = config["delegation_token_file"] + + with open(delegation_token_location, 'r') as delegation_token_file: + delegation_token = delegation_token_file.read().strip() + # get signer from delegation token + signer = oci.auth.signers.InstancePrincipalsDelegationTokenSigner(delegation_token=delegation_token) + + return config, signer + + except KeyError: + print("* Key Error obtaining delegation_token_file") + raise SystemExit + + except Exception: + raise + + # ----------------------------- + # config file authentication + # ----------------------------- + else: + config = oci.config.from_file( + (config_file if config_file else oci.config.DEFAULT_LOCATION), + (config_profile if config_profile else oci.config.DEFAULT_PROFILE) + ) + signer = oci.signer.Signer( + tenancy=config["tenancy"], + user=config["user"], + fingerprint=config["fingerprint"], + private_key_file_location=config.get("key_file"), + pass_phrase=oci.config.get_config_value_or_default(config, "pass_phrase"), + private_key_content=config.get("key_content") + ) + return config, signer + + +########################################################################## +# Load compartments +########################################################################## +def identity_read_compartments(identity, tenancy, filter_by_compartment_name, filter_by_compartment_path): + + return_compartments = [] + print("Loading Compartments...") + + try: + # read all compartments to variable + all_compartments = [] + try: + all_compartments = oci.pagination.list_call_get_all_results( + identity.list_compartments, + tenancy.id, + compartment_id_in_subtree=True, + retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY + ).data + + except oci.exceptions.ServiceError as e: + raise RuntimeError("Error in identity_read_compartments: " + str(e.args)) + + ################################################### + # Build Compartments + # return nested compartment list + ################################################### + def build_compartments_nested(identity_client, cid, path): + try: + compartment_list = [item for item in all_compartments if str(item.compartment_id) == str(cid)] + + if path != "": + path = path + " / " + + for c in compartment_list: + if c.lifecycle_state == oci.identity.models.Compartment.LIFECYCLE_STATE_ACTIVE: + cvalue = { + 'id': str(c.id), + 'name': str(c.name), + 'description': str(c.description), + 'time_created': str(c.time_created), + 'is_accessible': str(c.is_accessible), + 'path': path + str(c.name) + } + return_compartments.append(cvalue) + build_compartments_nested(identity_client, c.id, cvalue['path']) + + except Exception as error: + raise Exception("Error in build_compartments_nested: " + str(error.args)) + + ################################################### + # Add root compartment + ################################################### + try: + tenc = identity.get_compartment(tenancy.id).data + if tenc: + cvalue = { + 'id': str(tenc.id), + 'name': str(tenc.name), + 'description': str(tenc.description), + 'time_created': str(tenc.time_created), + 'is_accessible': str(tenc.is_accessible), + 'path': "/ " + str(tenc.name) + " (root)" + } + return_compartments.append(cvalue) + except Exception as error: + raise Exception("Error in add_tenant_compartment: " + str(error.args)) + + # Build the compartments + build_compartments_nested(identity, tenancy.id, "") + + # sort the compartment + sorted_compartments = sorted(return_compartments, key=lambda k: k['path']) + + # if not filtered by compartment return + if not (filter_by_compartment_name or filter_by_compartment_path): + print(str(len(sorted_compartments)) + " Compartments Loaded") + return sorted_compartments + + filtered_compart = [] + + # if filter by compartment, then reduce list and return new list + if filter_by_compartment_name: + for x in sorted_compartments: + if filter_by_compartment_name in x['name'] or filter_by_compartment_name in x['id']: + filtered_compart.append(x) + + # if filter by path compartment path, then reduce list and return new list + if filter_by_compartment_path: + for x in sorted_compartments: + if filter_by_compartment_path in x['path']: + filtered_compart.append(x) + + print(str(len(filtered_compart)) + " Filtered Compartments Loaded") + return filtered_compart + + except oci.exceptions.RequestException: + raise + except Exception as e: + raise Exception("Error in identity_read_compartments: " + str(e.args)) + + +########################################################################## +# get_license_model +########################################################################## +def get_license_model(license_model): + if license_model == "LICENSE_INCLUDED": + return "INCL" + elif license_model == "BRING_YOUR_OWN_LICENSE": + return "BYOL" + else: + return license_model + + +########################################################################## +# get_database_edition +########################################################################## +def get_database_edition(database_edition): + if database_edition == "ENTERPRISE_EDITION": + return "EE" + elif database_edition == "ENTERPRISE_EDITION_EXTREME_PERFORMANCE": + return "XP" + elif database_edition == "ENTERPRISE_EDITION_HIGH_PERFORMANCE": + return "HP" + elif database_edition == "STANDARD_EDITION": + return "SE" + else: + return database_edition + + +########################################################################## +# Print databases on screen +########################################################################## +def print_databases(databases_data): + + try: + if not databases_data: + return + + for region in databases_data: + reg_name = region['region_name'] + databases = region['data'] + print_header("Region " + reg_name, 0) + + sorted_databases = sorted(databases, key=lambda i: i['compartment_name']) + print("Compartment Display Name DB Name Lifecycle Shape OCPUs Nodes Lic Edition") + print("------------------------- ------------------------- ------------------------- ------------- ------------------------- ----------------- ----------------- ----- -------------------") + + for ct in sorted_databases: + compartment_name = str(ct['compartment_name']).ljust(25) + " " + display_name = str(ct['display_name']).ljust(25) + " " + db_name = str(ct['db_name']).ljust(25) + " " + shape = str(ct['shape']).ljust(25) + " " + cpu_core_count = "OCPUs: " + str(ct['cpu_core_count']).ljust(10) + " " + node_count = "Nodes: " + str(ct['node_count']).ljust(10) + " " + lifecycle_state = str(ct['lifecycle_state']).ljust(13) + " " + license_model = str(ct['license_model']).ljust(6) + database_edition = str(ct['database_edition']).ljust(6) + + print(compartment_name + display_name + db_name + lifecycle_state + shape + cpu_core_count + node_count + license_model + database_edition) + + print("") + print("") + + except Exception as e: + raise RuntimeError("Error in print_databases: " + str(e.args)) + + +########################################################################## +# create csv file +########################################################################## +def export_to_csv_file(file_name, database_data): + + csv_data = [] + + try: + for region in database_data: + databases = region['data'] + sorted_databases = sorted(databases, key=lambda i: i['compartment_name']) + + for ct in sorted_databases: + csv_data.append(ct) + + # if no data + if len(csv_data) == 0: + return + + # prepare keys and data + result = [dict(item) for item in csv_data] + fields = [key for key in result[0].keys()] + + with open(file_name, mode='w', newline='') as csv_file: + writer = csv.DictWriter(csv_file, fieldnames=fields) + + # write header + writer.writeheader() + + for row in result: + writer.writerow(row) + + print("") + print("Extracted to CSV file : --> " + file_name) + + except Exception as e: + raise Exception("Error in export_to_csv_file: " + str(e.args)) + + +########################################################################## +# load_databases +########################################################################## +def load_dbsystems_exadatas_databases(database_client, region_name, compartment, num): + global warnings + local_data = [] + try: + + start_time = time.time() + str_num = str(str(num) + ".").ljust(4) + print(" " + str_num + " Compartment " + (str(compartment['path']) + "... ").ljust(50), end="") + cnt = 0 + + # Get Database homes + homes = [] + try: + homes = oci.pagination.list_call_get_all_results( + database_client.list_db_homes, + compartment['id'], + retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY + ).data + + except oci.exceptions.ServiceError as e: + if check_service_error(e.code): + warnings += 1 + print("Warnings ") + return + raise + + # Loop on database homes + for db_home in homes: + if (db_home.lifecycle_state == "TERMINATED" or db_home.lifecycle_state == "TERMINATING" or db_home.lifecycle_state == "FAILED"): + continue + + list_databases = [] + try: + list_databases = oci.pagination.list_call_get_all_results( + database_client.list_databases, + compartment_id=compartment['id'], + db_home_id=db_home.id, + sort_by="DBNAME", + retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY + ).data + + except oci.exceptions.ServiceError as e: + if check_service_error(e.code): + warnings += 1 + print("Warnings ") + return local_data + raise + + # loop on the databases inside the home + # dbs = oci.database.models.DatabaseSummary + for dbs in list_databases: + if dbs.lifecycle_state == "TERMINATED" or dbs.lifecycle_state == "TERMINATING" or dbs.lifecycle_state == "FAILED": + continue + + value = { + 'tenant': str(tenancy.name), + 'region_name': region_name, + 'compartment_id': str(compartment['id']), + 'compartment_path': str(compartment['path']), + 'compartment_name': str(compartment['name']), + 'id': str(dbs.id), + 'display_name': "", + 'db_name': str(dbs.db_name), + 'db_unique_name': str(dbs.db_unique_name), + 'db_workload': str(dbs.db_workload), + 'time_created': str(dbs.time_created), + 'lifecycle_state': str(dbs.lifecycle_state), + 'db_system_id': str(dbs.db_system_id), + 'vm_cluster_id': str(dbs.vm_cluster_id), + 'home_version': str(db_home.db_version), + 'type': "", + 'shape': "", + 'cpu_core_count': "", + 'node_count': "", + 'version': "", + 'hostname': "", + 'cluster_name': "", + 'database_edition': "", + 'license_model': "", + 'role': "", + 'adb_auto_scaling_enabled': "", + 'error': "", + 'extract_date': str(datetime.datetime.now().strftime("%Y-%m-%d")) + } + + #################### + # if VM Cluster + #################### + if dbs.vm_cluster_id: + # ExaCS + if "cloudvmcluster" in dbs.vm_cluster_id or "dbsystem" in dbs.vm_cluster_id: + try: + vm = database_client.get_cloud_vm_cluster( + dbs.vm_cluster_id, + retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY + ).data + + value['type'] = "ExaCS" + value['shape'] = str(vm.shape) + value['display_name'] = str(vm.display_name) + value['cpu_core_count'] = str(vm.cpu_core_count) + value['node_count'] = ("" if vm.node_count is None else str(vm.node_count)) + value['version'] = str(vm.gi_version) + value['cluster_name'] = str(vm.cluster_name) + value['license_model'] = get_license_model(vm.license_model) + value['database_edition'] = "XP" + + except oci.exceptions.ServiceError as e: + print("W", end="") + warnings += 1 + value['error'] = str(e) + else: + try: + #################### + # EdxaCC + #################### + vm = database_client.get_vm_cluster( + dbs.vm_cluster_id, + retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY + ).data + + value['type'] = "ExaCC" + value['shape'] = str(vm.shape) + value['display_name'] = str(vm.display_name) + value['cpu_core_count'] = str(vm.cpus_enabled) + value['node_count'] = str(len(vm.db_servers)) + value['version'] = str(vm.gi_version) + value['cluster_name'] = str(vm.display_name) + value['license_model'] = get_license_model(vm.license_model) + value['database_edition'] = "XP" + + except oci.exceptions.ServiceError as e: + print("W", end="") + warnings += 1 + value['error'] = str(e) + + #################### + # if DB SystemId + #################### + if dbs.db_system_id and not dbs.vm_cluster_id: + try: + vm = database_client.get_db_system( + dbs.db_system_id, + retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY + ).data + value['type'] = "DBSystem" + value['shape'] = str(vm.shape) + value['display_name'] = str(vm.display_name) + value['cpu_core_count'] = str(vm.cpu_core_count) + value['node_count'] = ("" if vm.node_count is None else str(vm.node_count)) + value['version'] = ("" if vm.version is None else str(vm.version)) + value['cluster_name'] = ("" if vm.cluster_name is None else str(vm.cluster_name)) + value['license_model'] = get_license_model(vm.license_model) + value['database_edition'] = get_database_edition(vm.database_edition) + + except oci.exceptions.ServiceError as e: + print("W", end="") + warnings += 1 + value['error'] = str(e) + + # add the data + cnt += 1 + local_data.append(value) + + # print total and time for the compartment + et = time.time() - start_time + print(" (" + str(cnt) + ") - "'{:02d}:{:02d}:{:02d}'.format(round(et // 3600), (round(et % 3600 // 60)), round(et % 60))) + + # return data + return local_data + + except Exception as e: + raise RuntimeError("\nError extracting databases in load_databases - " + str(e)) + + +########################################################################## +# load_databases +########################################################################## +def load_autonomous_databases(database_client, region_name, compartment, num): + global warnings + local_data = [] + try: + + start_time = time.time() + str_num = str(str(num) + ".").ljust(4) + print(" " + str_num + " Compartment " + (str(compartment['path']) + "... ").ljust(50), end="") + cnt = 0 + + list_databases = [] + try: + list_databases = oci.pagination.list_call_get_all_results( + database_client.list_autonomous_databases, + compartment['id'], + sort_by="DISPLAYNAME", + retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY + ).data + + except oci.exceptions.ServiceError as e: + if check_service_error(e.code): + warnings += 1 + print("Warnings ") + return + raise + + # loop on the databases + # dbs = oci.database.models.AutonomousDatabaseSummary + for dbs in list_databases: + if dbs.lifecycle_state == oci.database.models.AutonomousDatabaseSummary.LIFECYCLE_STATE_TERMINATED or dbs.lifecycle_state == oci.database.models.AutonomousDatabaseSummary.LIFECYCLE_STATE_UNAVAILABLE: + continue + + value = { + 'tenant': str(tenancy.name), + 'region_name': region_name, + 'compartment_id': str(compartment['id']), + 'compartment_path': str(compartment['path']), + 'compartment_name': str(compartment['name']), + 'id': str(dbs.id), + 'display_name': str(dbs.display_name), + 'db_name': str(dbs.db_name), + 'db_unique_name': "", + 'db_workload': str(dbs.db_workload), + 'time_created': str(dbs.time_created), + 'lifecycle_state': str(dbs.lifecycle_state), + 'db_system_id': "", + 'vm_cluster_id': "", + 'home_version': "", + 'type': "Autonomous", + 'shape': "ADB-D" if dbs.is_dedicated else "ADB-S", + 'cpu_core_count': str(dbs.cpu_core_count), + 'node_count': "-", + 'version': str(dbs.db_version), + 'hostname': "", + 'cluster_name': "", + 'role': str(dbs.role), + 'database_edition': get_database_edition(str(dbs.database_edition)), + 'license_model': get_license_model(dbs.license_model), + 'adb_auto_scaling_enabled': str(dbs.is_auto_scaling_enabled), + 'error': "", + 'extract_date': str(datetime.datetime.now().strftime("%Y-%m-%d")) + } + + # add the data + cnt += 1 + local_data.append(value) + + # print total and time for the compartment + et = time.time() - start_time + print(" (" + str(cnt) + ") - "'{:02d}:{:02d}:{:02d}'.format(round(et // 3600), (round(et % 3600 // 60)), round(et % 60))) + return local_data + + except Exception as e: + raise RuntimeError("\nError extracting databases in load_autonomous - " + str(e)) + + +########################################################################## +# Main +########################################################################## + +# Get Command Line Parser +parser = argparse.ArgumentParser() +parser.add_argument('-c', default="", dest='config_file', help='OCI CLI Config file') +parser.add_argument('-t', default="", dest='config_profile', help='Config file section to use (tenancy profile)') +parser.add_argument('-p', default="", dest='proxy', help='Set Proxy (i.e. www-proxy-server.com:80) ') +parser.add_argument('-ip', default=False, action='store_true', dest='is_instance_principals', help='Use Instance Principals for Authentication') +parser.add_argument('-is', default=False, action='store_true', dest='is_security_token', help='Use Security Token for Authentication') +parser.add_argument('-dt', default=False, action='store_true', dest='is_delegation_token', help='Use Delegation Token for Authentication') +parser.add_argument('-rg', default="", dest='filter_region', help='filter by region (i.e. us-ashburn-1) ') +parser.add_argument('-cp', default="", dest='filter_compn', help='filter by compartment Name or Id') +parser.add_argument('-cr', default="", dest='filter_compr', help='filter by compartment Path') +parser.add_argument('-js', default=False, action='store_true', dest='print_json', help='print in JSON format') +parser.add_argument('-csv', default="", dest='csv', help="Output to CSV file, Input as file name") +cmd = parser.parse_args() + +# Start print time info +start_time = str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) +print("########################################################################################################################") +print("# Running List Database Shapes in Tenancy #") +print("# #") +print("# Written By Adi Zohar, Aug 2022 #") +print("# You can filter by region or compartment to run faster, please check --help for help #") +print("# #") +print("# DISCLAIMER – This is not an official Oracle application, It does not supported by Oracle Support #") +print("# It should NOT be used for billing utilization calculation purposes #") +print("########################################################################################################################") +print("Date/Time : " + str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) +print("Program : " + "list_databases_shapes_in_tenancy.py") +print("Machine : " + platform.node() + " (" + platform.machine() + ")") +print("Python Version : " + platform.python_version()) +print("App Version : " + version) +print("OCI SDK Version : " + oci.version.__version__) +print("Command Line : " + ' '.join(x for x in sys.argv[1:])) + +# Identity extract compartments +config, signer = create_signer(cmd.config_file, cmd.config_profile, cmd.is_instance_principals, cmd.is_delegation_token, cmd.is_security_token) +compartments = [] +filter_region = cmd.filter_region +filter_compartment_name = cmd.filter_compn +filter_compartment_path = cmd.filter_compr +print_json = cmd.print_json +data = [] +warnings = 0 +tenancy = None + +try: + print("\nConnecting to Identity Service...") + identity = oci.identity.IdentityClient(config, signer=signer) + if cmd.proxy: + identity.base_client.session.proxies = {'https': cmd.proxy} + + tenancy = identity.get_tenancy(config["tenancy"]).data + regions = identity.list_region_subscriptions(tenancy.id).data + + print("Tenant Name : " + str(tenancy.name)) + print("Tenant Id : " + tenancy.id) + print("") + + compartments = identity_read_compartments(identity, tenancy, filter_compartment_name, filter_compartment_path) + +except Exception as e: + raise RuntimeError("\nError extracting compartments section - " + str(e)) + + +############################################ +# Loop on all regions +############################################ +print("\nLoading DBSystems and Exadatas...") +main_data = [] +warnings = 0 + +for region_name in [str(es.region_name) for es in regions]: + if filter_region and str(filter_region) not in region_name: + continue + + region_data = [] + + print("\nRegion " + region_name + "...\n") + + # set the region in the config and signer + config['region'] = region_name + signer.region = region_name + + # connect to virtual_network + database_client = oci.database.DatabaseClient(config, signer=signer) + if cmd.proxy: + database_client.base_client.session.proxies = {'https': cmd.proxy} + + ############################################ + # Running on DBSystems and Exadatas + ############################################ + print(" Running on DBSystems and Exadatas...") + for num, compartment in enumerate(compartments, start=1): + compartment_data = load_dbsystems_exadatas_databases(database_client, region_name, compartment, num) + region_data.extend(compartment_data) + + ############################################ + # Running on Autonomous Databases + ############################################ + print("") + print(" Running on Autonomous Databases...") + for num, compartment in enumerate(compartments, start=1): + + compartment_data = load_autonomous_databases(database_client, region_name, compartment, num) + region_data.extend(compartment_data) + + main_data.append({ + 'region_name': region_name, + 'data': region_data + }) + +############################################ +# Print Output as JSON +############################################ +print_header("Output") +if cmd.csv: + print_databases(main_data) + export_to_csv_file(cmd.csv, main_data) +elif print_json: + print(json.dumps(main_data, indent=4, sort_keys=False)) +else: + print_databases(main_data) + +if warnings > 0: + print_header(str(warnings) + " Warnings appeared") +print_header("Completed at " + str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) diff --git a/src/oci/analytics/models/__init__.py b/src/oci/analytics/models/__init__.py index a3a14e488b..0bf005d812 100644 --- a/src/oci/analytics/models/__init__.py +++ b/src/oci/analytics/models/__init__.py @@ -16,6 +16,7 @@ from .private_access_channel import PrivateAccessChannel from .private_endpoint_details import PrivateEndpointDetails from .private_source_dns_zone import PrivateSourceDnsZone +from .private_source_scan_host import PrivateSourceScanHost from .public_endpoint_details import PublicEndpointDetails from .scale_analytics_instance_details import ScaleAnalyticsInstanceDetails from .set_kms_key_details import SetKmsKeyDetails @@ -44,6 +45,7 @@ "PrivateAccessChannel": PrivateAccessChannel, "PrivateEndpointDetails": PrivateEndpointDetails, "PrivateSourceDnsZone": PrivateSourceDnsZone, + "PrivateSourceScanHost": PrivateSourceScanHost, "PublicEndpointDetails": PublicEndpointDetails, "ScaleAnalyticsInstanceDetails": ScaleAnalyticsInstanceDetails, "SetKmsKeyDetails": SetKmsKeyDetails, diff --git a/src/oci/analytics/models/create_private_access_channel_details.py b/src/oci/analytics/models/create_private_access_channel_details.py index 20a9537a02..6a116838fb 100644 --- a/src/oci/analytics/models/create_private_access_channel_details.py +++ b/src/oci/analytics/models/create_private_access_channel_details.py @@ -34,25 +34,39 @@ def __init__(self, **kwargs): The value to assign to the private_source_dns_zones property of this CreatePrivateAccessChannelDetails. :type private_source_dns_zones: list[oci.analytics.models.PrivateSourceDnsZone] + :param private_source_scan_hosts: + The value to assign to the private_source_scan_hosts property of this CreatePrivateAccessChannelDetails. + :type private_source_scan_hosts: list[oci.analytics.models.PrivateSourceScanHost] + + :param network_security_group_ids: + The value to assign to the network_security_group_ids property of this CreatePrivateAccessChannelDetails. + :type network_security_group_ids: list[str] + """ self.swagger_types = { 'display_name': 'str', 'vcn_id': 'str', 'subnet_id': 'str', - 'private_source_dns_zones': 'list[PrivateSourceDnsZone]' + 'private_source_dns_zones': 'list[PrivateSourceDnsZone]', + 'private_source_scan_hosts': 'list[PrivateSourceScanHost]', + 'network_security_group_ids': 'list[str]' } self.attribute_map = { 'display_name': 'displayName', 'vcn_id': 'vcnId', 'subnet_id': 'subnetId', - 'private_source_dns_zones': 'privateSourceDnsZones' + 'private_source_dns_zones': 'privateSourceDnsZones', + 'private_source_scan_hosts': 'privateSourceScanHosts', + 'network_security_group_ids': 'networkSecurityGroupIds' } self._display_name = None self._vcn_id = None self._subnet_id = None self._private_source_dns_zones = None + self._private_source_scan_hosts = None + self._network_security_group_ids = None @property def display_name(self): @@ -154,6 +168,54 @@ def private_source_dns_zones(self, private_source_dns_zones): """ self._private_source_dns_zones = private_source_dns_zones + @property + def private_source_scan_hosts(self): + """ + Gets the private_source_scan_hosts of this CreatePrivateAccessChannelDetails. + List of Private Source DB SCAN hosts registered with Private Access Channel for access from Analytics Instance. + + + :return: The private_source_scan_hosts of this CreatePrivateAccessChannelDetails. + :rtype: list[oci.analytics.models.PrivateSourceScanHost] + """ + return self._private_source_scan_hosts + + @private_source_scan_hosts.setter + def private_source_scan_hosts(self, private_source_scan_hosts): + """ + Sets the private_source_scan_hosts of this CreatePrivateAccessChannelDetails. + List of Private Source DB SCAN hosts registered with Private Access Channel for access from Analytics Instance. + + + :param private_source_scan_hosts: The private_source_scan_hosts of this CreatePrivateAccessChannelDetails. + :type: list[oci.analytics.models.PrivateSourceScanHost] + """ + self._private_source_scan_hosts = private_source_scan_hosts + + @property + def network_security_group_ids(self): + """ + Gets the network_security_group_ids of this CreatePrivateAccessChannelDetails. + Network Security Group OCIDs for an Analytics instance. + + + :return: The network_security_group_ids of this CreatePrivateAccessChannelDetails. + :rtype: list[str] + """ + return self._network_security_group_ids + + @network_security_group_ids.setter + def network_security_group_ids(self, network_security_group_ids): + """ + Sets the network_security_group_ids of this CreatePrivateAccessChannelDetails. + Network Security Group OCIDs for an Analytics instance. + + + :param network_security_group_ids: The network_security_group_ids of this CreatePrivateAccessChannelDetails. + :type: list[str] + """ + self._network_security_group_ids = network_security_group_ids + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/analytics/models/private_access_channel.py b/src/oci/analytics/models/private_access_channel.py index 0536a6148f..adbe442411 100644 --- a/src/oci/analytics/models/private_access_channel.py +++ b/src/oci/analytics/models/private_access_channel.py @@ -46,6 +46,14 @@ def __init__(self, **kwargs): The value to assign to the private_source_dns_zones property of this PrivateAccessChannel. :type private_source_dns_zones: list[oci.analytics.models.PrivateSourceDnsZone] + :param private_source_scan_hosts: + The value to assign to the private_source_scan_hosts property of this PrivateAccessChannel. + :type private_source_scan_hosts: list[oci.analytics.models.PrivateSourceScanHost] + + :param network_security_group_ids: + The value to assign to the network_security_group_ids property of this PrivateAccessChannel. + :type network_security_group_ids: list[str] + """ self.swagger_types = { 'key': 'str', @@ -54,7 +62,9 @@ def __init__(self, **kwargs): 'subnet_id': 'str', 'ip_address': 'str', 'egress_source_ip_addresses': 'list[str]', - 'private_source_dns_zones': 'list[PrivateSourceDnsZone]' + 'private_source_dns_zones': 'list[PrivateSourceDnsZone]', + 'private_source_scan_hosts': 'list[PrivateSourceScanHost]', + 'network_security_group_ids': 'list[str]' } self.attribute_map = { @@ -64,7 +74,9 @@ def __init__(self, **kwargs): 'subnet_id': 'subnetId', 'ip_address': 'ipAddress', 'egress_source_ip_addresses': 'egressSourceIpAddresses', - 'private_source_dns_zones': 'privateSourceDnsZones' + 'private_source_dns_zones': 'privateSourceDnsZones', + 'private_source_scan_hosts': 'privateSourceScanHosts', + 'network_security_group_ids': 'networkSecurityGroupIds' } self._key = None @@ -74,6 +86,8 @@ def __init__(self, **kwargs): self._ip_address = None self._egress_source_ip_addresses = None self._private_source_dns_zones = None + self._private_source_scan_hosts = None + self._network_security_group_ids = None @property def key(self): @@ -249,6 +263,54 @@ def private_source_dns_zones(self, private_source_dns_zones): """ self._private_source_dns_zones = private_source_dns_zones + @property + def private_source_scan_hosts(self): + """ + Gets the private_source_scan_hosts of this PrivateAccessChannel. + List of Private Source DB SCAN hosts registered with Private Access Channel for access from Analytics Instance. + + + :return: The private_source_scan_hosts of this PrivateAccessChannel. + :rtype: list[oci.analytics.models.PrivateSourceScanHost] + """ + return self._private_source_scan_hosts + + @private_source_scan_hosts.setter + def private_source_scan_hosts(self, private_source_scan_hosts): + """ + Sets the private_source_scan_hosts of this PrivateAccessChannel. + List of Private Source DB SCAN hosts registered with Private Access Channel for access from Analytics Instance. + + + :param private_source_scan_hosts: The private_source_scan_hosts of this PrivateAccessChannel. + :type: list[oci.analytics.models.PrivateSourceScanHost] + """ + self._private_source_scan_hosts = private_source_scan_hosts + + @property + def network_security_group_ids(self): + """ + Gets the network_security_group_ids of this PrivateAccessChannel. + Network Security Group OCIDs for an Analytics instance. + + + :return: The network_security_group_ids of this PrivateAccessChannel. + :rtype: list[str] + """ + return self._network_security_group_ids + + @network_security_group_ids.setter + def network_security_group_ids(self, network_security_group_ids): + """ + Sets the network_security_group_ids of this PrivateAccessChannel. + Network Security Group OCIDs for an Analytics instance. + + + :param network_security_group_ids: The network_security_group_ids of this PrivateAccessChannel. + :type: list[str] + """ + self._network_security_group_ids = network_security_group_ids + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/analytics/models/private_endpoint_details.py b/src/oci/analytics/models/private_endpoint_details.py index 12cde115b3..581ce4c98e 100644 --- a/src/oci/analytics/models/private_endpoint_details.py +++ b/src/oci/analytics/models/private_endpoint_details.py @@ -32,22 +32,29 @@ def __init__(self, **kwargs): The value to assign to the subnet_id property of this PrivateEndpointDetails. :type subnet_id: str + :param network_security_group_ids: + The value to assign to the network_security_group_ids property of this PrivateEndpointDetails. + :type network_security_group_ids: list[str] + """ self.swagger_types = { 'network_endpoint_type': 'str', 'vcn_id': 'str', - 'subnet_id': 'str' + 'subnet_id': 'str', + 'network_security_group_ids': 'list[str]' } self.attribute_map = { 'network_endpoint_type': 'networkEndpointType', 'vcn_id': 'vcnId', - 'subnet_id': 'subnetId' + 'subnet_id': 'subnetId', + 'network_security_group_ids': 'networkSecurityGroupIds' } self._network_endpoint_type = None self._vcn_id = None self._subnet_id = None + self._network_security_group_ids = None self._network_endpoint_type = 'PRIVATE' @property @@ -98,6 +105,30 @@ def subnet_id(self, subnet_id): """ self._subnet_id = subnet_id + @property + def network_security_group_ids(self): + """ + Gets the network_security_group_ids of this PrivateEndpointDetails. + Network Security Group OCIDs for an Analytics instance. + + + :return: The network_security_group_ids of this PrivateEndpointDetails. + :rtype: list[str] + """ + return self._network_security_group_ids + + @network_security_group_ids.setter + def network_security_group_ids(self, network_security_group_ids): + """ + Sets the network_security_group_ids of this PrivateEndpointDetails. + Network Security Group OCIDs for an Analytics instance. + + + :param network_security_group_ids: The network_security_group_ids of this PrivateEndpointDetails. + :type: list[str] + """ + self._network_security_group_ids = network_security_group_ids + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/analytics/models/private_source_scan_host.py b/src/oci/analytics/models/private_source_scan_host.py new file mode 100644 index 0000000000..e66102d8fd --- /dev/null +++ b/src/oci/analytics/models/private_source_scan_host.py @@ -0,0 +1,132 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + + +from oci.util import formatted_flat_dict, NONE_SENTINEL, value_allowed_none_or_none_sentinel # noqa: F401 +from oci.decorators import init_model_state_from_kwargs + + +@init_model_state_from_kwargs +class PrivateSourceScanHost(object): + """ + Private source Scan Hostname model. + """ + + def __init__(self, **kwargs): + """ + Initializes a new PrivateSourceScanHost object with values from keyword arguments. + The following keyword arguments are supported (corresponding to the getters/setters of this class): + + :param scan_hostname: + The value to assign to the scan_hostname property of this PrivateSourceScanHost. + :type scan_hostname: str + + :param scan_port: + The value to assign to the scan_port property of this PrivateSourceScanHost. + :type scan_port: int + + :param description: + The value to assign to the description property of this PrivateSourceScanHost. + :type description: str + + """ + self.swagger_types = { + 'scan_hostname': 'str', + 'scan_port': 'int', + 'description': 'str' + } + + self.attribute_map = { + 'scan_hostname': 'scanHostname', + 'scan_port': 'scanPort', + 'description': 'description' + } + + self._scan_hostname = None + self._scan_port = None + self._description = None + + @property + def scan_hostname(self): + """ + **[Required]** Gets the scan_hostname of this PrivateSourceScanHost. + Private Source Scan hostname. Ex: db01-scan.corp.example.com, prd-db01-scan.mycompany.com. + + + :return: The scan_hostname of this PrivateSourceScanHost. + :rtype: str + """ + return self._scan_hostname + + @scan_hostname.setter + def scan_hostname(self, scan_hostname): + """ + Sets the scan_hostname of this PrivateSourceScanHost. + Private Source Scan hostname. Ex: db01-scan.corp.example.com, prd-db01-scan.mycompany.com. + + + :param scan_hostname: The scan_hostname of this PrivateSourceScanHost. + :type: str + """ + self._scan_hostname = scan_hostname + + @property + def scan_port(self): + """ + **[Required]** Gets the scan_port of this PrivateSourceScanHost. + Private Source Scan host port. This is the source port where SCAN protocol will get connected (e.g. 1521). + + + :return: The scan_port of this PrivateSourceScanHost. + :rtype: int + """ + return self._scan_port + + @scan_port.setter + def scan_port(self, scan_port): + """ + Sets the scan_port of this PrivateSourceScanHost. + Private Source Scan host port. This is the source port where SCAN protocol will get connected (e.g. 1521). + + + :param scan_port: The scan_port of this PrivateSourceScanHost. + :type: int + """ + self._scan_port = scan_port + + @property + def description(self): + """ + Gets the description of this PrivateSourceScanHost. + Description of private source scan host zone. + + + :return: The description of this PrivateSourceScanHost. + :rtype: str + """ + return self._description + + @description.setter + def description(self, description): + """ + Sets the description of this PrivateSourceScanHost. + Description of private source scan host zone. + + + :param description: The description of this PrivateSourceScanHost. + :type: str + """ + self._description = description + + def __repr__(self): + return formatted_flat_dict(self) + + def __eq__(self, other): + if other is None: + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self == other diff --git a/src/oci/analytics/models/public_endpoint_details.py b/src/oci/analytics/models/public_endpoint_details.py index 9eca510024..477f5dd4b6 100644 --- a/src/oci/analytics/models/public_endpoint_details.py +++ b/src/oci/analytics/models/public_endpoint_details.py @@ -13,6 +13,10 @@ class PublicEndpointDetails(NetworkEndpointDetails): Public endpoint configuration details. """ + #: A constant which can be used with the whitelisted_services property of a PublicEndpointDetails. + #: This constant has a value of "ALL" + WHITELISTED_SERVICES_ALL = "ALL" + def __init__(self, **kwargs): """ Initializes a new PublicEndpointDetails object with values from keyword arguments. The default value of the :py:attr:`~oci.analytics.models.PublicEndpointDetails.network_endpoint_type` attribute @@ -21,7 +25,8 @@ def __init__(self, **kwargs): :param network_endpoint_type: The value to assign to the network_endpoint_type property of this PublicEndpointDetails. - Allowed values for this property are: "PUBLIC", "PRIVATE" + Allowed values for this property are: "PUBLIC", "PRIVATE", 'UNKNOWN_ENUM_VALUE'. + Any unrecognized values returned by a service will be mapped to 'UNKNOWN_ENUM_VALUE'. :type network_endpoint_type: str :param whitelisted_ips: @@ -32,29 +37,38 @@ def __init__(self, **kwargs): The value to assign to the whitelisted_vcns property of this PublicEndpointDetails. :type whitelisted_vcns: list[oci.analytics.models.VirtualCloudNetwork] + :param whitelisted_services: + The value to assign to the whitelisted_services property of this PublicEndpointDetails. + Allowed values for items in this list are: "ALL", 'UNKNOWN_ENUM_VALUE'. + Any unrecognized values returned by a service will be mapped to 'UNKNOWN_ENUM_VALUE'. + :type whitelisted_services: list[str] + """ self.swagger_types = { 'network_endpoint_type': 'str', 'whitelisted_ips': 'list[str]', - 'whitelisted_vcns': 'list[VirtualCloudNetwork]' + 'whitelisted_vcns': 'list[VirtualCloudNetwork]', + 'whitelisted_services': 'list[str]' } self.attribute_map = { 'network_endpoint_type': 'networkEndpointType', 'whitelisted_ips': 'whitelistedIps', - 'whitelisted_vcns': 'whitelistedVcns' + 'whitelisted_vcns': 'whitelistedVcns', + 'whitelisted_services': 'whitelistedServices' } self._network_endpoint_type = None self._whitelisted_ips = None self._whitelisted_vcns = None + self._whitelisted_services = None self._network_endpoint_type = 'PUBLIC' @property def whitelisted_ips(self): """ Gets the whitelisted_ips of this PublicEndpointDetails. - Source IP addresses or IP address ranges igress rules. + Source IP addresses or IP address ranges in ingress rules. :return: The whitelisted_ips of this PublicEndpointDetails. @@ -66,7 +80,7 @@ def whitelisted_ips(self): def whitelisted_ips(self, whitelisted_ips): """ Sets the whitelisted_ips of this PublicEndpointDetails. - Source IP addresses or IP address ranges igress rules. + Source IP addresses or IP address ranges in ingress rules. :param whitelisted_ips: The whitelisted_ips of this PublicEndpointDetails. @@ -98,6 +112,36 @@ def whitelisted_vcns(self, whitelisted_vcns): """ self._whitelisted_vcns = whitelisted_vcns + @property + def whitelisted_services(self): + """ + Gets the whitelisted_services of this PublicEndpointDetails. + Oracle Cloud Services that are allowed to access this Analytics instance. + + Allowed values for items in this list are: "ALL", 'UNKNOWN_ENUM_VALUE'. + Any unrecognized values returned by a service will be mapped to 'UNKNOWN_ENUM_VALUE'. + + + :return: The whitelisted_services of this PublicEndpointDetails. + :rtype: list[str] + """ + return self._whitelisted_services + + @whitelisted_services.setter + def whitelisted_services(self, whitelisted_services): + """ + Sets the whitelisted_services of this PublicEndpointDetails. + Oracle Cloud Services that are allowed to access this Analytics instance. + + + :param whitelisted_services: The whitelisted_services of this PublicEndpointDetails. + :type: list[str] + """ + allowed_values = ["ALL"] + if whitelisted_services: + whitelisted_services[:] = ['UNKNOWN_ENUM_VALUE' if not value_allowed_none_or_none_sentinel(x, allowed_values) else x for x in whitelisted_services] + self._whitelisted_services = whitelisted_services + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/analytics/models/update_private_access_channel_details.py b/src/oci/analytics/models/update_private_access_channel_details.py index 84699ae83b..d30d2f88b8 100644 --- a/src/oci/analytics/models/update_private_access_channel_details.py +++ b/src/oci/analytics/models/update_private_access_channel_details.py @@ -34,25 +34,39 @@ def __init__(self, **kwargs): The value to assign to the private_source_dns_zones property of this UpdatePrivateAccessChannelDetails. :type private_source_dns_zones: list[oci.analytics.models.PrivateSourceDnsZone] + :param private_source_scan_hosts: + The value to assign to the private_source_scan_hosts property of this UpdatePrivateAccessChannelDetails. + :type private_source_scan_hosts: list[oci.analytics.models.PrivateSourceScanHost] + + :param network_security_group_ids: + The value to assign to the network_security_group_ids property of this UpdatePrivateAccessChannelDetails. + :type network_security_group_ids: list[str] + """ self.swagger_types = { 'display_name': 'str', 'vcn_id': 'str', 'subnet_id': 'str', - 'private_source_dns_zones': 'list[PrivateSourceDnsZone]' + 'private_source_dns_zones': 'list[PrivateSourceDnsZone]', + 'private_source_scan_hosts': 'list[PrivateSourceScanHost]', + 'network_security_group_ids': 'list[str]' } self.attribute_map = { 'display_name': 'displayName', 'vcn_id': 'vcnId', 'subnet_id': 'subnetId', - 'private_source_dns_zones': 'privateSourceDnsZones' + 'private_source_dns_zones': 'privateSourceDnsZones', + 'private_source_scan_hosts': 'privateSourceScanHosts', + 'network_security_group_ids': 'networkSecurityGroupIds' } self._display_name = None self._vcn_id = None self._subnet_id = None self._private_source_dns_zones = None + self._private_source_scan_hosts = None + self._network_security_group_ids = None @property def display_name(self): @@ -154,6 +168,54 @@ def private_source_dns_zones(self, private_source_dns_zones): """ self._private_source_dns_zones = private_source_dns_zones + @property + def private_source_scan_hosts(self): + """ + Gets the private_source_scan_hosts of this UpdatePrivateAccessChannelDetails. + List of Private Source DB SCAN hosts registered with Private Access Channel for access from Analytics Instance. + + + :return: The private_source_scan_hosts of this UpdatePrivateAccessChannelDetails. + :rtype: list[oci.analytics.models.PrivateSourceScanHost] + """ + return self._private_source_scan_hosts + + @private_source_scan_hosts.setter + def private_source_scan_hosts(self, private_source_scan_hosts): + """ + Sets the private_source_scan_hosts of this UpdatePrivateAccessChannelDetails. + List of Private Source DB SCAN hosts registered with Private Access Channel for access from Analytics Instance. + + + :param private_source_scan_hosts: The private_source_scan_hosts of this UpdatePrivateAccessChannelDetails. + :type: list[oci.analytics.models.PrivateSourceScanHost] + """ + self._private_source_scan_hosts = private_source_scan_hosts + + @property + def network_security_group_ids(self): + """ + Gets the network_security_group_ids of this UpdatePrivateAccessChannelDetails. + Network Security Group OCIDs for an Analytics instance. + + + :return: The network_security_group_ids of this UpdatePrivateAccessChannelDetails. + :rtype: list[str] + """ + return self._network_security_group_ids + + @network_security_group_ids.setter + def network_security_group_ids(self, network_security_group_ids): + """ + Sets the network_security_group_ids of this UpdatePrivateAccessChannelDetails. + Network Security Group OCIDs for an Analytics instance. + + + :param network_security_group_ids: The network_security_group_ids of this UpdatePrivateAccessChannelDetails. + :type: list[str] + """ + self._network_security_group_ids = network_security_group_ids + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/analytics/models/virtual_cloud_network.py b/src/oci/analytics/models/virtual_cloud_network.py index 8aa0b1bbfb..38457ffaaa 100644 --- a/src/oci/analytics/models/virtual_cloud_network.py +++ b/src/oci/analytics/models/virtual_cloud_network.py @@ -68,7 +68,7 @@ def id(self, id): def whitelisted_ips(self): """ Gets the whitelisted_ips of this VirtualCloudNetwork. - Source IP addresses or IP address ranges igress rules. + Source IP addresses or IP address ranges in ingress rules. :return: The whitelisted_ips of this VirtualCloudNetwork. @@ -80,7 +80,7 @@ def whitelisted_ips(self): def whitelisted_ips(self, whitelisted_ips): """ Sets the whitelisted_ips of this VirtualCloudNetwork. - Source IP addresses or IP address ranges igress rules. + Source IP addresses or IP address ranges in ingress rules. :param whitelisted_ips: The whitelisted_ips of this VirtualCloudNetwork. diff --git a/src/oci/core/models/__init__.py b/src/oci/core/models/__init__.py index 43fae7c9a7..25df526e2b 100644 --- a/src/oci/core/models/__init__.py +++ b/src/oci/core/models/__init__.py @@ -43,6 +43,7 @@ from .attach_service_determined_volume_details import AttachServiceDeterminedVolumeDetails from .attach_vnic_details import AttachVnicDetails from .attach_volume_details import AttachVolumeDetails +from .autotune_policy import AutotunePolicy from .bgp_session_info import BgpSessionInfo from .block_volume_replica import BlockVolumeReplica from .block_volume_replica_details import BlockVolumeReplicaDetails @@ -209,6 +210,7 @@ from .delete_virtual_circuit_public_prefix_details import DeleteVirtualCircuitPublicPrefixDetails from .detach_instance_pool_instance_details import DetachInstancePoolInstanceDetails from .detach_load_balancer_details import DetachLoadBalancerDetails +from .detached_volume_autotune_policy import DetachedVolumeAutotunePolicy from .device import Device from .dhcp_dns_option import DhcpDnsOption from .dhcp_option import DhcpOption @@ -272,10 +274,12 @@ from .instance_configuration_amd_vm_launch_instance_platform_config import InstanceConfigurationAmdVmLaunchInstancePlatformConfig from .instance_configuration_attach_vnic_details import InstanceConfigurationAttachVnicDetails from .instance_configuration_attach_volume_details import InstanceConfigurationAttachVolumeDetails +from .instance_configuration_autotune_policy import InstanceConfigurationAutotunePolicy from .instance_configuration_availability_config import InstanceConfigurationAvailabilityConfig from .instance_configuration_block_volume_details import InstanceConfigurationBlockVolumeDetails from .instance_configuration_create_vnic_details import InstanceConfigurationCreateVnicDetails from .instance_configuration_create_volume_details import InstanceConfigurationCreateVolumeDetails +from .instance_configuration_detached_volume_autotune_policy import InstanceConfigurationDetachedVolumeAutotunePolicy from .instance_configuration_instance_details import InstanceConfigurationInstanceDetails from .instance_configuration_instance_options import InstanceConfigurationInstanceOptions from .instance_configuration_instance_source_details import InstanceConfigurationInstanceSourceDetails @@ -291,6 +295,7 @@ from .instance_configuration_launch_instance_shape_config_details import InstanceConfigurationLaunchInstanceShapeConfigDetails from .instance_configuration_launch_options import InstanceConfigurationLaunchOptions from .instance_configuration_paravirtualized_attach_volume_details import InstanceConfigurationParavirtualizedAttachVolumeDetails +from .instance_configuration_performance_based_autotune_policy import InstanceConfigurationPerformanceBasedAutotunePolicy from .instance_configuration_summary import InstanceConfigurationSummary from .instance_configuration_volume_source_details import InstanceConfigurationVolumeSourceDetails from .instance_configuration_volume_source_from_volume_backup_details import InstanceConfigurationVolumeSourceFromVolumeBackupDetails @@ -347,6 +352,7 @@ from .paravirtualized_volume_attachment import ParavirtualizedVolumeAttachment from .peer_region_for_remote_peering import PeerRegionForRemotePeering from .percentage_of_cores_enabled_options import PercentageOfCoresEnabledOptions +from .performance_based_autotune_policy import PerformanceBasedAutotunePolicy from .phase_one_config_details import PhaseOneConfigDetails from .phase_two_config_details import PhaseTwoConfigDetails from .platform_config import PlatformConfig @@ -560,6 +566,7 @@ "AttachServiceDeterminedVolumeDetails": AttachServiceDeterminedVolumeDetails, "AttachVnicDetails": AttachVnicDetails, "AttachVolumeDetails": AttachVolumeDetails, + "AutotunePolicy": AutotunePolicy, "BgpSessionInfo": BgpSessionInfo, "BlockVolumeReplica": BlockVolumeReplica, "BlockVolumeReplicaDetails": BlockVolumeReplicaDetails, @@ -726,6 +733,7 @@ "DeleteVirtualCircuitPublicPrefixDetails": DeleteVirtualCircuitPublicPrefixDetails, "DetachInstancePoolInstanceDetails": DetachInstancePoolInstanceDetails, "DetachLoadBalancerDetails": DetachLoadBalancerDetails, + "DetachedVolumeAutotunePolicy": DetachedVolumeAutotunePolicy, "Device": Device, "DhcpDnsOption": DhcpDnsOption, "DhcpOption": DhcpOption, @@ -789,10 +797,12 @@ "InstanceConfigurationAmdVmLaunchInstancePlatformConfig": InstanceConfigurationAmdVmLaunchInstancePlatformConfig, "InstanceConfigurationAttachVnicDetails": InstanceConfigurationAttachVnicDetails, "InstanceConfigurationAttachVolumeDetails": InstanceConfigurationAttachVolumeDetails, + "InstanceConfigurationAutotunePolicy": InstanceConfigurationAutotunePolicy, "InstanceConfigurationAvailabilityConfig": InstanceConfigurationAvailabilityConfig, "InstanceConfigurationBlockVolumeDetails": InstanceConfigurationBlockVolumeDetails, "InstanceConfigurationCreateVnicDetails": InstanceConfigurationCreateVnicDetails, "InstanceConfigurationCreateVolumeDetails": InstanceConfigurationCreateVolumeDetails, + "InstanceConfigurationDetachedVolumeAutotunePolicy": InstanceConfigurationDetachedVolumeAutotunePolicy, "InstanceConfigurationInstanceDetails": InstanceConfigurationInstanceDetails, "InstanceConfigurationInstanceOptions": InstanceConfigurationInstanceOptions, "InstanceConfigurationInstanceSourceDetails": InstanceConfigurationInstanceSourceDetails, @@ -808,6 +818,7 @@ "InstanceConfigurationLaunchInstanceShapeConfigDetails": InstanceConfigurationLaunchInstanceShapeConfigDetails, "InstanceConfigurationLaunchOptions": InstanceConfigurationLaunchOptions, "InstanceConfigurationParavirtualizedAttachVolumeDetails": InstanceConfigurationParavirtualizedAttachVolumeDetails, + "InstanceConfigurationPerformanceBasedAutotunePolicy": InstanceConfigurationPerformanceBasedAutotunePolicy, "InstanceConfigurationSummary": InstanceConfigurationSummary, "InstanceConfigurationVolumeSourceDetails": InstanceConfigurationVolumeSourceDetails, "InstanceConfigurationVolumeSourceFromVolumeBackupDetails": InstanceConfigurationVolumeSourceFromVolumeBackupDetails, @@ -864,6 +875,7 @@ "ParavirtualizedVolumeAttachment": ParavirtualizedVolumeAttachment, "PeerRegionForRemotePeering": PeerRegionForRemotePeering, "PercentageOfCoresEnabledOptions": PercentageOfCoresEnabledOptions, + "PerformanceBasedAutotunePolicy": PerformanceBasedAutotunePolicy, "PhaseOneConfigDetails": PhaseOneConfigDetails, "PhaseTwoConfigDetails": PhaseTwoConfigDetails, "PlatformConfig": PlatformConfig, diff --git a/src/oci/core/models/autotune_policy.py b/src/oci/core/models/autotune_policy.py new file mode 100644 index 0000000000..9c89f01b30 --- /dev/null +++ b/src/oci/core/models/autotune_policy.py @@ -0,0 +1,107 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + + +from oci.util import formatted_flat_dict, NONE_SENTINEL, value_allowed_none_or_none_sentinel # noqa: F401 +from oci.decorators import init_model_state_from_kwargs + + +@init_model_state_from_kwargs +class AutotunePolicy(object): + """ + An autotune policy automatically tunes the volume's performace based on the type of the policy. + """ + + #: A constant which can be used with the autotune_type property of a AutotunePolicy. + #: This constant has a value of "DETACHED_VOLUME" + AUTOTUNE_TYPE_DETACHED_VOLUME = "DETACHED_VOLUME" + + #: A constant which can be used with the autotune_type property of a AutotunePolicy. + #: This constant has a value of "PERFORMANCE_BASED" + AUTOTUNE_TYPE_PERFORMANCE_BASED = "PERFORMANCE_BASED" + + def __init__(self, **kwargs): + """ + Initializes a new AutotunePolicy object with values from keyword arguments. This class has the following subclasses and if you are using this class as input + to a service operations then you should favor using a subclass over the base class: + + * :class:`~oci.core.models.DetachedVolumeAutotunePolicy` + * :class:`~oci.core.models.PerformanceBasedAutotunePolicy` + + The following keyword arguments are supported (corresponding to the getters/setters of this class): + + :param autotune_type: + The value to assign to the autotune_type property of this AutotunePolicy. + Allowed values for this property are: "DETACHED_VOLUME", "PERFORMANCE_BASED", 'UNKNOWN_ENUM_VALUE'. + Any unrecognized values returned by a service will be mapped to 'UNKNOWN_ENUM_VALUE'. + :type autotune_type: str + + """ + self.swagger_types = { + 'autotune_type': 'str' + } + + self.attribute_map = { + 'autotune_type': 'autotuneType' + } + + self._autotune_type = None + + @staticmethod + def get_subtype(object_dictionary): + """ + Given the hash representation of a subtype of this class, + use the info in the hash to return the class of the subtype. + """ + type = object_dictionary['autotuneType'] + + if type == 'DETACHED_VOLUME': + return 'DetachedVolumeAutotunePolicy' + + if type == 'PERFORMANCE_BASED': + return 'PerformanceBasedAutotunePolicy' + else: + return 'AutotunePolicy' + + @property + def autotune_type(self): + """ + **[Required]** Gets the autotune_type of this AutotunePolicy. + This specifies the type of autotunes supported by OCI. + + Allowed values for this property are: "DETACHED_VOLUME", "PERFORMANCE_BASED", 'UNKNOWN_ENUM_VALUE'. + Any unrecognized values returned by a service will be mapped to 'UNKNOWN_ENUM_VALUE'. + + + :return: The autotune_type of this AutotunePolicy. + :rtype: str + """ + return self._autotune_type + + @autotune_type.setter + def autotune_type(self, autotune_type): + """ + Sets the autotune_type of this AutotunePolicy. + This specifies the type of autotunes supported by OCI. + + + :param autotune_type: The autotune_type of this AutotunePolicy. + :type: str + """ + allowed_values = ["DETACHED_VOLUME", "PERFORMANCE_BASED"] + if not value_allowed_none_or_none_sentinel(autotune_type, allowed_values): + autotune_type = 'UNKNOWN_ENUM_VALUE' + self._autotune_type = autotune_type + + def __repr__(self): + return formatted_flat_dict(self) + + def __eq__(self, other): + if other is None: + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self == other diff --git a/src/oci/core/models/boot_volume.py b/src/oci/core/models/boot_volume.py index 16bfbef0f9..7a4a0f19a0 100644 --- a/src/oci/core/models/boot_volume.py +++ b/src/oci/core/models/boot_volume.py @@ -135,6 +135,10 @@ def __init__(self, **kwargs): The value to assign to the boot_volume_replicas property of this BootVolume. :type boot_volume_replicas: list[oci.core.models.BootVolumeReplicaInfo] + :param autotune_policies: + The value to assign to the autotune_policies property of this BootVolume. + :type autotune_policies: list[oci.core.models.AutotunePolicy] + """ self.swagger_types = { 'availability_domain': 'str', @@ -156,7 +160,8 @@ def __init__(self, **kwargs): 'kms_key_id': 'str', 'is_auto_tune_enabled': 'bool', 'auto_tuned_vpus_per_gb': 'int', - 'boot_volume_replicas': 'list[BootVolumeReplicaInfo]' + 'boot_volume_replicas': 'list[BootVolumeReplicaInfo]', + 'autotune_policies': 'list[AutotunePolicy]' } self.attribute_map = { @@ -179,7 +184,8 @@ def __init__(self, **kwargs): 'kms_key_id': 'kmsKeyId', 'is_auto_tune_enabled': 'isAutoTuneEnabled', 'auto_tuned_vpus_per_gb': 'autoTunedVpusPerGB', - 'boot_volume_replicas': 'bootVolumeReplicas' + 'boot_volume_replicas': 'bootVolumeReplicas', + 'autotune_policies': 'autotunePolicies' } self._availability_domain = None @@ -202,6 +208,7 @@ def __init__(self, **kwargs): self._is_auto_tune_enabled = None self._auto_tuned_vpus_per_gb = None self._boot_volume_replicas = None + self._autotune_policies = None @property def availability_domain(self): @@ -465,6 +472,8 @@ def vpus_per_gb(self): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -489,6 +498,8 @@ def vpus_per_gb(self, vpus_per_gb): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -679,7 +690,8 @@ def kms_key_id(self, kms_key_id): def is_auto_tune_enabled(self): """ Gets the is_auto_tune_enabled of this BootVolume. - Specifies whether the auto-tune performance is enabled for this boot volume. + Specifies whether the auto-tune performance is enabled for this boot volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :return: The is_auto_tune_enabled of this BootVolume. @@ -691,7 +703,8 @@ def is_auto_tune_enabled(self): def is_auto_tune_enabled(self, is_auto_tune_enabled): """ Sets the is_auto_tune_enabled of this BootVolume. - Specifies whether the auto-tune performance is enabled for this boot volume. + Specifies whether the auto-tune performance is enabled for this boot volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :param is_auto_tune_enabled: The is_auto_tune_enabled of this BootVolume. @@ -703,7 +716,7 @@ def is_auto_tune_enabled(self, is_auto_tune_enabled): def auto_tuned_vpus_per_gb(self): """ Gets the auto_tuned_vpus_per_gb of this BootVolume. - The number of Volume Performance Units per GB that this boot volume is effectively tuned to when it's idle. + The number of Volume Performance Units per GB that this boot volume is effectively tuned to. :return: The auto_tuned_vpus_per_gb of this BootVolume. @@ -715,7 +728,7 @@ def auto_tuned_vpus_per_gb(self): def auto_tuned_vpus_per_gb(self, auto_tuned_vpus_per_gb): """ Sets the auto_tuned_vpus_per_gb of this BootVolume. - The number of Volume Performance Units per GB that this boot volume is effectively tuned to when it's idle. + The number of Volume Performance Units per GB that this boot volume is effectively tuned to. :param auto_tuned_vpus_per_gb: The auto_tuned_vpus_per_gb of this BootVolume. @@ -747,6 +760,30 @@ def boot_volume_replicas(self, boot_volume_replicas): """ self._boot_volume_replicas = boot_volume_replicas + @property + def autotune_policies(self): + """ + Gets the autotune_policies of this BootVolume. + The list of autotune policies enabled for this volume. + + + :return: The autotune_policies of this BootVolume. + :rtype: list[oci.core.models.AutotunePolicy] + """ + return self._autotune_policies + + @autotune_policies.setter + def autotune_policies(self, autotune_policies): + """ + Sets the autotune_policies of this BootVolume. + The list of autotune policies enabled for this volume. + + + :param autotune_policies: The autotune_policies of this BootVolume. + :type: list[oci.core.models.AutotunePolicy] + """ + self._autotune_policies = autotune_policies + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/core/models/create_boot_volume_details.py b/src/oci/core/models/create_boot_volume_details.py index c63b80e92b..092e5c2b36 100644 --- a/src/oci/core/models/create_boot_volume_details.py +++ b/src/oci/core/models/create_boot_volume_details.py @@ -66,6 +66,10 @@ def __init__(self, **kwargs): The value to assign to the boot_volume_replicas property of this CreateBootVolumeDetails. :type boot_volume_replicas: list[oci.core.models.BootVolumeReplicaDetails] + :param autotune_policies: + The value to assign to the autotune_policies property of this CreateBootVolumeDetails. + :type autotune_policies: list[oci.core.models.AutotunePolicy] + """ self.swagger_types = { 'availability_domain': 'str', @@ -79,7 +83,8 @@ def __init__(self, **kwargs): 'vpus_per_gb': 'int', 'source_details': 'BootVolumeSourceDetails', 'is_auto_tune_enabled': 'bool', - 'boot_volume_replicas': 'list[BootVolumeReplicaDetails]' + 'boot_volume_replicas': 'list[BootVolumeReplicaDetails]', + 'autotune_policies': 'list[AutotunePolicy]' } self.attribute_map = { @@ -94,7 +99,8 @@ def __init__(self, **kwargs): 'vpus_per_gb': 'vpusPerGB', 'source_details': 'sourceDetails', 'is_auto_tune_enabled': 'isAutoTuneEnabled', - 'boot_volume_replicas': 'bootVolumeReplicas' + 'boot_volume_replicas': 'bootVolumeReplicas', + 'autotune_policies': 'autotunePolicies' } self._availability_domain = None @@ -109,6 +115,7 @@ def __init__(self, **kwargs): self._source_details = None self._is_auto_tune_enabled = None self._boot_volume_replicas = None + self._autotune_policies = None @property def availability_domain(self): @@ -342,12 +349,14 @@ def vpus_per_gb(self): Allowed values: - * `10`: Represents Balanced option. + * `10`: Represents the Balanced option. - * `20`: Represents Higher Performance option. + * `20`: Represents the Higher Performance option. * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -366,12 +375,14 @@ def vpus_per_gb(self, vpus_per_gb): Allowed values: - * `10`: Represents Balanced option. + * `10`: Represents the Balanced option. - * `20`: Represents Higher Performance option. + * `20`: Represents the Higher Performance option. * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -404,7 +415,8 @@ def source_details(self, source_details): def is_auto_tune_enabled(self): """ Gets the is_auto_tune_enabled of this CreateBootVolumeDetails. - Specifies whether the auto-tune performance is enabled for this boot volume. + Specifies whether the auto-tune performance is enabled for this boot volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :return: The is_auto_tune_enabled of this CreateBootVolumeDetails. @@ -416,7 +428,8 @@ def is_auto_tune_enabled(self): def is_auto_tune_enabled(self, is_auto_tune_enabled): """ Sets the is_auto_tune_enabled of this CreateBootVolumeDetails. - Specifies whether the auto-tune performance is enabled for this boot volume. + Specifies whether the auto-tune performance is enabled for this boot volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :param is_auto_tune_enabled: The is_auto_tune_enabled of this CreateBootVolumeDetails. @@ -450,6 +463,30 @@ def boot_volume_replicas(self, boot_volume_replicas): """ self._boot_volume_replicas = boot_volume_replicas + @property + def autotune_policies(self): + """ + Gets the autotune_policies of this CreateBootVolumeDetails. + The list of autotune policies to be enabled for this volume. + + + :return: The autotune_policies of this CreateBootVolumeDetails. + :rtype: list[oci.core.models.AutotunePolicy] + """ + return self._autotune_policies + + @autotune_policies.setter + def autotune_policies(self, autotune_policies): + """ + Sets the autotune_policies of this CreateBootVolumeDetails. + The list of autotune policies to be enabled for this volume. + + + :param autotune_policies: The autotune_policies of this CreateBootVolumeDetails. + :type: list[oci.core.models.AutotunePolicy] + """ + self._autotune_policies = autotune_policies + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/core/models/create_volume_details.py b/src/oci/core/models/create_volume_details.py index ce3c035c18..3cd249bb51 100644 --- a/src/oci/core/models/create_volume_details.py +++ b/src/oci/core/models/create_volume_details.py @@ -75,6 +75,10 @@ def __init__(self, **kwargs): The value to assign to the block_volume_replicas property of this CreateVolumeDetails. :type block_volume_replicas: list[oci.core.models.BlockVolumeReplicaDetails] + :param autotune_policies: + The value to assign to the autotune_policies property of this CreateVolumeDetails. + :type autotune_policies: list[oci.core.models.AutotunePolicy] + """ self.swagger_types = { 'availability_domain': 'str', @@ -90,7 +94,8 @@ def __init__(self, **kwargs): 'source_details': 'VolumeSourceDetails', 'volume_backup_id': 'str', 'is_auto_tune_enabled': 'bool', - 'block_volume_replicas': 'list[BlockVolumeReplicaDetails]' + 'block_volume_replicas': 'list[BlockVolumeReplicaDetails]', + 'autotune_policies': 'list[AutotunePolicy]' } self.attribute_map = { @@ -107,7 +112,8 @@ def __init__(self, **kwargs): 'source_details': 'sourceDetails', 'volume_backup_id': 'volumeBackupId', 'is_auto_tune_enabled': 'isAutoTuneEnabled', - 'block_volume_replicas': 'blockVolumeReplicas' + 'block_volume_replicas': 'blockVolumeReplicas', + 'autotune_policies': 'autotunePolicies' } self._availability_domain = None @@ -124,6 +130,7 @@ def __init__(self, **kwargs): self._volume_backup_id = None self._is_auto_tune_enabled = None self._block_volume_replicas = None + self._autotune_policies = None @property def availability_domain(self): @@ -341,6 +348,8 @@ def vpus_per_gb(self): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -367,6 +376,8 @@ def vpus_per_gb(self, vpus_per_gb): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -477,7 +488,8 @@ def volume_backup_id(self, volume_backup_id): def is_auto_tune_enabled(self): """ Gets the is_auto_tune_enabled of this CreateVolumeDetails. - Specifies whether the auto-tune performance is enabled for this volume. + Specifies whether the auto-tune performance is enabled for this volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :return: The is_auto_tune_enabled of this CreateVolumeDetails. @@ -489,7 +501,8 @@ def is_auto_tune_enabled(self): def is_auto_tune_enabled(self, is_auto_tune_enabled): """ Sets the is_auto_tune_enabled of this CreateVolumeDetails. - Specifies whether the auto-tune performance is enabled for this volume. + Specifies whether the auto-tune performance is enabled for this volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :param is_auto_tune_enabled: The is_auto_tune_enabled of this CreateVolumeDetails. @@ -523,6 +536,30 @@ def block_volume_replicas(self, block_volume_replicas): """ self._block_volume_replicas = block_volume_replicas + @property + def autotune_policies(self): + """ + Gets the autotune_policies of this CreateVolumeDetails. + The list of autotune policies to be enabled for this volume. + + + :return: The autotune_policies of this CreateVolumeDetails. + :rtype: list[oci.core.models.AutotunePolicy] + """ + return self._autotune_policies + + @autotune_policies.setter + def autotune_policies(self, autotune_policies): + """ + Sets the autotune_policies of this CreateVolumeDetails. + The list of autotune policies to be enabled for this volume. + + + :param autotune_policies: The autotune_policies of this CreateVolumeDetails. + :type: list[oci.core.models.AutotunePolicy] + """ + self._autotune_policies = autotune_policies + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/core/models/detached_volume_autotune_policy.py b/src/oci/core/models/detached_volume_autotune_policy.py new file mode 100644 index 0000000000..ad3c421a1a --- /dev/null +++ b/src/oci/core/models/detached_volume_autotune_policy.py @@ -0,0 +1,49 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + +from .autotune_policy import AutotunePolicy +from oci.util import formatted_flat_dict, NONE_SENTINEL, value_allowed_none_or_none_sentinel # noqa: F401 +from oci.decorators import init_model_state_from_kwargs + + +@init_model_state_from_kwargs +class DetachedVolumeAutotunePolicy(AutotunePolicy): + """ + Volume's performace will be tuned to the lower cost settings once detached. + """ + + def __init__(self, **kwargs): + """ + Initializes a new DetachedVolumeAutotunePolicy object with values from keyword arguments. The default value of the :py:attr:`~oci.core.models.DetachedVolumeAutotunePolicy.autotune_type` attribute + of this class is ``DETACHED_VOLUME`` and it should not be changed. + The following keyword arguments are supported (corresponding to the getters/setters of this class): + + :param autotune_type: + The value to assign to the autotune_type property of this DetachedVolumeAutotunePolicy. + Allowed values for this property are: "DETACHED_VOLUME", "PERFORMANCE_BASED" + :type autotune_type: str + + """ + self.swagger_types = { + 'autotune_type': 'str' + } + + self.attribute_map = { + 'autotune_type': 'autotuneType' + } + + self._autotune_type = None + self._autotune_type = 'DETACHED_VOLUME' + + def __repr__(self): + return formatted_flat_dict(self) + + def __eq__(self, other): + if other is None: + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self == other diff --git a/src/oci/core/models/instance_configuration_autotune_policy.py b/src/oci/core/models/instance_configuration_autotune_policy.py new file mode 100644 index 0000000000..a221c097a8 --- /dev/null +++ b/src/oci/core/models/instance_configuration_autotune_policy.py @@ -0,0 +1,107 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + + +from oci.util import formatted_flat_dict, NONE_SENTINEL, value_allowed_none_or_none_sentinel # noqa: F401 +from oci.decorators import init_model_state_from_kwargs + + +@init_model_state_from_kwargs +class InstanceConfigurationAutotunePolicy(object): + """ + An autotune policy automatically tunes the volume's performace based on the type of the policy. + """ + + #: A constant which can be used with the autotune_type property of a InstanceConfigurationAutotunePolicy. + #: This constant has a value of "DETACHED_VOLUME" + AUTOTUNE_TYPE_DETACHED_VOLUME = "DETACHED_VOLUME" + + #: A constant which can be used with the autotune_type property of a InstanceConfigurationAutotunePolicy. + #: This constant has a value of "PERFORMANCE_BASED" + AUTOTUNE_TYPE_PERFORMANCE_BASED = "PERFORMANCE_BASED" + + def __init__(self, **kwargs): + """ + Initializes a new InstanceConfigurationAutotunePolicy object with values from keyword arguments. This class has the following subclasses and if you are using this class as input + to a service operations then you should favor using a subclass over the base class: + + * :class:`~oci.core.models.InstanceConfigurationPerformanceBasedAutotunePolicy` + * :class:`~oci.core.models.InstanceConfigurationDetachedVolumeAutotunePolicy` + + The following keyword arguments are supported (corresponding to the getters/setters of this class): + + :param autotune_type: + The value to assign to the autotune_type property of this InstanceConfigurationAutotunePolicy. + Allowed values for this property are: "DETACHED_VOLUME", "PERFORMANCE_BASED", 'UNKNOWN_ENUM_VALUE'. + Any unrecognized values returned by a service will be mapped to 'UNKNOWN_ENUM_VALUE'. + :type autotune_type: str + + """ + self.swagger_types = { + 'autotune_type': 'str' + } + + self.attribute_map = { + 'autotune_type': 'autotuneType' + } + + self._autotune_type = None + + @staticmethod + def get_subtype(object_dictionary): + """ + Given the hash representation of a subtype of this class, + use the info in the hash to return the class of the subtype. + """ + type = object_dictionary['autotuneType'] + + if type == 'PERFORMANCE_BASED': + return 'InstanceConfigurationPerformanceBasedAutotunePolicy' + + if type == 'DETACHED_VOLUME': + return 'InstanceConfigurationDetachedVolumeAutotunePolicy' + else: + return 'InstanceConfigurationAutotunePolicy' + + @property + def autotune_type(self): + """ + **[Required]** Gets the autotune_type of this InstanceConfigurationAutotunePolicy. + This specifies the type of autotunes supported by OCI. + + Allowed values for this property are: "DETACHED_VOLUME", "PERFORMANCE_BASED", 'UNKNOWN_ENUM_VALUE'. + Any unrecognized values returned by a service will be mapped to 'UNKNOWN_ENUM_VALUE'. + + + :return: The autotune_type of this InstanceConfigurationAutotunePolicy. + :rtype: str + """ + return self._autotune_type + + @autotune_type.setter + def autotune_type(self, autotune_type): + """ + Sets the autotune_type of this InstanceConfigurationAutotunePolicy. + This specifies the type of autotunes supported by OCI. + + + :param autotune_type: The autotune_type of this InstanceConfigurationAutotunePolicy. + :type: str + """ + allowed_values = ["DETACHED_VOLUME", "PERFORMANCE_BASED"] + if not value_allowed_none_or_none_sentinel(autotune_type, allowed_values): + autotune_type = 'UNKNOWN_ENUM_VALUE' + self._autotune_type = autotune_type + + def __repr__(self): + return formatted_flat_dict(self) + + def __eq__(self, other): + if other is None: + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self == other diff --git a/src/oci/core/models/instance_configuration_create_volume_details.py b/src/oci/core/models/instance_configuration_create_volume_details.py index fe9b63b6fc..786cbfe1c5 100644 --- a/src/oci/core/models/instance_configuration_create_volume_details.py +++ b/src/oci/core/models/instance_configuration_create_volume_details.py @@ -58,6 +58,10 @@ def __init__(self, **kwargs): The value to assign to the source_details property of this InstanceConfigurationCreateVolumeDetails. :type source_details: oci.core.models.InstanceConfigurationVolumeSourceDetails + :param autotune_policies: + The value to assign to the autotune_policies property of this InstanceConfigurationCreateVolumeDetails. + :type autotune_policies: list[oci.core.models.InstanceConfigurationAutotunePolicy] + """ self.swagger_types = { 'availability_domain': 'str', @@ -69,7 +73,8 @@ def __init__(self, **kwargs): 'kms_key_id': 'str', 'vpus_per_gb': 'int', 'size_in_gbs': 'int', - 'source_details': 'InstanceConfigurationVolumeSourceDetails' + 'source_details': 'InstanceConfigurationVolumeSourceDetails', + 'autotune_policies': 'list[InstanceConfigurationAutotunePolicy]' } self.attribute_map = { @@ -82,7 +87,8 @@ def __init__(self, **kwargs): 'kms_key_id': 'kmsKeyId', 'vpus_per_gb': 'vpusPerGB', 'size_in_gbs': 'sizeInGBs', - 'source_details': 'sourceDetails' + 'source_details': 'sourceDetails', + 'autotune_policies': 'autotunePolicies' } self._availability_domain = None @@ -95,6 +101,7 @@ def __init__(self, **kwargs): self._vpus_per_gb = None self._size_in_gbs = None self._source_details = None + self._autotune_policies = None @property def availability_domain(self): @@ -312,6 +319,8 @@ def vpus_per_gb(self): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -338,6 +347,8 @@ def vpus_per_gb(self, vpus_per_gb): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -390,6 +401,30 @@ def source_details(self, source_details): """ self._source_details = source_details + @property + def autotune_policies(self): + """ + Gets the autotune_policies of this InstanceConfigurationCreateVolumeDetails. + The list of autotune policies enabled for this volume. + + + :return: The autotune_policies of this InstanceConfigurationCreateVolumeDetails. + :rtype: list[oci.core.models.InstanceConfigurationAutotunePolicy] + """ + return self._autotune_policies + + @autotune_policies.setter + def autotune_policies(self, autotune_policies): + """ + Sets the autotune_policies of this InstanceConfigurationCreateVolumeDetails. + The list of autotune policies enabled for this volume. + + + :param autotune_policies: The autotune_policies of this InstanceConfigurationCreateVolumeDetails. + :type: list[oci.core.models.InstanceConfigurationAutotunePolicy] + """ + self._autotune_policies = autotune_policies + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/core/models/instance_configuration_detached_volume_autotune_policy.py b/src/oci/core/models/instance_configuration_detached_volume_autotune_policy.py new file mode 100644 index 0000000000..d7e2295409 --- /dev/null +++ b/src/oci/core/models/instance_configuration_detached_volume_autotune_policy.py @@ -0,0 +1,49 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + +from .instance_configuration_autotune_policy import InstanceConfigurationAutotunePolicy +from oci.util import formatted_flat_dict, NONE_SENTINEL, value_allowed_none_or_none_sentinel # noqa: F401 +from oci.decorators import init_model_state_from_kwargs + + +@init_model_state_from_kwargs +class InstanceConfigurationDetachedVolumeAutotunePolicy(InstanceConfigurationAutotunePolicy): + """ + Volume's performace will be tuned to the lower cost settings once detached. + """ + + def __init__(self, **kwargs): + """ + Initializes a new InstanceConfigurationDetachedVolumeAutotunePolicy object with values from keyword arguments. The default value of the :py:attr:`~oci.core.models.InstanceConfigurationDetachedVolumeAutotunePolicy.autotune_type` attribute + of this class is ``DETACHED_VOLUME`` and it should not be changed. + The following keyword arguments are supported (corresponding to the getters/setters of this class): + + :param autotune_type: + The value to assign to the autotune_type property of this InstanceConfigurationDetachedVolumeAutotunePolicy. + Allowed values for this property are: "DETACHED_VOLUME", "PERFORMANCE_BASED" + :type autotune_type: str + + """ + self.swagger_types = { + 'autotune_type': 'str' + } + + self.attribute_map = { + 'autotune_type': 'autotuneType' + } + + self._autotune_type = None + self._autotune_type = 'DETACHED_VOLUME' + + def __repr__(self): + return formatted_flat_dict(self) + + def __eq__(self, other): + if other is None: + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self == other diff --git a/src/oci/core/models/instance_configuration_instance_source_via_image_details.py b/src/oci/core/models/instance_configuration_instance_source_via_image_details.py index 604631c746..48e1e71f02 100644 --- a/src/oci/core/models/instance_configuration_instance_source_via_image_details.py +++ b/src/oci/core/models/instance_configuration_instance_source_via_image_details.py @@ -122,6 +122,8 @@ def boot_volume_vpus_per_gb(self): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -146,6 +148,8 @@ def boot_volume_vpus_per_gb(self, boot_volume_vpus_per_gb): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels diff --git a/src/oci/core/models/instance_configuration_performance_based_autotune_policy.py b/src/oci/core/models/instance_configuration_performance_based_autotune_policy.py new file mode 100644 index 0000000000..e90e8dcccf --- /dev/null +++ b/src/oci/core/models/instance_configuration_performance_based_autotune_policy.py @@ -0,0 +1,85 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + +from .instance_configuration_autotune_policy import InstanceConfigurationAutotunePolicy +from oci.util import formatted_flat_dict, NONE_SENTINEL, value_allowed_none_or_none_sentinel # noqa: F401 +from oci.decorators import init_model_state_from_kwargs + + +@init_model_state_from_kwargs +class InstanceConfigurationPerformanceBasedAutotunePolicy(InstanceConfigurationAutotunePolicy): + """ + If a volume is being throttled at the current setting for a certain period of time, auto-tune will + gradually increase the volume\u2019s performance limited up to Maximum VPUs/GB. After the volume has been idle at the + current setting for a certain period of time, auto-tune will gradually decrease the volume\u2019s performance limited + down to Default/Minimum VPUs/GB. + """ + + def __init__(self, **kwargs): + """ + Initializes a new InstanceConfigurationPerformanceBasedAutotunePolicy object with values from keyword arguments. The default value of the :py:attr:`~oci.core.models.InstanceConfigurationPerformanceBasedAutotunePolicy.autotune_type` attribute + of this class is ``PERFORMANCE_BASED`` and it should not be changed. + The following keyword arguments are supported (corresponding to the getters/setters of this class): + + :param autotune_type: + The value to assign to the autotune_type property of this InstanceConfigurationPerformanceBasedAutotunePolicy. + Allowed values for this property are: "DETACHED_VOLUME", "PERFORMANCE_BASED" + :type autotune_type: str + + :param max_vpus_per_gb: + The value to assign to the max_vpus_per_gb property of this InstanceConfigurationPerformanceBasedAutotunePolicy. + :type max_vpus_per_gb: int + + """ + self.swagger_types = { + 'autotune_type': 'str', + 'max_vpus_per_gb': 'int' + } + + self.attribute_map = { + 'autotune_type': 'autotuneType', + 'max_vpus_per_gb': 'maxVpusPerGB' + } + + self._autotune_type = None + self._max_vpus_per_gb = None + self._autotune_type = 'PERFORMANCE_BASED' + + @property + def max_vpus_per_gb(self): + """ + **[Required]** Gets the max_vpus_per_gb of this InstanceConfigurationPerformanceBasedAutotunePolicy. + This will be the maximum VPUs/GB performance level that the volume will be auto-tuned + temporarily based on performance monitoring. + + + :return: The max_vpus_per_gb of this InstanceConfigurationPerformanceBasedAutotunePolicy. + :rtype: int + """ + return self._max_vpus_per_gb + + @max_vpus_per_gb.setter + def max_vpus_per_gb(self, max_vpus_per_gb): + """ + Sets the max_vpus_per_gb of this InstanceConfigurationPerformanceBasedAutotunePolicy. + This will be the maximum VPUs/GB performance level that the volume will be auto-tuned + temporarily based on performance monitoring. + + + :param max_vpus_per_gb: The max_vpus_per_gb of this InstanceConfigurationPerformanceBasedAutotunePolicy. + :type: int + """ + self._max_vpus_per_gb = max_vpus_per_gb + + def __repr__(self): + return formatted_flat_dict(self) + + def __eq__(self, other): + if other is None: + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self == other diff --git a/src/oci/core/models/performance_based_autotune_policy.py b/src/oci/core/models/performance_based_autotune_policy.py new file mode 100644 index 0000000000..35df3b2824 --- /dev/null +++ b/src/oci/core/models/performance_based_autotune_policy.py @@ -0,0 +1,85 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + +from .autotune_policy import AutotunePolicy +from oci.util import formatted_flat_dict, NONE_SENTINEL, value_allowed_none_or_none_sentinel # noqa: F401 +from oci.decorators import init_model_state_from_kwargs + + +@init_model_state_from_kwargs +class PerformanceBasedAutotunePolicy(AutotunePolicy): + """ + If a volume is being throttled at the current setting for a certain period of time, auto-tune will + gradually increase the volume\u2019s performance limited up to Maximum VPUs/GB. After the volume has been idle at the + current setting for a certain period of time, auto-tune will gradually decrease the volume\u2019s performance limited + down to Default/Minimum VPUs/GB. + """ + + def __init__(self, **kwargs): + """ + Initializes a new PerformanceBasedAutotunePolicy object with values from keyword arguments. The default value of the :py:attr:`~oci.core.models.PerformanceBasedAutotunePolicy.autotune_type` attribute + of this class is ``PERFORMANCE_BASED`` and it should not be changed. + The following keyword arguments are supported (corresponding to the getters/setters of this class): + + :param autotune_type: + The value to assign to the autotune_type property of this PerformanceBasedAutotunePolicy. + Allowed values for this property are: "DETACHED_VOLUME", "PERFORMANCE_BASED" + :type autotune_type: str + + :param max_vpus_per_gb: + The value to assign to the max_vpus_per_gb property of this PerformanceBasedAutotunePolicy. + :type max_vpus_per_gb: int + + """ + self.swagger_types = { + 'autotune_type': 'str', + 'max_vpus_per_gb': 'int' + } + + self.attribute_map = { + 'autotune_type': 'autotuneType', + 'max_vpus_per_gb': 'maxVpusPerGB' + } + + self._autotune_type = None + self._max_vpus_per_gb = None + self._autotune_type = 'PERFORMANCE_BASED' + + @property + def max_vpus_per_gb(self): + """ + **[Required]** Gets the max_vpus_per_gb of this PerformanceBasedAutotunePolicy. + This will be the maximum VPUs/GB performance level that the volume will be auto-tuned + temporarily based on performance monitoring. + + + :return: The max_vpus_per_gb of this PerformanceBasedAutotunePolicy. + :rtype: int + """ + return self._max_vpus_per_gb + + @max_vpus_per_gb.setter + def max_vpus_per_gb(self, max_vpus_per_gb): + """ + Sets the max_vpus_per_gb of this PerformanceBasedAutotunePolicy. + This will be the maximum VPUs/GB performance level that the volume will be auto-tuned + temporarily based on performance monitoring. + + + :param max_vpus_per_gb: The max_vpus_per_gb of this PerformanceBasedAutotunePolicy. + :type: int + """ + self._max_vpus_per_gb = max_vpus_per_gb + + def __repr__(self): + return formatted_flat_dict(self) + + def __eq__(self, other): + if other is None: + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self == other diff --git a/src/oci/core/models/update_boot_volume_details.py b/src/oci/core/models/update_boot_volume_details.py index dcab0c22a7..1b21285465 100644 --- a/src/oci/core/models/update_boot_volume_details.py +++ b/src/oci/core/models/update_boot_volume_details.py @@ -46,6 +46,10 @@ def __init__(self, **kwargs): The value to assign to the boot_volume_replicas property of this UpdateBootVolumeDetails. :type boot_volume_replicas: list[oci.core.models.BootVolumeReplicaDetails] + :param autotune_policies: + The value to assign to the autotune_policies property of this UpdateBootVolumeDetails. + :type autotune_policies: list[oci.core.models.AutotunePolicy] + """ self.swagger_types = { 'defined_tags': 'dict(str, dict(str, object))', @@ -54,7 +58,8 @@ def __init__(self, **kwargs): 'size_in_gbs': 'int', 'vpus_per_gb': 'int', 'is_auto_tune_enabled': 'bool', - 'boot_volume_replicas': 'list[BootVolumeReplicaDetails]' + 'boot_volume_replicas': 'list[BootVolumeReplicaDetails]', + 'autotune_policies': 'list[AutotunePolicy]' } self.attribute_map = { @@ -64,7 +69,8 @@ def __init__(self, **kwargs): 'size_in_gbs': 'sizeInGBs', 'vpus_per_gb': 'vpusPerGB', 'is_auto_tune_enabled': 'isAutoTuneEnabled', - 'boot_volume_replicas': 'bootVolumeReplicas' + 'boot_volume_replicas': 'bootVolumeReplicas', + 'autotune_policies': 'autotunePolicies' } self._defined_tags = None @@ -74,6 +80,7 @@ def __init__(self, **kwargs): self._vpus_per_gb = None self._is_auto_tune_enabled = None self._boot_volume_replicas = None + self._autotune_policies = None @property def defined_tags(self): @@ -209,6 +216,8 @@ def vpus_per_gb(self): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -233,6 +242,8 @@ def vpus_per_gb(self, vpus_per_gb): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -245,7 +256,8 @@ def vpus_per_gb(self, vpus_per_gb): def is_auto_tune_enabled(self): """ Gets the is_auto_tune_enabled of this UpdateBootVolumeDetails. - Specifies whether the auto-tune performance is enabled for this boot volume. + Specifies whether the auto-tune performance is enabled for this boot volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :return: The is_auto_tune_enabled of this UpdateBootVolumeDetails. @@ -257,7 +269,8 @@ def is_auto_tune_enabled(self): def is_auto_tune_enabled(self, is_auto_tune_enabled): """ Sets the is_auto_tune_enabled of this UpdateBootVolumeDetails. - Specifies whether the auto-tune performance is enabled for this boot volume. + Specifies whether the auto-tune performance is enabled for this boot volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :param is_auto_tune_enabled: The is_auto_tune_enabled of this UpdateBootVolumeDetails. @@ -291,6 +304,30 @@ def boot_volume_replicas(self, boot_volume_replicas): """ self._boot_volume_replicas = boot_volume_replicas + @property + def autotune_policies(self): + """ + Gets the autotune_policies of this UpdateBootVolumeDetails. + The list of autotune policies to be enabled for this volume. + + + :return: The autotune_policies of this UpdateBootVolumeDetails. + :rtype: list[oci.core.models.AutotunePolicy] + """ + return self._autotune_policies + + @autotune_policies.setter + def autotune_policies(self, autotune_policies): + """ + Sets the autotune_policies of this UpdateBootVolumeDetails. + The list of autotune policies to be enabled for this volume. + + + :param autotune_policies: The autotune_policies of this UpdateBootVolumeDetails. + :type: list[oci.core.models.AutotunePolicy] + """ + self._autotune_policies = autotune_policies + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/core/models/update_volume_details.py b/src/oci/core/models/update_volume_details.py index e47784ae8d..217ed328c8 100644 --- a/src/oci/core/models/update_volume_details.py +++ b/src/oci/core/models/update_volume_details.py @@ -46,6 +46,10 @@ def __init__(self, **kwargs): The value to assign to the block_volume_replicas property of this UpdateVolumeDetails. :type block_volume_replicas: list[oci.core.models.BlockVolumeReplicaDetails] + :param autotune_policies: + The value to assign to the autotune_policies property of this UpdateVolumeDetails. + :type autotune_policies: list[oci.core.models.AutotunePolicy] + """ self.swagger_types = { 'defined_tags': 'dict(str, dict(str, object))', @@ -54,7 +58,8 @@ def __init__(self, **kwargs): 'vpus_per_gb': 'int', 'size_in_gbs': 'int', 'is_auto_tune_enabled': 'bool', - 'block_volume_replicas': 'list[BlockVolumeReplicaDetails]' + 'block_volume_replicas': 'list[BlockVolumeReplicaDetails]', + 'autotune_policies': 'list[AutotunePolicy]' } self.attribute_map = { @@ -64,7 +69,8 @@ def __init__(self, **kwargs): 'vpus_per_gb': 'vpusPerGB', 'size_in_gbs': 'sizeInGBs', 'is_auto_tune_enabled': 'isAutoTuneEnabled', - 'block_volume_replicas': 'blockVolumeReplicas' + 'block_volume_replicas': 'blockVolumeReplicas', + 'autotune_policies': 'autotunePolicies' } self._defined_tags = None @@ -74,6 +80,7 @@ def __init__(self, **kwargs): self._size_in_gbs = None self._is_auto_tune_enabled = None self._block_volume_replicas = None + self._autotune_policies = None @property def defined_tags(self): @@ -187,6 +194,8 @@ def vpus_per_gb(self): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -213,6 +222,8 @@ def vpus_per_gb(self, vpus_per_gb): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, it would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -249,7 +260,8 @@ def size_in_gbs(self, size_in_gbs): def is_auto_tune_enabled(self): """ Gets the is_auto_tune_enabled of this UpdateVolumeDetails. - Specifies whether the auto-tune performance is enabled for this volume. + Specifies whether the auto-tune performance is enabled for this volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :return: The is_auto_tune_enabled of this UpdateVolumeDetails. @@ -261,7 +273,8 @@ def is_auto_tune_enabled(self): def is_auto_tune_enabled(self, is_auto_tune_enabled): """ Sets the is_auto_tune_enabled of this UpdateVolumeDetails. - Specifies whether the auto-tune performance is enabled for this volume. + Specifies whether the auto-tune performance is enabled for this volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :param is_auto_tune_enabled: The is_auto_tune_enabled of this UpdateVolumeDetails. @@ -295,6 +308,30 @@ def block_volume_replicas(self, block_volume_replicas): """ self._block_volume_replicas = block_volume_replicas + @property + def autotune_policies(self): + """ + Gets the autotune_policies of this UpdateVolumeDetails. + The list of autotune policies enabled for this volume. + + + :return: The autotune_policies of this UpdateVolumeDetails. + :rtype: list[oci.core.models.AutotunePolicy] + """ + return self._autotune_policies + + @autotune_policies.setter + def autotune_policies(self, autotune_policies): + """ + Sets the autotune_policies of this UpdateVolumeDetails. + The list of autotune policies enabled for this volume. + + + :param autotune_policies: The autotune_policies of this UpdateVolumeDetails. + :type: list[oci.core.models.AutotunePolicy] + """ + self._autotune_policies = autotune_policies + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/core/models/volume.py b/src/oci/core/models/volume.py index 702f13b9a5..4dd3a23ad9 100644 --- a/src/oci/core/models/volume.py +++ b/src/oci/core/models/volume.py @@ -132,6 +132,10 @@ def __init__(self, **kwargs): The value to assign to the block_volume_replicas property of this Volume. :type block_volume_replicas: list[oci.core.models.BlockVolumeReplicaInfo] + :param autotune_policies: + The value to assign to the autotune_policies property of this Volume. + :type autotune_policies: list[oci.core.models.AutotunePolicy] + """ self.swagger_types = { 'availability_domain': 'str', @@ -152,7 +156,8 @@ def __init__(self, **kwargs): 'volume_group_id': 'str', 'is_auto_tune_enabled': 'bool', 'auto_tuned_vpus_per_gb': 'int', - 'block_volume_replicas': 'list[BlockVolumeReplicaInfo]' + 'block_volume_replicas': 'list[BlockVolumeReplicaInfo]', + 'autotune_policies': 'list[AutotunePolicy]' } self.attribute_map = { @@ -174,7 +179,8 @@ def __init__(self, **kwargs): 'volume_group_id': 'volumeGroupId', 'is_auto_tune_enabled': 'isAutoTuneEnabled', 'auto_tuned_vpus_per_gb': 'autoTunedVpusPerGB', - 'block_volume_replicas': 'blockVolumeReplicas' + 'block_volume_replicas': 'blockVolumeReplicas', + 'autotune_policies': 'autotunePolicies' } self._availability_domain = None @@ -196,6 +202,7 @@ def __init__(self, **kwargs): self._is_auto_tune_enabled = None self._auto_tuned_vpus_per_gb = None self._block_volume_replicas = None + self._autotune_policies = None @property def availability_domain(self): @@ -489,6 +496,8 @@ def vpus_per_gb(self): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, It would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -515,6 +524,8 @@ def vpus_per_gb(self, vpus_per_gb): * `30`-`120`: Represents the Ultra High Performance option. + For performance autotune enabled volumes, It would be the Default(Minimum) VPUs/GB. + __ https://docs.cloud.oracle.com/iaas/Content/Block/Concepts/blockvolumeperformance.htm#perf_levels @@ -649,7 +660,8 @@ def volume_group_id(self, volume_group_id): def is_auto_tune_enabled(self): """ Gets the is_auto_tune_enabled of this Volume. - Specifies whether the auto-tune performance is enabled for this volume. + Specifies whether the auto-tune performance is enabled for this volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :return: The is_auto_tune_enabled of this Volume. @@ -661,7 +673,8 @@ def is_auto_tune_enabled(self): def is_auto_tune_enabled(self, is_auto_tune_enabled): """ Sets the is_auto_tune_enabled of this Volume. - Specifies whether the auto-tune performance is enabled for this volume. + Specifies whether the auto-tune performance is enabled for this volume. This field is deprecated. + Use the `DetachedVolumeAutotunePolicy` instead to enable the volume for detached autotune. :param is_auto_tune_enabled: The is_auto_tune_enabled of this Volume. @@ -673,7 +686,7 @@ def is_auto_tune_enabled(self, is_auto_tune_enabled): def auto_tuned_vpus_per_gb(self): """ Gets the auto_tuned_vpus_per_gb of this Volume. - The number of Volume Performance Units per GB that this volume is effectively tuned to when it's idle. + The number of Volume Performance Units per GB that this volume is effectively tuned to. :return: The auto_tuned_vpus_per_gb of this Volume. @@ -685,7 +698,7 @@ def auto_tuned_vpus_per_gb(self): def auto_tuned_vpus_per_gb(self, auto_tuned_vpus_per_gb): """ Sets the auto_tuned_vpus_per_gb of this Volume. - The number of Volume Performance Units per GB that this volume is effectively tuned to when it's idle. + The number of Volume Performance Units per GB that this volume is effectively tuned to. :param auto_tuned_vpus_per_gb: The auto_tuned_vpus_per_gb of this Volume. @@ -717,6 +730,30 @@ def block_volume_replicas(self, block_volume_replicas): """ self._block_volume_replicas = block_volume_replicas + @property + def autotune_policies(self): + """ + Gets the autotune_policies of this Volume. + The list of autotune policies enabled for this volume. + + + :return: The autotune_policies of this Volume. + :rtype: list[oci.core.models.AutotunePolicy] + """ + return self._autotune_policies + + @autotune_policies.setter + def autotune_policies(self, autotune_policies): + """ + Sets the autotune_policies of this Volume. + The list of autotune policies enabled for this volume. + + + :param autotune_policies: The autotune_policies of this Volume. + :type: list[oci.core.models.AutotunePolicy] + """ + self._autotune_policies = autotune_policies + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/database/models/create_data_guard_association_with_new_db_system_details.py b/src/oci/database/models/create_data_guard_association_with_new_db_system_details.py index aac52721d4..0ba91f09a9 100644 --- a/src/oci/database/models/create_data_guard_association_with_new_db_system_details.py +++ b/src/oci/database/models/create_data_guard_association_with_new_db_system_details.py @@ -145,6 +145,10 @@ def __init__(self, **kwargs): The value to assign to the database_defined_tags property of this CreateDataGuardAssociationWithNewDbSystemDetails. :type database_defined_tags: dict(str, dict(str, object)) + :param data_collection_options: + The value to assign to the data_collection_options property of this CreateDataGuardAssociationWithNewDbSystemDetails. + :type data_collection_options: oci.database.models.DataCollectionOptions + """ self.swagger_types = { 'database_software_image_id': 'str', @@ -172,7 +176,8 @@ def __init__(self, **kwargs): 'db_system_freeform_tags': 'dict(str, str)', 'db_system_defined_tags': 'dict(str, dict(str, object))', 'database_freeform_tags': 'dict(str, str)', - 'database_defined_tags': 'dict(str, dict(str, object))' + 'database_defined_tags': 'dict(str, dict(str, object))', + 'data_collection_options': 'DataCollectionOptions' } self.attribute_map = { @@ -201,7 +206,8 @@ def __init__(self, **kwargs): 'db_system_freeform_tags': 'dbSystemFreeformTags', 'db_system_defined_tags': 'dbSystemDefinedTags', 'database_freeform_tags': 'databaseFreeformTags', - 'database_defined_tags': 'databaseDefinedTags' + 'database_defined_tags': 'databaseDefinedTags', + 'data_collection_options': 'dataCollectionOptions' } self._database_software_image_id = None @@ -230,6 +236,7 @@ def __init__(self, **kwargs): self._db_system_defined_tags = None self._database_freeform_tags = None self._database_defined_tags = None + self._data_collection_options = None self._creation_type = 'NewDbSystem' @property @@ -788,6 +795,26 @@ def database_defined_tags(self, database_defined_tags): """ self._database_defined_tags = database_defined_tags + @property + def data_collection_options(self): + """ + Gets the data_collection_options of this CreateDataGuardAssociationWithNewDbSystemDetails. + + :return: The data_collection_options of this CreateDataGuardAssociationWithNewDbSystemDetails. + :rtype: oci.database.models.DataCollectionOptions + """ + return self._data_collection_options + + @data_collection_options.setter + def data_collection_options(self, data_collection_options): + """ + Sets the data_collection_options of this CreateDataGuardAssociationWithNewDbSystemDetails. + + :param data_collection_options: The data_collection_options of this CreateDataGuardAssociationWithNewDbSystemDetails. + :type: oci.database.models.DataCollectionOptions + """ + self._data_collection_options = data_collection_options + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/database/models/data_collection_options.py b/src/oci/database/models/data_collection_options.py index f77d725be7..75846a1afa 100644 --- a/src/oci/database/models/data_collection_options.py +++ b/src/oci/database/models/data_collection_options.py @@ -22,16 +22,30 @@ def __init__(self, **kwargs): The value to assign to the is_diagnostics_events_enabled property of this DataCollectionOptions. :type is_diagnostics_events_enabled: bool + :param is_health_monitoring_enabled: + The value to assign to the is_health_monitoring_enabled property of this DataCollectionOptions. + :type is_health_monitoring_enabled: bool + + :param is_incident_logs_enabled: + The value to assign to the is_incident_logs_enabled property of this DataCollectionOptions. + :type is_incident_logs_enabled: bool + """ self.swagger_types = { - 'is_diagnostics_events_enabled': 'bool' + 'is_diagnostics_events_enabled': 'bool', + 'is_health_monitoring_enabled': 'bool', + 'is_incident_logs_enabled': 'bool' } self.attribute_map = { - 'is_diagnostics_events_enabled': 'isDiagnosticsEventsEnabled' + 'is_diagnostics_events_enabled': 'isDiagnosticsEventsEnabled', + 'is_health_monitoring_enabled': 'isHealthMonitoringEnabled', + 'is_incident_logs_enabled': 'isIncidentLogsEnabled' } self._is_diagnostics_events_enabled = None + self._is_health_monitoring_enabled = None + self._is_incident_logs_enabled = None @property def is_diagnostics_events_enabled(self): @@ -57,6 +71,58 @@ def is_diagnostics_events_enabled(self, is_diagnostics_events_enabled): """ self._is_diagnostics_events_enabled = is_diagnostics_events_enabled + @property + def is_health_monitoring_enabled(self): + """ + Gets the is_health_monitoring_enabled of this DataCollectionOptions. + Indicates whether health monitoring is enabled for the VM cluster / Cloud VM cluster / VMBM DBCS. Enabling health monitoring allows Oracle to collect diagnostic data and share it with its operations and support personnel. You may also receive notifications for some events. Collecting health diagnostics enables Oracle to provide proactive support and enhanced service for your system. + Optionally enable health monitoring while provisioning a system. You can also disable or enable health monitoring anytime using the `UpdateVmCluster`, `UpdateCloudVmCluster` or `updateDbsystem` API. + + + :return: The is_health_monitoring_enabled of this DataCollectionOptions. + :rtype: bool + """ + return self._is_health_monitoring_enabled + + @is_health_monitoring_enabled.setter + def is_health_monitoring_enabled(self, is_health_monitoring_enabled): + """ + Sets the is_health_monitoring_enabled of this DataCollectionOptions. + Indicates whether health monitoring is enabled for the VM cluster / Cloud VM cluster / VMBM DBCS. Enabling health monitoring allows Oracle to collect diagnostic data and share it with its operations and support personnel. You may also receive notifications for some events. Collecting health diagnostics enables Oracle to provide proactive support and enhanced service for your system. + Optionally enable health monitoring while provisioning a system. You can also disable or enable health monitoring anytime using the `UpdateVmCluster`, `UpdateCloudVmCluster` or `updateDbsystem` API. + + + :param is_health_monitoring_enabled: The is_health_monitoring_enabled of this DataCollectionOptions. + :type: bool + """ + self._is_health_monitoring_enabled = is_health_monitoring_enabled + + @property + def is_incident_logs_enabled(self): + """ + Gets the is_incident_logs_enabled of this DataCollectionOptions. + Indicates whether incident logs and trace collection are enabled for the VM cluster / Cloud VM cluster / VMBM DBCS. Enabling incident logs collection allows Oracle to receive Events service notifications for guest VM issues, collect incident logs and traces, and use them to diagnose issues and resolve them. + Optionally enable incident logs collection while provisioning a system. You can also disable or enable incident logs collection anytime using the `UpdateVmCluster`, `updateCloudVmCluster` or `updateDbsystem` API. + + + :return: The is_incident_logs_enabled of this DataCollectionOptions. + :rtype: bool + """ + return self._is_incident_logs_enabled + + @is_incident_logs_enabled.setter + def is_incident_logs_enabled(self, is_incident_logs_enabled): + """ + Sets the is_incident_logs_enabled of this DataCollectionOptions. + Indicates whether incident logs and trace collection are enabled for the VM cluster / Cloud VM cluster / VMBM DBCS. Enabling incident logs collection allows Oracle to receive Events service notifications for guest VM issues, collect incident logs and traces, and use them to diagnose issues and resolve them. + Optionally enable incident logs collection while provisioning a system. You can also disable or enable incident logs collection anytime using the `UpdateVmCluster`, `updateCloudVmCluster` or `updateDbsystem` API. + + + :param is_incident_logs_enabled: The is_incident_logs_enabled of this DataCollectionOptions. + :type: bool + """ + self._is_incident_logs_enabled = is_incident_logs_enabled + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/database/models/db_system.py b/src/oci/database/models/db_system.py index af197382c0..8ab010cd8a 100644 --- a/src/oci/database/models/db_system.py +++ b/src/oci/database/models/db_system.py @@ -296,6 +296,10 @@ def __init__(self, **kwargs): The value to assign to the point_in_time_data_disk_clone_timestamp property of this DbSystem. :type point_in_time_data_disk_clone_timestamp: datetime + :param data_collection_options: + The value to assign to the data_collection_options property of this DbSystem. + :type data_collection_options: oci.database.models.DataCollectionOptions + """ self.swagger_types = { 'iorm_config_cache': 'ExadataIormConfig', @@ -344,7 +348,8 @@ def __init__(self, **kwargs): 'freeform_tags': 'dict(str, str)', 'defined_tags': 'dict(str, dict(str, object))', 'source_db_system_id': 'str', - 'point_in_time_data_disk_clone_timestamp': 'datetime' + 'point_in_time_data_disk_clone_timestamp': 'datetime', + 'data_collection_options': 'DataCollectionOptions' } self.attribute_map = { @@ -394,7 +399,8 @@ def __init__(self, **kwargs): 'freeform_tags': 'freeformTags', 'defined_tags': 'definedTags', 'source_db_system_id': 'sourceDbSystemId', - 'point_in_time_data_disk_clone_timestamp': 'pointInTimeDataDiskCloneTimestamp' + 'point_in_time_data_disk_clone_timestamp': 'pointInTimeDataDiskCloneTimestamp', + 'data_collection_options': 'dataCollectionOptions' } self._iorm_config_cache = None @@ -444,6 +450,7 @@ def __init__(self, **kwargs): self._defined_tags = None self._source_db_system_id = None self._point_in_time_data_disk_clone_timestamp = None + self._data_collection_options = None @property def iorm_config_cache(self): @@ -1725,6 +1732,26 @@ def point_in_time_data_disk_clone_timestamp(self, point_in_time_data_disk_clone_ """ self._point_in_time_data_disk_clone_timestamp = point_in_time_data_disk_clone_timestamp + @property + def data_collection_options(self): + """ + Gets the data_collection_options of this DbSystem. + + :return: The data_collection_options of this DbSystem. + :rtype: oci.database.models.DataCollectionOptions + """ + return self._data_collection_options + + @data_collection_options.setter + def data_collection_options(self, data_collection_options): + """ + Sets the data_collection_options of this DbSystem. + + :param data_collection_options: The data_collection_options of this DbSystem. + :type: oci.database.models.DataCollectionOptions + """ + self._data_collection_options = data_collection_options + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/database/models/db_system_summary.py b/src/oci/database/models/db_system_summary.py index 8d02b7de4c..e81e54b2a9 100644 --- a/src/oci/database/models/db_system_summary.py +++ b/src/oci/database/models/db_system_summary.py @@ -321,6 +321,10 @@ def __init__(self, **kwargs): The value to assign to the point_in_time_data_disk_clone_timestamp property of this DbSystemSummary. :type point_in_time_data_disk_clone_timestamp: datetime + :param data_collection_options: + The value to assign to the data_collection_options property of this DbSystemSummary. + :type data_collection_options: oci.database.models.DataCollectionOptions + """ self.swagger_types = { 'id': 'str', @@ -368,7 +372,8 @@ def __init__(self, **kwargs): 'freeform_tags': 'dict(str, str)', 'defined_tags': 'dict(str, dict(str, object))', 'source_db_system_id': 'str', - 'point_in_time_data_disk_clone_timestamp': 'datetime' + 'point_in_time_data_disk_clone_timestamp': 'datetime', + 'data_collection_options': 'DataCollectionOptions' } self.attribute_map = { @@ -417,7 +422,8 @@ def __init__(self, **kwargs): 'freeform_tags': 'freeformTags', 'defined_tags': 'definedTags', 'source_db_system_id': 'sourceDbSystemId', - 'point_in_time_data_disk_clone_timestamp': 'pointInTimeDataDiskCloneTimestamp' + 'point_in_time_data_disk_clone_timestamp': 'pointInTimeDataDiskCloneTimestamp', + 'data_collection_options': 'dataCollectionOptions' } self._id = None @@ -466,6 +472,7 @@ def __init__(self, **kwargs): self._defined_tags = None self._source_db_system_id = None self._point_in_time_data_disk_clone_timestamp = None + self._data_collection_options = None @property def id(self): @@ -1727,6 +1734,26 @@ def point_in_time_data_disk_clone_timestamp(self, point_in_time_data_disk_clone_ """ self._point_in_time_data_disk_clone_timestamp = point_in_time_data_disk_clone_timestamp + @property + def data_collection_options(self): + """ + Gets the data_collection_options of this DbSystemSummary. + + :return: The data_collection_options of this DbSystemSummary. + :rtype: oci.database.models.DataCollectionOptions + """ + return self._data_collection_options + + @data_collection_options.setter + def data_collection_options(self, data_collection_options): + """ + Sets the data_collection_options of this DbSystemSummary. + + :param data_collection_options: The data_collection_options of this DbSystemSummary. + :type: oci.database.models.DataCollectionOptions + """ + self._data_collection_options = data_collection_options + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/database/models/launch_db_system_base.py b/src/oci/database/models/launch_db_system_base.py index 54e7783cb6..c3284f347c 100644 --- a/src/oci/database/models/launch_db_system_base.py +++ b/src/oci/database/models/launch_db_system_base.py @@ -161,6 +161,10 @@ def __init__(self, **kwargs): The value to assign to the private_ip property of this LaunchDbSystemBase. :type private_ip: str + :param data_collection_options: + The value to assign to the data_collection_options property of this LaunchDbSystemBase. + :type data_collection_options: oci.database.models.DataCollectionOptions + """ self.swagger_types = { 'compartment_id': 'str', @@ -189,7 +193,8 @@ def __init__(self, **kwargs): 'freeform_tags': 'dict(str, str)', 'defined_tags': 'dict(str, dict(str, object))', 'source': 'str', - 'private_ip': 'str' + 'private_ip': 'str', + 'data_collection_options': 'DataCollectionOptions' } self.attribute_map = { @@ -219,7 +224,8 @@ def __init__(self, **kwargs): 'freeform_tags': 'freeformTags', 'defined_tags': 'definedTags', 'source': 'source', - 'private_ip': 'privateIp' + 'private_ip': 'privateIp', + 'data_collection_options': 'dataCollectionOptions' } self._compartment_id = None @@ -249,6 +255,7 @@ def __init__(self, **kwargs): self._defined_tags = None self._source = None self._private_ip = None + self._data_collection_options = None @staticmethod def get_subtype(object_dictionary): @@ -1102,6 +1109,26 @@ def private_ip(self, private_ip): """ self._private_ip = private_ip + @property + def data_collection_options(self): + """ + Gets the data_collection_options of this LaunchDbSystemBase. + + :return: The data_collection_options of this LaunchDbSystemBase. + :rtype: oci.database.models.DataCollectionOptions + """ + return self._data_collection_options + + @data_collection_options.setter + def data_collection_options(self, data_collection_options): + """ + Sets the data_collection_options of this LaunchDbSystemBase. + + :param data_collection_options: The data_collection_options of this LaunchDbSystemBase. + :type: oci.database.models.DataCollectionOptions + """ + self._data_collection_options = data_collection_options + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/database/models/launch_db_system_details.py b/src/oci/database/models/launch_db_system_details.py index 89d7d725b7..e3f51d48dd 100644 --- a/src/oci/database/models/launch_db_system_details.py +++ b/src/oci/database/models/launch_db_system_details.py @@ -161,6 +161,10 @@ def __init__(self, **kwargs): The value to assign to the private_ip property of this LaunchDbSystemDetails. :type private_ip: str + :param data_collection_options: + The value to assign to the data_collection_options property of this LaunchDbSystemDetails. + :type data_collection_options: oci.database.models.DataCollectionOptions + :param db_home: The value to assign to the db_home property of this LaunchDbSystemDetails. :type db_home: oci.database.models.CreateDbHomeDetails @@ -213,6 +217,7 @@ def __init__(self, **kwargs): 'defined_tags': 'dict(str, dict(str, object))', 'source': 'str', 'private_ip': 'str', + 'data_collection_options': 'DataCollectionOptions', 'db_home': 'CreateDbHomeDetails', 'database_edition': 'str', 'disk_redundancy': 'str', @@ -248,6 +253,7 @@ def __init__(self, **kwargs): 'defined_tags': 'definedTags', 'source': 'source', 'private_ip': 'privateIp', + 'data_collection_options': 'dataCollectionOptions', 'db_home': 'dbHome', 'database_edition': 'databaseEdition', 'disk_redundancy': 'diskRedundancy', @@ -282,6 +288,7 @@ def __init__(self, **kwargs): self._defined_tags = None self._source = None self._private_ip = None + self._data_collection_options = None self._db_home = None self._database_edition = None self._disk_redundancy = None diff --git a/src/oci/database/models/launch_db_system_from_backup_details.py b/src/oci/database/models/launch_db_system_from_backup_details.py index f50bc44bb1..532fd7e679 100644 --- a/src/oci/database/models/launch_db_system_from_backup_details.py +++ b/src/oci/database/models/launch_db_system_from_backup_details.py @@ -161,6 +161,10 @@ def __init__(self, **kwargs): The value to assign to the private_ip property of this LaunchDbSystemFromBackupDetails. :type private_ip: str + :param data_collection_options: + The value to assign to the data_collection_options property of this LaunchDbSystemFromBackupDetails. + :type data_collection_options: oci.database.models.DataCollectionOptions + :param db_home: The value to assign to the db_home property of this LaunchDbSystemFromBackupDetails. :type db_home: oci.database.models.CreateDbHomeFromBackupDetails @@ -209,6 +213,7 @@ def __init__(self, **kwargs): 'defined_tags': 'dict(str, dict(str, object))', 'source': 'str', 'private_ip': 'str', + 'data_collection_options': 'DataCollectionOptions', 'db_home': 'CreateDbHomeFromBackupDetails', 'database_edition': 'str', 'disk_redundancy': 'str', @@ -243,6 +248,7 @@ def __init__(self, **kwargs): 'defined_tags': 'definedTags', 'source': 'source', 'private_ip': 'privateIp', + 'data_collection_options': 'dataCollectionOptions', 'db_home': 'dbHome', 'database_edition': 'databaseEdition', 'disk_redundancy': 'diskRedundancy', @@ -276,6 +282,7 @@ def __init__(self, **kwargs): self._defined_tags = None self._source = None self._private_ip = None + self._data_collection_options = None self._db_home = None self._database_edition = None self._disk_redundancy = None diff --git a/src/oci/database/models/launch_db_system_from_database_details.py b/src/oci/database/models/launch_db_system_from_database_details.py index 730046a4f3..57dbcff6cb 100644 --- a/src/oci/database/models/launch_db_system_from_database_details.py +++ b/src/oci/database/models/launch_db_system_from_database_details.py @@ -161,6 +161,10 @@ def __init__(self, **kwargs): The value to assign to the private_ip property of this LaunchDbSystemFromDatabaseDetails. :type private_ip: str + :param data_collection_options: + The value to assign to the data_collection_options property of this LaunchDbSystemFromDatabaseDetails. + :type data_collection_options: oci.database.models.DataCollectionOptions + :param db_home: The value to assign to the db_home property of this LaunchDbSystemFromDatabaseDetails. :type db_home: oci.database.models.CreateDbHomeFromDatabaseDetails @@ -209,6 +213,7 @@ def __init__(self, **kwargs): 'defined_tags': 'dict(str, dict(str, object))', 'source': 'str', 'private_ip': 'str', + 'data_collection_options': 'DataCollectionOptions', 'db_home': 'CreateDbHomeFromDatabaseDetails', 'database_edition': 'str', 'disk_redundancy': 'str', @@ -243,6 +248,7 @@ def __init__(self, **kwargs): 'defined_tags': 'definedTags', 'source': 'source', 'private_ip': 'privateIp', + 'data_collection_options': 'dataCollectionOptions', 'db_home': 'dbHome', 'database_edition': 'databaseEdition', 'disk_redundancy': 'diskRedundancy', @@ -276,6 +282,7 @@ def __init__(self, **kwargs): self._defined_tags = None self._source = None self._private_ip = None + self._data_collection_options = None self._db_home = None self._database_edition = None self._disk_redundancy = None diff --git a/src/oci/database/models/launch_db_system_from_db_system_details.py b/src/oci/database/models/launch_db_system_from_db_system_details.py index a8b80d0063..6043e6051a 100644 --- a/src/oci/database/models/launch_db_system_from_db_system_details.py +++ b/src/oci/database/models/launch_db_system_from_db_system_details.py @@ -137,6 +137,10 @@ def __init__(self, **kwargs): The value to assign to the private_ip property of this LaunchDbSystemFromDbSystemDetails. :type private_ip: str + :param data_collection_options: + The value to assign to the data_collection_options property of this LaunchDbSystemFromDbSystemDetails. + :type data_collection_options: oci.database.models.DataCollectionOptions + :param source_db_system_id: The value to assign to the source_db_system_id property of this LaunchDbSystemFromDbSystemDetails. :type source_db_system_id: str @@ -179,6 +183,7 @@ def __init__(self, **kwargs): 'defined_tags': 'dict(str, dict(str, object))', 'source': 'str', 'private_ip': 'str', + 'data_collection_options': 'DataCollectionOptions', 'source_db_system_id': 'str', 'db_home': 'CreateDbHomeFromDbSystemDetails', 'license_model': 'str' @@ -212,6 +217,7 @@ def __init__(self, **kwargs): 'defined_tags': 'definedTags', 'source': 'source', 'private_ip': 'privateIp', + 'data_collection_options': 'dataCollectionOptions', 'source_db_system_id': 'sourceDbSystemId', 'db_home': 'dbHome', 'license_model': 'licenseModel' @@ -244,6 +250,7 @@ def __init__(self, **kwargs): self._defined_tags = None self._source = None self._private_ip = None + self._data_collection_options = None self._source_db_system_id = None self._db_home = None self._license_model = None diff --git a/src/oci/database/models/update_db_system_details.py b/src/oci/database/models/update_db_system_details.py index a46da0470c..110ff7fcf2 100644 --- a/src/oci/database/models/update_db_system_details.py +++ b/src/oci/database/models/update_db_system_details.py @@ -77,6 +77,10 @@ def __init__(self, **kwargs): The value to assign to the maintenance_window_details property of this UpdateDbSystemDetails. :type maintenance_window_details: oci.database.models.MaintenanceWindow + :param data_collection_options: + The value to assign to the data_collection_options property of this UpdateDbSystemDetails. + :type data_collection_options: oci.database.models.DataCollectionOptions + """ self.swagger_types = { 'cpu_core_count': 'int', @@ -90,7 +94,8 @@ def __init__(self, **kwargs): 'nsg_ids': 'list[str]', 'backup_network_nsg_ids': 'list[str]', 'license_model': 'str', - 'maintenance_window_details': 'MaintenanceWindow' + 'maintenance_window_details': 'MaintenanceWindow', + 'data_collection_options': 'DataCollectionOptions' } self.attribute_map = { @@ -105,7 +110,8 @@ def __init__(self, **kwargs): 'nsg_ids': 'nsgIds', 'backup_network_nsg_ids': 'backupNetworkNsgIds', 'license_model': 'licenseModel', - 'maintenance_window_details': 'maintenanceWindowDetails' + 'maintenance_window_details': 'maintenanceWindowDetails', + 'data_collection_options': 'dataCollectionOptions' } self._cpu_core_count = None @@ -120,6 +126,7 @@ def __init__(self, **kwargs): self._backup_network_nsg_ids = None self._license_model = None self._maintenance_window_details = None + self._data_collection_options = None @property def cpu_core_count(self): @@ -447,6 +454,26 @@ def maintenance_window_details(self, maintenance_window_details): """ self._maintenance_window_details = maintenance_window_details + @property + def data_collection_options(self): + """ + Gets the data_collection_options of this UpdateDbSystemDetails. + + :return: The data_collection_options of this UpdateDbSystemDetails. + :rtype: oci.database.models.DataCollectionOptions + """ + return self._data_collection_options + + @data_collection_options.setter + def data_collection_options(self, data_collection_options): + """ + Sets the data_collection_options of this UpdateDbSystemDetails. + + :param data_collection_options: The data_collection_options of this UpdateDbSystemDetails. + :type: oci.database.models.DataCollectionOptions + """ + self._data_collection_options = data_collection_options + def __repr__(self): return formatted_flat_dict(self) diff --git a/src/oci/ocvp/models/__init__.py b/src/oci/ocvp/models/__init__.py index c6f7a37924..5b5dec074c 100644 --- a/src/oci/ocvp/models/__init__.py +++ b/src/oci/ocvp/models/__init__.py @@ -23,6 +23,8 @@ from .supported_vmware_software_version_summary import SupportedVmwareSoftwareVersionSummary from .update_esxi_host_details import UpdateEsxiHostDetails from .update_sddc_details import UpdateSddcDetails +from .vsphere_license import VsphereLicense +from .vsphere_upgrade_object import VsphereUpgradeObject from .work_request import WorkRequest from .work_request_collection import WorkRequestCollection from .work_request_error import WorkRequestError @@ -52,6 +54,8 @@ "SupportedVmwareSoftwareVersionSummary": SupportedVmwareSoftwareVersionSummary, "UpdateEsxiHostDetails": UpdateEsxiHostDetails, "UpdateSddcDetails": UpdateSddcDetails, + "VsphereLicense": VsphereLicense, + "VsphereUpgradeObject": VsphereUpgradeObject, "WorkRequest": WorkRequest, "WorkRequestCollection": WorkRequestCollection, "WorkRequestError": WorkRequestError, diff --git a/src/oci/ocvp/models/create_esxi_host_details.py b/src/oci/ocvp/models/create_esxi_host_details.py index 8fc7d27b52..5f9d0cfc8f 100644 --- a/src/oci/ocvp/models/create_esxi_host_details.py +++ b/src/oci/ocvp/models/create_esxi_host_details.py @@ -88,6 +88,10 @@ def __init__(self, **kwargs): The value to assign to the capacity_reservation_id property of this CreateEsxiHostDetails. :type capacity_reservation_id: str + :param non_upgraded_esxi_host_id: + The value to assign to the non_upgraded_esxi_host_id property of this CreateEsxiHostDetails. + :type non_upgraded_esxi_host_id: str + :param freeform_tags: The value to assign to the freeform_tags property of this CreateEsxiHostDetails. :type freeform_tags: dict(str, str) @@ -107,6 +111,7 @@ def __init__(self, **kwargs): 'host_shape_name': 'str', 'host_ocpu_count': 'float', 'capacity_reservation_id': 'str', + 'non_upgraded_esxi_host_id': 'str', 'freeform_tags': 'dict(str, str)', 'defined_tags': 'dict(str, dict(str, object))' } @@ -121,6 +126,7 @@ def __init__(self, **kwargs): 'host_shape_name': 'hostShapeName', 'host_ocpu_count': 'hostOcpuCount', 'capacity_reservation_id': 'capacityReservationId', + 'non_upgraded_esxi_host_id': 'nonUpgradedEsxiHostId', 'freeform_tags': 'freeformTags', 'defined_tags': 'definedTags' } @@ -134,6 +140,7 @@ def __init__(self, **kwargs): self._host_shape_name = None self._host_ocpu_count = None self._capacity_reservation_id = None + self._non_upgraded_esxi_host_id = None self._freeform_tags = None self._defined_tags = None @@ -312,7 +319,7 @@ def failed_esxi_host_id(self): The `OCID`__ of the ESXi host that is failed. This is an optional parameter. If this parameter is specified, a new ESXi host will be created to replace the failed one, and the `failedEsxiHostId` field - will be udpated in the newly created Esxi host. + will be updated in the newly created Esxi host. __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm @@ -329,7 +336,7 @@ def failed_esxi_host_id(self, failed_esxi_host_id): The `OCID`__ of the ESXi host that is failed. This is an optional parameter. If this parameter is specified, a new ESXi host will be created to replace the failed one, and the `failedEsxiHostId` field - will be udpated in the newly created Esxi host. + will be updated in the newly created Esxi host. __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm @@ -417,6 +424,42 @@ def capacity_reservation_id(self, capacity_reservation_id): """ self._capacity_reservation_id = capacity_reservation_id + @property + def non_upgraded_esxi_host_id(self): + """ + Gets the non_upgraded_esxi_host_id of this CreateEsxiHostDetails. + The `OCID`__ of the ESXi host that + will be upgraded. This is an optional parameter. If this parameter + is specified, an ESXi host with new version will be created to replace the + original one, and the `nonUpgradedEsxiHostId` field will be updated in the newly + created Esxi host. + + __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm + + + :return: The non_upgraded_esxi_host_id of this CreateEsxiHostDetails. + :rtype: str + """ + return self._non_upgraded_esxi_host_id + + @non_upgraded_esxi_host_id.setter + def non_upgraded_esxi_host_id(self, non_upgraded_esxi_host_id): + """ + Sets the non_upgraded_esxi_host_id of this CreateEsxiHostDetails. + The `OCID`__ of the ESXi host that + will be upgraded. This is an optional parameter. If this parameter + is specified, an ESXi host with new version will be created to replace the + original one, and the `nonUpgradedEsxiHostId` field will be updated in the newly + created Esxi host. + + __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm + + + :param non_upgraded_esxi_host_id: The non_upgraded_esxi_host_id of this CreateEsxiHostDetails. + :type: str + """ + self._non_upgraded_esxi_host_id = non_upgraded_esxi_host_id + @property def freeform_tags(self): """ diff --git a/src/oci/ocvp/models/esxi_host.py b/src/oci/ocvp/models/esxi_host.py index aff1b54ceb..df7c40cc74 100644 --- a/src/oci/ocvp/models/esxi_host.py +++ b/src/oci/ocvp/models/esxi_host.py @@ -143,6 +143,18 @@ def __init__(self, **kwargs): The value to assign to the grace_period_end_date property of this EsxiHost. :type grace_period_end_date: datetime + :param vmware_software_version: + The value to assign to the vmware_software_version property of this EsxiHost. + :type vmware_software_version: str + + :param non_upgraded_esxi_host_id: + The value to assign to the non_upgraded_esxi_host_id property of this EsxiHost. + :type non_upgraded_esxi_host_id: str + + :param upgraded_replacement_esxi_host_id: + The value to assign to the upgraded_replacement_esxi_host_id property of this EsxiHost. + :type upgraded_replacement_esxi_host_id: str + :param compute_availability_domain: The value to assign to the compute_availability_domain property of this EsxiHost. :type compute_availability_domain: str @@ -183,6 +195,9 @@ def __init__(self, **kwargs): 'failed_esxi_host_id': 'str', 'replacement_esxi_host_id': 'str', 'grace_period_end_date': 'datetime', + 'vmware_software_version': 'str', + 'non_upgraded_esxi_host_id': 'str', + 'upgraded_replacement_esxi_host_id': 'str', 'compute_availability_domain': 'str', 'host_shape_name': 'str', 'host_ocpu_count': 'float', @@ -206,6 +221,9 @@ def __init__(self, **kwargs): 'failed_esxi_host_id': 'failedEsxiHostId', 'replacement_esxi_host_id': 'replacementEsxiHostId', 'grace_period_end_date': 'gracePeriodEndDate', + 'vmware_software_version': 'vmwareSoftwareVersion', + 'non_upgraded_esxi_host_id': 'nonUpgradedEsxiHostId', + 'upgraded_replacement_esxi_host_id': 'upgradedReplacementEsxiHostId', 'compute_availability_domain': 'computeAvailabilityDomain', 'host_shape_name': 'hostShapeName', 'host_ocpu_count': 'hostOcpuCount', @@ -228,6 +246,9 @@ def __init__(self, **kwargs): self._failed_esxi_host_id = None self._replacement_esxi_host_id = None self._grace_period_end_date = None + self._vmware_software_version = None + self._non_upgraded_esxi_host_id = None + self._upgraded_replacement_esxi_host_id = None self._compute_availability_domain = None self._host_shape_name = None self._host_ocpu_count = None @@ -659,6 +680,90 @@ def grace_period_end_date(self, grace_period_end_date): """ self._grace_period_end_date = grace_period_end_date + @property + def vmware_software_version(self): + """ + **[Required]** Gets the vmware_software_version of this EsxiHost. + The version of VMware software that the Oracle Cloud VMware Solution installed on the ESXi hosts. + + + :return: The vmware_software_version of this EsxiHost. + :rtype: str + """ + return self._vmware_software_version + + @vmware_software_version.setter + def vmware_software_version(self, vmware_software_version): + """ + Sets the vmware_software_version of this EsxiHost. + The version of VMware software that the Oracle Cloud VMware Solution installed on the ESXi hosts. + + + :param vmware_software_version: The vmware_software_version of this EsxiHost. + :type: str + """ + self._vmware_software_version = vmware_software_version + + @property + def non_upgraded_esxi_host_id(self): + """ + Gets the non_upgraded_esxi_host_id of this EsxiHost. + The `OCID`__ of the ESXi host that + will be upgraded. + + __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm + + + :return: The non_upgraded_esxi_host_id of this EsxiHost. + :rtype: str + """ + return self._non_upgraded_esxi_host_id + + @non_upgraded_esxi_host_id.setter + def non_upgraded_esxi_host_id(self, non_upgraded_esxi_host_id): + """ + Sets the non_upgraded_esxi_host_id of this EsxiHost. + The `OCID`__ of the ESXi host that + will be upgraded. + + __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm + + + :param non_upgraded_esxi_host_id: The non_upgraded_esxi_host_id of this EsxiHost. + :type: str + """ + self._non_upgraded_esxi_host_id = non_upgraded_esxi_host_id + + @property + def upgraded_replacement_esxi_host_id(self): + """ + Gets the upgraded_replacement_esxi_host_id of this EsxiHost. + The `OCID`__ of the ESXi host that + is newly created to upgrade the original host. + + __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm + + + :return: The upgraded_replacement_esxi_host_id of this EsxiHost. + :rtype: str + """ + return self._upgraded_replacement_esxi_host_id + + @upgraded_replacement_esxi_host_id.setter + def upgraded_replacement_esxi_host_id(self, upgraded_replacement_esxi_host_id): + """ + Sets the upgraded_replacement_esxi_host_id of this EsxiHost. + The `OCID`__ of the ESXi host that + is newly created to upgrade the original host. + + __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm + + + :param upgraded_replacement_esxi_host_id: The upgraded_replacement_esxi_host_id of this EsxiHost. + :type: str + """ + self._upgraded_replacement_esxi_host_id = upgraded_replacement_esxi_host_id + @property def compute_availability_domain(self): """ diff --git a/src/oci/ocvp/models/esxi_host_summary.py b/src/oci/ocvp/models/esxi_host_summary.py index 75453fa0e6..81cc727cb8 100644 --- a/src/oci/ocvp/models/esxi_host_summary.py +++ b/src/oci/ocvp/models/esxi_host_summary.py @@ -136,6 +136,18 @@ def __init__(self, **kwargs): The value to assign to the grace_period_end_date property of this EsxiHostSummary. :type grace_period_end_date: datetime + :param vmware_software_version: + The value to assign to the vmware_software_version property of this EsxiHostSummary. + :type vmware_software_version: str + + :param non_upgraded_esxi_host_id: + The value to assign to the non_upgraded_esxi_host_id property of this EsxiHostSummary. + :type non_upgraded_esxi_host_id: str + + :param upgraded_replacement_esxi_host_id: + The value to assign to the upgraded_replacement_esxi_host_id property of this EsxiHostSummary. + :type upgraded_replacement_esxi_host_id: str + :param compute_availability_domain: The value to assign to the compute_availability_domain property of this EsxiHostSummary. :type compute_availability_domain: str @@ -172,6 +184,9 @@ def __init__(self, **kwargs): 'failed_esxi_host_id': 'str', 'replacement_esxi_host_id': 'str', 'grace_period_end_date': 'datetime', + 'vmware_software_version': 'str', + 'non_upgraded_esxi_host_id': 'str', + 'upgraded_replacement_esxi_host_id': 'str', 'compute_availability_domain': 'str', 'host_shape_name': 'str', 'host_ocpu_count': 'float', @@ -194,6 +209,9 @@ def __init__(self, **kwargs): 'failed_esxi_host_id': 'failedEsxiHostId', 'replacement_esxi_host_id': 'replacementEsxiHostId', 'grace_period_end_date': 'gracePeriodEndDate', + 'vmware_software_version': 'vmwareSoftwareVersion', + 'non_upgraded_esxi_host_id': 'nonUpgradedEsxiHostId', + 'upgraded_replacement_esxi_host_id': 'upgradedReplacementEsxiHostId', 'compute_availability_domain': 'computeAvailabilityDomain', 'host_shape_name': 'hostShapeName', 'host_ocpu_count': 'hostOcpuCount', @@ -215,6 +233,9 @@ def __init__(self, **kwargs): self._failed_esxi_host_id = None self._replacement_esxi_host_id = None self._grace_period_end_date = None + self._vmware_software_version = None + self._non_upgraded_esxi_host_id = None + self._upgraded_replacement_esxi_host_id = None self._compute_availability_domain = None self._host_shape_name = None self._host_ocpu_count = None @@ -645,6 +666,90 @@ def grace_period_end_date(self, grace_period_end_date): """ self._grace_period_end_date = grace_period_end_date + @property + def vmware_software_version(self): + """ + **[Required]** Gets the vmware_software_version of this EsxiHostSummary. + The version of VMware software that the Oracle Cloud VMware Solution installed on the ESXi hosts. + + + :return: The vmware_software_version of this EsxiHostSummary. + :rtype: str + """ + return self._vmware_software_version + + @vmware_software_version.setter + def vmware_software_version(self, vmware_software_version): + """ + Sets the vmware_software_version of this EsxiHostSummary. + The version of VMware software that the Oracle Cloud VMware Solution installed on the ESXi hosts. + + + :param vmware_software_version: The vmware_software_version of this EsxiHostSummary. + :type: str + """ + self._vmware_software_version = vmware_software_version + + @property + def non_upgraded_esxi_host_id(self): + """ + Gets the non_upgraded_esxi_host_id of this EsxiHostSummary. + The `OCID`__ of the ESXi host that + will be upgraded. + + __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm + + + :return: The non_upgraded_esxi_host_id of this EsxiHostSummary. + :rtype: str + """ + return self._non_upgraded_esxi_host_id + + @non_upgraded_esxi_host_id.setter + def non_upgraded_esxi_host_id(self, non_upgraded_esxi_host_id): + """ + Sets the non_upgraded_esxi_host_id of this EsxiHostSummary. + The `OCID`__ of the ESXi host that + will be upgraded. + + __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm + + + :param non_upgraded_esxi_host_id: The non_upgraded_esxi_host_id of this EsxiHostSummary. + :type: str + """ + self._non_upgraded_esxi_host_id = non_upgraded_esxi_host_id + + @property + def upgraded_replacement_esxi_host_id(self): + """ + Gets the upgraded_replacement_esxi_host_id of this EsxiHostSummary. + The `OCID`__ of the ESXi host that + is newly created to upgrade the original host. + + __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm + + + :return: The upgraded_replacement_esxi_host_id of this EsxiHostSummary. + :rtype: str + """ + return self._upgraded_replacement_esxi_host_id + + @upgraded_replacement_esxi_host_id.setter + def upgraded_replacement_esxi_host_id(self, upgraded_replacement_esxi_host_id): + """ + Sets the upgraded_replacement_esxi_host_id of this EsxiHostSummary. + The `OCID`__ of the ESXi host that + is newly created to upgrade the original host. + + __ https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm + + + :param upgraded_replacement_esxi_host_id: The upgraded_replacement_esxi_host_id of this EsxiHostSummary. + :type: str + """ + self._upgraded_replacement_esxi_host_id = upgraded_replacement_esxi_host_id + @property def compute_availability_domain(self): """ diff --git a/src/oci/ocvp/models/sddc.py b/src/oci/ocvp/models/sddc.py index 26fe3f9813..cae3a78942 100644 --- a/src/oci/ocvp/models/sddc.py +++ b/src/oci/ocvp/models/sddc.py @@ -252,6 +252,18 @@ def __init__(self, **kwargs): Any unrecognized values returned by a service will be mapped to 'UNKNOWN_ENUM_VALUE'. :type lifecycle_state: str + :param upgrade_licenses: + The value to assign to the upgrade_licenses property of this Sddc. + :type upgrade_licenses: list[oci.ocvp.models.VsphereLicense] + + :param vsphere_upgrade_guide: + The value to assign to the vsphere_upgrade_guide property of this Sddc. + :type vsphere_upgrade_guide: str + + :param vsphere_upgrade_objects: + The value to assign to the vsphere_upgrade_objects property of this Sddc. + :type vsphere_upgrade_objects: list[oci.ocvp.models.VsphereUpgradeObject] + :param initial_host_shape_name: The value to assign to the initial_host_shape_name property of this Sddc. :type initial_host_shape_name: str @@ -323,6 +335,9 @@ def __init__(self, **kwargs): 'time_created': 'datetime', 'time_updated': 'datetime', 'lifecycle_state': 'str', + 'upgrade_licenses': 'list[VsphereLicense]', + 'vsphere_upgrade_guide': 'str', + 'vsphere_upgrade_objects': 'list[VsphereUpgradeObject]', 'initial_host_shape_name': 'str', 'initial_host_ocpu_count': 'float', 'is_shielded_instance_enabled': 'bool', @@ -377,6 +392,9 @@ def __init__(self, **kwargs): 'time_created': 'timeCreated', 'time_updated': 'timeUpdated', 'lifecycle_state': 'lifecycleState', + 'upgrade_licenses': 'upgradeLicenses', + 'vsphere_upgrade_guide': 'vsphereUpgradeGuide', + 'vsphere_upgrade_objects': 'vsphereUpgradeObjects', 'initial_host_shape_name': 'initialHostShapeName', 'initial_host_ocpu_count': 'initialHostOcpuCount', 'is_shielded_instance_enabled': 'isShieldedInstanceEnabled', @@ -430,6 +448,9 @@ def __init__(self, **kwargs): self._time_created = None self._time_updated = None self._lifecycle_state = None + self._upgrade_licenses = None + self._vsphere_upgrade_guide = None + self._vsphere_upgrade_objects = None self._initial_host_shape_name = None self._initial_host_ocpu_count = None self._is_shielded_instance_enabled = None @@ -1947,6 +1968,78 @@ def lifecycle_state(self, lifecycle_state): lifecycle_state = 'UNKNOWN_ENUM_VALUE' self._lifecycle_state = lifecycle_state + @property + def upgrade_licenses(self): + """ + Gets the upgrade_licenses of this Sddc. + The vSphere licenses to be used when upgrade SDDC. + + + :return: The upgrade_licenses of this Sddc. + :rtype: list[oci.ocvp.models.VsphereLicense] + """ + return self._upgrade_licenses + + @upgrade_licenses.setter + def upgrade_licenses(self, upgrade_licenses): + """ + Sets the upgrade_licenses of this Sddc. + The vSphere licenses to be used when upgrade SDDC. + + + :param upgrade_licenses: The upgrade_licenses of this Sddc. + :type: list[oci.ocvp.models.VsphereLicense] + """ + self._upgrade_licenses = upgrade_licenses + + @property + def vsphere_upgrade_guide(self): + """ + Gets the vsphere_upgrade_guide of this Sddc. + The link of guidance to upgrade vSphere. + + + :return: The vsphere_upgrade_guide of this Sddc. + :rtype: str + """ + return self._vsphere_upgrade_guide + + @vsphere_upgrade_guide.setter + def vsphere_upgrade_guide(self, vsphere_upgrade_guide): + """ + Sets the vsphere_upgrade_guide of this Sddc. + The link of guidance to upgrade vSphere. + + + :param vsphere_upgrade_guide: The vsphere_upgrade_guide of this Sddc. + :type: str + """ + self._vsphere_upgrade_guide = vsphere_upgrade_guide + + @property + def vsphere_upgrade_objects(self): + """ + Gets the vsphere_upgrade_objects of this Sddc. + The links of binary objects needed for upgrade vSphere. + + + :return: The vsphere_upgrade_objects of this Sddc. + :rtype: list[oci.ocvp.models.VsphereUpgradeObject] + """ + return self._vsphere_upgrade_objects + + @vsphere_upgrade_objects.setter + def vsphere_upgrade_objects(self, vsphere_upgrade_objects): + """ + Sets the vsphere_upgrade_objects of this Sddc. + The links of binary objects needed for upgrade vSphere. + + + :param vsphere_upgrade_objects: The vsphere_upgrade_objects of this Sddc. + :type: list[oci.ocvp.models.VsphereUpgradeObject] + """ + self._vsphere_upgrade_objects = vsphere_upgrade_objects + @property def initial_host_shape_name(self): """ diff --git a/src/oci/ocvp/models/vsphere_license.py b/src/oci/ocvp/models/vsphere_license.py new file mode 100644 index 0000000000..f8f91b64ca --- /dev/null +++ b/src/oci/ocvp/models/vsphere_license.py @@ -0,0 +1,101 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + + +from oci.util import formatted_flat_dict, NONE_SENTINEL, value_allowed_none_or_none_sentinel # noqa: F401 +from oci.decorators import init_model_state_from_kwargs + + +@init_model_state_from_kwargs +class VsphereLicense(object): + """ + License for vSphere upgrade. + """ + + def __init__(self, **kwargs): + """ + Initializes a new VsphereLicense object with values from keyword arguments. + The following keyword arguments are supported (corresponding to the getters/setters of this class): + + :param license_type: + The value to assign to the license_type property of this VsphereLicense. + :type license_type: str + + :param license_key: + The value to assign to the license_key property of this VsphereLicense. + :type license_key: str + + """ + self.swagger_types = { + 'license_type': 'str', + 'license_key': 'str' + } + + self.attribute_map = { + 'license_type': 'licenseType', + 'license_key': 'licenseKey' + } + + self._license_type = None + self._license_key = None + + @property + def license_type(self): + """ + **[Required]** Gets the license_type of this VsphereLicense. + vSphere license type. + + + :return: The license_type of this VsphereLicense. + :rtype: str + """ + return self._license_type + + @license_type.setter + def license_type(self, license_type): + """ + Sets the license_type of this VsphereLicense. + vSphere license type. + + + :param license_type: The license_type of this VsphereLicense. + :type: str + """ + self._license_type = license_type + + @property + def license_key(self): + """ + **[Required]** Gets the license_key of this VsphereLicense. + vSphere license key value. + + + :return: The license_key of this VsphereLicense. + :rtype: str + """ + return self._license_key + + @license_key.setter + def license_key(self, license_key): + """ + Sets the license_key of this VsphereLicense. + vSphere license key value. + + + :param license_key: The license_key of this VsphereLicense. + :type: str + """ + self._license_key = license_key + + def __repr__(self): + return formatted_flat_dict(self) + + def __eq__(self, other): + if other is None: + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self == other diff --git a/src/oci/ocvp/models/vsphere_upgrade_object.py b/src/oci/ocvp/models/vsphere_upgrade_object.py new file mode 100644 index 0000000000..adda9f2174 --- /dev/null +++ b/src/oci/ocvp/models/vsphere_upgrade_object.py @@ -0,0 +1,101 @@ +# coding: utf-8 +# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. + + +from oci.util import formatted_flat_dict, NONE_SENTINEL, value_allowed_none_or_none_sentinel # noqa: F401 +from oci.decorators import init_model_state_from_kwargs + + +@init_model_state_from_kwargs +class VsphereUpgradeObject(object): + """ + Binary object needed for vSphere upgrade + """ + + def __init__(self, **kwargs): + """ + Initializes a new VsphereUpgradeObject object with values from keyword arguments. + The following keyword arguments are supported (corresponding to the getters/setters of this class): + + :param download_link: + The value to assign to the download_link property of this VsphereUpgradeObject. + :type download_link: str + + :param link_description: + The value to assign to the link_description property of this VsphereUpgradeObject. + :type link_description: str + + """ + self.swagger_types = { + 'download_link': 'str', + 'link_description': 'str' + } + + self.attribute_map = { + 'download_link': 'downloadLink', + 'link_description': 'linkDescription' + } + + self._download_link = None + self._link_description = None + + @property + def download_link(self): + """ + **[Required]** Gets the download_link of this VsphereUpgradeObject. + Binary object download link. + + + :return: The download_link of this VsphereUpgradeObject. + :rtype: str + """ + return self._download_link + + @download_link.setter + def download_link(self, download_link): + """ + Sets the download_link of this VsphereUpgradeObject. + Binary object download link. + + + :param download_link: The download_link of this VsphereUpgradeObject. + :type: str + """ + self._download_link = download_link + + @property + def link_description(self): + """ + **[Required]** Gets the link_description of this VsphereUpgradeObject. + Binary object description. + + + :return: The link_description of this VsphereUpgradeObject. + :rtype: str + """ + return self._link_description + + @link_description.setter + def link_description(self, link_description): + """ + Sets the link_description of this VsphereUpgradeObject. + Binary object description. + + + :param link_description: The link_description of this VsphereUpgradeObject. + :type: str + """ + self._link_description = link_description + + def __repr__(self): + return formatted_flat_dict(self) + + def __eq__(self, other): + if other is None: + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self == other diff --git a/src/oci/version.py b/src/oci/version.py index 52c3a1e4db..3a7660846f 100644 --- a/src/oci/version.py +++ b/src/oci/version.py @@ -2,4 +2,4 @@ # Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. # This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. -__version__ = "2.80.0" +__version__ = "2.80.1"