Please whitelist cPanel in your adblocker so that you’re able to see our version release promotions, thanks!

The Community Forums

Interact with an entire community of cPanel & WHM users!

SOLVED Can't locate Cpanel/Logger.pm

Discussion in 'cPanel Developers' started by Matt Paplham, Apr 25, 2019.

Tags:
  1. Matt Paplham

    Matt Paplham Member

    Joined:
    Apr 12, 2019
    Messages:
    6
    Likes Received:
    1
    Trophy Points:
    3
    Location:
    WI - USA
    cPanel Access Level:
    Root Administrator
    Hi All,

    I've created a hook.pm that automates some of the things I do after I create a cPanel account. It compiled and registered without issue.

    However, when I create an account, none of the actions are completed. So I need to trace through my code to see whats going on.

    I tried to add the cPanel::Logger module, but get a compile error:

    Can't locate Cpanel/Logger.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .)

    I tried sudo yum install perl-Logger since it worked for the JSON.pm that I also needed, but that didn't work.

    I also checked WHM>>Software>>Install a Perl Module, but it wasn't there either.

    Any ideas?
     
  2. kdub

    kdub Member

    Joined:
    Apr 19, 2019
    Messages:
    24
    Likes Received:
    6
    Trophy Points:
    3
    Location:
    California
    cPanel Access Level:
    Root Administrator
    Logger is a module specific to Cpanel and should be automatically loaded by cpanel core. I believe it's located at /usr/local/cpanel/Cpanel/Logger.pm

    You can enable debugging in WHM >> Home >> Server Configuration >> Tweak Settings and tail /usr/local/cpanel/logs/error_log to see what's happening. Guide to Standardized Hooks - Debug Mode - Developer Documentation - cPanel Documentation

    Is this a Perl module or script? Does your logging code look like this?
    Code:
    # Use cPanel's error logging module.
    use Cpanel::Logger;
    my $logger = Cpanel::Logger->new();
    $logger->info("message to log");
    Did you save your hook in the right place as per Tutorial - Create a Standardized Hook - Developer Documentation - cPanel Documentation

    Also, Guide to Standardized Hooks - Debug Mode - Developer Documentation - cPanel Documentation states the following at the bottom:
     
  3. cPanelLauren

    cPanelLauren Forums Analyst II Staff Member

    Joined:
    Nov 14, 2017
    Messages:
    5,707
    Likes Received:
    436
    Trophy Points:
    233
    Location:
    Houston
    cPanel Access Level:
    DataCenter Provider
    @kdub thanks for the detailed answer to this! @Matt Paplham let us know if you still have questions once looking through the answers provided by kdub!
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  4. Matt Paplham

    Matt Paplham Member

    Joined:
    Apr 12, 2019
    Messages:
    6
    Likes Received:
    1
    Trophy Points:
    3
    Location:
    WI - USA
    cPanel Access Level:
    Root Administrator
    kdub - Thanks for your quick reply.

    I think my problem is that perl -c is not looking in /usr/local/cpanel/Cpanel for Cpanel::Logger.
    Code:
    [root@dev ~]# perl -c /usr/local/cpanel/OnCreate.pm
    Can't locate Cpanel/Logger.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /usr/local/cpanel/OnCreate.pm line 12.
    
    At any rate, it fails perl -c, but it does let me register the hook.
    Code:
    [root@dev ~]# /usr/local/cpanel/bin/manage_hooks add module OnCreate
    Added hook for Whostmgr::Accounts::Create to hooks registry
    [root@dev ~]# /usr/local/cpanel/bin/manage_hooks list
    Whostmgr:
            Accounts::Create:
                    stage: post
                    weight: 100
                    exectype: module
                    hook: OnCreate::add
                    blocking: 0
                    id: Na5nNZBe5nFJzvaakxq1OYKw
    
    Still no luck actually getting the hook to work. When I access the error log
    Code:
    [root@dev ~]# nano /usr/local/cpanel/logs/error_log
    
    I get
    Code:
    [2019-04-25 15:06:02 -0400] warn [whostmgr5] Can't call method "uapi" on an undefined value at /usr/local/cpanel/OnCreate.pm line 44.
    
    That correlates to this block of code:
    Code:
    # Create the support@domain.com email address.
        my $new_support_email = $cpliveapi->uapi(
            'Email', 'add_pop',
            {
                'email'           => 'support',
                'password'        => '********',
                'quota'           => '0',
                'skip_update_db'  => '1',
            }
        );
    Earlier in the code I have:
    Code:
    # LiveAPI module
    use LiveAPI;
    
    # Connect to cPanel - only do this once.
    my $cpliveapi = Cpanel::LiveAPI->new(); 
    Not sure why I am getting that error since all required parameters are there.
     
  5. kdub

    kdub Member

    Joined:
    Apr 19, 2019
    Messages:
    24
    Likes Received:
    6
    Trophy Points:
    3
    Location:
    California
    cPanel Access Level:
    Root Administrator
    It would probably help if you posted your complete script.

    'use LiveAPI;' would need to be 'use Cpanel::LiveAPI();' you would also need to deconstruct it with $cpliveapi->end(); after you're done with it. Either way, I don't believe you can utilize LiveAPI locally in perl hook modules. Or at least I haven't found any working examples.

    I believe all the references to the LiveAPI code in the cpanel documentation are talking about code in a LiveAPI perl module and not an action hook module. Guide to the LiveAPI System - Perl Module - Developer Documentation - cPanel Documentation

    From what I've read, calls to the LiveAPI from an action script need to be done externally. Unfortunately, the only example I could find is from 3 years ago: Create database(LiveAPI) inside Perl Module Standardized Hook

    A fresh example of LiveAPI in a hook would be amazing?!

    I would think you could move your LiveAPI code to an actual LiveAPI perl module and call that module from your hook module but I have no idea how that would be done. In fact, the documentation is clear as mud as to how these LiveAPI perl modules are actually called or used. These examples would be much appreciated as well.

    By the way, to save you the time of looking at the example LiveAPI cpanel provides:
    Code:
     # /usr/local/cpanel/base/frontend/paper_lantern/integration_examples/example.live.pl
    #!/usr/local/cpanel/3rdparty/bin/perl
    # cpanel - base/frontend/paper_lantern/test.live.pl
    #                                                    Copyright 2014 cPanel, Inc.
    #                                                           All rights Reserved.
    # copyright@cpanel.net                                         http://cpanel.net
    # This code is subject to the cPanel license. Unauthorized copying is prohibited
    
    use strict;
    
    use Cpanel::LiveAPI ();
    
    my $cpanel = Cpanel::LiveAPI->new();
    
    print "Content-type: text/html\r\n\r\n";
    
    print $cpanel->header('Example perl Page');
    
    print "We recommend that you create a new template toolkit file and place it in the paper lantern theme's root directory.";
    
    print $cpanel->footer();
    
    $cpanel->end();
    
     
  6. Matt Paplham

    Matt Paplham Member

    Joined:
    Apr 12, 2019
    Messages:
    6
    Likes Received:
    1
    Trophy Points:
    3
    Location:
    WI - USA
    cPanel Access Level:
    Root Administrator
    Thanks for all the help so far. I've spent a lot of time reading the documentation and searching for examples on the web but am also turning up empty handed.

    If you can't use LiveAPI Perl Modules from hooks, what version of the UAPI should a person use? Or you can't use UAPI at all?

    I figured since the hook was a Perl Module, LiveAPI Perl Modules would make sense. But again, this is my first time making one. And it did seem too easy at the beginning...

    Here is what I am trying to do with a post account create hook:
    • Compress website data
    • Create a database
    • Create a database user
    • Set user privileges for database
    • Create support@domain.com email
    • Encrypt that email
    • Create office@domain.com email
    • Encrypt that email
    This was my first pass at creating the hook Perl Module. I basically copied and pasted from the documentation and added the LiveAPI functions for each of the above in the #insert your actions here.

    Code:
    # Package this module.
    package AcctCreationHook;
    
    # Return errors if Perl experiences problems.
    use strict;
    use warnings;
    
    # Properly decode JSON.
    use JSON;
    
    # LiveAPI module
    use LiveAPI;
    
    # Embed hook attributes alongside the action code.
    sub describe {
        my $my_add = {
            'category' => 'Whostmgr',
            'event'    => 'Accounts::Create',
            'stage'    => 'post',
            'hook'     => 'AcctCreationHook::add',
            'blocking' => 0,
            'exectype' => 'module',
        };
     
        return [ $my_add ];
    }
    
    sub add {
        # Get the data that the system passes to the hook.
        my ( $context, $data ) = @_;              
     
        # Set success and failure messages.
        my $result  = 0;                             # This Boolean value is set to fail.  
        my $message = 'This is an error message.';   # This string is a reason for $result.
       
        # Connect to cPanel - only do this once.
        my $cpliveapi = Cpanel::LiveAPI->new();
       
        # Compress website data
        # This is commented out because it is causing a compile error
        # my $configure_mod_deflate = $cpliveapi->api1(OptimizeWS, optimizews ['all', 'text/html',]);
       
        # Create a new database.
        my $create_db = $cpliveapi->uapi(
            'Mysql', 'create_database',
            {
                'name'    => 'wp500',
            }
        );
       
        # Create a new database user.
        my $create_db_user = $cpliveapi->uapi(
            'Mysql', 'create_user',
            {
                'name'       => 'wp500',
                'password'   => 'password',
            }
        );
       
        # Set the user's privileges for the database.
        my $set_dbuser_privs = $cpliveapi->uapi(
            'Mysql', 'set_privileges_on_database',
            {
                'user'       => 'wp500',
                'database'   => 'wp500',
                'privileges' => 'ALL PRIVILEGES',
            }
        );
       
        # Create the support@domain.com email address.
        my $new_support_email = $cpliveapi->uapi(
            'Email', 'add_pop',
            {
                'email'           => 'support',
                'password'        => 'password',
                'quota'           => '0',
                'skip_update_db'  => '1',
            }
        );
       
        # Encrypt support@domain.com
        my $generate_key = $cpliveapi->api1('Gpg', 'genkey', [$new_support_email, $new_support_email, $new_support_email, '0y', '2048', 'password'] );
       
        # Create the office@domain.com email address.
        my $new_office_email = $cpliveapi->uapi(
            'Email', 'add_pop',
            {
                'email'           => 'office',
                'password'        => 'password',
                'quota'           => '0',
                'skip_update_db'  => '1',
            }
        );
       
        # Encrypt office@domain.com
        my $generate_key = $cpliveapi->api1('Gpg', 'genkey', [$new_office_email, $new_office_email, $new_office_email, '0y', '2048', 'password'] );
       
        my $cpliveapi->end();
     
     
        # Return the hook's result and message.
        return $result, $message;
    }
     
    1;
     
  7. kdub

    kdub Member

    Joined:
    Apr 19, 2019
    Messages:
    24
    Likes Received:
    6
    Trophy Points:
    3
    Location:
    California
    cPanel Access Level:
    Root Administrator
    All this is a bit above my experience level so I'm afraid I don't have a clear answer for you. As I mentioned, I think you can only use Cpanel::LiveAPI in LiveAPI modules. I don't think you can use Cpanel::LiveAPI in action hooks directly. Based on what I've found you would need to call the UAPI externally. cpanel gurus will have to provide some clarification and hopefully some examples of how this is done. Ideally, rather than call uapi externally from action hooks, you could put the uapi code in a LiveAPI perl module and bring it into your action hook so you don't have to mess with all the overhead of making webrequests. But I need someone to show us how that could be done.

    Here's an example of external uapi requests from Tutorial - Call UAPI's SSL::install_ssl Function in Custom Code - Developer Documentation - cPanel Documentation
    Code:
    #!/usr/local/cpanel/3rdparty/bin/perl
     
    # Return errors if Perl experiences problems.
    use strict;
    use warnings;
     
    # Allow my code to perform web requests.
    use LWP::UserAgent;
    use LWP::Protocol::https;
     
    # Use the correct encoding to prevent wide character warnings.
    use Encode;
    use utf8;
     
    # Properly decode JSON.
    use JSON;
     
    # Function properly with Base64 authentication headers.
    use MIME::Base64;
     
    # Authentication information.
    my $username = 'username';
    my $password = '12345luggage';
     
    # The URL for the SSL::install_ssl UAPI function.
    my $request = "https://localhost:2083/execute/SSL/install_ssl";
     
    # Required to allow HTTPS connections to unsigned services.
    # Services on localhost are always unsigned.
    $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
     
    # Create a useragent object.
    my $ua = LWP::UserAgent->new();
     
    # Add authentication headers.
    $ua->default_header(
        'Authorization' => 'Basic ' . MIME::Base64::encode("$username:$password"),
    );
     
    # Read in the SSL certificate and key file.
    my ( $cert, $key );
    {
        local $/;
        open ( my $fh, '<', '/path/to/certificate.crt' );
        $cert = <$fh>;
        close $fh;
        
        open ( $fh, '<', '/path/to/key.key' );
        $key = <$fh>;
        close $key;
    }
     
    # Make the call.
    my $response = $ua->post($request,
        Content_Type => 'form-data',
        Content => [
            domain => 'example.com',
            cert   => $cert,
            key    => $key,
        ],
    );
     
    # Create an object to decode the JSON.
    # Sorted by keys and pretty-printed.
    my $json_printer = JSON->new->pretty->canonical(1);
     
    # UTF-8 encode before decoding to avoid wide character warnings.
    my $content = JSON::decode_json(Encode::encode_utf8($response->decoded_content));
     
    # Print output, UTF-8 encoded to avoid wide character warnings.
    print Encode::encode_utf8($json_printer->encode($content));
     
    cPanelMichael likes this.
  8. cPanelMichael

    cPanelMichael Technical Support Community Manager Staff Member

    Joined:
    Apr 11, 2011
    Messages:
    46,968
    Likes Received:
    2,119
    Trophy Points:
    363
    cPanel Access Level:
    Root Administrator
    Twitter:
    Hello @Matt Paplham,

    The previous post is correct. Here's some more information about why you should not use LiveAPI in the example you provided:

    Problem with API call

    Let me know if this information and the information in the previous post is helpful.

    Thank you.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  9. kdub

    kdub Member

    Joined:
    Apr 19, 2019
    Messages:
    24
    Likes Received:
    6
    Trophy Points:
    3
    Location:
    California
    cPanel Access Level:
    Root Administrator
    @cPanelMichael Is something like I mention in the above quote possible? Can an action hook utilize a custom liveAPI perl module or is external api requests our only option? Thanks.
     
  10. Matt Paplham

    Matt Paplham Member

    Joined:
    Apr 12, 2019
    Messages:
    6
    Likes Received:
    1
    Trophy Points:
    3
    Location:
    WI - USA
    cPanel Access Level:
    Root Administrator
    @cPanelMichael - Are you able to share any hook.pm examples using uapi for the hook actions? The tutorial doesn't use uapi/api2/api1 functions at all, just File::Copy.

    The Guide to Standardized Hooks - Hook Action Code equally does not show how to use uapi/api2/api1 functions, simply:
    # Insert your actions here.

    I feel like if one example was shared, I could figure out how to implement the rest.

    Problem with API call explains why I can't use the live api environment - makes sense it is only for cPanel apps. It doesn't explain how to use uapi/api2/api1 functions in hook, which ultimately is my problem.

    Problem with API call also gives various examples of using uapi in PHP, but nothing for Perl.

    Thanks for your patience as I learn this stuff.
     
  11. cPanelMichael

    cPanelMichael Technical Support Community Manager Staff Member

    Joined:
    Apr 11, 2011
    Messages:
    46,968
    Likes Received:
    2,119
    Trophy Points:
    363
    cPanel Access Level:
    Root Administrator
    Twitter:
    Hello,

    When creating a hook, generally the first step is to find the corresponding event that you want to hook into. To find this information, enable "Debug mode is on. The system displays information about every stage for every hookable event, even if no hooks exist for that stage." under the "Development" tab in WHM >> Tweak Settings. Then, perform the specific action you want to hook into (e.g. create a new account in WHM) and watch the output in /usr/local/cpanel/logs/error_log.

    To test this, create a new addon domain from the cPanel UI after turning debug mode on. You'll see from the output to /usr/local/cpanel/logs/error_log that the following is the hook event to utilize when creating a hook for the addition of a new domain using cPanel >> Addon Domains:

    Cpanel::Api2::AddonDomain::addaddondomain

    Next, you'll want to create/write the hook action code that will run automatically "pre" or "post" the hook event described above. Your hook action code can be in any language that the Linux shell can execute (e.g. bash, Perl, PHP). In the resources below, you'll see how to write a real hook action code in bash:

    Tutorial - How to Setup Standardized Hooks with BASH in cPanel & WHM
    Tutorial - How To Automatically Install WordPress On New Accounts

    Hook action code as a script cannot access cPanel environment variables.

    Hook action code in a custom Perl module can access cPanel environment variables. For steps to create a hook action code Perl module, read our Create a Standardized Hook tutorial to see how the example Perl module below was created:

    Code:
    #!/usr/bin/perl
     
    # Package this module.
    package MyHook;
     
    # Return errors if Perl experiences problems.
    use strict;
    use warnings;
     
    # Use cPanel's error logging module.
    use Cpanel::Logger;
     
    # Use the core Perl module with file-copying functionality.
    use File::Copy;
     
    # Properly decode JSON.
    use JSON;
     
    # Instantiate the cPanel logging object.
    my $logger = Cpanel::Logger->new();
     
    # Embed hook attributes alongside the action code.
    sub describe {
        my $hooks = [
            {
                'category' => 'System',
                'event'    => 'upcp',
                'stage'    => 'pre',
                'hook'     => 'MyHook::copyfile',
                'exectype' => 'module',
            },{
                'category' => 'System',
                'event'    => 'upcp',
                'stage'    => 'post',
                'hook'     => 'MyHook::replacefile',
                'exectype' => 'module',
            }
        ];
        return $hooks;
    }
     
    # Set the file to preserve and the temp file location.
    my $preserve = "/usr/local/cpanel/base/horde/turba/config/backends.php";
    my $temp = "/usr/local/cpanel/base/horde/turba/config/backends.php.temp";
     
    # Before upcp, copy the file to the temp file.
    sub copyfile {
        # Get the data that the system passes to the hook.
        my ( $context, $data ) = @_;
     
        # Add a log entry for debugging.
        $logger->info("***** Copy my file before upcp *****");
     
        # Copy my file.
        copy($preserve,$temp) or die "Copy failed: $!";
    };
     
    # After upcp, copy the file back into place.
    sub replacefile {
        # Get the data that the system passes to the hook.
        my ( $context, $data ) = @_;
     
        # Add a log entry for debugging.
        $logger->info("***** Replace the temp file *****");
     
        # Replace my file.
        copy($temp,$preserve) or die "Replacement failed: $!";
     
        # Add a log entry for debugging.
        $logger->info("***** Delete the temp file *****");
     
        # Delete the temp file to keep cruft off my system.
        unlink($temp) or die "Cruft removal failed: $!";
    };
     
    1; 
    Note that you may need to run the "yum install perl-DBD-MySQL" command to address the "Can't locate Cpanel/Logger.pm in @INC" error message you reported. If that doesn't help, can you open a support ticket letting us know that you are following all of the example steps in our documentation and that it's not working? While we can't assist with creating the custom script, we can run through the example steps in a support ticket to make sure everything is working on your server the way we document it.

    Thank you.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  12. Matt Paplham

    Matt Paplham Member

    Joined:
    Apr 12, 2019
    Messages:
    6
    Likes Received:
    1
    Trophy Points:
    3
    Location:
    WI - USA
    cPanel Access Level:
    Root Administrator
    I just wanted to follow up on this thread. After banging my head on the wall for too long trying to get the hook coded as a Perl Module, I decided to try BASH instead.

    At least for me, it was much easier. I was able to very quickly implement the hook in BASH.

    Thanks for your help @cPanelMichael!!!
     
    cPanelMichael likes this.
  13. cPanelMichael

    cPanelMichael Technical Support Community Manager Staff Member

    Joined:
    Apr 11, 2011
    Messages:
    46,968
    Likes Received:
    2,119
    Trophy Points:
    363
    cPanel Access Level:
    Root Administrator
    Twitter:
    Hello @Matt Paplham,

    That's great! I'm glad to see you were able to implement the hook using BASH.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
Loading...

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice