首页 > 解决方案 > 在 GCP 中使用 python 代码创建 VM 实例时出现问题

问题描述

我正在尝试编写一个代码,该代码将从 excel 文件中读取值并在 Google Cloud 中创建虚拟机。我在两个位置遇到问题,如果我使用 'items': [tag] 创建标签,或者在创建服务帐户范围时它开始给我错误。

import os, json
import googleapiclient.discovery
from google.oauth2 import service_account
import csv

credentials = service_account.Credentials.from_service_account_file('G:/python/json/mykids-280210.json')
compute = googleapiclient.discovery.build('compute', 'v1', credentials=credentials)

def create_instance(compute, vm_name, image_project, image_family, machinetype, startupscript, zone, network,
                          subnet, project, scope, tag):
    # Get the latest Debian Jessie image.
    image_response = compute.images().getFromFamily(
        project=image_project, family=image_family).execute()
    source_disk_image = image_response['selfLink']

    # Configure the machine
    machine_type = "zones/" + zone + "/machineTypes/" + machinetype
    startup_script = startupscript

    config = {
        'name': vm_name,
        'machineType': machine_type,

        'description': 'This VM was created with python code',

        'tags': {
            'items': ['external', 'home', 'local']              #'items': [tag] <~~~~~~~~~~~
        },

        'deletionProtection': False,

        'labels': {'env': 'dev', 'server': 'mytower', 'purpose': 'personal'},

        # Specify the boot disk and the image to use as a source.
        'disks': [
            {
                'boot': True,
                'autoDelete': True,
                'initializeParams': {
                    'sourceImage': source_disk_image,
                }
            }
        ],

        # Specify a network interface with NAT to access the public
        # internet.
        'networkInterfaces': [{
            'network': 'global/networks/' + network,
            'subnetwork': 'regions/us-central1/subnetworks/' + subnet,
            'accessConfigs': [
                {'type': 'ONE_TO_ONE_NAT', 'name': 'External NAT'}
            ]
        }],

        # Allow the instance to access cloud storage and logging.
        'serviceAccounts': [{
            'email': 'default',
            'scopes': [
                #'https://www.googleapis.com/auth/devstorage.read_write', 'https://www.googleapis.com/auth/logging.write'
                #scope                          # scope      <~~~~~~~~~~~~~~~~~~~~
            ]
        }],
        'scheduling': {
            "preemptible": True
        },

        # Metadata is readable from the instance and allows you to
        # pass configuration from deployment scripts to instances.
         'metadata': {
            'items': [{
        # Startup script is automatically executed by the
        # instance upon startup.
                'key': 'startup-script',
                'value': startup_script
            }]
         }
    }

    return compute.instances().insert(
        project=project,
        zone=zone,
        body=config).execute()
# [END create_instance]

with open('vms.csv', newline='') as csvfile:
    data = csv.DictReader(csvfile)
    for row in data:
        vm_name = row['vm_name']
        image_project = row['image_project']
        image_family = row['image_family']
        machinetype = row['machinetype']
        startupscript = row['startupscript']
        zone = row['zone']
        network = row['network']
        subnet = row['subnet']
        project = row['project']
        scope = row['scopes']
        tag = row['tags']

        print(create_instance(compute, vm_name, image_project, image_family, machinetype, startupscript, zone, network,
                          subnet, project, scope, tag))
    csvfile.close()

使用范围变量时出错

G:\python\pythonProject\venv\Scripts\python.exe G:/python/pythonProject/read-excel-gcp/vm/create_vm.py
Traceback (most recent call last):
  File "G:\python\pythonProject\read-excel-gcp\vm\create_vm.py", line 100, in <module>
    print(create_instance(compute, vm_name, image_project, image_family, machinetype, startupscript, zone, network,
  File "G:\python\pythonProject\read-excel-gcp\vm\create_vm.py", line 79, in create_instance
    return compute.instances().insert(
  File "G:\python\pythonProject\venv\lib\site-packages\googleapiclient\_helpers.py", line 134, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "G:\python\pythonProject\venv\lib\site-packages\googleapiclient\http.py", line 915, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://compute.googleapis.com/compute/v1/projects/mykids-280210/zones/us-central1-a/instances?alt=json returned "One or more of the service account scopes are invalid: 'https://www.googleapis.com/auth/devstorage.read_write',  'https://www.googleapis.com/auth/logging.write''". Details: "One or more of the service account scopes are invalid: 'https://www.googleapis.com/auth/devstorage.read_write',  'https://www.googleapis.com/auth/logging.write''">

Process finished with exit code 1

当我使用标签变量时,我得到了类似的错误。

我在上面的代码中传递了 # 值。

以下是我的 csv 文件详细信息

vm_name,image_project,image_family,machinetype,startupscript,zone,network,subnet,project,scopes,tags
python-vm1,debian-cloud,debian-9,e2-micro,G:/python/json/startup-script.sh,us-central1-a,myvpc,subnet-a,mykids-280210,"https://www.googleapis.com/auth/devstorage.read_write',  'https://www.googleapis.com/auth/logging.write'","external', 'home', 'local'"
python-vm2,debian-cloud,debian-9,e2-micro,G:/python/json/startup-script.sh,us-central1-a,myvpc,subnet-a,mykids-280210,"https://www.googleapis.com/auth/devstorage.read_write',  'https://www.googleapis.com/auth/logging.write'","external', 'home', 'local'"

我不确定当直接传递值时它是否有效,但是当通过变量传递值时,它会失败。

我已经用<~~~~~~~~~~~~标记了问题区域

请建议是否有人理解这个问题。

标签: python-3.xgoogle-cloud-platform

解决方案


@ds您可以尝试将范围格式更改为以下内容:

 'serviceAccounts': [
 {
   'email': 'default'
   'scopes':[
    'https://www.googleapis.com/auth/compute',
    'https://www.googleapis.com/auth/servicecontrol',
    'https://www.googleapis.com/auth/service.management.readonly',
    'https://www.googleapis.com/auth/logging.write',
    'https://www.googleapis.com/auth/monitoring.write',
    'https://www.googleapis.com/auth/trace.append',
    'https://www.googleapis.com/auth/devstorage.read_write']}]

列出的范围是实例所需的默认范围。我认为您面临的问题是您试图仅列出两个不足以让您部署实例的范围。


推荐阅读