© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2023
C. BellMySQL Database Service Revealedhttps://doi.org/10.1007/978-1-4842-8945-7_9

9. OCI Command-Line and Application Programming Interfaces

Charles Bell1  
(1)
WARSAW, VA, USA
 

Thus far in this book we have used the OCI web-based console to work with OCI products and services. We saw how to set up our OCI account, create networking services, and create and configure DB Systems. If you are comfortable with the web-based console, you should consider continuing using it as every operation you need to perform is easy to find and most information can be found on a single page or a page with tabs.

However, what do you do if you want to write development operations (DevOps) procedures in the form of Bash (or similar) script files? What if you want to write those scripts in a programming language like Python? Further, what if you want to configure your PC to use only command-line access to manipulate objects in OCI? Fortunately, the answers for all these questions can be found in the command-line and application programming interfaces available for OCI.

In this chapter, we will see an overview of the capabilities of the command-line interface (CLI) and application programming interface (API) for working with OCI and MDS DB Systems.

Getting Started

One of the nice features of the OCI documentation is that Oracle often includes text that covers both web-based and CLI examples for working with OCI products and services. There are also examples where Oracle includes how to perform operations using the APIs, but those are often seen only in the API documentation.

You can use the CLI with very little effort on your part. In fact, if you have executed the examples in Chapter 7, you have already installed the CLI. Recall, we installed the CLI because MySQL Shell required it. However, what was not revealed was that the CLI is written using the Python OCI API. So, if you install the CLI, you’ve also installed the Python API. Nice!

In Chapter 7, we configured our PC for use with the CLI in the section entitled Configure Your PC for OCI CLI Access. This requires the following at a minimum, which applies to both the CLI and APIs. If you have not configured your PC yet, please refer to that section in Chapter 7 to configure your PC for use with the CLI and API:
  • An SSH key used for signing API requests and the public key uploaded into your OCI account.

  • Python 3 installed on a supported operating system.

Tip

See the CLI installation documentation at https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm for more information about installing the CLI.

Command-Line Interface (CLI)

The OCI CLI is a Python-based application that you can download and run from your PC. It represents an alternative to the web-based cloud console and is especially helpful for running repeated tasks or tasks you want to automate from your developer operations (DevOps) tools.

Interestingly, the CLI is built using the OCI APIs (SDK) and can show you what is possible for your own applications should you decide to use the API.

Install the CLI

Recall, we installed the CLI in Chapter 7 in the section entitled Install and Test the OCI CLI. If you have not installed the CLI yet, please refer to those sections to configure your PC and install the CLI.

Capabilities

The CLI is a macro-level interface for the Python API. As such, many of the operations available perform a set of tasks that would typically require several methods in the API. Fortunately, the CLI is designed with an eye for the operator. Thus, the operations are those that we think about when we work with OCI products and services.

The CLI works by providing a list of commands that each can have subcommands and parameters. The CLI main executable is named oci and invoked with the same name. A nice touch is you don’t need to remember all of the command lists because the CLI has context help. For example, you can issue the oci command without parameters to get more information about all commands or help for a specific command with oci <command>. This also applies to subcommands. Listing 9-1 shows the help for the main commands excerpted for brevity.
C:>oci
Usage: oci [OPTIONS] COMMAND [ARGS]...
  Oracle Cloud Infrastructure command line interface, with support for
  Audit, Block Volume, Compute, Database, IAM, Load Balancing, Networking,
  DNS, File Storage, Email Delivery and Object Storage Services.
  Most commands must specify a service, followed by a resource type and then
  an action. For example, to list users (where $T contains the OCID of the
  current tenant):
    oci iam user list --compartment-id $T
  Output is in JSON format.
...
Commands:
  iam                             Identity and Access Management Service
  raw-request                     Makes a raw request against an OCI service
  session                         Session commands for CLI
  setup                           Setup commands for CLI
  adm                             Application Dependency Management
  ai                              Language
  ai-vision                       Vision
  analytics                       Analytics
  announce                        Announcements Service
  anomaly-detection               Oracle Cloud AI Services
  api-gateway                     API Gateway
  apm-config                      Application Performance Monitoring
                                  Configuration
  apm-control-plane               Application Performance Monitoring Control
                                  Plane
  apm-synthetics                  Application Performance Monitoring Synthetic
                                  Monitoring
  apm-traces                      Application Performance Monitoring Trace
                                  Explorer
  application-migration           Application Migration
  appmgmt-control                 Resource Discovery and Monitoring Control
  artifacts                       Artifacts and Container Images
  audit                           Audit
  autoscaling                     Autoscaling
  bastion                         Bastion
  bds                             Big Data Service
  blockchain                      Blockchain Platform Control Plane
  budgets                         Budgets
  bv                              Block Volume Service
  ce                              Container Engine for Kubernetes
  certificates                    Certificates Service Retrieval
  certs-mgmt                      Certificates Service Management
  cloud-guard                     Cloud Guard and Security Zones
  compute                         Compute Service
  compute-management              Compute Management Service
  dashboard-service               Dashboards
  data-catalog                    Data Catalog
  data-connectivity               Data Connectivity Management
  data-flow                       Data Flow
  data-integration                Data Integration
  data-labeling-service           Data Labeling Management
  data-labeling-service-dataplane   Data Labeling
  data-safe                       Data Safe
  data-science                    Data Science
  database-management             Database Management
  database-migration              Oracle Database Migration Service
  db                              Database Service
  dbtools                         Database Tools
  devops                          DevOps
  dns                             DNS
  dts                             Data Transfer Service
  em-warehouse                    EmdwControlPlane
  email                           Email Delivery
  events                          Events
  fn                              Functions Service
  fs                              File Storage
  fusion-apps                     Fusion Applications Environment Management
  goldengate                      GoldenGate
  governance-rules-control-plane  GovernanceRulesControlPlane
  health-checks                   Health Checks
  iam                             Identity and Access Management Service
  instance-agent                  Compute Instance Agent Service
  integration                     Oracle Integration
  jms                             Java Management Service
  kms                             Key Management
  lb                              Load Balancing
  license-manager                 License Manager
  limits                          Service Limits
  log-analytics                   LogAnalytics
  logging                         Logging Management
  logging-ingestion               Logging Ingestion
  logging-search                  Logging Search
  management-agent                Management Agent
  management-dashboard            ManagementDashboard
  marketplace                     Marketplace Service
  media-services                  Media Services
  monitoring                      Monitoring
  mysql                           MySQL Database Service
  network                         Networking Service
  network-firewall                Network Firewall
  nlb                             NetworkLoadBalancer
  nosql                           NoSQL Database
  oce                             Oracle Content and Experience
  ocvs                            Oracle Cloud VMware Solution
  oda                             Digital Assistant Service Instance
  oma                             Managed Access
  onesubscription                 OneSubscription
  ons                             Notifications
  opa                             OracleProcessAutomation
  opctl                           OperatorAccessControl
  opensearch                      OpenSearch Service
  opsi                            Operations Insights
  optimizer                       Cloud Advisor
  organizations                   Organizations
  os                              Object Storage Service
  os-management                   OS Management
  osp-gateway                     OSP Gateway
  osub-billing-schedule           OneSubscription  Billing Schedule
  osub-organization-subscription  OneSubscription Gateway  Organization's
                                  Subscription
  osub-subscription               OneSubscription  Subscription, Commitment
                                  and Rate Card Details
  osub-usage                      OneSubscription  Usage Computation
  resource-manager                Resource Manager
  rover                           RoverCloudService
  sch                             Service Connector Hub
  search                          Search Service
  secrets                         Vault Secret Retrieval
  service-catalog                 Service Catalog
  service-manager-proxy           Service Manager Proxy
  service-mesh                    Service Mesh
  speech                          Speech
  stack-monitoring                Stack Monitoring
  streaming                       Streaming
  support                         Support Management
  threat-intelligence             Threat Intelligence
  usage                           Usage Proxy
  usage-api                       Usage
  vault                           Vault Secret Management
  visual-builder                  Visual Builder
  vn-monitoring                   Network Monitoring
  vulnerability-scanning          Scanning
  waa                             Web Application Acceleration (WAA)
  waas                            Web Application Acceleration and Security
                                  Services
  waf                             Web Application Firewall (WAF)
  work-requests                   Work Requests
Listing 9-1

CLI Help Example

As you can see, there are a lot of commands! The one command we are interested in most is the mysql command. Listing 9-2 shows the help for the mysql (MDS) commands.
C:>oci mysql
Usage: oci mysql [OPTIONS] COMMAND [ARGS]...
  The CLI for the MySQL Database Service
Options:
  -?, -h, --help  For detailed help on any of these individual commands, enter
                  <command> --help.
Commands:
  backup                  A full or incremental copy of a DB System which...
  channel                 A Channel connecting a DB System to an external...
  configuration           The set of MySQL variables to be used when...
  db-system               MySQL Database Service
  shape                   The shape of the DB System.
  version                 A supported MySQL Version.
  work-request            The status of an asynchronous task in the system.
  work-request-error      An error encountered while executing a work...
  work-request-log-entry  A log message from the execution of a work...
Listing 9-2

CLI mysql Help Example

Similarly, if you wanted to see the help for the mysql backup command, you can issue the oci mysql backup command. Listing 9-3 shows the output of this command.
C:>oci mysql backup
Usage: oci mysql backup [OPTIONS] COMMAND [ARGS]...
  A full or incremental copy of a DB System which can be used to create a
  new DB System or recover a DB System.
  To use any of the API operations, you must be authorized in an IAM policy.
  If you're not authorized, talk to an administrator. If you're an
  administrator who needs to write policies to give users access, see
  [Getting Started with Policies].
Options:
  -?, -h, --help  For detailed help on any of these individual commands, enter
                  <command> --help.
Commands:
  change-compartment  Moves a DB System Backup into a different compartment.
  create              Create a backup of a DB System.
  delete              Delete a Backup.
  get                 Get information about the specified Backup [Command...
  list                Get a list of DB System backups.
Listing 9-3

CLI mysql backup Help Example

Notice how much information is included in the help. This is the quickest way to explore the CLI and for the most part you should not need to visit the longer, more detailed online documentation. This is why we started with the web-based console. Once you master that, all these terms will become clear, and you can easily find the command and parameters you need to script any supported operation.

The output of the CLI is JavaScript object notation (JSON), which most will find easy to read and use. For example, if you wanted to list the backups for a specific DB System, you would issue the following command without parameters adding the --help option to get more information:
oci mysql backup list --help
This produces the output in Listing 9-4 (reformatted for brevity). Notice the DB System option.
C:>oci mysql backup list --help
"list"
******
* Description
* Usage
* Required Parameters
* Optional Parameters
* Global Parameters
* Examples
Description
===========
Get a list of DB System backups.
Usage
=====
   oci mysql backup list [OPTIONS]
Required Parameters
===================
--compartment-id, -c [text] The compartment OCID.
Optional Parameters
===================
--all Fetches all pages of results. If you provide this option, then you
cannot provide the "--limit" option.
--backup-id [text] Backup OCID
--creation-type [text] Backup creationType Accepted values are: AUTOMATIC, MANUAL, OPERATOR
--db-system-id [text] The DB System OCID.
--display-name [text] A filter to return only the resource matching the given display name exactly.
--from-json [text] Provide input to this command as a JSON document from a file using the file://path-to/file syntax.
The "--generate-full-command-json-input" option can be used to generate a sample json file to be used with this command option. The key names are pre-populated and match the command option names (converted to camelCase format, e.g. compartment-id compartmentId), while the values of the keys need to be populated by the user before using the sample file as an input to this command. For any command option that accepts multiple values, the value of the key can be a JSON array.
Options can still be provided on the command line. If an option exists in both the JSON document and the command line then the command line specified value will be used.
For examples on usage of this option, please see our using CLI with advanced JSON options link: https://docs.cloud.oracle.com/iaas/Content/API/SDKDocs/cliusing.htm#AdvancedJSONOptions
--lifecycle-state [text] Backup Lifecycle State Accepted values are: ACTIVE, CREATING, DELETED, DELETING, FAILED, INACTIVE, UPDATING
--limit [integer] The maximum number of items to return in a paginated list call. For information about pagination, see List Pagination.
--page [text] The value of the *opc-next-page* or *opc-prev-page* response header from the previous list call. For information about pagination, see
List Pagination.
--page-size [integer] When fetching results, the number of results to fetch per call. Only valid when used with "--all" or "--limit", and ignored otherwise.
--sort-by [text] The field to sort by. Only one sort order may be provided. Time fields are default ordered as descending. Accepted values are: displayName, timeCreated, timeUpdated
--sort-order [text] The sort order to use (ASC or DESC). Accepted values are: ASC, DESC
Global Parameters
=================
Use "oci --help" for help on global parameters.
"--auth-purpose", "--auth", "--cert-bundle", "--cli-auto-prompt", "--
cli-rc-file", "--config-file", "--connection-timeout", "--debug", "--
defaults-file", "--endpoint", "--generate-full-command-json-input", "
--generate-param-json-input", "--help", "--latest-version", "--max-
retries", "--no-retry", "--opc-client-request-id", "--opc-request-id",
"--output", "--profile", "--query", "--raw-output", "--read-timeout",
"--region", "--release-info", "--request-id", "--version", "-?", "-d",
"-h", "-i", "-v"
Listing 9-4

CLI mysql backup list Help Example

Wow, that’s a lot of information! We now know all we need to know to list the backups for a compartment or for a specific DB System (using the --db-system-id option).

Note

Some options are required while others are optional. Also, some provide with shortcuts. For example, --compartment-id and -c are the same option.

Now that we understand the basics of the CLI, let’s look at some example operations that you can use right away with your DB Systems.

Example Uses

The following are some examples of using the CLI for common MDS operations ranging from simple listing of objects to creating objects. These are provided as examples and do not represent complete coverage of all MDS CLI commands. See the For More Information below for links to the documentation.

Caution

The parameters for the oci command must not use spaces. For example, --param1=value is valid, but --param1 = value is invalid and will lead to “invalid option” errors.

List Backups for a DB System

To list the backups for a DB System, we use the --db-system-id and --compartment-id options providing the OCID for each. Listing 9-5 shows how to formulate and execute the command. Notice that the output generated in JSON format. Notice also we used the --lifecycle-state option with the ACTIVE parameter to skip all backups that aren’t active.
C:>oci mysql backup list --compartment-id=ocid1.compartment.MASKED --db-system-id=ocid1.mysqldbsystem.MASKED --lifecycle-state=ACTIVE
{
  "data": [
    {
      "backup-size-in-gbs": 1,
      "backup-type": "INCREMENTAL",
      "creation-type": "AUTOMATIC",
      "data-storage-size-in-gbs": 50,
      "db-system-id": "ocid1.mysqldbsystem.MASKED",
      "defined-tags": {
        "Oracle-Tags": {
          "CreatedOn": "2022-04-11T18:42:37.374Z"
        }
      },
      "description": null,
      "display-name": "mysqlbackup20220821100711",
      "freeform-tags": {},
      "id": "ocid1.mysqlbackup.MASKED",
      "lifecycle-state": "ACTIVE",
      "mysql-version": "8.0.29",
      "retention-in-days": 10,
      "shape-name": "MySQL.VM.Standard.E3.1.8GB",
      "time-created": "2022-08-21T10:07:11.725000+00:00"
    },
    {
      "backup-size-in-gbs": 1,
      "backup-type": "INCREMENTAL",
      "creation-type": "AUTOMATIC",
      "data-storage-size-in-gbs": 50,
      "db-system-id": "ocid1.mysqldbsystem.MASKED",
      "defined-tags": {
        "Oracle-Tags": {
          "CreatedOn": "2022-04-11T18:42:37.374Z"
        }
      },
      "description": null,
      "display-name": "mysqlbackup20220820100710",
      "freeform-tags": {},
      "id": "ocid1.mysqlbackup.MASKED",
      "lifecycle-state": "ACTIVE",
      "mysql-version": "8.0.29",
      "retention-in-days": 10,
      "shape-name": "MySQL.VM.Standard.E3.1.8GB",
      "time-created": "2022-08-20T10:07:10.149000+00:00"
    },
    {
      "backup-size-in-gbs": 1,
      "backup-type": "FULL",
      "creation-type": "AUTOMATIC",
      "data-storage-size-in-gbs": 50,
      "db-system-id": "ocid1.mysqldbsystem.MASKED",
      "defined-tags": {
        "Oracle-Tags": {
          "CreatedOn": "2022-04-11T18:42:37.374Z"
        }
      },
      "description": null,
      "display-name": "mysqlbackup20220818203231",
      "freeform-tags": {},
      "id": "ocid1.mysqlbackup.oc1.iad.MASKED",
      "lifecycle-state": "ACTIVE",
      "mysql-version": "8.0.29",
      "retention-in-days": 10,
      "shape-name": "MySQL.VM.Standard.E3.1.8GB",
      "time-created": "2022-08-18T20:32:31.588000+00:00"
    }
  ]
}
Listing 9-5

Listing Backups for a DB System

Note

You may be required to enter the password for your API SSH key.

Stop/Start a DB System

The next example shows how you can stop a DB System with the CLI. In this case, we need to use the mysql db-system command, pass the DB System OCID, and the stop operation. Listing 9-6 shows an example of this command.
C:>oci mysql db-system stop --db-system-id=ocid1.mysqldbsystem.MASKED --shutdown-type=fast
{
  "opc-work-request-id": "ocid1.mysqlworkrequest.MASKED"
}
Listing 9-6

Stopping a DB System

Notice the output is a work request id. This indicates an operation that is running and while we do not get a status, we can get more information about this work request including the status with the following command. Here, we use the work-request subcommand with the get operation to fetch the details of a work request with the OCID specified in the --work-request-id option:
oci mysql work-request get --work-request-id=<OCID>
C:>oci mysql work-request get --work-request-id=ocid1.mysqlworkrequest.MASKED
Private key passphrase:
{
  "data": {
    "compartment-id": "ocid1.compartment.MASKED",
    "id": "ocid1.mysqlworkrequest.MASKED",
    "operation-type": "STOP_DBSYSTEM",
    "percent-complete": 100.0,
    "resources": [
      {
        "action-type": "RELATED",
        "entity-type": "mysqldbsystem",
        "entity-uri": "/dbSystems/ocid1.mysqldbsystem.MASKED",
        "identifier": "ocid1.mysqldbsystem.MASKED"
      }
    ],
    "status": "SUCCEEDED",
    "time-accepted": "2022-08-22T01:01:18.469000+00:00",
    "time-finished": "2022-08-22T01:02:39.135000+00:00",
    "time-started": "2022-08-22T01:01:22.935000+00:00"
  }
}
Listing 9-7

Getting a Work Request Status

Notice we see a status of SUCCEEDED. If the work request were still running, we would see the appropriate status. This is how you can track your work requests with the CLI, and it is a common mechanism.

We can also get the information for the DB System we just stopped to ensure it is in a stopped state. Listing 9-8 shows the CLI command for getting the DB System information followed by fetches for the work request status.
C:>oci mysql db-system start --db-system-id=ocid1.mysqldbsystem.MASKED
{
  "opc-work-request-id": "ocid1.mysqlworkrequest.MASKED"
}
C:>oci mysql work-request get --work-request-id=ocid1.mysqlworkrequest.MASKED
{
  "data": {
    "compartment-id": "ocid1.compartment.MASKED",
    "id": "ocid1.mysqlworkrequest.MASKED",
    "operation-type": "START_DBSYSTEM",
    "percent-complete": 0.48333332,
    "resources": [
      {
        "action-type": "IN_PROGRESS",
        "entity-type": "mysqldbsystem",
        "entity-uri": "/dbSystems/ocid1.mysqldbsystem.MASKED",
        "identifier": "ocid1.mysqldbsystem.MASKED"
      }
    ],
    "status": "IN_PROGRESS",
    "time-accepted": "2022-08-22T01:09:46.862000+00:00",
    "time-finished": null,
    "time-started": "2022-08-22T01:09:56.948000+00:00"
  }
}
...
C:>oci mysql work-request get --work-request-id=ocid1.mysqlworkrequest.MASKED
{
  "data": {
    "compartment-id": "ocid1.compartment.MASKED",
    "id": "ocid1.mysqlworkrequest.MASKED",
    "operation-type": "START_DBSYSTEM",
    "percent-complete": 100.0,
    "resources": [
      {
        "action-type": "RELATED",
        "entity-type": "mysqldbsystem",
        "entity-uri": "/dbSystems/ocid1.mysqldbsystem.MASKED",
        "identifier": "ocid1.mysqldbsystem.MASKED"
      }
    ],
    "status": "SUCCEEDED",
    "time-accepted": "2022-08-22T01:09:46.862000+00:00",
    "time-finished": "2022-08-22T01:13:56.223000+00:00",
    "time-started": "2022-08-22T01:09:56.948000+00:00"
  }
}
Listing 9-8

Getting the DB System Information (stopped)

Like start/stop, you can also delete DB Systems as well as list the DB Systems in a compartment. There are many more commands available for DB Systems. Follow the links below in the For More Information section to learn more about the commands.

Ok, let’s look at one more example but this time we will use a complex operation: creating a new DB System.

Create a DB System

Creating a DB System requires a more complex set of parameters and options. In this case, we need, at a minimum, the compartment OCID, subnet OCID, shape name (not OCIDs), and availability domain name. We will add some more optional parameters, but let’s start assuming we do not know the OCIDs for these objects. Never fear, we can list them with the CLI!

Listing 9-9 shows the command to list the compartments in your tenancy. Notice we use the iam command (Identity and Access Management) with the compartment subcommand and the list parameter to list all compartments in our tenancy.
C:>oci iam compartment list
{
  "data": [
    {
      "compartment-id": "ocid1.tenancy.MASKED",
      "defined-tags": {},
      "description": "MASKED",
      "freeform-tags": {},
      "id": "ocid1.compartment.MASKED",
      "inactive-status": null,
      "is-accessible": null,
      "lifecycle-state": "ACTIVE",
      "name": "ManagedCompartmentForPaaS",
      "time-created": "2022-03-12T10:30:27.437000+00:00"
    },
    {
      "compartment-id": "ocid1.tenancy.MASKED",
      "defined-tags": {
        "Oracle-Tags": {
          "CreatedOn": "2022-04-15T20:11:23.394Z"
        }
      },
      "description": "Used for MySQL development",
      "freeform-tags": {},
      "id": "ocid1.compartment.MASKED",
      "inactive-status": null,
      "is-accessible": null,
      "lifecycle-state": "ACTIVE",
      "name": "mysql-development-compartment",
      "time-created": "2022-04-15T20:11:23.466000+00:00"
    },
    {
      "compartment-id": "ocid1.tenancy.MASKED",
      "defined-tags": {
        "Oracle-Tags": {
          "CreatedOn": "2022-03-11T19:40:29.719Z"
        }
      },
      "description": "Our first compartment!",
      "freeform-tags": {},
      "id": "ocid1.compartment.MASKED",
      "inactive-status": null,
      "is-accessible": null,
      "lifecycle-state": "ACTIVE",
      "name": "oci-tutorial-compartment",
      "time-created": "2022-03-11T19:40:29.794000+00:00"
    }
  ]
}
Listing 9-9

List Compartments

Listing the subnets for our compartment is a similar command except we can use the network command and subnet subcommand with the list option. We pass the compartment OCID with the --compartment-id parameter.
C:>oci network subnet list --compartment-id=ocid1.compartment.MASKED
Private key passphrase:
{
  "data": [
    {
      "availability-domain": null,
      "cidr-block": "10.0.1.0/24",
      "compartment-id": "ocid1.compartment.MASKED",
      "defined-tags": {
        "Oracle-Tags": {
          "CreatedOn": "2022-03-11T20:27:33.457Z"
        }
      },
      "dhcp-options-id": "ocid1.dhcpoptions.MASKED",
      "display-name": "Private Subnet-oci-tutorial-vcn",
      "dns-label": "sub03112027061",
      "freeform-tags": {
        "VCN": "VCN-2022-03-11T20:25:54"
      },
      "id": "ocid1.subnet.MASKED",
      "ipv6-cidr-block": null,
      "ipv6-cidr-blocks": null,
      "ipv6-virtual-router-ip": null,
      "lifecycle-state": "AVAILABLE",
      "prohibit-internet-ingress": true,
      "prohibit-public-ip-on-vnic": true,
      "route-table-id": "ocid1.routetable.MASKED",
      "security-list-ids": [
        "ocid1.securitylist.MASKED"
      ],
      "subnet-domain-name": "sub03112027061.ocitutorialvcn.oraclevcn.com",
      "time-created": "2022-03-11T20:27:33.893000+00:00",
      "vcn-id": "ocid1.vcn.MASKED",
      "virtual-router-ip": "10.0.1.1",
      "virtual-router-mac": "00:00:17:38:7B:54"
    },
    {
      "availability-domain": null,
      "cidr-block": "10.0.0.0/24",
      "compartment-id": "ocid1.compartment.MASKED",
      "defined-tags": {
        "Oracle-Tags": {
          "CreatedOn": "2022-03-11T20:27:32.655Z"
        }
      },
      "dhcp-options-id": "ocid1.dhcpoptions.MASKED",
      "display-name": "Public Subnet-oci-tutorial-vcn",
      "dns-label": "sub03112027060",
      "freeform-tags": {
        "VCN": "VCN-2022-03-11T20:25:54"
      },
      "id": "ocid1.subnet.MASKED",
      "ipv6-cidr-block": null,
      "ipv6-cidr-blocks": null,
      "ipv6-virtual-router-ip": null,
      "lifecycle-state": "AVAILABLE",
      "prohibit-internet-ingress": false,
      "prohibit-public-ip-on-vnic": false,
      "route-table-id": "ocid1.routetable.MASKED",
      "security-list-ids": [
        "ocid1.securitylist.MASKED"
      ],
      "subnet-domain-name": "sub03112027060.ocitutorialvcn.oraclevcn.com",
      "time-created": "2022-03-11T20:27:32.987000+00:00",
      "vcn-id": "ocid1.vcn.MASKED",
      "virtual-router-ip": "10.0.0.1",
      "virtual-router-mac": "00:00:17:38:7B:54"
    }
  ]
}
Listing 9-10

Listing the Subnets for a Compartment

Next, we need the MySQL shapes available. Since this list could be long, we will see a paged output that will require multiple calls to get the complete list. If you’re like me, you don’t have the patience for that, so we can use the --all parameter.

The command we need to get the list of shapes and their names requires using the mysql command and shape subcommand with the list option and the --compartment-id parameter as shown in Listing 9-11 (excerpted for brevity).
C:>oci mysql shape list --compartment-id=ocid1.compartment.MASKED --all
Private key passphrase:
{
  "data": [
    {
      "cpu-core-count": 1,
      "is-supported-for": [
        "DBSYSTEM"
      ],
      "memory-size-in-gbs": 8,
      "name": "VM.Standard.E2.1"
    },
    {
      "cpu-core-count": 2,
      "is-supported-for": [
        "DBSYSTEM"
      ],
      "memory-size-in-gbs": 16,
      "name": "VM.Standard.E2.2"
    },
    {
      "cpu-core-count": 4,
      "is-supported-for": [
        "DBSYSTEM"
      ],
      "memory-size-in-gbs": 32,
      "name": "VM.Standard.E2.4"
    },
    {
      "cpu-core-count": 8,
      "is-supported-for": [
        "DBSYSTEM"
      ],
      "memory-size-in-gbs": 64,
      "name": "VM.Standard.E2.8"
    },
    {
      "cpu-core-count": 1,
      "is-supported-for": [
        "DBSYSTEM"
      ],
      "memory-size-in-gbs": 8,
      "name": "MySQL.VM.Standard.E3.1.8GB"
    },
...
Listing 9-11

Listing the MySQL Shapes

Ok, there is one more list we need: the name of the availability domain. To find the availability domains, we issue the iam command with the availability-domain subcommand and the list option providing the compartment OCID with --compartment-id parameter.
C: >oci iam availability-domain list --compartment-id=ocid1.compartment.MASKED
{
  "data": [
    {
      "compartment-id": "ocid1.compartment.MASKED",
      "id": "ocid1.availabilitydomain.MASKED",
      "name": "DRUu:US-ASHBURN-AD-1"
    },
    {
      "compartment-id": "ocid1.compartment.MASKED",
      "id": "ocid1.availabilitydomain.MASKED",
      "name": "DRUu:US-ASHBURN-AD-2"
    },
    {
      "compartment-id": "ocid1.compartment.MASKED",
      "id": "ocid1.availabilitydomain.MASKED",
      "name": "DRUu:US-ASHBURN-AD-3"
    }
  ]
}
Listing 9-12

Listing Availability Domains

Next, we need some optional parameters. The following shows the options we will use and their parameters:
  • --admin-password <password>: The password for the MySQL administrative user.

  • --admin-username <name>: The username for the MySQL administrative user.

  • --data-storage-size-in-gbs <int>: Size of the data storage (database drive) in GBs.

  • --display-name <text>: A user-friendly name for the DB System.

  • --is-highly-available <bool>: Specifies if the DB System is highly available.

There is one more option we should discuss – the option to have the operation wait for a specific state. We do this with the --wait-for-state <state> option and one of the states (ACCEPTED, CANCELED, CANCELING, FAILED, IN_PROGRESS, SUCCEEDED). You can specify this option multiple times to wait for multiple operations. This operation asynchronously executes the operation and uses a work request to track the progress. Multiple states can be specified, returning on the first state. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.

Ok, now we are ready to form out command. The following is an example of the command. If you want to follow along, be sure to substitute your OCIDs instead of the masked OCIDs shown:
oci mysql db-system create
    --compartment-id=ocid1.compartment.MASKED
    --shape-name=VM.Standard.E2.4
    --subnet-id=ocid1.subnet.MASKED
    --admin-password=MASKED
    --admin-username=mysql_admin
    --data-storage-size-in-gbs=50
    --display-name=MySQL_CLI_Create
    --is-highly-available=false
    --wait-for-state=FAILED
    --wait-for-state=SUCCEEDED
    --availability-domain=DRUu:US-ASHBURN-AD-2
C:>oci mysql db-system create --compartment-id=ocid1.compartment.MASKED --shape-name=VM.Standard.E2.4 --subnet-id=ocid1.subnet.MASKED --admin-password=MASKED --admin-username=mysql_admin --data-storage-size-in-gbs=50 --display-name=MySQL_CLI_Create --is-highly-available=false --wait-for-state=FAILED --wait-for-state=SUCCEEDED --availability-domain=DRUu:US-ASHBURN-AD-2
Private key passphrase:
Private key passphrase:
Action completed. Waiting until the work request has entered state: ('FAILED', 'SUCCEEDED')
{
  "data": {
    "compartment-id": "ocid1.compartment.oc1..aaaaaaaawzwb45t3lutkqvyhofxh3ai26e5oli2a4q6efbh25g3llqwys7pa",
    "id": "ocid1.mysqlworkrequest.oc1.iad.83fd016c-1083-4a3f-92b9-c7c583d40b44.aaaaaaaai3m2mauwmhp3ppbdjvtwq26xomazthrsqk6teguy73mofidayk5q",
    "operation-type": "CREATE_DBSYSTEM",
    "percent-complete": 100.0,
    "resources": [
      {
        "action-type": "CREATED",
        "entity-type": "mysqldbsystem",
        "entity-uri": "/dbSystems/ocid1.mysqldbsystem.oc1.iad.aaaaaaaay3d7ex7lnbvb24snjyvdg7mn6cx3qrezaq2nifq56ohdwmjk4owa",
        "identifier": "ocid1.mysqldbsystem.oc1.iad.aaaaaaaay3d7ex7lnbvb24snjyvdg7mn6cx3qrezaq2nifq56ohdwmjk4owa"
      }
    ],
    "status": "SUCCEEDED",
    "time-accepted": "2022-08-22T01:54:59.037000+00:00",
    "time-finished": "2022-08-22T02:08:05.671000+00:00",
    "time-started": "2022-08-22T01:55:13.888000+00:00"
  }
}
Listing 9-13

Create DB System Example Command

Ok, now the operation has returned, and it succeeded. If we visit the OCI console, we can find the DB System and display its details page as demonstrated in Figure 9-1.

A Database page of My SQL C L I Create with details of general information, D B system configuration, backup, heatwave, high availability, networking, placement, and endpoint.

Figure 9-1

New DB System Details Page (CLI Example)

Finally, to clean up from this example, we can delete the newly created DB System with the following command as demonstrated in Listing 9-14. Notice you are asked to confirm the delete operation.
C:>oci mysql db-system delete --db-system-id=ocid1.mysqldbsystem.MASKED --wait-for-state=SUCCEEDED
Are you sure you want to delete this resource? [y/N]: y
Action completed. Waiting until the work request has entered state: ('SUCCEEDED',)
{
  "data": {
    "compartment-id": "ocid1.compartment.oc1..aaaaaaaawzwb45t3lutkqvyhofxh3ai26e5oli2a4q6efbh25g3llqwys7pa",
    "id": "ocid1.mysqlworkrequest.MASKED",
    "operation-type": "DELETE_DBSYSTEM",
    "percent-complete": 100.0,
    "resources": [
      {
        "action-type": "DELETED",
        "entity-type": "mysqldbsystem",
        "entity-uri": "/dbSystems/ocid1.mysqldbsystem.MASKED",
        "identifier": "ocid1.mysqldbsystem.MASKED"
      }
    ],
    "status": "SUCCEEDED",
    "time-accepted": "2022-08-22T02:15:30.534000+00:00",
    "time-finished": "2022-08-22T02:18:02.293000+00:00",
    "time-started": "2022-08-22T02:15:32.565000+00:00"
  }
}
Listing 9-14

Deleting a DB System

Now that we’ve seen a few of the more common operations including listing, creating, and deleting resources, let’s look at the documentation available for the other MDS operations available in the CLI.

For More Information

The most valuable resource and indeed the starting point for your continued research into the CLI is the documentation at https://docs.oracle.com/en-us/iaas/tools/oci-cli/3.15.0/oci_cli_docs/. This documentation is listed by OCI product and service which includes every possible use of the CLI for those products and services. For example, the MDS portion of the documentation contains the following major sections. Links to the documentation for each section are included:

Refer to the links above for more details about the CLI operations for these areas. You can also visit the OCI CLI main documentation at https://docs.oracle.com/en-us/iaas/tools/oci-cli/3.15.0/oci_cli_docs/index.html to see the complete list of the OCI CLI commands.

OCI APIs

Oracle provides APIs for almost every operation in OCI and MDS is no exception. Oracle also provides software development kits (SDK) that you can use to develop and deploy applications that interact with the OCI resources. Oracle provides SDKs for the following programming languages. Each SDK includes example code and documentation. Best of all, most SDKs are available via GitHub where you can contribute your own suggestions for improvements. The following show the SDKs available for OCI along with a link to the documentation for the SDK. If you want to use any of these SDKs for your applications, be sure to review the documentation and examples as you get started:

Since the Python SDK is popular and the Python language is easy to learn, we will look at a few examples of using the Python SDK. Before we jump into the Python API examples, let’s discuss the MDS APIs briefly so that we understand the interfaces.

Each SDK has as part of its documentation an API reference, which is an extensive list of the APIs for each resource supported. For example, the Python SDK API reference is found at https://docs.oracle.com/en-us/iaas/tools/python/2.79.0/api/landing.html.

Now, let’s take a brief look at the MDS API.

MDS API

The MDS API has five main components (or, more correctly, classes) that make up the interface. These include the following:
  • oci.mysql.ChannelsClient: API for working with inbound and outbound replication.

  • oci.mysql.DbBackupsClient: API for working with backups.

  • oci.mysql.DbSystemClient: API for working with DB Systems.

  • oci.mysql.MysqlaasClient: API for working with the MySQL client access (e.g. configuration, shapes, versions).

  • oci.mysql.WorkRequestsClient: API for interactive with work requests.

In addition, the MDS API has five classes that have grouped some of the individual API methods and classes together for macro operations. These include the following:
  • oci.mysql.ChannelsClientCompositeOperations: API for working with inbound and outbound replication.

  • oci.mysql.DbBackupsClientCompositeOperations: API for working with backups.

  • oci.mysql.DbSystemClientCompositeOperations: API for working with DB Systems.

  • oci.mysql.MysqlaasClientCompositeOperations: API for working with the MySQL client access (e.g., configuration, shapes, versions).

  • oci.mysql.WorkRequestsClientCompositeOperations: API for interactive with work requests.

It is often necessary to use multiple MDS API classes to achieve certain functions. Let’s get a brief tour of the MDS API in Python using a few examples.

Example Uses

Using the OCI SDKs can be a little challenging when you first begin working with them. In this section, we will see how to get started by demonstrating the basics of how the Python SDK works. But first, let’s install the Python SDK.

Note

You must have Python 3 installed on your PC. See the Python organization at www.python.org/ for more details about installing Python on your PC.

Install the Python SDK

Before we can use the Python SDK, we must install it. Recall, we mentioned that the Python SDK is part of the OCI CLI, but it is installed in its own environment, so it is not accessible by a typical Python client. Fortunately, we can install the Python SDK alongside the OCI CLI without affecting either product. The following demonstrates how to install the Python SDK on Windows 11, but details for installing on other platforms or with other methods can be found at https://docs.oracle.com/en-us/iaas/tools/python/2.79.0/installation.html.

The command to install the Python SDK uses pip, which is installed automatically when you install Python:
pip install oci
Listing 9-15 shows an excerpt of this command running on Windows 11. Once it is complete, you have the Python SDK installed and can proceed. The output for your PC may vary from this listing depending on the other Python components installed on your PC.
C: >pip install oci
Collecting oci
  Downloading oci-2.79.0-py2.py3-none-any.whl (16.9 MB)
     |████████████████████████████████| 16.9 MB 6.8 MB/s
Collecting python-dateutil<3.0.0,>=2.5.3
  Downloading python_dateutil-2.8.2-py2.py3-none-any.whl (247 kB)
     |████████████████████████████████| 247 kB 6.8 MB/s
Collecting cryptography<=37.0.2,>=3.2.1
  Downloading cryptography-37.0.2-cp36-abi3-win_amd64.whl (2.4 MB)
     |████████████████████████████████| 2.4 MB 3.3 MB/s
Collecting pytz>=2016.10
  Downloading pytz-2022.2.1-py2.py3-none-any.whl (500 kB)
     |████████████████████████████████| 500 kB ...
Collecting certifi
  Downloading certifi-2022.6.15-py3-none-any.whl (160 kB)
     |████████████████████████████████| 160 kB 3.3 MB/s
Collecting circuitbreaker<2.0.0,>=1.3.1
  Downloading circuitbreaker-1.4.0.tar.gz (9.7 kB)
Collecting pyOpenSSL<=22.0.0,>=17.5.0
  Downloading pyOpenSSL-22.0.0-py2.py3-none-any.whl (55 kB)
     |████████████████████████████████| 55 kB 943 kB/s
Collecting cffi>=1.12
  Downloading cffi-1.15.1-cp39-cp39-win_amd64.whl (179 kB)
     |████████████████████████████████| 179 kB 3.3 MB/s
Collecting pycparser
  Downloading pycparser-2.21-py2.py3-none-any.whl (118 kB)
     |████████████████████████████████| 118 kB 3.2 MB/s
Requirement already satisfied: six>=1.5 in c:userscbellappdatalocalprogramspythonpython39libsite-packages (from python-dateutil<3.0.0,>=2.5.3->oci) (1.16.0)
Using legacy 'setup.py install' for circuitbreaker, since package 'wheel' is not installed.
Installing collected packages: pycparser, cffi, cryptography, pytz, python-dateutil, pyOpenSSL, circuitbreaker, certifi, oci
    Running setup.py install for circuitbreaker ... done
Successfully installed certifi-2022.6.15 cffi-1.15.1 circuitbreaker-1.4.0 cryptography-37.0.2 oci-2.79.0 pyOpenSSL-22.0.0 pycparser-2.21 python-dateutil-2.8.2 pytz-2022.2.1
Listing 9-15

Installing the Python SDK

Getting Started

The basic layout of any Python SDK script begins with an import section where you import the getpass and oci modules. We need the getpass module because we must read the SSH key (called a passphrase) from the user (command-line).

This is followed by creating an instance of the oci.config class. This is an operation that reads your configuration file and prepares the SDK objects for use with your credentials. We then read and add the passphrase to the configuration file dictionary. Next, we connect to whichever API class we want to use and, if the connection is successful, we can proceed to make the API method calls.

Note

If you have not set up your PC to use the OCI CLI, please refer to Chapter 7 and finish that setup before attempting the API examples. The configuration file is required for access to MDS via the API.

Listing 9-16 shows the basic Python script you need to access the OCI API classes. The script is named basic_api.py.

Tip

If you are new to Python programming, you can visit www.python.org/ for how to download and install Python as well as tutorials and help getting started with Python. There are also many excellent books on Python and a few websites that can help you get started.

#
# MySQL Database Service
#
# Basic Python script for working with the MDS Python API
#
# Created by: Dr. Charles Bell
#
# Import the getpass module
import getpass
# Import the oci module
import oci
# Read your configuration file: be sure to provide a path if
# your configuration file.
config = oci.config.from_file()
# Read the passphrase from the user
pass_phrase = getpass.getpass("Enter the SSH key passphrase: ")
# Add the passphrase  to the config file dictionary.
config.update({'pass_phrase':pass_phrase})
# Initialize service client with default config file
mysql_client = oci.mysql.MysqlaasClient(config)
# Create an instance to the API module and call methods
# Check response codes as needed and exit
Listing 9-16

Basic Python API Script

You can execute this script with the following command. You should see it run and then exit without errors. If it does not, check your configuration file and the Python SDK install to make sure everything is installed and configured correctly before proceeding:
python3 basic_api.py

Now, let’s look at some of the examples we used in the CLI section to see how to accomplish the same using the Python SDK. Let’s start by listing the MySQL shapes using the oci.mysql.MysqlaasClient class.

Listing the MySQL Shapes

To list the MySQL shapes, we use the list_shapes() method from the oci.mysql.MysqlaasClient class, which takes as a parameter the compartment id, which is common among many of the API methods.

Since we will be using he compartment id often, we can save it in an environment variable and read it from the Python script. To set an environment variable in macOS or Linux, use the export command as shown below:
export COMPARTMENT_ID=ocid1.compartment.MASKED
For Windows, we use the set command as shown below:
set COMPARTMENT_ID=ocid1.compartment.MASKED
You can read an environment variable in Python with the os module as shown below:
import os
COMPARTMENT_ID = os.getenv('COMPARTMENT_ID')
The call to the API to get the list of shapes is shown below::
list_shapes_response = mysql_client.list_shapes(compartment_id=COMPARTMENT_ID)

This returns a list or ShapeSummary classes, which we can use to loop through the shapes and print the name, which is a lot cleaner (and fewer lines) than a JSON output like the CLI. You can find the description of the ShapeSummary class at https://docs.oracle.com/en-us/iaas/tools/python/2.79.0/api/mysql/models/oci.mysql.models.ShapeSummary.html#oci.mysql.models.ShapeSummary.

Ok, now let’s look at the complete code. Listing 9-17 shows the completed code for this example. The file is named list_mysql_shapes.py.
import getpass
import os
# Import the oci module
import oci
# Read your configuration file: be sure to provide a path if
# your configuration file.
config = oci.config.from_file()
# Read the passphrase from the user
pass_phrase = getpass.getpass("Enter the SSH key passphrase: ")
# Add the passphrase  to the config file dictionary.
config.update({'pass_phrase':pass_phrase})
# Initialize service client with default config file
mysql_client = oci.mysql.MysqlaasClient(config)
# Get the compartment id from the environment
COMPARTMENT_ID = os.getenv('COMPARTMENT_ID')
# List the MySQL shapes
list_shapes_response = mysql_client.list_shapes(compartment_id=COMPARTMENT_ID)
# Loop through the data and print the shape names only.
for shape_summary in list_shapes_response.data:
    print(shape_summary.name)
Listing 9-17

List MySQL Shapes Script

When you execute this code, you will see an excerpt of the list of MySQL shapes as shown in Listing 9-18.
C:Userscbell>python list_mysql_shapes.py
Enter the SSH key passphrase:
VM.Standard.E2.1
VM.Standard.E2.2
VM.Standard.E2.4
VM.Standard.E2.8
MySQL.VM.Standard.E3.1.8GB
MySQL.VM.Standard.E3.1.16GB
MySQL.VM.Standard.E3.2.32GB
MySQL.VM.Standard.E3.4.64GB
MySQL.VM.Standard.E3.8.128GB
MySQL.VM.Standard.E3.16.256GB
MySQL.VM.Standard.E3.24.384GB
MySQL.VM.Standard.E3.32.512GB
MySQL.VM.Standard.E3.48.768GB
MySQL.VM.Standard.E3.64.1024GB
...
MySQL.VM.Optimized3.1.8GB
MySQL.VM.Optimized3.1.16GB
MySQL.VM.Optimized3.2.32GB
MySQL.VM.Optimized3.4.64GB
MySQL.VM.Optimized3.8.128GB
MySQL.VM.Optimized3.16.256GB
MySQL.HeatWave.BM.Standard.E3
Listing 9-18

Output of List MySQL Shapes Script

Now, let’s take the complexity up a bit. Let’s see how to control DB Systems.

Stop/Start DB System

When working with DB Systems, we will use the oci.mysql.DbSystemClient class and its methods. To stop a DB System, we use the stop_db_system() method and to start a DB System, we use the start_db_system() method. As you can see, the API methods are often quite self-explanatory.

This example is a bit more complicated because we will have to provide a DB System id (OCID) in the form of another class named stop_db_system_details() for the stop or start operation. This class uses a model to populate the data. In this case, we need the DB System OCID and the shutdown type.

We are also going to make it a bit more complex by first listing the DB Systems in our compartment and select the one with a specific name. You may be amazed at how difficult it is to remember OCIDs, but it is much easier to remember a DB System name. We’ll display a list for the user to choose the DB System to control. To list the DB Systems, we use the list_db_systems() method and pass in the compartment id, which we have saved in an environment file.

In summary, we will import the libraries we need, read the configuration file, read the SSH key passphrase from the user, read the compartment id from the environment variable, then read the DB System name from the user. Once we have that information, we can call the method to list the DB Systems in the compartment, select one that matches the name, then either stop or start it.

Interestingly, these API methods do not return with a work request id like we saw with the CLI examples. Instead, the method waits until the operation is complete. Listing 9-19 shows the complete code for this example. The file is named stop_db_system.py Take some time to study it before moving on to the next example.
import getpass
import os
import sys
# Import the oci module
import oci
# Determine which operation is requested: start/stop
if len(sys.argv) > 1:
    is_stop = sys.argv[1].upper() == "STOP"
    operation = "Stopping"
else:
    is_stop = False
    operation = "Starting"
# Read your configuration file: be sure to provide a path if
# your configuration file.
config = oci.config.from_file()
# Read the passphrase from the user
pass_phrase = getpass.getpass("Enter the SSH key passphrase: ")
# Add the passphrase  to the config file dictionary.
config.update({'pass_phrase':pass_phrase})
# Initialize service client with default config file
db_client = oci.mysql.DbSystemClient(config)
# Get the compartment id from the environment
COMPARTMENT_ID = os.getenv('COMPARTMENT_ID')
# List the DB Systems
list_db_systems_response = db_client.list_db_systems(compartment_id=COMPARTMENT_ID)
# Loop through the DB System Summary
db_systems = []
num = 1
print("DB Systems in Compartment")
print("-------------------------")
for db_system_summary in list_db_systems_response.data:
    if db_system_summary.lifecycle_state != 'DELETED':
        print("{0}: {1}".format(num, db_system_summary.display_name))
        db_systems.append(db_system_summary)
# If no DB Systems active, exit
if len(db_systems) == 0:
    print("No db systems to control.")
    exit(1)
# Get the name of the DB System to control
db_num = int(input(" Which DB System (int)? "))
print(" {0} the DB System named '{1}' ".format(operation, db_systems[db_num-1].display_name))
# Perform the operation
if is_stop:
    db_system_response = db_client.stop_db_system(
        db_systems[db_num-1].id,
        stop_db_system_details=oci.mysql.models.StopDbSystemDetails(
            shutdown_type="FAST")
        )
    print(db_system_response.headers)
else:
    db_system_response = db_client.start_db_system(db_systems[db_num-1].id)
    print(db_system_response.headers)
print("Done!")
Listing 9-19

Control DB System Script

As you can see, the code it much more complex, but most of that is the Python code to gather the list of DB Systems and display them to the user to select one for the operation. Listing 9-20 shows the code running (formatted for easier reading). Notice we have a user-friendly albeit terse interface that may be more appealing and easier to use than the OCI console.
C:Userscbell>python control_db_system.py STOP
Enter the SSH key passphrase:
DB Systems in Compartment
-------------------------
1: oci-tutorial-mysql
Which DB System (int)? 1
Stopping the DB System named 'oci-tutorial-mysql'
{
    'Date': 'Mon, 22 Aug 2022 20:44:34 GMT',
    'opc-request-id': 'MASKED',
    'opc-work-request-id': 'ocid1.mysqlworkrequest.MASKED',
    'X-Content-Type-Options': 'nosniff',
    'Content-Type': 'application/json'
}
Done!
Listing 9-20

Output of the Control DB System Script

This script would make a good starting point for other operations you may want to perform on your DB Systems. Simply modify it to your needs!

The last example we will look at is the operation to create a new DB System. While the Python code may seem more complex, but it uses the same features of this example only with a more sophisticated Python programming style. However, there are more API methods, and the parameters are more complex.

Creating a DB System

Recall from the create DB System example in the CLI section that we needed several pieces of information in order to create the DB System. We repeat the required and optional parameters in the following list:
  • --compartment-id <id>: The compartment id.

  • --shape-name <name>: The shape name.

  • --subnet-id <id>: The subnet OCID.

  • --availability-domain <name>: The availability domain name to use.

  • --admin-password <password>: The password for the MySQL administrative user.

  • --admin-username <name>: The username for the MySQL administrative user.

  • --data-storage-size-in-gbs <int>: Size of the data storage (database drive) in GBs.

  • --display-name <text>: A user-friendly name for the DB System.

  • --is-highly-available <bool>: Specifies if the DB System is highly available.

Recall from the CLI example, we used four CLI commands; one each to get the shape name, subnet id, and availability domain, and one to perform the create. This example using the Python API will do the same thing only in a single Python script.

Like the last example, we will display a simple user interface to allow the user to choose the items from the lists asking only for the display name and data size as prompts. We will also prompt for the MySQL administrative user and password.

Rather than go through line-by-line, let’s summarize what we will be doing. We know we must get the subnet, shape, and availability domain so we will write methods to get that information using a helper method that presents a list to the user prompting her to choose one from the list. Thus, we will get these three data items from the user.

In doing so, we will explore more API classes including the oci.core.VirtualNetworkClient, oci.mysql.MysqlaasClient, and oci.identity.IdentityClient classes calling the appropriate methods for getting a list of those resources.

The optional parameters; MySQL administrator user and password, data storage size, and display name are read from the user with prompts. We also set the HA to disabled by default.

Once we have all the information, we use the create_db_system() method of the oci.mysql.DbSystemClient class to create the DB System. This method requires the population of a model named oci.mysql.models.CreateDbSystemDetails.

Finally, since the create_db_system() method returns immediately, we pole the DB System by fetching its details with the get_db_system() method passing in the OCID for the new DB System as returned in the create_db_system_response.data.id variable. We pole the DB System until its lifecycle_state equals ACTIVE. There are other methods for doing this including some helper methods in the OCI API, but those are a bit more advanced for those getting started. Polling the lifecycle_state is an acceptable initial solution if you want the script to execute and wait until the resource is ready.

That’s about it. There are more nuances to this example especially the Python programming parts, but we leave those details to you to ponder as an exercise. There are no magical or arcane code constructs here, just normal Python code around the Python API for OCI.

Listing 9-21 shows the completed script. Take a few moments and read it so that you understand how it works. Don’t worry about the Python details; they will come with experience working with Python.
import getpass
import os
import sys
import time
# Import the oci module
import oci
# Global variables
# Get the compartment id from the environment
COMPARTMENT_ID = os.getenv('COMPARTMENT_ID')
config = None
# Helper function to display a list of items and let user choose one.
def get_selection(title, items):
    item_chosen = -1
    print(" {0} ".format(title))
    num = 1
    for item in items:
        # Display only the first column if item is a list
        if isinstance(item, list):
            print("{0:2}: {1}".format(num, item[0]))
        else:
            print("{0:2}: {1}".format(num, item))
        num += 1
    item_chosen = int(input(" Select the item in the list (int): "))
    return item_chosen - 1
# Get the subnet OCID
def get_subnet_ocid():
    # Initialize service client with default config file
    core_client = oci.core.VirtualNetworkClient(config)
    # List the subnets
    list_subnets_response = core_client.list_subnets(
        compartment_id=COMPARTMENT_ID,
        lifecycle_state="AVAILABLE"
    )
    # Loop through the data and get the subnet name + OCID
    subnets = []
    for subnet_summary in list_subnets_response.data:
        subnets.append([subnet_summary.display_name, subnet_summary.id])
    return subnets[get_selection("Choose a subnet:", subnets)][1]
# Get the MySQL shape
def get_mysql_shape():
    # Initialize service client with default config file
    mysql_client = oci.mysql.MysqlaasClient(config)
    # List the MySQL shapes
    list_shapes_response =
    mysql_client.list_shapes(compartment_id=COMPARTMENT_ID)
    # Loop through the data and get the shape names only.
    shapes = []
    for shape_summary in list_shapes_response.data:
        shapes.append(shape_summary.name)
    return shapes[get_selection("Choose a MySQL shape name:", shapes)]
# Get the availability domain name
def get_availability_domain_name():
    # Initialize service client with default config file
    identity_client = oci.identity.IdentityClient(config)
    # List the availability domains
    list_availability_domains_response =
    identity_client.list_availability_domains(COMPARTMENT_ID)
    # Loop through the data and get the shape names only.
    ad_names = []
    for ad_summary in list_availability_domains_response.data:
        ad_names.append(ad_summary.name)
    return ad_names[get_selection(
    "Choose an availability domain:", ad_names)]
# Main function
def main():
    # Read your configuration file: be sure to provide a path if
    # your configuration file.
    global config
    config = oci.config.from_file()
    # Read the passphrase from the user
    pass_phrase = getpass.getpass("Enter the SSH key passphrase: ")
    # Add the passphrase  to the config file dictionary.
    config.update({'pass_phrase':pass_phrase})
    # Initialize service client with default config file
    db_client = oci.mysql.DbSystemClient(config)
    # We need to get three pieces of information:
    # 1. Subnet OCID
    # 2. MySQL shape name
    # 3. Availability domain name
    # Get the subnets for the compartment
    subnet_ocid = get_subnet_ocid()
    # Get the shape name
    shape_name = get_mysql_shape()
    # Get the availability domain
    availability_domain_name = get_availability_domain_name()
    # Get optional parameters
    print(" Enter optional parameters: ")
    display_name = input("Enter display name: ")
    db_size = int(input("Enter DB size in GBs (e.g. 50): "))
    mysql_admin_user = input("Enter MySQL administrator user name: ")
    mysql_admin_passwd = getpass.getpass(
    "Enter MySQL administrator password: ")
    # Disable HA
    is_ha = False
    # Now, we create the DB System
    create_db_system_response = db_client.create_db_system(
        create_db_system_details=oci.mysql.models.CreateDbSystemDetails(
            compartment_id=COMPARTMENT_ID,
            shape_name=shape_name,
            subnet_id=subnet_ocid,
            display_name=display_name,
            is_highly_available=is_ha,
            availability_domain=availability_domain_name,
            admin_username=mysql_admin_user,
            admin_password=mysql_admin_passwd,
            data_storage_size_in_gbs=db_size,
          backup_policy=oci.mysql.models.CreateBackupPolicyDetails(
                is_enabled=False),
        )
    )
    print(" Waiting for DB System to be available.", end='')
    # Now, loop until the work request is done by watching
    # the DB System lifecycle state.
    db_system_ocid = create_db_system_response.data.id
    while True:
        get_db_system_response = db_client.get_db_system(
            db_system_id=db_system_ocid)
        if get_db_system_response.data.lifecycle_state == 'AVAILABLE':
            break
        else:
            print(".", end='')
            sys.stdout.flush()
            time.sleep(10)
    print("Done!")
# Direct execution to main if this module is executed directly
if __name__ == "__main__":
    main()
Listing 9-21

Create DB Systems Script

Now, let’s see the code running. Listing 9-22 shows the output from running the script. Notice the lists of choices and the responses (edited for brevity).
C:Userscbell>python create_db_system.py
Enter the SSH key passphrase:
Choose a subnet:
 1: Private Subnet-oci-tutorial-vcn
 2: Public Subnet-oci-tutorial-vcn
Select the item in the list (int): 1
Choose a MySQL shape name:
 1: VM.Standard.E2.1
 2: VM.Standard.E2.2
 3: VM.Standard.E2.4
 4: VM.Standard.E2.8
 5: MySQL.VM.Standard.E3.1.8GB
 6: MySQL.VM.Standard.E3.1.16GB
 7: MySQL.VM.Standard.E3.2.32GB
 8: MySQL.VM.Standard.E3.4.64GB
 9: MySQL.VM.Standard.E3.8.128GB
10: MySQL.VM.Standard.E3.16.256GB
11: MySQL.VM.Standard.E3.24.384GB
12: MySQL.VM.Standard.E3.32.512GB
13: MySQL.VM.Standard.E3.48.768GB
14: MySQL.VM.Standard.E3.64.1024GB
...
45: MySQL.HeatWave.BM.Standard.E3
Select the item in the list (int): 5
Choose an availability domain:
 1: DRUu:US-ASHBURN-AD-1
 2: DRUu:US-ASHBURN-AD-2
 3: DRUu:US-ASHBURN-AD-3
Select the item in the list (int): 3
Enter optional parameters:
Enter display name: TEST_API
Enter DB size in GBs (e.g. 50): 50
Enter MySQL administrator user name: mysql_admin
Enter MySQL administrator password:
Waiting................................................................................................................................Done!
Listing 9-22

Output from DB System Script

Take some time and experiment with this script for your own uses. You may find it helpful to getting your own automation in Python going for MDS.

However, in case you’re curious, Figure 9-2 shows the DB System details page from the console.

A Database page of TEST A P I with details of general information, D B system configuration, backup, heatwave, high availability, networking, placement, and endpoint.

Figure 9-2

New DB System Details Page (API Example)

But wait, there is more. Let’s add a bonus example for you to try on your own.

Delete a DB System

Your challenge is to take the control DB System script above and add the delete operation. To get started, you will need to use the delete_db_system () method of the oci.mysql.DbSystemClient class. You can find the documentation for this method and an example Python script at https://docs.oracle.com/en-us/iaas/tools/python/2.79.0/api/mysql/client/oci.mysql.DbSystemClient.html#oci.mysql.DbSystemClient.delete_db_system. You should not have to add much to the control DB System script (control_db_system.py) to accomplish this task, but it will be a good exercise for those just starting out with Python and the API.

Well, that’s our tour of the API! Although the tour of the MDS API and the Python SDK was brief, it should give you an idea of what is possible and the basis to begin researching your own Python applications to work with MDS resources.

Summary

When working with tens, hundreds, or thousands of DB Systems, performing maintenance operations on or working with the OCI web-based console may become tedious and somewhat slower than you’d like. That’s where the CLI and APIs shine; they allow you to script common operations either in a Bash (or similar) script or in a Python code file that you can execute.

Either way, you will gain greater control and greater productivity when working with many OCI products and services and especially when your OCI operations become routine. In those cases, any improvement in productivity pays dividends. If these advantages appeal to you, I encourage you to read the online documentation for those areas you want to automate (script) first so that you can get acquainted with the mechanisms used. Once you’ve mastered the basics, you can branch out to explore more complex operations.

In the next chapter, we will learn some strategies and planning for migrating existing on-prem MySQL installations to MDS.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.131.168