OPNsense Forum

English Forums => Development and Code Review => Topic started by: iosense on December 28, 2015, 11:37:40 am

Title: Cron job for my custom module
Post by: iosense on December 28, 2015, 11:37:40 am
Hi,

I'd like to find a way to define a cron job to my custom module.
Basically I want to run a service for a certain period of time.
e.g:
I want to run the following command every 3600 seconds.
Code: [Select]
# configctl mymodule mycronjob

btw. I have already read the Creating the hello world module. ( https://wiki.opnsense.org/index.php/Develop:Creating_the_hello_world_module ) but I could not find a title on a cron job.

Thank you in advance for your help.
Title: Re: Cron job for my custom module
Post by: AdSchellevis on December 28, 2015, 12:12:31 pm
@iosense, there is a model for cron jobs available already, for some directions on how to use it you could look at the IDS module:
https://github.com/opnsense/core/blob/master/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/ServiceController.php#L129-L142 (https://github.com/opnsense/core/blob/master/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/ServiceController.php#L129-L142)
Title: Re: Cron job for my custom module
Post by: iosense on January 08, 2016, 01:17:52 pm
Hey Ad,

I'm trying to create a cron job for a while but I think there's something I missed.

I added the UpdateCron to the MyModule model

Code: [Select]
# MyModule.xml
<model>
  <mount>//OPNsense/MyModule</mount>
  <description>
    MyModule application
  </description>
  <items>
    <general>
    <UpdateCron type="ModelRelationField">
      <Model>
        <queues>
          <source>OPNsense.Cron.Cron</source>
          <items>jobs.job</items>
          <display>description</display>
          <filters>
            <origin>/MyModule/</origin>
          </filters>
        </queues>
      </Model>
      <ValidationMessage>Related cron not found</ValidationMessage>
      <Required>N</Required>
    </UpdateCron>
    </general>
  </items>
</model>


Code: [Select]
# ServiceController.php

/**
 * reconfigure MyModule
 */
public function reloadAction()
{
  $status = "failed";
  if ($this->request->isPost()) {
    $mdlMyModule = new MyModule();

    if ((string)$mdlMyModule->general->UpdateCron == "") {
      $mdlCron = new Cron();
      // update cron relation (if this doesn't break consistency)
      $mdlMyModule->general->UpdateCron = $mdlCron->newDailyJob("MyModule", "mymodule test", "MyModule test job", "0");
      if ($mdlCron->performValidation()->count() == 0) {
        $mdlCron->serializeToConfig();
        // save data to config, do not validate because the current in memory model doesn't know about the
        // cron item just created.
        $mdlMyModule->serializeToConfig($validateFullModel = false, $disable_validation = true);
        Config::getInstance()->save();
      }
    }

    $backend = new Backend();
    $bckresult = trim($backend->configdRun("template reload OPNsense.MyModule"));
    if ($bckresult == "OK") {
        $status = "ok";
    }
  }


  return array("status" => $status);
}


I've updated services accordingly to the UpdateCron but
Code: [Select]
$mdlCron->performValidation()->count()  return 1
Code: [Select]
$mdlCron->performValidation() return empty
I can not find what the problem is.
Title: Re: Cron job for my custom module
Post by: AdSchellevis on January 08, 2016, 02:07:04 pm
Hi,

Just run something like this to retrieve all errors, don't forget to add a configd command for your action and deliver a description for it (look at the IDS sample for more details).

Code: [Select]
$mdlCron = new Cron();
$mdlCron->newDailyJob("MyModule", "mymodule test", "MyModule test job", "0");
print_r($mdlCron->performValidation());

Which outputs at my end:

Code: [Select]
Phalcon\Validation\Message\Group Object
(
    [_position:protected] =>
    [_messages:protected] => Array
        (
            [0] => Phalcon\Validation\Message Object
                (
                    [_type:protected] => PresenceOf
                    [_message:protected] => Value needs to be between 0 and 59, multiple values, ranges and * are supported (ex. 1,10,20,30 or 1-30  )
                    [_field:protected] => jobs.job.f8e0db2b-8909-41cf-9847-82abc5b17741.minutes
                )

            [1] => Phalcon\Validation\Message Object
                (
                    [_type:protected] => PresenceOf
                    [_message:protected] => Value needs to be between 0 and 23, multiple values, ranges and * are supported (ex. 1,2,8 or 0-8 )
                    [_field:protected] => jobs.job.f8e0db2b-8909-41cf-9847-82abc5b17741.hours
                )

            [2] => Phalcon\Validation\Message Object
                (
                    [_type:protected] => PresenceOf
                    [_message:protected] => Value needs to be between 0 and 6 ( Sunday to Saturday), multiple values, ranges and * are supported (ex. 1,2,4 or 0-4  )
                    [_field:protected] => jobs.job.f8e0db2b-8909-41cf-9847-82abc5b17741.weekdays
                )

            [3] => Phalcon\Validation\Message Object
                (
                    [_type:protected] => InclusionIn
                    [_message:protected] => Select a command from the list.
                    [_field:protected] => jobs.job.f8e0db2b-8909-41cf-9847-82abc5b17741.command
                )

        )
)

For some reason I seem to hit a phalcon error at my end (0 is not present??), complaining about an empty option, can you confirm that you suffer from the same issue?

If you want to see what it was planning to insert/update, just execute this:

Code: [Select]
echo $mdlCron->toXML()->asXML();
Title: Re: Cron job for my custom module
Post by: AdSchellevis on January 08, 2016, 02:20:21 pm
My local osx client had an old version of phalcon installed, which suffered from this https://github.com/ryomo/cphalcon/commit/564dfb5001f5b4f9eaaa939c00b1229bb7dbb480 (https://github.com/ryomo/cphalcon/commit/564dfb5001f5b4f9eaaa939c00b1229bb7dbb480)
Title: Re: Cron job for my custom module
Post by: iosense on January 08, 2016, 09:03:01 pm

Hey Ad,

thank you for your help,

Quote
# configctl mymodule test command works successfully on the command line.



$mdlCron = new Cron();
$mdlCron->newDailyJob("MyModule", "mymodule test", "MyModule test job", "0");
print_r($mdlCron->performValidation()); output as follows:

Code: [Select]
Phalcon\Validation\Message\Group Object
(
    [_position:protected] =>
    [_messages:protected] => Array
        (
            [0] => Phalcon\Validation\Message Object
                (
                    [_type:protected] => InclusionIn
                    [_message:protected] => Select a command from the list.
                    [_field:protected] => jobs.job.c98659f2-3555-471e-9e0c-e1acf26e791a.command
                    [_code:protected] => 0
                )

        )

)

echo $mdlCron->toXML()->asXML(); output as follows:

Code: [Select]
<OPNsense>
    <cron>
        <jobs>
            <job uuid="ae473210-e201-4c51-8eb5-0cb70f211101">
                <origin>IDS</origin>
                <enabled>0</enabled>
                <minutes>0</minutes>
                <hours>0</hours>
                <days>*</days>
                <months>*</months>
                <weekdays>0</weekdays>
                <who>root</who>
                <command>ids update</command>
                <parameters/>
                <description>ids rule updates</description>
            </job>
            <job uuid="c98659f2-3555-471e-9e0c-e1acf26e791a">
                <origin>MyModule</origin>
                <enabled>0</enabled>
                <minutes>0</minutes>
                <hours>0</hours>
                <days>*</days>
                <months>*</months>
                <weekdays>0</weekdays>
                <who>root</who>
                <command>mymodule test</command>
                <parameters/>
                <description>MyModule test job</description>
            </job>
        </jobs>
    </cron>
</OPNsense>

Apparently, cron job was created successfully but it does not saved to my model, even it does not appear on http://localhost/ui/cron/ page

Title: Re: Cron job for my custom module
Post by: AdSchellevis on January 09, 2016, 09:11:30 am
If you execute this on the command line:

Code: [Select]
configctl configd actions list | grep mymodule
What's the output then?

it should look like this (example from the ids output):

Code: [Select]
ids update [ update IDS rules ]

Mark the text between the brackets [], which comes from the "description" tag from the ids action.

Title: Re: Cron job for my custom module
Post by: iosense on January 18, 2016, 06:05:54 pm
Hey Ad,

Thank you for your help, I realized that the problems associated with description tag. it's all a simple typo error, now everything is fine.

But there is one issue I wondered;

New cron job appear in cron page ( http://localhost/ui/cron/ ) but it can not be automatically activated, I have set this task manually.

I wonder, how can I set this task automatically? There are tasks that I want to run every 15-20 minutes.
and $mdlCron->newDailyJob has only weekdays argument How do I set Minutes for cron ?

Code: [Select]
/**
 * Class Cron
 * @package OPNsense\Cron
 */
class Cron extends BaseModel
{
    /**
     * create a new daily job
     * @param string $origin
     * @param string $command
     * @param string $description
     * @param string $weekdays day(s) of the week to run
     * @param string $enabled default add disabled cron jobs, if triggered enabled be sure to call regenerate on cron.
     * @return string
     */
    public function newDailyJob($origin, $command, $description, $weekdays = "*", $enabled = "0")
    {
        $cron = $this->jobs->job->Add();
        $uuid = $cron->getAttributes()['uuid'];
        $cron->origin = $origin;
        $cron->command = $command;
        $cron->description = $description;
        $cron->weekdays = $weekdays ;
        $cron->enabled = $enabled;
        return $uuid;
    }
}

My Cron code

Code: [Select]
if ((string)$mdlMymodule->general->UpdateCron == "") {
    $mdlCron = new Cron();
    $mdlMymodule->general->UpdateCron = $mdlCron->newDailyJob("Mymodule", "mymodule test", "Mymodule Test cron", "1");
    if ($mdlCron->performValidation()->count() == 0) {
        $mdlCron->serializeToConfig();
        $mdlMymodule->serializeToConfig($validateFullModel = false, $disable_validation = true);
        Config::getInstance()->save();
    }
}
Title: Re: Cron job for my custom module
Post by: AdSchellevis on January 19, 2016, 11:34:43 am
Hi iosense,

Your welcome, if you want to setup a non weekly cronjob you can just create an object and set the properties manually, something like this should work:

Code: [Select]
$mdlcron = new Cron();
$cron = $mdlcron->jobs->job->Add();
$cron->origin = "your origin";
$cron->command = "your command";
$cron->description = "your description";
$cron->hours = "*" ;
$cron->enabled = 1;
... followed by the same save actions you already had.


Regards,

Ad