@@ -44,36 +44,48 @@ def parse_json(self):
44
44
45
45
extension = json_data .get ("externaldetails" , {}).get ("extension" , {})
46
46
host = json_data .get ("externaldetails" , {}).get ("host" , {})
47
+ vm = json_data .get ("externaldetails" , {}).get ("virtualmachine" , {})
47
48
48
49
endpoint = host .get ("endpoint" ) or extension .get ("endpoint" )
49
50
apikey = host .get ("apikey" ) or extension .get ("apikey" )
50
51
distro_series = (
51
52
json_data .get ("cloudstack.vm.details" , {})
52
53
.get ("details" , {})
53
- .get ("distro_series" , "ubuntu" )
54
+ .get ("distro_series" , None )
54
55
)
55
56
56
57
if not endpoint or not apikey :
57
58
fail ("Missing MAAS endpoint or apikey" )
58
59
59
- # normalize endpoint
60
60
if not endpoint .startswith ("http://" ) and not endpoint .startswith ("https://" ):
61
61
endpoint = "http://" + endpoint
62
62
endpoint = endpoint .rstrip ("/" )
63
63
64
- # split api key
65
64
parts = apikey .split (":" )
66
65
if len (parts ) != 3 :
67
66
fail ("Invalid apikey format. Expected consumer:token:secret" )
68
67
69
68
consumer , token , secret = parts
69
+
70
+ system_id = (
71
+ json_data .get ("cloudstack.vm.details" , {})
72
+ .get ("details" , {})
73
+ .get ("maas_system_id" )
74
+ or vm .get ("maas_system_id" , "" )
75
+ )
76
+
77
+ vm_name = vm .get ("vm_name" ) or json_data .get ("cloudstack.vm.details" , {}).get ("name" )
78
+ if not vm_name :
79
+ vm_name = f"cs-{ system_id } " if system_id else "cs-unknown"
80
+
70
81
return {
71
82
"endpoint" : endpoint ,
72
83
"consumer" : consumer ,
73
84
"token" : token ,
74
85
"secret" : secret ,
75
- "distro_series" : distro_series ,
76
- "system_id" : json_data .get ("cloudstack.vm.details" , {}).get ("details" , {}).get ("maas_system_id" , "" ),
86
+ "distro_series" : distro_series or "ubuntu/focal" ,
87
+ "system_id" : system_id ,
88
+ "vm_name" : vm_name ,
77
89
}
78
90
except Exception as e :
79
91
fail (f"Error parsing JSON: { str (e )} " )
@@ -103,9 +115,19 @@ def prepare(self):
103
115
if not ready :
104
116
fail ("No Ready machines available" )
105
117
106
- system = ready [0 ]
118
+ sysid = self .data .get ("system_id" )
119
+
120
+ if sysid :
121
+ match = next ((m for m in ready if m ["system_id" ] == sysid ), None )
122
+ if not match :
123
+ fail (f"Provided system_id '{ sysid } ' not found among Ready machines" )
124
+ system = match
125
+ else :
126
+ system = ready [0 ]
127
+
107
128
system_id = system ["system_id" ]
108
129
mac = system .get ("interface_set" , [{}])[0 ].get ("mac_address" )
130
+ hostname = system .get ("hostname" , "" )
109
131
110
132
if not mac :
111
133
fail ("No MAC address found" )
@@ -119,18 +141,38 @@ def prepare(self):
119
141
120
142
result = {
121
143
"nics" : json_data ["cloudstack.vm.details" ]["nics" ],
122
- "details" : {"External:mac_address" : mac , "maas_system_id" : system_id },
144
+ "details" : {
145
+ "External:mac_address" : mac ,
146
+ "External:maas_system_id" : system_id ,
147
+ "External:hostname" : hostname ,
148
+ },
123
149
}
124
150
succeed (result )
125
151
126
152
def create (self ):
127
153
sysid = self .data .get ("system_id" )
128
154
if not sysid :
129
155
fail ("system_id missing for create" )
156
+
157
+ ds = self .data .get ("distro_series" , "ubuntu/focal" )
158
+ vm_name = self .data .get ("vm_name" )
159
+
160
+ # Cloud-init userdata to disable netplan, flush IPs on ens35, and run dhclient
161
+ userdata = """#cloud-config
162
+ network:
163
+ config: disabled
164
+ runcmd:
165
+ - [ sh, -c, "dhclient -v -4 ens35 || true" ]
166
+ """
167
+
130
168
self .call_maas (
131
169
"POST" ,
132
170
f"/machines/{ sysid } /" ,
133
- {"op" : "deploy" , "distro_series" : self .data ["distro_series" ]},
171
+ {
172
+ "op" : "deploy" ,
173
+ "distro_series" : ds ,
174
+ "userdata" : userdata ,
175
+ },
134
176
)
135
177
succeed ({"status" : "success" , "message" : f"Instance created with { self .data ['distro_series' ]} " })
136
178
0 commit comments