Implementation of PTP support in SysInv and Puppet
Precision Time Protocol (PTP) support is added to StarlingX. Controller Nodes act as a Boundary Clocks and synchronize its clock to a Grand Master clock via OAM interface. Serve as a time source to other nodes. Compute/Storage Nodes are Slave Clocks (Ordinary Clocks) and synchronize its clock to a Controller Nodes via Management interface. API is provided to enable and configure PTP as follows: "system ptp-modify --enabled=<true/false>" is there to turn it on/off. Note that NTP must be disabled first before turning PTP service on. "system ptp-modify --mode=<hardware/software/legacy>" selects time stamping. Hardware timestamping is the default option and achieves best time syncing. "system ptp-modify --transport=<l2,udp>" switches between IEEE 802.3 or UDP network transport for PTP messaging. L2 is the default transport. "system ptp-modify --mechanism=<e2e,p2p>" sets the PTP delay mechanism. Options: default delay request-response (E2E) mechanism and peer delay (P2P). "system ptp-show" displays the current status of PTP service. Change-Id: I6bb6162903c70a49b55f4fc02b44e5ca8a66d5a5 Story: 2002935 Task: 22923 Signed-off-by: Alex Kozyrev <alex.kozyrev@windriver.com>
This commit is contained in:
parent
5354843163
commit
3a42372b64
|
@ -20,6 +20,7 @@ include ::platform::fstab
|
||||||
include ::platform::password
|
include ::platform::password
|
||||||
include ::platform::ldap::client
|
include ::platform::ldap::client
|
||||||
include ::platform::ntp::client
|
include ::platform::ntp::client
|
||||||
|
include ::platform::ptp
|
||||||
include ::platform::lldp
|
include ::platform::lldp
|
||||||
include ::platform::patching
|
include ::platform::patching
|
||||||
include ::platform::remotelogging
|
include ::platform::remotelogging
|
||||||
|
|
|
@ -25,6 +25,7 @@ include ::platform::ldap::server
|
||||||
include ::platform::ldap::client
|
include ::platform::ldap::client
|
||||||
include ::platform::password
|
include ::platform::password
|
||||||
include ::platform::ntp::server
|
include ::platform::ntp::server
|
||||||
|
include ::platform::ptp
|
||||||
include ::platform::lldp
|
include ::platform::lldp
|
||||||
include ::platform::amqp::rabbitmq
|
include ::platform::amqp::rabbitmq
|
||||||
include ::platform::postgresql::server
|
include ::platform::postgresql::server
|
||||||
|
|
|
@ -18,6 +18,7 @@ include ::platform::fstab
|
||||||
include ::platform::password
|
include ::platform::password
|
||||||
include ::platform::ldap::client
|
include ::platform::ldap::client
|
||||||
include ::platform::ntp::client
|
include ::platform::ntp::client
|
||||||
|
include ::platform::ptp
|
||||||
include ::platform::lldp
|
include ::platform::lldp
|
||||||
include ::platform::patching
|
include ::platform::patching
|
||||||
include ::platform::remotelogging
|
include ::platform::remotelogging
|
||||||
|
|
|
@ -211,6 +211,13 @@ define platform::firewall::services (
|
||||||
provider => $provider,
|
provider => $provider,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firewall { "203 platform accept ptp ${version}":
|
||||||
|
proto => 'udp',
|
||||||
|
dport => [319, 320],
|
||||||
|
action => 'accept',
|
||||||
|
provider => $provider,
|
||||||
|
}
|
||||||
|
|
||||||
# allow IGMP Query traffic if IGMP Snooping is
|
# allow IGMP Query traffic if IGMP Snooping is
|
||||||
# enabled on the TOR switch
|
# enabled on the TOR switch
|
||||||
firewall { "204 platform accept igmp ${version}":
|
firewall { "204 platform accept igmp ${version}":
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
class platform::ptp (
|
||||||
|
$enabled = false,
|
||||||
|
$mode = 'hardware',
|
||||||
|
$transport = 'l2',
|
||||||
|
$mechanism = 'e2e',
|
||||||
|
) {
|
||||||
|
if $::platform::params::personality == 'controller' {
|
||||||
|
include ::platform::network::oam::params
|
||||||
|
$oam_interface = $::platform::network::oam::params::interface_name
|
||||||
|
$slave_interface = split($oam_interface, '[.]')[0]
|
||||||
|
$slave_subnet = $::platform::network::oam::params::subnet_version
|
||||||
|
include ::platform::network::mgmt::params
|
||||||
|
$mgmt_interface = $::platform::network::mgmt::params::interface_name
|
||||||
|
$master_interface = split($mgmt_interface, '[.]')[0]
|
||||||
|
$master_subnet = $::platform::network::mgmt::params::subnet_version
|
||||||
|
if $::platform::params::system_type == 'All-in-one' {
|
||||||
|
$slave_only = true
|
||||||
|
} else {
|
||||||
|
$slave_only = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
include ::platform::network::mgmt::params
|
||||||
|
$mgmt_interface = $::platform::network::mgmt::params::interface_name
|
||||||
|
$slave_interface = split($mgmt_interface, '[.]')[0]
|
||||||
|
$slave_subnet = $::platform::network::mgmt::params::subnet_version
|
||||||
|
$slave_only = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if $enabled {
|
||||||
|
$pmon_ensure = 'link'
|
||||||
|
} else {
|
||||||
|
$pmon_ensure = 'absent'
|
||||||
|
}
|
||||||
|
|
||||||
|
file { 'ptp4l_config':
|
||||||
|
ensure => file,
|
||||||
|
path => '/etc/ptp4l.conf',
|
||||||
|
mode => '0644',
|
||||||
|
content => template('platform/ptp4l.conf.erb'),
|
||||||
|
} ->
|
||||||
|
file { 'ptp4l_service':
|
||||||
|
ensure => file,
|
||||||
|
path => '/usr/lib/systemd/system/ptp4l.service',
|
||||||
|
mode => '0644',
|
||||||
|
content => template('platform/ptp4l.service.erb'),
|
||||||
|
} ->
|
||||||
|
file { 'ptp4l_sysconfig':
|
||||||
|
ensure => file,
|
||||||
|
path => '/etc/sysconfig/ptp4l',
|
||||||
|
mode => '0644',
|
||||||
|
content => template('platform/ptp4l.erb'),
|
||||||
|
} ->
|
||||||
|
file { 'phc2sys_service':
|
||||||
|
ensure => file,
|
||||||
|
path => '/usr/lib/systemd/system/phc2sys.service',
|
||||||
|
mode => '0644',
|
||||||
|
content => template('platform/phc2sys.service.erb'),
|
||||||
|
} ->
|
||||||
|
file { 'phc2sys_sysconfig':
|
||||||
|
ensure => file,
|
||||||
|
path => '/etc/sysconfig/phc2sys',
|
||||||
|
mode => '0644',
|
||||||
|
content => template('platform/phc2sys.erb'),
|
||||||
|
} ->
|
||||||
|
file { 'ptp4l_pmon':
|
||||||
|
ensure => file,
|
||||||
|
path => '/etc/ptp4l.pmon.conf',
|
||||||
|
mode => '0644',
|
||||||
|
content => template('platform/ptp4l.pmon.conf.erb'),
|
||||||
|
} ->
|
||||||
|
file { 'phc2sys_pmon':
|
||||||
|
ensure => file,
|
||||||
|
path => '/etc/phc2sys.pmon.conf',
|
||||||
|
mode => '0644',
|
||||||
|
content => template('platform/phc2sys.pmon.conf.erb'),
|
||||||
|
} ->
|
||||||
|
file { 'ptp4l_pmon_link':
|
||||||
|
ensure => $pmon_ensure,
|
||||||
|
path => '/etc/pmon.d/ptp4l.conf',
|
||||||
|
target => '/etc/ptp4l.pmon.conf',
|
||||||
|
owner => 'root',
|
||||||
|
group => 'root',
|
||||||
|
mode => '0600',
|
||||||
|
} ->
|
||||||
|
file { 'phc2sys_pmon_link':
|
||||||
|
ensure => $pmon_ensure,
|
||||||
|
path => '/etc/pmon.d/phc2sys.conf',
|
||||||
|
target => '/etc/phc2sys.pmon.conf',
|
||||||
|
owner => 'root',
|
||||||
|
group => 'root',
|
||||||
|
mode => '0600',
|
||||||
|
} ->
|
||||||
|
exec { 'systemctl-daemon-reload':
|
||||||
|
command => '/usr/bin/systemctl daemon-reload',
|
||||||
|
}
|
||||||
|
|
||||||
|
if $enabled {
|
||||||
|
exec { 'enable-ptp4l':
|
||||||
|
command => '/usr/bin/systemctl enable ptp4l.service',
|
||||||
|
require => Exec['systemctl-daemon-reload'],
|
||||||
|
} ->
|
||||||
|
exec { 'enable-phc2sys':
|
||||||
|
command => '/usr/bin/systemctl enable phc2sys.service',
|
||||||
|
} ->
|
||||||
|
service { 'ptp4l':
|
||||||
|
ensure => 'running',
|
||||||
|
enable => true,
|
||||||
|
name => 'ptp4l',
|
||||||
|
hasstatus => true,
|
||||||
|
hasrestart => true,
|
||||||
|
} ->
|
||||||
|
service { 'phc2sys':
|
||||||
|
ensure => 'running',
|
||||||
|
enable => true,
|
||||||
|
name => 'phc2sys',
|
||||||
|
hasstatus => true,
|
||||||
|
hasrestart => true,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
exec { 'disable-ptp4l':
|
||||||
|
command => '/usr/bin/systemctl disable ptp4l.service',
|
||||||
|
require => Exec['systemctl-daemon-reload'],
|
||||||
|
} ->
|
||||||
|
exec { 'disable-phc2sys':
|
||||||
|
command => '/usr/bin/systemctl disable phc2sys.service',
|
||||||
|
}
|
||||||
|
exec { 'stop-ptp4l':
|
||||||
|
command => '/usr/bin/systemctl stop ptp4l.service',
|
||||||
|
} ->
|
||||||
|
exec { 'stop-phc2sys':
|
||||||
|
command => '/usr/bin/systemctl stop phc2sys.service',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ restrict -6 default kod nomodify notrap nopeer noquery
|
||||||
restrict 127.0.0.1
|
restrict 127.0.0.1
|
||||||
restrict -6 ::1
|
restrict -6 ::1
|
||||||
|
|
||||||
<%- if @enabled == true -%>
|
<%- if scope['platform::ntp::enabled'] == true -%>
|
||||||
# Use orphan mode if external servers are unavailable (or not configured)
|
# Use orphan mode if external servers are unavailable (or not configured)
|
||||||
tos orphan 12
|
tos orphan 12
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ restrict -6 default kod nomodify notrap nopeer noquery
|
||||||
restrict 127.0.0.1
|
restrict 127.0.0.1
|
||||||
restrict -6 ::1
|
restrict -6 ::1
|
||||||
|
|
||||||
<%- if @enabled == true -%>
|
<%- if scope['platform::ntp::enabled'] == true -%>
|
||||||
# orphan - Use orphan mode if external servers are unavailable (or not configured).
|
# orphan - Use orphan mode if external servers are unavailable (or not configured).
|
||||||
# minclock - Prevent clustering algorithm from casting out any outlyers by setting
|
# minclock - Prevent clustering algorithm from casting out any outlyers by setting
|
||||||
# minclock to the maximum number of ntp servers that can be configured
|
# minclock to the maximum number of ntp servers that can be configured
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
OPTIONS="-a -r -E linreg -u 60"
|
|
@ -0,0 +1,19 @@
|
||||||
|
[process]
|
||||||
|
process = phc2sys
|
||||||
|
service = phc2sys
|
||||||
|
pidfile = /var/run/phc2sys.pid
|
||||||
|
style = lsb ; ocf or lsb
|
||||||
|
severity = minor ; minor, major, critical
|
||||||
|
restarts = 0 ; restart retries before error assertion
|
||||||
|
interval = 10 ; number of seconds to wait between restarts
|
||||||
|
debounce = 10 ; number of seconds that a process needs to remain
|
||||||
|
; running before degrade is removed and retry count
|
||||||
|
; is cleared.
|
||||||
|
; These settings will generate a log only without attempting to restart
|
||||||
|
; pmond will put the process into an ignore state after failure.
|
||||||
|
|
||||||
|
startuptime = 180 ; Seconds to wait after process start before starting the debounce monitor
|
||||||
|
mode = passive ; Monitoring mode: passive (default) or active
|
||||||
|
; passive: process death monitoring (default: always)
|
||||||
|
; active : heartbeat monitoring, i.e. request / response messaging
|
||||||
|
; ignore : do not monitor or stop monitoring
|
|
@ -0,0 +1,13 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Synchronize system clock or PTP hardware clock (PHC)
|
||||||
|
After=ntpdate.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
EnvironmentFile=-/etc/sysconfig/phc2sys
|
||||||
|
ExecStart=/usr/sbin/phc2sys $OPTIONS
|
||||||
|
ExecStartPost=/bin/bash -c 'echo $MAINPID > /var/run/phc2sys.pid'
|
||||||
|
ExecStopPost=/bin/rm -f /var/run/phc2sys.pid
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -0,0 +1,107 @@
|
||||||
|
[global]
|
||||||
|
#
|
||||||
|
# Default Data Set
|
||||||
|
#
|
||||||
|
twoStepFlag 1
|
||||||
|
<%- if @slave_only == true -%>
|
||||||
|
slaveOnly 1
|
||||||
|
<%- else -%>
|
||||||
|
slaveOnly 0
|
||||||
|
<%- end -%>
|
||||||
|
priority1 128
|
||||||
|
priority2 128
|
||||||
|
domainNumber 0
|
||||||
|
#utc_offset 37
|
||||||
|
clockClass 248
|
||||||
|
clockAccuracy 0xFE
|
||||||
|
offsetScaledLogVariance 0xFFFF
|
||||||
|
free_running 0
|
||||||
|
freq_est_interval 1
|
||||||
|
dscp_event 0
|
||||||
|
dscp_general 0
|
||||||
|
#
|
||||||
|
# Port Data Set
|
||||||
|
#
|
||||||
|
logAnnounceInterval 1
|
||||||
|
logSyncInterval 0
|
||||||
|
logMinDelayReqInterval 0
|
||||||
|
logMinPdelayReqInterval 0
|
||||||
|
announceReceiptTimeout 3
|
||||||
|
syncReceiptTimeout 0
|
||||||
|
delayAsymmetry 0
|
||||||
|
fault_reset_interval 4
|
||||||
|
neighborPropDelayThresh 20000000
|
||||||
|
#
|
||||||
|
# Run time options
|
||||||
|
#
|
||||||
|
assume_two_step 0
|
||||||
|
logging_level 6
|
||||||
|
path_trace_enabled 0
|
||||||
|
follow_up_info 0
|
||||||
|
hybrid_e2e 0
|
||||||
|
tx_timestamp_timeout 1
|
||||||
|
use_syslog 1
|
||||||
|
verbose 0
|
||||||
|
summary_interval 6
|
||||||
|
kernel_leap 1
|
||||||
|
check_fup_sync 0
|
||||||
|
#
|
||||||
|
# Servo Options
|
||||||
|
#
|
||||||
|
pi_proportional_const 0.0
|
||||||
|
pi_integral_const 0.0
|
||||||
|
pi_proportional_scale 0.0
|
||||||
|
pi_proportional_exponent -0.3
|
||||||
|
pi_proportional_norm_max 0.7
|
||||||
|
pi_integral_scale 0.0
|
||||||
|
pi_integral_exponent 0.4
|
||||||
|
pi_integral_norm_max 0.3
|
||||||
|
step_threshold 0.0
|
||||||
|
first_step_threshold 0.00002
|
||||||
|
max_frequency 900000000
|
||||||
|
clock_servo linreg
|
||||||
|
sanity_freq_limit 200000000
|
||||||
|
ntpshm_segment 0
|
||||||
|
#
|
||||||
|
# Transport options
|
||||||
|
#
|
||||||
|
transportSpecific 0x0
|
||||||
|
ptp_dst_mac 01:1B:19:00:00:00
|
||||||
|
p2p_dst_mac 01:80:C2:00:00:0E
|
||||||
|
udp_ttl 1
|
||||||
|
udp6_scope 0x0E
|
||||||
|
uds_address /var/run/ptp4l
|
||||||
|
#
|
||||||
|
# Default interface options
|
||||||
|
#
|
||||||
|
network_transport L2
|
||||||
|
delay_mechanism <%= scope['platform::ptp::mechanism'].upcase %>
|
||||||
|
time_stamping <%= scope['platform::ptp::mode'].downcase %>
|
||||||
|
tsproc_mode filter
|
||||||
|
delay_filter moving_median
|
||||||
|
delay_filter_length 10
|
||||||
|
egressLatency 0
|
||||||
|
ingressLatency 0
|
||||||
|
<%- if @slave_only == true -%>
|
||||||
|
boundary_clock_jbod 0
|
||||||
|
<%- else -%>
|
||||||
|
boundary_clock_jbod 1
|
||||||
|
<%- end -%>
|
||||||
|
#
|
||||||
|
# Clock description
|
||||||
|
#
|
||||||
|
productDescription ;;
|
||||||
|
revisionData ;;
|
||||||
|
manufacturerIdentity 00:00:00
|
||||||
|
userDescription ;
|
||||||
|
timeSource 0xA0
|
||||||
|
|
||||||
|
<%- if scope['platform::ptp::transport'] == 'udp' -%>
|
||||||
|
[<%= @slave_interface %>]
|
||||||
|
network_transport UDPv<%= @slave_subnet %>
|
||||||
|
|
||||||
|
<%- if @slave_only == false -%>
|
||||||
|
[<%= @master_interface %>]
|
||||||
|
network_transport UDPv<%= @master_subnet %>
|
||||||
|
<%- end -%>
|
||||||
|
<%- end -%>
|
|
@ -0,0 +1 @@
|
||||||
|
OPTIONS="-f /etc/ptp4l.conf"
|
|
@ -0,0 +1,19 @@
|
||||||
|
[process]
|
||||||
|
process = ptp4l
|
||||||
|
service = ptp4l
|
||||||
|
pidfile = /var/run/ptp4l.pid
|
||||||
|
style = lsb ; ocf or lsb
|
||||||
|
severity = minor ; minor, major, critical
|
||||||
|
restarts = 0 ; restart retries before error assertion
|
||||||
|
interval = 10 ; number of seconds to wait between restarts
|
||||||
|
debounce = 10 ; number of seconds that a process needs to remain
|
||||||
|
; running before degrade is removed and retry count
|
||||||
|
; is cleared.
|
||||||
|
; These settings will generate a log only without attempting to restart
|
||||||
|
; pmond will put the process into an ignore state after failure.
|
||||||
|
|
||||||
|
startuptime = 180 ; Seconds to wait after process start before starting the debounce monitor
|
||||||
|
mode = passive ; Monitoring mode: passive (default) or active
|
||||||
|
; passive: process death monitoring (default: always)
|
||||||
|
; active : heartbeat monitoring, i.e. request / response messaging
|
||||||
|
; ignore : do not monitor or stop monitoring
|
|
@ -0,0 +1,12 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Precision Time Protocol (PTP) service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
EnvironmentFile=-/etc/sysconfig/ptp4l
|
||||||
|
ExecStart=/usr/sbin/ptp4l $OPTIONS
|
||||||
|
ExecStartPost=/bin/bash -c 'echo $MAINPID > /var/run/ptp4l.pid'
|
||||||
|
ExecStopPost=/bin/rm -f /var/run/ptp4l.pid
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -1,2 +1,2 @@
|
||||||
SRC_DIR="cgts-client"
|
SRC_DIR="cgts-client"
|
||||||
TIS_PATCH_VER=59
|
TIS_PATCH_VER=60
|
||||||
|
|
|
@ -96,6 +96,7 @@ def _does_command_need_no_wrap(callback):
|
||||||
|
|
||||||
if callback.__name__ in \
|
if callback.__name__ in \
|
||||||
['donot_config_ntp_list',
|
['donot_config_ntp_list',
|
||||||
|
'donot_config_ptp_list',
|
||||||
'do_host_apply_memprofile',
|
'do_host_apply_memprofile',
|
||||||
'do_host_apply_cpuprofile',
|
'do_host_apply_cpuprofile',
|
||||||
'do_host_apply_ifprofile',
|
'do_host_apply_ifprofile',
|
||||||
|
|
|
@ -57,6 +57,7 @@ from cgtsclient.v1 import network
|
||||||
from cgtsclient.v1 import partition
|
from cgtsclient.v1 import partition
|
||||||
from cgtsclient.v1 import pci_device
|
from cgtsclient.v1 import pci_device
|
||||||
from cgtsclient.v1 import port
|
from cgtsclient.v1 import port
|
||||||
|
from cgtsclient.v1 import ptp
|
||||||
from cgtsclient.v1 import remotelogging
|
from cgtsclient.v1 import remotelogging
|
||||||
from cgtsclient.v1 import route
|
from cgtsclient.v1 import route
|
||||||
from cgtsclient.v1 import sdn_controller
|
from cgtsclient.v1 import sdn_controller
|
||||||
|
@ -102,6 +103,7 @@ class Client(http.HTTPClient):
|
||||||
self.iuser = iuser.iuserManager(self)
|
self.iuser = iuser.iuserManager(self)
|
||||||
self.idns = idns.idnsManager(self)
|
self.idns = idns.idnsManager(self)
|
||||||
self.intp = intp.intpManager(self)
|
self.intp = intp.intpManager(self)
|
||||||
|
self.ptp = ptp.ptpManager(self)
|
||||||
self.iextoam = iextoam.iextoamManager(self)
|
self.iextoam = iextoam.iextoamManager(self)
|
||||||
self.controller_fs = controller_fs.ControllerFsManager(self)
|
self.controller_fs = controller_fs.ControllerFsManager(self)
|
||||||
self.storage_backend = storage_backend.StorageBackendManager(self)
|
self.storage_backend = storage_backend.StorageBackendManager(self)
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
from cgtsclient.common import base
|
||||||
|
from cgtsclient import exc
|
||||||
|
|
||||||
|
|
||||||
|
CREATION_ATTRIBUTES = []
|
||||||
|
|
||||||
|
|
||||||
|
class ptp(base.Resource):
|
||||||
|
def __repr__(self):
|
||||||
|
return "<ptp %s>" % self._info
|
||||||
|
|
||||||
|
|
||||||
|
class ptpManager(base.Manager):
|
||||||
|
resource_class = ptp
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _path(id=None):
|
||||||
|
return '/v1/ptp/%s' % id if id else '/v1/ptp'
|
||||||
|
|
||||||
|
def list(self):
|
||||||
|
return self._list(self._path(), "ptps")
|
||||||
|
|
||||||
|
def get(self, ptp_id):
|
||||||
|
try:
|
||||||
|
return self._list(self._path(ptp_id))[0]
|
||||||
|
except IndexError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def create(self, **kwargs):
|
||||||
|
new = {}
|
||||||
|
for (key, value) in kwargs.items():
|
||||||
|
if key in CREATION_ATTRIBUTES:
|
||||||
|
new[key] = value
|
||||||
|
else:
|
||||||
|
raise exc.InvalidAttribute('%s' % key)
|
||||||
|
return self._create(self._path(), new)
|
||||||
|
|
||||||
|
def delete(self, ptp_id):
|
||||||
|
return self._delete(self._path(ptp_id))
|
||||||
|
|
||||||
|
def update(self, ptp_id, patch):
|
||||||
|
return self._update(self._path(ptp_id), patch)
|
|
@ -0,0 +1,79 @@
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
from cgtsclient.common import utils
|
||||||
|
from cgtsclient import exc
|
||||||
|
|
||||||
|
|
||||||
|
def _print_ptp_show(ptp):
|
||||||
|
fields = ['uuid', 'enabled', 'mode', 'transport', 'mechanism',
|
||||||
|
'isystem_uuid', 'created_at', 'updated_at']
|
||||||
|
data = [(f, getattr(ptp, f, '')) for f in fields]
|
||||||
|
utils.print_tuple_list(data)
|
||||||
|
|
||||||
|
|
||||||
|
def do_ptp_show(cc, args):
|
||||||
|
"""Show PTP (Precision Time Protocol) attributes."""
|
||||||
|
|
||||||
|
ptps = cc.ptp.list()
|
||||||
|
|
||||||
|
_print_ptp_show(ptps[0])
|
||||||
|
|
||||||
|
|
||||||
|
def donot_config_ptp_list(cc, args):
|
||||||
|
"""List ptps."""
|
||||||
|
|
||||||
|
ptps = cc.ptp.list()
|
||||||
|
|
||||||
|
field_labels = ['uuid', 'enabled', 'mode', 'transport', 'mechanism']
|
||||||
|
fields = ['uuid', 'enabled', 'mode', 'transport', 'mechanism']
|
||||||
|
utils.print_list(ptps, fields, field_labels, sortby=1)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('--enabled',
|
||||||
|
metavar='<true/false>',
|
||||||
|
help="PTP service enabled.")
|
||||||
|
@utils.arg('--mode',
|
||||||
|
metavar='<mode>',
|
||||||
|
default=None,
|
||||||
|
help="PTP time stamping mode.")
|
||||||
|
@utils.arg('--transport',
|
||||||
|
metavar='<transport>',
|
||||||
|
default=None,
|
||||||
|
help="PTP transport protocol.")
|
||||||
|
@utils.arg('--mechanism',
|
||||||
|
metavar='<mechanism>',
|
||||||
|
default=None,
|
||||||
|
help="PTP delay mechanism.")
|
||||||
|
def do_ptp_modify(cc, args):
|
||||||
|
"""Modify PTP attributes."""
|
||||||
|
|
||||||
|
ptps = cc.ptp.list()
|
||||||
|
ptp = ptps[0]
|
||||||
|
op = "replace"
|
||||||
|
|
||||||
|
attributes = []
|
||||||
|
if args.enabled is not None:
|
||||||
|
attributes.append('enabled=%s' % args.enabled)
|
||||||
|
if args.mode is not None:
|
||||||
|
attributes.append('mode=%s' % args.mode)
|
||||||
|
if args.transport is not None:
|
||||||
|
attributes.append('transport=%s' % args.transport)
|
||||||
|
if args.mechanism is not None:
|
||||||
|
attributes.append('mechanism=%s' % args.mechanism)
|
||||||
|
if len(attributes) == 0:
|
||||||
|
print "No options provided."
|
||||||
|
return
|
||||||
|
|
||||||
|
patch = utils.args_array_to_patch("replace", attributes)
|
||||||
|
try:
|
||||||
|
ptp = cc.ptp.update(ptp.uuid, patch)
|
||||||
|
except exc.HTTPNotFound:
|
||||||
|
raise exc.CommandError('PTP not found: %s' % ptp.uuid)
|
||||||
|
|
||||||
|
_print_ptp_show(ptp)
|
|
@ -46,6 +46,7 @@ from cgtsclient.v1 import network_shell
|
||||||
from cgtsclient.v1 import partition_shell
|
from cgtsclient.v1 import partition_shell
|
||||||
from cgtsclient.v1 import pci_device_shell
|
from cgtsclient.v1 import pci_device_shell
|
||||||
from cgtsclient.v1 import port_shell
|
from cgtsclient.v1 import port_shell
|
||||||
|
from cgtsclient.v1 import ptp_shell
|
||||||
from cgtsclient.v1 import remotelogging_shell
|
from cgtsclient.v1 import remotelogging_shell
|
||||||
from cgtsclient.v1 import route_shell
|
from cgtsclient.v1 import route_shell
|
||||||
from cgtsclient.v1 import sdn_controller_shell
|
from cgtsclient.v1 import sdn_controller_shell
|
||||||
|
@ -63,6 +64,7 @@ COMMAND_MODULES = [
|
||||||
iuser_shell,
|
iuser_shell,
|
||||||
idns_shell,
|
idns_shell,
|
||||||
intp_shell,
|
intp_shell,
|
||||||
|
ptp_shell,
|
||||||
iextoam_shell,
|
iextoam_shell,
|
||||||
controller_fs_shell,
|
controller_fs_shell,
|
||||||
storage_backend_shell,
|
storage_backend_shell,
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
SRC_DIR="sysinv"
|
SRC_DIR="sysinv"
|
||||||
TIS_PATCH_VER=278
|
TIS_PATCH_VER=279
|
||||||
|
|
|
@ -53,6 +53,7 @@ from sysinv.api.controllers.v1 import partition
|
||||||
from sysinv.api.controllers.v1 import pci_device
|
from sysinv.api.controllers.v1 import pci_device
|
||||||
from sysinv.api.controllers.v1 import port
|
from sysinv.api.controllers.v1 import port
|
||||||
from sysinv.api.controllers.v1 import profile
|
from sysinv.api.controllers.v1 import profile
|
||||||
|
from sysinv.api.controllers.v1 import ptp
|
||||||
from sysinv.api.controllers.v1 import pv
|
from sysinv.api.controllers.v1 import pv
|
||||||
from sysinv.api.controllers.v1 import remotelogging
|
from sysinv.api.controllers.v1 import remotelogging
|
||||||
from sysinv.api.controllers.v1 import route
|
from sysinv.api.controllers.v1 import route
|
||||||
|
@ -137,6 +138,9 @@ class V1(base.APIBase):
|
||||||
intp = [link.Link]
|
intp = [link.Link]
|
||||||
"Links to the intp resource"
|
"Links to the intp resource"
|
||||||
|
|
||||||
|
ptp = [link.Link]
|
||||||
|
"Links to the ptp resource"
|
||||||
|
|
||||||
iextoam = [link.Link]
|
iextoam = [link.Link]
|
||||||
"Links to the iextoam resource"
|
"Links to the iextoam resource"
|
||||||
|
|
||||||
|
@ -387,39 +391,47 @@ class V1(base.APIBase):
|
||||||
]
|
]
|
||||||
|
|
||||||
v1.idns = [link.Link.make_link('self', pecan.request.host_url,
|
v1.idns = [link.Link.make_link('self', pecan.request.host_url,
|
||||||
'idns', ''),
|
'idns', ''),
|
||||||
link.Link.make_link('bookmark',
|
link.Link.make_link('bookmark',
|
||||||
pecan.request.host_url,
|
pecan.request.host_url,
|
||||||
'idns', '',
|
'idns', '',
|
||||||
bookmark=True)
|
bookmark=True)
|
||||||
]
|
]
|
||||||
|
|
||||||
v1.intp = [link.Link.make_link('self', pecan.request.host_url,
|
v1.intp = [link.Link.make_link('self', pecan.request.host_url,
|
||||||
'intp', ''),
|
'intp', ''),
|
||||||
link.Link.make_link('bookmark',
|
link.Link.make_link('bookmark',
|
||||||
pecan.request.host_url,
|
pecan.request.host_url,
|
||||||
'intp', '',
|
'intp', '',
|
||||||
bookmark=True)
|
bookmark=True)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
v1.ptp = [link.Link.make_link('self', pecan.request.host_url,
|
||||||
|
'ptp', ''),
|
||||||
|
link.Link.make_link('bookmark',
|
||||||
|
pecan.request.host_url,
|
||||||
|
'ptp', '',
|
||||||
|
bookmark=True)
|
||||||
|
]
|
||||||
|
|
||||||
v1.iextoam = [link.Link.make_link('self', pecan.request.host_url,
|
v1.iextoam = [link.Link.make_link('self', pecan.request.host_url,
|
||||||
'iextoam', ''),
|
'iextoam', ''),
|
||||||
link.Link.make_link('bookmark',
|
link.Link.make_link('bookmark',
|
||||||
pecan.request.host_url,
|
pecan.request.host_url,
|
||||||
'iextoam', '',
|
'iextoam', '',
|
||||||
bookmark=True)
|
bookmark=True)
|
||||||
]
|
]
|
||||||
|
|
||||||
v1.controller_fs = [link.Link.make_link('self', pecan.request.host_url,
|
v1.controller_fs = [link.Link.make_link('self', pecan.request.host_url,
|
||||||
'controller_fs', ''),
|
'controller_fs', ''),
|
||||||
link.Link.make_link('bookmark',
|
link.Link.make_link('bookmark',
|
||||||
pecan.request.host_url,
|
pecan.request.host_url,
|
||||||
'controller_fs', '',
|
'controller_fs', '',
|
||||||
bookmark=True)
|
bookmark=True)
|
||||||
]
|
]
|
||||||
|
|
||||||
v1.storage_backend = [link.Link.make_link('self',
|
v1.storage_backend = [link.Link.make_link('self',
|
||||||
pecan.request.host_url,
|
pecan.request.host_url,
|
||||||
'storage_backend', ''),
|
'storage_backend', ''),
|
||||||
link.Link.make_link('bookmark',
|
link.Link.make_link('bookmark',
|
||||||
pecan.request.host_url,
|
pecan.request.host_url,
|
||||||
|
@ -717,6 +729,7 @@ class Controller(rest.RestController):
|
||||||
iuser = user.UserController()
|
iuser = user.UserController()
|
||||||
idns = dns.DNSController()
|
idns = dns.DNSController()
|
||||||
intp = ntp.NTPController()
|
intp = ntp.NTPController()
|
||||||
|
ptp = ptp.PTPController()
|
||||||
iextoam = network_oam.OAMNetworkController()
|
iextoam = network_oam.OAMNetworkController()
|
||||||
controller_fs = controller_fs.ControllerFsController()
|
controller_fs = controller_fs.ControllerFsController()
|
||||||
storage_backend = storage_backend.StorageBackendController()
|
storage_backend = storage_backend.StorageBackendController()
|
||||||
|
|
|
@ -159,6 +159,15 @@ def _check_ntp_data(op, ntp):
|
||||||
|
|
||||||
MAX_S = 3
|
MAX_S = 3
|
||||||
|
|
||||||
|
ptp_list = pecan.request.dbapi.ptp_get_by_isystem(ntp['forisystemid'])
|
||||||
|
|
||||||
|
if ptp_list:
|
||||||
|
if hasattr(ptp_list[0], 'enabled'):
|
||||||
|
if ptp_list[0].enabled is True and enabled is True:
|
||||||
|
raise wsme.exc.ClientSideError(_(
|
||||||
|
"NTP cannot be configured alongside with PTP."
|
||||||
|
" Please disable PTP before enabling NTP."))
|
||||||
|
|
||||||
dns_list = pecan.request.dbapi.idns_get_by_isystem(ntp['forisystemid'])
|
dns_list = pecan.request.dbapi.idns_get_by_isystem(ntp['forisystemid'])
|
||||||
|
|
||||||
if dns_list:
|
if dns_list:
|
||||||
|
|
|
@ -0,0 +1,253 @@
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
import jsonpatch
|
||||||
|
|
||||||
|
import pecan
|
||||||
|
from pecan import rest
|
||||||
|
|
||||||
|
import wsme
|
||||||
|
from wsme import types as wtypes
|
||||||
|
import wsmeext.pecan as wsme_pecan
|
||||||
|
|
||||||
|
from sysinv.api.controllers.v1 import base
|
||||||
|
from sysinv.api.controllers.v1 import collection
|
||||||
|
from sysinv.api.controllers.v1 import link
|
||||||
|
from sysinv.api.controllers.v1 import types
|
||||||
|
from sysinv.api.controllers.v1 import utils
|
||||||
|
from sysinv.common import exception
|
||||||
|
from sysinv.common import utils as cutils
|
||||||
|
from sysinv import objects
|
||||||
|
from sysinv.openstack.common.gettextutils import _
|
||||||
|
from sysinv.openstack.common import log
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class PTPPatchType(types.JsonPatchType):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mandatory_attrs():
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
class PTP(base.APIBase):
|
||||||
|
"""API representation of PTP configuration.
|
||||||
|
|
||||||
|
This class enforces type checking and value constraints, and converts
|
||||||
|
between the internal object model and the API representation of
|
||||||
|
an ptp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
uuid = types.uuid
|
||||||
|
"Unique UUID for this ptp"
|
||||||
|
|
||||||
|
enabled = types.boolean
|
||||||
|
"Represent the status of the ptp."
|
||||||
|
|
||||||
|
mode = wtypes.Enum(str, 'hardware', 'software', 'legacy')
|
||||||
|
"Time stamping mode used by ptp."
|
||||||
|
|
||||||
|
transport = wtypes.Enum(str, 'l2', 'udp')
|
||||||
|
"Network transport used by ptp."
|
||||||
|
|
||||||
|
mechanism = wtypes.Enum(str, 'e2e', 'p2p')
|
||||||
|
"Messaging mechanism used by ptp."
|
||||||
|
|
||||||
|
links = [link.Link]
|
||||||
|
"A list containing a self link and associated ptp links"
|
||||||
|
|
||||||
|
isystem_uuid = types.uuid
|
||||||
|
"The UUID of the system this ptp belongs to"
|
||||||
|
|
||||||
|
created_at = wtypes.datetime.datetime
|
||||||
|
updated_at = wtypes.datetime.datetime
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self.fields = objects.ptp.fields.keys()
|
||||||
|
for k in self.fields:
|
||||||
|
setattr(self, k, kwargs.get(k))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def convert_with_links(cls, rpc_ptp, expand=True):
|
||||||
|
|
||||||
|
ptp = PTP(**rpc_ptp.as_dict())
|
||||||
|
if not expand:
|
||||||
|
ptp.unset_fields_except(['uuid',
|
||||||
|
'enabled',
|
||||||
|
'mode',
|
||||||
|
'transport',
|
||||||
|
'mechanism',
|
||||||
|
'isystem_uuid',
|
||||||
|
'created_at',
|
||||||
|
'updated_at'])
|
||||||
|
|
||||||
|
ptp.links = [link.Link.make_link('self', pecan.request.host_url,
|
||||||
|
'ptps', ptp.uuid),
|
||||||
|
link.Link.make_link('bookmark',
|
||||||
|
pecan.request.host_url,
|
||||||
|
'ptps', ptp.uuid,
|
||||||
|
bookmark=True)
|
||||||
|
]
|
||||||
|
|
||||||
|
return ptp
|
||||||
|
|
||||||
|
|
||||||
|
class ptpCollection(collection.Collection):
|
||||||
|
"""API representation of a collection of ptps."""
|
||||||
|
|
||||||
|
ptps = [PTP]
|
||||||
|
"A list containing ptp objects"
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self._type = 'ptps'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def convert_with_links(cls, rpc_ptps, limit, url=None,
|
||||||
|
expand=False, **kwargs):
|
||||||
|
collection = ptpCollection()
|
||||||
|
collection.ptps = [PTP.convert_with_links(p, expand)
|
||||||
|
for p in rpc_ptps]
|
||||||
|
collection.next = collection.get_next(limit, url=url, **kwargs)
|
||||||
|
return collection
|
||||||
|
|
||||||
|
|
||||||
|
##############
|
||||||
|
# UTILS
|
||||||
|
##############
|
||||||
|
def _check_ptp_data(op, ptp):
|
||||||
|
enabled = ptp['enabled']
|
||||||
|
ntp_list = pecan.request.dbapi.intp_get_by_isystem(ptp['isystem_uuid'])
|
||||||
|
if ntp_list:
|
||||||
|
if hasattr(ntp_list[0], 'enabled'):
|
||||||
|
if ntp_list[0].enabled is True and enabled is True:
|
||||||
|
raise wsme.exc.ClientSideError(_(
|
||||||
|
"PTP cannot be configured alongside with NTP."
|
||||||
|
" Please disable NTP before enabling PTP."))
|
||||||
|
return ptp
|
||||||
|
|
||||||
|
|
||||||
|
LOCK_NAME = 'PTPController'
|
||||||
|
|
||||||
|
|
||||||
|
class PTPController(rest.RestController):
|
||||||
|
"""REST controller for ptps."""
|
||||||
|
|
||||||
|
_custom_actions = {
|
||||||
|
'detail': ['GET'],
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_ptps_collection(self, marker, limit, sort_key, sort_dir,
|
||||||
|
expand=False, resource_url=None):
|
||||||
|
|
||||||
|
limit = utils.validate_limit(limit)
|
||||||
|
sort_dir = utils.validate_sort_dir(sort_dir)
|
||||||
|
|
||||||
|
marker_obj = None
|
||||||
|
if marker:
|
||||||
|
marker_obj = objects.ptp.get_by_uuid(pecan.request.context,
|
||||||
|
marker)
|
||||||
|
|
||||||
|
ptps = pecan.request.dbapi.ptp_get_list(limit, marker_obj,
|
||||||
|
sort_key=sort_key,
|
||||||
|
sort_dir=sort_dir)
|
||||||
|
|
||||||
|
return ptpCollection.convert_with_links(ptps, limit,
|
||||||
|
url=resource_url,
|
||||||
|
expand=expand,
|
||||||
|
sort_key=sort_key,
|
||||||
|
sort_dir=sort_dir)
|
||||||
|
|
||||||
|
@wsme_pecan.wsexpose(ptpCollection, types.uuid, int,
|
||||||
|
wtypes.text, wtypes.text)
|
||||||
|
def get_all(self, marker=None, limit=None,
|
||||||
|
sort_key='id', sort_dir='asc'):
|
||||||
|
"""Retrieve a list of ptps. Only one per system"""
|
||||||
|
|
||||||
|
return self._get_ptps_collection(marker, limit,
|
||||||
|
sort_key, sort_dir)
|
||||||
|
|
||||||
|
@wsme_pecan.wsexpose(ptpCollection, types.uuid, int,
|
||||||
|
wtypes.text, wtypes.text)
|
||||||
|
def detail(self, marker=None, limit=None,
|
||||||
|
sort_key='id', sort_dir='asc'):
|
||||||
|
"""Retrieve a list of ptps with detail."""
|
||||||
|
# NOTE(lucasagomes): /detail should only work agaist collections
|
||||||
|
parent = pecan.request.path.split('/')[:-1][-1]
|
||||||
|
if parent != "ptps":
|
||||||
|
raise exception.HTTPNotFound
|
||||||
|
|
||||||
|
expand = True
|
||||||
|
resource_url = '/'.join(['ptps', 'detail'])
|
||||||
|
return self._get_ptps_collection(marker, limit,
|
||||||
|
sort_key, sort_dir,
|
||||||
|
expand, resource_url)
|
||||||
|
|
||||||
|
@wsme_pecan.wsexpose(PTP, types.uuid)
|
||||||
|
def get_one(self, ptp_uuid):
|
||||||
|
"""Retrieve information about the given ptp."""
|
||||||
|
rpc_ptp = objects.ptp.get_by_uuid(pecan.request.context, ptp_uuid)
|
||||||
|
return PTP.convert_with_links(rpc_ptp)
|
||||||
|
|
||||||
|
@wsme_pecan.wsexpose(PTP, body=PTP)
|
||||||
|
def post(self, ptp):
|
||||||
|
"""Create a new ptp."""
|
||||||
|
raise exception.OperationNotPermitted
|
||||||
|
|
||||||
|
@cutils.synchronized(LOCK_NAME)
|
||||||
|
@wsme.validate(types.uuid, [PTPPatchType])
|
||||||
|
@wsme_pecan.wsexpose(PTP, types.uuid,
|
||||||
|
body=[PTPPatchType])
|
||||||
|
def patch(self, ptp_uuid, patch):
|
||||||
|
"""Update the current PTP configuration."""
|
||||||
|
|
||||||
|
rpc_ptp = objects.ptp.get_by_uuid(pecan.request.context, ptp_uuid)
|
||||||
|
patch_obj = jsonpatch.JsonPatch(patch)
|
||||||
|
|
||||||
|
state_rel_path = ['/uuid', '/id']
|
||||||
|
if any(p['path'] in state_rel_path for p in patch_obj):
|
||||||
|
raise wsme.exc.ClientSideError(_("The following fields can not be "
|
||||||
|
"modified: %s" %
|
||||||
|
state_rel_path))
|
||||||
|
|
||||||
|
try:
|
||||||
|
ptp = PTP(**jsonpatch.apply_patch(rpc_ptp.as_dict(),
|
||||||
|
patch_obj))
|
||||||
|
|
||||||
|
except utils.JSONPATCH_EXCEPTIONS as e:
|
||||||
|
raise exception.PatchError(patch=patch, reason=e)
|
||||||
|
|
||||||
|
ptp = _check_ptp_data("modify", ptp.as_dict())
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Update only the fields that have changed
|
||||||
|
for field in objects.ptp.fields:
|
||||||
|
if rpc_ptp[field] != ptp[field]:
|
||||||
|
rpc_ptp[field] = ptp[field]
|
||||||
|
|
||||||
|
delta = rpc_ptp.obj_what_changed()
|
||||||
|
if delta:
|
||||||
|
rpc_ptp.save()
|
||||||
|
# perform rpc to conductor to perform config apply
|
||||||
|
pecan.request.rpcapi.update_ptp_config(pecan.request.context)
|
||||||
|
else:
|
||||||
|
LOG.info("No PTP config changes")
|
||||||
|
|
||||||
|
return PTP.convert_with_links(rpc_ptp)
|
||||||
|
|
||||||
|
except exception.HTTPNotFound:
|
||||||
|
msg = _("PTP update failed: enabled %s : %s %s %s : patch %s"
|
||||||
|
% (ptp['enabled'], ptp['mode'], ptp['transport'],
|
||||||
|
ptp['mechanism'], patch))
|
||||||
|
raise wsme.exc.ClientSideError(msg)
|
||||||
|
|
||||||
|
@wsme_pecan.wsexpose(None, types.uuid, status_code=204)
|
||||||
|
def delete(self, ptp_uuid):
|
||||||
|
"""Delete a ptp."""
|
||||||
|
raise exception.OperationNotPermitted
|
|
@ -478,7 +478,11 @@ class DNSAlreadyExists(Conflict):
|
||||||
|
|
||||||
|
|
||||||
class NTPAlreadyExists(Conflict):
|
class NTPAlreadyExists(Conflict):
|
||||||
message = _("An NTP with UUID %(uuid)s already exists.")
|
message = _("A NTP with UUID %(uuid)s already exists.")
|
||||||
|
|
||||||
|
|
||||||
|
class PTPAlreadyExists(Conflict):
|
||||||
|
message = _("A PTP with UUID %(uuid)s already exists.")
|
||||||
|
|
||||||
|
|
||||||
class PMAlreadyExists(Conflict):
|
class PMAlreadyExists(Conflict):
|
||||||
|
@ -614,6 +618,10 @@ class NTPNotFound(NotFound):
|
||||||
message = _("No NTP with id %(uuid)s found.")
|
message = _("No NTP with id %(uuid)s found.")
|
||||||
|
|
||||||
|
|
||||||
|
class PTPNotFound(NotFound):
|
||||||
|
message = _("No PTP with id %(uuid)s found.")
|
||||||
|
|
||||||
|
|
||||||
class DiskNotFound(NotFound):
|
class DiskNotFound(NotFound):
|
||||||
message = _("No disk with id %(disk_id)s")
|
message = _("No disk with id %(disk_id)s")
|
||||||
|
|
||||||
|
|
|
@ -227,6 +227,8 @@ class ConductorManager(service.PeriodicService):
|
||||||
|
|
||||||
# fill in empty remotelogging system_id fields
|
# fill in empty remotelogging system_id fields
|
||||||
self.dbapi.remotelogging_fill_empty_system_id(system.id)
|
self.dbapi.remotelogging_fill_empty_system_id(system.id)
|
||||||
|
# fill in empty ptp system_id fields
|
||||||
|
self.dbapi.ptp_fill_empty_system_id(system.id)
|
||||||
|
|
||||||
return system # system already configured
|
return system # system already configured
|
||||||
except exception.NotFound:
|
except exception.NotFound:
|
||||||
|
@ -271,9 +273,10 @@ class ConductorManager(service.PeriodicService):
|
||||||
'rtt_ms': constants.DRBD_RTT_MS_DEFAULT
|
'rtt_ms': constants.DRBD_RTT_MS_DEFAULT
|
||||||
})
|
})
|
||||||
|
|
||||||
# remotelogging tables have attribute 'system_id' not 'forisystemid'
|
# remotelogging and ptp tables have attribute 'system_id' not 'forisystemid'
|
||||||
system_id_attribute_value = {'system_id': system.id}
|
system_id_attribute_value = {'system_id': system.id}
|
||||||
self.dbapi.remotelogging_create(system_id_attribute_value)
|
self.dbapi.remotelogging_create(system_id_attribute_value)
|
||||||
|
self.dbapi.ptp_create(system_id_attribute_value)
|
||||||
|
|
||||||
# set default storage_backend
|
# set default storage_backend
|
||||||
values.update({'backend': constants.SB_TYPE_FILE,
|
values.update({'backend': constants.SB_TYPE_FILE,
|
||||||
|
@ -5156,6 +5159,13 @@ class ConductorManager(service.PeriodicService):
|
||||||
personalities = [constants.CONTROLLER]
|
personalities = [constants.CONTROLLER]
|
||||||
self._config_update_hosts(context, personalities, reboot=True)
|
self._config_update_hosts(context, personalities, reboot=True)
|
||||||
|
|
||||||
|
def update_ptp_config(self, context):
|
||||||
|
"""Update the PTP configuration"""
|
||||||
|
personalities = [constants.CONTROLLER,
|
||||||
|
constants.COMPUTE,
|
||||||
|
constants.STORAGE]
|
||||||
|
self._config_update_hosts(context, personalities)
|
||||||
|
|
||||||
def update_system_mode_config(self, context):
|
def update_system_mode_config(self, context):
|
||||||
"""Update the system mode configuration"""
|
"""Update the system mode configuration"""
|
||||||
personalities = [constants.CONTROLLER]
|
personalities = [constants.CONTROLLER]
|
||||||
|
|
|
@ -702,6 +702,13 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
|
||||||
return self.call(context, self.make_msg('update_ntp_config',
|
return self.call(context, self.make_msg('update_ntp_config',
|
||||||
service_change=service_change))
|
service_change=service_change))
|
||||||
|
|
||||||
|
def update_ptp_config(self, context):
|
||||||
|
"""Synchronously, have the conductor update the PTP configuration.
|
||||||
|
|
||||||
|
:param context: request context.
|
||||||
|
"""
|
||||||
|
return self.call(context, self.make_msg('update_ptp_config'))
|
||||||
|
|
||||||
def update_system_mode_config(self, context):
|
def update_system_mode_config(self, context):
|
||||||
"""Synchronously, have the conductor update the system mode
|
"""Synchronously, have the conductor update the system mode
|
||||||
configuration.
|
configuration.
|
||||||
|
|
|
@ -1864,7 +1864,6 @@ class Connection(object):
|
||||||
def intp_create(self, values):
|
def intp_create(self, values):
|
||||||
"""Create a new intp for an isystem.
|
"""Create a new intp for an isystem.
|
||||||
|
|
||||||
:param forisystemid: intp belongs to this isystem
|
|
||||||
:param values: A dict containing several items used to identify
|
:param values: A dict containing several items used to identify
|
||||||
and track the ntp settings.
|
and track the ntp settings.
|
||||||
{
|
{
|
||||||
|
@ -1878,18 +1877,18 @@ class Connection(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def intp_get(self, server):
|
def intp_get(self, intp_id):
|
||||||
"""Return an intp.
|
"""Return an intp.
|
||||||
|
|
||||||
:param isystem: The id or uuid of an intp.
|
:param intp_id: The id or uuid of an intp.
|
||||||
:returns: A intp.
|
:returns: An intp.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def intp_get_one(self):
|
def intp_get_one(self):
|
||||||
"""Return exactly one intp.
|
"""Return exactly one intp.
|
||||||
|
|
||||||
:returns: A intp.
|
:returns: An intp.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
@ -1910,7 +1909,7 @@ class Connection(object):
|
||||||
sort_key=None, sort_dir=None):
|
sort_key=None, sort_dir=None):
|
||||||
"""List all the intp for a given isystem.
|
"""List all the intp for a given isystem.
|
||||||
|
|
||||||
:param isystem: The id or uuid of an isystem.
|
:param isystem_id: The id or uuid of an isystem.
|
||||||
:param limit: Maximum number of intp to return.
|
:param limit: Maximum number of intp to return.
|
||||||
:param marker: the last item of the previous page; we return the next
|
:param marker: the last item of the previous page; we return the next
|
||||||
result set.
|
result set.
|
||||||
|
@ -1921,7 +1920,7 @@ class Connection(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def intp_update(self, server, values):
|
def intp_update(self, intp_id, values):
|
||||||
"""Update properties of an intp.
|
"""Update properties of an intp.
|
||||||
|
|
||||||
:param intp_id: The id or uuid of an intp.
|
:param intp_id: The id or uuid of an intp.
|
||||||
|
@ -1940,10 +1939,105 @@ class Connection(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def intp_destroy(self, server):
|
def intp_destroy(self, intp_id):
|
||||||
"""Destroy an intp.
|
"""Destroy an intp.
|
||||||
|
|
||||||
:param id: The id or uuid of an intp.
|
:param intp_id: The id or uuid of an intp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def ptp_create(self, values):
|
||||||
|
"""Create a new ptp for an isystem.
|
||||||
|
|
||||||
|
:param values: A dict containing several items used to identify
|
||||||
|
and track the ptp settings.
|
||||||
|
{
|
||||||
|
'enabled': 'True',
|
||||||
|
'mode': 'hardware',
|
||||||
|
'transport': 'l2',
|
||||||
|
'mechanism': 'e2e',
|
||||||
|
}
|
||||||
|
:returns: A ptp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def ptp_get(self, ptp_id):
|
||||||
|
"""Return a ptp.
|
||||||
|
|
||||||
|
:param ptp_id: The id or uuid of a ptp.
|
||||||
|
:returns: A ptp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def ptp_get_one(self):
|
||||||
|
"""Return exactly one ptp.
|
||||||
|
|
||||||
|
:returns: A ptp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def ptp_get_list(self, limit=None, marker=None,
|
||||||
|
sort_key=None, sort_dir=None):
|
||||||
|
"""Return a list of ptp.
|
||||||
|
|
||||||
|
:param limit: Maximum number of ptp to return.
|
||||||
|
:param marker: the last item of the previous page; we return the next
|
||||||
|
result set.
|
||||||
|
:param sort_key: Attribute by which results should be sorted.
|
||||||
|
:param sort_dir: direction in which results should be sorted.
|
||||||
|
(asc, desc)
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def ptp_get_by_isystem(self, isystem_id, limit=None, marker=None,
|
||||||
|
sort_key=None, sort_dir=None):
|
||||||
|
"""List all the ptp for a given isystem.
|
||||||
|
|
||||||
|
:param isystem_id: The id or uuid of an isystem.
|
||||||
|
:param limit: Maximum number of ptp to return.
|
||||||
|
:param marker: the last item of the previous page; we return the next
|
||||||
|
result set.
|
||||||
|
:param sort_key: Attribute by which results should be sorted
|
||||||
|
:param sort_dir: direction in which results should be sorted
|
||||||
|
(asc, desc)
|
||||||
|
:returns: A list of ptp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def ptp_update(self, ptp_id, values):
|
||||||
|
"""Update properties of a ptp.
|
||||||
|
|
||||||
|
:param ptp_id: The id or uuid of a ptp.
|
||||||
|
:param values: Dict of values to update.
|
||||||
|
May be a partial list, eg. when setting the
|
||||||
|
properties for capabilities. For example:
|
||||||
|
|
||||||
|
{
|
||||||
|
'capabilities':
|
||||||
|
{
|
||||||
|
'my-field-1': val1,
|
||||||
|
'my-field-2': val2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:returns: A ptp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def ptp_destroy(self, ptp_id):
|
||||||
|
"""Destroy a ptp.
|
||||||
|
|
||||||
|
:param ptp_id: The id or uuid of a ptp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def ptp_fill_empty_system_id(self, system_id):
|
||||||
|
"""fills all empty system_id in a ptp.
|
||||||
|
ptp did not always fill this entry in properly
|
||||||
|
so existing systems might still have no value in the
|
||||||
|
system_id field. This function fills in the system_id
|
||||||
|
in existing systems that were missing this value.
|
||||||
|
|
||||||
|
:param system_id: The value to fill system_id with
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
|
|
@ -3508,14 +3508,14 @@ class Connection(api.Connection):
|
||||||
|
|
||||||
query.delete()
|
query.delete()
|
||||||
|
|
||||||
def _ntp_get(self, server):
|
def _ntp_get(self, intp_id):
|
||||||
query = model_query(models.intp)
|
query = model_query(models.intp)
|
||||||
query = add_identity_filter(query, server)
|
query = add_identity_filter(query, intp_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return query.one()
|
return query.one()
|
||||||
except NoResultFound:
|
except NoResultFound:
|
||||||
raise exception.NTPNotFound(server=server)
|
raise exception.NTPNotFound(intp_id=intp_id)
|
||||||
|
|
||||||
@objects.objectify(objects.ntp)
|
@objects.objectify(objects.ntp)
|
||||||
def intp_create(self, values):
|
def intp_create(self, values):
|
||||||
|
@ -3564,25 +3564,25 @@ class Connection(api.Connection):
|
||||||
sort_key, sort_dir, query)
|
sort_key, sort_dir, query)
|
||||||
|
|
||||||
@objects.objectify(objects.ntp)
|
@objects.objectify(objects.ntp)
|
||||||
def intp_update(self, server, values):
|
def intp_update(self, intp_id, values):
|
||||||
with _session_for_write() as session:
|
with _session_for_write() as session:
|
||||||
query = model_query(models.intp, session=session)
|
query = model_query(models.intp, session=session)
|
||||||
query = add_identity_filter(query, server)
|
query = add_identity_filter(query, intp_id)
|
||||||
|
|
||||||
count = query.update(values, synchronize_session='fetch')
|
count = query.update(values, synchronize_session='fetch')
|
||||||
if count != 1:
|
if count != 1:
|
||||||
raise exception.NTPNotFound(server=server)
|
raise exception.NTPNotFound(intp_id=intp_id)
|
||||||
return query.one()
|
return query.one()
|
||||||
|
|
||||||
def intp_destroy(self, server):
|
def intp_destroy(self, intp_id):
|
||||||
with _session_for_write() as session:
|
with _session_for_write() as session:
|
||||||
query = model_query(models.intp, session=session)
|
query = model_query(models.intp, session=session)
|
||||||
query = add_identity_filter(query, server)
|
query = add_identity_filter(query, intp_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
query.one()
|
query.one()
|
||||||
except NoResultFound:
|
except NoResultFound:
|
||||||
raise exception.NTPNotFound(server=server)
|
raise exception.NTPNotFound(intp_id=intp_id)
|
||||||
# if node_ref['reservation'] is not None:
|
# if node_ref['reservation'] is not None:
|
||||||
# raise exception.NodeLocked(node=node)
|
# raise exception.NodeLocked(node=node)
|
||||||
|
|
||||||
|
@ -3595,6 +3595,92 @@ class Connection(api.Connection):
|
||||||
|
|
||||||
query.delete()
|
query.delete()
|
||||||
|
|
||||||
|
def _ptp_get(self, ptp_id):
|
||||||
|
query = model_query(models.PTP)
|
||||||
|
query = add_identity_filter(query, ptp_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return query.one()
|
||||||
|
except NoResultFound:
|
||||||
|
raise exception.PTPNotFound(ptp_id=ptp_id)
|
||||||
|
|
||||||
|
@objects.objectify(objects.ptp)
|
||||||
|
def ptp_create(self, values):
|
||||||
|
if not values.get('uuid'):
|
||||||
|
values['uuid'] = uuidutils.generate_uuid()
|
||||||
|
ptp = models.PTP()
|
||||||
|
ptp.update(values)
|
||||||
|
with _session_for_write() as session:
|
||||||
|
try:
|
||||||
|
session.add(ptp)
|
||||||
|
session.flush()
|
||||||
|
except db_exc.DBDuplicateEntry:
|
||||||
|
raise exception.PTPAlreadyExists(uuid=values['uuid'])
|
||||||
|
return self._ptp_get(values['uuid'])
|
||||||
|
|
||||||
|
@objects.objectify(objects.ptp)
|
||||||
|
def ptp_get(self, ptp_id):
|
||||||
|
return self._ptp_get(ptp_id)
|
||||||
|
|
||||||
|
@objects.objectify(objects.ptp)
|
||||||
|
def ptp_get_one(self):
|
||||||
|
query = model_query(models.PTP)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return query.one()
|
||||||
|
except NoResultFound:
|
||||||
|
raise exception.NotFound()
|
||||||
|
|
||||||
|
@objects.objectify(objects.ptp)
|
||||||
|
def ptp_get_list(self, limit=None, marker=None,
|
||||||
|
sort_key=None, sort_dir=None):
|
||||||
|
|
||||||
|
query = model_query(models.PTP)
|
||||||
|
|
||||||
|
return _paginate_query(models.PTP, limit, marker,
|
||||||
|
sort_key, sort_dir, query)
|
||||||
|
|
||||||
|
@objects.objectify(objects.ptp)
|
||||||
|
def ptp_get_by_isystem(self, isystem_id, limit=None, marker=None,
|
||||||
|
sort_key=None, sort_dir=None):
|
||||||
|
# isystem_get() to raise an exception if the isystem is not found
|
||||||
|
isystem_obj = self.isystem_get(isystem_id)
|
||||||
|
query = model_query(models.PTP)
|
||||||
|
query = query.filter_by(system_id=isystem_obj.id)
|
||||||
|
return _paginate_query(models.PTP, limit, marker,
|
||||||
|
sort_key, sort_dir, query)
|
||||||
|
|
||||||
|
@objects.objectify(objects.ptp)
|
||||||
|
def ptp_update(self, ptp_id, values):
|
||||||
|
with _session_for_write() as session:
|
||||||
|
query = model_query(models.PTP, session=session)
|
||||||
|
query = add_identity_filter(query, ptp_id)
|
||||||
|
|
||||||
|
count = query.update(values, synchronize_session='fetch')
|
||||||
|
if count != 1:
|
||||||
|
raise exception.PTPNotFound(ptp_id=ptp_id)
|
||||||
|
return query.one()
|
||||||
|
|
||||||
|
def ptp_destroy(self, ptp_id):
|
||||||
|
with _session_for_write() as session:
|
||||||
|
query = model_query(models.PTP, session=session)
|
||||||
|
query = add_identity_filter(query, ptp_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
query.one()
|
||||||
|
except NoResultFound:
|
||||||
|
raise exception.PTPNotFound(ptp_id=ptp_id)
|
||||||
|
|
||||||
|
query.delete()
|
||||||
|
|
||||||
|
def ptp_fill_empty_system_id(self, system_id):
|
||||||
|
values = {'system_id': system_id}
|
||||||
|
with _session_for_write() as session:
|
||||||
|
query = model_query(models.PTP,
|
||||||
|
session=session)
|
||||||
|
query = query.filter_by(system_id=None)
|
||||||
|
query.update(values, synchronize_session='fetch')
|
||||||
|
|
||||||
# NOTE: method is deprecated and provided for API compatibility.
|
# NOTE: method is deprecated and provided for API compatibility.
|
||||||
# object class will convert Network entity to an iextoam object
|
# object class will convert Network entity to an iextoam object
|
||||||
@objects.objectify(objects.oam_network)
|
@objects.objectify(objects.oam_network)
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from sqlalchemy import Integer, String, Boolean, DateTime
|
||||||
|
from sqlalchemy import Column, MetaData, Table, ForeignKey
|
||||||
|
|
||||||
|
ENGINE = 'InnoDB'
|
||||||
|
CHARSET = 'utf8'
|
||||||
|
|
||||||
|
def _populate_ptp_table(migrate_engine, meta, ptp, i_system):
|
||||||
|
"""This function inserts all the initial data about journals,
|
||||||
|
into the ptp table.
|
||||||
|
"""
|
||||||
|
|
||||||
|
sys = list(i_system.select().where(i_system.c.uuid is not None).execute())
|
||||||
|
if len(sys) > 0:
|
||||||
|
ptp_insert = ptp.insert()
|
||||||
|
ptp_uuid = str(uuid.uuid4())
|
||||||
|
values = {'created_at': datetime.now(),
|
||||||
|
'updated_at': None,
|
||||||
|
'deleted_at': None,
|
||||||
|
'uuid': ptp_uuid,
|
||||||
|
'enabled': False,
|
||||||
|
'mode': 'hardware',
|
||||||
|
'transport': 'l2',
|
||||||
|
'mechanism': 'e2e',
|
||||||
|
'system_id': sys[0].id,
|
||||||
|
}
|
||||||
|
ptp_insert.execute(values)
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(migrate_engine):
|
||||||
|
|
||||||
|
meta = MetaData()
|
||||||
|
meta.bind = migrate_engine
|
||||||
|
|
||||||
|
i_system = Table('i_system', meta, autoload=True)
|
||||||
|
ptp = Table(
|
||||||
|
'ptp',
|
||||||
|
meta,
|
||||||
|
Column('created_at', DateTime),
|
||||||
|
Column('updated_at', DateTime),
|
||||||
|
Column('deleted_at', DateTime),
|
||||||
|
|
||||||
|
Column('id', Integer, primary_key=True, nullable=False),
|
||||||
|
Column('uuid', String(36), unique=True),
|
||||||
|
|
||||||
|
Column('enabled', Boolean, default=False),
|
||||||
|
Column('mode', String(16), default='hardware'),
|
||||||
|
Column('transport', String(4), default='l2'),
|
||||||
|
Column('mechanism', String(4), default='e2e'),
|
||||||
|
|
||||||
|
Column('system_id', Integer,
|
||||||
|
ForeignKey('i_system.id', ondelete="CASCADE"),
|
||||||
|
nullable=True),
|
||||||
|
|
||||||
|
mysql_engine=ENGINE,
|
||||||
|
mysql_charset=CHARSET,
|
||||||
|
)
|
||||||
|
ptp.create()
|
||||||
|
# Populate the new ptp table with the initial data
|
||||||
|
_populate_ptp_table(migrate_engine, meta, ptp, i_system)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade(migrate_engine):
|
||||||
|
meta = MetaData()
|
||||||
|
meta.bind = migrate_engine
|
||||||
|
|
||||||
|
ptp = Table('ptp', meta, autoload=True)
|
||||||
|
ptp.drop()
|
|
@ -809,6 +809,23 @@ class intp(Base):
|
||||||
system = relationship("isystem", lazy="joined", join_depth=1)
|
system = relationship("isystem", lazy="joined", join_depth=1)
|
||||||
|
|
||||||
|
|
||||||
|
class PTP(Base):
|
||||||
|
__tablename__ = 'ptp'
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
uuid = Column(String(36))
|
||||||
|
|
||||||
|
enabled = Column(Boolean, default=False)
|
||||||
|
mode = Column(String(16), default='hardware')
|
||||||
|
transport = Column(String(4), default='l2')
|
||||||
|
mechanism = Column(String(4), default='e2e')
|
||||||
|
|
||||||
|
system_id = Column(Integer,
|
||||||
|
ForeignKey('i_system.id', ondelete='CASCADE'))
|
||||||
|
|
||||||
|
system = relationship("isystem", lazy="joined", join_depth=1)
|
||||||
|
|
||||||
|
|
||||||
class StorageTier(Base):
|
class StorageTier(Base):
|
||||||
__tablename__ = 'storage_tiers'
|
__tablename__ = 'storage_tiers'
|
||||||
|
|
||||||
|
|
|
@ -50,13 +50,14 @@ from sysinv.objects import load
|
||||||
from sysinv.objects import lvg
|
from sysinv.objects import lvg
|
||||||
from sysinv.objects import memory
|
from sysinv.objects import memory
|
||||||
from sysinv.objects import network
|
from sysinv.objects import network
|
||||||
|
from sysinv.objects import network_oam
|
||||||
from sysinv.objects import node
|
from sysinv.objects import node
|
||||||
from sysinv.objects import ntp
|
from sysinv.objects import ntp
|
||||||
from sysinv.objects import network_oam
|
|
||||||
from sysinv.objects import pci_device
|
from sysinv.objects import pci_device
|
||||||
from sysinv.objects import peer
|
from sysinv.objects import peer
|
||||||
from sysinv.objects import port
|
from sysinv.objects import port
|
||||||
from sysinv.objects import profile
|
from sysinv.objects import profile
|
||||||
|
from sysinv.objects import ptp
|
||||||
from sysinv.objects import pv
|
from sysinv.objects import pv
|
||||||
from sysinv.objects import remote_logging
|
from sysinv.objects import remote_logging
|
||||||
from sysinv.objects import route
|
from sysinv.objects import route
|
||||||
|
@ -137,6 +138,7 @@ community = community.Community
|
||||||
user = user.User
|
user = user.User
|
||||||
dns = dns.DNS
|
dns = dns.DNS
|
||||||
ntp = ntp.NTP
|
ntp = ntp.NTP
|
||||||
|
ptp = ptp.PTP
|
||||||
oam_network = network_oam.OAMNetwork
|
oam_network = network_oam.OAMNetwork
|
||||||
storage_backend = storage_backend.StorageBackend
|
storage_backend = storage_backend.StorageBackend
|
||||||
storage_ceph = storage_ceph.StorageCeph
|
storage_ceph = storage_ceph.StorageCeph
|
||||||
|
@ -201,6 +203,7 @@ __all__ = (system,
|
||||||
user,
|
user,
|
||||||
dns,
|
dns,
|
||||||
ntp,
|
ntp,
|
||||||
|
ptp,
|
||||||
oam_network,
|
oam_network,
|
||||||
storage_backend,
|
storage_backend,
|
||||||
storage_ceph,
|
storage_ceph,
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
from sysinv.db import api as db_api
|
||||||
|
from sysinv.objects import base
|
||||||
|
from sysinv.objects import utils
|
||||||
|
|
||||||
|
|
||||||
|
class PTP(base.SysinvObject):
|
||||||
|
|
||||||
|
dbapi = db_api.get_instance()
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
'id': int,
|
||||||
|
'uuid': utils.str_or_none,
|
||||||
|
|
||||||
|
'enabled': utils.bool_or_none,
|
||||||
|
'mode': utils.str_or_none,
|
||||||
|
'transport': utils.str_or_none,
|
||||||
|
'mechanism': utils.str_or_none,
|
||||||
|
|
||||||
|
'isystem_uuid': utils.str_or_none,
|
||||||
|
'system_id': utils.int_or_none
|
||||||
|
}
|
||||||
|
|
||||||
|
_foreign_fields = {
|
||||||
|
'isystem_uuid': 'system:uuid'
|
||||||
|
}
|
||||||
|
|
||||||
|
@base.remotable_classmethod
|
||||||
|
def get_by_uuid(cls, context, uuid):
|
||||||
|
return cls.dbapi.ptp_get(uuid)
|
||||||
|
|
||||||
|
def save_changes(self, context, updates):
|
||||||
|
self.dbapi.ptp_update(self.uuid, updates)
|
|
@ -62,6 +62,7 @@ class PlatformPuppet(base.BasePuppet):
|
||||||
config = {}
|
config = {}
|
||||||
config.update(self._get_host_platform_config(host, config_uuid))
|
config.update(self._get_host_platform_config(host, config_uuid))
|
||||||
config.update(self._get_host_ntp_config(host))
|
config.update(self._get_host_ntp_config(host))
|
||||||
|
config.update(self._get_host_ptp_config(host))
|
||||||
config.update(self._get_host_sysctl_config(host))
|
config.update(self._get_host_sysctl_config(host))
|
||||||
config.update(self._get_host_drbd_config(host))
|
config.update(self._get_host_drbd_config(host))
|
||||||
config.update(self._get_host_upgrade_config(host))
|
config.update(self._get_host_upgrade_config(host))
|
||||||
|
@ -430,6 +431,20 @@ class PlatformPuppet(base.BasePuppet):
|
||||||
'platform::ntp::ntpdate_timeout': ntpdate_timeout,
|
'platform::ntp::ntpdate_timeout': ntpdate_timeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _get_host_ptp_config(self, host):
|
||||||
|
ptp = self.dbapi.ptp_get_one()
|
||||||
|
|
||||||
|
return {
|
||||||
|
'platform::ptp::enabled':
|
||||||
|
ptp.enabled,
|
||||||
|
'platform::ptp::mode':
|
||||||
|
ptp.mode,
|
||||||
|
'platform::ptp::transport':
|
||||||
|
ptp.transport,
|
||||||
|
'platform::ptp::mechanism':
|
||||||
|
ptp.mechanism,
|
||||||
|
}
|
||||||
|
|
||||||
def _get_host_sysctl_config(self, host):
|
def _get_host_sysctl_config(self, host):
|
||||||
config = {}
|
config = {}
|
||||||
|
|
||||||
|
|
|
@ -1873,3 +1873,22 @@ class TestMigrations(BaseMigrationTestCase, WalkVersionsMixin):
|
||||||
for col, coltype in ntps_col.items():
|
for col, coltype in ntps_col.items():
|
||||||
self.assertTrue(isinstance(ntps.c[col].type,
|
self.assertTrue(isinstance(ntps.c[col].type,
|
||||||
getattr(sqlalchemy.types, coltype)))
|
getattr(sqlalchemy.types, coltype)))
|
||||||
|
|
||||||
|
def _check_075(self, engine, data):
|
||||||
|
# Assert data types for all columns in new table "ptp"
|
||||||
|
ptp = db_utils.get_table(engine, 'ptp')
|
||||||
|
ptp_cols = {
|
||||||
|
'created_at': 'DateTime',
|
||||||
|
'updated_at': 'DateTime',
|
||||||
|
'deleted_at': 'DateTime',
|
||||||
|
'id': 'Integer',
|
||||||
|
'uuid': 'String',
|
||||||
|
'enabled': 'Boolean',
|
||||||
|
'mode': 'String',
|
||||||
|
'transport': 'String',
|
||||||
|
'mechanism': 'String',
|
||||||
|
'system_id': 'Integer',
|
||||||
|
}
|
||||||
|
for col, coltype in ptp_cols.items():
|
||||||
|
self.assertTrue(isinstance(ptp.c[col].type,
|
||||||
|
getattr(sqlalchemy.types, coltype)))
|
||||||
|
|
Loading…
Reference in New Issue