Merge "Experimental JOID Support"
[pharos-tools.git] / laas-fog / pharoslaas / actions / fogAction.py
1 ##############################################################################
2 # Copyright 2017 Parker Berberian and Others                                 #
3 #                                                                            #
4 # Licensed under the Apache License, Version 2.0 (the "License");            #
5 # you may not use this file except in compliance with the License.           #
6 # You may obtain a copy of the License at                                    #
7 #                                                                            #
8 #    http://www.apache.org/licenses/LICENSE-2.0                              #
9 #                                                                            #
10 # Unless required by applicable law or agreed to in writing, software        #
11 # distributed under the License is distributed on an "AS IS" BASIS,          #
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
13 # See the License for the specific language governing permissions and        #
14 # limitations under the License.                                             #
15 ##############################################################################
16
17 import requests
18 import sys
19 import json
20 import time
21 from st2actions.runners.pythonrunner import Action
22
23
24 class FogAction(Action):
25     """
26     This class talks with the REST web api for the FOG server.
27     """
28     def __init__(self, config=None):
29         self.baseURL = config['fog']['address']
30         self.fogKey = config['fog']['api_key']
31         self.userKey = config['fog']['user_key']
32         self.updateHeader()
33
34     def updateHeader(self):
35         """
36         recreates the http header used to talk to the fog api
37         """
38         self.header = {}
39         self.header['fog-api-token'] = self.fogKey
40         self.header['fog-user-token'] = self.userKey
41
42     def getImageID(self, img=None, os=None, host=None):
43         """
44         returns the numerical id associated with the given img name or
45         operating system. If both are given, the img gets priority.
46         if img is a number, it is assumed to be a valid id
47         """
48         # st2 will promote an empty arg to the str "None" :(
49         if not img or img == "None":
50             return self.getImageIDFromOS(os, host)
51         try:
52             return int(img)
53         except:
54             url = self.baseURL+"image"
55             images = requests.get(url=url, headers=self.header)
56             images = images.json()['images']
57             for image in images:
58                 if img == image['name']:
59                     return image['id']
60         return -1
61
62     def getImageIDFromOS(self, os, host):
63         enum = {"ubuntu": "ubuntu_image",
64                 "centos": "centos_image",
65                 "suse": "suse_image"
66                 }
67         os = os.lower()
68         if os not in enum.keys():
69             return -1
70         host_dict = json.loads(
71                 self.action_service.get_value(name=host, local=False)
72                 )
73         return int(host_dict[enum[os]])
74
75     def delTask(self, hostNum):
76         """
77         Tries to delete an existing task for the host
78         with hostNum as a host number
79         """
80         try:
81             url = self.baseURL+'fog/host/'+str(hostNum)+'/cancel'
82             req = requests.delete(url, headers=self.header)
83             if req.status_code == 200:
84                 self.logger.info("%s", "successfully deleted image task")
85         except Exception:
86             self.logger.exception("Failed to delete the imaging task!")
87
88     def getHostNumber(self, hostname):
89         """
90         returns the host number of given host
91         """
92         try:
93             req = requests.get(self.baseURL+"host", headers=self.header)
94             hostData = req.json()
95             if hostData is not None:
96                 for hostDict in hostData['hosts']:
97                     if hostname == hostDict['name']:
98                         return hostDict['id']
99             return -1
100         except Exception:
101             self.logger.exception('%s', "Failed to connect to the FOG server")
102
103     def request(self, url, data=None, method="get"):
104         if data is not None:
105             return self.dataRequest(url, data, method=method)
106         try:
107             response = requests.get(url, headers=self.header)
108             return response.json()
109         except Exception:
110             self.logger.exception("Failed to reach FOG at %s", url)
111             sys.exit(1)
112
113     def dataRequest(self, url, data, method="post"):
114         methods = {
115                 "post": requests.post,
116                 "put": requests.put
117                 }
118         try:
119             return methods[method](url, json=data, headers=self.header)
120         except Exception:
121             self.logger.exception("Failed to reach FOG at %s", url)
122             sys.exit(1)
123
124     def getFogHost(self, host):
125         hostData = self.action_service.get_value(host, local=False)
126         return json.loads(hostData)['fog_name']
127
128     def waitForTask(self, taskID):
129         """
130         Watches a task and waits for it to finish (disapear).
131         There may be a smarter way to do this and track errors,
132         but st2 will timeout for me if something goes wrong
133         """
134         task = self.getTask(taskID)
135         while(task):
136             time.sleep(15)
137             task = self.getTask(taskID)
138
139     def getAllTasks(self):
140         try:
141             tasks = requests.get(
142                     self.baseURL+'task/current',
143                     headers=self.header
144                     ).json()['tasks']
145             return tasks
146         except Exception:
147             return []
148
149     def getTask(self, taskID):
150         for task in self.getAllTasks():
151             if task['id'] == taskID:
152                 return task
153         return {}