zbuilder 0.2.2__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {zbuilder-0.2.2 → zbuilder-0.2.3}/PKG-INFO +5 -18
  2. {zbuilder-0.2.2 → zbuilder-0.2.3}/README.md +4 -12
  3. {zbuilder-0.2.2 → zbuilder-0.2.3}/pyproject.toml +1 -10
  4. {zbuilder-0.2.2 → zbuilder-0.2.3}/pyproject.toml.orig +1 -15
  5. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/helpers.py +1 -1
  6. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/vm/aws.py +4 -1
  7. zbuilder-0.2.2/src/zbuilder/dns/gcp.py +0 -90
  8. zbuilder-0.2.2/src/zbuilder/vm/gcp.py +0 -305
  9. {zbuilder-0.2.2 → zbuilder-0.2.3}/LICENSE +0 -0
  10. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/__init__.py +0 -0
  11. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/base.py +0 -0
  12. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/cfg.py +0 -0
  13. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/cli.py +0 -0
  14. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/dns/__init__.py +0 -0
  15. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/dns/aws.py +0 -0
  16. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/dns/bind.py +0 -0
  17. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/dns/powerdns.py +0 -0
  18. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/ipam/__init__.py +0 -0
  19. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/ipam/phpipam.py +0 -0
  20. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/options.py +0 -0
  21. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/plugins.py +0 -0
  22. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/vm/__init__.py +0 -0
  23. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/vm/kvm.py +0 -0
  24. {zbuilder-0.2.2 → zbuilder-0.2.3}/src/zbuilder/vm/proxmox.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zbuilder
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Create VMs
5
5
  Author: Nikos Chasiotis
6
6
  Author-email: Nikos Chasiotis <hasiotis@gmail.com>
@@ -31,14 +31,9 @@ Requires-Dist: boto3>=1.43.73
31
31
  Requires-Dist: tabulate>=0.10.0
32
32
  Requires-Dist: libvirt-python>=11,<12
33
33
  Requires-Dist: pycdlib>=1.14,<2
34
- Requires-Dist: google-auth-oauthlib>=0.4,<1.5 ; extra == 'gcp'
35
- Requires-Dist: oauthlib>=3.2.1,<4 ; extra == 'gcp'
36
- Requires-Dist: google-api-python-client>=2.198.0,<3 ; extra == 'gcp'
37
- Requires-Dist: google-cloud-dns>=0.37.0,<0.38 ; extra == 'gcp'
38
34
  Requires-Dist: proxmoxer>=1.1,<3 ; extra == 'proxmox'
39
35
  Requires-Python: >=3.12, <4
40
36
  Project-URL: Repository, https://github.com/hasiotis/zbuilder
41
- Provides-Extra: gcp
42
37
  Provides-Extra: proxmox
43
38
  Description-Content-Type: text/markdown
44
39
 
@@ -47,7 +42,6 @@ Description-Content-Type: text/markdown
47
42
  [![PyPi version](https://badge.fury.io/py/zbuilder.svg)](https://pypi.org/project/zbuilder/)
48
43
  [![PyPi downloads](https://img.shields.io/pypi/dm/zbuilder.svg)](https://pypistats.org/packages/zbuilder)
49
44
  [![Build status](https://github.com/hasiotis/zbuilder/workflows/master/badge.svg)](https://github.com/hasiotis/zbuilder/actions?query=workflow%3A%22master%22)
50
- [![Documentation Status](https://readthedocs.org/projects/zbuilder/badge/?version=stable)](https://zbuilder.readthedocs.io/en/stable/?badge=stable)
51
45
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://github.com/hasiotis/zbuilder/blob/master/LICENSE)
52
46
 
53
47
  ZBuilder is a tool to help you build VMs ready to be transferred to ansible.
@@ -73,11 +67,6 @@ or
73
67
  pip3 install --user --upgrade zbuilder
74
68
  ```
75
69
 
76
- The `gcp` provider needs the google client libraries, which ship as an extra:
77
- ```
78
- pipx install --force 'zbuilder[gcp]'
79
- ```
80
-
81
70
  The `proxmox` provider needs `proxmoxer`, which ships as an extra:
82
71
  ```
83
72
  pipx install --force 'zbuilder[proxmox]'
@@ -87,12 +76,11 @@ pipx install --force 'zbuilder[proxmox]'
87
76
 
88
77
  | Family | Providers |
89
78
  |---|---|
90
- | VM | `aws`, `gcp`, `kvm`, `proxmox` |
91
- | DNS | `aws`, `bind`, `gcp`, `powerdns` |
79
+ | VM | `aws`, `kvm`, `proxmox` |
80
+ | DNS | `aws`, `bind`, `powerdns` |
92
81
  | IPAM | `phpipam` |
93
82
 
94
- See the [documentation](https://zbuilder.readthedocs.io/en/stable/) for the
95
- settings each one accepts, or run `zbuilder providers`.
83
+ Run `zbuilder providers` to see the settings each one accepts.
96
84
 
97
85
  ## Development
98
86
  During development you can:
@@ -106,6 +94,5 @@ prek run --all-files # lint and format
106
94
 
107
95
  ## Links
108
96
 
109
- [Documentation](https://zbuilder.readthedocs.io/en/stable/?badge=stable)
110
- | [Releases](https://pypi.org/project/zbuilder/)
97
+ [Releases](https://pypi.org/project/zbuilder/)
111
98
  | [Code](https://github.com/hasiotis/zbuilder)
@@ -3,7 +3,6 @@
3
3
  [![PyPi version](https://badge.fury.io/py/zbuilder.svg)](https://pypi.org/project/zbuilder/)
4
4
  [![PyPi downloads](https://img.shields.io/pypi/dm/zbuilder.svg)](https://pypistats.org/packages/zbuilder)
5
5
  [![Build status](https://github.com/hasiotis/zbuilder/workflows/master/badge.svg)](https://github.com/hasiotis/zbuilder/actions?query=workflow%3A%22master%22)
6
- [![Documentation Status](https://readthedocs.org/projects/zbuilder/badge/?version=stable)](https://zbuilder.readthedocs.io/en/stable/?badge=stable)
7
6
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://github.com/hasiotis/zbuilder/blob/master/LICENSE)
8
7
 
9
8
  ZBuilder is a tool to help you build VMs ready to be transferred to ansible.
@@ -29,11 +28,6 @@ or
29
28
  pip3 install --user --upgrade zbuilder
30
29
  ```
31
30
 
32
- The `gcp` provider needs the google client libraries, which ship as an extra:
33
- ```
34
- pipx install --force 'zbuilder[gcp]'
35
- ```
36
-
37
31
  The `proxmox` provider needs `proxmoxer`, which ships as an extra:
38
32
  ```
39
33
  pipx install --force 'zbuilder[proxmox]'
@@ -43,12 +37,11 @@ pipx install --force 'zbuilder[proxmox]'
43
37
 
44
38
  | Family | Providers |
45
39
  |---|---|
46
- | VM | `aws`, `gcp`, `kvm`, `proxmox` |
47
- | DNS | `aws`, `bind`, `gcp`, `powerdns` |
40
+ | VM | `aws`, `kvm`, `proxmox` |
41
+ | DNS | `aws`, `bind`, `powerdns` |
48
42
  | IPAM | `phpipam` |
49
43
 
50
- See the [documentation](https://zbuilder.readthedocs.io/en/stable/) for the
51
- settings each one accepts, or run `zbuilder providers`.
44
+ Run `zbuilder providers` to see the settings each one accepts.
52
45
 
53
46
  ## Development
54
47
  During development you can:
@@ -62,6 +55,5 @@ prek run --all-files # lint and format
62
55
 
63
56
  ## Links
64
57
 
65
- [Documentation](https://zbuilder.readthedocs.io/en/stable/?badge=stable)
66
- | [Releases](https://pypi.org/project/zbuilder/)
58
+ [Releases](https://pypi.org/project/zbuilder/)
67
59
  | [Code](https://github.com/hasiotis/zbuilder)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "zbuilder"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  description = "Create VMs"
5
5
  license = "GPL-3.0-or-later"
6
6
  license-files = ["LICENSE"]
@@ -41,12 +41,6 @@ name = "Nikos Chasiotis"
41
41
  email = "hasiotis@gmail.com"
42
42
 
43
43
  [project.optional-dependencies]
44
- gcp = [
45
- "google-auth-oauthlib>=0.4,<1.5",
46
- "oauthlib>=3.2.1,<4",
47
- "google-api-python-client>=2.198.0,<3",
48
- "google-cloud-dns>=0.37.0,<0.38",
49
- ]
50
44
  proxmox = ["proxmoxer>=1.1,<3"]
51
45
 
52
46
  [project.urls]
@@ -57,14 +51,12 @@ zbuilder = "zbuilder.cli:cli"
57
51
 
58
52
  [project.entry-points."zbuilder.vm"]
59
53
  aws = "zbuilder.vm.aws:vmProvider"
60
- gcp = "zbuilder.vm.gcp:vmProvider"
61
54
  kvm = "zbuilder.vm.kvm:vmProvider"
62
55
  proxmox = "zbuilder.vm.proxmox:vmProvider"
63
56
 
64
57
  [project.entry-points."zbuilder.dns"]
65
58
  aws = "zbuilder.dns.aws:dnsProvider"
66
59
  bind = "zbuilder.dns.bind:dnsProvider"
67
- gcp = "zbuilder.dns.gcp:dnsProvider"
68
60
  powerdns = "zbuilder.dns.powerdns:dnsProvider"
69
61
 
70
62
  [project.entry-points."zbuilder.ipam"]
@@ -75,7 +67,6 @@ dev = [
75
67
  "pytest>=9.1.1,<10",
76
68
  "pytest-md-report>=0.8.0",
77
69
  ]
78
- docs = ["sphinx>=7.2.6,<8"]
79
70
 
80
71
  [tool.uv]
81
72
  default-groups = ["dev"]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "zbuilder"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  description = "Create VMs"
5
5
  authors = [{ name = "Nikos Chasiotis", email = "hasiotis@gmail.com" }]
6
6
  license = "GPL-3.0-or-later"
@@ -40,15 +40,6 @@ dependencies = [
40
40
  ]
41
41
 
42
42
  [project.optional-dependencies]
43
- # The gcp providers (vm and dns) pull in the whole google client stack, which
44
- # is a large dependency tree nobody outside GCP needs. zbuilder/vm/gcp.py and
45
- # zbuilder/dns/gcp.py import it lazily and say what to install when missing.
46
- gcp = [
47
- "google-auth-oauthlib>=0.4,<1.5",
48
- "oauthlib>=3.2.1,<4",
49
- "google-api-python-client>=2.198.0,<3",
50
- "google-cloud-dns>=0.37.0,<0.38",
51
- ]
52
43
  # The proxmox provider talks to PVE through proxmoxer, which nobody outside a
53
44
  # proxmox cluster needs. zbuilder/vm/proxmox.py imports it lazily and says what
54
45
  # to install when it is missing.
@@ -66,14 +57,12 @@ zbuilder = "zbuilder.cli:cli"
66
57
  # distribution can register providers under the same groups.
67
58
  [project.entry-points."zbuilder.vm"]
68
59
  aws = "zbuilder.vm.aws:vmProvider"
69
- gcp = "zbuilder.vm.gcp:vmProvider"
70
60
  kvm = "zbuilder.vm.kvm:vmProvider"
71
61
  proxmox = "zbuilder.vm.proxmox:vmProvider"
72
62
 
73
63
  [project.entry-points."zbuilder.dns"]
74
64
  aws = "zbuilder.dns.aws:dnsProvider"
75
65
  bind = "zbuilder.dns.bind:dnsProvider"
76
- gcp = "zbuilder.dns.gcp:dnsProvider"
77
66
  powerdns = "zbuilder.dns.powerdns:dnsProvider"
78
67
 
79
68
  [project.entry-points."zbuilder.ipam"]
@@ -84,9 +73,6 @@ dev = [
84
73
  "pytest>=9.1.1,<10",
85
74
  "pytest-md-report>=0.8.0",
86
75
  ]
87
- docs = [
88
- "sphinx>=7.2.6,<8",
89
- ]
90
76
 
91
77
  [tool.uv]
92
78
  default-groups = ["dev"]
@@ -183,7 +183,7 @@ def getProviders(cfg, state):
183
183
  try:
184
184
  cp = cfg["providers"][p]
185
185
  cp["state"] = state
186
- # A name can be registered in more than one family (gcp is both a
186
+ # A name can be registered in more than one family (aws is both a
187
187
  # vm and a dns provider), vm wins as it is the richer one.
188
188
  if cp["type"] in zbuilder.plugins.names(zbuilder.plugins.VM):
189
189
  curProvider = zbuilder.vm.vmProvider(cp["type"], cp)
@@ -36,10 +36,13 @@ class vmProvider(VMProvider):
36
36
  for h, v in self._getVMs(hosts).items():
37
37
  if v["status"] is None:
38
38
  click.echo(" - Creating host: {} ".format(h))
39
+ # Debian AMIs boot from /dev/xvda, ubuntu ones from /dev/sda1. A mapping for any other device
40
+ # name adds a second volume instead of resizing the root one.
41
+ rootDevice = self.ec2.Image(v["values"]["ami"]).root_device_name
39
42
  self.ec2.create_instances(
40
43
  BlockDeviceMappings=[
41
44
  {
42
- "DeviceName": "/dev/sda1",
45
+ "DeviceName": rootDevice,
43
46
  "Ebs": {
44
47
  "DeleteOnTermination": True,
45
48
  "VolumeSize": v["values"].get("disksize", 20),
@@ -1,90 +0,0 @@
1
- """GCP DNS provider.
2
-
3
- Like the gcp vm provider, the google client stack is an optional extra
4
- (`zbuilder[gcp]`) imported lazily, so this module imports without it.
5
- """
6
-
7
- import time
8
- import click
9
-
10
-
11
- from zbuilder.base import DNSProvider
12
- from zbuilder.vm.gcp import auth, require
13
-
14
- try:
15
- from google.cloud import dns
16
- except ImportError: # installed without the gcp extra
17
- dns = None
18
-
19
-
20
- DNS_TTL = 60 * 10 # 10 mins
21
-
22
-
23
- class dnsProvider(DNSProvider):
24
- def __init__(self, cfg):
25
- super().__init__(cfg)
26
- if cfg:
27
- require(dns, "google-cloud-dns")
28
- creds = auth(self.cfg)
29
-
30
- try:
31
- if "project" in cfg["dns"]:
32
- self.dns = dns.Client(project=self.cfg["dns"]["project"], credentials=creds)
33
- else:
34
- self.dns = dns.Client(credentials=creds)
35
- except Exception as e:
36
- click.echo("Login failed: [{}]".format(e))
37
- raise click.Abort()
38
-
39
- def _getZoneInfo(self, host, zone):
40
- zones = self.dns.list_zones()
41
- mzone = None
42
- for z in zones:
43
- if z.dns_name == zone + ".":
44
- mzone = z
45
- break
46
-
47
- return mzone
48
-
49
- def update(self, host, zone, ip):
50
- mzone = self._getZoneInfo(host, zone)
51
- try:
52
- changes = mzone.changes()
53
- changes.delete_record_set(mzone.resource_record_set("{}.{}.".format(host, zone), "A", DNS_TTL, [ip]))
54
- changes.create()
55
- while changes.status != "done":
56
- time.sleep(5)
57
- changes.reload()
58
- click.echo(" - Updating record [{}.{}] with ip [{}]".format(host, zone, ip))
59
- except Exception:
60
- click.echo(" - Creating record [{}.{}] with ip [{}]".format(host, zone, ip))
61
-
62
- changes = mzone.changes()
63
- changes.add_record_set(mzone.resource_record_set("{}.{}.".format(host, zone), "A", DNS_TTL, [ip]))
64
- changes.create()
65
- while changes.status != "done":
66
- time.sleep(5)
67
- changes.reload()
68
- time.sleep(5)
69
-
70
- def remove(self, host, zone):
71
- mzone = self._getZoneInfo(host, zone)
72
- records = mzone.list_resource_record_sets()
73
- found = False
74
- for r in records:
75
- if r.name == "{}.{}.".format(host, zone) and r.record_type in [
76
- "A",
77
- "CNAME",
78
- ]:
79
- found = True
80
- click.echo(" - Removing record [{}.{}]".format(host, zone))
81
- changes = mzone.changes()
82
- changes.delete_record_set(mzone.resource_record_set(r.name, r.record_type, r.ttl, r.rrdatas))
83
- changes.create()
84
- while changes.status != "done":
85
- time.sleep(5)
86
- changes.reload()
87
- break
88
-
89
- if not found:
90
- click.echo(" - No such record [{}.{}]".format(host, zone))
@@ -1,305 +0,0 @@
1
- """GCP provider, driving the google api client.
2
-
3
- The google client stack is an optional extra (`zbuilder[gcp]`) and is imported
4
- lazily: this module has to import on a machine without it, or provider
5
- discovery would break for everybody.
6
- """
7
-
8
- import os
9
- import click
10
- import pickle
11
-
12
- from zbuilder.base import VMProvider
13
- from zbuilder.dns import dnsUpdate, dnsRemove
14
-
15
- try:
16
- import googleapiclient.discovery
17
- from google.oauth2 import service_account
18
- from google_auth_oauthlib.flow import InstalledAppFlow
19
- from google.auth.transport.requests import Request
20
- except ImportError: # installed without the gcp extra
21
- googleapiclient = None
22
-
23
- CONFIG_PATH = "~/.config/zbuilder/"
24
-
25
-
26
- def require(module, name):
27
- """The gcp extra is optional, say so instead of raising ImportError"""
28
- if module is None:
29
- raise click.ClickException(
30
- "The gcp provider needs [{}], install it with: pip install 'zbuilder[gcp]'".format(name)
31
- )
32
- return module
33
-
34
-
35
- def auth(cfg):
36
- require(googleapiclient, "google-api-python-client")
37
-
38
- SCOPES = [
39
- "https://www.googleapis.com/auth/compute",
40
- "https://www.googleapis.com/auth/ndev.clouddns.readwrite",
41
- ]
42
-
43
- creds = None
44
- # First we check for client-secret and creds-file
45
- if "client-secret" in cfg and "creds-file" in cfg:
46
- secretFilename = os.path.expanduser("{}/{}".format(CONFIG_PATH, cfg["client-secret"]))
47
- tokenFilename = os.path.expanduser("{}/{}".format(CONFIG_PATH, cfg.get("creds-file", "")))
48
- if os.path.exists(secretFilename) and os.path.exists(tokenFilename):
49
- with open(tokenFilename, "rb") as token:
50
- creds = pickle.load(token)
51
- if not creds or not creds.valid:
52
- if creds and creds.expired and creds.refresh_token:
53
- creds.refresh(Request())
54
- else:
55
- flow = InstalledAppFlow.from_client_secrets_file(secretFilename, SCOPES)
56
- creds = flow.run_local_server(port=0)
57
- with open(tokenFilename, "wb") as token:
58
- pickle.dump(creds, token)
59
-
60
- # In case of missing client-secret or creds-file fallback to service-key
61
- if creds is None and "service-key" in cfg:
62
- secretFilename = os.path.expanduser("{}/{}".format(CONFIG_PATH, cfg["service-key"]))
63
- if os.path.exists(secretFilename) and os.path.exists(secretFilename):
64
- creds = service_account.Credentials.from_service_account_file(secretFilename, scopes=SCOPES)
65
-
66
- # Fail if no auth keys are available
67
- if creds is None:
68
- click.echo("Unable to authenticate due to missing secrets")
69
- raise click.Abort()
70
-
71
- return creds
72
-
73
-
74
- class vmProvider(VMProvider):
75
- def __init__(self, cfg):
76
- super().__init__(cfg)
77
- if cfg:
78
- creds = auth(self.cfg)
79
-
80
- try:
81
- self.compute = googleapiclient.discovery.build("compute", "v1", credentials=creds)
82
- except Exception as e:
83
- click.echo("Login failed: [{}]".format(e))
84
- raise click.Abort()
85
-
86
- def _waitDone(self, ops, msg=None):
87
- for h, op in ops.items():
88
- while True:
89
- request = self.compute.zoneOperations().get(
90
- project=op["project"], zone=op["zone"], operation=op["name"]
91
- )
92
- response = request.execute()
93
- if response["status"] == "DONE":
94
- if msg:
95
- click.echo(msg.format(h))
96
- break
97
-
98
- def _getVMs(self, hosts):
99
- retValue = {}
100
- for h, v in hosts.items():
101
- if hosts[h]["enabled"]:
102
- shortname = h.partition(".")[0]
103
- try:
104
- result = (
105
- self.compute.instances()
106
- .list(
107
- project=v["project"],
108
- zone=v["zone"],
109
- filter='name="{}"'.format(shortname),
110
- )
111
- .execute()
112
- )
113
- except Exception as e:
114
- click.echo("Error [{}]".format(e))
115
- exit()
116
- items = result.get("items", [])
117
- if items:
118
- retValue[h] = items[0]
119
- retValue[h]["values"] = v
120
- else:
121
- retValue[h] = {"status": None}
122
- retValue[h]["values"] = v
123
-
124
- image_response = (
125
- self.compute.images()
126
- .getFromFamily(project=v["image"]["project"], family=v["image"]["family"])
127
- .execute()
128
- )
129
- source_disk_image = image_response["selfLink"]
130
-
131
- fname = os.path.expanduser(v["ZBUILDER_PUBKEY"])
132
- sshkey = ""
133
- if os.path.isfile(fname):
134
- with open(fname, "r") as f:
135
- sshkey = f.read().rstrip("\n")
136
-
137
- network = "global/networks/{v[network]}".format(v=v)
138
- if "/" in v["network"]:
139
- network = v["network"]
140
-
141
- subnetwork = "regions/{v[region]}/subnetworks/{v[subnet]}".format(v=v)
142
- if "/" in v["subnet"]:
143
- subnetwork = v["subnet"]
144
-
145
- accessConfigs = []
146
- if v.get("net_external", False):
147
- accessConfigs = [{"type": "ONE_TO_ONE_NAT", "name": "External NAT"}]
148
-
149
- retValue[h]["insert"] = self.compute.instances().insert(
150
- project=v["project"],
151
- zone=v["zone"],
152
- body={
153
- "name": shortname,
154
- "machineType": "zones/{v[zone]}/machineTypes/{v[size]}".format(v=v),
155
- "disks": [
156
- {
157
- "boot": True,
158
- "autoDelete": True,
159
- "initializeParams": {
160
- "sourceImage": source_disk_image,
161
- },
162
- }
163
- ],
164
- "networkInterfaces": [
165
- {
166
- "network": network,
167
- "subnetwork": subnetwork,
168
- "accessConfigs": accessConfigs,
169
- }
170
- ],
171
- "metadata": {"items": [{"key": "ssh-keys", "value": "gcpadmin:" + sshkey}]},
172
- },
173
- )
174
-
175
- return retValue
176
-
177
- def build(self, hosts):
178
- ops = {}
179
- ips = {}
180
- for h, v in self._getVMs(hosts).items():
181
- if v["status"] is None:
182
- click.echo(" - Creating host: {} ".format(h))
183
- r = v["insert"].execute()
184
- ops[h] = {
185
- "name": r["name"],
186
- "project": hosts[h]["project"],
187
- "zone": hosts[h]["zone"],
188
- }
189
- ips[h] = None
190
- elif v["status"] == "TERMINATED":
191
- click.echo(" - Booting host: {} ".format(h))
192
- self.compute.instances().start(
193
- project=hosts[h]["project"],
194
- zone=hosts[h]["zone"],
195
- instance=v["name"],
196
- ).execute()
197
- elif v["status"] == "RUNNING":
198
- click.echo(" - Already up host: {} ".format(h))
199
- else:
200
- click.echo(" - Status of host: {} is {}".format(h, v["status"]))
201
-
202
- self._waitDone(ops, " - Host {} created")
203
- for h, v in self._getVMs(hosts).items():
204
- if v["values"].get("dns_external", False):
205
- ips[h] = v["networkInterfaces"][0]["accessConfigs"][0]["natIP"]
206
- else:
207
- ips[h] = v["networkInterfaces"][0]["networkIP"]
208
-
209
- dnsUpdate(ips)
210
-
211
- def up(self, hosts):
212
- for h, v in self._getVMs(hosts).items():
213
- if v["status"] is None:
214
- click.echo(" - No such host: {} ".format(h))
215
- elif v["status"] == "TERMINATED":
216
- click.echo(" - Booting host: {} ".format(h))
217
- self.compute.instances().start(
218
- project=hosts[h]["project"],
219
- zone=hosts[h]["zone"],
220
- instance=v["name"],
221
- ).execute()
222
- elif v["status"] == "RUNNING":
223
- click.echo(" - Already up host: {} ".format(h))
224
- else:
225
- click.echo(" - Status of host: {} is {}".format(h, v["status"]))
226
-
227
- def halt(self, hosts):
228
- for h, v in self._getVMs(hosts).items():
229
- if v["status"] is None:
230
- click.echo(" - No such host: {} ".format(h))
231
- if v["status"] == "RUNNING":
232
- click.echo(" - Halting host: {} ".format(h))
233
- self.compute.instances().stop(
234
- project=hosts[h]["project"],
235
- zone=hosts[h]["zone"],
236
- instance=v["name"],
237
- ).execute()
238
- else:
239
- click.echo(" - Status of host: {} is {}".format(h, v["status"]))
240
-
241
- def destroy(self, hosts):
242
- updateHosts = {}
243
- ops = {}
244
- for h, v in self._getVMs(hosts).items():
245
- if v["status"] is not None:
246
- click.echo(" - Destroying host: {} ".format(h))
247
- r = (
248
- self.compute.instances()
249
- .delete(
250
- project=hosts[h]["project"],
251
- zone=hosts[h]["zone"],
252
- instance=v["name"],
253
- )
254
- .execute()
255
- )
256
- ops[h] = {
257
- "name": r["name"],
258
- "project": hosts[h]["project"],
259
- "zone": hosts[h]["zone"],
260
- }
261
- updateHosts[h] = {}
262
- else:
263
- click.echo(" - Host does not exists : {}".format(h))
264
-
265
- self._waitDone(ops, " - Host {} destroyed")
266
- dnsRemove(updateHosts)
267
-
268
- def dnsupdate(self, hosts):
269
- ips = {}
270
- for h, v in self._getVMs(hosts).items():
271
- if v["values"].get("dns_external", False):
272
- ips[h] = v["networkInterfaces"][0]["accessConfigs"][0]["natIP"]
273
- else:
274
- ips[h] = v["networkInterfaces"][0]["networkIP"]
275
-
276
- dnsUpdate(ips)
277
-
278
- def dnsremove(self, hosts):
279
- ips = {}
280
- for h in hosts:
281
- if hosts[h]["enabled"]:
282
- ips[h] = None
283
-
284
- dnsRemove(hosts)
285
-
286
- def snapCreate(self, hosts):
287
- pass
288
-
289
- def snapRestore(self, hosts):
290
- pass
291
-
292
- def snapDelete(self, hosts):
293
- pass
294
-
295
- def config(self):
296
- if "service-key" in self.cfg:
297
- return "service-key: {}{}".format(CONFIG_PATH, self.cfg["service-key"])
298
- else:
299
- return "client-secret: {}{}".format(CONFIG_PATH, self.cfg["client-secret"])
300
-
301
- def status(self):
302
- return "PASS"
303
-
304
- def params(self, params):
305
- return {k: params[k] for k in ["size", "image"]}
File without changes
File without changes
File without changes
File without changes