Python Forum
Python script that calls jamfHelper binary - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Python script that calls jamfHelper binary (/thread-17975.html)

Pages: 1 2


Python script that calls jamfHelper binary - kennethdean2010 - May-01-2019

Hi I have a python script I am using to update my Macbooks at work that calls the jamfBinary to display a hud that allows the user to defer updates.

At this time it only presents the hud once with 5 options,
  • "Start Now",
  • "5 minutes",
  • "2 hours",
  • "4 hours",
  • "8 hours".
If the user chooses "5 minutes" then the install starts in five minutes.

What I want is it to display the prompt again minus the options that preceded it.
So if the input is 5 mins, then in roughly five minutes the hud reappears with
  • "Start Now",
  • "2 hours",
  • "4 hours",
  • "8 hours".
If the hud comes up and user decides I will do it in "4 hours" then I want the prompt to reappear with only the 8 hour option.

I want them to be able to defer multiple times until the max deferral time period has been reached.
I have attached the script.
I was thinking I could just re-use this section of code however many times I need it to prompt but I am not sure if I am thinking about this correctly as I am not a Python Pro but I have some experience programming in C++.
My apologies. Any guidance is much appreciated.

***This is the code I believe I can reuse to accomplish the hud being prompted, I am just not sure if I am logically approaching this the right way.

def display_prompt():
    """Displays prompt to allow user to schedule update installation

    Args:
        None

    Returns:
        (int) defer_seconds: Number of seconds user wishes to defer policy
        OR
        None if an error occurs
    """
    cmd = [JAMFHELPER,
           '-windowType', 'hud',
           '-title', GUI_WINDOW_TITLE,
           '-heading', GUI_HEADING,
           '-icon', GUI_ICON,
           '-description', GUI_MESSAGE,
           '-button1', GUI_BUTTON,
           '-showDelayOptions',
           ' '.join(GUI_DEFER_OPTIONS),
           '-lockHUD']
    error_values = ['2', '3', '239', '243', '250', '255']
    # Instead of returning an error code to stderr, jamfHelper always returns 0
    # and possibly returns an 'error value' to stdout. This makes it somewhat
    # spotty to check for some deferrment values including 0 for 'Start Now'.
    # The return value is an integer, so leading zeroes are dropped. Selecting
    # 'Start Now' should technically return '01'; instead, only '1' is returned
    # which matches the 'error value' for 'The Jamf Helper was unable to launch'
    # All we can do is make sure the subprocess doesn't raise an error, then
    # assume (yikes!) a return value of '1' equates to 'Start Now'
    try:
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        out, err = proc.communicate()
        # Check that the return value does not represent an 'error value'
        if not out in error_values:
            # Special case for 'Start Now' which returns '1'
            if out == '1':
                return 0
            else:
                return int(out[:-1])
        else:
            return None
    except:
        # Catch possible CalledProcessError and OSError
        print "An error occurred when displaying the user prompt."
        return None



RE: Python script that calls jamfHelper binary - Yoriz - May-01-2019

I'm not entirely sure if this is what your looking for and it can probably be improved upon.
class ChoiceError(Exception):
    pass

class RestartChoices():

    def __init__(self):
        self.reset_choices()

    def reset_choices(self):
        self.choices = ["Start Now", "5 minutes", "2 hours", "4 hours",
                        "8 hours"]
        self.last_choice = ''

    def make_choice(self, choice):
        if choice not in self.choices:
            raise ChoiceError('invalid choice')
        self.last_choice = choice
        if choice == self.choices[-1] or choice == self.choices[0]:
            self.choices = []
            return

        choice_index = self.choices.index(choice) + 1
        self.choices = self.choices[:1] + self.choices[choice_index:]

restart_choices = RestartChoices()
restart_choices.make_choice('5 minutes')
print(f'choice: {restart_choices.last_choice}')
print(f'Remaining: {restart_choices.choices}')

restart_choices.make_choice('4 hours')
print(f'choice: {restart_choices.last_choice}')
print(f'Remaining: {restart_choices.choices}')

restart_choices.make_choice('8 hours')
print(f'choice: {restart_choices.last_choice}')
print(f'Remaining: {restart_choices.choices}')

restart_choices.reset_choices()
restart_choices.make_choice('2 hours')
print(f'choice: {restart_choices.last_choice}')
print(f'Remaining: {restart_choices.choices}')

restart_choices.reset_choices()
restart_choices.make_choice('Start Now')
print(f'choice: {restart_choices.last_choice}')
print(f'Remaining: {restart_choices.choices}')
Output:
choice: 5 minutes Remaining: ['Start Now', '2 hours', '4 hours', '8 hours'] choice: 4 hours Remaining: ['Start Now', '8 hours'] choice: 8 hours Remaining: [] choice: 2 hours Remaining: ['Start Now', '4 hours', '8 hours'] choice: Start Now Remaining: []



RE: Python script that calls jamfHelper binary - kennethdean2010 - May-02-2019

Hi Yoriz,

Ty for your response.

So I assume I would somehow pass the output from
def display_prompt():
to
 class ChoiceError(Exception): ??? 
I hope I tagged the code correctly Yoriz!!! Sorry for my first post.


RE: Python script that calls jamfHelper binary - Yoriz - May-02-2019

ChoiceError is just an error to raise if a choice is made that is not a valid choice
restart_choices = RestartChoices()
restart_choices.make_choice('15 minutes')
Output:
Traceback (most recent call last): File "C:\Users\Dave\Documents\Eclipse Workspace\Test\forum\forum_post.py", line 29, in <module> restart_choices.make_choice('15 minutes') File "C:\Users\Dave\Documents\Eclipse Workspace\Test\forum\forum_post.py", line 17, in make_choice raise ChoiceError('invalid choice') __main__.ChoiceError: invalid choice



RE: Python script that calls jamfHelper binary - kennethdean2010 - May-02-2019

Sorry I copied and pasted the wrong function... I meant:

How do I pass the value of:
def display_prompt(): 
to
class RestartChoices():



RE: Python script that calls jamfHelper binary - SheeppOSU - May-02-2019

You could make a self in RestartChoices that takes the value of a parameter passed through and then update it with the value of display_prompt


RE: Python script that calls jamfHelper binary - kennethdean2010 - May-03-2019

(May-02-2019, 10:13 PM)SheeppOSU Wrote: You could make a self in RestartChoices that takes the value of a parameter passed through and then update it with the value of display_prompt
Ty SheeppOSU I will give it a shot!!!


RE: Python script that calls jamfHelper binary - kennethdean2010 - May-03-2019

(May-02-2019, 10:13 PM)SheeppOSU Wrote: You could make a self in RestartChoices that takes the value of a parameter passed through and then update it with the value of display_prompt

Should I create that outside of my current better-jamf-policy-deferral.py script? Or create it in the same .py script... are classes in python like classes in C#? You create them as a different file and then bundle them all up together? My apologies I am script kiddy that took some courses at my local community college, I am def not a Computer Science major lol


RE: Python script that calls jamfHelper binary - SheeppOSU - May-03-2019

I've done a litte C++ which I've heard is similar to C#. In C++ classes are usually made in different files like you said. In Python in depends. When making a game, to shorten code, sometimes functions and classes are put into a separate files. In this case since it is a small amount of code it can go into the same file

Also create what outside of the current file


RE: Python script that calls jamfHelper binary - kennethdean2010 - May-04-2019

(May-03-2019, 10:18 PM)SheeppOSU Wrote: I've done a litte C++ which I've heard is similar to C#. In C++ classes are usually made in different files like you said. In Python in depends. When making a game, to shorten code, sometimes functions and classes are put into a separate files. In this case since it is a small amount of code it can go into the same file
Also create what outside of the current file

Ok thanks SheeppOSU!!! I will toy with this all weekend :)