in mds_plugin/util.py [0:0]
def create_compute_instance_for_endpoint(**kwargs):
"""Returns a public compute instance
If the instance does not yet exists in the compartment, create it
Args:
**kwargs: Optional parameters
Keyword Args:
instance_name (str): The name of the compute instance
db_system_name (str): The new name of the DB System.
db_system_id (str): The OCID of the db_system
private_key_file_path (str): The file path to an SSH private key
subnet_id (str): The OCID of the subnet to use
public_ip (bool): If set to false, no public IP will be assigned
shape (str): The name of the shape to use
cpu_count (int): The number of OCPUs
memory_size (int): The amount of memory
dns_a_record_notification (bool): Whether to print a message to setup the DNS A record for this instance
domain_name (str): The domain name of the compute instance
compartment_id (str): The OCID of the compartment
config (object): An OCI config object or None.
config_profile (str): The name of an OCI config profile
interactive (bool): Indicates whether to execute in interactive mode
raise_exceptions (bool): If set to true exceptions are raised
return_formatted (bool): If set to true, a list object is returned
return_python_object (bool): Used for internal plugin calls
Returns:
None
"""
instance_name = kwargs.get("instance_name", "MDSJumpHost")
db_system_name = kwargs.get("db_system_name")
db_system_id = kwargs.get("db_system_id")
private_key_file_path = kwargs.get(
"private_key_file_path", "~/.ssh/id_rsa")
public_ip = kwargs.get("public_ip", True)
subnet_id = kwargs.get("subnet_id")
shape = kwargs.get("shape", "VM.Standard.E4.Flex")
cpu_count = kwargs.get("cpu_count", 1)
memory_size = kwargs.get("memory_size", 16)
dns_a_record_notification = kwargs.get("dns_a_record_notification", False)
domain_name = kwargs.get("domain_name")
compartment_id = kwargs.get("compartment_id")
config = kwargs.get("config")
config_profile = kwargs.get("config_profile")
interactive = kwargs.get("interactive", core.get_interactive_default())
raise_exceptions = kwargs.get("raise_exceptions", not interactive)
return_formatted = kwargs.get("return_formatted", interactive)
return_python_object = kwargs.get("return_python_object", False)
# Get the active config and compartment
try:
config = configuration.get_current_config(
config=config, config_profile=config_profile,
interactive=interactive)
compartment_id = configuration.get_current_compartment_id(
compartment_id=compartment_id, config=config)
import oci.mysql
from pathlib import Path
import os.path
from mds_plugin import compartment, compute, network
import time
db_system = mysql_database_service.get_db_system(
db_system_name=db_system_name, db_system_id=db_system_id,
compartment_id=compartment_id, config=config,
interactive=interactive, raise_exceptions=True,
return_python_object=True)
if db_system is None:
raise ValueError("DB System not specified or found.")
# Get compartment and public subnet_id from MDS
if not compartment_id:
compartment_id = db_system.compartment_id
if not subnet_id:
mds_subnet = network.get_subnet(
subnet_id=db_system.subnet_id,
config=config, interactive=False)
subnet = network.get_subnet(
network_id=mds_subnet.vcn_id,
public_subnet=public_ip,
config=config,
interactive=False)
if subnet:
subnet_id = subnet.id
if not subnet_id:
if public_ip:
raise ValueError(
'The network used by the MDS instance does not have public subnet.'
'Please add a public subnet first')
else:
raise ValueError('No subnet specified.')
# Try to get the Compute Instance with the given name
mds_jump_host = compute.get_instance(
instance_name=instance_name,
compartment_id=compartment_id,
config=config, interactive=False,
raise_exceptions=True,
return_python_object=True)
# If it already exists, return it
if mds_jump_host:
return mds_jump_host
# if interactive:
# # If there is no MySQL DBSystemProxy instance yet, ask the user
# print(f"In order to perform the requested operation for the MySQL "
# f"DB System\na compute instance named 'MDSJumpHost' "
# f"needs to be created.\n")
# prompt = core.prompt(
# "Do you want to create a new compute instance to be used as "
# "bastion host? [YES/no]: ",
# {'defaultValue': 'yes'}).strip().lower()
# if prompt != "yes":
# print("Operation cancelled.\n")
# return
if interactive:
print(f"Creating Compute Instance '{instance_name}'...")
new_jump_host = compute.create_instance(
instance_name=instance_name,
shape=shape,
cpu_count=cpu_count, memory_size=memory_size,
operating_system="Oracle Linux",
operating_system_version="9",
use_latest_image=True,
subnet_id=subnet_id,
public_subnet=public_ip,
init_script_file_path=os.path.join(
os.path.join(Path(__file__).parent.absolute(), "internal"), "init_router_script.sh"),
interactive=False,
return_python_object=True)
if new_jump_host is None:
print("Compute instance could not be created.")
return
# Initialize the identity client
compute_client = core.get_oci_compute_client(config=config)
print(f"Waiting for Compute Instance '{instance_name}' to become "
"available.\nThis can take up to 5 minutes or more.", end="")
# Wait until the lifecycle_state == RUNNING, 5 minutes max
try:
cycles = 0
while cycles < 60:
mds_jump_host = compute_client.get_instance(
new_jump_host.id).data
if mds_jump_host.lifecycle_state == "RUNNING":
break
else:
time.sleep(5)
print(".", end="")
cycles += 1
print("")
except oci.exceptions.ServiceError as e:
print(f'Could not fetch the compute instances state.\n'
f'ERROR: {e.message}. (Code: {e.code}; Status: {e.status})')
return
if mds_jump_host.lifecycle_state != "RUNNING":
print(f"Compute Instance '{instance_name}' did not become available "
f"within 5 minutes. Please check the state manually.")
return None if interactive else mds_jump_host
if interactive:
print(f"Compute Instance '{instance_name}' became available.")
# Get the public IP of the instance
public_ip = compute.get_instance_public_ip(
instance_id=mds_jump_host.id, compartment_id=compartment_id,
config=config, private_ip_fallback=True)
if public_ip is None or public_ip == "":
raise Exception(
f"The public IP of the {instance_name} instance could not be "
"fetched.")
if dns_a_record_notification and interactive:
print("\nATTENTION: Please create a DNS A record using the following values.\n"
f"Domain: {domain_name}\n"
f"Destination TCP/IP address: {public_ip}")
answered = False
while not answered:
try:
result = core.prompt(
f"Please click OK once the DNS A record has been created. [OK/Cancel]: ",
{"defaultValue": "OK"})
answered = True
except:
print(
"Please select OK or Cancel on the confirmation notification.")
pass
if result != "OK":
raise Exception(
"Endpoint creation cancelled. Please delete the compute instance that has been created.")
if interactive:
print("\nPerforming base configuration.\n"
f"Connecting to {instance_name} instance at {public_ip}...",
end="")
setup_complete = False
connected = False
cycles = 0
while not setup_complete and cycles < 10:
cycles += 1
try:
with compute.SshConnection(
username="opc", host=public_ip,
private_key_file_path=private_key_file_path) as conn:
connected = True
if interactive:
print(f"\nConnected to {instance_name} instance at "
f"{public_ip}.")
# Get MySQL Router configuration from remote instance
output = ""
output = conn.execute('mysqlsh --js -e "mds.info()"').strip()
if "MySQL Shell MDS Plugin" not in output:
# If the config is not available yet, give the instance
# time to complete setup
if interactive:
print(f"Waiting for {instance_name} setup to be "
f"completed.\nThis can take up to 2 minutes.",
end="")
try:
i = 0
while ("MySQL Shell MDS Plugin" not in output
and i < 25):
output = conn.execute(
'mysqlsh --js -e "mds.info()"').strip()
if "MySQL Shell MDS Plugin" not in output:
time.sleep(5)
if interactive:
print(".", end="")
i += 1
except:
pass
if interactive:
print("")
if "MySQL Shell MDS Plugin" not in output:
raise Exception(
f"\nCould not finish the '{instance_name}' setup "
f"at {public_ip}.\n")
else:
setup_complete = True
except Exception as e:
if cycles < 10 and not connected:
time.sleep(5)
if interactive:
print(".", end="")
else:
raise Exception(
f"Could not connect to compute instance "
f"'{instance_name}' at {public_ip}.\n"
f"ERROR: {str(e)}")
if interactive:
print(f"Compute Instance '{instance_name}' successfully created.")
return core.return_oci_object(
oci_object=new_jump_host,
return_formatted=return_formatted,
return_python_object=return_python_object,
format_function=compute.format_instance_listing)
except Exception as e:
if raise_exceptions:
raise
print(f"ERROR: {str(e)}")