3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
18 from ironic.common.i18n import _
20 from ironic_virtmedia_driver.vendors.ironic_virtmedia_hw import IronicVirtMediaHW
21 from ironic_virtmedia_driver import virtmedia_exception
23 import redfish.ris.tpdefs
24 from redfish import AuthMethod, redfish_client
25 from redfish.rest.v1 import ServerDownOrUnreachableError
27 class HP(IronicVirtMediaHW):
28 def __init__(self, log):
29 super(HP, self).__init__(log)
30 self.remote_share = '/bootimages/'
33 def _init_connection(self, driver_info):
34 """Get connection info and init rest_object"""
35 host = 'https://' + driver_info['address']
36 user = driver_info['username']
37 password = driver_info['password']
40 redfishclient = redfish_client(base_url=host, \
41 username=user, password=password, \
42 default_prefix="/redfish/v1")
43 redfishclient.login(auth=AuthMethod.SESSION)
44 self._init_typepath(redfishclient)
45 except ServerDownOrUnreachableError as error:
46 operation = _("iLO not responding")
47 raise virtmedia_exception.VirtmediaOperationError(
48 operation=operation, error=error)
49 except Exception as error:
50 operation = _("Failed to login to iLO")
51 raise virtmedia_exception.VirtmediaOperationError(
52 operation=operation, error=error)
55 def _init_typepath(self, connection):
56 typepath = redfish.ris.tpdefs.Typesandpathdefines()
57 typepath.getgen(url=connection.get_base_url())
58 typepath.defs.redfishchange()
59 self.typepath = typepath
61 def _search_for_type(self, typename, resources):
63 nosettings = [item for item in resources["resources"] if "/settings/" not in item["@odata.id"]]
64 for item in nosettings:
65 if "@odata.type" in item and \
66 typename.lower() in item["@odata.type"].lower():
67 instances.append(item)
70 def _get_instances(self, connection):
73 response = connection.get("/redfish/v1/resourcedirectory/")
74 if response.status == 200:
75 resources["resources"] = response.dict["Instances"]
79 return self._search_for_type("Manager.", resources)
81 def _get_error(self, response):
82 message = json.loads(response.text)
83 error = message["error"]["@Message.ExtendedInfo"][0]["MessageId"].split(".")
87 def _umount_virtual_cd(self, connection, cd_location):
88 unmount_path = cd_location
89 unmount_body = {"Action": "EjectVirtualMedia", "Target": self.typepath.defs.oempath}
90 resp = connection.post(path=unmount_path, body=unmount_body)
91 if resp.status != 200:
92 self.log.error("Unmounting cd failed: %r, cd location: %r", resp, unmount_path)
93 operation = _("Failed to unmount image")
94 error = self._get_error(resp)
95 raise virtmedia_exception.VirtmediaOperationError(
96 operation=operation, error=error)
99 def _get_virtual_media_devices(self, connection, instance):
100 rsp = connection.get(instance["@odata.id"])
101 rsp = connection.get(rsp.dict["VirtualMedia"]["@odata.id"])
102 return rsp.dict['Members']
104 def _mount_virtual_cd(self, connection, image_location):
105 instances = self._get_instances(connection)
106 for instance in instances:
107 for vmlink in self._get_virtual_media_devices(connection, instance):
108 response = connection.get(vmlink["@odata.id"])
110 if response.status == 200 and "DVD" in response.dict["MediaTypes"]:
111 if response.dict['Inserted']:
112 self._umount_virtual_cd(connection, vmlink["@odata.id"])
114 body = {"Image": image_location}
117 body["Oem"] = {self.typepath.defs.oemhp: {"BootOnNextServerReset": \
120 response = connection.patch(path=vmlink["@odata.id"], body=body)
121 elif response.status != 200:
122 self.log.error("Failed to mount image")
123 error = self._get_error(response)
124 operation = _("Failed to mount image")
125 raise virtmedia_exception.VirtmediaOperationError(
126 operation=operation, error=error)
128 def attach_virtual_cd(self, image_filename, driver_info, task):
129 connection = self._init_connection(driver_info)
130 image_location = 'http://' + driver_info['provisioning_server'] + ':' + driver_info['provisioning_server_http_port'] + self.remote_share + image_filename
131 self._mount_virtual_cd(connection, image_location)
135 def detach_virtual_cd(self, driver_info, task):
136 connection = self._init_connection(driver_info)
137 instances = self._get_instances(connection)
138 for instance in instances:
139 for vmlink in self._get_virtual_media_devices(connection, instance):
140 response = connection.get(vmlink["@odata.id"])
141 if response.status == 200 and "DVD" in response.dict["MediaTypes"]:
142 if response.dict['Inserted']:
143 self._umount_virtual_cd(connection, vmlink["@odata.id"])
147 def set_boot_device(self, task):
148 """ This is done during the mounting"""