VMware Licence Service Service Definition
What is the VMware Licence Service?
The VMware Licence Service (VLS) is an innovative licensing model designed with VMware to make it easier to modernise your existing VMware environments as you migrate to the cloud. VLS enables you to exchange the fixed cost of your ongoing VMware Support and Subscription (SnS) Service for existing perpetual VMware licences with a VMware Cloud Provider Programme (VCPP) consumption-based licence provided by UKCloud.
This ideally suits customers who:
Want to migrate to a full rental/consumption-based OPEX model rather than a fixed-cost (that is, CAPEX-centric) model on either an annual or monthly basis
Want to expand their VMware estate without the associated upfront capital expense
Are in the middle of cloud migration and are seeing a steady decrease in their on-premises requirements, and therefore seek a flexible licensing model rather than a more traditional three-year Enterprise License Agreement (ELA)
Want to benefit from UKCloud's partnership with VMware to switch to a viable, cost-effective and efficient model offered by VMware
What the service can help you achieve
Reduce costs. VLS calculates your VMware support costs on a different basis to standard fixed CPU licences by utilising UKCloud's bulk purchasing cost advantage, which typically delivers 15-25% cost reductions.
Financial efficiency. Choice of annual or monthly payments depending on your specific circumstances or organisation requirements, with incremental discounts delivered for annual payment.
Only pay for what you use. Your consumption is based on the output reporting of the VMware usage meter, which directly relates to your actual operational licences. No longer pay for licences sitting on shelves or on powered-off servers.
Scalability. VMware metered licensing is entirely flexible, so can scale up and down as your needs change.
Flexibility. An easier and more cost-effective method for adopting new VMware technologies, without committing to the purchase cost of perpetual licenses. Utilise enhanced features or capabilities with just a small monthly increase in consumption reporting.
Mix and match SnS with VLS. You can utilise both traditional SnS and VLS in the same environment so that existing support arrangements can continue, with new VLS licences layered on top.
Advantages of utilising UKCloud
VLS is a service delivered by UKCloud, a specialist VMware Cloud Verified Provider, headquartered in the UK and dedicated to serving public sector organisations with over eight years' experience in providing and supporting VMware cloud workloads.
UK-based, award-winning service desk, manned 24/7 by vetted and security-cleared experts.
Every UKCloud customer has a designated Service Delivery Manager regardless of usage or number of workloads.
Migration to multi-cloud (a mix of true public cloud and secure private cloud spanning on-premises, Crown Campus and hyperscaler) becomes cheaper, faster and safer with UKCloud's portfolio of Cloud Services, Professional Services and Managed Services.
Fixed-price or metered service available.
Licence eligibility
Includes:
vROps, vSAN, NSX, SRM, Workstation
All licences that are captured in the usage meter
Excludes:
- WSP1, Avi Networks, Velocloud, Carbon Black, Pivotal (until these appear on the VCPP product guide)
What's involved?
To administer VLS, three changes are required to the existing VMware environment:
New licence keys must be 'injected' into all VMware products covered under VLS, as these keys represent the new consumption-based service arrangement. This is a very simple activity that can be done by the customer or UKCloud. As part of the onboarding the customer will ensure that all elements of the environment are on a supported version of VMware software.
The VMware metering tool will be deployed as this delivers accurate consumption / utilisation that enables variable costs to be compared against the pre-agreed fixed cost.
- The customer is responsible for providing the usage reports to UKCloud within the first five working days of each month. Failure to do so is a breach of contract and costs will be estimated.
Customers will be supported by UKCloud's experienced technical services team and will receive the same level of support as they would directly from VMware. Any remediation of the customer environment will be performed by the customer.
What's included?
The service is designed to be flexible and comes with our standard onboarding:
Creation of a UKCloud Portal account. Enabling you to access our ticketing system and notifications centre.
UKCloud licensing keys. We will create and distribute unique VMware licence keys for you to use with this service for the relevant software.
Knowledge Centre. Access to our extensive library of articles to assist you in using VMware on a self-service basis.
Support services. UKCloud becomes the authorised 24/7 service desk for VMware support and provides first and second-line support for the VMware products within the environment, and will manage escalations for third-line support via the VMware engineering team as appropriate. All tickets are prioritised and full details are available in our Knowledge Centre.
Additional, optional services are available, including the following:
Enhanced onboarding. UKCloud can install and configure the VMware Usage Meter and replace existing perpetual licence keys with VCPP licence keys across all applicable VMware products within the environment.
Monitoring and management service. UKCloud can remotely monitor the VMware products within the environment, alert you of any incidents if appropriate and provide a high level of engagement appropriate with the level of managed services. This may include patching, capacity management, performance management or supporting non-VMware products (Storage Array, Physical Network).
Professional services. UKCloud can provide specialist Professional Services to help you assess your environment, create an actionable cloud strategy and migrate workloads to the UKCloud multi-cloud environment. UKCloud can also provide expert services to help you adopt cloud-native approaches such as DevOps, automation, and containerisation.
Pricing and packaging
VLS starts at 43p per point per month for academia. Full pricing is available in the UKCloud Pricing Guide.
Accreditation and information assurance
The security of our platform is our number one priority. We've always been committed to adhering to exacting standards, frameworks and best practice. Everything we do is subject to regular independent validation by government accreditors, sector auditors and management system assessors. Details are available on the UKCloud website.
Connectivity options
UKCloud provides one of the best-connected cloud platforms for the UK Public Sector. We enable access to our secure platform by DDoS-protected internet, PSN, Janet, HSCN and RLI and your own leased lines via our HybridConnect or CrownConnect services. The full range of flexible connectivity options is detailed in the UKCloud Pricing Guide.
An SLA you can trust
We understand that enterprise workloads need a dependable service that underpins the reliability of the application to users and other systems, which is why we offer one of the best SLAs on G-Cloud. For full details on the service SLA, including measurements and service credits, see the SLA definition.
The small print
For full terms and conditions, including onboarding and responsibilities, refer to the Terms and Conditions documents.
For more information about this service, see the Service Scope.
Why UKCloud?
UKCloud is dedicated to the digital transformation of our nation's public services through our flexible, secure and cost-effective multi-cloud platform and the expertise of our people and partners. We believe that diversity of technology drives value and innovation and so we bring together different cloud technologies, with different deployment models spanning on-premises (private cloud), on-campus (Government's Crown Campus) and off-campus global public cloud services. This enables you to choose the right cloud for creating new workloads or migrating or replacing existing applications to the cloud with specialist SaaS solutions.
We recognise the importance of public services to UK citizens and businesses, which is why we include the highest level of support to all our customers at no extra cost. This includes dedicated 24/7 UK support, a Network Operations Centre (NOC), utilising protective and proactive monitoring tools, and access to UKCloud's experts. UKCloud can also provide outcome-based professional services or managed services to help you with digital transformation.
Feedback
If you find a problem with this article, click Improve this Doc to make the change yourself or raise an issue in GitHub. If you have an idea for how we could improve any of our services, send an email to feedback@ukcloud.com.


The Salmon Cookie Fishery
Welcome to our delicious fishery.
The home of the Famous Salmon Cookie with the Fishy Center
Sales
Locations
Hours
About this site


We weren’t supposed to see Yoenis Cespedes taking batting practice
by Peter BotteEndy Chavez deleted his video throwing batting practice to injured Mets star Yoenis Cespedes quicker than Yadier Molina’s home run rendered his game-saving catch in the 2006 NLCS an afterthought.
“Throwing BP to a prospect in recovery,” Chavez, now a minor-league instructor for the organization, posted as a caption alongside the video Tuesday morning on Instagram.
Several outlets captured it before it was removed from the social media site, including SNY, the team’s television network.
Last week at the GM meetings in Arizona, Mets general manager Brodie Van Wagenen indicated that Cespedes’ status for 2020 remains uncertain. The $110 million outfielder missed all of last season with an ankle injury suffered on his Florida ranch while recuperating from surgeries on both heels from the previous year.
“I don’t have enough information to predict when he’s going to be back,” Van Wagenen said of Cespedes, who is due to earn $29.5 million in the final year of his contract.


Is an interactive web-based visualization tool that provides researchers in the field of human studies with a novel visualization method for their datasets, as well as a web-based access to such data. Subject-Book provides two level of data abstraction. The high-level ,where the essence of a study’ s data is condensed and presented in a single figure giving an overview of the study that helps identify the interesting patterns on the fly, and the low-level, which provides a more detailed picture of the data helping users understand the relationship between different pieces of data, confirm found patterns, or disambiguate unexpected observations.
Making your data compatible with our tool is easy and straightforward. There are only few steps you need to follow.
Having created your study, It is time to enjoy the unique view that SubjectBook provide for your data. Navigating between sessions has been made intuitive and friendly.
SubjectBook is an interactive tool that allows researchers to interact with the visualized data to gain more in-depth knowledge about their data helping them find the hidden patterns.


View features based on age-groups. Feel free to check out all the features.
Share your amazing thoughts and write-ups with others and read others write-ups too.
Share NowDon't have an idea about what or how to cook your favourite dish, we got you covered. Use meal-finder to find recipes.
Find Meals NowShare your amazing thoughts and write-ups with others and read others write-ups too.
Solve puzzles which includes images of seven wonders of world with 3 difficulty modes.
Be mesmerised by the beauty of nature. Watching nature helps us remain calm and fills us with positivity.
View ImagesWe brought in the common bill payments, major stores, etc. to one site which also provides learning, entertainment and is informative for all age groups.
Major Sites
A wide variety of stores and major sites like Amazon, Myntra, Dominos, IRCTC, Times of India, etc. brought under one site.
Payment Categories
Pay all major household bills like electricity bill, piped gas bills, etc.; mobile and dth recharges at a single place.
Features
Lots of features like learning, games, multiplayer game, book finder, movie finder, meal finder, recipe sharing, etc.


Earlier today, FIRSTNAME LASTNAME, a recently employed Associate Consultant, was conclusively proven to be a dangerous terrorist working for IAM, the notorious subversive hacker collective.
"We suspected TITLE LASTNAME from the beginning," says Vitaly Vedenin, head of Information Acquisition for the UK branch. "Our background checks had revealed certain disturbing connections, so when PRONOUN applied for a position, we kept OBJECTPRONOUN under strict supervision."
"To test POSSESSIVE loyalty, AlethiCorp employees made contact, posing as IAM operatives. FIRSTNAME immediately demanded to be involved in the most dangerous IAM assignments and insisted that the subversive cause justified any means."
"I was taken aback by FIRSTNAME's bloodlust," says Oskar Jönsson, head of IT security, who ran the operation along with Information Acquisition. "I was expecting OBJECTPRONOUN to report the contact to security, but instead PRONOUN gleefully embraced the opportunity to work with IAM terrorists."
"At the end of the operation, we made FIRSTNAME believe that IAM had given OBJECTPRONOUN access to drone strikes. FIRSTNAME wasted no time in organizing what would have been an unprecedented act of mass murder, had this whole thing not been a carefully controlled sting operation. It sends chills down my spine when I consider what might have happened had FIRSTNAME LASTNAME not been exposed."
"What makes the matter even worse," continues Mr. Jönsson, "Is that FIRSTNAME is now trying to claim that PRONOUN was merely playing along with the hackers, as part of some ludicrous triple-agent scheme. Why, PRONOUN is even saying that security was aware of this. Luckily, there are tons of employees who can testify to the absurdity of this claim. TITLE LASTNAME would do well to accept responsibility for POSSESSIVE crimes, if PRONOUN wants any chance of clemency."
"This is a tragic event", says CEO Alex DuMaurier, speaking to a group of approved media representatives. "But it also confirms the importance of the work we are doing here at AlethiCorp. Were it not for our information management efforts, there is no telling how many innocents might have been killed by FIRSTNAME LASTNAME's terrorist acts.
"However, we must remember that FIRSTNAME LASTNAME, and others like OBJECTPRONOUN, are misguided souls, who should be pitied, not hated. We are working with the Larkhill Resettlement Council to resettle TITLE LASTNAME to a high-security location, where PRONOUN can live POSSESSIVE life, without being a danger to ordinary citizens. Let us hope that PRONOUN will one day find a measure of peace."
Added Mx. DuMaurier: "In retrospect, we should have seen it coming. Those 'BEARTYPE' types are never reliable. I will ensure that steps are taken to improve our hiring processes."


{@link javax.xml.bind.annotation.adapters.XmlAdapter XmlAdapter} for the setting map used by {@link hu.sllauncher.bean.settings.SettingsBean SettingsBean}.


Original idea from Raphael and Matthieu using Simon 's button design and a royalty free music from Bensound.


Your face is your password
These apps support the Pixel 4's face unlock feature
Let's see if your favorite apps work with the Pixel 4.
by Joe MaringThe Pixel 4 is an important phone for the Android landscape. The 90Hz display, dual rear cameras, and wireless charging are all perfectly cool, but the thing that really makes it stand out is Google's all-new face unlock system.
We've seen other Android phones offer face unlock in the past, but the Pixel 4 is the first one that's secure enough to be useful beyond the lock screen — meaning you can use face unlock on the Pixel 4 to authorize purchases and log in to apps — such as mobile banking apps and password managers.
If you pick up your Pixel 4 and realize that face unlock doesn't work with your favorite apps, however, you're not doing anything wrong. Developers need to support Google's BiometricPrompt API in order for it to work, and the adoption of it has been quite slow.
Apps that currently work with the Pixel 4's face unlock
- 1Password
- Bank of America
- Dashlane
- Keeper
- LastPass (in beta)
- Navy Federal Credit Union
- Password Safe
- Enpass
- Robinhood
- Venmo
- Turbo
Apps that have confirmed to be working on the Pixel 4's face unlock
- American Express (no set date)
- U.S. Bank (no set date)
- Wells Fargo (no set date)
Waiting game
As you can see, the list of apps that already work with the Pixel 4's face unlock is ... disappointing, to say the least.
In order for the Pixel 4's face unlock to work, apps need to support the BiometricPrompt API. As of November 1, apps released to the Play Store have to support the API if they want to offer biometric authentication of any sort, but apps aren't forced to support it on that date, but simply for their next update after that date. We just have to hope that Google really pushes developers to get their updates out sooner.
For you and everyone else that buys the Pixel 4, that could mean waiting months before your banking app supports face unlock on the Pixel 4. Until then, you'll be stuck entering a password or PIN each time you want to access sensitive apps like that.
We're actively reaching out to companies to see if they have a timeline for supporting the Pixel 4's face unlock, and as we learn more, we'll keep this list up-to-date.
Unlock with your face
Google Pixel 4
Android's best face unlock still has room to grow.
The Google Pixel 4 stands out for a lot of reasons, one of which is its powerful face unlock system. Not only is it one of the fastest implementations we've ever seen, it's also secure enough to go beyond the lock screen and work with app logins.
We may earn a commission for purchases using our links. Learn more.


|
Class Summary |
| BetaDistribution |
BetaDistribution distribution is the posterior distribution of the parameter p of a binomial distribution
after observing α − 1 independent events with probability p and
β − 1 with probability 1 − p ,
if the prior distribution of p is uniform. |
| ChiSquareDistribution |
Chi-square distribution is the distribution of
the sum of the squares of a set of statistically independent standard Gaussian random variables. |
| EmpiricalDistribution |
An empirical cumulative probability distribution function
is a cumulative probability distribution function that
assigns probability 1/n at each of the n numbers in a sample. |
| ExponentialDistribution |
An exponential distribution describes the times between events in a Poisson process,
a process in which events occur continuously and independently at a constant average rate. |
| FDistribution |
FDistribution distribution is the distribution of the ratio of two independent chi-squared variates. |
| GammaDistribution |
GammaDistribution distribution, when k is an integer, is the distribution of
the sum of k independent exponentially distributed random variables,
each of which has a mean of θ (which is equivalent to a rate parameter of θ−1 ). |
| NormalDistribution |
The NormalDistribution distribution has its density of a Gaussian function. |
| RayleighDistribution |
The L2 norm of (x1, x2) , where xi 's are normal, uncorrelated, equal variance and
have RayleighDistribution distributions. |
| TDistribution |
Student's t distribution is the probability distribution of t , where
x̄ - μ
t = ------------
s / sqrt(N)
x̄ is the sample mean;
μ is the population mean;
s is the square root of the sample variance;
N is the sample size;
The importance of the Student's distribution is
when (as in nearly all practical statistical work) the population standard deviation is unknown and has to be estimated from the data. |
| WeibullDistribution |
The WeibullDistribution distribution interpolates between the exponential distribution (k = 1) and the Rayleigh distribution (k = 2),
where k is the shape parameter. |


Overview
IDEO Shanghai is offering a summer internship for talented Chinese students who are interested in exploring a career of creating positive impact through design.
We will provide you with a rapid guided learning experience that enables you to practice, experiment with, and master a variety of skills. Our people, our process, and our design-led projects will inspire you to imagine new possibilities for your career.
Our internship is two months long, and will begin in early July.
GET YOUR HANDS DIRTY
The bulk of the program is centered around fast-paced projects at IDEO Shanghai. You may work on a project to redefine the mission of an international brand in China; paint a vision for the future kitchen; or even design a new venture from scratch. Every intern is expected to be a contributing team member along the entire design thinking process.
ENGAGE A CREATIVE NETWORK
We believe that young talent are best inspired when they can meet new people who can become new role models. As an intern, you will meet a variety of talented people from the IDEO creative network, and have the chance to broaden your perspective by speaking with designers who come from wildly diverse backgrounds.
LEARN, REFLECT, & SHINE
As part of the program, you will have several mentors and guides to help you along your journey. We will provide a safe space for you to test out personal projects that showcase your passion and creativity, and provide advice on things like IDEO’s culture, skill development, and potential future career paths.

SOMEONE WHO BRINGS YOUR WHOLE SELF TO WORK
We want to get inspired by you! You are someone who inspires us to look at the world through a different lens. If you have any unique skills, experiences, or points of view, please let us know! IDEO’ers are more than just designers, we are also documentarians, drummers, and stand-up comedians.
PASSIONATE ABOUT DESIGN THINKING
We are looking for students who understand the fundamentals of our methodology, and who are passionate about applying human-centered design to business challenges. Regardless of whether you are studying design, the social sciences, literature, or finance, you should have a strong interest in using your skills to drive social and business innovation in China.
HOW TO APPLY
Send your resume, a cover letter that includes answers to the below 2 questions, and any other materials that can help us to know you better to<EMAIL_ADDRESS>with “Summer Internship” in the subject line.
The deadline for submission is June 10, 2018. We look forward to hearing from you!
1) What you are most passionate about and why?
2) What are some of the unique things (e.g. skills, POV, network) you think you can bring to IDEO Shanghai?
Take a 1 min to fill in a questionnaire to help us get a better sense of who you are.


dprintf
, vdprintf
—print to a file descriptorSynopsis
#include <stdio.h> #include <stdarg.h> int dprintf(int fd, const char *restrict format, ...); int vdprintf(int fd, const char *restrict format, va_list ap); int _dprintf_r(struct _reent *ptr, int fd, const char *restrict format, ...); int _vdprintf_r(struct _reent *ptr, int fd, const char *restrict format, va_list ap);
Description
dprintf
and vdprintf
allow printing a format, similarly to
printf
, but write to a file descriptor instead of to a FILE
stream.
The functions _dprintf_r
and _vdprintf_r
are simply
reentrant versions of the functions above.
Returns
The return value and errors are exactly as for write
, except that
errno
may also be set to ENOMEM
if the heap is exhausted.
Portability
This function is originally a GNU extension in glibc and is not portable.
Supporting OS subroutines required: sbrk
, write
.


Specifying Document Title In PDFs
Source: https://www.w3.org/TR/WCAG20-TECHS/PDF18.html
Description
The intent of this technique is to show how a descriptive title for a PDF document can be specified for assistive technology by using the /Title entry in the document information dictionary and by setting the DisplayDocTitle flag to True in a viewer preferences dictionary. This is typically accomplished by using a tool for authoring PDF.
Document titles identify the current location without requiring users to read or interpret page content. User agents make the title of the page easily available to the user for identifying the page. For instance, a user agent may display the page title in the window title bar or as the name of the tab containing the page.
PDF18: Specifying the document title using the Title entry in the document information dictionary of a PDF document as Accessed 4 January 2019


The tuple/take.h
header defines an algorithm that extracts a user-specified number of elements from the beginning of a tuple.
#include <chaos/preprocessor/tuple/take.h>
The CHAOS_PP_TUPLE_TAKE
macro extracts the number of elements specified by its first argument from its second argument.
CHAOS_PP_TUPLE_TAKE
(n, tuple)
The number of elements to be extracted.
Valid values range from 0
to
.
CHAOS_PP_TUPLE_SIZE
(tuple)
The tuple from which elements are to be extracted.
This macro expands to a tuple containing the first n elements of tuple.
The efficiency of the algorithm's use of the recursion backend can be described in terms of the number of recursion steps required to complete the algorithm. The asymptotic upper and lower bounds are Θ, where n is n.
This macro operates on the nil tuple representation used by the core tuple operations defined in <chaos/preprocessor/tuple/core.h>
.
Specifically, ()
is a one-element tuple, not a zero-element tuple.
This macro uses bypass semantics.
If bypass semantics are already in effect, CHAOS_PP_TUPLE_TAKE_BYPASS
must be used instead.
CHAOS_PP_DROP
CHAOS_PP_RANGE
CHAOS_PP_SEQ_DROP
CHAOS_PP_SEQ_RANGE
CHAOS_PP_SEQ_TAKE
CHAOS_PP_TAKE
CHAOS_PP_TUPLE_DROP
CHAOS_PP_TUPLE_RANGE
#include<chaos/preprocessor/config.h>
#include<chaos/preprocessor/tuple/take.h>
#ifCHAOS_PP_VARIADICS
CHAOS_PP_TUPLE_TAKE
( 12, (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z) ) // (a, b, c, d, e, f, g, h, i, j, k, l) #endif
The CHAOS_PP_TUPLE_TAKE_ID
macro indirectly expands to CHAOS_PP_TUPLE_TAKE
.
CHAOS_PP_TUPLE_TAKE_ID
()
This macro effectively allows CHAOS_PP_TUPLE_TAKE
to pass through itself without becoming disabled.
The CHAOS_PP_TUPLE_TAKE_
macro expands to a λ expression representing CHAOS_PP_TUPLE_TAKE
.
CHAOS_PP_TUPLE_TAKE_
This macro is a shorthand form of the following λ binding:
The CHAOS_PP_TUPLE_TAKE_BYPASS
macro behaves identically to CHAOS_PP_TUPLE_TAKE
except that it is parametized by the bypass recursion state.
CHAOS_PP_TUPLE_TAKE_BYPASS
(s, n, tuple)
The current bypass recursion state.
The number of elements to be extracted.
Valid values range from 0
to
.
CHAOS_PP_TUPLE_SIZE
(tuple)
The tuple from which elements are to be extracted.
If bypass semantics are already in effect, this macro must be used instead of CHAOS_PP_TUPLE_TAKE
.
The CHAOS_PP_TUPLE_TAKE_BYPASS_ID
macro indirectly expands to CHAOS_PP_TUPLE_TAKE_BYPASS
.
CHAOS_PP_TUPLE_TAKE_BYPASS_ID
()
This macro effectively allows CHAOS_PP_TUPLE_TAKE_BYPASS
to pass through itself without becoming disabled.
The CHAOS_PP_TUPLE_TAKE_BYPASS_
macro expands to a λ expression representing CHAOS_PP_TUPLE_TAKE_BYPASS
.
CHAOS_PP_TUPLE_TAKE_BYPASS_
This macro is a shorthand form of the following λ binding:


Initial setup (may or may not be required)
Start with fresh samba files:
rm -rf /var/lib/samba; mkdir /var/lib/samba; rm -f /etc/samba/smb.conf
Make sure you can resolv to the DC
echo nameserver <IP_ADDRESS> > /etc/resolv.conf # this is the IP address of the DC
We have a command called "samba-tool drs clone-dc-database", which is similar to "samba-tool domain join DC". The difference is that it only tests the replication without creating an account for a new dc (and it requires the --targetdir option, which should point to a temporary location). This is developed for debugging purposes, but not for setting up another DC. You can read more about clone-dc-database and exportkeytab here.
There is also:
samba-tool drs clone-dc-database --include-secrets
You only need to be aware that the "SYSVOL" folder is not automatically replicated between windows and samba. And the GPO-GUI should only be used against the remaining windows server with manual syncing of the SYSVOL. You may also need to use "samba-tool ntacl sysvolreset" after the sync.
Now, the actual way to replicate is to join your new DC to the domain and then start replication. This can be done with:
samba-tool domain join <domain> DC -U domain\\username
There is a catch! Typically a DC replicates both ways, but as an attacker you may not want that to happen. There used to be a patch from securusglobal (see child page), but it no longer exists. If the text on their page shows the full patch, it should be simple to implement the patch in any installation of samba 4 by editing join.py.
The old way with patching
The patch essentially adds a GUID, calls .join_provision(), join_replicate(), and then returns (essentially stopping after a replicate).
The section that needs to be patched can be found in the source on
Github: samba/python/join.py
And (as of writing this) the do_join() function starts on line 1122.
What is interesting is (in the latest version) that a parameter ctx.clone_only essentially accomplishes what we want. By setting clone_only to true, join.py will call join_provision(), join_replicate(), and join_finalise().
clone_only is initially set to False in join.py __init__ on lines 51-56:
def __init__(ctx, logger=None, server=None, creds=None, lp=None, site=None,
netbios_name=None, targetdir=None, domain=None,
machinepass=None, use_ntvfs=False, dns_backend=None,
promote_existing=False, clone_only=False):
ctx.clone_only=clone_only
join_finalise has the same switches for clone_only. It will log some info, set a message element to "isSynchronized", will set the GUID for us to the remote_dc_ntds_guid, set message element to "dsServiceName", and then return.
These actions therefore cover everything from the original securus patch as long as you modify join.py and set clone_only=True.*
*Note I haven't actually tested this at all.
The new way with join_clone
Patching join.py can be done or (upon futher investigation) there is a method that can be called: join_clone
It automatically sets inits with clone_only=True, sets replica flags, and then calls do_join(). Simple as that.
This looks like it's called from class cmd_drs_clone_dc_database(Command) in drs, which will call join_clone.
It needs testing since the information at the top mentions it's only for debug, but if a simple:
samba-tool drs clone-dc-database <domain> --target-dir=/tmp
is all that is needed, then all the better.


|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object net.sourceforge.cilib.Container.Graph.Graph
An implementation of a Acyclic Graph Data structure.
| Constructor Summary | |
Graph()
Create a Graph data structure without a name |
|
Graph(java.lang.String name)
Create a Graph data structure and associate it with the given name |
| Method Summary | |
void |
addEdge(Edge e)
Add an edge to the Graph |
void |
addVertex(Vertex v)
Add a Vertex to the current Graph |
void |
breadthFirstTraversal(Visitor visitor,
Vertex startVertex)
Performs a breadth first traversal on the graph. |
void |
depthFirstTraversal(PrePostVisitor visitor,
Vertex startVertex)
A traversal of the Graph starting at a specific Vertex |
Edge |
getEdgeBetweenVerticies(Vertex v1,
Vertex v2)
Get the associated edge between two verticies. |
int |
getEdgeCount()
Get the number of edges currently in the Graph |
java.util.ListIterator |
getEdges()
Get an Iterator to the edge set |
java.lang.String |
getName()
Get the associated name of the Graph , if any |
int |
getNumberOfVertices()
Get the number of verticies contained in the Graph |
Vertex |
getVertexAt(int index)
Get the Vertex at a specific position in the list based on the index |
java.util.ListIterator |
getVertices()
Get an iterator to the verticies contained within the graph. |
java.util.ListIterator |
getVertices(int index)
Get an iterator to the verticies contained within the Graph . |
int |
indexOf(Vertex v)
Get the index of the vertex as contained in the internal container. |
void |
printGraphSummary()
Print a summary of the Graph structure. |
| Methods inherited from class java.lang.Object |
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Constructor Detail |
public Graph()
Graph
data structure without a name
public Graph(java.lang.String name)
Graph
data structure and associate it with the given name
name
- The name to be given to this Graph
| Method Detail |
public void addVertex(Vertex v)
Vertex
to the current Graph
v
- The Vertex to be inserted into the Graphpublic void addEdge(Edge e)
Graph
e
- The edge to be added to the Graph
public java.lang.String getName()
Graph
, if any
String
containing the name or null
if there is no namepublic int getNumberOfVertices()
Graph
public int getEdgeCount()
Graph
Graph
public Vertex getVertexAt(int index)
Vertex
at a specific position in the list based on the index
index
- The index at which to return the Vertex
public int indexOf(Vertex v)
v
- The Vertex
to have it's iondex returned
Vertex
in the internal containerpublic java.util.ListIterator getEdges()
Iterator
to the edge set
Iterator
to the edge setpublic Edge getEdgeBetweenVerticies(Vertex v1, Vertex v2)
v1
- A vertex to reference the edge fromv2
- A vertex to reference the edge to
Edge
created by the two verticies v1 and v2public java.util.ListIterator getVertices()
ListIterator
starting at index 0public java.util.ListIterator getVertices(int index)
Graph
.
index
- The position to start the interator.
ListIterator
starting at the specified indexpublic void depthFirstTraversal(PrePostVisitor visitor, Vertex startVertex)
Graph
starting at a specific Vertex
visitor
- The PrePostVisitor
to apply to the traversalstartVertex
- The Vertex
to start the traversal atpublic void breadthFirstTraversal(Visitor visitor, Vertex startVertex)
Vertex
startVertex
- The vertex to start the traversal frompublic void printGraphSummary()
Graph
structure. The summary is 2 fold. First the summary is based on
incident edges and then the summary is based on eminating edges.
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |


The great greek Chimera
In Greek mythology, the chimera is a three-headed, fire-breathing hybrid monster with the head and body of a lion, the head of a goat on its back and a tail that ends with a head of a snake. The legendary beast is the child of Typhoeus, the mightiest and deadliest monster, and Echidna, a half-snake, half-woman creature. Ancient Greek and Roman art have often shown this beast being slain by the hero Bellerophon while riding the winged horse Pegasus.
The term "chimera" has come to describe any mythical or fictional creature with parts taken from various animals, to describe anything composed of very disparate parts, or perceived as wildly imaginative, implausible, or dazzling.
The Chimera is generally considered to have been female (see the quotation from Hesiod above) despite the mane adorning her head, the inclusion of a close mane was often depicted on lionesses, but the ears were always visible (that does not occur with depictions of male lions).
While there are different genealogies, in one version the Chimera mated with her brother Orthrus and was the mother of the Sphinx and the Nemean lion (others have Orthrus and their mother, Echidna, mating; most attribute all to Typhon and Echidna).
The Chimera finally was defeated by Bellerophon with the help of Pegasus, at the command of King Iobates of Lycia, after terrorizing Lycia and nearby lands. Since Pegasus could fly, Bellerophon shot the Chimera from the air, safe from her heads and breath.[9]
From its brief above,the chimera can be a scary pet to have..but its still qualifies to be one of the most feared mythodological creatures ever lived....!
wanna get to know more fictional creatures..,click the link below..
link at..fictional pets!..


{% include 'graph/header.html' %}
{% include 'graph/body.html' %} {% include 'graph/javascript.html' %}


facet/facet.service.ts
Options for the [[FacetService.AddFilter]] and [[FacetService.AddFilterSearch]] methods
and: If multiple items are filtered, determines whether they are filtered as AND or OR not: Whether this is an exlusion of the filtered item replaceCurrent: if true, the current filter is replaced
Properties |
|
| and |
and:
|
Type : boolean
|
| Optional |
| forceAdd |
forceAdd:
|
Type : boolean
|
| Optional |
| not |
not:
|
Type : boolean
|
| Optional |
| replaceCurrent |
replaceCurrent:
|
Type : boolean
|
| Optional |
import {Injectable, Inject, Optional, InjectionToken} from "@angular/core";
import {UserSettingsWebService, UserSettings, Suggestion,
Results, Aggregation, AggregationItem, TreeAggregation, TreeAggregationNode,
AuditEvents, EngineType, Select, CCColumn
} from "@sinequa/core/web-services";
import {IntlService} from "@sinequa/core/intl";
import {Query, AppService, FormatService, ExprBuilder, Expr} from "@sinequa/core/app-utils";
import {FieldValue, Utils} from "@sinequa/core/base";
import {Subject, Observable, map} from "rxjs";
import {SearchService, BreadcrumbsItem, Breadcrumbs} from "@sinequa/components/search";
import {SuggestService} from "@sinequa/components/autocomplete";
import { FacetConfig } from "./facet-config";
import { Action } from "@sinequa/components/action";
// Facet interface (from models/UserSettings)
export interface FacetState {
name: string;
position: number; // eg 0 = left, 1 = right
}
/**
* Options for the [[FacetService.AddFilter]] and [[FacetService.AddFilterSearch]] methods
*
* and: If multiple items are filtered, determines whether they are filtered as AND or OR
* not: Whether this is an exlusion of the filtered item
* replaceCurrent: if true, the current filter is replaced
*/
export interface AddFilterOptions {
and?: boolean;
not?: boolean;
replaceCurrent?: boolean;
forceAdd?: boolean; // force a new select creation instead of append it into the current one
}
// Audit Events (from models/Audit)
export const enum FacetEventType {
Loaded = "Facet_Loaded",
Add = "Facet_Added",
AddAll = "Facets_Added",
Remove = "Facet_Removed",
RemoveAll = "Facets_Removed",
SetDefaults = "Facets_SetDefaults",
Patched = "Facet_Patched",
ClearFilters = "Facet_ClearFilters",
AddFilter = "Facet_AddFilter",
RemoveFilter = "Facet_RemoveFilter",
Open = "Facet_TreeOpen"
}
// Types of events triggering a change event
export const FACET_CHANGE_EVENTS = [
FacetEventType.Loaded,
FacetEventType.Add,
FacetEventType.AddAll,
FacetEventType.Remove,
FacetEventType.RemoveAll,
FacetEventType.SetDefaults
];
// CRUD Events
export interface FacetChangeEvent {
type: FacetEventType;
facet?: FacetState;
}
export const ALL_FACETS = new InjectionToken<FacetConfig<any>[]>('ALL_FACETS');
export const DEFAULT_FACETS = new InjectionToken<FacetState[]>('DEFAULT_FACETS');
@Injectable({
providedIn: 'root',
})
export class FacetService {
protected readonly _events = new Subject<FacetChangeEvent>();
protected readonly _changes = new Subject<FacetChangeEvent>();
constructor(
protected userSettingsService: UserSettingsWebService,
protected searchService: SearchService,
protected suggestService: SuggestService,
protected appService: AppService,
protected intlService: IntlService,
protected formatService: FormatService,
protected exprBuilder: ExprBuilder,
@Optional() @Inject(ALL_FACETS) public allFacets: FacetConfig<{}>[],
@Optional() @Inject(DEFAULT_FACETS) public defaultFacets: FacetState[]){
// Listen to the user settings
this.userSettingsService.events.subscribe(event => {
// E.g. new login occurs
// ==> Menus need to be rebuilt
this.events.next({type: FacetEventType.Loaded});
});
// Listen to own events, to trigger change events
this._events.subscribe(event => {
if(FACET_CHANGE_EVENTS.indexOf(event.type) !== -1){
this.changes.next(event);
}
});
}
// GETTERS
/**
* Returns the list of this user's facets.
* The list is stored in the user settings (this is a redirection).
* Using this service creates the list of facets if it does not already exist.
*/
public get facets() : FacetState[] {
if(!this.userSettingsService.userSettings)
this.userSettingsService.userSettings = {};
if(!this.userSettingsService.userSettings["facets"]) {
this.userSettingsService.userSettings["facets"] = [];
if(!!this.defaultFacets){
this.userSettingsService.userSettings["facets"].push(...this.defaultFacets);
this.patchFacets();
}
}
return this.userSettingsService.userSettings["facets"];
}
/**
* @returns a facet with the given name or undefined if it does not exist
* @param name
*/
public facet(name: string): FacetState | undefined {
const i = this.facetIndex(name);
return i>= 0? this.facets[i] : undefined;
}
/**
* Returns the list of facet config in the given container (position)
* @param position (default to 0 if there is a single container)
*/
public getFacets(position: number = 0, results: Results) : FacetConfig<{}>[] {
if (!this.allFacets) {
return [];
}
return this.facets.filter(f => f.position === position)
.map(f => this.allFacets.find(_f => _f.name === f.name)!)
.filter(f => f && this.isFacetIncluded(f, results));
}
public isFacetIncluded(facet: FacetConfig<{}>, results: Results): boolean {
return !(facet.includedTabs && !facet.includedTabs.includes(results.tab)) && !facet.excludedTabs?.includes(results.tab)
}
/**
* Returns true if this facet is opened (in any container)
* @param facetName
*/
public isFacetOpened(facetName): boolean {
return !!this.facets.find(f => f.name === facetName);
}
protected facetIndex(name: string): number {
for (let i = 0, ic = this.facets.length; i < ic; i++) {
const facet = this.facets[i];
if (facet && facet.name === name) {
return i;
}
}
return -1;
}
/**
* Triggers any events regarding the facets
*/
public get events(): Subject<FacetChangeEvent> {
return this._events;
}
/**
* Triggers when events affect the list of facets
* Cf. CHANGE_EVENTS list
*/
public get changes() : Subject<FacetChangeEvent> {
return this._changes;
}
public addFacet(facet: FacetState){
this.facets.push(facet);
this.updateFacets(FacetEventType.Add, facet);
}
public removeFacet(facet: FacetState){
const i = this.facetIndex(facet.name);
if(i !== -1){
this.facets.splice(i,1);
this.updateFacets(FacetEventType.Remove, facet);
}
}
public setDefaultFacets() {
this.facets.splice(0);
if(!!this.defaultFacets) this.facets.push(...this.defaultFacets);
this.updateFacets(FacetEventType.SetDefaults);
}
public addAllFacets() {
this.facets.splice(0);
if(!!this.allFacets) this.allFacets.forEach(f => this.facets.push({name: f.name, position: 0}));
this.updateFacets(FacetEventType.AddAll);
}
public removeAllFacets() {
this.facets.splice(0);
this.updateFacets(FacetEventType.RemoveAll);
}
public updateFacets(type: FacetEventType, facet?: FacetState) {
this.events.next({type, facet});
const detail = facet? { facet: facet?.name } : undefined
this.patchFacets([{type, detail}]);
}
public createFacetMenu(): Action {
const outFacets: Action[] = [];
outFacets.push(new Action({
name: `set_defaults`,
text: "msg#facet.filters.setDefaults",
title: "msg#facet.filters.setDefaults",
action: () => {
this.setDefaultFacets();
}
}));
outFacets.push(new Action({
name: `add_all`,
text: "msg#facet.filters.addAll",
title: "msg#facet.filters.addAll",
action: () => {
this.addAllFacets();
}
}));
outFacets.push(new Action({
name: `remove_all`,
text: "msg#facet.filters.removeAll",
title: "msg#facet.filters.removeAll",
action: () => {
this.removeAllFacets();
}
}));
outFacets.push(new Action({separator: true}));
for (const facet of this.allFacets) {
outFacets.push(new Action({
name: `add_remove_${facet.name}`,
text: facet.title,
icon: facet.icon,
selected: !!this.facets?.find(userFacet => userFacet.name === facet.name),
title: !!this.facets?.find(userFacet => userFacet.name === facet.name) ? "msg#facet.filters.add" : "msg#facet.filters.remove",
action: () => {
const fs = this.facets?.find(userFacet => userFacet.name === facet.name);
if (fs) {
this.removeFacet(fs);
}
else {
this.addFacet({name: facet.name, position: 0});
}
}
}));
}
return new Action({
name: "facets_config",
icon: "fas fa-cog",
title: "msg#facet.filters.customizeFacets",
scrollable: true,
children: outFacets
});
}
/**
* Updates facets in User settings.
* @param auditEvents : Audit Events to be triggered
* @returns an Observable which can be used to trigger further events
*/
protected patchFacets(auditEvents?: AuditEvents) {
return this.userSettingsService.patch({facets: this.facets} as UserSettings, auditEvents)
.subscribe(
next => {
this.events.next({type: FacetEventType.Patched});
},
error => {
console.error("Could not patch Facets!", error);
});
}
/**
* Filter/Exclude an item in a facet and launch a search.
* Triggers an internal event and an Audit Event
* @param facetName
* @param aggregation
* @param items
* @param options
*/
public addFilterSearch(
facetName: string,
aggregation: Aggregation,
items: AggregationItem | AggregationItem[],
options: AddFilterOptions = {}): Promise<boolean> {
const success = this.addFilter(facetName, aggregation, items, options);
if(success) {
this.events.next({ type: FacetEventType.AddFilter, facet: this.facet(facetName) });
if(this.searchService.isSearchRouteActive()) {
return this.searchService.search(undefined, {
type: FacetEventType.AddFilter,
detail: {
item: <any>this.searchService.query.lastSelect(),
itembox: facetName,
itemcolumn: aggregation.column,
isitemexclude: options.not,
"from-result-id": this.searchService.results?.id
}
});
}
}
return Promise.resolve(false);
}
/**
* Filter/Exclude one or more item(s) in a facet (without launching a search)
* @param facetName
* @param aggregation
* @param items
* @param options
* @param query the query on which to add the filter (defaults to search service query)
* @param breadcrumbs breadcrumbs in which to look for selected items (defaults to search service breadcrumbs)
*/
public addFilter(
facetName: string,
aggregation: Aggregation,
items: AggregationItem | AggregationItem[],
options: AddFilterOptions = {},
query = this.searchService.query,
breadcrumbs = this.searchService.breadcrumbs): boolean {
if (!items) {
return false;
}
// if options.forceAdd is true, we add the filter as a new "select"
// if options.replaceCurrent is true, previous "select" is remove first
// otherwise, we try to append new filter to previous "select"
if (options.replaceCurrent) {
query.removeSelect(facetName);
} else if (!aggregation.isTree && breadcrumbs?.activeSelects.length && !options.forceAdd) {
// here, we try to add a filter to the previous selection
const existingExpr = breadcrumbs.findSelect(facetName);
const existingSelectIndex = breadcrumbs.activeSelects.findIndex(select => select.facet === facetName && (select.expr === existingExpr || select.expr === existingExpr?.parent));
/* if items is not an array (just a single selection filter),
* just append it to the existing filter.
* so, we are assuming that new filter selection is the same 'select" as previous one.
*/
const isSameSelect = (!Array.isArray(items)) ? true : (options.and ? "AND" : "OR") === (existingExpr?.and ? "AND" : "OR") && (options.not ? "YES" : "NO") === (existingExpr?.not ? "YES" : "NO");
/* if an expression is found and same is true, we just add the new item to the existing expression
* to do this, we re-construct the expression and add it to the query
*/
if (existingExpr && isSameSelect && existingSelectIndex !== -1){
let _items: AggregationItem[];
if (existingExpr?.operands) {
_items = this.exprToAggregationItem(existingExpr.operands, aggregation.valuesAreExpressions).concat(items);
} else {
// previous selection is a single value
_items = this.exprToAggregationItem(existingExpr as Expr, aggregation.valuesAreExpressions).concat(items);
}
// MUST reset $excluded property otherwise expression is misunderstood
_items.forEach(item => item.$excluded = undefined);
// overrides options settings with expression if any
let _expr = this.exprBuilder.makeAggregationExpr(aggregation, _items, options.and || existingExpr.and);
if (options.not || existingExpr.not) {
_expr = this.exprBuilder.makeNotExpr(_expr);
}
if (_expr) {
query.replaceSelect(existingSelectIndex, {expression: _expr, facet: facetName});
return true;
}
}
}
let expr = this.exprBuilder.makeAggregationExpr(aggregation, items, options.and);
if (options.not) {
expr = this.exprBuilder.makeNotExpr(expr);
}
if (expr) {
query.addSelect(expr, facetName);
return true;
}
return false;
}
/**
* Clears the query from the current selection on the given facet
* @param facetName
* @param all
* @param query the query to clear from the facet selection (defaults to search service query)
*/
public clearFilters(facetName: string, all?: boolean, query = this.searchService.query) {
query.removeSelect(facetName, all);
}
/**
* Clears the query from the current selection on the given facet and perform a search
* @param facetName
* @param all
*/
public clearFiltersSearch(facetName: string | string[], all?: boolean): Promise<boolean> {
[].concat(facetName as []).forEach(name => {
this.clearFilters(name, all);
this._events.next({type: FacetEventType.ClearFilters, facet: this.facet(name)});
});
if(this.searchService.isSearchRouteActive()) {
return this.searchService.search(undefined, {
type: FacetEventType.ClearFilters,
detail: {
itembox: facetName,
"from-result-id": this.searchService.results?.id
}
});
}
return Promise.resolve(false);
}
/**
* Remove a filter and update the appropriate Select if it was previously included in a selection
* @param facetName the facet that removes the filter
* @param aggregation the aggregation that contains the item to remove
* @param item the aggregation item to remove from the query
* @param query the query on which to remove the filter (defaults to search service query)
* @param breadcrumbs breadcrumbs in which to look for selected items (defaults to search service breadcrumbs)
*/
public removeFilter(
facetName: string,
aggregation: Aggregation,
item: AggregationItem,
query = this.searchService.query,
breadcrumbs = this.searchService.breadcrumbs): Select | undefined {
if (breadcrumbs) {
// if item is excluded, makeAggregation() should returns a NOT expression
// the expr to remove
// from aggregation and item, create a expression string
const stringExpr = item.$excluded ? this.exprBuilder.makeNotExpr(this.exprBuilder.makeAggregationExpr(aggregation, item)) : this.exprBuilder.makeAggregationExpr(aggregation, item);
// find filter expression or just parse the string expression
const filterExpr = this.findItemFilter(facetName, aggregation, item, breadcrumbs) || this.appService.parseExpr(stringExpr);
// find expression from breadcrumbs selects
const expr = breadcrumbs.findSelect(facetName, filterExpr);
// once found, retrieve it's index
const i = breadcrumbs.activeSelects.findIndex(select => select.facet === facetName && (select.expr === expr || select.expr === expr?.parent));
if (expr && expr.parent && expr.parent.operands.length > 1) {
// create a new Expr from parent and replaces Select by this new one
// so, breadcrumbs stay ordered
const filterByValuesAreExpression = (it: AggregationItem) => it.value.toString().replace(/ /g, "") !== item.value.toString().replace(/ /g, "");
const filterByValue = (it: AggregationItem) => it.value !== item.value
const filter = (aggregation.valuesAreExpressions) ? filterByValuesAreExpression : filterByValue;
// transform expression to aggregation items
let items: AggregationItem[] = this.exprToAggregationItem(expr.parent.operands, aggregation.valuesAreExpressions);
// excludes 'item' object (from parameters) from aggregation items previously created
// only not removed filters stay on the array
items = items.filter(filter);
// MUST reset $excluded property otherwise expression is misunderstood (mainly NOT expressions)
items.forEach(item => item.$excluded = undefined);
const {not, and} = breadcrumbs.selects[i].expr || {};
let _expr = this.exprBuilder.makeAggregationExpr(aggregation, items, and);
if (not) {
_expr = this.exprBuilder.makeNotExpr(_expr);
}
if (_expr) {
query.replaceSelect(i, {expression: _expr, facet: facetName});
return {expression: this.exprBuilder.makeAggregationExpr(aggregation, item), facet: facetName};
}
} else {
// filter is a single value... remove it
const select = query.select ? query.select[i] : undefined;
query.removeSelect(i);
return select;
}
}
return undefined;
}
/**
* Removes the aggregation from the search service query and refresh the search
* @param facetName
* @param aggregation
* @param item
*/
public removeFilterSearch(facetName: string, aggregation: Aggregation, item: AggregationItem): Promise<boolean>{
const select = this.removeFilter(facetName, aggregation, item);
if(select) {
this._events.next({type: FacetEventType.RemoveFilter, facet: this.facet(facetName || "")});
delete this.searchService.query.queryId; // SBA-154
if(this.searchService.isSearchRouteActive()) {
return this.searchService.search(undefined, {
type: FacetEventType.RemoveFilter,
detail: {
item: {expression: select?.expression, facet: select?.facet},
itembox: facetName,
itemcolumn: aggregation.column,
"from-result-id": !!this.searchService.results ? this.searchService.results.id : null
}
});
}
}
return Promise.resolve(false);
}
/**
* Queries the server for data for this aggregation
* @param aggregation
* @param skip
* @param count
* @param query the query to use to fetch the data (default to search service query)
*/
public loadData(
aggregation: string,
skip: number = 0,
count: number = 10,
query = this.searchService.query,
searchInactive = true): Observable<Aggregation | undefined> {
query = Utils.copy(query);
query.action = "aggregate";
query.aggregations = {};
query.aggregations[aggregation] = {skip: skip, count: count};
return this.searchService.getResults(query, undefined, {searchInactive}).pipe(
map((results: Results) => {
const data = results.aggregations.find(a => Utils.eqNC(a.name, aggregation));
if (data) {
this.setColumn(data); // Useful for formatting and i18n
const max = this.appService.getCCAggregation(data.name)?.count || 10;
if (data.items) {
if (!data.isDistribution && data.items?.length > max) {
data.items = data.items.slice(0, count);
}
}
}
return data;
})
);
}
/**
* Get suggestions given a text and a field name, using the Suggest service
* @param text
* @param field
* @param suggestQuery
*/
public suggest(text: string, field: string, suggestQuery = this.appService.suggestQueries[0]): Observable<Suggestion[]> {
return this.suggestService.get(suggestQuery, text, [field], this.searchService.query);
}
/**
* Format the given result item, using field formatter and/or i18n service
* @param item
*/
formatValue(item: AggregationItem): string {
return this.intlService.formatMessage(
this.formatService.formatFieldValue(item, item.$column));
}
/**
* Returns true if this facet has at least one active selection
* filtering the search
* @param facetName
* @param breadcrumbs breadcrumbs in which to look for selected items (defaults to search service breadcrumbs)
*/
public hasFiltered(facetName: string, breadcrumbs = this.searchService.breadcrumbs) : boolean {
return !!this.findFilter(facetName, breadcrumbs);
}
/**
* Returns an active selection of this facet filtering the search
* Returns it as an expression
* @param facetName
* @param breadcrumbs breadcrumbs in which to look for selected items (defaults to search service breadcrumbs)
*/
public findFilter(facetName: string, breadcrumbs = this.searchService.breadcrumbs) : Expr | undefined {
return breadcrumbs?.findSelect(facetName);
}
/**
* Look for an aggregation with the given name in the search results and returns it.
* Takes care of initializing the aggregation items to insert their $column property.
* @param aggregationName
* @param results The search results can be provided explicitly or taken from the SearchService implicitly.
*/
getAggregation(
aggregationName: string,
results = this.searchService.results,
treeAggregationOptions?: {
facetName: string,
levelCallback?: (nodes: TreeAggregationNode[], level: number, node: TreeAggregationNode) => void
}
): Aggregation | TreeAggregation | undefined {
if (results?.aggregations) {
const aggregation = results.aggregations.find(agg => Utils.eqNC(agg.name, aggregationName))
if (aggregation) {
this.setColumn(aggregation); // Useful for formatting and i18n
this.convertNullValueToString(aggregation);
// adjust aggregation's items length except for treepath aggregation
if (!aggregation.isTree && aggregation.items) {
// set aggregation's count
const max = this.getAggregationCount(aggregationName);
const count = max < 0 ? aggregation.items.length : max;
if (!aggregation.isDistribution && aggregation.items.length > count) {
aggregation.items = aggregation.items?.slice(0, count);
}
}
if (aggregation.isTree && treeAggregationOptions) {
const expr = this.findFilter(treeAggregationOptions.facetName);
const expandPaths = expr ? expr.getValues(aggregation.column) : [];
this.initTreeNodes(treeAggregationOptions.facetName, aggregation, "/", aggregation.items as TreeAggregationNode[], expandPaths, treeAggregationOptions.levelCallback);
return aggregation as TreeAggregation;
}
return aggregation;
}
}
return undefined;
}
/**
* Look for a Tree aggregation with the given name in the search results and returns it.
* Takes care of initializing the Node aggregation items to insert their properties ($column, $path, $opened, $level)
* @deprecated use getAggregation() instead
* @param facetName
* @param aggregationName
* @param results The search results can be provided explicitly or taken from the SearchService implicitly.
* @param levelCallback A callback method called at every level of the tree.
* Can be used to read or alter the properties of the nodes (opening, closing), or node list (sorting)
*/
getTreeAggregation(
facetName: string,
aggregationName: string,
results = this.searchService.results,
levelCallback?: (nodes: TreeAggregationNode[], level: number, node: TreeAggregationNode) => void
): TreeAggregation | undefined {
const agg = this.getAggregation(aggregationName, results);
if(agg?.isTree){
const expr = this.findFilter(facetName);
const expandPaths = expr ? expr.getValues(agg.column) : [];
this.initTreeNodes(facetName, agg, "/", agg.items as TreeAggregationNode[], expandPaths, levelCallback);
return agg as TreeAggregation;
}
return undefined;
}
/**
* Returns the count parameter of the given aggregation (default is -1 === return all items)
* @param aggregationName
*/
getAggregationCount(aggregationName: string) : number {
const cc = this.appService.getCCAggregation(aggregationName);
return cc ? (!!cc.count ? cc.count : 10) : -1;
}
/**
* Returns the label associated to an aggregation, if any
* @param aggregationName
*/
getAggregationLabel(aggregationName: string) : string {
const ccagg = this.appService.getCCAggregation(aggregationName);
if(ccagg) {
return this.appService.getPluralLabel(ccagg.column, aggregationName);
}
return aggregationName;
}
/**
* Opens a Tree node of the given tree facet by querying data from the server
* Takes care of initializing the Node aggregation items to insert their properties ($column, $path, $opened, $level)
* @param facetName
* @param aggregation
* @param item
* @param levelCallback A callback method called at every level of the tree.
* Can be used to read or alter the properties of the nodes (opening, closing), or node list (sorting)
*/
open(
facetName: string,
aggregation: TreeAggregation,
item: TreeAggregationNode,
levelCallback?: (nodes: TreeAggregationNode[], level: number, node: TreeAggregationNode) => void,
query = this.searchService.query,
searchInactive = true
): Observable<Results> {
const value = item.$path + "*";
query = Query.copy(query);
query.action = "open";
const expr = this.exprBuilder.makeExpr(aggregation.column, value);
query.addOpen(expr, aggregation.name);
this.events.next({type: FacetEventType.Open, facet: this.facet(facetName)});
return this.searchService.getResults(query, undefined, {searchInactive}).pipe(
map((results: Results) => {
if (item.$path) {
const source = FacetService.getAggregationNode(results.aggregations[0].items as TreeAggregationNode[], item.$path);
const target = FacetService.getAggregationNode(aggregation.items as TreeAggregationNode[], item.$path);
if (source && target) {
target.items = source.items; // Insert the new data (source) into the original (target)
}
if (target && target.items) {
this.initTreeNodes(facetName, aggregation, item.$path, target.items, undefined, levelCallback);
}
}
return results;
})
);
}
/**
* Returns true if a given aggregation item is currently actively filtering the search
* @param facetName
* @param aggregation
* @param item
* @param breadcrumbs breadcrumbs in which to look for selected items (default to search service breadcrumbs)
*/
itemFiltered(facetName: string, aggregation: Aggregation, item: AggregationItem, breadcrumbs = this.searchService.breadcrumbs): boolean {
return !!this.findItemFilter(facetName, aggregation, item, breadcrumbs);
}
protected findItemFilter(facetName: string, aggregation: Aggregation, item: AggregationItem, breadcrumbs: Breadcrumbs | undefined) : Expr | undefined {
let expr: Expr | undefined;
let exprText: string;
if (!aggregation.valuesAreExpressions) {
let value: string;
if (aggregation.isTree) {
value = Utils.toSqlValue((<TreeAggregationNode>item).$path + "*");
}
else {
value = Utils.toSqlValue(item.value);
}
exprText = this.exprBuilder.makeExpr(aggregation.column, value);
}
else {
exprText = item.value as string;
}
const ret = this.appService.parseExpr(exprText);
if (ret instanceof Expr) {
expr = <Expr>ret;
}
if (expr) {
const expr2 = breadcrumbs?.findSelect(facetName, expr);
if(!!expr2 && (!expr2.parent || !expr2.parent.parent)){
return expr2;
}
}
return undefined;
}
/**
* Initializes the nodes of a tree (private, with a callback)
* @param facetName
* @param aggregation
* @param root
* @param children
* @param expandPaths
* @param levelCallback
*/
protected initTreeNodes(
facetName: string,
aggregation: Aggregation,
root: string,
children: TreeAggregationNode[],
expandPaths?: string[],
levelCallback?: (nodes: TreeAggregationNode[], level: number, node: TreeAggregationNode) => void
) {
if (!children) {
return;
}
let rootLevel: number;
if (root) {
rootLevel = Utils.count(root, "/", false) - 1;
}
else {
root = "/";
rootLevel = 0;
}
const column = this.appService.getColumn(aggregation.column);
Utils.traverse(children, (_nodes) => {
if (!_nodes) {
return false;
}
let path = root;
let level = rootLevel;
for (const _node of _nodes) {
path = path + _node.value + "/";
level++;
}
// console.log(path);
const _node = _nodes[_nodes.length - 1];
_node.$path = path;
_node.$column = column;
_node.$level = level;
_node.$opened = false;
_node.$filtered = this.itemFiltered(facetName, aggregation, _node)
expandPaths?.forEach(expandPath => {
if (expandPath.indexOf(path) === 0) {
const count = !!_node.items ? _node.items.length : _node.hasChildren ? -1 : 0;
if (count > 0) {
_node.$opened = true;
}
}
});
if (levelCallback) {
levelCallback(_nodes, level, _node);
}
return false; // don't stop
});
}
protected setColumn(aggregation: Aggregation){
if(!aggregation.isTree && aggregation.items){
const column = this.appService.getColumn(aggregation.column);
aggregation.items.forEach((value) => value.$column = column);
aggregation.column = this.appService.resolveColumnAlias(aggregation.column);
}
}
protected convertNullValueToString(aggregation: Aggregation) {
if(!aggregation.isTree && !aggregation.valuesAreExpressions && aggregation.items){
aggregation.items.forEach((item: AggregationItem) => {
// convert null value without display property to string
if (item.value === null && !item.display) {
item.value = String(item.value);
}
});
}
}
// static methods
protected static splitTreepath(path: string): string[] {
if (!path) return [];
path = path.trim();
if (path.length > 0 && path[0] === "/") {
path = path.substr(1);
}
if (path.length > 0 && path[path.length - 1] === "/") {
path = path.substr(0, path.length - 1);
}
if (path.length === 0) {
return [];
}
return path.split("/");
}
public static treepathLast(path: string): string {
const parts = FacetService.splitTreepath(path);
if (!parts || parts.length === 0) {
return "";
}
return parts[parts.length - 1];
}
protected static getAggregationNode(nodes: TreeAggregationNode[], path: string): TreeAggregationNode | undefined {
if (!nodes || nodes.length === 0) {
return undefined;
}
const names = FacetService.splitTreepath(path);
let node: TreeAggregationNode | undefined;
for (let _i = 0, _a = names; _i < _a.length; _i++) {
if (!nodes || nodes.length === 0) {
return undefined;
}
const name = _a[_i].toLocaleLowerCase();
node = undefined;
for (let _j = 0, _b = nodes; _j < _b.length; _j++) {
const _node = _b[_j];
if ((<string>_node.value).toLocaleLowerCase() === name) {
node = _node;
break;
}
}
if (!node) {
return undefined;
}
nodes = node.items;
}
return node;
}
/**
* Convert an Expression object or an Expression Array to their AggregationItem equivalent
*
* @param expr Expression object or Expression Array
* @param valuesAreExpressions when true values should be converted to string otherwise no
*
* @returns AggregationItem array with converted expression or an empty array
*/
exprToAggregationItem(expr: Expr[] | Expr, valuesAreExpressions: boolean = false): AggregationItem[] {
const fn = [
(item: Expr) => {
let value: FieldValue = item.value as string;
if (item.column?.eType === EngineType.bool) {
value = Utils.isTrue(item.value);
}
if (item.column?.eType === EngineType.csv) {
value = item.display || item.value || "";
const path = item.value?.slice(0, -1);
return ({count: 0, value, display: item.display, $column: item.column, $path: path, $excluded: (item?.not || item?.parent?.not)} as TreeAggregationNode);
}
if (item.column?.eType === EngineType.integer) {
value = Number(item.value as string) || String(value);
}
return ({count: 0, value, display: item.display, $column: item.column, $excluded: (item?.not || item?.parent?.not)} as AggregationItem);
},
(item: Expr) => ({count: 0, value: item.toString((item.value) ? true : false), display: item.display, $column: item.column, $excluded: (item?.not || item?.parent?.not)} as AggregationItem)
];
const callback = valuesAreExpressions ? fn[1] : fn[0];
return [].concat(expr as []).map(callback) as AggregationItem[];
}
/**
* Get all Breadcrumbs items from a specific facet
*
* @param facetName facet name where to extract all breadcrumbs
* @param breadcrumbs breadcrumbs in which to look for selected items
*/
getBreadcrumbsItems(facetName: string, breadcrumbs: Breadcrumbs | undefined): BreadcrumbsItem[] {
return breadcrumbs?.items.filter(item => item.facet === facetName) || [];
}
/**
* Get all Aggregation items from a facet, currently filtered
*
* @param facetName facet name where to inspect
* @param valuesAreExpressions when true, some transformations should be done
* @param breadcrumbs breadcrumbs in which to look for selected items (default to search service breadcrumbs)
*/
getAggregationItemsFiltered(facetName: string, valuesAreExpressions: boolean = false, breadcrumbs = this.searchService.breadcrumbs): AggregationItem[] {
const items = this.getBreadcrumbsItems(facetName, breadcrumbs);
// aggregation items are constructed from nested expressions
const expr = [] as Expr[][];
for (const item of items) {
const value = (item.expr?.display === undefined) ? item.expr?.operands as Expr[] || item.expr : item.expr;
if (value) {
expr.push(value as Expr[]);
}
}
// faltten results
const flattenExpr = [].concat.apply([], expr);
return this.exprToAggregationItem(flattenExpr, valuesAreExpressions);
}
/**
* Convert Suggestion to AggregationItem
* @param suggest a Suggestion object
*
* @returns AggregationItem object with is `$column` property defined.
* On boolean type, convert `value` property to boolean
*/
suggestionToAggregationItem(suggest: Suggestion): AggregationItem {
const item: AggregationItem = {
value: suggest.normalized || suggest.display,
display: suggest.display,
count: +(suggest.frequency || 0),
$column: this.appService.getColumn(suggest.category)
};
if (item.$column?.eType === EngineType.bool) {
item.value = Utils.isTrue(item.value);
}
return item;
}
/**
* Converts a list of suggestions into a structure of TreeAggregationNodes
* @param suggests Suggestions to convert
* @param searchTerm The searched term in the suggestions
* @param aggregation The tree aggregations
*/
suggestionsToTreeAggregationNodes(suggests: Suggestion[], searchTerm: string, aggregation: Aggregation | undefined): TreeAggregationNode[] {
const suggestions: TreeAggregationNode[] = [];
if(suggests.length > 0) {
const path2node = new Map<string, TreeAggregationNode>();
// searchTerm should be escaped
const term = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const searchPattern = new RegExp(`\\b${term}`, 'i');
const column = this.appService.getColumn(aggregation?.column);
suggests.forEach(suggest => {
if(suggest.display.length > 1) {
const match = searchPattern.exec(suggest.display);
this.addNode(suggestions, path2node, "/", suggest.display, +(suggest.frequency || 0), 1, (match?.index || 0)+searchTerm.length, column);
}
});
}
return suggestions;
}
/**
* Utility recursive function to generate a tree aggregation structure from
* a list of suggestions
*/
protected addNode(items: TreeAggregationNode[],
path2node: Map<string,TreeAggregationNode>,
parentPath: string,
path: string,
count: number,
level: number,
matchend: number,
column: CCColumn | undefined) {
const nextChild = path.indexOf("/", parentPath.length); // path = /Cities/Paris/17e/ parentPath = /Cities/
const currentPath = path.substring(0, nextChild+1); // => currentPath = /Cities/Paris/
let node = path2node.get(currentPath);
if(!node) {
const value = path.substring(parentPath.length, nextChild);
node = {
value,
count,
items: [],
hasChildren: false,
$column: column,
$level: level,
$opened: matchend >= currentPath.length,
$path: currentPath
};
path2node.set(currentPath, node);
items.push(node);
}
if(currentPath.length < path.length) {
node.hasChildren = true;
this.addNode(node.items, path2node, currentPath, path, count, level+1, matchend, column);
}
}
/**
* Check if a facet contains items
* @param aggregation aggregation name
* @param results search results
*
* @returns true if the facet contains a least one item otherwise false
*/
hasData(aggregation: string, results: Results): boolean {
// Avoid calling getAggregation() which is costly
return !!results.aggregations.find(agg => Utils.eqNC(agg.name, aggregation))?.items?.length;
}
/**
* Returns the index of the first element in the supplied array
* corresponding to `item.value` or -1 when not found.
* A fallback to `item.display` is done before returning -1
* @param item item to find
*/
filteredIndex(data: Aggregation | undefined, arr: Array<AggregationItem>, item: AggregationItem): number {
let indx = -1;
// specific to Values Are Expressions where expression are not well formatted by Expression Parser
// eg: when values is : "> 0", Expression Parser returns : ">0" without space between operator and value
if (data?.valuesAreExpressions) {
const value = this.trimAllWhitespace(item.value);
const normalizedArr = arr.map(item => ({...item, value: this.trimAllWhitespace(item.value)})) || [];
indx = normalizedArr.findIndex(it => it.value === value);
// fallback to display
if (indx === -1 && item.display) {
indx= normalizedArr.findIndex(it => it.display === item.display);
}
} else {
indx = this.findAggregationItemIndex(arr, item);
}
return indx;
}
/**
* Utility function to returns aggregation item's index in supplied array with fallback to `display` comparison.
* Otherwise -1, indicating that no element passed the test.
* @param arr The array findIndex() was called upon
* @param value The value to be test
*/
public findAggregationItemIndex = (arr: Array<AggregationItem>, item: AggregationItem) => {
// first check value as is
let index = arr.findIndex(it => it.value === item.value);
// fallback to display comparison
if (index === -1 && item.display) {
index = arr.findIndex(it => it.display === item.display);
}
return index;
};
private trimAllWhitespace = (value: FieldValue | undefined): FieldValue | undefined => {
switch (typeof value) {
case "string":
return value.replace(/\s/g, '');
default:
return value;
}
};
}


{% load i18n %}
You are using U2F hardware token authentication. At this point, activate it by pressing the button or applying it to the phone.
{% endblocktrans %}You are using a browser for which we have not confirmed the correct U2F authentication.
Sorry for the inconvenience. Unfortunately, we recommend using a browser based on Chromium engine (Google Chrome, Opera, etc.).
You can try the current browser at your own risk. You were warned.
{% endblocktrans %}


Automating Red Hat Enterprise Linux Patching with Ansible (Part 1 of 2)
How we automated Red Hat Enterprise Linux OS patching to reduce time-to-production and human error, while improving compliance and risk management posture.
In this first installment of a two-part series, we’ll be going over Phase One, the build out of the “core” patching and reboot functionality on Ansible.
History
Around a year ago, we began working with a customer whose Red Hat Enterprise Linux (RHEL) 6 and 7 OS patching process was being conducted manually. This required highly skilled administrators focused solely on patching. Documentation was eschewed in favor of tribal knowledge and manual command entry at the command line presented moderate to high risk during server patching. Some of the involved environments included the handling of Personally Identifiable Information (PII) as well as data and information subject to Payment Card Industry (PCI) compliance requirements.
PCI Security Standards Council states:
Ensure that all system components and software are protected from known vulnerabilities by installing applicable vendor-supplied security patches. Install critical patches within one month of release.
Because of this and other PCI compliance requirements, all the customer’s RHEL servers needed to be patched at least once monthly. Patching needed to follow a DEVELOPMENT -> STAGING -> PRODUCTION workflow to minimize risks to the production environments. Because of the complexities involved in a fully manual patching process, meeting PCI compliance standards was a constant chase with inconsistent results.
Dissatisfied with the high costs, high complexity and consistent underperformance of the manual patching process, the customer sought ways to improve operational efficiency and reduce costs, expressing interest in leveraging automation where it made sense to do so.
Enter Ansible
To minimize complexity, the solution was developed on Ansible, in conjunction with common Linux tools such as YUM, Bash scripts and SSH keys. No agent software installation or additional security infrastructure was required, thus the customer incurred zero appreciable cost for the technology.
Implementation was carried out in three phases:
- Automate Basic Patching and Endpoint Reboots
- Automate Standard Pre- and Post-patching Activities
- Automate Application/Host-specific Pre- and Post-patching Activities
Phase One - Automate Basic Patching and Endpoint Reboots
The first phase of the project focused on the installation and configuration of Ansible on a control node, as well as developing the core patch installation and reboot functionality. Automation of patch installation and reboots, without any change to pre- and post-patching activity processes saw an immediate benefit of speedier patch installation as well as a marked reduction in human errors being introduced.
Before development of patching automation could begin in earnest, a foundational directory structure needed to be established for Ansible. Following is a visual representation:
Inventory
The inventory
subdirectory is home to the hosts
file and Ansible references to know what systems to work with. For our customer, the hosts file contains server FQDNs (preferred) and IP addresses (where hostname usage is prohibitive) for all Ansible managed endpoints. For example (these are NOT real hostnames):
/ansible/invetory/hosts
[group1]
clsusa1ipm01.internal.cls.com
clsusa1cfg01.internal.cls.com
mon02.cls1.usa1.internal.cls.com
dns01.cls1.usa1.internal.cls.com
dns03.cls1.usa1.internal.cls.com
clsusa1log01.internal.cls.com
clsusa1log03.internal.cls.com
clsusa1esn02.internal.cls.com
clsusa1mon03.internal.cls.com
clsusa1mon04.internal.cls.com
[group2]
clsusa1jnk01.internal.cls.com
mta01.afg1.nor1.internal.cls.com
mon01.afg1.nor1.internal.cls.com
dns02.afg1.nor1.internal.cls.com
clsusa1log02.internal.cls.com
clsusa1esn01.internal.cls.com
clsusa1esn03.internal.cls.com
clsusa1std01.internal.cls.com
[noreboot]
clsusa1rhs01.internal.cls.com
clsusa1ssh01.internal.cls.com
clsusa1sto01.internal.cls.com
vds01.afg1.nor1.internal.cls.com
[satellite]
clsusa1rhs01.internal.cls.com
Inside the group_vars
and host_vars
directories reside subdirectories named for either the group or the host for which variables are defined. Order of precedence prioritizes host definitions over group definitions. For application environments with no special requirements, a standard all
group is defined. all
group definitions are overridden by more specific group and host definitions. Following are examples:
/ansible/inventory/group_vars/all/config
# File name of pre and post patching scripts.
pre_update_script: /opt/home/svc_cls/pre_update.sh
post_update_script: /opt/home/svc_cls/post_update.sh
post_update_conf: /opt/home/svc_cls/post_update_conf.env
env_verify_dest: /opt/home/svc_cls/env_verify.sh
# Comma-separated list of application team email addresses
app_email<EMAIL_ADDRESS>/ansible/inventory/host_vars/clsusa1ipm01.intneral.cls.com (the role_path
variale is globally defined in the Ansible configuration)
env_verify_src: "{{ role_path }}/files/host/clsusa1ipm01.internal.cls.com /env_verify.sh"
pre_update_src: "{{ role_path }}/files/host/clsusa1ipm01.internal.cls.com /pre_update.sh"
Playbooks
The playbooks
directory houses all the playbooks (written in YAML) that are used to execute automated patching actions, as well as any other automation that is implemented through Ansible. In the following example, update.yaml includes logic for emailing notifications both before and after patching activities are executed against a host. The roles included in this playbook are explored later on.
/ansible/playbooks/update.yaml
---
#------------------------------------------------------------------------------
# Description: Playbook to perform 'yum update' on selected hosts.
# NOTE: This playbook will also reboot hosts if kernel is updated.
#------------------------------------------------------------------------------
- name: Performing yum update on host(s)
hosts: group1
become: yes
any_errors_fatal: false
##########################################################
# Send notification email at start of change to app teams
##########################################################
pre_tasks:
- mail:
subject: 'OS patching for {{ ansible_hostname }} is beginning now.'
from: 'svc_cls@{{ ansible_fqdn }}'
body: 'Automated OS patching for {{ ansible_hostname }} is beginning now.'
to: '{{ app_email }}'
charset: utf8
delegate_to: localhost
tags: mail
#########################################################
# Execute update procedures
#########################################################
roles:
- { role: pre_update, become: yes }
- { role: yum_update, become: yes }
- { role: post_update, become: yes }
##########################################################
# Send notifiction of completion
##########################################################
post_tasks:
- mail:
subject: 'OS patching for {{ ansible_hostname }} has completed.'
from: 'svc_cls@{{ ansible_fqdn }}'
body: "Automated OS patching for {{ ansible_hostname }} has completed."
to: '{{ app_email }}'
charset: utf8
delegate_to: localhost
tags: mail
- name: Performing yum update on host(s)
hosts: group2
become: yes
any_errors_fatal: false
##########################################################
# Send notification email at start of change to app teams
##########################################################
pre_tasks:
- mail:
subject: 'OS patching for {{ ansible_hostname }} is beginning now.'
from: 'svc_cls@{{ ansible_fqdn }}'
body: 'Automated OS patching for {{ ansible_hostname }} is beginning now.'
to: '{{ app_email }}'
charset: utf8
delegate_to: localhost
tags: mail
#########################################################
# Execute update procedures
#########################################################
roles:
- { role: pre_update, become: yes }
- { role: yum_update, become: yes }
- { role: post_update, become: yes }
##########################################################
# Send notifiction of completion
##########################################################
post_tasks:
- mail:
subject: 'OS patching for {{ ansible_hostname }} has completed.'
from: 'svc_cls@{{ ansible_fqdn }}'
body: "Automated OS patching for {{ ansible_hostname }} has completed."
to: '{{ app_email }}'
charset: utf8
delegate_to: localhost
tags: mail
- name: Performing yum update on host(s)
hosts: noreboot
become: yes
any_errors_fatal: false
##########################################################
# Send notification email at start of change to app teams
##########################################################
pre_tasks:
- mail:
subject: 'OS patching for {{ ansible_hostname }} is beginning now.'
from: 'svc_cls@{{ ansible_fqdn }}'
body: 'Automated OS patching for {{ ansible_hostname }} is beginning now.'
to: '{{ app_email }}'
charset: utf8
delegate_to: localhost
tags: mail
#########################################################
# Execute update procedures
#########################################################
roles:
- { role: pre_update, become: yes }
- { role: yum_update, become: yes }
- { role: post_update, become: yes }
##########################################################
# Send notifiction of completion
##########################################################
post_tasks:
- mail:
subject: 'OS patching for {{ ansible_hostname }} has completed.'
from: 'svc_cls@{{ ansible_fqdn }}'
body: "Automated OS patching for {{ ansible_hostname }} has completed."
to: '{{ app_email }}'
charset: utf8
delegate_to: localhost
tags: mail
- name: Performing yum update on satellite servers
hosts: satellite
become: yes
any_errors_fatal: false
##########################################################
# Send notification email at start of change to app teams
##########################################################
pre_tasks:
- mail:
subject: 'OS patching for {{ ansible_hostname }} is beginning now.'
from: 'svc_cls@{{ ansible_fqdn }}'
body: 'Automated OS patching for {{ ansible_hostname }} is beginning now.'
to: '{{ app_email }}'
charset: utf8
delegate_to: localhost
tags: mail
#########################################################
# Execute update procedures
#########################################################
roles:
- { role: pre_update, become: yes }
- { role: yum_noreboot, become: yes }
- { role: post_update, become: yes }
##########################################################
# Send notifiction of completion
##########################################################
post_tasks:
- mail:
subject: 'OS patching for {{ ansible_hostname }} has completed.'
from: 'svc_cls@{{ ansible_fqdn }}'
body: "Automated OS patching for {{ ansible_hostname }} has completed."
to: '{{ app_email }}'
charset: utf8
delegate_to: localhost
tags: mail
Roles
Everything inside the roles
directory and its subdirectories exists to carry out all the actions called out in a playbook. Basic patching automation makes use of four distinct roles:
- yum_update
- yum_noreboot
- pre_update
- post_update
yum_update
/ansible/roles/yum_update/tasks/main.yaml
executes a yum update to the latest available version on all installed packages, and then performs a check to see if a new kernel was installed, creating a flag that triggers a reboot during post_update
if one was.
/ansible/roles/yum_update/tasks/main.yaml
---
#------------------------------------------------------------------------------
# Description: Perform yum update on selected hosts and compare running
# kernel version with last updated kernel version.
# Notes: shell module used to compare last kernel and
# current, can't find a better method.
#------------------------------------------------------------------------------
- name: Updating all packages
yum:
name: '*'
state: latest
tags:
- skip_ansible_lint
- name: Comparing last kernel and running kernel
shell: |
LAST_KERNEL=$(rpm -q --last kernel | perl -pe 's/^kernel-(\S+).*/$1/' | head -1)
CURRENT_KERNEL=$(uname -r)
if [[ $LAST_KERNEL != $CURRENT_KERNEL ]]; then
# Set reboot flag
touch /tmp/reboot
# Shutdown/stop any services before reboot if exists.
if [[ -f /opt/home/svc_cls/pre_reboot.sh ]]; then
/opt/home/svc_cls/pre_reboot.sh
fi
fi
tags:
- skip_ansible_lint
yum_noreboot
/anbsible/roles/yum_noreboot/tasks/main.yaml
executes a yum update to the latest available version on all installed packages. This role does NOT check for a new kernel or create a flag to trigger a reboot during post_update
. This functionality is reserved for those servers and application environments where an automated reboot may cause issues (e.g. rebooting the Satellite server, which houses all YUM repos, in the middle of a patching cycle).
/anbsible/roles/yum_noreboot/tasks/main.yaml
---
#------------------------------------------------------------------------------
# Description: Perform yum update on selected hosts and compare running
# kernel version with last updated kernel version.
#------------------------------------------------------------------------------
- name: Updating all packages
yum:
name: '*'
state: latest
tags:
- skip_ansible_lint
pre_update
The pre_update
role, like the yum_update
and yum_noreboot
roles, also has a main.yaml
file located in its tasks
subdirectory. This role looks for the existence of a pre_update.sh script on the remote host and executes it. The pre_update
role is more heavily leveraged when an application has special requirements.
/ansible/roles/pre_update/tasks/main.yaml
---
#------------------------------------------------------------------------------
# Description: Check for existence of pre_update.sh script and run it if
# found.
#------------------------------------------------------------------------------
- name: Checking if pre_update.sh script exists
stat:
path: /opt/home/svc_cls/pre_update.sh
register: update_scripts
- name: Running pre update script
command: sh /opt/home/svc_cls/pre_update.sh
when: update_scripts.stat.exists == true
ignore_errors: no
post_update
The post_update
roles also contains a main.yaml
file in its tasks
directory. This role checks for the reboot flag (created in the yum_update
role) and initiates a reboot of the remote host if the flag exists. Ansible then waits for the remote host to come back online before it checks for and executes the post_update.sh
script on the remote host (if it exists). At a minimum, post_update triggers a report of newly installed packages and send the notification that patching is complete.
/ansible/roles/post_update/tasks/main.yaml
---
# Description: Check for existence of post_update.sh script and if reboot
# flag has been set; if so, reboot host and wait for restart.
#------------------------------------------------------------------------------
- name: Checking if post_update.sh script exists
stat:
path: /opt/home/svc_cls/post_update.sh
register: update_scripts
- name: Checking if reboot flag exists
stat:
path: /tmp/reboot
register: reboot
- name: Clearing reboot flag
file:
path: /tmp/reboot
state: absent
when: reboot.stat.exists == true
- name: Rebooting host(s).
shell: sleep 2 && /sbin/shutdown -r now "Reboot required for updated kernel." && sleep 2
async: 20
poll: 0
when: reboot.stat.exists == true
# This version doesn't freak out about sudo permission issues for non-privileged execution.
- name: Waiting for host(s) to reboot
wait_for_connection:
delay: 60
timeout: 300
when: reboot.stat.exists == true
- name: Running post update script
command: sh /opt/home/svc_cls/post_update.sh
when:
- update_scripts.stat.exists == true
Results
As a result of simply automating the patching and reboot functions through leveraging Ansible, opportunities for human error were effectively reduced. While pre-patching and post-patching actions still required varying levels of manual effort, depending on the application environment involved, laying the foundation for automation reclaimed enough time to clear the way for a deeper dive into automation, which will be explored in Part 2 of this series.
-Brian
Share this post
Twitter
Google+
Facebook
Reddit
LinkedIn
StumbleUpon
Email


# extends 'base.html' # block content
Access materials relating to the FRC (FIRST Robotics Competition) topic.
Access materials relating to the FTC (FIRST Tech Challenge) topic.
Access materials relating to the FLL (FIRST Lego League) topic.
Access materials relating to the FLL Jr. (FIRST Lego League Jr.) topic.
Help make this community better by contributing materials.
Learn more about the FIRSTMastery project.


Autodesk View & Data API
Documents
Gallery
Showcase
Quick load
Load from urn
Upload
View
Save
Load
Delete
Explode Motion
Rotate Motion
Stop Motions
UI
Browser
Properties
Extensions
Upload
Manage
Source
Find!
Community
Developer
Autodesk
Support
Blog
About
×
Close
Upload your documents
Drop your files here or click to select from disk ...
Author:
Email:
×
Close
Items to suppress
×
Close
Load document
Filter by
Author
Model name
Model urn
Disable filter
{{model.name}}
Author:
{{model.author.name}}
Type:
{{model.type}}
×
Close
Load view
×
Close
Save view
View Name:
×
Close
Load from URN
URN:
×
Close
About that sample
Written by
Philippe Leefsma
Autodesk Developer Network
July 2014
×
Close
This feature is password protected …
Password:
×
Close
Share your 3D model
Embed code
×
Close
Load Extensions
Drop your files here or click to select from disk ...
{{file.name}}
×
Close
Manage Extensions
×
Close
Show Extensions Source


Download the most recent version of the data.
To regularly update the data we use this openly available R package. Here you can get the source code to do the update yourself.
The data set emerged from various works on globalization and related issues, but it was introduced in this paper published in the Review of World Economics*.
We are sure the data set will be far from perfect. While we cannot guarantee to fulfill all your wishes, we appreciate any feedback.
In case you find the data useful it would be great if you cited our paper - as well as the original sources of the data. Here you get more information about how to do so.
Here you can find a short introduction of the authors and links to their websites and institutions.
The research that has led to the compilation of the data set, the development of this homepage, and the publication of the accompanying paper has been funded by the Anniversary Fund of the Austrian Central Bank (Österreichische Nationalbank) under grant numbers 17383 and 18144.


!= include('stylesheet'); ?>
Shopping list
Item
Qty.
Add to list
(Double-click over an item to remove it)
!= include('scripts'); ?>


To pay the ultimate homage to Terry Pratchett use this OWIN middleware to keep him alive in the internet.


Development of e-commerce websites and standalone modules
Mainly focused on the webshops back-office part:
- Integration to third party systems for the products catalog, deliveries, payments,...
- Custom functionalities for promotions, reports, inventories,...
Customers were mostly sizable national companies:
- Large amount of products and orders
- Usage of both Community and Enterprise editions of Magento
Main developer and primary technical support on some projects
Technologies
- Languages:
- Framework:
- Environment:
- Linux (Debian)
- MySQL
- Apache
- Varnish
- Solr
- Development:


Collection of utility functions used in the KEHRA project (see http://www.brunel.ac.uk/ife/britishcouncil). It refers to the multidimensional analysis of air pollution, weather and health data.
| Version: | 0.1 |
| Depends: | R (≥ 2.14.0) |
| Imports: | Hmisc, raster, reshape2, stringr, sp, xts, zoo |
| Published: | 2016-06-10 |
| Author: | Claudia Vitolo [aut, cre], Allan Tucker [aut], Andrew Russell [aut] |
| Maintainer: | Claudia Vitolo <cvitolodev at gmail.com> |
| BugReports: | https://github.com/kehraProject/r_kehra/issues |
| License: | GPL-3 |
| URL: | https://github.com/kehraProject/r_kehra |
| NeedsCompilation: | no |
| CRAN checks: | kehra results |
| Reference manual: | kehra.pdf |
| Package source: | kehra_0.1.tar.gz |
| Windows binaries: | r-devel: kehra_0.1.zip, r-release: kehra_0.1.zip, r-oldrel: kehra_0.1.zip |
| OS X binaries: | r-release: kehra_0.1.tgz, r-oldrel: kehra_0.1.tgz |
Please use the canonical form https://CRAN.R-project.org/package=kehra to link to this page.


Nicholas Gallegos
I wear silly hats
I enjoy eating my brothers food
I make beats for the low
I love world
I am married to garfield


3.Work Experience
Child Minding
- I have experience working in the child play-centre "Supernova" as a server,
a superviser and an activities leader.
Reference no. 08*127564*
- I have also babysat for a 2 year old child regularly.
Shop Assisting
- I have experience working in Vibes and Scribes arts and crafts store as a shop floor assistant.
Reference no. 08*770564*
Fashion Design
- I have work experience with "Calvin Klein Golf Designs", assisting the designer Aoife Backer.
Reference no. 08*774564*
- I have also worked with Jo King fashion designer as an assistant.
Reference no. 08*883564*
- I have also worked with Jo King fashion designer.
Waitressing
- I have worked in "Grumpy and Wise" cafe, Crosshaven.
Reference no. 08*77432**


Class: ActiveSupport::Messages::Codec
Do not use. This class is for internal use only.
| Relationships & Source Files | |
| Extension / Inclusion / Inheritance Descendants | |
|
Subclasses:
|
|
| Super Chains via Extension / Inclusion / Inheritance | |
|
Instance Chain:
self,
Metadata
|
|
| Inherits: | Object |
| Defined in: | activesupport/lib/active_support/messages/codec.rb |
Constant Summary
Metadata
- Included
Class Attribute Summary
Class Method Summary
- .new(**options) ⇒ Codec constructor
Instance Attribute Summary
- #serializer readonly private
- #use_message_serializer_for_metadata? ⇒ Boolean readonly private
Metadata
- Included
Instance Method Summary
- #catch_and_ignore(throwable, &block) private
- #catch_and_raise(throwable, as: nil, &block) private
- #decode(encoded, url_safe: @url_safe) private
- #deserialize(serialized) private
- #encode(data, url_safe: @url_safe) private
- #serialize(data) private
Metadata
- Included
Constructor Details
.new(**options) ⇒ Codec
# File 'activesupport/lib/active_support/messages/codec.rb', line 15
def initialize(** ) @serializer = [:serializer] || self.class.default_serializer @serializer = SerializerWithFallback[@serializer] if @serializer.is_a?(Symbol) @url_safe = [:url_safe] @force_legacy_metadata_serializer = [: ] end
Class Attribute Details
.default_serializer (rw)
[ GitHub ]# File 'activesupport/lib/active_support/messages/codec.rb', line 12
class_attribute :default_serializer, default: :marshal, instance_accessor: false, instance_predicate: false
Instance Attribute Details
#serializer (readonly, private)
[ GitHub ]# File 'activesupport/lib/active_support/messages/codec.rb', line 23
attr_reader :serializer
#use_message_serializer_for_metadata? ⇒ Boolean
(readonly, private)
[ GitHub ]
# File 'activesupport/lib/active_support/messages/codec.rb', line 60
def !@force_legacy_metadata_serializer && super end
Instance Method Details
#catch_and_ignore(throwable, &block) (private)
[ GitHub ]# File 'activesupport/lib/active_support/messages/codec.rb', line 45
def catch_and_ignore(throwable, &block) catch throwable do return block.call end nil end
#catch_and_raise(throwable, as: nil, &block) (private)
[ GitHub ]# File 'activesupport/lib/active_support/messages/codec.rb', line 52
def catch_and_raise(throwable, as: nil, &block) error = catch throwable do return block.call end error = as.new(error.to_s) if as raise error end
#decode(encoded, url_safe: @url_safe) (private)
[ GitHub ]# File 'activesupport/lib/active_support/messages/codec.rb', line 29
def decode(encoded, url_safe: @url_safe) url_safe ? ::Base64.urlsafe_decode64(encoded) : ::Base64.strict_decode64(encoded) rescue ArgumentError => error throw :, error end
#deserialize(serialized) (private)
[ GitHub ]# File 'activesupport/lib/active_support/messages/codec.rb', line 39
def deserialize(serialized) serializer.load(serialized) rescue StandardError => error throw :, error end
#encode(data, url_safe: @url_safe) (private)
[ GitHub ]# File 'activesupport/lib/active_support/messages/codec.rb', line 25
def encode(data, url_safe: @url_safe) url_safe ? ::Base64.urlsafe_encode64(data, padding: false) : ::Base64.strict_encode64(data) end
#serialize(data) (private)
[ GitHub ]# File 'activesupport/lib/active_support/messages/codec.rb', line 35
def serialize(data) serializer.dump(data) end


Apr 20, 2013 at 4:48pm UTC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
typedef struct Element Element;
struct Element
{
char x;
double * y;
};
int main()
{
Element a;
printf("%d\n" ,sizeof (Element ));
return 0;
}
this one with y pointer gives 8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
typedef struct Element Element;
struct Element
{
char x;
double y;
};
int main()
{
Element a;
printf("%d\n" ,sizeof (Element ));
return 0;
}
ths one with a normal y variable gives 12
Last edited on Apr 20, 2013 at 4:49pm UTC
Apr 20, 2013 at 5:01pm UTC
Your pointers are probably 4 bytes (try doing sizeof (double *)
)
Your doubles are probably 8 bytes (try doing sizeof (double )
)
The single char is 1 byte, but the struct will get padded up to the nearest 4-byte boundary for alignment reasons.
Apr 20, 2013 at 6:29pm UTC
thank you guys .. reading about " padding" .made me figuring it out
Apr 20, 2013 at 10:32pm UTC
could also simply crash ( on certain non-Intel platforms )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include <iostream>
#pragma pack(1)
struct Element
{
char x;
double y;
};
#pragma pack()
int main()
{
Element e = {'a' , 3.14};
std::cout << "Size of Element is " << sizeof e << '\n'
<< "Enter a double: " ;
std::cin >> e.y;
std::cerr << e.y << '\n' ;
}
$ ./test
Size of Element is 9
Enter a double: 1.23
Bus Error
Last edited on Apr 20, 2013 at 11:25pm UTC


DiscreteWavelets Toolbox
Bug Reporting
Please report all bugs via
email
to Patrick Van Fleet.
Support
Known Bugs
© 2007-2008 Patrick Van Fleet