oracle/oci-python-sdk

Metadata with ssh and user_data is not working

astuanax opened this issue · 11 comments

The example with launch_instance_example is sending ss keys and an init script as an example, but those things are not working.
Example: https://github.com/oracle/oci-python-sdk/blob/master/examples/launch_instance_example.py

The instance launches, but access is not enabled with the ssh key, nor is the script applied.
We are using Centos7 images.

Here is what I am trying.

First prepare the metadata:

script = oci.util.file_content_as_launch_instance_user_data('/home/opc/oci/init.sh')

with open('/home/opc/oci/pub.key', mode='r') as file:
    ssh_public_key = file.read()

Prepare the instance detail

instance_detail = oci.core.models.LaunchInstanceDetails(
            metadata={
                "ssh_authorized_keys": ssh_file,
                "user_data": init_script

            },
            availability_domain=availability_domain.name,
            shape=shape,
            compartment_id=self.compartment or compartment_id,
            display_name=instance_name,
            source_details=oci.core.models.InstanceSourceViaImageDetails(
                source_type="image", image_id=image_id),
            create_vnic_details=oci.core.models.CreateVnicDetails(
                assign_public_ip=True, subnet_id=subnet_id, assign_private_dns_record=True),
            agent_config=oci.core.models.LaunchInstanceAgentConfigDetails(
                is_monitoring_disabled=False,
                is_management_disabled=False,
                plugins_config=[oci.core.models.InstanceAgentPluginConfigDetails(
                    name='Vulnerability Scanning', desired_state='DISABLED'),
                    oci.core.models.InstanceAgentPluginConfigDetails(name='Compute Instance Monitoring',
                                                                     desired_state='DISABLED')]),
            defined_tags={},
            freeform_tags={},
            instance_options=oci.core.models.InstanceOptions(are_legacy_imds_endpoints_disabled=True),
            availability_config=oci.core.models.LaunchInstanceAvailabilityConfigDetails(
                recovery_action="RESTORE_INSTANCE"),
            shape_config=oci.core.models.LaunchInstanceShapeConfigDetails(ocpus=ocpus, memory_in_gbs=memory_in_gbs,
                                                                          baseline_ocpu_utilization="BASELINE_1_2", )
        )

Then start and wait


launch_instance_response = self.compute_client_composite_operations.launch_instance_and_wait_for_state(
            launch_instance_details,
            wait_for_states=[oci.core.models.Instance.LIFECYCLE_STATE_RUNNING]

The instance details come back with base64 encoded strings for the user_data and a copy of the public key.
Once the instance is running, no scripts have been applied, and no ssh key is enabled.

Any idea what's going wrong?

I had a look at this issue: #54
Thee it also did not work; none of the scripts is executed when sending them with this SDK.
How to send parameters? How to send data to the instance?

Thx in advance!

@astuanax

I am assuming there is a typo in the code you have shared for preparing metadata and preparing instance details.

ssh_public_key -> ssh_file
script -> init_script

This looks good to me. I personally use something similar and it works for me:-

    with open(SSH_FILE_PATH, mode='r') as file:
        ssh_public_key = file.read()

    instance_metadata = {'ssh_authorized_keys': ssh_public_key}
    if os.path.exists(LAUNCH_INSTANCE_FILE):
        instance_metadata['user_data'] = oci.util.file_content_as_launch_instance_user_data(LAUNCH_INSTANCE_FILE)

    instance_name = 'sdk-test'
    instance_source_via_image_details = oci.core.models.InstanceSourceViaImageDetails(
        image_id=image.id
    )
    create_vnic_details = oci.core.models.CreateVnicDetails(
        subnet_id=subnet.id
    )
    launch_instance_details = oci.core.models.LaunchInstanceDetails(
        display_name=instance_name,
        compartment_id=compartment_id,
        availability_domain=availability_domain.name,
        shape=shape.shape,
        metadata=instance_metadata,
        source_details=instance_source_via_image_details,
        create_vnic_details=create_vnic_details
    )

Can you enable logging in Python SDK and share the opc-request-id for this request so that we may forward it to the compute team for more analysis.

Refer https://docs.oracle.com/en-us/iaas/tools/python/2.83.0/logging.html to learn how to enable logging in Python SDK.

Hi,
Thanks for the reply, and yes the variables for the ssh keys and the cloud-init script are set up differently.

Maybe it is because the custom image has been set up with previous user_data and ssh_authorized_keys.
This would mean the script cannot modify it afterwards, I believe.
Or only when it is running?

https://docs.oracle.com/en-us/iaas/tools/python/2.83.0/api/core/models/oci.core.models.UpdateInstanceDetails.html?highlight=user_data#oci.core.models.UpdateInstanceDetails.extended_metadata

The “user_data” field and the “ssh_authorized_keys” field cannot be changed after an instance has launched. Any request that updates, removes, or adds either of these fields will be rejected. You must provide the same values for “user_data” and “ssh_authorized_keys” that already exist on the instance.

It is possible to add them manually in the dashboard, adding new keys and cloud-init scripts.

I will enable logging and do some more testing to confirm my suspicion.

And the IDs for the requests:

header: opc-request-id: D3F1810E88604B7798CC2B349EA8DE0B/30760E7F2AC2C5C95326DB78D8AB5EF7/23A58ED8F7271887744E66028B7A44F8

header: opc-request-id: FC56099A7D4C41EABF19B42DCF319765/CC9F40EE1F57ABB6A524C2BF2FAA72B5/82D8840C229F858C16870DBF979892A1

header: opc-request-id: 57E1147130C34604A54DA1A351174F95/DD96DD3297C1FBE656968E4F3CC14A41/E009FA7A7B60536822A9BBFF8928465D

@astuanax
Can you also share the region you were running these requests in?

@astuanax
Got some more info on this.
Can you check if that cloud-init is installed and set to automatically start in the image you are using? That is what performs the first-boot and on-boot configuration from the metadata instances using the content provided via the Console or SDK/CLI.

It's worth testing the script using an Oracle Linux 7 image which has this stuff enabled: that will indicate whether the issue is with the script or the image.

You should use one of the GenericCloud images: https://cloud.centos.org/centos/7/images/ (or Oracle Linux, which gets supported by Oracle at no additional cost, while CentOS does not)

We used the Centos7 image provided by Oracle, we are not uploading our own images.

So, Centos7 provided by Oracle is not supported?
Only Oracle Linux?

This is weird, everything works fine when using the dashboard, just not when using the python SDK.
That would imply there is a difference and the UI is installing the cloud-init software, while the python SDK is not.

I'll test with Oracle Linux, to confirm.

I can confirm that it works with Oracle Linx.

This is a bit sad, as we spent a week creating images and reading the SDK code to find out that Oracle does not support Centos7 the same way as their distro.

A bit of documentation would be great for the next person to come along.

@astuanax
Let me check if there is a wiki on setting cloud-init on a Centos 7 image.

@astuanax
I believe the Centos 7 images at https://cloud.centos.org/centos/7/images/ have this feature enabled.

@astuanax
Did you get a chance to use the Centos 7 image from the link I shared?

@astuanax
As we haven't heard back from you in a while, we will close this ticket. Please feel free to re-open this ticket if you see issues with the Centos 7 images I shared with you or on an Oracle Linux 7 image.