Skip to content

Commit

Permalink
Merge pull request #126 from grafuls/development
Browse files Browse the repository at this point in the history
feat: added VirtualMedia check and unmount
  • Loading branch information
sadsfae committed Sep 9, 2020
2 parents bc34f4d + a60c9a6 commit 5b1c1af
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 1 deletion.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
* [Firmware inventory](#firmware-inventory)
* [Clear Job Queue](#clear-job-queue)
* [List Job Queue](#list-job-queue)
* [Check Virtual Media](#check-virtual-media)
* [Unmount Virtual Media](#unmount-virtual-media)
* [Bulk actions via text file with list of hosts](#bulk-actions-via-text-file-with-list-of-hosts)
* [Verbose Output](#verbose-output)
* [Log to File](#log-to-file)
Expand Down Expand Up @@ -239,6 +241,20 @@ If you would like to list all active jobs that are queued on the remote iDRAC yo
./src/badfish/badfish.py -H mgmt-your-server.example.com -u root -p yourpass --ls-jobs
```

### Check Virtual Media
If you would like to check for any active virtual media you can run ```badfish``` with the ```--check-virtual-media``` option which query for all active virtual devices.
```
./src/badfish/badfish.py -H mgmt-your-server.example.com -u root -p yourpass --check-virtual-media
```

### Unmount Virtual Media
If you would like to unmount all active virtual media you can run ```badfish``` with the ```--unmount-virtual-media``` option which post a request for unmounting all active virtual devices.
```
./src/badfish/badfish.py -H mgmt-your-server.example.com -u root -p yourpass --unmount-virtual-media
```
NOTE:
* This functionality is only available for SuperMicro devices.

### Bulk actions via text file with list of hosts
In the case you would like to execute a common badfish action on a list of hosts, you can pass the optional argument ```--host-list``` in place of ```-H``` with the path to a text file with the hosts you would like to action upon and any addtional arguments defining a common action for all these hosts.
```
Expand Down
138 changes: 137 additions & 1 deletion src/badfish/badfish.py
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,41 @@ async def check_supported_idrac_version(self):

return True

async def get_virtual_media_config_uri(self):
_url = "%s%s" % (self.host_uri, self.manager_resource)
_response = await self.get_request(_url)

try:
raw = await _response.text("utf-8", "ignore")
data = json.loads(raw.strip())
except ValueError:
self.logger.error("Not able to access Firmware inventory.")
raise BadfishException

vm_endpoint = data.get("VirtualMedia")
if vm_endpoint:
virtual_media = vm_endpoint.get('@odata.id')
if virtual_media:
vm_url = "%s%s" % (self.host_uri, virtual_media)
vm_response = await self.get_request(vm_url)
try:
raw = await vm_response.text("utf-8", "ignore")
vm_data = json.loads(raw.strip())

oem = vm_data.get("Oem")
if oem:
sm = oem.get("Supermicro")
if sm:
vmc = sm.get("VirtualMediaConfig")
if vmc:
return vmc.get("@odata.id")

except ValueError:
self.logger.error("Not able to check for supported virtual media unmount")
raise BadfishException

return None

async def delete_job_queue_dell(self, force):
_url = (
"%s/Dell/Managers/iDRAC.Embedded.1/DellJobService/Actions/DellJobService.DeleteJobQueue"
Expand Down Expand Up @@ -1083,6 +1118,91 @@ def get_host_type_boot_device(self, host_type, _interfaces_path):
]
return None

async def get_virtual_media(self):
_url = "%s%s" % (self.host_uri, self.manager_resource)
_response = await self.get_request(_url)

try:
raw = await _response.text("utf-8", "ignore")
data = json.loads(raw.strip())
except ValueError:
self.logger.error("Not able to access Firmware inventory.")
raise BadfishException

vm_endpoint = data.get("VirtualMedia")
vms = []
if vm_endpoint:
virtual_media = vm_endpoint.get('@odata.id')
if virtual_media:
vm_url = "%s%s" % (self.host_uri, virtual_media)
vm_response = await self.get_request(vm_url)
try:
raw = await vm_response.text("utf-8", "ignore")
vm_data = json.loads(raw.strip())

if vm_data.get("Members"):
for member in vm_data["Members"]:
vms.append(member["@odata.id"])
else:
self.logger.warning("No active VirtualMedia found")
return vms

except ValueError:
self.logger.error("Not able to access Firmware inventory.")
raise BadfishException
else:
self.logger.error("No VirtualMedia endpoint found")
raise BadfishException
else:
self.logger.error("No VirtualMedia endpoint found")
raise BadfishException

return vms

async def check_virtual_media(self):
vms = await self.get_virtual_media()
for vm in vms:
disc_url = "%s%s" % (self.host_uri, vm)
disc_response = await self.get_request(disc_url)
try:
raw = await disc_response.text("utf-8", "ignore")
disc_data = json.loads(raw.strip())
_id = disc_data.get("Id")
name = disc_data.get("Name")
image_name = disc_data.get("ImageName")
inserted = disc_data.get("Inserted")
self.logger.info(f"ID: {_id} - Name: {name} - ImageName: {image_name} - Inserted: {inserted}")
except ValueError:
self.logger.error("There was something wrong getting values for VirtualMedia")
raise BadfishException

return True

async def unmount_virtual_media(self):

vmc = await self.get_virtual_media_config_uri()
if not vmc:
self.logger.warning(
"OOB management does not support Virtual Media unmount"
)
return False

_vmc_url = "%s%s/Actions/IsoConfig.UnMount" % (self.host_uri, vmc)
_headers = {"content-type": "application/json"}
_payload = {}
try:
disc_response = await self.post_request(_vmc_url, _payload, _headers)
if disc_response.status == 200:
self.logger.info("Successfully unmounted all VirtualMedia")
else:
self.logger.error("There was something wrong unmounting the VirtualMedia")
raise BadfishException
except ValueError:
self.logger.error("There was something wrong getting values for VirtualMedia")
raise BadfishException

return True


async def execute_badfish(_host, _args, logger):
_username = _args["u"]
Expand All @@ -1105,6 +1225,8 @@ async def execute_badfish(_host, _args, logger):
firmware_inventory = _args["firmware_inventory"]
clear_jobs = _args["clear_jobs"]
list_jobs = _args["ls_jobs"]
check_virtual_media = _args["check_virtual_media"]
unmount_virtual_media = _args["unmount_virtual_media"]
retries = int(_args["retries"])

result = True
Expand Down Expand Up @@ -1152,6 +1274,10 @@ async def execute_badfish(_host, _args, logger):
await badfish.reboot_server(graceful=False)
elif reboot_only:
await badfish.reboot_server()
elif check_virtual_media:
await badfish.check_virtual_media()
elif unmount_virtual_media:
await badfish.unmount_virtual_media()

if pxe and not host_type:
await badfish.set_next_boot_pxe()
Expand Down Expand Up @@ -1244,6 +1370,16 @@ def main(argv=None):
parser.add_argument(
"--ls-jobs", help="List any scheduled jobs in queue", action="store_true",
)
parser.add_argument(
"--check-virtual-media",
help="Check for mounted iso images",
action="store_true",
)
parser.add_argument(
"--unmount-virtual-media",
help="Unmount any mounted iso images",
action="store_true",
)
parser.add_argument("-v", "--verbose", help="Verbose output", action="store_true")
parser.add_argument(
"-r",
Expand Down Expand Up @@ -1289,7 +1425,7 @@ def main(argv=None):
try:
with open(host_list, "r") as _file:
for _host in _file.readlines():
logger = getLogger(_host.split(".")[0])
logger = getLogger(_host.strip().split(".")[0])
logger.addHandler(_queue_handler)
logger.setLevel(log_level)
fn = functools.partial(
Expand Down

0 comments on commit 5b1c1af

Please sign in to comment.