|
| 1 | + |
| 2 | +import argparse |
| 3 | +import sys |
| 4 | +import time |
| 5 | + |
| 6 | +from yandex.cloud.compute.v1.image_service_pb2 import GetImageLatestByFamilyRequest |
| 7 | +from yandex.cloud.compute.v1.image_service_pb2_grpc import ImageServiceStub |
| 8 | +from yandex.cloud.compute.v1.instance_pb2 import IPV4, Instance |
| 9 | +from yandex.cloud.compute.v1.instance_service_pb2 import CreateInstanceRequest, ResourcesSpec, AttachedDiskSpec, NetworkInterfaceSpec, PrimaryAddressSpec, OneToOneNatSpec, DeleteInstanceRequest, CreateInstanceMetadata |
| 10 | +from yandex.cloud.compute.v1.instance_service_pb2_grpc import InstanceServiceStub |
| 11 | +from yandex.cloud.operation.operation_service_pb2 import GetOperationRequest |
| 12 | +from yandex.cloud.operation.operation_service_pb2_grpc import OperationServiceStub |
| 13 | +from yandex.cloud.vpc.v1.subnet_service_pb2 import ListSubnetsRequest |
| 14 | +from yandex.cloud.vpc.v1.subnet_service_pb2_grpc import SubnetServiceStub |
| 15 | + |
| 16 | +import yandexcloud |
| 17 | + |
| 18 | + |
| 19 | +def get_subnet(sdk, folder_id, zone): |
| 20 | + subnet_service = sdk.client(SubnetServiceStub) |
| 21 | + subnets = subnet_service.List(ListSubnetsRequest( |
| 22 | + folder_id=folder_id)).subnets |
| 23 | + applicable = [s for s in subnets if s.zone_id == zone] |
| 24 | + if len(applicable) == 1: |
| 25 | + return applicable[0].id |
| 26 | + if len(applicable) == 0: |
| 27 | + message = 'There are no subnets in {} zone, please create it.' |
| 28 | + raise RuntimeError(message.format(zone)) |
| 29 | + message = 'There are more than one subnet in {} zone, please specify it' |
| 30 | + raise RuntimeError(message.format(zone)) |
| 31 | + |
| 32 | + |
| 33 | +def create_instance(sdk, folder_id, zone, name, subnet_id): |
| 34 | + image_service = sdk.client(ImageServiceStub) |
| 35 | + source_image = image_service.GetLatestByFamily( |
| 36 | + GetImageLatestByFamilyRequest( |
| 37 | + folder_id='standard-images', |
| 38 | + family='debian-9')) |
| 39 | + subnet_id = subnet_id or get_subnet(sdk, folder_id, zone) |
| 40 | + instance_service = sdk.client(InstanceServiceStub) |
| 41 | + operation = instance_service.Create(CreateInstanceRequest( |
| 42 | + folder_id=folder_id, |
| 43 | + name=name, |
| 44 | + resources_spec=ResourcesSpec( |
| 45 | + memory=2 * 2**30, |
| 46 | + cores=1, |
| 47 | + core_fraction=0), |
| 48 | + zone_id=zone, |
| 49 | + platform_id='standard-v1', |
| 50 | + boot_disk_spec=AttachedDiskSpec( |
| 51 | + auto_delete=True, |
| 52 | + disk_spec=AttachedDiskSpec.DiskSpec( |
| 53 | + type_id='network-hdd', |
| 54 | + size=20 * 2 ** 30, |
| 55 | + image_id=source_image.id)), |
| 56 | + network_interface_specs=[ |
| 57 | + NetworkInterfaceSpec( |
| 58 | + subnet_id=subnet_id, |
| 59 | + primary_v4_address_spec=PrimaryAddressSpec( |
| 60 | + one_to_one_nat_spec=OneToOneNatSpec( |
| 61 | + ip_version=IPV4, |
| 62 | + ))), |
| 63 | + ], |
| 64 | + )) |
| 65 | + print('Creating initiated') |
| 66 | + return operation |
| 67 | + |
| 68 | + |
| 69 | +def delete_instance(sdk, instance_id): |
| 70 | + instance_service = sdk.client(InstanceServiceStub) |
| 71 | + return instance_service.Delete( |
| 72 | + DeleteInstanceRequest(instance_id=instance_id)) |
| 73 | + |
| 74 | + |
| 75 | +def wait_for_operation(sdk, op): |
| 76 | + operation_service = sdk.client(OperationServiceStub) |
| 77 | + while True: |
| 78 | + new_op = operation_service.Get(GetOperationRequest(operation_id=op.id)) |
| 79 | + if new_op.done: |
| 80 | + if new_op.HasField('error'): |
| 81 | + raise RuntimeError('Operation error: {}'.format(new_op.error)) |
| 82 | + print('done') |
| 83 | + return new_op |
| 84 | + sys.stdout.write('.') |
| 85 | + sys.stdout.flush() |
| 86 | + time.sleep(1) |
| 87 | + |
| 88 | + |
| 89 | +def main(token, folder_id, zone, name, subnet_id): |
| 90 | + sdk = yandexcloud.SDK(token=token) |
| 91 | + operation = create_instance(sdk, folder_id, zone, name, subnet_id) |
| 92 | + meta = CreateInstanceMetadata() |
| 93 | + operation.metadata.Unpack(meta) |
| 94 | + print('Creating instance {}'.format(meta.instance_id)) |
| 95 | + operation = wait_for_operation(sdk, operation) |
| 96 | + |
| 97 | + instance = Instance() |
| 98 | + operation.response.Unpack(instance) |
| 99 | + |
| 100 | + print('Deleting instance {}'.format(instance.id)) |
| 101 | + operation = delete_instance(sdk, instance.id) |
| 102 | + wait_for_operation(sdk, operation) |
| 103 | + |
| 104 | + |
| 105 | +if __name__ == '__main__': |
| 106 | + parser = argparse.ArgumentParser( |
| 107 | + description=__doc__, |
| 108 | + formatter_class=argparse.RawDescriptionHelpFormatter) |
| 109 | + parser.add_argument('--token', help='OAuth token') |
| 110 | + parser.add_argument('--folder-id', help='Your Yandex.Cloud folder id') |
| 111 | + parser.add_argument( |
| 112 | + '--zone', default='ru-central1-b', |
| 113 | + help='Compute Engine zone to deploy to.') |
| 114 | + parser.add_argument( |
| 115 | + '--name', default='demo-instance', help='New instance name.') |
| 116 | + parser.add_argument( |
| 117 | + '--subnet-id', default='', help='Subnet of the instance') |
| 118 | + |
| 119 | + args = parser.parse_args() |
| 120 | + |
| 121 | + main(args.token, args.folder_id, args.zone, args.name, args.subnet_id) |
0 commit comments