11import json
22import logging
3- import os
43
5- from .http import HttpMixin , use_admin_auth , endpoint
4+ from .http import use_admin_auth , endpoint
65from .exceptions import StackException
76
7+ from .blueprint import BlueprintMixin
8+ from .formula import FormulaMixin
9+ from .profile import ProfileMixin
10+ from .provider import ProviderMixin
11+ from .region import RegionMixin
12+ from .settings import SettingsMixin
13+ from .stack import StackMixin
14+
15+ from .version import _parse_version_string
16+
817logger = logging .getLogger (__name__ )
918
1019
11- class StackdIO (HttpMixin ):
20+ class StackdIO (BlueprintMixin , FormulaMixin , ProfileMixin ,
21+ ProviderMixin , RegionMixin , StackMixin , SettingsMixin ):
1222
13- def __init__ (self ,
14- protocol = "https" ,
15- host = "localhost" ,
16- port = 443 ,
17- base_url = None ,
18- auth = None ,
19- auth_admin = None ,
23+ def __init__ (self , protocol = "https" , host = "localhost" , port = 443 ,
24+ base_url = None , auth = None , auth_admin = None ,
2025 verify = False ):
2126 """auth_admin is optional, only needed for creating provider, profile,
2227 and base security groups"""
@@ -33,106 +38,12 @@ def __init__(self,
3338 self .auth = auth
3439 self .auth_admin = auth_admin
3540
41+ _ , self .version = _parse_version_string (self .get_version ())
3642
37- @use_admin_auth
38- @endpoint ("providers/" )
39- def create_provider (self , ** kwargs ):
40- """Create a provider"""
41-
42- form_data = {
43- "title" : None ,
44- "account_id" : None ,
45- "provider_type" : None ,
46- "access_key_id" : None ,
47- "secret_access_key" : None ,
48- "keypair" : None ,
49- "security_groups" : None ,
50- "route53_domain" : None ,
51- "default_availability_zone" : None ,
52- "private_key" : None
53- }
54-
55- for key in form_data .keys ():
56- form_data [key ] = kwargs .get (key )
57-
58- return self ._post (endpoint , data = json .dumps (form_data ), jsonify = True )
59-
60-
61- @endpoint ("providers/" )
62- def get_provider (self , title , provider_name ):
63- """Look for and return a provider"""
64-
65- result = self ._get (endpoint , jsonify = True )
66- for provider in result ['results' ]:
67- if provider .get ("title" ) == title and \
68- provider .get ("provider_type_name" ) == provider_name :
69-
70- return provider
71-
72- raise StackException ("Provider %s not found" % title )
73-
74-
75- @use_admin_auth
76- @endpoint ("providers/" )
77- def create_profile (self , title , image_id , ssh_user , cloud_provider ,
78- default_instance_size = None ):
79- """Create a profile"""
80- data = {
81- "title" : title ,
82- "image_id" : image_id ,
83- "ssh_user" : ssh_user ,
84- "cloud_provider" : cloud_provider ,
85- "default_instance_size" : default_instance_size
86- }
87- return self ._post (endpoint , data = json .dumps (data ), jsonify = True )
88-
89-
90- @endpoint ("profiles/" )
91- def get_profile (self , title , cloud_provider ):
92- """Look for and return a profile"""
93-
94- result = self ._get (endpoint , jsonify = True )
95-
96- for profile in result ['results' ]:
97- if profile .get ("title" ) == title and \
98- profile .get ("cloud_provider" ) == cloud_provider :
99- return profile
100-
101- return None
102-
103-
104- @endpoint ("formulas/" )
105- def import_formula (self , formula_uri , public = True ):
106- """Import a formula"""
107- data = {
108- "uri" : formula_uri ,
109- "public" : public ,
110- }
111- return self ._post (endpoint , data = json .dumps (data ), jsonify = True )
112-
113-
114- @endpoint ("blueprints/" )
115- def create_blueprint (self , blueprint , provider = "ec2" ):
116- """Create a blueprint"""
117-
118- # check the provided blueprint to see if we need to look up any ids
119- for host in blueprint ["hosts" ]:
120- if isinstance (host ["size" ], str ):
121- host ["size" ] = self .get_instance_id (host ["size" ], provider )
12243
123- if isinstance (host ["zone" ], str ):
124- host ["zone" ] = self .get_zone (host ["zone" ], provider )
125-
126- if isinstance (host ["cloud_profile" ], str ):
127- host ["cloud_profile" ] = self .get_profile_id (host ["cloud_profile" ])
128-
129- for component in host ["formula_components" ]:
130- if isinstance (component ["id" ], (tuple , list )):
131- component ["id" ] = self .get_component_id (
132- self .get_formula (component ["id" ][0 ]),
133- component ["id" ][1 ])
134-
135- return self ._post (endpoint , data = json .dumps (blueprint ), jsonify = True )
44+ @endpoint ("version/" )
45+ def get_version (self ):
46+ return self ._get (endpoint , jsonify = True )['version' ]
13647
13748
13849 @use_admin_auth
@@ -149,149 +60,6 @@ def create_security_group(self, name, description, cloud_provider, is_default=Tr
14960 return self ._post (endpoint , data = json .dumps (data ), jsonify = True )
15061
15162
152- @endpoint ("settings/" )
153- def set_public_key (self , public_key ):
154- """Upload a public key for our user. public_key can be the actual key, a
155- file handle, or a path to a key file"""
156-
157- if isinstance (public_key , file ):
158- public_key = public_key .read ()
159- elif isinstance (public_key , str ) and os .path .exists (public_key ):
160- public_key = open (public_key , "r" ).read ()
161-
162- data = {
163- "public_key" : public_key
164- }
165- return self ._put (endpoint , data = json .dumps (data ), jsonify = True )
166-
167-
168- @endpoint ("formulas/" )
169- def get_formulas (self ):
170- """Return all formulas"""
171- return self ._get (endpoint , jsonify = True )['results' ]
172-
173-
174- def get_formula (self , title ):
175- """Get a formula that matches title"""
176-
177- for formula in self .get_formulas ():
178- if formula .get ("title" ) == title :
179- return formula
180-
181- raise StackException ("Formula %s not found" % title )
182-
183-
184- def get_formula_id (self , title ):
185- """Get the id for a formula that matches title. If component_title is
186- provided, find and return the component id"""
187-
188- formula = self .get_formula (title )
189- return formula .get ("id" )
190-
191-
192- def get_component_id (self , formula , component_title ):
193- """Get the id for a component from formula_id that matches title"""
194-
195- for component in formula .get ("components" ):
196- if component .get ("title" ) == component_title :
197- return component .get ("id" )
198-
199- raise StackException ("Component %s not found for formula %s" %
200- (component_title , formula .get ("title" )))
201-
202-
203- @endpoint ("providers/" )
204- def get_provider_id (self , slug , title = False ):
205- """Get the id for a provider that matches slug. If title is True will
206- look at title instead."""
207-
208- result = self ._get (endpoint , jsonify = True )
209-
210- for provider in result ['results' ]:
211- if provider .get ("slug" if not title else "title" ) == slug :
212- return provider .get ("id" )
213-
214- raise StackException ("Provider %s not found" % slug )
215-
216-
217- @endpoint ("profiles/" )
218- def get_profile_id (self , slug , title = False ):
219- """Get the id for a profile that matches slug. If title is True will look
220- at title instead."""
221-
222- result = self ._get (endpoint , jsonify = True )
223-
224- for profile in result ['results' ]:
225- if profile .get ("slug" if not title else "title" ) == slug :
226- return profile .get ("id" )
227-
228- return StackException ("Provider %s not found" % slug )
229-
230-
231- @endpoint ("stacks/" )
232- def get_stacks (self ):
233- """Return a list of all stacks"""
234- return self ._get (endpoint , jsonify = True )['results' ]
235-
236-
237- @endpoint ("stacks/{stack_id}/" )
238- def get_stack (self , stack_id ):
239- """Get stack info"""
240- result = self ._get (endpoint , none_on_404 = True , jsonify = True )
241- if result is None :
242- raise StackException ("Stack %s not found" % stack_id )
243- else :
244- return result
245-
246-
247- @endpoint ("stacks/{stack_id}/history/" )
248- def get_stack_history (self , stack_id ):
249- """Get stack info"""
250- result = self ._get (endpoint , none_on_404 = True , jsonify = True )
251- if result is None :
252- raise StackException ("Stack %s not found" % stack_id )
253- else :
254- return result
255-
256-
257- @endpoint ("stacks/" )
258- def get_stack_id (self , title ):
259- """Find a stack id"""
260-
261- result = self ._get (endpoint , jsonify = True )
262- try :
263- for stack in result ['results' ]:
264- if stack .get ("title" ) == title :
265- return stack .get ("id" )
266- except TypeError , e :
267- logger .error ("Error querying stacks: %s" , e )
268-
269- raise StackException ("Stack %s not found" % title )
270-
271-
272- @endpoint ("stacks/{stack_id}/hosts/" )
273- def get_stack_hosts (self , stack_id ):
274- """Get a list of all stack hosts"""
275- return self ._get (endpoint , jsonify = True )['results' ]
276-
277-
278- @endpoint ("blueprints/{blueprint_id}/" )
279- def get_blueprint (self , blueprint_id ):
280- """Return info for a specific blueprint_id"""
281- return self ._get (endpoint , jsonify = True )
282-
283-
284- @endpoint ("blueprints/" )
285- def get_blueprint_id (self , title ):
286- """Get the id for a blueprint that matches title"""
287- result = self ._get (endpoint , params = {"title" : title }, jsonify = True )
288-
289- if not result .get ('count' ) == 1 :
290- raise StackException ("Blueprint %s not found" % title )
291-
292- return result ['results' ][0 ]['id' ]
293-
294-
29563 @endpoint ("instance_sizes/" )
29664 def get_instance_id (self , instance_id , provider_type = "ec2" ):
29765 """Get the id for an instance_id. The instance_id parameter is the
@@ -306,88 +74,3 @@ def get_instance_id(self, instance_id, provider_type="ec2"):
30674
30775 raise StackException ("Instance type %s from provider %s not found" %
30876 (instance_id , provider_type ))
309-
310-
311- @endpoint ("provider_types/" )
312- def get_provider_type (self , type_name ):
313- """Get the id for the provider specified by type_name"""
314-
315- result = self ._get (endpoint , jsonify = True )
316- for provider_type in result ['results' ]:
317- if provider_type .get ("type_name" ) == type_name :
318- return provider_type .get ("id" )
319-
320- raise StackException ("Provider type %s not found" % type_name )
321-
322-
323- @endpoint ("zones/" )
324- def get_zone (self , title , type_name = "ec2" ):
325- """Get a zone id for title"""
326-
327- provider_type = self .get_provider_type (type_name )
328- result = self ._get (endpoint , jsonify = True )
329- for zone in result ['results' ]:
330- if zone .get ("title" ) == title and \
331- zone .get ("provider_type" ) == provider_type :
332- return zone .get ("id" )
333-
334- raise StackException ("Zone %s not found for %s" % (title , type_name ))
335-
336-
337- @endpoint ("stacks/" )
338- def launch_stack (self , stack_data ):
339- """Launch a stack as described by stack_data"""
340- return self ._post (endpoint , data = json .dumps (stack_data ), jsonify = True )
341-
342-
343- @endpoint ("stacks/{stack_id}/hosts/" )
344- def describe_hosts (self , stack_id , key = "fqdn" , ec2 = False ):
345- """Retrieve a list of info about a stack. Defaults to the id for each
346- host, but you can specify any available key. Setting ec2=True will
347- force it to inspect the ec2_metadata field."""
348-
349- EC2 = "ec2_metadata"
350- result = self ._get (endpoint , jsonify = True )
351-
352- stack_details = []
353-
354- for host in result ['results' ]:
355- if not ec2 :
356- host_details = host .get (key )
357- else :
358- host_details = host .get (EC2 ).get (key )
359-
360- if host_details :
361- stack_details .append (host_details )
362-
363- if stack_details :
364- return stack_details
365-
366- raise StackException ("Key %s for stack %s not available" % (key , stack_id ))
367-
368-
369- @endpoint ("stacks/{stack_id}/" )
370- def delete_stack (self , stack_id ):
371- """Destructively delete a stack forever."""
372- # make sure the stack exists
373- self .get_stack (stack_id )
374- return self ._delete (endpoint , jsonify = True )
375-
376-
377- @endpoint ("stacks/{stack_id}/action/" )
378- def get_valid_actions (self , stack_id ):
379- return self ._get (endpoint , jsonify = True )['available_actions' ]
380-
381-
382- @endpoint ("stacks/{stack_id}/action/" )
383- def do_action (self , stack_id , action ):
384- """Execute an action on a stack"""
385- valid_actions = self .get_valid_actions (stack_id )
386-
387- if action not in valid_actions :
388- raise StackException ("Invalid action, must be one of %s" %
389- ", " .join (valid_actions ))
390-
391- data = {"action" : action }
392-
393- return self ._post (endpoint , data = json .dumps (data ), jsonify = True )
0 commit comments