Skip to content

Commit 43dffac

Browse files
akremenetskygmelikov
authored andcommitted
IAM default client vars and disks vars
- Added variables for IAM default client such as uuid, id, secret. - Added variables to specify root and data disks for core set - Logic to bootstrap scripts to handle the variables - DRY_RUN mode for the libvirt driver Signed-off-by: Anton Kremenetsky <anton.kremenetsky@gmail.com>
1 parent e0e290c commit 43dffac

7 files changed

Lines changed: 288 additions & 20 deletions

File tree

exordos/manifests/core.yaml.j2

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,20 @@ resources:
9898
setter:
9999
kind: selector
100100
selector_strategy: latest
101-
101+
core_root_disk_size:
102+
uuid: "695f4e94-e46b-43ae-aa66-194044740912"
103+
name: "core_root_disk_size"
104+
project_id: "12345678-c625-4fee-81d5-f691897b8142"
105+
setter:
106+
kind: selector
107+
selector_strategy: latest
108+
core_data_disk_size:
109+
uuid: "cf92f6f5-b62f-4cc4-898c-5250a6608d51"
110+
name: "core_data_disk_size"
111+
project_id: "12345678-c625-4fee-81d5-f691897b8142"
112+
setter:
113+
kind: selector
114+
selector_strategy: latest
102115
# HS256 JWKS encryption key (A256GCM, 32 bytes)
103116
hs256_jwks_encryption_key:
104117
uuid: "c371a647-e1a6-4bec-bef2-a50041bc5af2"
@@ -107,6 +120,27 @@ resources:
107120
setter:
108121
kind: selector
109122
selector_strategy: latest
123+
iam_default_client_uuid:
124+
uuid: "d23fa962-18b8-444f-81a0-027ece98fbdb"
125+
name: "default_client_uuid"
126+
project_id: "12345678-c625-4fee-81d5-f691897b8142"
127+
setter:
128+
kind: selector
129+
selector_strategy: latest
130+
iam_default_client_id:
131+
uuid: "239e2a55-c3ad-4adc-85a8-3fa90b669556"
132+
name: "default_client_id"
133+
project_id: "12345678-c625-4fee-81d5-f691897b8142"
134+
setter:
135+
kind: selector
136+
selector_strategy: latest
137+
iam_default_client_secret:
138+
uuid: "784c1f6d-f9e2-47e0-a3ba-16725854ac09"
139+
name: "default_client_secret"
140+
project_id: "12345678-c625-4fee-81d5-f691897b8142"
141+
setter:
142+
kind: selector
143+
selector_strategy: latest
110144

111145
$core.compute.sets:
112146
core_set:
@@ -119,9 +153,9 @@ resources:
119153
disk_spec:
120154
kind: "disks"
121155
disks:
122-
- size: 10
156+
- size: $core.vs.variables.$core_root_disk_size:value
123157
image: "{{ repository | default('https://repo.exordos.com/exordos-elements') }}/core/{{ version }}/images/exordos-core.raw.zst"
124-
- size: 10
158+
- size: $core.vs.variables.$core_data_disk_size:value
125159
label: data
126160

127161
$core.dns.domains:
@@ -203,6 +237,36 @@ resources:
203237
- kind: rewrite_url
204238
regex: "^/api/core/(.*)"
205239
replacement: "/$1"
240+
core_lb_iam_default_client:
241+
project_id: "12345678-c625-4fee-81d5-f691897b8142"
242+
parent: $core.network.lb.$core_lb.vhosts.$core_lb_core_http:uuid
243+
condition:
244+
kind: prefix
245+
value: /api/core/v1/iam/clients/default
246+
allowed_ips:
247+
- 0.0.0.0/0
248+
actions:
249+
- kind: backend
250+
pool: $core.network.lb.$core_lb.backend_pools.$core_lb_core_backend_http:uuid
251+
protocol:
252+
kind: http
253+
modifiers:
254+
- kind: auto_header
255+
headers:
256+
- 'Host'
257+
- 'X-Forwarded-For'
258+
- 'X-Forwarded-Port'
259+
- 'X-Forwarded-Proto'
260+
- 'X-Forwarded-Prefix'
261+
- kind: set_header
262+
name: X-Client-Id
263+
value: $core.vs.variables.$iam_default_client_id:value
264+
- kind: set_header
265+
name: X-Client-Secret
266+
value: $core.vs.variables.$iam_default_client_secret:value
267+
- kind: rewrite_url
268+
regex: "^/api/core/v1/iam/clients/default(.*)"
269+
replacement: f"/v1/iam/clients/{$core.vs.variables.$iam_default_client_uuid:value}$1"
206270
core_lb_static_route:
207271
project_id: "12345678-c625-4fee-81d5-f691897b8142"
208272
parent: $core.network.lb.$core_lb.vhosts.$core_lb_core_http:uuid

exordos_core/bootstrap/defaults.py

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,42 @@
3838
USER = "ubuntu"
3939

4040

41+
def set_var(
42+
name: str,
43+
value: tp.Any,
44+
var_uuid: sys_uuid.UUID,
45+
val_uuid: sys_uuid.UUID | None = None,
46+
) -> bool:
47+
if val_uuid is None:
48+
namespace = sys_uuid.UUID("5c8140af-4eca-4871-951e-4c939f94b39e")
49+
val_uuid = sys_uuid.uuid5(namespace, name)
50+
51+
existing_value = vs_models.Value.objects.get_one_or_none(
52+
filters={"uuid": dm_filters.EQ(val_uuid)}
53+
)
54+
if existing_value:
55+
LOG.info("The value for the '%s' variable already exists", name)
56+
return True
57+
58+
LOG.info("Set %s variable", name)
59+
var = vs_models.Variable.objects.get_one_or_none(
60+
filters={"uuid": dm_filters.EQ(var_uuid)}
61+
)
62+
63+
# The variable hasn't been created, skip
64+
if not var:
65+
return False
66+
67+
val = vs_models.Value(
68+
uuid=val_uuid,
69+
variable=var,
70+
value=value,
71+
project_id=c.EM_HIDDEN_PROJECT_ID,
72+
)
73+
val.insert()
74+
return True
75+
76+
4177
def add_core_set(
4278
spec: dict[str, tp.Any], set_active: bool = False
4379
) -> "node_set_models.NodeSet":
@@ -208,7 +244,9 @@ def set_core_ip_var(value: tp.Any) -> bool:
208244
return True
209245

210246

211-
def init_secrets(spec: dict[str, tp.Any], global_salt, client_secret) -> None:
247+
def init_secrets(
248+
spec: dict[str, tp.Any], global_salt: str, client_id: str, client_secret: str
249+
) -> None:
212250
"""Idempotent secrets initialization."""
213251
# Check if the secrets are already initialized
214252
default_client = iam_models.IamClient.objects.get_one_or_none(
@@ -237,6 +275,7 @@ def init_secrets(spec: dict[str, tp.Any], global_salt, client_secret) -> None:
237275
)
238276
default_client.salt = admin_salt
239277
default_client.secret_hash = client_secret_hash
278+
default_client.client_id = client_id
240279
default_client.save()
241280

242281
# Regenerate secrets for the default IAM user
@@ -594,3 +633,43 @@ def set_hs256_jwks_encryption_key_var(hs256_jwks_encryption_key: str) -> bool:
594633
)
595634
hs256_val.insert()
596635
return True
636+
637+
638+
def set_core_root_disk_size_var(spec: dict) -> bool:
639+
return set_var(
640+
"core_root_disk_size",
641+
spec["stand"]["bootstraps"][0]["disks"][0]["size"],
642+
c.VAR_ROOT_DISK_UUID,
643+
)
644+
645+
646+
def set_core_data_disk_size_var(spec: dict) -> bool:
647+
return set_var(
648+
"core_data_disk_size",
649+
spec["stand"]["bootstraps"][0]["disks"][1]["size"],
650+
c.VAR_DATA_DISK_UUID,
651+
)
652+
653+
654+
def set_iam_default_client_uuid_var(spec: dict) -> bool:
655+
return set_var(
656+
"iam_default_client_uuid",
657+
spec["iam"]["default_client_uuid"],
658+
c.VAR_IAM_DEFAULT_CLIENT_UUID,
659+
)
660+
661+
662+
def set_iam_default_client_id_var(spec: dict) -> bool:
663+
return set_var(
664+
"iam_default_client_id",
665+
spec["iam"]["default_client_id"],
666+
c.VAR_IAM_DEFAULT_CLIENT_ID_UUID,
667+
)
668+
669+
670+
def set_iam_default_client_secret_var(spec: dict) -> bool:
671+
return set_var(
672+
"iam_default_client_secret",
673+
spec["iam"]["default_client_secret"],
674+
c.VAR_IAM_DEFAULT_CLIENT_SECRET_UUID,
675+
)

exordos_core/cmd/bootstrap.py

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import typing as tp
2727
import uuid as sys_uuid
2828

29+
from gcl_sdk.clients.http import base as http_base
2930
from oslo_config import cfg
3031
from restalchemy.common import config_opts as ra_config_opts
3132
from restalchemy.dm import filters as dm_filters
@@ -45,6 +46,7 @@
4546
GCTL_CFG_DIR = f"/home/{USER}/.exordos"
4647
SPEC_PATH = "/mnt/cdrom/spec.json"
4748
MANIFEST_PATH = "/mnt/cdrom/core.yaml"
49+
MANIFEST_COLLECTION = "/v1/em/manifests/"
4850
ECOSYSTEM_REALM_MANIFEST_PATH = "/mnt/cdrom/ecosystem_realm.yaml"
4951
MAIN_SUBNET_UUID = sys_uuid.UUID("c910a7e1-61ae-4d56-bdd6-a59faa3cbda3")
5052

@@ -67,7 +69,7 @@
6769
),
6870
cfg.StrOpt(
6971
"core_endpoint",
70-
default="http://localhost:11010",
72+
default="http://localhost/api/core",
7173
help="Core endpoint",
7274
),
7375
cfg.StrOpt(
@@ -83,11 +85,6 @@
8385
default=None,
8486
help="Global salt for IAM",
8587
),
86-
cfg.StrOpt(
87-
"client_secret",
88-
default="GenesisCoreSecret",
89-
help="Client secret for IAM",
90-
),
9188
cfg.StrOpt(
9289
"hs256_jwks_encryption_key",
9390
default=c.DEFAULT_HS256_JWKS_ENCRYPTION_KEY,
@@ -227,7 +224,7 @@ def _apply_startup_db(spec: dict[str, tp.Any]) -> None:
227224
LOG.info("Machine pool %s already exists, skipping", pool.uuid)
228225

229226

230-
def _ensure_gctl_config(spec: dict[str, tp.Any]):
227+
def _ensure_exordos_config(spec: dict[str, tp.Any]):
231228
"""Ensure gctl configuration file exists."""
232229
if "admin_password" not in spec:
233230
raise RuntimeError("No admin password found in spec")
@@ -269,6 +266,7 @@ def _ensure_gctl_config(spec: dict[str, tp.Any]):
269266
def _install_element_manifest(
270267
element_name: str,
271268
manifest_path: str,
269+
spec: dict[str, tp.Any],
272270
):
273271
"""Idempotent element manifest installation."""
274272
element = em_models.Element.objects.get_one_or_none(
@@ -283,10 +281,34 @@ def _install_element_manifest(
283281
LOG.info("No manifest file found at %s", manifest_path)
284282
return
285283

286-
os.system(
287-
f"exordos --config {GCTL_CFG_DIR}/exordosctl.yaml ee install {manifest_path}"
284+
with open(manifest_path) as f:
285+
manifest_data = yaml.safe_load(f)
286+
287+
auth = http_base.CoreIamAuthenticator(
288+
base_url="http://localhost:11010",
289+
username=CONF.core_user,
290+
password=spec["admin_password"],
291+
client_id=spec["iam"]["default_client_id"],
292+
client_secret=spec["iam"]["default_client_secret"],
293+
client_uuid=sys_uuid.UUID(spec["iam"]["default_client_uuid"]),
294+
)
295+
296+
client = http_base.CollectionBaseClient(
297+
base_url="http://localhost:11010", auth=auth
288298
)
289299

300+
manifest_data = client.create(MANIFEST_COLLECTION, manifest_data)
301+
try:
302+
client.do_action(
303+
MANIFEST_COLLECTION, "install", manifest_data["uuid"], invoke=True
304+
)
305+
except Exception:
306+
LOG.exception(
307+
"Failed to install manifest %s, deleting...", manifest_data["uuid"]
308+
)
309+
client.delete(MANIFEST_COLLECTION, manifest_data["uuid"])
310+
raise
311+
290312

291313
def _set_defaults_vs(spec: dict[str, tp.Any]):
292314
"""Set default values, profiles, etc."""
@@ -297,6 +319,8 @@ def _set_defaults_vs(spec: dict[str, tp.Any]):
297319
"func": bootstrap_defaults.set_core_ip_var,
298320
"args": [spec["stand"]["bootstraps"][0]["ports"][0]["ip"]],
299321
},
322+
{"func": bootstrap_defaults.set_core_root_disk_size_var, "args": [spec]},
323+
{"func": bootstrap_defaults.set_core_data_disk_size_var, "args": [spec]},
300324
{"func": bootstrap_defaults.set_ecosystem_endpoint_var, "args": [spec]},
301325
{"func": bootstrap_defaults.set_disable_telemetry_var, "args": [spec]},
302326
{"func": bootstrap_defaults.set_realm_uuid_var, "args": [spec]},
@@ -307,6 +331,9 @@ def _set_defaults_vs(spec: dict[str, tp.Any]):
307331
"func": bootstrap_defaults.set_hs256_jwks_encryption_key_var,
308332
"args": [CONF["iam"].hs256_jwks_encryption_key],
309333
},
334+
{"func": bootstrap_defaults.set_iam_default_client_uuid_var, "args": [spec]},
335+
{"func": bootstrap_defaults.set_iam_default_client_id_var, "args": [spec]},
336+
{"func": bootstrap_defaults.set_iam_default_client_secret_var, "args": [spec]},
310337
]
311338

312339
# Perform all tasks to set default values until timeout
@@ -354,13 +381,16 @@ def main() -> None:
354381
LOG.info("GC Bootstrap script")
355382
bootstrap_defaults.apply_startup_db(spec)
356383
bootstrap_defaults.init_secrets(
357-
spec, CONF["iam"].global_salt, CONF["iam"].client_secret
384+
spec,
385+
CONF["iam"].global_salt,
386+
spec["iam"]["default_client_id"],
387+
spec["iam"]["default_client_secret"],
358388
)
359389
bootstrap_defaults.add_core_set(spec)
360-
_ensure_gctl_config(spec)
361-
_install_element_manifest("core", CONF.manifest_path)
390+
_ensure_exordos_config(spec)
391+
_install_element_manifest("core", CONF.manifest_path, spec)
362392
_install_element_manifest(
363-
"ecosystem_realm", CONF.ecosystem_realm_manifest_path
393+
"ecosystem_realm", CONF.ecosystem_realm_manifest_path, spec
364394
)
365395
_set_defaults_vs(spec)
366396
return

exordos_core/common/constants.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@
2424
CORE_SET_UUID = sys_uuid.UUID("70c88222-b4d9-46c3-9340-aa5bfaaa4b94")
2525
MAIN_SUBNET_UUID = sys_uuid.UUID("c910a7e1-61ae-4d56-bdd6-a59faa3cbda3")
2626
VAR_CORE_IP_ADDRESS_UUID = sys_uuid.UUID("55814431-ede5-4c4e-abd6-e61600a3069b")
27+
VAR_ROOT_DISK_UUID = sys_uuid.UUID("695f4e94-e46b-43ae-aa66-194044740912")
28+
VAR_DATA_DISK_UUID = sys_uuid.UUID("cf92f6f5-b62f-4cc4-898c-5250a6608d51")
2729
VALUE_CORE_IP_ADDRESS_UUID = sys_uuid.UUID("0225c5ed-07db-45fe-8154-2b8b9cae388a")
30+
VAR_IAM_DEFAULT_CLIENT_UUID = sys_uuid.UUID("d23fa962-18b8-444f-81a0-027ece98fbdb")
31+
VAR_IAM_DEFAULT_CLIENT_ID_UUID = sys_uuid.UUID("239e2a55-c3ad-4adc-85a8-3fa90b669556")
32+
VAR_IAM_DEFAULT_CLIENT_SECRET_UUID = sys_uuid.UUID(
33+
"784c1f6d-f9e2-47e0-a3ba-16725854ac09"
34+
)
2835
NETWORK_UUID = "1d4f64db-817a-4862-a588-c9e950823cc1"
2936
DEFAULT_DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S.%f"
3037
DEFAULT_SQL_LIMIT = 100

exordos_core/compute/agents/universal/drivers/pool.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# under the License.
1616

1717
import logging
18+
import os
1819
import typing as tp
1920
import uuid as sys_uuid
2021

@@ -32,6 +33,7 @@
3233
from exordos_core.compute.pool.drivers import exceptions as driver_exc
3334

3435
LOG = logging.getLogger(__name__)
36+
DRY_RUN_ENV = "EXO_AGENTS_DRY_RUN"
3537

3638

3739
class RootVolumeNotFound(ua_driver_exc.AgentDriverException):
@@ -90,7 +92,14 @@ def load_driver(self) -> driver_base.AbstractPoolDriver:
9092
driver_kind = self.driver_spec["driver"]
9193

9294
class_ = utils.load_from_entry_point(nc.EP_MACHINE_POOL_DRIVERS, driver_kind)
93-
driver = class_(self)
95+
96+
# NOTE(akremenetsky): We should use command approach for dry_run in agents,
97+
# but it hasn't implemented yet so use environment variable.
98+
# https://github.com/exordos/gcl_sdk/issues/124
99+
# Check for dry run mode based on environment variable
100+
dry_run = str(os.getenv(DRY_RUN_ENV)).lower() in {"1", "true", "yes"}
101+
102+
driver = class_(self, dry_run=dry_run)
94103
self.__driver_map__[driver_key] = driver
95104
return driver
96105

0 commit comments

Comments
 (0)