{"id":4471,"date":"2018-06-29T20:54:50","date_gmt":"2018-06-29T23:54:50","guid":{"rendered":"https:\/\/blog.clusterweb.com.br\/?p=4471"},"modified":"2018-06-29T20:54:50","modified_gmt":"2018-06-29T23:54:50","slug":"manualchr-mikrotik","status":"publish","type":"post","link":"https:\/\/blog.clusterweb.com.br\/?p=4471","title":{"rendered":"Manual:CHR MIKROTIK"},"content":{"rendered":"<h2><span id=\"Cloud_Hosted_Router\" class=\"mw-headline\">Cloud Hosted Router<\/span><\/h2>\n<p>Cloud Hosted Router (CHR) is a RouterOS version intended for running as a virtual machine. It supports the x86 64-bit architecture and can be used on most of the popular hypervisors such as VMWare, Hyper-V, VirtualBox, KVM and others. CHR has full RouterOS features enabled by default but has a different licensing model than other RouterOS versions.<\/p>\n<h2><span id=\"System_Requirements\" class=\"mw-headline\">System Requirements<\/span><\/h2>\n<h4><span id=\"Minimal_requirements:\" class=\"mw-headline\">Minimal requirements:<\/span><\/h4>\n<ul>\n<li>RouterOS version 6.34 or later installed<\/li>\n<li>64bit CPU with virtualization support<\/li>\n<li>128 MB or more RAM for the CHR instance<\/li>\n<li>128 MB disk space for the CHR virtual hard drive\n<ul>\n<li>Maximum supported system disk image size is 16GB<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<div id=\"shbox\">\n<div class=\"floatleft\"><a class=\"image\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:Icon-note.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/thumb\/e\/ee\/Icon-note.png\/56px-Icon-note.png\" srcset=\"\/images\/thumb\/e\/ee\/Icon-note.png\/84px-Icon-note.png 1.5x, \/images\/thumb\/e\/ee\/Icon-note.png\/112px-Icon-note.png 2x\" alt=\"Icon-note.png\" width=\"56\" height=\"56\" \/><\/a><\/div>\n<p><b>Note:<\/b>\u00a0Minimal requirement is 128MB of RAM to complete the self-installation process.<\/p>\n<p>&nbsp;<\/p>\n<\/div>\n<p><!--more--><\/p>\n<h4><span id=\"CHR_has_been_tested_on_the_following_platforms:\" class=\"mw-headline\">CHR has been tested on the following platforms:<\/span><\/h4>\n<ul>\n<li>VirtualBox 5 on Linux and OS X<\/li>\n<li>VMWare Fusion 7 and 8 on OS X<\/li>\n<li>VMWare ESXi 6.5<\/li>\n<li>Qemu 2.4.0.1 on Linux and OS X<\/li>\n<li>Hyper-V on Windows Server 2008r2, 2012 and Windows 10\u00a0<i>(Only Generation 1 Hyper-V virtual machine is supported at the moment)<\/i><\/li>\n<li>Xen Project 4.6.5<\/li>\n<li>Xen Server 7.1<\/li>\n<\/ul>\n<div id=\"shbox\">\n<div class=\"floatleft\"><a class=\"image\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:Icon-warn.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/thumb\/1\/1d\/Icon-warn.png\/56px-Icon-warn.png\" srcset=\"\/images\/thumb\/1\/1d\/Icon-warn.png\/84px-Icon-warn.png 1.5x, \/images\/thumb\/1\/1d\/Icon-warn.png\/112px-Icon-warn.png 2x\" alt=\"Icon-warn.png\" width=\"56\" height=\"56\" \/><\/a><\/div>\n<p><b>Warning:<\/b>\u00a0Hypervisors that provide paravirtualization are not supported.<\/p>\n<\/div>\n<h4><span id=\"Usable_Network_and_Disk_interfaces_on_various_hypervisors:\" class=\"mw-headline\">Usable Network and Disk interfaces on various hypervisors:<\/span><\/h4>\n<ul>\n<li>ESX:\n<ul>\n<li>Network: vmxnet3, E1000<\/li>\n<li>Disk: IDE, VMware paravirtual SCSI, LSI Logic SAS, LSI Logic Parallel<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Hyper-V:\n<ul>\n<li>Network: Network adapter, Legacy Network adapter<\/li>\n<li>Disk: IDE, SCSI<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Qemu\/KVM:\n<ul>\n<li>Network: Virtio, E1000, vmxnet3 (optional)<\/li>\n<li>Disk: IDE, Sata, Virtio<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Xen Project:\n<ul>\n<li>Network: E1000, rtl8193, netfront<\/li>\n<li>Disk: IDE, Sata<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>VirtualBox\n<ul>\n<li>Network: E1000, rtl8193<\/li>\n<li>Disk: IDE, Sata, SCSI, SAS<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<div id=\"shbox\">\n<div class=\"floatleft\"><a class=\"image\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:Icon-note.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/thumb\/e\/ee\/Icon-note.png\/56px-Icon-note.png\" srcset=\"\/images\/thumb\/e\/ee\/Icon-note.png\/84px-Icon-note.png 1.5x, \/images\/thumb\/e\/ee\/Icon-note.png\/112px-Icon-note.png 2x\" alt=\"Icon-note.png\" width=\"56\" height=\"56\" \/><\/a><\/div>\n<p><b>Note:<\/b>\u00a0SCSI controller Hyper-V and ESX is usable just for secondary disks, system image must be used with IDE controller!<\/p>\n<\/div>\n<div id=\"shbox\">\n<div class=\"floatleft\"><a class=\"image\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:Icon-warn.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/thumb\/1\/1d\/Icon-warn.png\/56px-Icon-warn.png\" srcset=\"\/images\/thumb\/1\/1d\/Icon-warn.png\/84px-Icon-warn.png 1.5x, \/images\/thumb\/1\/1d\/Icon-warn.png\/112px-Icon-warn.png 2x\" alt=\"Icon-warn.png\" width=\"56\" height=\"56\" \/><\/a><\/div>\n<p><b>Warning:<\/b>\u00a0We do not recommend using E1000 network interface if better synthetic interface options are available on specific Hypervisor!<\/p>\n<\/div>\n<h2><span id=\"How_to_Install_CHR\" class=\"mw-headline\">How to Install CHR<\/span><\/h2>\n<p>We provide 4 different virtual disk images to choose from. Note that they are only disk images, and you can&#8217;t simply run them.<\/p>\n<ul>\n<li>RAW disk image (.img file)<\/li>\n<li>VMWare disk image (.vmdk file)<\/li>\n<li>Hyper-V disk image (.vhdx file)<\/li>\n<li>VirtualBox disk image (.vdi file)<\/li>\n<\/ul>\n<h4><span id=\"Steps_to_install_CHR\" class=\"mw-headline\">Steps to install CHR<\/span><\/h4>\n<ol>\n<li><a class=\"external text\" href=\"http:\/\/www.mikrotik.com\/download#chr\" rel=\"nofollow\">Download<\/a>\u00a0virtual disk image for your hypervisor<\/li>\n<li>Create a guest virtual machine<\/li>\n<li>Use previously downloaded image file as a virtual disk drive<\/li>\n<li>Start the guest CHR virtual machine<\/li>\n<li>Log in to your new CHR. Default user is &#8216;admin&#8217;, without password<\/li>\n<\/ol>\n<p>Please note that running CHR systems can be cloned and copied, but the copy will be aware of the previous trial period, so you cannot extend your trial time by making a copy of your CHR. However, you are allowed to license both systems individually. To make a new trial system, you need to make a fresh installation and reconfigure RouterOS.<\/p>\n<h4><span id=\"Installing_CHR\" class=\"mw-headline\">Installing CHR<\/span><\/h4>\n<ul>\n<li><a title=\"Manual:CHR VMWare installation\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/Manual:CHR_VMWare_installation\">VMWare<\/a>\u00a0Fusion \/ Workstation and ESXi 6.5<\/li>\n<li><a title=\"Manual:CHR VirtualBox installation\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/Manual:CHR_VirtualBox_installation\">VirtualBox<\/a><\/li>\n<li><a title=\"Manual:CHR Hyper-V installation\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/Manual:CHR_Hyper-V_installation\">Hyper-V<\/a><\/li>\n<li><a title=\"Manual:CHR AWS installation\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/Manual:CHR_AWS_installation\">Amazon Web Services (AWS)<\/a><\/li>\n<li><a title=\"Manual:CHR Linode\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/Manual:CHR_Linode\">Linode<\/a><\/li>\n<li><a title=\"Manual:CHR GCE\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/Manual:CHR_GCE\">Google Compute Engine<\/a><\/li>\n<li><a title=\"Manual:CHR ProxMox installation\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/Manual:CHR_ProxMox_installation\">ProxMox<\/a><\/li>\n<\/ul>\n<h2><span id=\"CHR_Licensing\" class=\"mw-headline\">CHR Licensing<\/span><\/h2>\n<p>The CHR has 4 license levels:<\/p>\n<ul>\n<li><i><b>free<\/b><\/i><\/li>\n<li><i><b>p1<\/b><\/i>\u00a0<i>perpetual-1<\/i>\u00a0($45)<\/li>\n<li><i><b>p10<\/b><\/i>\u00a0<i>perpetual-10<\/i>\u00a0($95)<\/li>\n<li><i><b>p-unlimited<\/b><\/i>\u00a0<i>perpetual-unlimited<\/i>\u00a0($250)<\/li>\n<\/ul>\n<p>60-day free trial license is available for all paid license levels. To get the free trial license, you have to have an account on\u00a0<a class=\"external text\" href=\"http:\/\/mikrotik.com\/\" rel=\"nofollow\">MikroTik.com<\/a>\u00a0as all license management is done there.<\/p>\n<p>Perpetual is a lifetime license (buy once, use forever). It is possible to transfer a perpetual license to another CHR instance. A running CHR instance will indicate the time when it has to access the account server to renew it&#8217;s license. If the CHR instance will not be able to renew the license it will behave as if the trial period has ran out and will not allow an upgrade of RouterOS to a newer version.<\/p>\n<p>After licensing a running trial system, you\u00a0<b>must<\/b>\u00a0manually run the\u00a0<i>\/system license renew<\/i>\u00a0function from the CHR to make it active. Otherwise the system will not know you have licensed it in your account. If you do not do this before the system deadline time, the trial will end and you will have to do a complete fresh CHR installation, request a new trial and then license it with the license you had obtained.<\/p>\n<table class=\"styled_table\">\n<tbody>\n<tr>\n<th>License<\/th>\n<th>Speed limit<\/th>\n<th>Price<\/th>\n<\/tr>\n<tr>\n<td>Free<\/td>\n<td>1Mbit<\/td>\n<td>FREE<\/td>\n<\/tr>\n<tr>\n<td>P1<\/td>\n<td>1Gbit<\/td>\n<td>$45<\/td>\n<\/tr>\n<tr>\n<td>P10<\/td>\n<td>10Gbit<\/td>\n<td>$95<\/td>\n<\/tr>\n<tr>\n<td>P-Unlimited<\/td>\n<td>Unlimited<\/td>\n<td>$250<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><span id=\"Paid_licenses\" class=\"mw-headline\">Paid licenses<\/span><\/h3>\n<h5><span id=\"p1\" class=\"mw-headline\">p1<\/span><\/h5>\n<p><i>p1<\/i>\u00a0(perpetual-1) license level allows CHR to run indefinitely. It is limited to 1Gbps upload per interface. All the rest of the features provided by CHR are available without restrictions. It is possible to upgrade\u00a0<i>p1<\/i>\u00a0to\u00a0<i>p10<\/i>\u00a0or\u00a0<i>p-unlimited<\/i>\u00a0After the upgrade is purchased the former license will become available for later use on your account.<\/p>\n<h5><span id=\"p10\" class=\"mw-headline\">p10<\/span><\/h5>\n<p><i>p10<\/i>\u00a0(perpetual-10) license level allows CHR to run indefinitely. It is limited to 10Gbps upload per interface. All the rest of the features provided by CHR are available without restrictions. It is possible to upgrade\u00a0<i>p10<\/i>\u00a0to\u00a0<i>p-unlimited<\/i>\u00a0After the upgrade is purchased the former license will become available for later use on your account.<\/p>\n<h5><span id=\"p-unlimited\" class=\"mw-headline\">p-unlimited<\/span><\/h5>\n<p>The\u00a0<i>p-unlimited<\/i>\u00a0(perpetual-unlimited) license level allows CHR to run indefinitely. It is the highest tier license and it has no enforced limitations.<\/p>\n<h3><span id=\"Free_licenses\" class=\"mw-headline\">Free licenses<\/span><\/h3>\n<p>There are several options to use and try CHR free of charge.<\/p>\n<h6><span id=\"free\" class=\"mw-headline\">free<\/span><\/h6>\n<p>The\u00a0<i>free<\/i>\u00a0license level allows CHR to run indefinitely. It is limited to 1Mbps upload per interface. All the rest of the features provided by CHR are available without restrictions. To use this, all you have to do is download disk image file from our download page and create a virtual guest.<\/p>\n<h6><span id=\"60-day_trial\" class=\"mw-headline\">60-day trial<\/span><\/h6>\n<p>In addition to the limited Free installation, you can also test the increased speed of P1\/P10\/PU licenses with a 60 trial.<\/p>\n<p>You will have to have an account registered on\u00a0<a class=\"external text\" href=\"http:\/\/mikrotik.com\/\" rel=\"nofollow\">MikroTik.com<\/a>. Then you can request the desired license level for trial from your router that will assign your router ID to your account and enable a purchase of the license from your account. All the paid license equivalents are available for trial. A trial period is 60 days from the day of acquisition, after this time passes, your license menu will start to show &#8220;Limited upgrades&#8221;, which means that RouterOS can no longer be upgraded.<\/p>\n<p>If you plan to purchase the selected license, you must do it within 60 days of the trial end date. If your trial ends, and there are no purchases within 2 months after it ended, the device will no longer appear in your MikroTik account. You will have to make a new CHR installation to make a purchase within the required time frame.<\/p>\n<p>To request a trial license, you must run the command &#8220;<b>\/system license renew<\/b>&#8221; from the CHR device command line. You will be asked for the username and password of your mikrotik.com account.<\/p>\n<div id=\"shbox\">\n<div class=\"floatleft\"><a class=\"image\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:Icon-warn.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/thumb\/1\/1d\/Icon-warn.png\/56px-Icon-warn.png\" srcset=\"\/images\/thumb\/1\/1d\/Icon-warn.png\/84px-Icon-warn.png 1.5x, \/images\/thumb\/1\/1d\/Icon-warn.png\/112px-Icon-warn.png 2x\" alt=\"Icon-warn.png\" width=\"56\" height=\"56\" \/><\/a><\/div>\n<p><b>Warning:<\/b>\u00a0If you plan to use multiple virtual systems of the same kind, it may be possible that the next machine has the same systemID as the original one. This can happen on certain cloud providers, such as Linode. To avoid this, after your first boot, run the command &#8220;\/system license generate-new-id&#8221;\u00a0<b>before<\/b>\u00a0you request a trial license.<\/p>\n<\/div>\n<h2><span id=\"Getting_the_License\" class=\"mw-headline\">Getting the License<\/span><\/h2>\n<p>After the initial setup a CHR instance will have a\u00a0<i>free<\/i>\u00a0license assigned. From there, it is possible to upgrade the license to a higher tier. Once you have a trial license all the work with the license is done on the\u00a0<a class=\"external text\" href=\"https:\/\/mikrotik.com\/client\" rel=\"nofollow\">account server<\/a>\u00a0where it is possible to upgrade license to a higher tier unless it is\u00a0<i>p-unlimited<\/i>\u00a0already.<\/p>\n<h4><span id=\"Upgrade_from_free_to_p1_or_higher\" class=\"mw-headline\">Upgrade from free to p1 or higher<\/span><\/h4>\n<p>Initial upgrade from the\u00a0<i>free<\/i>\u00a0tier to anything higher than that incurs CHR instance registration on the\u00a0<a class=\"external text\" href=\"https:\/\/mikrotik.com\/client\" rel=\"nofollow\">account server<\/a>. To do that you have to enter your\u00a0<a class=\"external text\" href=\"https:\/\/www.mikrotik.com\/client\/\" rel=\"nofollow\">MikroTik.com<\/a>\u00a0username and password and a desired license level you want to acquire. As a result, a CHR ID number will be assigned to your account on the account server and 60-day trial created for that ID. There are 2 ways to obtain a license &#8211; using WinBox or RouterOS command line interface:<\/p>\n<p><b>Using WinBox (Sytem -&gt; License menu):<\/b><\/p>\n<p><a class=\"image\" title=\"CHR Licence Renew\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:CHR_Licence_01.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/a\/ae\/CHR_Licence_01.png\" alt=\"CHR Licence Renew\" width=\"354\" height=\"305\" \/><\/a><\/p>\n<p><a class=\"image\" title=\"CHR Licence Renew\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:CHR_Licence_02.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/7\/74\/CHR_Licence_02.png\" alt=\"CHR Licence Renew\" width=\"354\" height=\"166\" \/><\/a><\/p>\n<p><b>Using command line interface:<\/b><\/p>\n<pre>[admin@MikroTik] &gt; \/system license print \r\n  system-id: 6lR1ZP\/utuJ\r\n      level: free\r\n\r\n[admin@MikroTik] &gt; \/system license renew \r\naccount: mymikrotikcomaccount\r\npassword: *********************\r\nlevel: p1 \r\n  status: done\r\n  \r\n[admin@MikroTik] &gt; \/system license print \r\n        system-id: 6lR1ZP\/utuJ\r\n            level: p1\r\n  next-renewal-at: jan\/10\/2016 21:59:59\r\n      deadline-at: feb\/09\/2016 21:59:59\r\n<\/pre>\n<p>To acquire a higher level trial, set up a new CHR instance, renew the license and select the desired level.<\/p>\n<p><b>To upgrade from a Trial license to Paid go to\u00a0<a class=\"external text\" href=\"https:\/\/www.mikrotik.com\/client\" rel=\"nofollow\">MikroTik.com account server<\/a>\u00a0and choose &#8216;all keys&#8217; in Cloud Hosted Router (CHR) section:<\/b><\/p>\n<p><a class=\"image\" title=\"Account server\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:CHR_keys_01.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/thumb\/d\/de\/CHR_keys_01.png\/900px-CHR_keys_01.png\" srcset=\"\/images\/d\/de\/CHR_keys_01.png 1.5x\" alt=\"Account server\" width=\"900\" height=\"503\" \/><\/a><\/p>\n<p><b>You will be presented with a list of your CHR machines and licenses:<\/b><\/p>\n<p><a class=\"image\" title=\"Account server\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:CHR_keys_02a.PNG\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/f\/fc\/CHR_keys_02a.PNG\" alt=\"Account server\" width=\"900\" height=\"281\" \/><\/a><\/p>\n<p><b>To upgrade from a Trial to a Paid license click &#8216;Upgrade&#8217;, choose the desired license level (it can be different than the level of the trial license) and click &#8216;Upgrade key&#8217;:<\/b><\/p>\n<p><a class=\"image\" title=\"Account server\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:CHR_keys_03.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/thumb\/3\/3b\/CHR_keys_03.png\/900px-CHR_keys_03.png\" srcset=\"\/images\/thumb\/3\/3b\/CHR_keys_03.png\/1350px-CHR_keys_03.png 1.5x, \/images\/thumb\/3\/3b\/CHR_keys_03.png\/1800px-CHR_keys_03.png 2x\" alt=\"Account server\" width=\"900\" height=\"516\" \/><\/a><\/p>\n<p><b>Choose the payment method:<\/b><\/p>\n<p><a class=\"image\" title=\"Account server\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:CHR_keys_04.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/3\/3a\/CHR_keys_04.png\" alt=\"Account server\" width=\"900\" height=\"422\" \/><\/a><\/p>\n<p><b>It is possible to pay using account balance (deposit), credit card (CC), PayPal or using Balance (prepaid) key (if you have any).<\/b><\/p>\n<h4><span id=\"Upgrade_from_higher_tier_up\" class=\"mw-headline\">Upgrade from higher tier up<\/span><\/h4>\n<p>Only an upgrade to a higher tier is possible at the moment (for paid licenses only) and that is done in the account server. For changes to take place on the router itself\u00a0<i>renew<\/i>\u00a0command should be issued. When the router already has any kind of trial or paid license, the license level you set for the\u00a0<i>renew<\/i>\u00a0command is not important anymore, it is mandated by\u00a0<a class=\"external text\" href=\"https:\/\/www.mikrotik.com\/client\/cloudhosting\" rel=\"nofollow\">the account server<\/a>. Possible upgrades are as follows:<\/p>\n<ul>\n<li><i>p1<\/i>\u00a0upgrade to\u00a0<i>p10<\/i><\/li>\n<li><i>p1<\/i>\u00a0upgrade to\u00a0<i>p-unlimited<\/i><\/li>\n<li><i>p10<\/i>\u00a0upgrade to\u00a0<i>p-unlimited<\/i><\/li>\n<\/ul>\n<h2><span id=\"License_Update\" class=\"mw-headline\">License Update<\/span><\/h2>\n<p><a class=\"image\" href=\"https:\/\/wiki.mikrotik.com\/wiki\/File:CHR_Licence_02.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wiki.mikrotik.com\/images\/7\/74\/CHR_Licence_02.png\" alt=\"CHR Licence 02.png\" width=\"354\" height=\"166\" \/><\/a><\/p>\n<p>In &#8216;\/system license&#8217; menu router will indicate the time\u00a0<i>next-renewal-at<\/i>\u00a0when it will attempt to contact server located on licence.mikrotik.com. Communication attempts will be performed once an hour after the date on\u00a0<i>next-renewal-at<\/i>\u00a0and will not cease until the server responds with an error. If\u00a0<i>deadline-at<\/i>\u00a0date is reached without successfully contacting the account server, the router will consider that license has expired and will disallow further software updates. However, router will continue to work with the same license tier as before.<\/p>\n<h2><span id=\"Troubleshooting\" class=\"mw-headline\">Troubleshooting<\/span><\/h2>\n<h3><span id=\"Running_on_VMware_ESXi\" class=\"mw-headline\">Running on VMware ESXi<\/span><\/h3>\n<h6><span id=\"Changing_MTU\" class=\"mw-headline\">Changing MTU<\/span><\/h6>\n<p>VMware ESXi supports MTU of up to 9000 bytes. To get the benefit of that, you have to adjust your ESXi installation to allow a higher MTU. Virtual Ethernet interface added\u00a0<b>after<\/b>\u00a0the MTU change will be properly allowed by the ESXi server to pass jumbo frames. Interfaces added prior to MTU change on the ESXi server will be barred by the ESXi server (it will still report old MTU as maximum possible size). If you have this, you have to re-add interfaces to the virtual guests.<\/p>\n<p><b>Example.<\/b>\u00a0There are 2 interfaces added to the ESXi guest, auto-detected MTU on the interfaces show MTU size as it was at the time when the interface was added:<\/p>\n<pre>[admin@chr-vm] &gt; interface ethernet print \r\nFlags: X - disabled, R - running, S - slave \r\n #    NAME           MTU MAC-ADDRESS       ARP       \r\n 0 R  ether1        9000 00:0C:29:35:37:5C enabled   \r\n 1 R  ether2        1500 00:0C:29:35:37:66 enabled\r\n<\/pre>\n<h3><span id=\"Using_bridge_on_Linux\" class=\"mw-headline\">Using bridge on Linux<\/span><\/h3>\n<p>If Linux bridge supports IGMP snooping, and there are problems with IPv6 traffic it is required to disable that feature as it interacts with MLD packets (multicast) and is not passing them through.<\/p>\n<pre>echo -n 0 &gt; \/sys\/class\/net\/vmbr0\/bridge\/multicast_snooping\r\n<\/pre>\n<h3><span id=\"Packets_not_passing_from_guests\" class=\"mw-headline\">Packets not passing from guests<\/span><\/h3>\n<p>The problem: after configuring a software interface (VLAN, EoIP, bridge, etc.) on the guest CHR it stops passing data to the outside world beyond the router.<\/p>\n<p>The solution: check your VMS (Virtualization Management System) security settings, if other MAC addresses allowed to pass if packets with VLAN tags allowed to pass through. Adjust the security settings according to your needs like allowing MAC spoofing or certain MAC address range. For VLAN interfaces, it is usually possible to define allowed VLAN tags or VLAN tag range.<\/p>\n<h3><span id=\"Using_vlans_on_CHR_in_various_Hypervisors\" class=\"mw-headline\">Using vlans on CHR in various Hypervisors<\/span><\/h3>\n<p>In some of hypervisors before Vlans can be used on VMs they need to first be configured on hypervisor it self.<\/p>\n<h4><span id=\"ESXI\" class=\"mw-headline\">ESXI<\/span><\/h4>\n<p>Enable Promiscuous mode in port group or virtual switch that you will use for specific VM.<\/p>\n<p><i><b>ESX documentation:<\/b><\/i><\/p>\n<ul>\n<li><a class=\"external free\" href=\"https:\/\/kb.vmware.com\/kb\/1002934\" rel=\"nofollow\">https:\/\/kb.vmware.com\/kb\/1002934<\/a><\/li>\n<li><a class=\"external free\" href=\"https:\/\/kb.vmware.com\/kb\/1004099\" rel=\"nofollow\">https:\/\/kb.vmware.com\/kb\/1004099<\/a><\/li>\n<\/ul>\n<h4><span id=\"Hyper-V\" class=\"mw-headline\">Hyper-V<\/span><\/h4>\n<p><i><b>Hyper-V documentation:<\/b><\/i><\/p>\n<ul>\n<li><a class=\"external free\" href=\"https:\/\/technet.microsoft.com\/en-us\/library\/cc816585(v=ws.10).aspx#Anchor_2\" rel=\"nofollow\">https:\/\/technet.microsoft.com\/en-us\/library\/cc816585(v=ws.10).aspx#Anchor_2<\/a><\/li>\n<\/ul>\n<h4><span id=\"bhyve_hypervisor\" class=\"mw-headline\">bhyve hypervisor<\/span><\/h4>\n<p>It wont be possible to run CHR on this hypervisor. CHR cannot be run as paravirtualized platform.<\/p>\n<h4><span id=\"Linode\" class=\"mw-headline\">Linode<\/span><\/h4>\n<p>When creating multiple Linodes with the same disk size, new Linodes will have the same systemID. This will cause issues to get a Trial\/Paid license. To avoid this, run the command\u00a0<code>\/system license generate-new-id<\/code>\u00a0after the first boot and before you request a trial or paid license. This will make sure the ID is unique.<\/p>\n<p><i><b>Some useful articles:<\/b><\/i><\/p>\n<p>Specific vlan is untagged by nic interface:<\/p>\n<ul>\n<li><a class=\"external free\" href=\"https:\/\/blogs.msdn.microsoft.com\/adamfazio\/2008\/11\/14\/understanding-hyper-v-vlans\/\" rel=\"nofollow\">https:\/\/blogs.msdn.microsoft.com\/adamfazio\/2008\/11\/14\/understanding-hyper-v-vlans\/<\/a><\/li>\n<li><a class=\"external free\" href=\"http:\/\/www.aidanfinn.com\/?p=10164\" rel=\"nofollow\">http:\/\/www.aidanfinn.com\/?p=10164<\/a><\/li>\n<\/ul>\n<p>Allow passing other vlans:<\/p>\n<ul>\n<li><a class=\"external free\" href=\"https:\/\/social.technet.microsoft.com\/Forums\/windows\/en-US\/79d36d5b-c794-4502-8ed4-b7a4183b1891\/vlan-tags-and-hyperv-switches?forum=winserverhyperv\" rel=\"nofollow\">https:\/\/social.technet.microsoft.com\/Forums\/windows\/en-US\/79d36d5b-c794-4502-8ed4-b7a4183b1891\/vlan-tags-and-hyperv-switches?forum=winserverhyperv<\/a><\/li>\n<\/ul>\n<h2><span id=\"Guest_tools\" class=\"mw-headline\">Guest tools<\/span><\/h2>\n<h3><span id=\"VMWare\" class=\"mw-headline\">VMWare<\/span><\/h3>\n<h4><span id=\"Time_synchronization\" class=\"mw-headline\">Time synchronization<\/span><\/h4>\n<p>Must be enabled from GUI (&#8216;Synchronize guest time with host&#8217;). Backwards synchronization is disabled by default &#8211; if guest is ahead of host by more than ~5 seconds, synchronization is not performed<\/p>\n<h4><span id=\"Power_operations\" class=\"mw-headline\">Power operations<\/span><\/h4>\n<ul>\n<li><i>poweron<\/i>\u00a0and\u00a0<i>resume<\/i>\u00a0scripts are executed (if present and enabled) after poweron and resume operations respectively.<\/li>\n<li><i>poweroff<\/i>\u00a0and\u00a0<i>suspend<\/i>\u00a0scripts are executed before poweroff and suspend operations respectively.<\/li>\n<li>If scripts take longer than 30 seconds or contain errors, the operation fails<\/li>\n<li>In case of failure, retrying the same operation will ignore any errors and complete successfully<\/li>\n<li>Failed script output is saved to file (e. g. &#8216;poweroff-script.log&#8217;, &#8216;resume-script.log&#8217; etc)<\/li>\n<li>Scripts can be enabled\/disabled from hypervisor GUI (&#8216;run VMware Tools Scripts&#8217;) or by enbaling\/disabling scripts from console<\/li>\n<\/ul>\n<h4><span id=\"Quiescing.2Fbackup\" class=\"mw-headline\">Quiescing\/backup<\/span><\/h4>\n<p>Guest filesystem quiescing is performed only if requested.<\/p>\n<ul>\n<li><i>freeze<\/i>\u00a0script is executed before freezing the filesystem<\/li>\n<li><i>freeze-fail<\/i>\u00a0script is executed if hypervisor failed to prepare for snapshot or if\u00a0<i>freeze<\/i>\u00a0script failed<\/li>\n<li><i>thaw<\/i>\u00a0script is executed after snapshot has been taken<\/li>\n<li>Script run time is limited to 60 seconds<\/li>\n<li><i>freeze<\/i>\u00a0script timeouts and errors result in backup operation being aborted<\/li>\n<li>FAT32 disks are not quiesced<\/li>\n<li>Failed script output is saved to file (e. g. &#8216;freeze-script.log&#8217;, &#8216;freeze-fail-script.log&#8217;, &#8216;thaw-script.log&#8217;)<\/li>\n<\/ul>\n<h4><span id=\"Guest_info\" class=\"mw-headline\">Guest info<\/span><\/h4>\n<p>Networking, disk, and OS info is reported to hypervisor every 30 seconds (GuestStats (memory) are disabled by default, can be enabled by setting &#8216;guestinfo.disable-perfmon = &#8220;FALSE&#8221;&#8216; in VM config).<\/p>\n<ul>\n<li>The order, in which network interfaces are reported, can be controlled by setting &#8216;guestinfo.exclude-nics&#8217;, &#8216;guestinfo.primary-nics&#8217; and &#8216;guestinfo.low-priority-nics&#8217; options. Standard\u00a0<a class=\"external text\" href=\"http:\/\/www.tldp.org\/LDP\/GNU-Linux-Tools-Summary\/html\/x11655.htm\" rel=\"nofollow\">wildcard<\/a>\u00a0patterns can be used.<\/li>\n<\/ul>\n<h4><span id=\"Provisioning\" class=\"mw-headline\">Provisioning<\/span><\/h4>\n<p>Can use the\u00a0<a class=\"external text\" href=\"https:\/\/www.vmware.com\/support\/developer\/converter-sdk\/conv55_apireference\/vim.vm.guest.ProcessManager.html\" rel=\"nofollow\">ProcessManager<\/a>\u00a0from vim API to execute scripts. Python bindings are\u00a0<a class=\"external text\" href=\"https:\/\/github.com\/vmware\/pyvmomi\" rel=\"nofollow\">available<\/a><\/p>\n<ul>\n<li>Main data structure:\u00a0<a class=\"external text\" href=\"https:\/\/www.vmware.com\/support\/developer\/converter-sdk\/conv55_apireference\/vim.vm.guest.ProcessManager.ProgramSpec.html\" rel=\"nofollow\">GuestProgramSpec<\/a>\n<ul>\n<li>The\u00a0<i>workingDirectory<\/i>\u00a0and\u00a0<i>envVariables<\/i>\u00a0members are ignored<\/li>\n<li><i>programPath<\/i>\u00a0must be set to either &#8216;inline&#8217; or &#8216;import&#8217;<\/li>\n<li>If\u00a0<i>programPath<\/i>\u00a0is &#8216;<b>inline&#8217;<\/b>,\u00a0<i>arguments<\/i>\u00a0are interpreted as script text<\/li>\n<li>If\u00a0<i>programPath<\/i>\u00a0is &#8216;<b>import&#8217;<\/b>,\u00a0<i>arguments<\/i>\u00a0are interpreted as file path<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>After using\u00a0<i>GuestProgramSpec<\/i>\u00a0together with an instance of\u00a0<a class=\"external text\" href=\"https:\/\/www.vmware.com\/support\/developer\/converter-sdk\/conv55_apireference\/vim.vm.guest.GuestAuthentication.html\" rel=\"nofollow\">GuestAuthentication<\/a>\u00a0as arguments to\u00a0<a class=\"external text\" href=\"https:\/\/www.vmware.com\/support\/developer\/converter-sdk\/conv55_apireference\/vim.vm.guest.ProcessManager.html#startProgram\" rel=\"nofollow\">StartProgramInGuest<\/a>\u00a0unique\u00a0<i>JobID<\/i>\u00a0is obtained.<\/p>\n<p>Script progress can be tracked by using the\u00a0<a class=\"external text\" href=\"https:\/\/www.vmware.com\/support\/developer\/converter-sdk\/conv55_apireference\/vim.vm.guest.ProcessManager.html#listProcesses\" rel=\"nofollow\">ListProcessesInGuest<\/a>\u00a0command.\u00a0<i>ListProcessesInGuest<\/i>\u00a0accepts an array of job id&#8217;s; passing an empty array will report on all jobs started from API<\/p>\n<ul>\n<li><i>ListProcessesInGuest<\/i>\u00a0returns an array of\u00a0<a class=\"external text\" href=\"https:\/\/www.vmware.com\/support\/developer\/converter-sdk\/conv55_apireference\/vim.vm.guest.ProcessManager.ProcessInfo.html\" rel=\"nofollow\">GuestProcessInfo<\/a>\u00a0instances:\n<ul>\n<li><i>pid<\/i>\u00a0field is set to\u00a0<i>JobID<\/i><\/li>\n<li><i>endTime<\/i>\u00a0is only set after completion<\/li>\n<li><i>exitCode<\/i>\u00a0is set to 0 on success and -1 on error<\/li>\n<li><i>name<\/i>\u00a0is set to &#8216;inline&#8217; or &#8216;import&#8217; (same as\u00a0<i>programPath<\/i>\u00a0in\u00a0<i>GuestProgramSpec<\/i>)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Information about completed jobs is kept around for ~1 minute, or untill\u00a0<i>ListProcessesInGuest<\/i>\u00a0(with the corresponding\u00a0<i>JobID<\/i>) is called. If the script fails, a file named &#8216;vix_job_$JobID$ .txt&#8217; containing the script output is created. Script run time is limited to 120 seconds and script output is not saved on timeout,<\/p>\n<ul>\n<li>The\u00a0<a class=\"external text\" href=\"https:\/\/www.vmware.com\/pdf\/vix160_vmrun_command.pdf\" rel=\"nofollow\">vmrun<\/a>\u00a0command\u00a0<i>runScriptInGuest<\/i>\u00a0can also be used<\/li>\n<li>The\u00a0<a class=\"external text\" href=\"https:\/\/code.vmware.com\/doc\/preview?id=5975#\/doc\/Overview.html\" rel=\"nofollow\">PowerCLI<\/a>\u00a0cmdlet\u00a0<a class=\"external text\" href=\"https:\/\/code.vmware.com\/doc\/preview?id=5975#\/doc\/Invoke-VMScript.html\" rel=\"nofollow\">Invoke-VMScript<\/a>\u00a0is not supported<\/li>\n<li>Host\/guest file transfer is not supported<\/li>\n<\/ul>\n<h5><span id=\"Python_example\" class=\"mw-headline\">Python example<\/span><\/h5>\n<pre>#!\/usr\/bin\/env python\r\n# -*- coding: utf-8 -*-\r\n\r\nimport sys,time\r\nfrom pyVim import connect\r\nfrom pyVmomi import vmodl,vim\r\n\r\n\r\ndef runInline(content,vm,creds,source):\r\n    ''' Execute script source on vm '''\r\n    if isinstance(source, list):\r\n        source = '\\n'.join(source)\r\n    ps = vim.vm.guest.ProcessManager.ProgramSpec(\r\n                programPath = 'console',\r\n                arguments = source\r\n        )\r\n    return content.guestOperationsManager.processManager.StartProgramInGuest(vm,creds,ps)\r\n\r\ndef runFromFile(content,vm,creds,fileName):\r\n    ''' Execute script file located on CHR '''\r\n    ps = vim.vm.guest.ProcessManager.ProgramSpec(\r\n                programPath = 'import',\r\n                arguments = fileName\r\n    )\r\n    return content.guestOperationsManager.processManager.StartProgramInGuest(vm,creds,ps)\r\n\r\n\r\ndef findDatastore(content,name):\r\n    sessionManager = content.sessionManager\r\n\r\n    dcenterObjView = content.viewManager.CreateContainerView(content.rootFolder, [vim.Datacenter], True)\r\n\r\n    datacenter = None\r\n    datastore = None\r\n    for dc in dcenterObjView.view:\r\n        dstoreObjView = content.viewManager.CreateContainerView(dc, [vim.Datastore], True)\r\n        for ds in dstoreObjView:\r\n            if ds.info.name == name:\r\n                datacenter = dc\r\n                datastore = ds\r\n                break\r\n        dstoreObjView.Destroy()\r\n\r\n    dcenterObjView.Destroy()\r\n\r\n    return datacenter,datastore\r\n\r\ndef _FAILURE(s,*a):\r\n    print(s.format(*a))\r\n    sys.exit(-1)\r\n\r\n#------------------------------------------------------------------------------#\r\n\r\nif __name__ == '__main__':\r\n    host = sys.argv[1] # ip or something\r\n    user = 'root'\r\n    pwd = 'MikroTik'\r\n    vmName = 'chr-test'\r\n    dataStoreName = 'datastore1'\r\n\r\n\r\n\r\n    service = connect.SmartConnectNoSSL(host=host,user=user,pwd=pwd)\r\n    if not service:\r\n        _FAILURE(\"Could not connect to the specified host using specified username and password\")\r\n\r\n    content = service.RetrieveContent()\r\n\r\n\r\n    #---------------------------------------------------------------------------\r\n    # Find datacenter and datastore\r\n\r\n\r\n    datacenter,datastore = findDatastore(content,dataStoreName)\r\n\r\n    if not datacenter or not datastore:\r\n        connect.Disconnect(service)\r\n        _FAILURE('Could not find datastore \\'{}\\'',dataStorename)\r\n\r\n\r\n    #---------------------------------------------------------------------------\r\n    # Locate vm\r\n\r\n\r\n    vmxPath = '[{0}] {1}\/{1}.vmx'.format(dataStoreName, vmName)\r\n    vm = content.searchIndex.FindByDatastorePath(datacenter, vmxPath)\r\n\r\n    if not vm:\r\n        connect.Disconnect(service)\r\n        _FAILURE(\"Could not locate vm\")\r\n\r\n\r\n    #---------------------------------------------------------------------------\r\n    # Setup credentials from user name and pasword\r\n\r\n    creds = vim.vm.guest.NamePasswordAuthentication(username = 'admin', password = '')\r\n\r\n\r\n    #---------------------------------------------------------------------------\r\n    # Run script\r\n\r\n    pm = content.guestOperationsManager.processManager\r\n\r\n    try:\r\n        # Run script\r\n        src = [':ip address add address=192.168.0.1\/24 interface=ether1;']\r\n        jobID = runInline(content, vm, creds, src)\r\n\r\n        # Or run file (from FTP root)\r\n        # jobID = runFromFile(content,vm,creds, 'scripts\/provision.rsc')\r\n\r\n\r\n        #---------------------------------------------------------------------------\r\n        # Wait for job to finish\r\n\r\n        pm = content.guestOperationsManager.processManager\r\n        jobInfo = pm.ListProcessesInGuest(vm, creds, [jobID])[0]\r\n        while jobInfo.endTime is None:\r\n            time.sleep(1.0)\r\n            jobInfo = pm.ListProcessesInGuest(vm, creds, [jobID])[0]\r\n\r\n        if jobInfo.exitCode\u00a0!= 0:\r\n            _FAILURE('Script failed!')\r\n    except:\r\n        raise\r\n    else:\r\n        connect.Disconnect(service)\r\n\r\n<\/pre>\n<h3><span id=\"Xen\" class=\"mw-headline\">Xen<\/span><\/h3>\n<p>Network, disk, memory and OS info is reported to hypervisor every 30 seconds<\/p>\n<ul>\n<li>On older hosts (pre 21.06.2017) only the first ipv4 address assigned to interface is visible<\/li>\n<\/ul>\n<h4><span id=\"Provisioning_2\" class=\"mw-headline\">Provisioning<\/span><\/h4>\n<p>Base-64 encoded strings written to (domain local) xenstore path (&#8216;vm-data\/provision\/script&#8217;) are decoded and interpreted a script-text. Status (&#8216;ready&#8217;, &#8216;running&#8217;, &#8216;error&#8217;) is reported in &#8216;vm-data\/provision\/script\/status&#8217;. Scripts are accepted only if &#8216;status&#8217;\u00a0!= &#8216;running&#8217;. Base 64 encoded script output (if any) is written to &#8216;vm-data\/provision\/script\/otuput&#8217;.<\/p>\n<ul>\n<li>When creating a VM scripts can be provided by using\u00a0<a class=\"external text\" href=\"http:\/\/xapi-project.github.io\/xen-api\/classes\/vm.html\" rel=\"nofollow\">xenapi<\/a>\u00a0(<i>VM.add_to_xenstore_data<\/i>)<\/li>\n<\/ul>\n<h3><span id=\"KVM\" class=\"mw-headline\">KVM<\/span><\/h3>\n<p><a class=\"external text\" href=\"https:\/\/qemu.weilnetz.de\/doc\/qemu-ga-ref.html\" rel=\"nofollow\">QEMU guest agent<\/a>\u00a0is available. Supported agent commands can be retrieved by using\u00a0<a class=\"external text\" href=\"https:\/\/qemu.weilnetz.de\/doc\/qemu-ga-ref.html#index-guest_002dinfo\" rel=\"nofollow\">guest-info<\/a>\u00a0command. Host-guest file transfer can be performed by using\u00a0<a class=\"external text\" href=\"https:\/\/qemu.weilnetz.de\/doc\/qemu-ga-ref.html#index-guest_002dfile_002dopen\" rel=\"nofollow\">guest-file-*<\/a>\u00a0commands. Guest networking information can be retrieved by using the\u00a0<a class=\"external text\" href=\"https:\/\/qemu.weilnetz.de\/doc\/qemu-ga-ref.html#index-guest_002dnetwork_002dget_002dinterfaces\" rel=\"nofollow\">guest-network-get-interfaces<\/a>\u00a0command.<\/p>\n<ul>\n<li>Scripts can be executed by using the\u00a0<a class=\"external text\" href=\"https:\/\/qemu.weilnetz.de\/doc\/qemu-ga-ref.html#index-guest_002dexec\" rel=\"nofollow\">guest-exec<\/a>\u00a0command together with the\u00a0<a class=\"external text\" href=\"https:\/\/qemu.weilnetz.de\/doc\/qemu-ga-ref.html#index-GuestExec\" rel=\"nofollow\">GuestExec<\/a>\u00a0data structure:\n<ul>\n<li>If the\u00a0<i>path<\/i>\u00a0member is provided, the corresponding file is executed<\/li>\n<li>If the\u00a0<i>path<\/i>\u00a0member is not set and\u00a0<i>input-data<\/i>\u00a0member is provided,\u00a0<i>input-data<\/i>\u00a0value is used as script input<\/li>\n<li>If\u00a0<i>capture-output<\/i>\u00a0is set, script output is reported back<\/li>\n<li><i>args<\/i>\u00a0and\u00a0<i>env<\/i>\u00a0members are not used<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Script job progress can be monitored with\u00a0<a class=\"external text\" href=\"https:\/\/qemu.weilnetz.de\/doc\/qemu-ga-ref.html#index-guest_002dexec_002dstatus\" rel=\"nofollow\">guest-exec-status<\/a>\u00a0command. The\u00a0<a class=\"external text\" href=\"https:\/\/qemu.weilnetz.de\/doc\/qemu-ga-ref.html#index-GuestExecStatus\" rel=\"nofollow\">GuestExecStatus<\/a>\u00a0data structure is populated as follows:\n<ul>\n<li>On success\u00a0<i>exitcode<\/i>\u00a0member is set to 0<\/li>\n<li>If the script timed out\u00a0<i>exitcode<\/i>\u00a0is set to 1<\/li>\n<li>If the script contained errors\u00a0<i>exitcode<\/i>\u00a0is set to -1<\/li>\n<li><i>signal<\/i>\u00a0member is not set<\/li>\n<li>The\u00a0<i>err-data<\/i>\u00a0member is not used<\/li>\n<li>If\u00a0<i>capture-output<\/i>\u00a0was true, Base64 encoded script output is stored in\u00a0<i>out-data<\/i><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li><a class=\"external text\" href=\"https:\/\/wiki.libvirt.org\/page\/Qemu_guest_agent\" rel=\"nofollow\">Enabling guest agent in libvirt<\/a><\/li>\n<li>An additional agent channel (&#8216;chr.provision_channel&#8217;) is also available<\/li>\n<\/ul>\n<h4><span id=\"Proxmox\" class=\"mw-headline\">Proxmox<\/span><\/h4>\n<p>Some agent commands can be issued by using\u00a0<a class=\"external text\" href=\"https:\/\/pve.proxmox.com\/pve-docs\/api-viewer\/index.html\" rel=\"nofollow\">Proxmox REST api<\/a>. Guest filesystem quiescing is automatically performed when taking a snapshot<\/p>\n<ul>\n<li><a class=\"external text\" href=\"https:\/\/pve.proxmox.com\/wiki\/Qemu-guest-agent\" rel=\"nofollow\">Enabling guest agent on proxmox<\/a><\/li>\n<\/ul>\n<ul>\n<li>Enabling &#8216;chr.provision-agent&#8217; for remote access on port 1234<\/li>\n<\/ul>\n<p>In host shell:<\/p>\n<pre>vmid=256\r\nhostip=192.168.0.1\r\nportnum=1234\r\nqm set $vmid --args \"-chardev 'socket,host=$hostip,port=$portnum,id=chr-agent,server,nowait' -device 'virtio-serial,bus=pci.0,addr=0x9' -device 'virtserialport,chardev=chr-agent,name=chr.provision_agent'\"\r\n<\/pre>\n<ul>\n<li>Disabling &#8216;chr.provision-agent&#8217;<\/li>\n<\/ul>\n<p>In host shell:<\/p>\n<pre>vmid=256\r\nqm set $vmid --delete args\r\n<\/pre>\n<ul>\n<li>Providing remote access to default agent on port 1234<\/li>\n<\/ul>\n<p>In host shell:<\/p>\n<pre>vmid=256\r\nportnum=1234\r\nsocat TCP-LISTEN:$portnum,reuseaddr,fork UNIX-CLIENT:\/run\/qemu-server\/$vmid.qga\r\n<\/pre>\n<h4><span id=\"Guest_agent_python_example\" class=\"mw-headline\">Guest agent python example<\/span><\/h4>\n<pre>import os,time,base64,json,socket,select,errno\r\n\r\nclass GuestAgent(object):\r\n    '''\r\n        Qemu guest agent interface\r\n        runScript and runFile commands are tailored for ROS agent implementation\r\n        Transport provided by derived classes (transact method)\r\n    '''\r\n\r\n    def __init__(self,**kwargs):\r\n        # Due to file contents being passed as base64 inside json:\r\n        #  - large chunk sizes may slow down guest-side parsing.\r\n        #  - small chunk sizes result in additional message fragmentation overhead.\r\n        # Default value is a guestimate.\r\n        self.__chunkSize = kwargs.get('chunkSize', 4096)\r\n\r\n    def _qmpError(self,cls,msg):\r\n        ''' Generic callback to log qmp errors before (optionally) raising an exception '''\r\n        print(cls)\r\n        for line in msg.split('\\n'):\r\n            print(line)\r\n        # raise RuntimeError()\r\n\r\n    def _error(self,msg,*a):\r\n        ''' Generic callback to misc errors before (optionally) raising an exception '''\r\n        print(msg.format(*a))\r\n        # raise RuntimeError()\r\n\r\n    def _info(self,msg,*a):\r\n        ''' Generic callback to log info '''\r\n        print(msg.format(*a))\r\n\r\n    def _monitorJob(self,pid):\r\n        ''' Block untill script job completes, echo output. Returns None on failure '''\r\n        ret = self.transact('guest-exec-status',{'pid':pid})\r\n        if ret is None:\r\n            return None\r\n\r\n        while not bool(ret['exited']):\r\n            time.sleep(1)\r\n            ret = self.transact('guest-exec-status',{'pid':pid})\r\n            if ret is None:\r\n                return None\r\n\r\n        # err-data is never sent\r\n        out = []\r\n        if 'out-data' in ret.keys():\r\n            out = base64.b64decode(ret['out-data']).decode('utf-8').split('\\n')\r\n            if not out[-1]:\r\n                out = out[:-1]\r\n\r\n        exitcode = int(ret['exitcode'])\r\n        return exitcode, out\r\n\r\n    def putFile(self,src,dst):\r\n        ''' Upload file '''\r\n        src = os.path.expanduser(src)\r\n        if not os.path.exists(src) or not os.path.isfile(src):\r\n            self._error('File does not exist: \\'{}\\'', src)\r\n            return None\r\n\r\n        ret = self.transact('guest-file-open', {'path':dst,'mode':'w'})\r\n        if ret is None:\r\n            return None\r\n\r\n        handle = int(ret)\r\n\r\n        file = open(src, 'rb')\r\n        for chunk in iter(lambda\u00a0: file.read(self.__chunkSize), b''):\r\n            count = len(chunk)\r\n            chunk = base64.b64encode(chunk).decode('ascii')\r\n\r\n            ret = self.transact('guest-file-write',{'handle':handle,'buf-b64':chunk,'count':count})\r\n            if ret is None:\r\n                return None\r\n        self.transact('guest-file-flush',{'handle':handle})\r\n        ret = self.transact('guest-file-close',{'handle':handle})\r\n        return True\r\n\r\n    def getFile(self,src,dst):\r\n        ''' Download file '''\r\n        dst = os.path.expanduser(dst)\r\n\r\n        ret = self.transact('guest-file-open',{'path':src,'mode':'rb'})\r\n        if ret is None:\r\n            return None\r\n\r\n        handle = int(ret)\r\n        data = ''\r\n        size = 0\r\n\r\n        while True:\r\n            ret = self.transact('guest-file-read',{'handle':handle,'count':self.__chunkSize})\r\n            if ret is None:\r\n                return None\r\n            data += ret['buf-b64']\r\n            size += int(ret['count'])\r\n            if bool(ret['eof']):\r\n                break\r\n\r\n        ret = self.transact('guest-file-close',{'handle':handle})\r\n        data = base64.b64decode(data.encode('ascii'))\r\n        with open(dst,'wb') as f:\r\n            f.write(data)\r\n        return True\r\n\r\n    def runFile(self,fileName):\r\n        ''' Execute file (on guest) as script '''\r\n        ret = self.transact('guest-exec',{'path':fileName, 'capture-output':True})\r\n        if ret is None:\r\n            return None\r\n\r\n        pid = ret['pid']\r\n        return self._monitorJob(pid)\r\n\r\n    def runSource(self,cmd):\r\n        ''' Execute script '''\r\n        if isinstance(cmd,list):\r\n            cmd = '\\n'.join(cmd)\r\n        cmd += '\\n'\r\n        cmd = base64.b64encode(cmd.encode('utf-8')).decode('ascii')\r\n\r\n        ret = self.transact('guest-exec',{'input-data':cmd, 'capture-output':True})\r\n        if ret is None:\r\n            return None\r\n\r\n        pid = ret['pid']\r\n        return self._monitorJob(pid)\r\n\r\n    def shutdown(self,mode='powerdown'):\r\n        '''\r\n            Execut shutdown command\r\n            mode == 'reboot' - reboot guest\r\n            mode == 'shutdown' or mode == 'halt' - shutdown guest\r\n         '''\r\n        ret = self.transact('guest-shutdown',{'mode':mode})\r\n        return ret\r\n\r\nclass SocketAgent(GuestAgent):\r\n    '''\r\n        GuestAgent using unix\/tcp sockets for communication.\r\n    '''\r\n    def __init__(self):\r\n        GuestAgent.__init__(self,chunkSize= 32 * 65536)\r\n\r\n    @staticmethod\r\n    def unix(dev):\r\n        ''' Connect using unix socket '''\r\n        self = SocketAgent()\r\n        self.__af = socket.AF_UNIX\r\n        self.__args = dev\r\n        self.__wait = False\r\n        return self\r\n\r\n    @staticmethod\r\n    def tcp(ip,port,wait = True):\r\n        ''' Connect using tcp socket '''\r\n        self = SocketAgent()\r\n        self.__af = socket.AF_INET\r\n        self.__args = (ip,port)\r\n        self.__wait = wait\r\n        return self\r\n\r\n    def __enter__(self):\r\n        self._sock = socket.socket(self.__af, socket.SOCK_STREAM)\r\n        if self.__wait:\r\n            self._info('Waiting for guest ...')\r\n            # Wait for hyper to create channel\r\n            while True:\r\n                try:\r\n                    self._sock.connect(self.__args)\r\n                    break\r\n                except socket.error as e:\r\n                    if e.errno == errno.EHOSTUNREACH or e.errno == errno.ECONNREFUSED:\r\n                        time.sleep(1)\r\n                    else:\r\n                        self._sock.close()\r\n                        raise\r\n\r\n            #Wait for guest agent to initialize and sync\r\n            while True:\r\n                import random\r\n                key = random.randint(0, 0xffffffff)\r\n                msg = json.dumps({'execute':'guest-sync-delimited','arguments':{'id':key}},separators=(',',':'),sort_keys=True)\r\n                self._sock.send(msg.encode('ascii'))\r\n\r\n                self._sock.setblocking(0)\r\n                response = b''\r\n                if (select.select([self._sock],[],[])[0]):\r\n                    response += self._sock.recv(65536)\r\n                else:\r\n                    raise RuntimeError()\r\n                self._sock.setblocking(1)\r\n\r\n                sentinel = b'\\xff'\r\n                response = response.split(sentinel)[-1]\r\n                if not response:\r\n                    time.sleep(3)\r\n                    continue\r\n                response = json.loads(response.decode('utf-8').strip())\r\n                if 'return' in response.keys():\r\n                    if int(response['return']) == key:\r\n                        break\r\n                time.sleep(3)\r\n        else:\r\n            self._sock.connect(self.__args)\r\n\r\n        return self\r\n\r\n    def __exit__(self,*a):\r\n        self._sock.close()\r\n\r\n    def transact(self,cmd,args={}):\r\n        ''' Exchange a single command with guest agent '''\r\n        timeout = 2\r\n        msg = json.dumps({'execute':cmd,'arguments':args},separators=(',',':'),sort_keys=True)\r\n        self._sock.send(msg.encode('ascii'))\r\n        self._sock.setblocking(0)\r\n        response = b''\r\n        if (select.select([self._sock],[],[],timeout)[0]):\r\n            response += self._sock.recv(65536)\r\n        self._sock.setblocking(1)\r\n        if not response:\r\n            response = None\r\n        else:\r\n            if response[0] == 255: # sync\r\n                response = response[1:]\r\n            response = json.loads(response.decode('utf-8').strip())\r\n            if 'error' in response.keys():\r\n                self._qmpError(response['error']['class'],response['error']['desc'])\r\n                response = None\r\n            elif 'return' in response:\r\n                response = response['return']\r\n        return response\r\n\r\n#-------------------------------------------------------------------------------\r\n\r\nif __name__ == '__main__':\r\n    script = [':log info \"hello world\";']\r\n\r\n    ip = '192.168.0.1'\r\n    port = 1234\r\n\r\n    # can also use unix sockets\r\n    #with SocketAgent.unix('\/dev\/something') as agent:\r\n\r\n    with SocketAgent.tcp(ip, port) as agent:\r\n        ret,out = agent.runSource(script)\r\n        print('ret = {}'.format(ret))\r\n        for line in out:\r\n            print(line)<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Cloud Hosted Router Cloud Hosted Router (CHR) is a RouterOS version intended for running as a virtual machine. It supports the x86 64-bit architecture and can be used on most of the popular hypervisors such as VMWare, Hyper-V, VirtualBox, KVM and others. CHR has full RouterOS features enabled by default but has a different licensing [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[730,1,42,415,495],"tags":[1189,1188,297],"class_list":["post-4471","post","type-post","status-publish","format-standard","hentry","category-clusterweb","category-viazap","category-leitura-recomendada","category-mikrotik-2","category-profissional-de-ti","tag-chr","tag-manual","tag-mikrotik"],"_links":{"self":[{"href":"https:\/\/blog.clusterweb.com.br\/index.php?rest_route=\/wp\/v2\/posts\/4471","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.clusterweb.com.br\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.clusterweb.com.br\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.clusterweb.com.br\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.clusterweb.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4471"}],"version-history":[{"count":1,"href":"https:\/\/blog.clusterweb.com.br\/index.php?rest_route=\/wp\/v2\/posts\/4471\/revisions"}],"predecessor-version":[{"id":4472,"href":"https:\/\/blog.clusterweb.com.br\/index.php?rest_route=\/wp\/v2\/posts\/4471\/revisions\/4472"}],"wp:attachment":[{"href":"https:\/\/blog.clusterweb.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4471"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.clusterweb.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4471"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.clusterweb.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4471"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}